# HG changeset patch # User kostya # Date 1157441513 0 # Node ID 2702eec8c8b9755ec77c60cd26b3e14936769683 # Parent 93a961e40d6563b36e3bde5d64aa9f6cb1a8a1c7 Try to handle all chunks, previous scheme was not correct. diff -r 93a961e40d65 -r 2702eec8c8b9 vmnc.c --- a/vmnc.c Tue Sep 05 07:29:26 2006 +0000 +++ b/vmnc.c Tue Sep 05 07:31:53 2006 +0000 @@ -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 @@ 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 @@ return -1; } - t = BE_32(src); - src += 4; - - 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; + c->pic.key_frame = 0; + c->pic.pict_type = FF_P_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; + 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; + } + 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 } - 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); - } - 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; } *data_size = sizeof(AVFrame); *(AVFrame*)data = c->pic;