changeset 3679:2702eec8c8b9 libavcodec

Try to handle all chunks, previous scheme was not correct.
author kostya
date Tue, 05 Sep 2006 07:31:53 +0000
parents 93a961e40d65
children 7690bafea6e0
files vmnc.c
diffstat 1 files changed, 64 insertions(+), 70 deletions(-) [+]
line wrap: on
line diff
--- 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;