Try to handle all chunks, previous scheme was not correct.
Originally committed as revision 6173 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
c0d6fc1f73
commit
805934b3e4
@ -30,7 +30,15 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "avcodec.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 {
|
enum HexTile_Flags {
|
||||||
HT_RAW = 1, // tile is raw
|
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;
|
VmncContext * const c = (VmncContext *)avctx->priv_data;
|
||||||
uint8_t *outptr;
|
uint8_t *outptr;
|
||||||
uint8_t *src = buf;
|
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.reference = 1;
|
||||||
c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
t = BE_32(src);
|
c->pic.key_frame = 0;
|
||||||
src += 4;
|
c->pic.pict_type = FF_P_TYPE;
|
||||||
|
|
||||||
chunks = t & 0xFF;
|
src += 2;
|
||||||
if(chunks > 8) {
|
chunks = BE_16(src); src += 2;
|
||||||
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;
|
|
||||||
}
|
|
||||||
while(chunks--) {
|
while(chunks--) {
|
||||||
// decode FramebufferUpdate struct
|
|
||||||
dx = BE_16(src); src += 2;
|
dx = BE_16(src); src += 2;
|
||||||
dy = BE_16(src); src += 2;
|
dy = BE_16(src); src += 2;
|
||||||
w = BE_16(src); src += 2;
|
w = BE_16(src); src += 2;
|
||||||
h = 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;
|
enc = BE_32(src); src += 4;
|
||||||
if(enc != 0x00000005) {
|
switch(enc) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "Only hextile decoding is supported for now\n");
|
case MAGIC_WMVd: // unknown
|
||||||
switch(enc) {
|
src += 2;
|
||||||
case 0:
|
src += w * h * 8; // skip this data for now
|
||||||
av_log(avctx, AV_LOG_INFO, "And this is raw encoding\n");
|
break;
|
||||||
break;
|
case MAGIC_WMVe: // unknown
|
||||||
case 1:
|
src += 2;
|
||||||
av_log(avctx, AV_LOG_INFO, "And this is CopyRect encoding\n");
|
break;
|
||||||
break;
|
case MAGIC_WMVf: // unknown and empty
|
||||||
case 2:
|
break;
|
||||||
av_log(avctx, AV_LOG_INFO, "And this is RRE encoding\n");
|
case MAGIC_WMVi: // ServerInitialization struct
|
||||||
break;
|
c->pic.key_frame = 1;
|
||||||
case 3:
|
c->pic.pict_type = FF_I_TYPE;
|
||||||
av_log(avctx, AV_LOG_INFO, "And this is CoRRE encoding\n");
|
depth = *src++;
|
||||||
break;
|
if(depth != c->bpp) {
|
||||||
default:
|
av_log(avctx, AV_LOG_INFO, "Depth mismatch. Container %i bpp, Frame data: %i bpp\n", c->bpp, depth);
|
||||||
av_log(avctx, AV_LOG_INFO, "And this is unknown encoding (%i)\n", enc);
|
|
||||||
}
|
}
|
||||||
return -1;
|
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
|
||||||
}
|
}
|
||||||
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);
|
*data_size = sizeof(AVFrame);
|
||||||
*(AVFrame*)data = c->pic;
|
*(AVFrame*)data = c->pic;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user