summaryrefslogtreecommitdiff
path: root/libavcodec/vmnc.c
diff options
context:
space:
mode:
authorKostya Shishkov <kostya.shishkov@gmail.com>2006-09-05 07:31:53 +0000
committerKostya Shishkov <kostya.shishkov@gmail.com>2006-09-05 07:31:53 +0000
commit805934b3e4057a9d722c78090f63cfc9672f83b1 (patch)
tree6972b212c2759278e0836980e54e8a8bb55899d7 /libavcodec/vmnc.c
parentc0d6fc1f739135fe72059a0d5ea9b33e8840fe7e (diff)
Try to handle all chunks, previous scheme was not correct.
Originally committed as revision 6173 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/vmnc.c')
-rw-r--r--libavcodec/vmnc.c130
1 files changed, 62 insertions, 68 deletions
diff --git a/libavcodec/vmnc.c b/libavcodec/vmnc.c
index 927cdcaf87..a39bf271f0 100644
--- a/libavcodec/vmnc.c
+++ b/libavcodec/vmnc.c
@@ -30,7 +30,15 @@
#include "common.h"
#include "avcodec.h"
-#define MAGIC_WMVi 0x574D5669
+enum EncTypes {
+ MAGIC_WMVd = 0x574D5664,
+ MAGIC_WMVe,
+ MAGIC_WMVf,
+ MAGIC_WMVg,
+ MAGIC_WMVh,
+ MAGIC_WMVi,
+ MAGIC_WMVj
+};
enum HexTile_Flags {
HT_RAW = 1, // tile is raw
@@ -174,7 +182,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8
VmncContext * const c = (VmncContext *)avctx->priv_data;
uint8_t *outptr;
uint8_t *src = buf;
- int t, dx, dy, w, h, enc, chunks, res;
+ int dx, dy, w, h, depth, enc, chunks, res;
c->pic.reference = 1;
c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
@@ -183,81 +191,67 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8
return -1;
}
- t = BE_32(src);
- src += 4;
+ c->pic.key_frame = 0;
+ c->pic.pict_type = FF_P_TYPE;
- chunks = t & 0xFF;
- if(chunks > 8) {
- av_log(avctx, AV_LOG_ERROR, "Frame decoding is not possible. Please report sample to developers.\n");
- return -1;
- }
- if(chunks == 8) {
- int w, h, depth;
- c->pic.key_frame = 1;
- c->pic.pict_type = FF_I_TYPE;
-
- /* parse ServerInitialization struct */
- src += 4;
- w = BE_16(src); src += 2;
- h = BE_16(src); src += 2;
- t = BE_32(src); src += 4;
- if(t != MAGIC_WMVi) {
- av_log(avctx, AV_LOG_INFO, "Invalid header: magic not found\n");
- return -1;
- }
- depth = *src++;
- if(depth != c->bpp) {
- av_log(avctx, AV_LOG_INFO, "Depth mismatch. Container %i bpp, Frame data: %i bpp\n", c->bpp, depth);
- }
- src++;
- c->bigendian = *src++;
- if(c->bigendian & (~1)) {
- av_log(avctx, AV_LOG_INFO, "Invalid header: bigendian flag = %i\n", c->bigendian);
- return -1;
- }
- //skip pixel format data
- src += 13;
- chunks = 1; // there should be one chunk with the whole frame, rest could be ignored
- } else {
- c->pic.key_frame = 0;
- c->pic.pict_type = FF_P_TYPE;
- }
+ src += 2;
+ chunks = BE_16(src); src += 2;
while(chunks--) {
- // decode FramebufferUpdate struct
dx = BE_16(src); src += 2;
dy = BE_16(src); src += 2;
w = BE_16(src); src += 2;
h = BE_16(src); src += 2;
- if((dx + w > c->width) || (dy + h > c->height)) {
- av_log(avctx, AV_LOG_ERROR, "Incorrect frame size: %ix%i+%ix%i of %ix%i\n", w, h, dx, dy, c->width, c->height);
- return -1;
- }
enc = BE_32(src); src += 4;
- if(enc != 0x00000005) {
- av_log(avctx, AV_LOG_ERROR, "Only hextile decoding is supported for now\n");
- switch(enc) {
- case 0:
- av_log(avctx, AV_LOG_INFO, "And this is raw encoding\n");
- break;
- case 1:
- av_log(avctx, AV_LOG_INFO, "And this is CopyRect encoding\n");
- break;
- case 2:
- av_log(avctx, AV_LOG_INFO, "And this is RRE encoding\n");
- break;
- case 3:
- av_log(avctx, AV_LOG_INFO, "And this is CoRRE encoding\n");
- break;
- default:
- av_log(avctx, AV_LOG_INFO, "And this is unknown encoding (%i)\n", enc);
+ switch(enc) {
+ case MAGIC_WMVd: // unknown
+ src += 2;
+ src += w * h * 8; // skip this data for now
+ break;
+ case MAGIC_WMVe: // unknown
+ src += 2;
+ break;
+ case MAGIC_WMVf: // unknown and empty
+ break;
+ case MAGIC_WMVi: // ServerInitialization struct
+ c->pic.key_frame = 1;
+ c->pic.pict_type = FF_I_TYPE;
+ depth = *src++;
+ if(depth != c->bpp) {
+ av_log(avctx, AV_LOG_INFO, "Depth mismatch. Container %i bpp, Frame data: %i bpp\n", c->bpp, depth);
+ }
+ src++;
+ c->bigendian = *src++;
+ if(c->bigendian & (~1)) {
+ av_log(avctx, AV_LOG_INFO, "Invalid header: bigendian flag = %i\n", c->bigendian);
+ return -1;
+ }
+ //skip the rest of pixel format data
+ src += 13;
+ break;
+ case 0x00000000: // raw rectangle data
+ if((dx + w > c->width) || (dy + h > c->height)) {
+ av_log(avctx, AV_LOG_ERROR, "Incorrect frame size: %ix%i+%ix%i of %ix%i\n", w, h, dx, dy, c->width, c->height);
+ return -1;
+ }
+ outptr = c->pic.data[0] + dx * c->bpp2 + dy * c->pic.linesize[0];
+ paint_raw(outptr, w, h, src, c->bpp2, c->bigendian, c->pic.linesize[0]);
+ src += w * h * c->bpp2;
+ break;
+ case 0x00000005: // HexTile encoded rectangle
+ if((dx + w > c->width) || (dy + h > c->height)) {
+ av_log(avctx, AV_LOG_ERROR, "Incorrect frame size: %ix%i+%ix%i of %ix%i\n", w, h, dx, dy, c->width, c->height);
+ return -1;
}
- return -1;
+ outptr = c->pic.data[0] + dx * c->bpp2 + dy * c->pic.linesize[0];
+ res = decode_hextile(c, outptr, src, w, h, c->pic.linesize[0]);
+ if(res < 0)
+ return -1;
+ src += res;
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "Unsupported block type 0x%08X\n", enc);
+ chunks = 0; // leave chunks decoding loop
}
- outptr = c->pic.data[0] + dx * c->bpp2 + dy * c->pic.linesize[0];
- res = decode_hextile(c, outptr, src, w, h, c->pic.linesize[0]);
- if(res < 0)
- return -1;
- src += res;
}
*data_size = sizeof(AVFrame);
*(AVFrame*)data = c->pic;