OSDN Git Service

fix bitstream decoding.
authorNoumi Akira <noumiakira@users.sourceforge.jp>
Wed, 1 Jul 2009 08:11:49 +0000 (17:11 +0900)
committerNoumi Akira <noumiakira@users.sourceforge.jp>
Wed, 1 Jul 2009 08:11:49 +0000 (17:11 +0900)
Lib/QTheoraEx/FrameDecoder.c
Lib/QTheoraEx/FrameDecoder.h
Lib/QTheoraEx/FrameDecoder_Impl.h

index 566224c..beffcf3 100644 (file)
@@ -237,6 +237,192 @@ static const INT8 COEFFS[5] = { 1, 5, 9, 13, 36 };
 
 /* */
 
+static void DecodeDCCoefficients(FrameDecoder_t* t)
+{
+       INT32 i;
+
+       INT32 eob = 0;
+
+       const UINT8* c = t->Count;
+
+       INT16* dc = t->DC;
+
+       for (i = 0; i < 3; i++) {
+               const INT8*  br = t->BRun  [i][0];
+               const INT16* bc = t->BCoeff[i][0];
+
+               const UINT8* end = c + t->Index->BC[i];
+
+               const UINT16* bi = t->Index->BIndex[i];
+
+               for (; ; ) {
+                       INT16 coeff = 0;
+
+                       for (; c < end && *c == 0xff; c++) {
+                               dc[*(bi++)] = NOT_CODED;
+                       }
+
+                       if (c >= end) {
+                               break;
+                       }
+
+                       if (eob == 0) {
+                               INT8  rr = *(br++);
+                               INT16 cc = *(bc++);
+
+                               if (rr == 0) {
+                                       coeff = cc;
+
+                               } else if (rr < 0) {
+                                       eob = cc;
+                               }
+                       }
+
+                       if (eob > 0) {
+                               eob--;
+                       }
+
+                       dc[*(bi++)] = coeff;
+
+                       c++;
+               }
+
+               dc += t->Index->BC[i];
+       }
+}
+
+/* */
+
+static const INT32 DCP_W[16][4] = {
+       /*  L    DL    D   DR */
+       {   1,    2,   4,   8 },
+
+       { 128,    0,   0,   0 }, /*  1 */
+       {   0,  128,   0,   0 }, /*  2 */
+       { 128,    0,   0,   0 }, /*  3 */
+       {   0,    0, 128,   0 }, /*  4 */
+       {  64,    0,  64,   0 }, /*  5 */
+       {   0,    0, 128,   0 }, /*  6 */
+       { 116, -104, 116,   0 }, /*  7 */
+       {   0,    0,   0, 128 }, /*  8 */
+       {  75,    0,   0,  53 }, /*  9 */
+       {   0,   64,   0,  64 }, /* 10 */
+       {  75,    0,   0,  53 }, /* 11 */
+       {   0,    0, 128,   0 }, /* 12 */
+       {  75,    0,   0,  53 }, /* 13 */
+       {   0,   24,  80,  24 }, /* 14 */
+       { 116, -104, 116,   0 }  /* 15 */
+
+};
+
+static const INT32 DCP_T[8] = {
+       1, 0, 1, 1,
+       1, 2, 2, 1
+};
+
+/* */
+
+static void UndoDCPrediction(
+       FrameDecoder_t* t)
+{
+       INT32 i;
+       INT32 x, y;
+
+       INT16* DC = t->DC;
+
+       const UINT8* mode = t->BMode;
+
+       for (i = 0; i < 3; i++) {
+               INT32 bx = t->Index->BX[i];
+               INT32 by = t->Index->BY[i];
+
+               INT16 last[3] = { 0 };
+
+               INT32 v[4] = { 0 };
+
+               INT32 idx = 0;
+
+               for (y = 0; y < by; y++) {
+                       for (x = 0; x < bx; x++, idx++) {
+                               INT32 dc = DC[idx];
+                               if (dc != NOT_CODED) {
+                                       INT32 pred;
+
+                                       INT32 t0 = 0;
+                                       INT32 type = DCP_T[mode[idx]];
+
+                                       if (x > 0) {
+                                               INT32 i0 = idx - 1;
+                                               v[0] = DC[i0];
+                                               if (v[0] != NOT_CODED && DCP_T[mode[i0]] == type) {
+                                                       t0 += DCP_W[0][0];
+                                               }
+                                       }
+
+                                       if (y > 0) {
+                                               if (x > 0) {
+                                                       INT32 i1 = idx - bx - 1;
+                                                       v[1] = DC[i1];
+                                                       if (v[1] != NOT_CODED && DCP_T[mode[i1]] == type) {
+                                                               t0 += DCP_W[0][1];
+                                                       }
+                                               }
+
+                                               {
+                                                       INT32 i2 = idx - bx;
+                                                       v[2] = DC[i2];
+                                                       if (v[2] != NOT_CODED && DCP_T[mode[i2]] == type) {
+                                                               t0 += DCP_W[0][2];
+                                                       }
+                                               }
+
+                                               if (x < bx - 1) {
+                                                       INT32 i3 = idx - bx + 1;
+                                                       v[3] = DC[i3];
+                                                       if (v[3] != NOT_CODED && DCP_T[mode[i3]] == type) {
+                                                               t0 += DCP_W[0][3];
+                                                       }
+                                               }
+                                       }
+
+                                       if (t0 > 0) {
+                                               pred =
+                                                       ( v[0] * DCP_W[t0][0]
+                                                       + v[1] * DCP_W[t0][1]
+                                                       + v[2] * DCP_W[t0][2]
+                                                       + v[3] * DCP_W[t0][3] ) / 128;
+
+                                               if ((t0 & 0x7) == 7) {
+                                                       INT32 d = pred - v[2]; /* D */
+                                                       if (d < -128 || d > 128) {
+                                                               pred = v[2];
+                                                       } else if (d = pred - v[0], d < -128 || d > 128) { /* L */
+                                                               pred = v[0];
+                                                       } else if (d = pred - v[1], d < -128 || d > 128) { /* DL */
+                                                               pred = v[1];
+                                                       }
+                                               }
+
+                                       } else {
+                                               pred = last[type];
+                                       }
+
+                                       dc += pred;
+
+                                       DC[idx] = dc;
+
+                                       last[type] = dc;
+                               }
+                       }
+               }
+
+               DC   += t->Index->BC[i];
+               mode += t->Index->BC[i];
+       }
+}
+
+/* */
+
 #define ARCH_C
 
 #include "QTheoraArch.h"
@@ -334,6 +520,11 @@ BOOL QT_FrameDecoder_Setup(
                return FALSE;
        }
 
+       t->BMode = (UINT8*)QT_MemoryPool_Allocate(pool, sizeof(UINT8) * index->Blocks);
+       if (t->BMode == NULL) {
+               return FALSE;
+       }
+
        t->MV = (MotionVector_t*)QT_MemoryPool_Allocate(pool, sizeof(MotionVector_t) * index->BC[0]);
        if (t->MV == NULL) {
                return FALSE;
@@ -349,6 +540,11 @@ BOOL QT_FrameDecoder_Setup(
                return FALSE;
        }
 
+       t->DC = (INT16*)QT_MemoryPool_Allocate(pool, sizeof(INT16) * index->Blocks);
+       if (t->DC == NULL) {
+               return FALSE;
+       }
+
        /* */
 
        if (g_QT_Enable_SSE2 || g_QT_Enable_MMX) {
index 8c93481..5dc7289 100644 (file)
@@ -63,6 +63,8 @@ struct QT_FrameDecoder {
 
        UINT8* MBMode;
 
+       UINT8* BMode;
+
        MotionVector_t* MV;
 
        INT32 BlocksCoded[3];
@@ -70,6 +72,10 @@ struct QT_FrameDecoder {
        INT8*  DCTRun;
        INT16* DCTCoeff;
 
+       INT16* DC;
+
+       /* */
+
        INT8*  BRun  [3][64];
        INT16* BCoeff[3][64];
 
@@ -81,6 +87,10 @@ struct QT_FrameDecoder {
 
 /* */
 
+#define NOT_CODED -32768
+
+/* */
+
 BOOL QT_FrameDecoder_Setup(
        FrameDecoder_t*      t,
        const BlockIndex_t*  index,
index a07c16d..0446a06 100644 (file)
@@ -65,6 +65,8 @@ static BOOL FrameDecoder_DecodeCodedBlockFlag(
                t->BlocksCoded[i] = 0;
        }
 
+       memset(t->Count, 0, sizeof(UINT8) * t->Index->Blocks);
+
        /* PARTIAL or FULL */
 
        FETCH_BITS_I(x, 1)
@@ -182,6 +184,13 @@ static BOOL FrameDecoder_DecodeMacroBlockCodingModes(
        UINT8* m   = t->MBMode;
        UINT8* end = m + t->Index->MC;
 
+       const UINT16* mbi = t->Index->MBIndex;
+       const UINT16* cbi = t->Index->CBIndex;
+
+       UINT8* m0 = t->BMode;
+       UINT8* m1 = m0 + t->Index->BC[0];
+       UINT8* m2 = m1 + t->Index->BC[1];
+
        const UINT8* c = t->Count;
 
        FETCH_BITS_I(scheme, 3)
@@ -197,7 +206,7 @@ static BOOL FrameDecoder_DecodeMacroBlockCodingModes(
        }
 
        if (scheme != 7) {
-               for (; m < end; m++, c += 4) {
+               for (; m < end; m++, c += 4, mbi += 4, cbi++) {
                        UINT8 mm = 0;
 
                        if (c[0] != 0xff || c[1] != 0xff || c[2] != 0xff || c[3] != 0xff) {
@@ -209,10 +218,17 @@ static BOOL FrameDecoder_DecodeMacroBlockCodingModes(
                        }
 
                        *m = mm;
+
+                       m0[mbi[0]] = mm;
+                       m0[mbi[1]] = mm;
+                       m0[mbi[2]] = mm;
+                       m0[mbi[3]] = mm;
+                       m1[cbi[0]] = mm;
+                       m2[cbi[0]] = mm;
                }
 
        } else {
-               for (; m < end; m++, c += 4) {
+               for (; m < end; m++, c += 4, mbi += 4, cbi++) {
                        UINT8 mm = 0;
 
                        if (c[0] != 0xff || c[1] != 0xff || c[2] != 0xff || c[3] != 0xff) {
@@ -222,6 +238,13 @@ static BOOL FrameDecoder_DecodeMacroBlockCodingModes(
                        }
 
                        *m = mm;
+
+                       m0[mbi[0]] = mm;
+                       m0[mbi[1]] = mm;
+                       m0[mbi[2]] = mm;
+                       m0[mbi[3]] = mm;
+                       m1[cbi[0]] = mm;
+                       m2[cbi[0]] = mm;
                }
        }
 
@@ -241,9 +264,9 @@ static BOOL FrameDecoder_DecodeMotionVectors(
        const UINT8* m   = t->MBMode;
        const UINT8* end = m + t->Index->MC;
 
-       const UINT8* c = t->Count;
+       const UINT16* mbi = t->Index->MBIndex;
 
-       MotionVector_t* mv = t->MV;
+       const UINT8* c = t->Count;
 
        MotionVector_t last[2] = { { 0, 0 }, { 0, 0 } };
 
@@ -254,7 +277,9 @@ static BOOL FrameDecoder_DecodeMotionVectors(
 
        Decode = (x == 0) ? DecodeMV0 : DecodeMV1;
 
-       for (; m < end; m++, c += 4, mv += 4) {
+       for (; m < end; m++, c += 4, mbi += 4) {
+               MotionVector_t* mv = t->MV + mbi[0];
+
                switch (*m) {
                case 2: /* INTER_MV */
                        LOAD_BITS
@@ -286,27 +311,26 @@ static BOOL FrameDecoder_DecodeMotionVectors(
 
                case 7: /* INTER_MV_FOUR */
                {
-                       const MotionVector_t* mv0 = mv;
-
                        INT32 i;
                        for (i = 0; i < 4; i++) {
-                               /* Check: Raster Order */
+                               MotionVector_t* v = t->MV + mbi[i];
+
                                if (c[i] != 0xff) {
                                        LOAD_BITS
                                        x = GET_BITS_I(16);
-                                       s = Decode(mv + i, x);
+                                       s = Decode(v, x);
                                        RETIRE_BITS(s)
 
-                                       mv0 = mv + i;
+                                       mv = v;
 
                                } else {
-                                       mv[i].X = 0;
-                                       mv[i].Y = 0;
+                                       v->X = 0;
+                                       v->Y = 0;
                                }
                        }
 
                        last[1] = last[0];
-                       last[0] = *mv0;
+                       last[0] = *mv;
                        break;
                }
 
@@ -399,8 +423,6 @@ static BOOL FrameDecoder_DecodeBlocks(
                                }
                        }
 
-                       printf("T: %d\n", token);
-
                        if (token >= 0 && token < 7) {
                                INT32 blen = EOB_BITS_LEN[token];
                                ctx->EOB_Run = EOB_RUN_BASE[token];
@@ -448,7 +470,7 @@ static BOOL FrameDecoder_DecodeBlocks(
                        *((ctx->Run  )++) = run;
                        *((ctx->Coeff)++) = coeff;
 
-                       if (index + run + 1 >= 64) {
+                       if (index + run + 1 > 64) {
                                return FALSE;
                        }
 
@@ -461,13 +483,13 @@ static BOOL FrameDecoder_DecodeBlocks(
                } else {
                        INT32 eob = ctx->EOB_Run;
 
-                       *((ctx->Run  )++) = -1;
-                       *((ctx->Coeff)++) = eob;
-
                        if (eob > count) {
                                eob = count;
                        }
 
+                       *((ctx->Run  )++) = -1;
+                       *((ctx->Coeff)++) = eob;
+
                        for (i = index + 1; i < 64; i++) {
                                ctx->BlocksCoded[i] -= eob;
                        }
@@ -531,8 +553,6 @@ static BOOL FrameDecoder_DecodeDCTCoefficients(
 
                                ctx.BlocksCoded = Coded[k];
 
-                               printf("DCT: %d : %d\n", index, k);
-
                                if (!FrameDecoder_DecodeBlocks(
                                        t,
                                        d,
@@ -568,6 +588,8 @@ static BOOL FrameDecoder_Decode(
        if (t->Header.Type == 0) { /* Intra */
                memset(t->Count, 0, sizeof(UINT8) * t->Index->Blocks);
 
+               memset(t->BMode, 1, t->Index->Blocks);
+
                t->BlocksCoded[0] = t->Index->BC[0];
                t->BlocksCoded[1] = t->Index->BC[1];
                t->BlocksCoded[2] = t->Index->BC[2];
@@ -592,6 +614,62 @@ static BOOL FrameDecoder_Decode(
 
        /* */
 
+       DecodeDCCoefficients(t);
+
+#if 0
+       {
+               INT32 i;
+               INT32 x, y;
+
+               const INT16* dc = t->DC;
+
+               for (i = 0; i < 3; i++) {
+                       INT32 bx = t->Index->BX[i];
+                       INT32 by = t->Index->BY[i];
+
+                       printf("DC: %d\n", i);
+                       for (y = 0; y < by; y++) {
+                               for (x = 0; x < bx; x++, dc++) {
+                                       if (x > 0) {
+                                               printf(" ");
+                                       }
+                                       printf("%d", *dc);
+                               }
+                               printf("\n");
+                       }
+               }
+       }
+#endif
+
+       /* */
+
+       UndoDCPrediction(t);
+
+       {
+               INT32 i;
+               INT32 x, y;
+
+               const INT16* dc = t->DC;
+
+               for (i = 0; i < 3; i++) {
+                       INT32 bx = t->Index->BX[i];
+                       INT32 by = t->Index->BY[i];
+
+                       printf("DC: %d\n", i);
+                       for (y = 0; y < by; y++) {
+                               for (x = 0; x < bx; x++, dc++) {
+                                       if (x > 0) {
+                                               printf(" ");
+                                       }
+                                       printf("%d", *dc);
+                               }
+                               printf("\n");
+                       }
+               }
+       }
+
+       /* */
+
        return TRUE;
 }