summaryrefslogtreecommitdiffstats
path: root/Src/mpeg4dec
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 14:54:57 +0200
committerJef <jef@targetspot.com>2024-09-24 14:54:57 +0200
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/mpeg4dec
parentAdding .gitignore (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar
winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.bz2
winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.lz
winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.xz
winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.zst
winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.zip
Diffstat (limited to 'Src/mpeg4dec')
-rw-r--r--Src/mpeg4dec/mp4dec.h708
-rw-r--r--Src/mpeg4dec/mp4decvop.c1983
-rw-r--r--Src/mpeg4dec/mp4decvopb.c831
-rw-r--r--Src/mpeg4dec/mp4decvopi.c408
-rw-r--r--Src/mpeg4dec/mp4decvopp.c1079
-rw-r--r--Src/mpeg4dec/mp4decvops.c655
-rw-r--r--Src/mpeg4dec/mp4def.h975
-rw-r--r--Src/mpeg4dec/mp4parse.c1109
-rw-r--r--Src/mpeg4dec/mp4stream.c326
-rw-r--r--Src/mpeg4dec/mp4tbl.c153
-rw-r--r--Src/mpeg4dec/mpeg4dec.sln20
-rw-r--r--Src/mpeg4dec/mpeg4dec.vcproj214
-rw-r--r--Src/mpeg4dec/mpeg4vid_api.c661
-rw-r--r--Src/mpeg4dec/mpeg4vid_api.h54
14 files changed, 9176 insertions, 0 deletions
diff --git a/Src/mpeg4dec/mp4dec.h b/Src/mpeg4dec/mp4dec.h
new file mode 100644
index 000000000..9959e1de1
--- /dev/null
+++ b/Src/mpeg4dec/mp4dec.h
@@ -0,0 +1,708 @@
+/* ///////////////////////////////////////////////////////////////////////
+//
+// INTEL CORPORATION PROPRIETARY INFORMATION
+// This software is supplied under the terms of a license agreement or
+// nondisclosure agreement with Intel Corporation and may not be copied
+// or disclosed except in accordance with the terms of that agreement.
+// Copyright (c) 2001-2007 Intel Corporation. All Rights Reserved.
+//
+// Description: MPEG-4 header.
+//
+*/
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//#ifdef __INTEL_COMPILER
+//#include <emmintrin.h>
+//#define USE_INTRINSIC_EMM
+//#else
+#undef USE_INTRINSIC_XMM
+#undef USE_INTRINSIC_EMM
+//#endif
+
+#define USE_TABLE_INTRA_DIV
+
+#define mp4_Div2(a) ((a) >= 0 ? ((a) >> 1) : (((a)+1) >> 1))
+#define mp4_Div2Round(a) (((a) >> 1) | ((a) & 1))
+#define mp4_DivRoundInf(a, b) ((((a) + (((a) >= 0) ? ((b) >> 1) : -((b) >> 1))) / (b)))
+#ifndef USE_TABLE_INTRA_DIV
+#define mp4_DivIntraDC(a, b) (((a) + ((b) >> 1)) / (b))
+#define mp4_DivIntraAC(a, b) mp4_DivRoundInf(a, b)
+#else
+// tested on (-2047..2047) // (1..46)
+#define mp4_DivIntraDC(a, b) (((a) * mp4_DivIntraDivisor[b] + (1 << 17)) >> 18)
+#define mp4_DivIntraAC(a, b) mp4_DivIntraDC(a, b)
+#endif
+
+__INLINE int16_t mp4_Median(int16_t a, int16_t b, int16_t c)
+{
+ if (a > b) {
+ int16_t t = a; a = b; b = t;
+ }
+ return (int16_t)((b <= c) ? b : (c >= a) ? c : a);
+}
+
+__INLINE void mp4_ComputeChromaMV(const IppMotionVector *mvLuma, IppMotionVector *mvChroma)
+{
+ mvChroma->dx = (int16_t)mp4_Div2Round(mvLuma->dx);
+ mvChroma->dy = (int16_t)mp4_Div2Round(mvLuma->dy);
+}
+
+__INLINE void mp4_ComputeChromaMVQ(const IppMotionVector *mvLuma, IppMotionVector *mvChroma)
+{
+ int32_t dx, dy;
+
+ dx = mp4_Div2(mvLuma->dx);
+ dy = mp4_Div2(mvLuma->dy);
+ mvChroma->dx = (int16_t)mp4_Div2Round(dx);
+ mvChroma->dy = (int16_t)mp4_Div2Round(dy);
+}
+
+__INLINE void mp4_ComputeChroma4MV(const IppMotionVector mvLuma[4], IppMotionVector *mvChroma)
+{
+ int32_t dx, dy, cdx, cdy, adx, ady;
+
+ dx = mvLuma[0].dx + mvLuma[1].dx + mvLuma[2].dx + mvLuma[3].dx;
+ dy = mvLuma[0].dy + mvLuma[1].dy + mvLuma[2].dy + mvLuma[3].dy;
+ adx = abs(dx);
+ ady = abs(dy);
+ cdx = mp4_cCbCrMvRound16[adx & 15] + (adx >> 4) * 2;
+ cdy = mp4_cCbCrMvRound16[ady & 15] + (ady >> 4) * 2;
+ mvChroma->dx = (int16_t)((dx >= 0) ? cdx : -cdx);
+ mvChroma->dy = (int16_t)((dy >= 0) ? cdy : -cdy);
+}
+
+__INLINE void mp4_ComputeChroma4MVQ(const IppMotionVector mvLuma[4], IppMotionVector *mvChroma)
+{
+ int32_t dx, dy, cdx, cdy, adx, ady;
+
+ dx = mp4_Div2(mvLuma[0].dx) + mp4_Div2(mvLuma[1].dx) + mp4_Div2(mvLuma[2].dx) + mp4_Div2(mvLuma[3].dx);
+ dy = mp4_Div2(mvLuma[0].dy) + mp4_Div2(mvLuma[1].dy) + mp4_Div2(mvLuma[2].dy) + mp4_Div2(mvLuma[3].dy);
+ adx = abs(dx);
+ ady = abs(dy);
+ cdx = mp4_cCbCrMvRound16[adx & 15] + (adx >> 4) * 2;
+ cdy = mp4_cCbCrMvRound16[ady & 15] + (ady >> 4) * 2;
+ mvChroma->dx = (int16_t)((dx >= 0) ? cdx : -cdx);
+ mvChroma->dy = (int16_t)((dy >= 0) ? cdy : -cdy);
+}
+
+#define limitMV(dx, xmin, xmax, mvd) \
+{ \
+ if ((dx) < (xmin)) \
+ mvd = (int16_t)(xmin); \
+ else if ((dx) >= (xmax)) \
+ mvd = (int16_t)(xmax); \
+ else \
+ mvd = (int16_t)(dx); \
+}
+
+__INLINE void mp4_LimitMV(const IppMotionVector *pSrcMV, IppMotionVector *pDstMV, const IppiRect *limitRect, int32_t x, int32_t y, int32_t size)
+{
+ limitMV(pSrcMV->dx, (limitRect->x - x) << 1, (limitRect->x - x + limitRect->width - size) << 1, pDstMV->dx);
+ limitMV(pSrcMV->dy, (limitRect->y - y) << 1, (limitRect->y - y + limitRect->height - size) << 1, pDstMV->dy);
+}
+
+__INLINE void mp4_LimitMVQ(const IppMotionVector *pSrcMV, IppMotionVector *pDstMV, const IppiRect *limitRect, int32_t x, int32_t y, int32_t size)
+{
+ limitMV(pSrcMV->dx, (limitRect->x - x) << 2, (limitRect->x - x + limitRect->width - size) << 2, pDstMV->dx);
+ limitMV(pSrcMV->dy, (limitRect->y - y) << 2, (limitRect->y - y + limitRect->height - size) << 2, pDstMV->dy);
+}
+
+__INLINE void mp4_Limit4MV(const IppMotionVector *pSrcMV, IppMotionVector *pDstMV, const IppiRect *limitRect, int32_t x, int32_t y, int32_t size)
+{
+ mp4_LimitMV(&pSrcMV[0], &pDstMV[0], limitRect, x , y, size);
+ mp4_LimitMV(&pSrcMV[1], &pDstMV[1], limitRect, x + size, y, size);
+ mp4_LimitMV(&pSrcMV[2], &pDstMV[2], limitRect, x , y + size, size);
+ mp4_LimitMV(&pSrcMV[3], &pDstMV[3], limitRect, x + size, y + size, size);
+}
+
+__INLINE void mp4_Limit4MVQ(const IppMotionVector *pSrcMV, IppMotionVector *pDstMV, const IppiRect *limitRect, int32_t x, int32_t y, int32_t size)
+{
+ mp4_LimitMVQ(&pSrcMV[0], &pDstMV[0], limitRect, x , y, size);
+ mp4_LimitMVQ(&pSrcMV[1], &pDstMV[1], limitRect, x + size, y, size);
+ mp4_LimitMVQ(&pSrcMV[2], &pDstMV[2], limitRect, x , y + size, size);
+ mp4_LimitMVQ(&pSrcMV[3], &pDstMV[3], limitRect, x + size, y + size, size);
+}
+
+__INLINE void mp4_LimitFMV(const IppMotionVector *pSrcMV, IppMotionVector *pDstMV, const IppiRect *limitRect, int32_t x, int32_t y, int32_t size)
+{
+ limitMV(pSrcMV->dx, (limitRect->x - x) << 1, (limitRect->x - x + limitRect->width - size) << 1, pDstMV->dx);
+ limitMV(pSrcMV->dy << 1, (limitRect->y - y) << 1, (limitRect->y - y + limitRect->height - size) << 1, pDstMV->dy);
+ pDstMV->dy >>= 1;
+}
+
+__INLINE void mp4_LimitFMVQ(const IppMotionVector *pSrcMV, IppMotionVector *pDstMV, const IppiRect *limitRect, int32_t x, int32_t y, int32_t size)
+{
+ limitMV(pSrcMV->dx, (limitRect->x - x) << 2, (limitRect->x - x + limitRect->width - size) << 2, pDstMV->dx);
+ limitMV(pSrcMV->dy << 1, (limitRect->y - y) << 2, (limitRect->y - y + limitRect->height - size) << 2, pDstMV->dy);
+ pDstMV->dy >>= 1;
+}
+
+#define MP4_MV_OFF_HP(dx, dy, step) \
+ (((dx) >> 1) + (step) * ((dy) >> 1))
+
+#define MP4_MV_ACC_HP(dx, dy) \
+ ((((dy) & 1) << 1) + ((dx) & 1))
+
+#define MP4_MV_OFF_QP(dx, dy, step) \
+ (((dx) >> 2) + (step) * ((dy) >> 2))
+
+#define MP4_MV_ACC_QP(dx, dy) \
+ ((((dy) & 3) << 2) + ((dx) & 3))
+
+#define mp4_Copy8x4HP_8u(pSrc, srcStep, pDst, dstStep, mv, rc) \
+ ippiCopy8x4HP_8u_C1R(pSrc + MP4_MV_OFF_HP((mv)->dx, (mv)->dy, srcStep), srcStep, pDst, dstStep, MP4_MV_ACC_HP((mv)->dx, (mv)->dy), rc)
+
+#define mp4_Copy8x8HP_8u(pSrc, srcStep, pDst, dstStep, mv, rc) \
+ ippiCopy8x8HP_8u_C1R(pSrc + MP4_MV_OFF_HP((mv)->dx, (mv)->dy, srcStep), srcStep, pDst, dstStep, MP4_MV_ACC_HP((mv)->dx, (mv)->dy), rc)
+
+#define mp4_Copy16x8HP_8u(pSrc, srcStep, pDst, dstStep, mv, rc) \
+ ippiCopy16x8HP_8u_C1R(pSrc + MP4_MV_OFF_HP((mv)->dx, (mv)->dy, srcStep), srcStep, pDst, dstStep, MP4_MV_ACC_HP((mv)->dx, (mv)->dy), rc)
+
+#define mp4_Copy16x16HP_8u(pSrc, srcStep, pDst, dstStep, mv, rc) \
+ ippiCopy16x16HP_8u_C1R(pSrc + MP4_MV_OFF_HP((mv)->dx, (mv)->dy, srcStep), srcStep, pDst, dstStep, MP4_MV_ACC_HP((mv)->dx, (mv)->dy), rc)
+
+#define mp4_Copy8x8QP_8u(pSrc, srcStep, pDst, dstStep, mv, rc) \
+ ippiCopy8x8QP_MPEG4_8u_C1R(pSrc + MP4_MV_OFF_QP((mv)->dx, (mv)->dy, srcStep), srcStep, pDst, dstStep, MP4_MV_ACC_QP((mv)->dx, (mv)->dy), rc)
+
+#define mp4_Copy16x8QP_8u(pSrc, srcStep, pDst, dstStep, mv, rc) \
+ ippiCopy16x8QP_MPEG4_8u_C1R(pSrc + MP4_MV_OFF_QP((mv)->dx, (mv)->dy, srcStep), srcStep, pDst, dstStep, MP4_MV_ACC_QP((mv)->dx, (mv)->dy), rc)
+
+#define mp4_Copy16x16QP_8u(pSrc, srcStep, pDst, dstStep, mv, rc) \
+ ippiCopy16x16QP_MPEG4_8u_C1R(pSrc + MP4_MV_OFF_QP((mv)->dx, (mv)->dy, srcStep), srcStep, pDst, dstStep, MP4_MV_ACC_QP((mv)->dx, (mv)->dy), rc)
+
+#define mp4_Add8x8HP_16s8u(pSrc, srcStep, pResid, pDst, dstStep, mv, rc) \
+ ippiAdd8x8HP_16s8u_C1RS(pResid, 16, pSrc + MP4_MV_OFF_HP((mv)->dx, (mv)->dy, srcStep), srcStep, pDst, dstStep, MP4_MV_ACC_HP((mv)->dx, (mv)->dy), rc)
+
+#define mp4_Add8x8_16s8u(pSrcDst, pResid, srcDstStep) \
+ ippiAdd8x8_16s8u_C1IRS(pResid, 16, pSrcDst, srcDstStep)
+
+
+#define mp4_UpdateQuant(pInfo, quant) \
+{ \
+ quant += mp4_dquant[mp4_GetBits9(pInfo, 2)]; \
+ mp4_CLIP(quant, 1, (1 << pInfo->VisualObject.VideoObject.quant_precision) - 1); \
+}
+
+#define mp4_UpdateQuant_B(pInfo, quant) \
+if (mp4_GetBit(pInfo) != 0) { \
+ quant += (mp4_GetBit(pInfo) == 0) ? -2 : 2; \
+ mp4_CLIP(quant, 1, (1 << pInfo->VisualObject.VideoObject.quant_precision) - 1); \
+}
+
+__INLINE void mp4_Set8x8_8u(uint8_t *p, int32_t step, uint8_t v)
+{
+#if defined(USE_INTRINSIC_XMM) || defined(USE_INTRINSIC_EMM)
+ __m64 _p_v = _mm_set1_pi8(v);
+ *(__m64*)p = _p_v;
+ *(__m64*)(p+step) = _p_v;
+ p += 2 * step;
+ *(__m64*)p = _p_v;
+ *(__m64*)(p+step) = _p_v;
+ p += 2 * step;
+ *(__m64*)p = _p_v;
+ *(__m64*)(p+step) = _p_v;
+ p += 2 * step;
+ *(__m64*)p = _p_v;
+ *(__m64*)(p+step) = _p_v;
+ _mm_empty();
+#else
+ uint32_t val;
+
+ val = v + (v << 8);
+ val += val << 16;
+ ((uint32_t*)p)[0] = val; ((uint32_t*)p)[1] = val; p += step;
+ ((uint32_t*)p)[0] = val; ((uint32_t*)p)[1] = val; p += step;
+ ((uint32_t*)p)[0] = val; ((uint32_t*)p)[1] = val; p += step;
+ ((uint32_t*)p)[0] = val; ((uint32_t*)p)[1] = val; p += step;
+ ((uint32_t*)p)[0] = val; ((uint32_t*)p)[1] = val; p += step;
+ ((uint32_t*)p)[0] = val; ((uint32_t*)p)[1] = val; p += step;
+ ((uint32_t*)p)[0] = val; ((uint32_t*)p)[1] = val; p += step;
+ ((uint32_t*)p)[0] = val; ((uint32_t*)p)[1] = val;
+#endif
+}
+
+__INLINE void mp4_Set16x16_8u(uint8_t *p, int32_t step, uint8_t val)
+{
+ int32_t i, j;
+
+ for (i = 0; i < 16; i ++) {
+ for (j = 0; j < 16; j ++)
+ p[j] = val;
+ p += step;
+ }
+}
+
+#if defined(USE_INTRINSIC_XMM) || defined(USE_INTRINSIC_EMM)
+
+#define mp4_Zero4MV(mv) \
+ memset(mv, 0, 4 * sizeof(IppMotionVector));
+
+#if defined(USE_INTRINSIC_XMM)
+
+#define mp4_Zero64_16s(pDst) \
+{ \
+ __m64 _p_zero = _mm_setzero_si64(); \
+ ((__m64*)(pDst))[0] = _p_zero; \
+ ((__m64*)(pDst))[1] = _p_zero; \
+ ((__m64*)(pDst))[2] = _p_zero; \
+ ((__m64*)(pDst))[3] = _p_zero; \
+ ((__m64*)(pDst))[4] = _p_zero; \
+ ((__m64*)(pDst))[5] = _p_zero; \
+ ((__m64*)(pDst))[6] = _p_zero; \
+ ((__m64*)(pDst))[7] = _p_zero; \
+ ((__m64*)(pDst))[8] = _p_zero; \
+ ((__m64*)(pDst))[9] = _p_zero; \
+ ((__m64*)(pDst))[10] = _p_zero; \
+ ((__m64*)(pDst))[11] = _p_zero; \
+ ((__m64*)(pDst))[12] = _p_zero; \
+ ((__m64*)(pDst))[13] = _p_zero; \
+ ((__m64*)(pDst))[14] = _p_zero; \
+ ((__m64*)(pDst))[15] = _p_zero; \
+ _m_empty(); \
+}
+
+#define mp4_Set64_16s(val, pDst) \
+{ \
+ __m64 _p_val = _mm_set1_pi16((int16_t)(val)); \
+ ((__m64*)(pDst))[0] = _p_val; \
+ ((__m64*)(pDst))[1] = _p_val; \
+ ((__m64*)(pDst))[2] = _p_val; \
+ ((__m64*)(pDst))[3] = _p_val; \
+ ((__m64*)(pDst))[4] = _p_val; \
+ ((__m64*)(pDst))[5] = _p_val; \
+ ((__m64*)(pDst))[6] = _p_val; \
+ ((__m64*)(pDst))[7] = _p_val; \
+ ((__m64*)(pDst))[8] = _p_val; \
+ ((__m64*)(pDst))[9] = _p_val; \
+ ((__m64*)(pDst))[10] = _p_val; \
+ ((__m64*)(pDst))[11] = _p_val; \
+ ((__m64*)(pDst))[12] = _p_val; \
+ ((__m64*)(pDst))[13] = _p_val; \
+ ((__m64*)(pDst))[14] = _p_val; \
+ ((__m64*)(pDst))[15] = _p_val; \
+ _m_empty(); \
+}
+
+#elif defined(USE_INTRINSIC_EMM)
+
+#define mp4_Zero64_16s(pDst) \
+{ \
+ __m128i _p_val = _mm_setzero_si128(); \
+ ((__m128i*)(pDst))[0] = _p_val; \
+ ((__m128i*)(pDst))[1] = _p_val; \
+ ((__m128i*)(pDst))[2] = _p_val; \
+ ((__m128i*)(pDst))[3] = _p_val; \
+ ((__m128i*)(pDst))[4] = _p_val; \
+ ((__m128i*)(pDst))[5] = _p_val; \
+ ((__m128i*)(pDst))[6] = _p_val; \
+ ((__m128i*)(pDst))[7] = _p_val; \
+}
+
+#define mp4_Set64_16s(val, pDst) \
+{ \
+ __m128i _p_val = _mm_set1_epi16((int16_t)(val)); \
+ ((__m128i*)(pDst))[0] = _p_val; \
+ ((__m128i*)(pDst))[1] = _p_val; \
+ ((__m128i*)(pDst))[2] = _p_val; \
+ ((__m128i*)(pDst))[3] = _p_val; \
+ ((__m128i*)(pDst))[4] = _p_val; \
+ ((__m128i*)(pDst))[5] = _p_val; \
+ ((__m128i*)(pDst))[6] = _p_val; \
+ ((__m128i*)(pDst))[7] = _p_val; \
+}
+
+#endif
+
+#else
+
+#define mp4_Zero4MV(mv) \
+ (mv)[0].dx = (mv)[0].dy = (mv)[1].dx = (mv)[1].dy = (mv)[2].dx = (mv)[2].dy = (mv)[3].dx = (mv)[3].dy = 0
+
+#define mp4_Zero64_16s(pDst) \
+{ \
+ int32_t i; \
+ for (i = 0; i < 32; i += 8) { \
+ ((uint32_t*)(pDst))[i] = 0; \
+ ((uint32_t*)(pDst))[i+1] = 0; \
+ ((uint32_t*)(pDst))[i+2] = 0; \
+ ((uint32_t*)(pDst))[i+3] = 0; \
+ ((uint32_t*)(pDst))[i+4] = 0; \
+ ((uint32_t*)(pDst))[i+5] = 0; \
+ ((uint32_t*)(pDst))[i+6] = 0; \
+ ((uint32_t*)(pDst))[i+7] = 0; \
+ } \
+}
+
+#define mp4_Set64_16s(val, pDst) \
+{ \
+ int32_t i; \
+ uint32_t v; \
+ v = ((val) << 16) + (Ipp16u)(val); \
+ for (i = 0; i < 32; i += 8) { \
+ ((uint32_t*)(pDst))[i] = v; \
+ ((uint32_t*)(pDst))[i+1] = v; \
+ ((uint32_t*)(pDst))[i+2] = v; \
+ ((uint32_t*)(pDst))[i+3] = v; \
+ ((uint32_t*)(pDst))[i+4] = v; \
+ ((uint32_t*)(pDst))[i+5] = v; \
+ ((uint32_t*)(pDst))[i+6] = v; \
+ ((uint32_t*)(pDst))[i+7] = v; \
+ } \
+}
+
+#endif
+
+#define mp4_MC_HP(pat, pRef, stepRef, pCur, stepCur, coeffMB, mv, rc) \
+{ \
+ if (pat) { \
+ mp4_Add8x8HP_16s8u(pRef, stepRef, coeffMB, pCur, stepCur, mv, rc); \
+ } else { \
+ mp4_Copy8x8HP_8u(pRef, stepRef, pCur, stepCur, mv, rc); \
+ } \
+}
+
+#define mp4_AddResidual(pat, pc, stepc, coeffMB) \
+{ \
+ if (pat) { \
+ mp4_Add8x8_16s8u(pc, coeffMB, stepc); \
+ } \
+}
+
+#define mp4_DCTInvCoeffsIntraMB(coeffMB, lnz, pFc, stepFc) \
+{ \
+ int32_t i; \
+ for (i = 0; i < 6; i ++) { \
+ if (lnz[i] > 0) \
+ ippiDCT8x8Inv_16s8u_C1R(&coeffMB[i*64], pFc[i], stepFc[i]); \
+ else { \
+ int k = (coeffMB[i*64] + 4) >> 3; \
+ mp4_CLIP(k, 0, 255); \
+ mp4_Set8x8_8u(pFc[i], stepFc[i], (uint8_t)k); \
+ } \
+ } \
+}
+
+#define mp4_ReconstructCoeffsIntraMB_SVH(pInfo, coeffMB, lnz, pat, quant, err) \
+{ \
+ int32_t i, pm = 32; \
+ for (i = 0; i < 6; i ++) { \
+ if (ippiReconstructCoeffsIntra_H263_1u16s(&pInfo->bufptr, &pInfo->bitoff, coeffMB+i*64, &lnz[i], pat & pm, quant, 0, IPPVC_SCAN_ZIGZAG, 0) != ippStsNoErr) { \
+ mp4_Error("Error: decoding coefficients of Intra block"); \
+ goto err; \
+ } \
+ if (pat & pm) { \
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTRA_AC); \
+ } else { \
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTRA_DC); \
+ } \
+ pm >>= 1; \
+ } \
+}
+
+#define mp4_ReconstructCoeffsInterMB_SVH(pInfo, coeffMB, lnz, pat, quant, err) \
+{ \
+ if (pat) { \
+ int32_t i, pm = 32; \
+ for (i = 0; i < 6; i ++) { \
+ if (pat & pm) { \
+ if (ippiReconstructCoeffsInter_H263_1u16s(&pInfo->bufptr, &pInfo->bitoff, coeffMB+i*64, &lnz[i], quant, 0) != ippStsNoErr) { \
+ mp4_Error("Error: decoding coefficients of Inter block"); \
+ goto err; \
+ } \
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_C); \
+ } else { \
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC); \
+ } \
+ pm >>= 1; \
+ } \
+ } else { \
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC); \
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC); \
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC); \
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC); \
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC); \
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC); \
+ } \
+}
+
+#define mp4_DCTInvCoeffsInterMB_SVH(coeffMB, lastNZ, pat) \
+if (pat) { \
+ int32_t i, lnz, pm = 32; \
+ int16_t *coeff = coeffMB; \
+ for (i = 0; i < 6; i ++) { \
+ if ((pat) & pm) { \
+ lnz = lastNZ[i]; \
+ if (lnz != 0) { \
+ if ((lnz <= 4) && (coeff[16] == 0)) \
+ ippiDCT8x8Inv_2x2_16s_C1I(coeff); \
+ else if ((lnz <= 13) && (coeff[32] == 0)) \
+ ippiDCT8x8Inv_4x4_16s_C1I(coeff); \
+ else \
+ ippiDCT8x8Inv_16s_C1I(coeff); \
+ } else \
+ mp4_Set64_16s((int16_t)((coeff[0] + 4) >> 3), coeff); \
+ } \
+ pm >>= 1; \
+ coeff += 64; \
+ } \
+}
+
+#define mp4_DecodeMCInterBlock_SVH(pInfo, quant, pat, pRef, pCur, step, coeffMB, mv, err) \
+{ \
+ if (pat) { \
+ int32_t lnz; \
+ if (ippiReconstructCoeffsInter_H263_1u16s(&pInfo->bufptr, &pInfo->bitoff, coeffMB, &lnz, quant, 0) != ippStsNoErr) { \
+ mp4_Error("Error: decoding coefficients of Inter block"); \
+ goto err; \
+ } \
+ if (lnz != 0) { \
+ if ((lnz <= 4) && (coeffMB[16] == 0)) \
+ ippiDCT8x8Inv_2x2_16s_C1I(coeffMB); \
+ else if ((lnz <= 13) && (coeffMB[32] == 0)) \
+ ippiDCT8x8Inv_4x4_16s_C1I(coeffMB); \
+ else \
+ ippiDCT8x8Inv_16s_C1I(coeffMB); \
+ } else { \
+ mp4_Set64_16s((int16_t)((coeffMB[0] + 4) >> 3), coeffMB); \
+ } \
+ mp4_Add8x8HP_16s8u(pRef, step, coeffMB, pCur, step, mv, 0); \
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_C); \
+ } else { \
+ mp4_Copy8x8HP_8u(pRef, step, pCur, step, mv, 0); \
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC); \
+ } \
+}
+
+// reset Intra prediction buffer on new Video_packet
+#define mp4_ResetIntraPredBuffer(pInfo) \
+{ \
+ mp4_IntraPredBlock *b = pInfo->VisualObject.VideoObject.IntraPredBuff.dcB; \
+ int32_t i; \
+ b[3].dct_dc = b[4].dct_dc = b[5].dct_dc = -1; \
+ b = pInfo->VisualObject.VideoObject.IntraPredBuff.block; \
+ for (i = 0; i <= pInfo->VisualObject.VideoObject.MacroBlockPerRow; i ++) { \
+ b[i*6+0].dct_dc = b[i*6+1].dct_dc = b[i*6+2].dct_dc = b[i*6+3].dct_dc = b[i*6+4].dct_dc = b[i*6+5].dct_dc = -1; \
+ } \
+}
+
+// reset B-prediction blocks on new row
+#define mp4_ResetIntraPredBblock(pInfo) \
+{ \
+ pInfo->VisualObject.VideoObject.IntraPredBuff.dcB[3].dct_dc = \
+ pInfo->VisualObject.VideoObject.IntraPredBuff.dcB[4].dct_dc = \
+ pInfo->VisualObject.VideoObject.IntraPredBuff.dcB[5].dct_dc = -1; \
+}
+
+// mark current MB as invalid for Intra prediction and rotate buffer
+#define mp4_UpdateIntraPredBuffInvalid(pInfo, colNum) \
+{ \
+ mp4_IntraPredBlock *b = &pInfo->VisualObject.VideoObject.IntraPredBuff.block[colNum*6+6]; \
+ pInfo->VisualObject.VideoObject.IntraPredBuff.dcB[3].dct_dc = b[3].dct_dc; \
+ pInfo->VisualObject.VideoObject.IntraPredBuff.dcB[4].dct_dc = b[4].dct_dc; \
+ pInfo->VisualObject.VideoObject.IntraPredBuff.dcB[5].dct_dc = b[5].dct_dc; \
+ b[0].dct_dc = b[1].dct_dc = b[2].dct_dc = b[3].dct_dc = b[4].dct_dc = b[5].dct_dc = -1; \
+ /* pInfo->VisualObject.VideoObject.IntraPredBuff.quant[colNum+1] = (uint8_t)quant; */ \
+}
+
+
+/* 2x2 and 4x4 DCT decision suitable for Classical Zigzag Scan only */
+#define mp4_DecodeMCBlockInter_MPEG4(pat, pr, stepr, pc, stepc, mv, rt, err) \
+{ \
+ if (pat) { \
+ int32_t lnz; \
+ if (ippiReconstructCoeffsInter_MPEG4_1u16s(&pInfo->bufptr, &pInfo->bitoff, coeffMB, &lnz, rvlc, scan, pInfo->VisualObject.VideoObject.QuantInvInterSpec, quant) != ippStsNoErr) { \
+ mp4_Error("Error: decoding coefficients of Inter block"); \
+ goto err; \
+ } \
+ if (pInfo->VisualObject.VideoObject.quant_type == 0 || (coeffMB[63] == 0)) { \
+ if (lnz != 0) { \
+ if ((lnz <= 4) && (coeffMB[16] == 0)) \
+ ippiDCT8x8Inv_2x2_16s_C1I(coeffMB); \
+ else if ((lnz <= 13) && (coeffMB[32] == 0)) \
+ ippiDCT8x8Inv_4x4_16s_C1I(coeffMB); \
+ else \
+ ippiDCT8x8Inv_16s_C1I(coeffMB); \
+ } else { \
+ mp4_Set64_16s((int16_t)((coeffMB[0] + 4) >> 3), coeffMB); \
+ } \
+ } else { \
+ ippiDCT8x8Inv_16s_C1I(coeffMB); \
+ } \
+ mp4_Add8x8HP_16s8u(pr, stepr, coeffMB, pc, stepc, &mv, rt); \
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_C); \
+ } else { \
+ mp4_Copy8x8HP_8u(pr, stepr, pc, stepc, &mv, rt); \
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC); \
+ } \
+}
+
+/* 2x2 and 4x4 DCT decision suitable for Classical Zigzag Scan only */
+#define mp4_DecodeReconBlockInter_MPEG4(pat, pc, stepc, err) \
+{ \
+ if (pat) { \
+ int32_t lnz; \
+ if (ippiReconstructCoeffsInter_MPEG4_1u16s(&pInfo->bufptr, &pInfo->bitoff, coeffMB, &lnz, rvlc, scan, pInfo->VisualObject.VideoObject.QuantInvInterSpec, quant) != ippStsNoErr) { \
+ mp4_Error("Error: decoding coefficients of Inter block"); \
+ goto err; \
+ } \
+ if (pInfo->VisualObject.VideoObject.quant_type == 0 || (coeffMB[63] == 0)) { \
+ if (lnz != 0) { \
+ if ((lnz <= 4) && (coeffMB[16] == 0)) \
+ ippiDCT8x8Inv_2x2_16s_C1I(coeffMB); \
+ else if ((lnz <= 13) && (coeffMB[32] == 0)) \
+ ippiDCT8x8Inv_4x4_16s_C1I(coeffMB); \
+ else \
+ ippiDCT8x8Inv_16s_C1I(coeffMB); \
+ } else { \
+ mp4_Set64_16s((int16_t)((coeffMB[0] + 4) >> 3), coeffMB); \
+ } \
+ } else { \
+ ippiDCT8x8Inv_16s_C1I(coeffMB); \
+ } \
+ mp4_Add8x8_16s8u(pc, coeffMB, stepc); \
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_C); \
+ } else { \
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC); \
+ } \
+}
+
+__INLINE int32_t mp4_GetMacroBlockNumberSize(int32_t nmb)
+{
+ int32_t nb = 0;
+ nmb --;
+ do {
+ nmb >>= 1;
+ nb ++;
+ } while (nmb);
+ return nb;
+}
+
+__INLINE int32_t mp4_GetConvRatio(mp4_Info* pInfo)
+{
+ if (mp4_GetBit(pInfo) == 1)
+ return 0;
+ else
+ return (mp4_GetBit(pInfo) == 0 ? 2 : 4);
+}
+
+// decode cbpy for Inter nontransparent MB
+__INLINE mp4_Status mp4_DecodeCBPY_P(mp4_Info* pInfo, int32_t *yPattern, int32_t mbType)
+{
+ uint32_t code;
+
+ code = mp4_ShowBits9(pInfo, 6);
+ if (mbType < IPPVC_MBTYPE_INTRA)
+ *yPattern = 15 - mp4_cbpy4[code].code;
+ else
+ *yPattern = mp4_cbpy4[code].code;
+ if (mp4_cbpy4[code].len == 255) {
+ mp4_Error("Error: decoding CBPY");
+ return MP4_STATUS_ERROR;
+ } else {
+ mp4_FlushBits(pInfo, mp4_cbpy4[code].len);
+ return MP4_STATUS_OK;
+ }
+}
+
+// decode cbpy for Intra nontransparent MB
+
+__INLINE mp4_Status mp4_DecodeCBPY_I(mp4_Info* pInfo, int32_t *yPattern)
+{
+ uint32_t code;
+
+ code = mp4_ShowBits9(pInfo, 6);
+ *yPattern = mp4_cbpy4[code].code;
+ if (mp4_cbpy4[code].len == 255) {
+ mp4_Error("Error: decoding CBPY");
+ return MP4_STATUS_ERROR;
+ } else {
+ mp4_FlushBits(pInfo, mp4_cbpy4[code].len);
+ return MP4_STATUS_OK;
+ }
+}
+
+extern mp4_Status mp4_DecodeMVD(mp4_Info *pInfo, int32_t *mvdx, int32_t *mvdy, int32_t fcode);
+extern mp4_Status mp4_DecodeMV(mp4_Info *pInfo, IppMotionVector *mv, int32_t fcode);
+extern mp4_Status mp4_Decode4MV(mp4_Info *pInfo, IppMotionVector *mv, int32_t fcode);
+extern mp4_Status mp4_DecodeMV_Direct(mp4_Info *pInfo, IppMotionVector mvC[4], IppMotionVector mvForw[4], IppMotionVector mvBack[4], int32_t TRB, int32_t TRD, int32_t modb, int32_t comb_type);
+extern mp4_Status mp4_DecodeMV_DirectField(mp4_Info *pInfo, int32_t mb_ftfr, int32_t mb_fbfr, IppMotionVector *mvTop, IppMotionVector *mvBottom, IppMotionVector *mvForwTop, IppMotionVector *mvForwBottom, IppMotionVector *mvBackTop, IppMotionVector *mvBackBottom, int32_t TRB, int32_t TRD, int32_t modb);
+extern mp4_Status mp4_DecodeIntraMB_SVH(mp4_Info *pInfo, int32_t pat, int32_t quant, uint8_t *pR[], int32_t stepR[]);
+extern mp4_Status mp4_DecodeIntraMB_DP(mp4_Info *pInfo, int16_t dct_dc[], int32_t x, int32_t pat, int32_t quant, int32_t dcVLC, int32_t ac_pred_flag, uint8_t *pR[], int32_t stepR[]);
+extern mp4_Status mp4_DecodeIntraMB(mp4_Info *pInfo, int32_t x, int32_t pat, int32_t quant, int32_t dcVLC, int32_t ac_pred_flag, uint8_t *pR[], int32_t stepR[]);
+extern mp4_Status mp4_DecodeInterMB_SVH(mp4_Info *pInfo, int16_t *coeffMB, int32_t quant, int32_t pat);
+extern mp4_Status mp4_DecodeInterMB(mp4_Info *pInfo, int16_t *coeffMB, int32_t quant, int32_t pat, int32_t scan);
+extern mp4_Status mp4_ReconstructCoeffsIntraMB(mp4_Info *pInfo, int32_t x, int32_t pat, int32_t quant, int32_t dcVLC, int32_t ac_pred_flag, int16_t *coeff, int32_t lnz[]);
+extern mp4_Status mp4_DecodeMCBPC_P(mp4_Info* pInfo, int32_t *mbType, int32_t *mbPattern, int32_t stat);
+extern mp4_Status mp4_PredictDecode1MV(mp4_Info *pInfo, mp4_MacroBlock *MBcurr, int32_t y, int32_t x);
+extern mp4_Status mp4_PredictDecode4MV(mp4_Info *pInfo, mp4_MacroBlock *MBcurr, int32_t y, int32_t x);
+extern mp4_Status mp4_PredictDecodeFMV(mp4_Info *pInfo, mp4_MacroBlock *MBcurr, int32_t y, int32_t x, IppMotionVector *mvT, IppMotionVector *mvB);
+extern mp4_Status mp4_DecodeVideoObjectPlane(mp4_Info* pInfo);
+extern mp4_Status mp4_DecodeVOP_I(mp4_Info* pInfo);
+extern mp4_Status mp4_DecodeVOP_P(mp4_Info* pInfo);
+extern mp4_Status mp4_DecodeVOP_B(mp4_Info* pInfo);
+extern mp4_Status mp4_DecodeVOP_S(mp4_Info* pInfo);
+extern mp4_Status mp4_DecodeVOP_I_MT(mp4_Info* pInfo);
+extern mp4_Status mp4_DecodeVOP_P_MT(mp4_Info* pInfo);
+extern mp4_Status mp4_DecodeVOP_B_MT(mp4_Info* pInfo);
+extern mp4_Status mp4_DecodeVOP_S_MT(mp4_Info* pInfo);
+extern void mp4_DCTInvCoeffsInterMB(mp4_Info *pInfo, int16_t *coeffMB, int32_t lnz[], int32_t pat, int32_t scan);
+extern void mp4_PadFrame(mp4_Info* pInfo);
+extern void mp4_OBMC(mp4_Info *pInfo, mp4_MacroBlock *pMBinfo, IppMotionVector *mvCur, int32_t colNum, int32_t rowNum, IppiRect limitRectL, uint8_t *pYc, int32_t stepYc, uint8_t *pYr, int32_t stepYr, int32_t cbpy, int16_t *coeffMB, int32_t dct_type);
+extern mp4_Status mp4_CheckDecodeVideoPacket(mp4_Info* pInfo, int32_t *found);
+extern int32_t mp4_CheckDecodeGOB_SVH(mp4_Info* pInfo);
+extern void mp4_CopyMacroBlocks(const mp4_Frame *rFrame, mp4_Frame *cFrame, int32_t mbPerRow, int32_t rowNum, int32_t colNum, int32_t n);
+
+extern mp4_Status mp4_Sprite_Trajectory(mp4_Info* pInfo);
+extern mp4_Status mp4_PredictDecodeMV(mp4_Info *pInfo, mp4_MacroBlock *MBcurr, int32_t frGOB, int32_t y, int32_t x);
+extern mp4_Status mp4_DecodeMCBPC_I(mp4_Info* pInfo, int32_t *mbType, int32_t *mbPattern);
+
+#ifdef FLOAT_POINT_IDCT
+
+static void fIDCT_16s8u_C1R(int16_t *coeff, uint8_t *pR, int stepR)
+{
+ __ALIGN16(Ipp32f, c, 64);
+ int i, j;
+
+ for (i = 0; i < 64; i ++)
+ c[i] = coeff[i];
+ ippiDCT8x8Inv_32f_C1I(c);
+ for (i = 0; i < 8; i ++)
+ for (j = 0; j < 8; j ++)
+ pR[i*stepR+j] = c[i*8+j] < 0 ? 0 : c[i*8+j] > 255 ? 255 : (int16_t)(c[i*8+j] + 0.5f);
+}
+
+static void fIDCT_16s_C1I(int16_t *coeff)
+{
+ __ALIGN16(Ipp32f, c, 64);
+ int i;
+
+ for (i = 0; i < 64; i ++)
+ c[i] = coeff[i];
+ ippiDCT8x8Inv_32f_C1I(c);
+ for (i = 0; i < 64; i ++)
+ coeff[i] = c[i] < 0 ? (int16_t)(c[i] - 0.5f) : (int16_t)(c[i] + 0.5f);
+}
+
+#define ippiDCT8x8Inv_16s8u_C1R(coeff, pR, stepR) \
+ fIDCT_16s8u_C1R(coeff, pR, stepR)
+
+#define ippiDCT8x8Inv_2x2_16s_C1I(coeff) \
+ fIDCT_16s_C1I(coeff)
+
+#define ippiDCT8x8Inv_4x4_16s_C1I(coeff) \
+ fIDCT_16s_C1I(coeff)
+
+#define ippiDCT8x8Inv_16s_C1I(coeff) \
+ fIDCT_16s_C1I(coeff)
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/Src/mpeg4dec/mp4decvop.c b/Src/mpeg4dec/mp4decvop.c
new file mode 100644
index 000000000..3bd8b2a27
--- /dev/null
+++ b/Src/mpeg4dec/mp4decvop.c
@@ -0,0 +1,1983 @@
+/* ///////////////////////////////////////////////////////////////////////
+//
+// INTEL CORPORATION PROPRIETARY INFORMATION
+// This software is supplied under the terms of a license agreement or
+// nondisclosure agreement with Intel Corporation and may not be copied
+// or disclosed except in accordance with the terms of that agreement.
+// Copyright (c) 2001-2008 Intel Corporation. All Rights Reserved.
+//
+// Description: Decodes MPEG-4 bitstream.
+//
+*/
+
+#include "mp4def.h"
+#include "mp4dec.h"
+
+#pragma warning(disable : 188) // enumerated type mixed with another type ICL
+
+void mp4_ResetVOL(mp4_Info *pInfo)
+{
+ pInfo->VisualObject.VideoObject.VOPindex = 0;
+ pInfo->VisualObject.VideoObject.prevPlaneIsB = 0;
+ pInfo->VisualObject.VideoObject.GroupOfVideoObjectPlane.time_code = 0;
+ ReleaseFrame(&pInfo->VisualObject, pInfo->VisualObject.cFrame);
+ pInfo->VisualObject.cFrame=0;
+ ReleaseFrame(&pInfo->VisualObject, pInfo->VisualObject.rFrame);
+ pInfo->VisualObject.rFrame=0;
+ ReleaseFrame(&pInfo->VisualObject, pInfo->VisualObject.nFrame);
+ pInfo->VisualObject.nFrame=0;
+ ReleaseFrame(&pInfo->VisualObject, pInfo->VisualObject.sFrame);
+ pInfo->VisualObject.sFrame=0;
+}
+
+static int AllocateInitFrame(mp4_Frame* pFrame)
+{
+ int32_t w, h;
+
+ w = (pFrame->mbPerRow + 2 * MP4_NUM_EXT_MB) << 4;
+ h = (pFrame->mbPerCol + 2 * MP4_NUM_EXT_MB) << 4;
+ pFrame->mid = malloc(w * h + (w * h >> 1));
+ if (!pFrame->mid)
+ return 1; // out of memory
+
+ ippsSet_8u(0, pFrame->mid, w * h);
+ ippsSet_8u(128, pFrame->mid + w * h, w * h >> 1);
+
+ pFrame->stepY = w;
+ pFrame->stepCb = w >> 1;
+ pFrame->stepCr = w >> 1;
+
+ /* benski> stuff from LockFrame... */
+ pFrame->apY = pFrame->mid;
+ pFrame->pY = pFrame->apY + w * 16 + 16;
+ pFrame->apCb = pFrame->apY + w * h;
+ w >>= 1;
+ h >>= 1;
+ pFrame->pCb = pFrame->apCb + w * 8 + 8;
+ pFrame->apCr = pFrame->apCb + w * h;
+ pFrame->pCr = pFrame->apCr + w * 8 + 8;
+
+ return 0;
+}
+
+static mp4_Status mp4_AllocInitFrame(mp4_Frame* pFrame, int32_t mbPerRow, int32_t mbPerCol)
+{
+ int32_t w, h;
+
+ w = (mbPerRow + 2 * MP4_NUM_EXT_MB) << 4;
+ h = (mbPerCol + 2 * MP4_NUM_EXT_MB) << 4;
+ pFrame->stepY = w;
+ pFrame->apY = ippsMalloc_8u(w * h);
+ if (!pFrame->apY)
+ return MP4_STATUS_NO_MEM;
+ ippsSet_8u(0, pFrame->apY, w * h);
+ pFrame->pY = pFrame->apY + w * 16 + 16;
+ w >>= 1;
+ h >>= 1;
+ pFrame->stepCb = w;
+ pFrame->apCb = ippsMalloc_8u(w * h);
+ if (!pFrame->apCb)
+ return MP4_STATUS_NO_MEM;
+ ippsSet_8u(128, pFrame->apCb, w * h);
+ pFrame->pCb = pFrame->apCb + w * 8 + 8;
+ pFrame->stepCr = w;
+ pFrame->apCr = ippsMalloc_8u(w * h);
+ if (!pFrame->apCr)
+ return MP4_STATUS_NO_MEM;
+ pFrame->pCr = pFrame->apCr + w * 8 + 8;
+ ippsSet_8u(128, pFrame->apCr, w * h);
+ return MP4_STATUS_OK;
+}
+
+/*
+// mp4_Info for decoding of Video Object Layer
+*/
+mp4_Status mp4_InitVOL(mp4_Info* pInfo)
+{
+ int32_t mbPerRow, mbPerCol, specSize;
+
+ if (pInfo->VisualObject.VideoObject.short_video_header) {
+ pInfo->noBVOPs = 1;
+ } else {
+ if (pInfo->strictSyntaxCheck) {
+ if (pInfo->VisualObject.VideoObject.random_accessible_vol)
+ pInfo->noPVOPs = pInfo->noBVOPs = 1;
+ if (pInfo->VisualObject.VideoObject.type_indication == MP4_VIDEO_OBJECT_TYPE_SIMPLE ||
+ pInfo->VisualObject.VideoObject.type_indication == MP4_VIDEO_OBJECT_TYPE_ADVANCED_REAL_TIME_SIMPLE ||
+ pInfo->VisualObject.VideoObject.VOLControlParameters.low_delay) {
+ pInfo->noBVOPs = 1;
+ }
+ }
+ }
+ if (pInfo->VisualObject.VideoObject.shape == MP4_SHAPE_TYPE_RECTANGULAR)
+ {
+ mbPerRow = (pInfo->VisualObject.VideoObject.width + 15) >> 4;
+ mbPerCol = (pInfo->VisualObject.VideoObject.height + 15) >> 4;
+ // current frame
+// if (mp4_AllocInitFrame(&pInfo->VisualObject.cFrame, mbPerRow, mbPerCol) != MP4_STATUS_OK)
+// return MP4_STATUS_NO_MEM;
+ if (pInfo->VisualObject.VideoObject.sprite_enable != MP4_SPRITE_STATIC)
+ {
+ // ref in past frame
+// if (mp4_AllocInitFrame(&pInfo->VisualObject.rFrame, mbPerRow, mbPerCol) != MP4_STATUS_OK)
+// return MP4_STATUS_NO_MEM;
+ // ref in future frame
+// if (mp4_AllocInitFrame(&pInfo->VisualObject.nFrame, mbPerRow, mbPerCol) != MP4_STATUS_OK)
+// return MP4_STATUS_NO_MEM;
+ // motion info (not needed for Sprites)
+ pInfo->VisualObject.VideoObject.MBinfo = (mp4_MacroBlock*)ippsMalloc_8u(mbPerRow*mbPerCol*sizeof(mp4_MacroBlock));
+ if (!pInfo->VisualObject.VideoObject.MBinfo) return MP4_STATUS_NO_MEM;
+#ifdef USE_NOTCODED_STATE
+ // not_coded MB state
+ pInfo->VisualObject.VideoObject.ncState = ippsMalloc_8u(mbPerCol * mbPerRow);
+ if (!pInfo->VisualObject.VideoObject.ncState) return MP4_STATUS_NO_MEM;
+ pInfo->VisualObject.VideoObject.ncStateCleared = 0;
+#endif
+ }
+ else
+ { // data for static sprite
+ mbPerRow = pInfo->VisualObject.sFrame->mbPerRow = (pInfo->VisualObject.VideoObject.sprite_width + 15) >> 4;
+ mbPerCol = pInfo->VisualObject.sFrame->mbPerCol = (pInfo->VisualObject.VideoObject.sprite_height + 15) >> 4;
+// if (mp4_AllocInitFrame(&pInfo->VisualObject.sFrame, mbPerRow, mbPerCol) != MP4_STATUS_OK)
+// return MP4_STATUS_NO_MEM;
+ }
+ pInfo->VisualObject.VideoObject.MacroBlockPerRow = mbPerRow;
+ pInfo->VisualObject.VideoObject.MacroBlockPerCol = mbPerCol;
+ pInfo->VisualObject.VideoObject.MacroBlockPerVOP = mbPerRow * mbPerCol;
+ pInfo->VisualObject.VideoObject.mbns = mp4_GetMacroBlockNumberSize(pInfo->VisualObject.VideoObject.MacroBlockPerVOP);
+
+ if (!pInfo->VisualObject.VideoObject.short_video_header)
+ {
+ // Intra Prediction info (not needed for SVH)
+ pInfo->VisualObject.VideoObject.IntraPredBuff.quant = ippsMalloc_8u(mbPerRow + 1);
+ if (!pInfo->VisualObject.VideoObject.IntraPredBuff.quant) return MP4_STATUS_NO_MEM;
+ pInfo->VisualObject.VideoObject.IntraPredBuff.block = (mp4_IntraPredBlock*)ippsMalloc_8u((mbPerRow + 1)*6*sizeof(mp4_IntraPredBlock));
+ if (!pInfo->VisualObject.VideoObject.IntraPredBuff.block) return MP4_STATUS_NO_MEM;
+ {
+ mp4_IntraPredBlock *mbCurr = pInfo->VisualObject.VideoObject.IntraPredBuff.block;
+ mp4_IntraPredBlock *mbA = mbCurr, *mbB = pInfo->VisualObject.VideoObject.IntraPredBuff.dcB, *mbC = mbCurr + 6;
+ int32_t j;
+
+ for (j = 0; j < mbPerRow; j ++) {
+ mbCurr[0].predA = &mbA[1]; mbCurr[0].predB = &mbB[3]; mbCurr[0].predC = &mbC[2];
+ mbCurr[1].predA = &mbC[0]; mbCurr[1].predB = &mbC[2]; mbCurr[1].predC = &mbC[3];
+ mbCurr[2].predA = &mbA[3]; mbCurr[2].predB = &mbA[1]; mbCurr[2].predC = &mbC[0];
+ mbCurr[3].predA = &mbC[2]; mbCurr[3].predB = &mbC[0]; mbCurr[3].predC = &mbC[1];
+ mbCurr[4].predA = &mbA[4]; mbCurr[4].predB = &mbB[4]; mbCurr[4].predC = &mbC[4];
+ mbCurr[5].predA = &mbA[5]; mbCurr[5].predB = &mbB[5]; mbCurr[5].predC = &mbC[5];
+ mbCurr += 6; mbA += 6; mbC += 6;
+ }
+ }
+ if (pInfo->VisualObject.VideoObject.data_partitioned) {
+ // DataPart info
+ pInfo->VisualObject.VideoObject.DataPartBuff = (mp4_DataPartMacroBlock*)ippsMalloc_8u(mbPerRow*mbPerCol*sizeof(mp4_DataPartMacroBlock));
+ if (!pInfo->VisualObject.VideoObject.DataPartBuff) return MP4_STATUS_NO_MEM;
+ }
+ if (pInfo->VisualObject.VideoObject.interlaced) {
+ // Field MV for B-VOP
+ pInfo->VisualObject.VideoObject.FieldMV = (IppMotionVector*)ippsMalloc_8u(mbPerRow*mbPerCol*sizeof(IppMotionVector)*2);
+ if (!pInfo->VisualObject.VideoObject.FieldMV) return MP4_STATUS_NO_MEM;
+ }
+ ippiQuantInvIntraGetSize_MPEG4(&specSize);
+ pInfo->VisualObject.VideoObject.QuantInvIntraSpec = (IppiQuantInvIntraSpec_MPEG4*)ippsMalloc_8u(specSize);
+ ippiQuantInvIntraInit_MPEG4(pInfo->VisualObject.VideoObject.quant_type ? pInfo->VisualObject.VideoObject.intra_quant_mat : NULL, pInfo->VisualObject.VideoObject.QuantInvIntraSpec, 8);
+ ippiQuantInvInterGetSize_MPEG4(&specSize);
+ pInfo->VisualObject.VideoObject.QuantInvInterSpec = (IppiQuantInvInterSpec_MPEG4*)ippsMalloc_8u(specSize);
+ ippiQuantInvInterInit_MPEG4(pInfo->VisualObject.VideoObject.quant_type ? pInfo->VisualObject.VideoObject.nonintra_quant_mat : NULL, pInfo->VisualObject.VideoObject.QuantInvInterSpec, 8);
+ ippiWarpGetSize_MPEG4(&specSize);
+ pInfo->VisualObject.VideoObject.WarpSpec = (IppiWarpSpec_MPEG4*)ippsMalloc_8u(specSize);
+ }
+ }
+ return MP4_STATUS_OK;
+}
+
+/*
+// Free memory allocated for mp4_Info
+*/
+mp4_Status mp4_FreeVOL(mp4_Info* pInfo)
+{
+ if (pInfo->VisualObject.VideoObject.shape == MP4_SHAPE_TYPE_RECTANGULAR) {
+ if (pInfo->VisualObject.VideoObject.sprite_enable != MP4_SPRITE_STATIC) {
+ ippsFree(pInfo->VisualObject.VideoObject.MBinfo); pInfo->VisualObject.VideoObject.MBinfo = NULL;
+#ifdef USE_NOTCODED_STATE
+ ippsFree(pInfo->VisualObject.VideoObject.ncState);
+#endif
+ } else {
+ }
+ if (!pInfo->VisualObject.VideoObject.short_video_header) {
+ ippsFree(pInfo->VisualObject.VideoObject.IntraPredBuff.quant); pInfo->VisualObject.VideoObject.IntraPredBuff.quant = NULL;
+ ippsFree(pInfo->VisualObject.VideoObject.IntraPredBuff.block); pInfo->VisualObject.VideoObject.IntraPredBuff.block = NULL;
+ if (pInfo->VisualObject.VideoObject.data_partitioned) {
+ ippsFree(pInfo->VisualObject.VideoObject.DataPartBuff); pInfo->VisualObject.VideoObject.DataPartBuff = NULL;
+ }
+ if (pInfo->VisualObject.VideoObject.interlaced) {
+ ippsFree(pInfo->VisualObject.VideoObject.FieldMV); pInfo->VisualObject.VideoObject.FieldMV = NULL;
+ }
+ ippsFree(pInfo->VisualObject.VideoObject.QuantInvIntraSpec); pInfo->VisualObject.VideoObject.QuantInvIntraSpec = NULL;
+ ippsFree(pInfo->VisualObject.VideoObject.QuantInvInterSpec); pInfo->VisualObject.VideoObject.QuantInvInterSpec = NULL;
+ ippsFree(pInfo->VisualObject.VideoObject.WarpSpec); pInfo->VisualObject.VideoObject.WarpSpec = NULL;
+ }
+
+ }
+ return MP4_STATUS_OK;
+}
+
+
+mp4_Status mp4_DecodeMVD(mp4_Info *pInfo, int32_t *mvdx, int32_t *mvdy, int32_t fcode)
+{
+ const mp4_VLC1 *pTab;
+ int32_t mvd, sign;
+ uint32_t code;
+ int32_t factor = fcode - 1;
+
+ /* decode MVDx */
+ code = mp4_ShowBits(pInfo, 12);
+ if (code >= 128)
+ pTab = mp4_MVD_B12_2 + ((code - 128) >> 5);
+ else if (code >= 2)
+ pTab = mp4_MVD_B12_1 + (code - 2);
+ else {
+ mp4_Error("Error: decoding MVD");
+ return MP4_STATUS_ERROR;
+ }
+ mvd = pTab->code;
+ mp4_FlushBits(pInfo, pTab->len);
+ if (mvd) {
+ sign = mp4_GetBit(pInfo);
+ if (factor) {
+ code = mp4_GetBits9(pInfo, factor);
+ mvd = ((mvd - 1) << factor) + code + 1;
+ }
+ if (sign)
+ mvd = -mvd;
+ }
+ *mvdx = mvd;
+ /* decode MVDy */
+ code = mp4_ShowBits(pInfo, 12);
+ if (code >= 128)
+ pTab = mp4_MVD_B12_2 + ((code - 128) >> 5);
+ else if (code >= 2)
+ pTab = mp4_MVD_B12_1 + (code - 2);
+ else {
+ mp4_Error("Error: decoding MVD");
+ return MP4_STATUS_ERROR;
+ }
+ mvd = pTab->code;
+ mp4_FlushBits(pInfo, pTab->len);
+ if (mvd) {
+ sign = mp4_GetBit(pInfo);
+ if (factor) {
+ code = mp4_GetBits9(pInfo, factor);
+ mvd = ((mvd - 1) << factor) + code + 1;
+ }
+ if (sign)
+ mvd = -mvd;
+ }
+ *mvdy = mvd;
+ return MP4_STATUS_OK;
+}
+
+mp4_Status mp4_DecodeMV(mp4_Info *pInfo, IppMotionVector *mv, int32_t fcode)
+{
+ int32_t mvdx, mvdy, range, range2, dx, dy;
+
+ if (mp4_DecodeMVD(pInfo, &mvdx, &mvdy, fcode) != MP4_STATUS_OK)
+ return MP4_STATUS_ERROR;
+ range = 16 << fcode;
+ range2 = range + range;
+ dx = mv->dx + mvdx;
+ if (dx < -range)
+ dx += range2;
+ else if (dx >= range)
+ dx -= range2;
+ mv->dx = (int16_t)dx;
+ dy = mv->dy + mvdy;
+ if (dy < -range)
+ dy += range2;
+ else if (dy >= range)
+ dy -= range2;
+ mv->dy = (int16_t)dy;
+ return MP4_STATUS_OK;
+}
+
+mp4_Status mp4_Decode4MV(mp4_Info *pInfo, IppMotionVector *mv, int32_t fcode)
+{
+ int32_t i, mvdx, mvdy, range, range2, dx, dy;
+
+ range = 16 << fcode;
+ range2 = range + range;
+ for (i = 0; i < 4; i ++) {
+ if (mp4_DecodeMVD(pInfo, &mvdx, &mvdy, fcode) != MP4_STATUS_OK)
+ return MP4_STATUS_ERROR;
+ dx = mv[i].dx + mvdx;
+ if (dx < -range)
+ dx += range2;
+ else if (dx >= range)
+ dx -= range2;
+ mv[i].dx = (int16_t)dx;
+ dy = mv[i].dy + mvdy;
+ if (dy < -range)
+ dy += range2;
+ else if (dy >= range)
+ dy -= range2;
+ mv[i].dy = (int16_t)dy;
+ }
+ return MP4_STATUS_OK;
+}
+
+mp4_Status mp4_DecodeMV_Direct(mp4_Info *pInfo, IppMotionVector mvC[4], IppMotionVector mvForw[4], IppMotionVector mvBack[4], int32_t TRB, int32_t TRD, int32_t modb, int32_t comb_type)
+{
+ int32_t mvdx, mvdy, i;
+
+ if (modb == 2) {
+ if (comb_type != IPPVC_MBTYPE_INTER4V) {
+ mvForw[0].dx = mvForw[1].dx = mvForw[2].dx = mvForw[3].dx = (int16_t)((TRB * mvC[0].dx) / TRD);
+ mvForw[0].dy = mvForw[1].dy = mvForw[2].dy = mvForw[3].dy = (int16_t)((TRB * mvC[0].dy) / TRD);
+ mvBack[0].dx = mvBack[1].dx = mvBack[2].dx = mvBack[3].dx = (int16_t)(((TRB - TRD) * mvC[0].dx) / TRD);
+ mvBack[0].dy = mvBack[1].dy = mvBack[2].dy = mvBack[3].dy = (int16_t)(((TRB - TRD) * mvC[0].dy) / TRD);
+ } else
+ for (i = 0; i < 4; i ++) {
+ mvForw[i].dx = (int16_t)((TRB * mvC[i].dx) / TRD);
+ mvForw[i].dy = (int16_t)((TRB * mvC[i].dy) / TRD);
+ mvBack[i].dx = (int16_t)(((TRB - TRD) * mvC[i].dx) / TRD);
+ mvBack[i].dy = (int16_t)(((TRB - TRD) * mvC[i].dy) / TRD);
+ }
+ } else {
+ if (mp4_DecodeMVD(pInfo, &mvdx, &mvdy, 1) != MP4_STATUS_OK)
+ return MP4_STATUS_ERROR;
+ if (comb_type != IPPVC_MBTYPE_INTER4V) {
+ mvForw[0].dx = mvForw[1].dx = mvForw[2].dx = mvForw[3].dx = (int16_t)((TRB * mvC[0].dx) / TRD + mvdx);
+ mvForw[0].dy = mvForw[1].dy = mvForw[2].dy = mvForw[3].dy = (int16_t)((TRB * mvC[0].dy) / TRD + mvdy);
+ if (mvdx == 0)
+ mvBack[0].dx = mvBack[1].dx = mvBack[2].dx = mvBack[3].dx = (int16_t)(((TRB - TRD) * mvC[0].dx) / TRD);
+ else
+ mvBack[0].dx = mvBack[1].dx = mvBack[2].dx = mvBack[3].dx = (int16_t)(mvForw[0].dx - mvC[0].dx);
+ if (mvdy == 0)
+ mvBack[0].dy = mvBack[1].dy = mvBack[2].dy = mvBack[3].dy = (int16_t)(((TRB - TRD) * mvC[0].dy) / TRD);
+ else
+ mvBack[0].dy = mvBack[1].dy = mvBack[2].dy = mvBack[3].dy = (int16_t)(mvForw[0].dy - mvC[0].dy);
+ } else
+ for (i = 0; i < 4; i++) {
+ mvForw[i].dx = (int16_t)((TRB * mvC[i].dx) / TRD + mvdx);
+ mvForw[i].dy = (int16_t)((TRB * mvC[i].dy) / TRD + mvdy);
+ if (mvdx == 0)
+ mvBack[i].dx = (int16_t)(((TRB - TRD) * mvC[i].dx) / TRD);
+ else
+ mvBack[i].dx = (int16_t)(mvForw[i].dx - mvC[i].dx);
+ if (mvdy == 0)
+ mvBack[i].dy = (int16_t)(((TRB - TRD) * mvC[i].dy) / TRD);
+ else
+ mvBack[i].dy = (int16_t)(mvForw[i].dy - mvC[i].dy);
+ }
+ }
+ return MP4_STATUS_OK;
+}
+
+mp4_Status mp4_DecodeMV_DirectField(mp4_Info *pInfo, int32_t mb_ftfr, int32_t mb_fbfr, IppMotionVector *mvTop, IppMotionVector *mvBottom, IppMotionVector *mvForwTop, IppMotionVector *mvForwBottom, IppMotionVector *mvBackTop, IppMotionVector *mvBackBottom, int32_t TRB, int32_t TRD, int32_t modb)
+{
+ // field direct mode
+ int32_t TRDt, TRDb, TRBt, TRBb, deltaTop, deltaBottom, mvdx, mvdy;
+
+ deltaTop = mb_ftfr;
+ deltaBottom = mb_fbfr - 1;
+ if (pInfo->VisualObject.VideoObject.VideoObjectPlane.top_field_first) {
+ deltaTop = -deltaTop;
+ deltaBottom = -deltaBottom;
+ }
+ TRDt = mp4_DivRoundInf(TRD, pInfo->VisualObject.VideoObject.Tframe) * 2 + deltaTop;
+ TRDb = mp4_DivRoundInf(TRD, pInfo->VisualObject.VideoObject.Tframe) * 2 + deltaBottom;
+ TRBt = mp4_DivRoundInf(TRB, pInfo->VisualObject.VideoObject.Tframe) * 2 + deltaTop;
+ TRBb = mp4_DivRoundInf(TRB, pInfo->VisualObject.VideoObject.Tframe) * 2 + deltaBottom;
+ if (modb == 2) {
+ // delta == 0
+ mvdx = mvdy = 0;
+ } else {
+ if (mp4_DecodeMVD(pInfo, &mvdx, &mvdy, 1) != MP4_STATUS_OK)
+ return MP4_STATUS_ERROR;
+ }
+ mvForwTop->dx = (int16_t)((TRBt * mvTop->dx) / TRDt + mvdx);
+ if (mvdx == 0)
+ mvBackTop->dx = (int16_t)(((TRBt - TRDt) * mvTop->dx) / TRDt);
+ else
+ mvBackTop->dx = (int16_t)(mvForwTop->dx - mvTop->dx);
+ mvForwTop->dy = (int16_t)((TRBt * mvTop->dy * 2) / TRDt + mvdy);
+ if (mvdy == 0)
+ mvBackTop->dy = (int16_t)(((TRBt - TRDt) * mvTop->dy * 2) / TRDt);
+ else
+ mvBackTop->dy = (int16_t)(mvForwTop->dy - mvTop->dy * 2);
+ mvForwBottom->dx = (int16_t)((TRBb * mvBottom->dx) / TRDb + mvdx);
+ if (mvdx == 0)
+ mvBackBottom->dx = (int16_t)(((TRBb - TRDb) * mvBottom->dx) / TRDb);
+ else
+ mvBackBottom->dx = (int16_t)(mvForwBottom->dx - mvBottom->dx);
+ mvForwBottom->dy = (int16_t)((TRBb * mvBottom->dy * 2) / TRDb + mvdy);
+ if (mvdy == 0)
+ mvBackBottom->dy = (int16_t)(((TRBb - TRDb) * mvBottom->dy * 2) / TRDb);
+ else
+ mvBackBottom->dy = (int16_t)(mvForwBottom->dy - mvBottom->dy * 2);
+ mvForwTop->dy >>= 1;
+ mvBackTop->dy >>= 1;
+ mvForwBottom->dy >>= 1;
+ mvBackBottom->dy >>= 1;
+ return MP4_STATUS_OK;
+}
+
+/*static*/ void mp4_ExpandFrameReplicate(uint8_t *pSrcDstPlane, int32_t frameWidth, int32_t frameHeight, int32_t expandPels, int32_t step)
+{
+ uint8_t *pDst1, *pDst2, *pSrc1, *pSrc2;
+ int32_t i, j;
+ uint32_t t1, t2;
+
+ pDst1 = pSrcDstPlane + step * expandPels;
+ pDst2 = pDst1 + frameWidth + expandPels;
+ if (expandPels == 8) {
+ for (i = 0; i < frameHeight; i ++) {
+ t1 = pDst1[8] + (pDst1[8] << 8);
+ t2 = pDst2[-1] + (pDst2[-1] << 8);
+ t1 = (t1 << 16) + t1;
+ t2 = (t2 << 16) + t2;
+ ((uint32_t*)pDst1)[0] = t1;
+ ((uint32_t*)pDst1)[1] = t1;
+ ((uint32_t*)pDst2)[0] = t2;
+ ((uint32_t*)pDst2)[1] = t2;
+ pDst1 += step;
+ pDst2 += step;
+ }
+ } else if (expandPels == 16) {
+ for (i = 0; i < frameHeight; i ++) {
+ t1 = pDst1[16] + (pDst1[16] << 8);
+ t2 = pDst2[-1] + (pDst2[-1] << 8);
+ t1 = (t1 << 16) + t1;
+ t2 = (t2 << 16) + t2;
+ ((uint32_t*)pDst1)[0] = t1;
+ ((uint32_t*)pDst1)[1] = t1;
+ ((uint32_t*)pDst1)[2] = t1;
+ ((uint32_t*)pDst1)[3] = t1;
+ ((uint32_t*)pDst2)[0] = t2;
+ ((uint32_t*)pDst2)[1] = t2;
+ ((uint32_t*)pDst2)[2] = t2;
+ ((uint32_t*)pDst2)[3] = t2;
+ pDst1 += step;
+ pDst2 += step;
+ }
+ } else {
+ for (i = 0; i < frameHeight; i ++) {
+ ippsSet_8u(pDst1[expandPels], pDst1, expandPels);
+ ippsSet_8u(pDst2[-1], pDst2, expandPels);
+ pDst1 += step;
+ pDst2 += step;
+ }
+ }
+ pDst1 = pSrcDstPlane;
+ pSrc1 = pSrcDstPlane + expandPels * step;
+ pDst2 = pSrc1 + frameHeight * step;
+ pSrc2 = pDst2 - step;
+ j = frameWidth + 2 * expandPels;
+ for (i = 0; i < expandPels; i ++) {
+ ippsCopy_8u(pSrc1, pDst1, j);
+ ippsCopy_8u(pSrc2, pDst2, j);
+ pDst1 += step;
+ pDst2 += step;
+ }
+}
+
+void mp4_PadFrame(mp4_Info* pInfo)
+{
+#if 0
+ /*
+ // padding VOP (for not complete blocks padd by
+ // 0 for DivX(tm) 5.0 AVI streams
+ // 128 for QuickTime(tm) MP4 streams
+ // replication for other
+ */
+ int32_t wL, hL, wC, hC, i;
+
+ //if (pInfo->VisualObject.VideoObject.short_video_header)
+ // return;
+ wL = pInfo->VisualObject.VideoObject.width;
+ hL = pInfo->VisualObject.VideoObject.height;
+ wC = pInfo->VisualObject.VideoObject.width >> 1;
+ hC = pInfo->VisualObject.VideoObject.height >> 1;
+ if ((pInfo->VisualObject.VideoObject.width & 15 || pInfo->VisualObject.VideoObject.height & 15) &&
+ ((pInfo->ftype == 1 && pInfo->ftype_f == 0) || (pInfo->ftype == 2 && pInfo->ftype_f == 1))) {
+ uint8_t pad = (uint8_t)(pInfo->ftype == 1 ? 128 : 0);
+
+ if (pInfo->VisualObject.VideoObject.width & 15) {
+ uint8_t *p;
+ // pad one col
+ p = pInfo->VisualObject.cFrame.pY + pInfo->VisualObject.VideoObject.width;
+ for (i = 0; i < pInfo->VisualObject.VideoObject.height; i ++) {
+ *p = pad;
+ p += pInfo->VisualObject.cFrame.stepY;
+ }
+ p = pInfo->VisualObject.cFrame.pCb + (pInfo->VisualObject.VideoObject.width >> 1);
+ for (i = 0; i < pInfo->VisualObject.VideoObject.height >> 1; i ++) {
+ *p = pad;
+ p += pInfo->VisualObject.cFrame.stepCb;
+ }
+ p = pInfo->VisualObject.cFrame.pCr + (pInfo->VisualObject.VideoObject.width >> 1);
+ for (i = 0; i < pInfo->VisualObject.VideoObject.height >> 1; i ++) {
+ *p = pad;
+ p += pInfo->VisualObject.cFrame.stepCr;
+ }
+ wL ++;
+ wC ++;
+ }
+ if (pInfo->VisualObject.VideoObject.height & 15) {
+ // pad one row
+ ippsSet_8u(pad, pInfo->VisualObject.cFrame.pY + pInfo->VisualObject.cFrame.stepY * pInfo->VisualObject.VideoObject.height, pInfo->VisualObject.VideoObject.width);
+ ippsSet_8u(pad, pInfo->VisualObject.cFrame.pCb + pInfo->VisualObject.cFrame.stepCb * (pInfo->VisualObject.VideoObject.height >> 1), pInfo->VisualObject.VideoObject.width >> 1);
+ ippsSet_8u(pad, pInfo->VisualObject.cFrame.pCr + pInfo->VisualObject.cFrame.stepCr * (pInfo->VisualObject.VideoObject.height >> 1), pInfo->VisualObject.VideoObject.width >> 1);
+ hL ++;
+ hC ++;
+ }
+ }
+#else
+ /*
+ // padding VOP for not complete blocks
+ // replication from macroblock boundary for DIVX and MP4 and from frame boundary for other
+ */
+ int32_t wL, hL, wC, hC;
+
+ if ((pInfo->ftype == 1 && pInfo->ftype_f == 0) || (pInfo->ftype == 2 && pInfo->ftype_f == 1)) {
+ wL = pInfo->VisualObject.VideoObject.MacroBlockPerRow * 16;
+ hL = pInfo->VisualObject.VideoObject.MacroBlockPerCol * 16;
+ } else {
+ wL = pInfo->VisualObject.VideoObject.width;
+ hL = pInfo->VisualObject.VideoObject.height;
+ }
+ wC = wL >> 1;
+ hC = hL >> 1;
+#endif
+ mp4_ExpandFrameReplicate(pInfo->VisualObject.cFrame->apY, wL, hL, 16 * MP4_NUM_EXT_MB, pInfo->VisualObject.cFrame->stepY);
+ mp4_ExpandFrameReplicate(pInfo->VisualObject.cFrame->apCb, wC, hC, 8 * MP4_NUM_EXT_MB, pInfo->VisualObject.cFrame->stepCb);
+ mp4_ExpandFrameReplicate(pInfo->VisualObject.cFrame->apCr, wC, hC, 8 * MP4_NUM_EXT_MB, pInfo->VisualObject.cFrame->stepCr);
+
+}
+
+mp4_Status mp4_DecodeVideoObjectPlane(mp4_Info* pInfo)
+{
+ mp4_Status status = MP4_STATUS_OK;
+ Ipp64s vop_time;
+
+ // set VOP time
+ if (pInfo->VisualObject.VideoObject.short_video_header)
+ {
+ vop_time = pInfo->VisualObject.VideoObject.vop_sync_time + pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.temporal_reference * 1001;
+ if (pInfo->VisualObject.cFrame && pInfo->VisualObject.cFrame->time > vop_time)
+ {
+ pInfo->VisualObject.VideoObject.vop_sync_time += 256 * 1001;
+ vop_time += 256 * 1001;
+ }
+ }
+ else
+ {
+ if (pInfo->VisualObject.VideoObject.VideoObjectPlane.coding_type == MP4_VOP_TYPE_B)
+ {
+ vop_time = pInfo->VisualObject.VideoObject.vop_sync_time_b + pInfo->VisualObject.VideoObject.VideoObjectPlane.modulo_time_base * pInfo->VisualObject.VideoObject.vop_time_increment_resolution + pInfo->VisualObject.VideoObject.VideoObjectPlane.time_increment;
+ }
+ else
+ {
+ if (pInfo->VisualObject.VideoObject.GroupOfVideoObjectPlane.time_code > pInfo->VisualObject.VideoObject.vop_sync_time)
+ pInfo->VisualObject.VideoObject.vop_sync_time = pInfo->VisualObject.VideoObject.GroupOfVideoObjectPlane.time_code;
+ vop_time = pInfo->VisualObject.VideoObject.vop_sync_time + pInfo->VisualObject.VideoObject.VideoObjectPlane.modulo_time_base * pInfo->VisualObject.VideoObject.vop_time_increment_resolution + pInfo->VisualObject.VideoObject.VideoObjectPlane.time_increment;
+ if (pInfo->VisualObject.VideoObject.vop_sync_time_b < pInfo->VisualObject.VideoObject.vop_sync_time)
+ pInfo->VisualObject.VideoObject.vop_sync_time_b = pInfo->VisualObject.VideoObject.vop_sync_time;
+ if (pInfo->VisualObject.VideoObject.VideoObjectPlane.modulo_time_base != 0) {
+ pInfo->VisualObject.VideoObject.vop_sync_time = vop_time - pInfo->VisualObject.VideoObject.VideoObjectPlane.time_increment;
+ }
+ }
+ }
+// if (pInfo->VisualObject.VideoObject.VideoObjectPlane.coded || vop_time != pInfo->VisualObject.rFrame.time) {
+ if (pInfo->VisualObject.VideoObject.VideoObjectPlane.coded ||
+ ( (!pInfo->VisualObject.cFrame || vop_time != pInfo->VisualObject.cFrame->time) &&
+ (!pInfo->VisualObject.rFrame || vop_time != pInfo->VisualObject.rFrame->time) &&
+ (!pInfo->VisualObject.nFrame || vop_time != pInfo->VisualObject.nFrame->time)
+ ))
+ {
+ switch (pInfo->VisualObject.VideoObject.VideoObjectPlane.coding_type)
+ {
+ case MP4_VOP_TYPE_I :
+ // set new video frame
+ if (pInfo->VisualObject.VideoObject.sprite_enable == MP4_SPRITE_STATIC)
+ {
+ // TODO: verify
+ ReleaseFrame(&pInfo->VisualObject, pInfo->VisualObject.sFrame);
+ pInfo->VisualObject.sFrame = pInfo->VisualObject.cFrame;
+ pInfo->VisualObject.cFrame = 0;
+ }
+ else
+ {
+ if (pInfo->noPVOPs)
+ {
+ DisplayFrame(&pInfo->VisualObject, pInfo->VisualObject.cFrame);
+ pInfo->VisualObject.cFrame=0;
+ }
+ else if (pInfo->noBVOPs)
+ {
+ DisplayFrame(&pInfo->VisualObject, pInfo->VisualObject.rFrame);
+ ReleaseFrame(&pInfo->VisualObject, pInfo->VisualObject.rFrame);
+ pInfo->VisualObject.rFrame = pInfo->VisualObject.cFrame;
+ pInfo->VisualObject.cFrame = 0;
+ }
+ else
+ {
+ if (pInfo->VisualObject.VideoObject.VOPindex > 0)
+ {
+ if (pInfo->VisualObject.VideoObject.prevPlaneIsB)
+ {
+ DisplayFrame(&pInfo->VisualObject, pInfo->VisualObject.cFrame);
+ pInfo->VisualObject.cFrame = 0;
+ DisplayFrame(&pInfo->VisualObject, pInfo->VisualObject.nFrame);
+ ReleaseFrame(&pInfo->VisualObject, pInfo->VisualObject.rFrame);
+ pInfo->VisualObject.rFrame = pInfo->VisualObject.nFrame;
+ pInfo->VisualObject.nFrame = 0;
+ pInfo->VisualObject.VideoObject.prevPlaneIsB=0;
+ }
+ else
+ {
+ DisplayFrame(&pInfo->VisualObject, pInfo->VisualObject.cFrame);
+ ReleaseFrame(&pInfo->VisualObject, pInfo->VisualObject.rFrame);
+ pInfo->VisualObject.rFrame = pInfo->VisualObject.cFrame;
+ pInfo->VisualObject.cFrame = 0;
+ }
+
+ }
+ }
+ }
+ if (pInfo->VisualObject.VideoObject.VideoObjectPlane.coded)
+ {
+ if (pInfo->VisualObject.VideoObject.shape == MP4_SHAPE_TYPE_RECTANGULAR)
+ {
+ status = mp4_DecodeVOP_I(pInfo);
+ } //f else
+ //f status = mp4_DecodeVOP_I_Shape(pInfo);
+ if (pInfo->VisualObject.VideoObject.sprite_enable == MP4_SPRITE_STATIC && pInfo->VisualObject.VideoObject.VOPindex == 0)
+ {
+ // TODO: verify (was: mp4_SWAP(mp4_Frame, pInfo->VisualObject.sFrame, pInfo->VisualObject.cFrame);
+ ReleaseFrame(&pInfo->VisualObject, pInfo->VisualObject.sFrame);
+ pInfo->VisualObject.sFrame = pInfo->VisualObject.cFrame;
+ pInfo->VisualObject.cFrame = 0;
+ mp4_ExpandFrameReplicate(pInfo->VisualObject.sFrame->apY, pInfo->VisualObject.VideoObject.sprite_width, pInfo->VisualObject.VideoObject.sprite_height, 16, pInfo->VisualObject.sFrame->stepY);
+ mp4_ExpandFrameReplicate(pInfo->VisualObject.sFrame->apCb, pInfo->VisualObject.VideoObject.sprite_width >> 1, pInfo->VisualObject.VideoObject.sprite_height >> 1, 8, pInfo->VisualObject.sFrame->stepCb);
+ mp4_ExpandFrameReplicate(pInfo->VisualObject.sFrame->apCr, pInfo->VisualObject.VideoObject.sprite_width >> 1, pInfo->VisualObject.VideoObject.sprite_height >> 1, 8, pInfo->VisualObject.sFrame->stepCr);
+ } else {
+ mp4_PadFrame(pInfo);
+ }
+ // set past and future time for B-VOP
+ pInfo->VisualObject.VideoObject.rTime = pInfo->VisualObject.VideoObject.nTime;
+ pInfo->VisualObject.VideoObject.nTime = vop_time;
+#ifdef USE_NOTCODED_STATE
+ // Clear not_coded MB state
+ if ((pInfo->VisualObject.VideoObject.sprite_enable != MP4_SPRITE_STATIC) && pInfo->VisualObject.VideoObject.obmc_disable && !pInfo->VisualObject.VideoObject.ncStateCleared) {
+ ippsZero_8u(pInfo->VisualObject.VideoObject.ncState, pInfo->VisualObject.VideoObject.MacroBlockPerVOP);
+ pInfo->VisualObject.VideoObject.ncStateCleared = 1;
+ }
+#endif
+ }
+ mp4_StatisticInc(&pInfo->VisualObject.Statistic.nVOP_I);
+ break;
+ case MP4_VOP_TYPE_P :
+ // set new video frame
+ if (pInfo->noBVOPs)
+ {
+ DisplayFrame(&pInfo->VisualObject, pInfo->VisualObject.rFrame);
+ ReleaseFrame(&pInfo->VisualObject, pInfo->VisualObject.rFrame);
+ pInfo->VisualObject.rFrame = pInfo->VisualObject.cFrame;
+ pInfo->VisualObject.cFrame = 0;
+ }
+ else
+ {
+ if (pInfo->VisualObject.VideoObject.VOPindex > 0)
+ {
+ if (pInfo->VisualObject.VideoObject.prevPlaneIsB)
+ {
+ DisplayFrame(&pInfo->VisualObject, pInfo->VisualObject.cFrame);
+ ReleaseFrame(&pInfo->VisualObject, pInfo->VisualObject.cFrame);
+ pInfo->VisualObject.cFrame=0;
+ DisplayFrame(&pInfo->VisualObject, pInfo->VisualObject.nFrame);
+ ReleaseFrame(&pInfo->VisualObject, pInfo->VisualObject.rFrame);
+ pInfo->VisualObject.rFrame = pInfo->VisualObject.nFrame;
+ pInfo->VisualObject.nFrame = 0;
+ pInfo->VisualObject.VideoObject.prevPlaneIsB = 0;
+ }
+ else
+ {
+ if (pInfo->VisualObject.cFrame)
+ {
+ int w, h;
+ DisplayFrame(&pInfo->VisualObject, pInfo->VisualObject.cFrame);
+ ReleaseFrame(&pInfo->VisualObject, pInfo->VisualObject.rFrame);
+ pInfo->VisualObject.rFrame = pInfo->VisualObject.cFrame;
+ pInfo->VisualObject.cFrame=0;
+
+ pInfo->VisualObject.cFrame = CreateFrame(&pInfo->VisualObject);
+ w = (pInfo->VisualObject.cFrame->mbPerRow + 2 * MP4_NUM_EXT_MB) << 4;
+ h = (pInfo->VisualObject.cFrame->mbPerCol + 2 * MP4_NUM_EXT_MB) << 4;
+ memcpy(pInfo->VisualObject.cFrame->mid, pInfo->VisualObject.rFrame->mid, w * h + (w * h >> 1));
+ }
+ }
+
+ }
+ }
+ if (pInfo->VisualObject.VideoObject.VideoObjectPlane.coded)
+ {
+ status = mp4_DecodeVOP_P(pInfo);
+ mp4_PadFrame(pInfo);
+ // set past and future time for B-VOP
+ pInfo->VisualObject.VideoObject.rTime = pInfo->VisualObject.VideoObject.nTime;
+ pInfo->VisualObject.VideoObject.nTime = vop_time;
+ }
+ mp4_StatisticInc(&pInfo->VisualObject.Statistic.nVOP_P);
+#ifdef USE_NOTCODED_STATE
+ pInfo->VisualObject.VideoObject.ncStateCleared = 0;
+#endif
+ break;
+ case MP4_VOP_TYPE_B :
+ status = MP4_STATUS_OK;
+ // after reset it is need to skip first B-frames
+ //if (pInfo->VisualObject.VideoObject.VOPindex >= 2)
+ //DisplayFrame(&pInfo->VisualObject, pInfo->VisualObject.cFrame);
+
+ if (!pInfo->VisualObject.VideoObject.prevPlaneIsB)
+ {
+ ReleaseFrame(&pInfo->VisualObject, pInfo->VisualObject.nFrame);
+ pInfo->VisualObject.nFrame = pInfo->VisualObject.cFrame;
+ pInfo->VisualObject.cFrame = 0;
+ pInfo->VisualObject.VideoObject.prevPlaneIsB = 1;
+ }
+ else
+ {
+ DisplayFrame(&pInfo->VisualObject, pInfo->VisualObject.cFrame);
+ ReleaseFrame(&pInfo->VisualObject, pInfo->VisualObject.cFrame);
+ pInfo->VisualObject.cFrame=0;
+ }
+ if (pInfo->VisualObject.VideoObject.VOPindex < 2)
+ {
+ // if we don't have both reference frames
+ if (pInfo->ftype == 2)
+ {
+ //repeat last frame for AVI timing reasons
+ DisplayFrame(&pInfo->VisualObject, pInfo->VisualObject.nFrame);
+ if (pInfo->VisualObject.nFrame)
+ pInfo->VisualObject.nFrame->outputted = 0;
+ }
+ mp4_StatisticInc(&pInfo->VisualObject.Statistic.nVOP_B);
+ break;
+ }
+
+ // set Tframe for direct interlaced mode
+ if (!pInfo->VisualObject.VideoObject.Tframe)
+ pInfo->VisualObject.VideoObject.Tframe = (int32_t)(vop_time - pInfo->VisualObject.rFrame->time);
+ if (pInfo->VisualObject.VideoObject.VideoObjectPlane.coded)
+ {
+ pInfo->VisualObject.VideoObject.TRB = (int32_t)(vop_time - pInfo->VisualObject.VideoObject.rTime);
+ pInfo->VisualObject.VideoObject.TRD = (int32_t)(pInfo->VisualObject.VideoObject.nTime - pInfo->VisualObject.VideoObject.rTime);
+ // defense from bad streams when B-VOPs are before Past and/or Future
+ if (pInfo->VisualObject.VideoObject.TRB <= 0)
+ pInfo->VisualObject.VideoObject.TRB = 1;
+ if (pInfo->VisualObject.VideoObject.TRD <= 0)
+ pInfo->VisualObject.VideoObject.TRD = 2;
+ if (pInfo->VisualObject.VideoObject.TRD <= pInfo->VisualObject.VideoObject.TRB)
+ {
+ pInfo->VisualObject.VideoObject.TRB = 1;
+ pInfo->VisualObject.VideoObject.TRD = 2;
+ }
+ if (pInfo->VisualObject.VideoObject.Tframe >= pInfo->VisualObject.VideoObject.TRD)
+ pInfo->VisualObject.VideoObject.Tframe = pInfo->VisualObject.VideoObject.TRB;
+ status = mp4_DecodeVOP_B(pInfo);
+ }
+ mp4_StatisticInc(&pInfo->VisualObject.Statistic.nVOP_B);
+ break;
+ case MP4_VOP_TYPE_S :
+ // set new video frame
+ if (pInfo->VisualObject.VideoObject.sprite_enable == MP4_SPRITE_GMC)
+ {
+ if (pInfo->VisualObject.VideoObject.VOPindex > 0)
+ {
+ if (pInfo->VisualObject.VideoObject.prevPlaneIsB)
+ {
+ DisplayFrame(&pInfo->VisualObject, pInfo->VisualObject.cFrame);
+ ReleaseFrame(&pInfo->VisualObject, pInfo->VisualObject.cFrame);
+ pInfo->VisualObject.cFrame=0;
+ DisplayFrame(&pInfo->VisualObject, pInfo->VisualObject.nFrame);
+ ReleaseFrame(&pInfo->VisualObject, pInfo->VisualObject.rFrame);
+ pInfo->VisualObject.rFrame = pInfo->VisualObject.nFrame;
+ pInfo->VisualObject.nFrame = 0;
+ pInfo->VisualObject.VideoObject.prevPlaneIsB = 0;
+ }
+ else
+ {
+ DisplayFrame(&pInfo->VisualObject, pInfo->VisualObject.cFrame);
+ ReleaseFrame(&pInfo->VisualObject, pInfo->VisualObject.rFrame);
+ pInfo->VisualObject.rFrame = pInfo->VisualObject.cFrame;
+ pInfo->VisualObject.cFrame = 0;
+ }
+ }
+ }
+ else
+ {
+ DisplayFrame(&pInfo->VisualObject, pInfo->VisualObject.cFrame);
+ ReleaseFrame(&pInfo->VisualObject, pInfo->VisualObject.cFrame);
+ pInfo->VisualObject.cFrame=0;
+ }
+
+ if (pInfo->VisualObject.VideoObject.VideoObjectPlane.coded)
+ {
+ status = mp4_DecodeVOP_S(pInfo);
+ if (pInfo->VisualObject.VideoObject.sprite_enable == MP4_SPRITE_GMC)
+ {
+ mp4_PadFrame(pInfo);
+ // set past and future time for B-VOP
+ pInfo->VisualObject.VideoObject.rTime = pInfo->VisualObject.VideoObject.nTime;
+ pInfo->VisualObject.VideoObject.nTime = vop_time;
+ }
+#ifdef USE_NOTCODED_STATE
+ // Clear not_coded MB state
+ if ((pInfo->VisualObject.VideoObject.sprite_enable != MP4_SPRITE_STATIC) && pInfo->VisualObject.VideoObject.obmc_disable && !pInfo->VisualObject.VideoObject.ncStateCleared)
+ {
+ ippsZero_8u(pInfo->VisualObject.VideoObject.ncState, pInfo->VisualObject.VideoObject.MacroBlockPerVOP);
+ pInfo->VisualObject.VideoObject.ncStateCleared = 1;
+ }
+#endif
+ }
+ mp4_StatisticInc(&pInfo->VisualObject.Statistic.nVOP_S);
+ break;
+ }
+ if (!pInfo->VisualObject.VideoObject.VideoObjectPlane.coded)
+ {
+ //pInfo->VisualObject.rFrame->outputted = 0;
+ //pInfo->VisualObject.cFrame = pInfo->VisualObject.rFrame;
+ //pInfo->VisualObject.rFrame=0;
+ //DisplayFrame(&pInfo->VisualObject, pInfo->VisualObject.rFrame);
+ //ippsCopy_8u(pInfo->VisualObject.rFrame->apY, pInfo->VisualObject.cFrame->apY, pInfo->VisualObject.cFrame->stepY * ((pInfo->VisualObject.VideoObject.MacroBlockPerCol + 2) << 4));
+ //ippsCopy_8u(pInfo->VisualObject.rFrame->apCb, pInfo->VisualObject.cFrame->apCb, pInfo->VisualObject.cFrame->stepCb * ((pInfo->VisualObject.VideoObject.MacroBlockPerCol + 2) << 3));
+ //ippsCopy_8u(pInfo->VisualObject.rFrame->apCr, pInfo->VisualObject.cFrame->apCr, pInfo->VisualObject.cFrame->stepCr * ((pInfo->VisualObject.VideoObject.MacroBlockPerCol + 2) << 3));
+#ifdef USE_NOTCODED_STATE
+ ippsSet_8u(1, pInfo->VisualObject.VideoObject.ncState, pInfo->VisualObject.VideoObject.MacroBlockPerVOP);
+ pInfo->VisualObject.VideoObject.ncStateCleared = 0;
+#endif
+ }
+ mp4_StatisticInc(&pInfo->VisualObject.Statistic.nVOP);
+ }
+ if (pInfo->VisualObject.cFrame)
+ {
+ // save current VOP type
+ pInfo->VisualObject.cFrame->type = pInfo->VisualObject.VideoObject.VideoObjectPlane.coding_type;
+ // save current VOP time
+ pInfo->VisualObject.cFrame->time = vop_time;
+ }
+ return status;
+}
+
+/*
+// Intra DC and AC reconstruction for SVH macroblock
+*/
+mp4_Status mp4_DecodeIntraMB_SVH(mp4_Info *pInfo, int32_t pat, int32_t quant, uint8_t *pR[], int32_t stepR[])
+{
+ __ALIGN16(int16_t, coeff, 64);
+ int32_t blockNum, pm = 32, lnz;
+
+ for (blockNum = 0; blockNum < 6; blockNum ++) {
+ if (ippiReconstructCoeffsIntra_H263_1u16s(&pInfo->bufptr, &pInfo->bitoff, coeff, &lnz, pat & pm, quant, 0, IPPVC_SCAN_ZIGZAG, 0) != ippStsNoErr) {
+ mp4_Error("Error: decoding coefficients of Inter block");
+ return MP4_STATUS_ERROR;
+ }
+ if (lnz > 0) {
+ ippiDCT8x8Inv_16s8u_C1R(coeff, pR[blockNum], stepR[blockNum]);
+ } else {
+ mp4_Set8x8_8u(pR[blockNum], stepR[blockNum], (uint8_t)((coeff[0] + 4) >> 3));
+ }
+ if (pat & pm) {
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTRA_AC);
+ } else {
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTRA_DC);
+ }
+ pm >>= 1;
+ }
+ return MP4_STATUS_OK;
+}
+
+
+mp4_Status mp4_DecodeInterMB_SVH(mp4_Info *pInfo, int16_t *coeffMB, int32_t quant, int32_t pat)
+{
+ int32_t i, lnz, pm = 32;
+ int16_t *coeff = coeffMB;
+
+ for (i = 0; i < 6; i ++) {
+ if ((pat) & pm) {
+ if (ippiReconstructCoeffsInter_H263_1u16s(&pInfo->bufptr, &pInfo->bitoff, coeff, &lnz, quant, 0) != ippStsNoErr) {
+ mp4_Error("Error: decoding coefficients of Inter block");
+ return MP4_STATUS_ERROR;
+ }
+ if (lnz != 0) {
+ if ((lnz <= 4) && (coeff[16] == 0))
+ ippiDCT8x8Inv_2x2_16s_C1I(coeff);
+ else if ((lnz <= 13) && (coeff[32] == 0))
+ ippiDCT8x8Inv_4x4_16s_C1I(coeff);
+ else
+ ippiDCT8x8Inv_16s_C1I(coeff);
+ } else {
+ mp4_Set64_16s((int16_t)((coeff[0] + 4) >> 3), coeff);
+ }
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_C);
+ } else {
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ }
+ pm >>= 1;
+ coeff += 64;
+ }
+ return MP4_STATUS_OK;
+}
+
+/*
+// Intra DC and AC reconstruction for macroblock
+*/
+mp4_Status mp4_DecodeIntraMB(mp4_Info *pInfo, int32_t x, int32_t pat, int32_t quant, int32_t dcVLC, int32_t ac_pred_flag, uint8_t *pR[], int32_t stepR[])
+{
+ __ALIGN16(int16_t, coeff, 64);
+ int32_t blockNum, lnz, predDir, scan, dc, dcA, dcB, dcC, dcP, k, nz, predQuantA, predQuantC, dcScaler, pm = 32;
+ int16_t *predAcA, *predAcC, sDC = 0;
+ mp4_IntraPredBlock *bCurr;
+
+ for (blockNum = 0; blockNum < 6; blockNum ++) {
+ // find prediction direction
+ bCurr = &pInfo->VisualObject.VideoObject.IntraPredBuff.block[6*x+blockNum];
+ dcA = bCurr->predA->dct_dc >= 0 ? bCurr->predA->dct_dc : 1024;
+ dcB = bCurr->predB->dct_dc >= 0 ? bCurr->predB->dct_dc : 1024;
+ dcC = bCurr->predC->dct_dc >= 0 ? bCurr->predC->dct_dc : 1024;
+ if (mp4_ABS(dcA - dcB) < mp4_ABS(dcB - dcC)) {
+ predDir = IPPVC_SCAN_HORIZONTAL;
+ dcP = dcC;
+ } else {
+ predDir = IPPVC_SCAN_VERTICAL;
+ dcP = dcA;
+ }
+ scan = IPPVC_SCAN_ZIGZAG;
+ if (pInfo->VisualObject.VideoObject.VideoObjectPlane.alternate_vertical_scan_flag)
+ scan = IPPVC_SCAN_VERTICAL;
+ else if (ac_pred_flag)
+ scan = predDir;
+ // decode coeffs
+ if (dcVLC) {
+ if (ippiDecodeDCIntra_MPEG4_1u16s(&pInfo->bufptr, &pInfo->bitoff, coeff, (blockNum < 4) ? IPPVC_BLOCK_LUMA : IPPVC_BLOCK_CHROMA) != ippStsNoErr) {
+ mp4_Error("Error: decoding DC coefficient of Intra block");
+ return MP4_STATUS_ERROR;
+ }
+ }
+ if (pat & pm) {
+ if (ippiDecodeCoeffsIntra_MPEG4_1u16s(&pInfo->bufptr, &pInfo->bitoff, coeff, &lnz, 0, dcVLC, scan) != ippStsNoErr) {
+ mp4_Error("Error: decoding coefficients of Intra block");
+ return MP4_STATUS_ERROR;
+ }
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTRA_AC);
+ } else {
+ if (dcVLC)
+ sDC = coeff[0];
+ mp4_Zero64_16s(coeff);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTRA_DC);
+ lnz = 0;
+ if (dcVLC)
+ coeff[0] = sDC;
+ }
+ // predict DC
+ dcScaler = (blockNum < 4) ? mp4_DCScalerLuma[quant] : mp4_DCScalerChroma[quant];
+ dc = coeff[0] + mp4_DivIntraDC(dcP, dcScaler);
+ mp4_CLIP(dc, -2048, 2047);
+ coeff[0] = (int16_t)dc;
+ // predict AC
+ nz = 0;
+ if (ac_pred_flag) {
+ if (predDir == IPPVC_SCAN_HORIZONTAL && (bCurr->predC->dct_dc >= 0)) {
+ predAcC = bCurr->predC->dct_acC;
+ predQuantC = (blockNum == 2 || blockNum == 3) ? quant : pInfo->VisualObject.VideoObject.IntraPredBuff.quant[x+1];
+ if (predQuantC == quant)
+ for (k = 1; k < 8; k ++) {
+ coeff[k] = (int16_t)(coeff[k] + predAcC[k]);
+ if (coeff[k]) {
+ mp4_CLIP(coeff[k], -2048, 2047);
+ nz = 1;
+ }
+ }
+ else
+ for (k = 1; k < 8; k ++) {
+ coeff[k] = (int16_t)(coeff[k] + mp4_DivIntraAC(predAcC[k] * predQuantC, quant));
+ if (coeff[k]) {
+ mp4_CLIP(coeff[k], -2048, 2047);
+ nz = 1;
+ }
+ }
+ } else if (predDir == IPPVC_SCAN_VERTICAL && (bCurr->predA->dct_dc >= 0)) {
+ predAcA = bCurr->predA->dct_acA;
+ predQuantA = (blockNum == 1 || blockNum == 3) ? quant : pInfo->VisualObject.VideoObject.IntraPredBuff.quant[x];
+ if (predQuantA == quant)
+ for (k = 1; k < 8; k ++) {
+ coeff[k*8] = (int16_t)(coeff[k*8] + predAcA[k]);
+ if (coeff[k*8]) {
+ mp4_CLIP(coeff[k*8], -2048, 2047);
+ nz = 1;
+ }
+ }
+ else
+ for (k = 1; k < 8; k ++) {
+ coeff[k*8] = (int16_t)(coeff[k*8] + mp4_DivIntraAC(predAcA[k] * predQuantA, quant));
+ if (coeff[k*8]) {
+ mp4_CLIP(coeff[k*8], -2048, 2047);
+ nz = 1;
+ }
+ }
+ }
+ }
+ // copy predicted AC for future Prediction
+ for (k = 1; k < 8; k ++) {
+ bCurr[6].dct_acC[k] = coeff[k];
+ bCurr[6].dct_acA[k] = coeff[k*8];
+ }
+ if ((nz | lnz) || (pInfo->VisualObject.VideoObject.quant_type == 1)) {
+ ippiQuantInvIntra_MPEG4_16s_C1I(coeff, 63, pInfo->VisualObject.VideoObject.QuantInvIntraSpec, quant, (blockNum < 4) ? IPPVC_BLOCK_LUMA : IPPVC_BLOCK_CHROMA);
+ ippiDCT8x8Inv_16s8u_C1R(coeff, pR[blockNum], stepR[blockNum]);
+ } else {
+ k = coeff[0] * dcScaler;
+ mp4_CLIP(k, -2048, 2047);
+ coeff[0] = (int16_t)k;
+ k = (k + 4) >> 3;
+ mp4_CLIP(k, 0, 255);
+ mp4_Set8x8_8u(pR[blockNum], stepR[blockNum], (uint8_t)k);
+ }
+ // copy DC for future Prediction
+ if (blockNum >= 3)
+ pInfo->VisualObject.VideoObject.IntraPredBuff.dcB[blockNum].dct_dc = bCurr[6].dct_dc;
+ bCurr[6].dct_dc = coeff[0];
+ // copy quant
+ if (blockNum == 5)
+ pInfo->VisualObject.VideoObject.IntraPredBuff.quant[x+1] = (uint8_t)quant;
+ pm >>= 1;
+ }
+ return MP4_STATUS_OK;
+}
+
+/*
+// Intra DC and AC reconstruction for DP macroblock
+*/
+mp4_Status mp4_DecodeIntraMB_DP(mp4_Info *pInfo, int16_t dct_dc[], int32_t x, int32_t pat, int32_t quant, int32_t dcVLC, int32_t ac_pred_flag, uint8_t *pR[], int32_t stepR[])
+{
+ __ALIGN16(int16_t, coeff, 64);
+ int32_t blockNum, lnz, predDir, scan, dc, dcA, dcB, dcC, dcP, k, nz, predQuantA, predQuantC, dcScaler, pm = 32;
+ int16_t *predAcA, *predAcC;
+ mp4_IntraPredBlock *bCurr;
+
+ for (blockNum = 0; blockNum < 6; blockNum ++) {
+ // find prediction direction
+ bCurr = &pInfo->VisualObject.VideoObject.IntraPredBuff.block[6*x+blockNum];
+ dcA = bCurr->predA->dct_dc >= 0 ? bCurr->predA->dct_dc : 1024;
+ dcB = bCurr->predB->dct_dc >= 0 ? bCurr->predB->dct_dc : 1024;
+ dcC = bCurr->predC->dct_dc >= 0 ? bCurr->predC->dct_dc : 1024;
+ if (mp4_ABS(dcA - dcB) < mp4_ABS(dcB - dcC)) {
+ predDir = IPPVC_SCAN_HORIZONTAL;
+ dcP = dcC;
+ } else {
+ predDir = IPPVC_SCAN_VERTICAL;
+ dcP = dcA;
+ }
+ scan = (ac_pred_flag) ? predDir : IPPVC_SCAN_ZIGZAG;
+ // decode coeffs
+ if (pat & pm) {
+ if (ippiDecodeCoeffsIntra_MPEG4_1u16s(&pInfo->bufptr, &pInfo->bitoff, coeff, &lnz, pInfo->VisualObject.VideoObject.reversible_vlc, dcVLC, scan) != ippStsNoErr) {
+ mp4_Error("Error: decoding coefficients of Intra block");
+ return MP4_STATUS_ERROR;
+ }
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTRA_AC);
+ } else {
+ mp4_Zero64_16s(coeff);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTRA_DC);
+ lnz = 0;
+ }
+ if (dcVLC)
+ coeff[0] = dct_dc[blockNum];
+ // predict DC
+ dcScaler = (blockNum < 4) ? mp4_DCScalerLuma[quant] : mp4_DCScalerChroma[quant];
+ dc = coeff[0] + mp4_DivIntraDC(dcP, dcScaler);
+ mp4_CLIP(dc, -2048, 2047);
+ coeff[0] = (int16_t)dc;
+ // predict AC
+ nz = 0;
+ if (ac_pred_flag) {
+ if (predDir == IPPVC_SCAN_HORIZONTAL && (bCurr->predC->dct_dc >= 0)) {
+ predAcC = bCurr->predC->dct_acC;
+ predQuantC = (blockNum == 2 || blockNum == 3) ? quant : pInfo->VisualObject.VideoObject.IntraPredBuff.quant[x+1];
+ if (predQuantC == quant)
+ for (k = 1; k < 8; k ++) {
+ coeff[k] = (int16_t)(coeff[k] + predAcC[k]); // clip ??
+ if (coeff[k]) {
+ mp4_CLIP(coeff[k], -2048, 2047);
+ nz = 1;
+ }
+ }
+ else
+ for (k = 1; k < 8; k ++) {
+ coeff[k] = (int16_t)(coeff[k] + mp4_DivIntraAC(predAcC[k] * predQuantC, quant));
+ if (coeff[k]) {
+ mp4_CLIP(coeff[k], -2048, 2047);
+ nz = 1;
+ }
+ }
+ } else if (predDir == IPPVC_SCAN_VERTICAL && (bCurr->predA->dct_dc >= 0)) {
+ predAcA = bCurr->predA->dct_acA;
+ predQuantA = (blockNum == 1 || blockNum == 3) ? quant : pInfo->VisualObject.VideoObject.IntraPredBuff.quant[x];
+ if (predQuantA == quant)
+ for (k = 1; k < 8; k ++) {
+ coeff[k*8] = (int16_t)(coeff[k*8] + predAcA[k]);
+ if (coeff[k*8]) {
+ mp4_CLIP(coeff[k*8], -2048, 2047);
+ nz = 1;
+ }
+ }
+ else
+ for (k = 1; k < 8; k ++) {
+ coeff[k*8] = (int16_t)(coeff[k*8] + mp4_DivIntraAC(predAcA[k] * predQuantA, quant));
+ if (coeff[k*8]) {
+ mp4_CLIP(coeff[k*8], -2048, 2047);
+ nz = 1;
+ }
+ }
+ }
+ }
+ // copy predicted AC for future Prediction
+ for (k = 1; k < 8; k ++) {
+ bCurr[6].dct_acC[k] = coeff[k];
+ bCurr[6].dct_acA[k] = coeff[k*8];
+ }
+ if ((nz | lnz) || (pInfo->VisualObject.VideoObject.quant_type == 1)) {
+ ippiQuantInvIntra_MPEG4_16s_C1I(coeff, 63, pInfo->VisualObject.VideoObject.QuantInvIntraSpec, quant, (blockNum < 4) ? IPPVC_BLOCK_LUMA : IPPVC_BLOCK_CHROMA);
+ ippiDCT8x8Inv_16s8u_C1R(coeff, pR[blockNum], stepR[blockNum]);
+ } else {
+ k = coeff[0] * dcScaler;
+ mp4_CLIP(k, -2048, 2047);
+ coeff[0] = (int16_t)k;
+ k = (k + 4) >> 3;
+ mp4_CLIP(k, 0, 255);
+ mp4_Set8x8_8u(pR[blockNum], stepR[blockNum], (uint8_t)k);
+ }
+ // copy DC for future Prediction
+ if (blockNum >= 3)
+ pInfo->VisualObject.VideoObject.IntraPredBuff.dcB[blockNum].dct_dc = bCurr[6].dct_dc;
+ bCurr[6].dct_dc = coeff[0];
+ // copy quant
+ if (blockNum == 5)
+ pInfo->VisualObject.VideoObject.IntraPredBuff.quant[x+1] = (uint8_t)quant;
+ pm >>= 1;
+ }
+ return MP4_STATUS_OK;
+}
+
+/*
+// Intra DC and AC reconstruction for macroblock (w/o iDCT)
+*/
+mp4_Status mp4_ReconstructCoeffsIntraMB(mp4_Info *pInfo, int32_t x, int32_t pat, int32_t quant, int32_t dcVLC, int32_t ac_pred_flag, int16_t *coeffMB, int32_t lastNZ[])
+{
+ int32_t blockNum, lnz, predDir, scan, dc, dcA, dcB, dcC, dcP, k, nz, predQuantA, predQuantC, dcScaler, pm = 32;
+ int16_t *predAcA, *predAcC, sDC = 0, *coeff = coeffMB;
+ mp4_IntraPredBlock *bCurr;
+
+ for (blockNum = 0; blockNum < 6; blockNum ++) {
+ // find prediction direction
+ bCurr = &pInfo->VisualObject.VideoObject.IntraPredBuff.block[6*x+blockNum];
+ dcA = bCurr->predA->dct_dc >= 0 ? bCurr->predA->dct_dc : 1024;
+ dcB = bCurr->predB->dct_dc >= 0 ? bCurr->predB->dct_dc : 1024;
+ dcC = bCurr->predC->dct_dc >= 0 ? bCurr->predC->dct_dc : 1024;
+ if (mp4_ABS(dcA - dcB) < mp4_ABS(dcB - dcC)) {
+ predDir = IPPVC_SCAN_HORIZONTAL;
+ dcP = dcC;
+ } else {
+ predDir = IPPVC_SCAN_VERTICAL;
+ dcP = dcA;
+ }
+ scan = IPPVC_SCAN_ZIGZAG;
+ if (pInfo->VisualObject.VideoObject.VideoObjectPlane.alternate_vertical_scan_flag)
+ scan = IPPVC_SCAN_VERTICAL;
+ else if (ac_pred_flag)
+ scan = predDir;
+ // decode coeffs
+ if (dcVLC) {
+ if (ippiDecodeDCIntra_MPEG4_1u16s(&pInfo->bufptr, &pInfo->bitoff, coeff, (blockNum < 4) ? IPPVC_BLOCK_LUMA : IPPVC_BLOCK_CHROMA) != ippStsNoErr) {
+ mp4_Error("Error: decoding DC coefficient of Intra block");
+ return MP4_STATUS_ERROR;
+ }
+ }
+ if (pat & pm) {
+ if (ippiDecodeCoeffsIntra_MPEG4_1u16s(&pInfo->bufptr, &pInfo->bitoff, coeff, &lnz, 0, dcVLC, scan) != ippStsNoErr) {
+ mp4_Error("Error: decoding coefficients of Intra block");
+ return MP4_STATUS_ERROR;
+ }
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTRA_AC);
+ } else {
+ if (dcVLC)
+ sDC = coeff[0];
+ mp4_Zero64_16s(coeff);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTRA_DC);
+ lnz = 0;
+ if (dcVLC)
+ coeff[0] = sDC;
+ }
+ // predict DC
+ dcScaler = (blockNum < 4) ? mp4_DCScalerLuma[quant] : mp4_DCScalerChroma[quant];
+ dc = coeff[0] + mp4_DivIntraDC(dcP, dcScaler);
+ mp4_CLIP(dc, -2048, 2047);
+ coeff[0] = (int16_t)dc;
+ // predict AC
+ nz = 0;
+ if (ac_pred_flag) {
+ if (predDir == IPPVC_SCAN_HORIZONTAL && (bCurr->predC->dct_dc >= 0)) {
+ predAcC = bCurr->predC->dct_acC;
+ predQuantC = (blockNum == 2 || blockNum == 3) ? quant : pInfo->VisualObject.VideoObject.IntraPredBuff.quant[x+1];
+ if (predQuantC == quant)
+ for (k = 1; k < 8; k ++) {
+ coeff[k] = (int16_t)(coeff[k] + predAcC[k]);
+ if (coeff[k]) {
+ mp4_CLIP(coeff[k], -2048, 2047);
+ nz = 1;
+ }
+ }
+ else
+ for (k = 1; k < 8; k ++) {
+ coeff[k] = (int16_t)(coeff[k] + mp4_DivIntraAC(predAcC[k] * predQuantC, quant));
+ if (coeff[k]) {
+ mp4_CLIP(coeff[k], -2048, 2047);
+ nz = 1;
+ }
+ }
+ } else if (predDir == IPPVC_SCAN_VERTICAL && (bCurr->predA->dct_dc >= 0)) {
+ predAcA = bCurr->predA->dct_acA;
+ predQuantA = (blockNum == 1 || blockNum == 3) ? quant : pInfo->VisualObject.VideoObject.IntraPredBuff.quant[x];
+ if (predQuantA == quant)
+ for (k = 1; k < 8; k ++) {
+ coeff[k*8] = (int16_t)(coeff[k*8] + predAcA[k]);
+ if (coeff[k*8]) {
+ mp4_CLIP(coeff[k*8], -2048, 2047);
+ nz = 1;
+ }
+ }
+ else
+ for (k = 1; k < 8; k ++) {
+ coeff[k*8] = (int16_t)(coeff[k*8] + mp4_DivIntraAC(predAcA[k] * predQuantA, quant));
+ if (coeff[k*8]) {
+ mp4_CLIP(coeff[k*8], -2048, 2047);
+ nz = 1;
+ }
+ }
+ }
+ }
+ // copy predicted AC for future Prediction
+ for (k = 1; k < 8; k ++) {
+ bCurr[6].dct_acC[k] = coeff[k];
+ bCurr[6].dct_acA[k] = coeff[k*8];
+ }
+ if ((nz | lnz) || (pInfo->VisualObject.VideoObject.quant_type == 1)) {
+ ippiQuantInvIntra_MPEG4_16s_C1I(coeff, 63, pInfo->VisualObject.VideoObject.QuantInvIntraSpec, quant, (blockNum < 4) ? IPPVC_BLOCK_LUMA : IPPVC_BLOCK_CHROMA);
+ lnz = 63;
+ } else {
+ k = coeff[0] * dcScaler;
+ mp4_CLIP(k, -2048, 2047);
+ coeff[0] = (int16_t)k;
+ }
+ // copy DC for future Prediction
+ if (blockNum >= 3)
+ pInfo->VisualObject.VideoObject.IntraPredBuff.dcB[blockNum].dct_dc = bCurr[6].dct_dc;
+ bCurr[6].dct_dc = coeff[0];
+ // copy quant
+ if (blockNum == 5)
+ pInfo->VisualObject.VideoObject.IntraPredBuff.quant[x+1] = (uint8_t)quant;
+ lastNZ[blockNum] = lnz;
+ pm >>= 1;
+ coeff += 64;
+ }
+ return MP4_STATUS_OK;
+}
+
+mp4_Status mp4_DecodeInterMB(mp4_Info *pInfo, int16_t *coeffMB, int32_t quant, int32_t pat, int32_t scan)
+{
+ int32_t i, lnz, pm = 32;
+ int16_t *coeff = coeffMB;
+
+ for (i = 0; i < 6; i ++) {
+ if ((pat) & pm) {
+ if (ippiReconstructCoeffsInter_MPEG4_1u16s(&pInfo->bufptr, &pInfo->bitoff, coeff, &lnz, pInfo->VisualObject.VideoObject.reversible_vlc, scan, pInfo->VisualObject.VideoObject.QuantInvInterSpec, quant) != ippStsNoErr) {
+ mp4_Error("Error: decoding coefficients of Inter block");
+ return MP4_STATUS_ERROR;
+ }
+ if (pInfo->VisualObject.VideoObject.quant_type == 0 || (coeff[63] == 0)) {
+ if (lnz != 0) {
+ if (scan == IPPVC_SCAN_ZIGZAG) {
+ if ((lnz <= 4) && (coeff[16] == 0))
+ ippiDCT8x8Inv_2x2_16s_C1I(coeff);
+ else if ((lnz <= 13) && (coeff[32] == 0))
+ ippiDCT8x8Inv_4x4_16s_C1I(coeff);
+ else
+ ippiDCT8x8Inv_16s_C1I(coeff);
+ } else { // IPPVC_SCAN_VERTICAL
+ if ((lnz <= 5) && (coeff[16] == 0) && (coeff[24] == 0))
+ ippiDCT8x8Inv_2x2_16s_C1I(coeff);
+ else if (lnz <= 9)
+ ippiDCT8x8Inv_4x4_16s_C1I(coeff);
+ else
+ ippiDCT8x8Inv_16s_C1I(coeff);
+ }
+ } else {
+ mp4_Set64_16s((int16_t)((coeff[0] + 4) >> 3), coeff);
+ }
+ } else {
+ ippiDCT8x8Inv_16s_C1I(coeff);
+ }
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_C);
+ } else {
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ }
+ pm >>= 1;
+ coeff += 64;
+ }
+ return MP4_STATUS_OK;
+}
+
+void mp4_DCTInvCoeffsInterMB(mp4_Info *pInfo, int16_t *coeffMB, int32_t lastNZ[], int32_t pat, int32_t scan)
+{
+ int32_t i, lnz, pm = 32;
+ int16_t *coeff = coeffMB;
+
+ for (i = 0; i < 6; i ++) {
+ if ((pat) & pm) {
+ if (pInfo->VisualObject.VideoObject.quant_type == 0 || (coeff[63] == 0)) {
+ lnz = lastNZ[i];
+ if (lnz != 0) {
+ if (scan == IPPVC_SCAN_ZIGZAG) {
+ if ((lnz <= 4) && (coeff[16] == 0))
+ ippiDCT8x8Inv_2x2_16s_C1I(coeff);
+ else if ((lnz <= 13) && (coeff[32] == 0))
+ ippiDCT8x8Inv_4x4_16s_C1I(coeff);
+ else
+ ippiDCT8x8Inv_16s_C1I(coeff);
+ } else { // IPPVC_SCAN_VERTICAL
+ if ((lnz <= 5) && (coeff[16] == 0) && (coeff[24] == 0))
+ ippiDCT8x8Inv_2x2_16s_C1I(coeff);
+ else if (lnz <= 9)
+ ippiDCT8x8Inv_4x4_16s_C1I(coeff);
+ else
+ ippiDCT8x8Inv_16s_C1I(coeff);
+ }
+ } else {
+ mp4_Set64_16s((int16_t)((coeff[0] + 4) >> 3), coeff);
+ }
+ } else {
+ ippiDCT8x8Inv_16s_C1I(coeff);
+ }
+ }
+ pm >>= 1;
+ coeff += 64;
+ }
+}
+
+/*
+// decode mcbpc and set MBtype and ChromaPattern
+*/
+mp4_Status mp4_DecodeMCBPC_P(mp4_Info* pInfo, int32_t *mbType, int32_t *mbPattern, int32_t stat)
+{
+ uint32_t code;
+ int32_t type, pattern;
+
+ code = mp4_ShowBits9(pInfo, 9);
+ if (code >= 256) {
+ type = IPPVC_MBTYPE_INTER;
+ pattern = 0;
+ mp4_FlushBits(pInfo, 1);
+ } else {
+ type = mp4_PVOPmb_type[code];
+ pattern = mp4_PVOPmb_cbpc[code];
+ mp4_FlushBits(pInfo, mp4_PVOPmb_bits[code]);
+ }
+ if (code == 0) {
+ mp4_Error("Error: decoding MCBPC");
+ return MP4_STATUS_ERROR;
+ }
+ *mbType = type;
+ *mbPattern = pattern;
+ if (stat) {
+ if (type == IPPVC_MBTYPE_INTER)
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_INTER);
+ else if (type == IPPVC_MBTYPE_INTER_Q)
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_INTER_Q);
+ else if (type == IPPVC_MBTYPE_INTRA)
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_INTRA);
+ else if (type == IPPVC_MBTYPE_INTRA_Q)
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_INTRA_Q);
+ else if (type == IPPVC_MBTYPE_INTER4V)
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_INTER4V);
+ }
+ return MP4_STATUS_OK;
+}
+
+mp4_Status mp4_PredictDecode1MV(mp4_Info *pInfo, mp4_MacroBlock *MBcurr, int32_t y, int32_t x)
+{
+ IppMotionVector *mvLeft, *mvTop, *mvRight, *mvCurr;
+ int32_t mbInRow = pInfo->VisualObject.VideoObject.MacroBlockPerRow;
+ int32_t fcode = pInfo->VisualObject.VideoObject.VideoObjectPlane.fcode_forward;
+ int32_t resync_marker_disable = pInfo->VisualObject.VideoObject.resync_marker_disable;
+
+ // block 0
+ mvCurr = MBcurr[0].mv;
+ mvLeft = MBcurr[-1].mv;
+ mvTop = MBcurr[-mbInRow].mv;
+ mvRight = MBcurr[-mbInRow+1].mv;
+ if (resync_marker_disable) {
+ if ((y | x) == 0) {
+ mvCurr[0].dx = mvCurr[0].dy = 0;
+ } else if (x == 0) {
+ mvCurr[0].dx = mp4_Median(0, mvTop[2].dx, mvRight[2].dx);
+ mvCurr[0].dy = mp4_Median(0, mvTop[2].dy, mvRight[2].dy);
+ } else if (y == 0) {
+ mvCurr[0] = mvLeft[1];
+ } else if (x == mbInRow - 1) {
+ mvCurr[0].dx = mp4_Median(0, mvLeft[1].dx, mvTop[2].dx);
+ mvCurr[0].dy = mp4_Median(0, mvLeft[1].dy, mvTop[2].dy);
+ } else {
+ mvCurr[0].dx = mp4_Median(mvLeft[1].dx, mvTop[2].dx, mvRight[2].dx);
+ mvCurr[0].dy = mp4_Median(mvLeft[1].dy, mvTop[2].dy, mvRight[2].dy);
+ }
+ } else {
+ int32_t validLeft, validTop, validRight;
+
+ if (x > 0)
+ validLeft = MBcurr[-1].validPred;
+ else
+ validLeft = 0;
+ if (y > 0)
+ validTop = MBcurr[-mbInRow].validPred;
+ else
+ validTop = 0;
+ if ((y > 0) && (x < mbInRow - 1))
+ validRight = MBcurr[-mbInRow+1].validPred;
+ else
+ validRight = 0;
+ switch ((validLeft << 2) | (validTop << 1) | validRight) {
+ case 7:
+ mvCurr[0].dx = mp4_Median(mvLeft[1].dx, mvTop[2].dx, mvRight[2].dx);
+ mvCurr[0].dy = mp4_Median(mvLeft[1].dy, mvTop[2].dy, mvRight[2].dy);
+ break;
+ case 6:
+ mvCurr[0].dx = mp4_Median(mvLeft[1].dx, mvTop[2].dx, 0);
+ mvCurr[0].dy = mp4_Median(mvLeft[1].dy, mvTop[2].dy, 0);
+ break;
+ case 5:
+ mvCurr[0].dx = mp4_Median(mvLeft[1].dx, 0, mvRight[2].dx);
+ mvCurr[0].dy = mp4_Median(mvLeft[1].dy, 0, mvRight[2].dy);
+ break;
+ case 4:
+ mvCurr[0] = mvLeft[1];
+ break;
+ case 3:
+ mvCurr[0].dx = mp4_Median(0, mvTop[2].dx, mvRight[2].dx);
+ mvCurr[0].dy = mp4_Median(0, mvTop[2].dy, mvRight[2].dy);
+ break;
+ case 2:
+ mvCurr[0] = mvTop[2];
+ break;
+ case 1:
+ mvCurr[0] = mvRight[2];
+ break;
+ default:
+ mvCurr[0].dx = mvCurr[0].dy = 0;
+ break;
+ }
+ }
+ return mp4_DecodeMV(pInfo, mvCurr, fcode);
+}
+
+mp4_Status mp4_PredictDecode4MV(mp4_Info *pInfo, mp4_MacroBlock *MBcurr, int32_t y, int32_t x)
+{
+ IppMotionVector *mvLeft, *mvTop, *mvRight, *mvCurr;
+ int32_t mbInRow = pInfo->VisualObject.VideoObject.MacroBlockPerRow;
+ int32_t fcode = pInfo->VisualObject.VideoObject.VideoObjectPlane.fcode_forward;
+ int32_t resync_marker_disable = pInfo->VisualObject.VideoObject.resync_marker_disable;
+
+ mvCurr = MBcurr[0].mv;
+ mvLeft = MBcurr[-1].mv;
+ mvTop = MBcurr[-mbInRow].mv;
+ mvRight = MBcurr[-mbInRow+1].mv;
+ if (resync_marker_disable) {
+ // block 0
+ if ((y | x) == 0) {
+ mvCurr[0].dx = mvCurr[0].dy = 0;
+ } else if (x == 0) {
+ mvCurr[0].dx = mp4_Median(0, mvTop[2].dx, mvRight[2].dx);
+ mvCurr[0].dy = mp4_Median(0, mvTop[2].dy, mvRight[2].dy);
+ } else if (y == 0) {
+ mvCurr[0] = mvLeft[1];
+ } else if (x == mbInRow - 1) {
+ mvCurr[0].dx = mp4_Median(0, mvLeft[1].dx, mvTop[2].dx);
+ mvCurr[0].dy = mp4_Median(0, mvLeft[1].dy, mvTop[2].dy);
+ } else {
+ mvCurr[0].dx = mp4_Median(mvLeft[1].dx, mvTop[2].dx, mvRight[2].dx);
+ mvCurr[0].dy = mp4_Median(mvLeft[1].dy, mvTop[2].dy, mvRight[2].dy);
+ }
+ if (mp4_DecodeMV(pInfo, mvCurr, fcode) != MP4_STATUS_OK)
+ return MP4_STATUS_ERROR;
+ // block 1
+ if (y == 0) {
+ mvCurr[1] = mvCurr[0];
+ } else if (x == mbInRow - 1) {
+ mvCurr[1].dx = mp4_Median(mvCurr[0].dx, mvTop[3].dx, 0);
+ mvCurr[1].dy = mp4_Median(mvCurr[0].dy, mvTop[3].dy, 0);
+ } else {
+ mvCurr[1].dx = mp4_Median(mvCurr[0].dx, mvTop[3].dx, mvRight[2].dx);
+ mvCurr[1].dy = mp4_Median(mvCurr[0].dy, mvTop[3].dy, mvRight[2].dy);
+ }
+ if (mp4_DecodeMV(pInfo, mvCurr+1, fcode) != MP4_STATUS_OK)
+ return MP4_STATUS_ERROR;
+ // block 2
+ if (x == 0) {
+ mvCurr[2].dx = mp4_Median(0, mvCurr[0].dx, mvCurr[1].dx);
+ mvCurr[2].dy = mp4_Median(0, mvCurr[0].dy, mvCurr[1].dy);
+ } else {
+ mvCurr[2].dx = mp4_Median(mvLeft[3].dx, mvCurr[0].dx, mvCurr[1].dx);
+ mvCurr[2].dy = mp4_Median(mvLeft[3].dy, mvCurr[0].dy, mvCurr[1].dy);
+ }
+ if (mp4_DecodeMV(pInfo, mvCurr+2, fcode) != MP4_STATUS_OK)
+ return MP4_STATUS_ERROR;
+ // block 3
+ mvCurr[3].dx = mp4_Median(mvCurr[2].dx, mvCurr[0].dx, mvCurr[1].dx);
+ mvCurr[3].dy = mp4_Median(mvCurr[2].dy, mvCurr[0].dy, mvCurr[1].dy);
+ if (mp4_DecodeMV(pInfo, mvCurr+3, fcode) != MP4_STATUS_OK)
+ return MP4_STATUS_ERROR;
+ } else {
+ int32_t validLeft, validTop, validRight;
+
+ if (x > 0)
+ validLeft = MBcurr[-1].validPred;
+ else
+ validLeft = 0;
+ if (y > 0)
+ validTop = MBcurr[-mbInRow].validPred;
+ else
+ validTop = 0;
+ if ((y > 0) && (x < mbInRow - 1))
+ validRight = MBcurr[-mbInRow+1].validPred;
+ else
+ validRight = 0;
+ // block 0
+ switch ((validLeft << 2) | (validTop << 1) | validRight) {
+ case 7:
+ mvCurr[0].dx = mp4_Median(mvLeft[1].dx, mvTop[2].dx, mvRight[2].dx);
+ mvCurr[0].dy = mp4_Median(mvLeft[1].dy, mvTop[2].dy, mvRight[2].dy);
+ break;
+ case 6:
+ mvCurr[0].dx = mp4_Median(mvLeft[1].dx, mvTop[2].dx, 0);
+ mvCurr[0].dy = mp4_Median(mvLeft[1].dy, mvTop[2].dy, 0);
+ break;
+ case 5:
+ mvCurr[0].dx = mp4_Median(mvLeft[1].dx, 0, mvRight[2].dx);
+ mvCurr[0].dy = mp4_Median(mvLeft[1].dy, 0, mvRight[2].dy);
+ break;
+ case 4:
+ mvCurr[0] = mvLeft[1];
+ break;
+ case 3:
+ mvCurr[0].dx = mp4_Median(0, mvTop[2].dx, mvRight[2].dx);
+ mvCurr[0].dy = mp4_Median(0, mvTop[2].dy, mvRight[2].dy);
+ break;
+ case 2:
+ mvCurr[0] = mvTop[2];
+ break;
+ case 1:
+ mvCurr[0] = mvRight[2];
+ break;
+ default:
+ mvCurr[0].dx = mvCurr[0].dy = 0;
+ break;
+ }
+ if (mp4_DecodeMV(pInfo, mvCurr, fcode) != MP4_STATUS_OK)
+ return MP4_STATUS_ERROR;
+ // block 1
+ switch ((validTop << 1) | validRight) {
+ case 3:
+ mvCurr[1].dx = mp4_Median(mvCurr[0].dx, mvTop[3].dx, mvRight[2].dx);
+ mvCurr[1].dy = mp4_Median(mvCurr[0].dy, mvTop[3].dy, mvRight[2].dy);
+ break;
+ case 2:
+ mvCurr[1].dx = mp4_Median(mvCurr[0].dx, mvTop[3].dx, 0);
+ mvCurr[1].dy = mp4_Median(mvCurr[0].dy, mvTop[3].dy, 0);
+ break;
+ case 1:
+ mvCurr[1].dx = mp4_Median(mvCurr[0].dx, 0, mvRight[2].dx);
+ mvCurr[1].dy = mp4_Median(mvCurr[0].dy, 0, mvRight[2].dy);
+ break;
+ default:
+ mvCurr[1] = mvCurr[0];
+ break;
+ }
+ if (mp4_DecodeMV(pInfo, mvCurr+1, fcode) != MP4_STATUS_OK)
+ return MP4_STATUS_ERROR;
+ // block 2
+ if (validLeft) {
+ mvCurr[2].dx = mp4_Median(mvLeft[3].dx, mvCurr[0].dx, mvCurr[1].dx);
+ mvCurr[2].dy = mp4_Median(mvLeft[3].dy, mvCurr[0].dy, mvCurr[1].dy);
+ } else {
+ mvCurr[2].dx = mp4_Median(0, mvCurr[0].dx, mvCurr[1].dx);
+ mvCurr[2].dy = mp4_Median(0, mvCurr[0].dy, mvCurr[1].dy);
+ }
+ if (mp4_DecodeMV(pInfo, mvCurr+2, fcode) != MP4_STATUS_OK)
+ return MP4_STATUS_ERROR;
+ // block 3
+ mvCurr[3].dx = mp4_Median(mvCurr[2].dx, mvCurr[0].dx, mvCurr[1].dx);
+ mvCurr[3].dy = mp4_Median(mvCurr[2].dy, mvCurr[0].dy, mvCurr[1].dy);
+ if (mp4_DecodeMV(pInfo, mvCurr+3, fcode) != MP4_STATUS_OK)
+ return MP4_STATUS_ERROR;
+ }
+ return MP4_STATUS_OK;
+}
+
+mp4_Status mp4_PredictDecodeFMV(mp4_Info *pInfo, mp4_MacroBlock *MBcurr, int32_t y, int32_t x, IppMotionVector *mvT, IppMotionVector *mvB)
+{
+ IppMotionVector mvLeft = {0, 0}, mvTop = {0, 0}, mvRight = {0, 0}, mvPred;
+ int32_t mbInRow = pInfo->VisualObject.VideoObject.MacroBlockPerRow;
+ int32_t fcode = pInfo->VisualObject.VideoObject.VideoObjectPlane.fcode_forward;
+ int32_t resync_marker_disable = pInfo->VisualObject.VideoObject.resync_marker_disable;
+
+ if (x > 0) {
+ mvLeft = MBcurr[-1].mv[1];
+ mvLeft.dy = (int16_t)mp4_Div2(mvLeft.dy);
+ }
+ if (y > 0) {
+ mvTop = MBcurr[-mbInRow].mv[2];
+ mvTop.dy = (int16_t)mp4_Div2(mvTop.dy);
+ if (x < (mbInRow - 1)) {
+ mvRight = MBcurr[-mbInRow+1].mv[2];
+ mvRight.dy = (int16_t)mp4_Div2(mvRight.dy);
+ }
+ }
+ if (resync_marker_disable) {
+ if ((y | x) == 0) {
+ mvPred.dx = mvPred.dy = 0;
+ } else if (x == 0) {
+ mvPred.dx = mp4_Median(0, mvTop.dx, mvRight.dx);
+ mvPred.dy = mp4_Median(0, mvTop.dy, mvRight.dy);
+ } else if (y == 0) {
+ mvPred = mvLeft;
+ } else if (x == mbInRow - 1) {
+ mvPred.dx = mp4_Median(0, mvLeft.dx, mvTop.dx);
+ mvPred.dy = mp4_Median(0, mvLeft.dy, mvTop.dy);
+ } else {
+ mvPred.dx = mp4_Median(mvLeft.dx, mvTop.dx, mvRight.dx);
+ mvPred.dy = mp4_Median(mvLeft.dy, mvTop.dy, mvRight.dy);
+ }
+ } else {
+ int32_t validLeft, validTop, validRight;
+
+ if (x > 0)
+ validLeft = MBcurr[-1].validPred;
+ else
+ validLeft = 0;
+ if (y > 0)
+ validTop = MBcurr[-mbInRow].validPred;
+ else
+ validTop = 0;
+ if ((y > 0) && (x < mbInRow - 1))
+ validRight = MBcurr[-mbInRow+1].validPred;
+ else
+ validRight = 0;
+ switch ((validLeft << 2) | (validTop << 1) | validRight) {
+ case 7:
+ mvPred.dx = mp4_Median(mvLeft.dx, mvTop.dx, mvRight.dx);
+ mvPred.dy = mp4_Median(mvLeft.dy, mvTop.dy, mvRight.dy);
+ break;
+ case 6:
+ mvPred.dx = mp4_Median(mvLeft.dx, mvTop.dx, 0);
+ mvPred.dy = mp4_Median(mvLeft.dy, mvTop.dy, 0);
+ break;
+ case 5:
+ mvPred.dx = mp4_Median(mvLeft.dx, 0, mvRight.dx);
+ mvPred.dy = mp4_Median(mvLeft.dy, 0, mvRight.dy);
+ break;
+ case 4:
+ mvPred = mvLeft;
+ break;
+ case 3:
+ mvPred.dx = mp4_Median(0, mvTop.dx, mvRight.dx);
+ mvPred.dy = mp4_Median(0, mvTop.dy, mvRight.dy);
+ break;
+ case 2:
+ mvPred = mvTop;
+ break;
+ case 1:
+ mvPred = mvRight;
+ break;
+ default:
+ mvPred.dx = mvPred.dy = 0;
+ break;
+ }
+ }
+ *mvT = mvPred;
+ if (mp4_DecodeMV(pInfo, mvT, fcode) != MP4_STATUS_OK)
+ return MP4_STATUS_ERROR;
+ *mvB = mvPred;
+ if (mp4_DecodeMV(pInfo, mvB, fcode) != MP4_STATUS_OK)
+ return MP4_STATUS_ERROR;
+ // update MV buffer for future prediction
+ MBcurr->mv[0].dx = MBcurr->mv[1].dx = MBcurr->mv[2].dx = MBcurr->mv[3].dx = (int16_t)mp4_Div2Round(mvT->dx + mvB->dx);
+ MBcurr->mv[0].dy = MBcurr->mv[1].dy = MBcurr->mv[2].dy = MBcurr->mv[3].dy = (int16_t)(mvT->dy + mvB->dy);
+ return MP4_STATUS_OK;
+}
+
+void mp4_OBMC(mp4_Info *pInfo, mp4_MacroBlock *pMBinfo, IppMotionVector *mvCur, int32_t colNum, int32_t rowNum, IppiRect limitRectL, uint8_t *pYc, int32_t stepYc, uint8_t *pYr, int32_t stepYr, int32_t cbpy, int16_t *coeffMB, int32_t dct_type)
+{
+ IppMotionVector mvOBMCL, mvOBMCU, mvOBMCR, mvOBMCB, *mvLeft, *mvUpper, *mvRight;
+ int32_t mbPerRow = pInfo->VisualObject.VideoObject.MacroBlockPerRow, dx, dy, rt;
+
+ // get Right MV
+ if (colNum == mbPerRow - 1)
+ mvRight = &mvCur[1];
+ else if (pMBinfo[1].type >= IPPVC_MBTYPE_INTRA)
+ mvRight = &mvCur[1];
+ else
+ mvRight = pMBinfo[1].mv;
+ // get Left MV
+ if (colNum == 0)
+ mvLeft = mvCur - 1;
+ else if (pMBinfo[-1].type >= IPPVC_MBTYPE_INTRA)
+ mvLeft = mvCur - 1;
+ else
+ mvLeft = pMBinfo[-1].mv;
+ // get Upper MV
+ if (rowNum == 0)
+ mvUpper = mvCur - 2;
+ else if (pMBinfo[-mbPerRow].type >= IPPVC_MBTYPE_INTRA)
+ mvUpper = mvCur - 2;
+ else
+ mvUpper = pMBinfo[-mbPerRow].mv;
+ dx = colNum * 16;
+ dy = rowNum * 16;
+ rt = pInfo->VisualObject.VideoObject.VideoObjectPlane.rounding_type;
+ if (pInfo->VisualObject.VideoObject.quarter_sample) {
+ mp4_LimitMVQ(&mvLeft[1], &mvOBMCL, &limitRectL, dx, dy, 8);
+ mp4_LimitMVQ(&mvUpper[2], &mvOBMCU, &limitRectL, dx, dy, 8);
+ mp4_LimitMVQ(&mvCur[1], &mvOBMCR, &limitRectL, dx, dy, 8);
+ mp4_LimitMVQ(&mvCur[2], &mvOBMCB, &limitRectL, dx, dy, 8);
+ ippiOBMC8x8QP_MPEG4_8u_C1R(pYr, stepYr, pYc, stepYc, &mvCur[0], &mvOBMCL, &mvOBMCR, &mvOBMCU, &mvOBMCB, rt);
+ mp4_LimitMVQ(&mvCur[0], &mvOBMCL, &limitRectL, dx+8, dy, 8);
+ mp4_LimitMVQ(&mvUpper[3], &mvOBMCU, &limitRectL, dx+8, dy, 8);
+ mp4_LimitMVQ(&mvRight[0], &mvOBMCR, &limitRectL, dx+8, dy, 8);
+ mp4_LimitMVQ(&mvCur[3], &mvOBMCB, &limitRectL, dx+8, dy, 8);
+ ippiOBMC8x8QP_MPEG4_8u_C1R(pYr+8, stepYr, pYc+8, stepYc, &mvCur[1], &mvOBMCL, &mvOBMCR, &mvOBMCU, &mvOBMCB, rt);
+ mp4_LimitMVQ(&mvLeft[3], &mvOBMCL, &limitRectL, dx, dy+8, 8);
+ mp4_LimitMVQ(&mvCur[0], &mvOBMCU, &limitRectL, dx, dy+8, 8);
+ mp4_LimitMVQ(&mvCur[3], &mvOBMCR, &limitRectL, dx, dy+8, 8);
+ ippiOBMC8x8QP_MPEG4_8u_C1R(pYr+stepYr*8, stepYr, pYc+stepYc*8, stepYc, &mvCur[2], &mvOBMCL, &mvOBMCR, &mvOBMCU, &mvCur[2], rt);
+ mp4_LimitMVQ(&mvCur[2], &mvOBMCL, &limitRectL, dx+8, dy+8, 8);
+ mp4_LimitMVQ(&mvCur[1], &mvOBMCU, &limitRectL, dx+8, dy+8, 8);
+ mp4_LimitMVQ(&mvRight[2], &mvOBMCR, &limitRectL, dx+8, dy+8, 8);
+ ippiOBMC8x8QP_MPEG4_8u_C1R(pYr+8+stepYr*8, stepYr, pYc+8+stepYc*8, stepYc, &mvCur[3], &mvOBMCL, &mvOBMCR, &mvOBMCU, &mvCur[3], rt);
+ } else {
+ mp4_LimitMV(&mvLeft[1], &mvOBMCL, &limitRectL, dx, dy, 8);
+ mp4_LimitMV(&mvUpper[2], &mvOBMCU, &limitRectL, dx, dy, 8);
+ mp4_LimitMV(&mvCur[1], &mvOBMCR, &limitRectL, dx, dy, 8);
+ mp4_LimitMV(&mvCur[2], &mvOBMCB, &limitRectL, dx, dy, 8);
+ ippiOBMC8x8HP_MPEG4_8u_C1R(pYr, stepYr, pYc, stepYc, &mvCur[0], &mvOBMCL, &mvOBMCR, &mvOBMCU, &mvOBMCB, rt);
+ mp4_LimitMV(&mvCur[0], &mvOBMCL, &limitRectL, dx+8, dy, 8);
+ mp4_LimitMV(&mvUpper[3], &mvOBMCU, &limitRectL, dx+8, dy, 8);
+ mp4_LimitMV(&mvRight[0], &mvOBMCR, &limitRectL, dx+8, dy, 8);
+ mp4_LimitMV(&mvCur[3], &mvOBMCB, &limitRectL, dx+8, dy, 8);
+ ippiOBMC8x8HP_MPEG4_8u_C1R(pYr+8, stepYr, pYc+8, stepYc, &mvCur[1], &mvOBMCL, &mvOBMCR, &mvOBMCU, &mvOBMCB, rt);
+ mp4_LimitMV(&mvLeft[3], &mvOBMCL, &limitRectL, dx, dy+8, 8);
+ mp4_LimitMV(&mvCur[0], &mvOBMCU, &limitRectL, dx, dy+8, 8);
+ mp4_LimitMV(&mvCur[3], &mvOBMCR, &limitRectL, dx, dy+8, 8);
+ ippiOBMC8x8HP_MPEG4_8u_C1R(pYr+stepYr*8, stepYr, pYc+stepYc*8, stepYc, &mvCur[2], &mvOBMCL, &mvOBMCR, &mvOBMCU, &mvCur[2], rt);
+ mp4_LimitMV(&mvCur[2], &mvOBMCL, &limitRectL, dx+8, dy+8, 8);
+ mp4_LimitMV(&mvCur[1], &mvOBMCU, &limitRectL, dx+8, dy+8, 8);
+ mp4_LimitMV(&mvRight[2], &mvOBMCR, &limitRectL, dx+8, dy+8, 8);
+ ippiOBMC8x8HP_MPEG4_8u_C1R(pYr+8+stepYr*8, stepYr, pYc+8+stepYc*8, stepYc, &mvCur[3], &mvOBMCL, &mvOBMCR, &mvOBMCU, &mvCur[3], rt);
+ }
+ if (!dct_type) {
+ mp4_AddResidual(cbpy & 8, pYc, stepYc, coeffMB);
+ mp4_AddResidual(cbpy & 4, pYc+8, stepYc, coeffMB+64);
+ mp4_AddResidual(cbpy & 2, pYc+stepYc*8, stepYc, coeffMB+128);
+ mp4_AddResidual(cbpy & 1, pYc+stepYc*8+8, stepYc, coeffMB+192);
+ } else {
+ mp4_AddResidual(cbpy & 8, pYc, stepYc*2, coeffMB);
+ mp4_AddResidual(cbpy & 4, pYc+8, stepYc*2, coeffMB+64);
+ mp4_AddResidual(cbpy & 2, pYc+stepYc, stepYc*2, coeffMB+128);
+ mp4_AddResidual(cbpy & 1, pYc+stepYc+8, stepYc*2, coeffMB+192);
+ }
+}
+
+
+void mp4_CopyMacroBlocks(const mp4_Frame *rFrame, mp4_Frame *cFrame, int32_t mbPerRow, int32_t rowNum, int32_t colNum, int32_t n)
+{
+ int32_t i, stepYr, stepYc, stepCbr, stepCbc, stepCrr, stepCrc;
+ uint8_t *pYc, *pCbc, *pCrc, *pYr, *pCbr, *pCrr;
+
+ if (n <= 0)
+ return;
+ stepYc = cFrame->stepY;
+ stepCbc = cFrame->stepCb;
+ stepCrc = cFrame->stepCr;
+ stepYr = rFrame->stepY;
+ stepCbr = rFrame->stepCb;
+ stepCrr = rFrame->stepCr;
+ pYc = cFrame->pY + (rowNum * stepYc + colNum) * 16;
+ pCbc = cFrame->pCb + (rowNum * stepCbc + colNum) * 8;
+ pCrc = cFrame->pCr + (rowNum * stepCrc + colNum) * 8;
+ pYr = rFrame->pY + (rowNum * stepYr + colNum) * 16;
+ pCbr = rFrame->pCb + (rowNum * stepCbr + colNum) * 8;
+ pCrr = rFrame->pCr + (rowNum * stepCrr + colNum) * 8;
+ for (i = rowNum * mbPerRow + colNum; i < rowNum * mbPerRow + colNum + n; i ++) {
+ ippiCopy16x16_8u_C1R(pYr, stepYr, pYc, stepYc);
+ ippiCopy8x8_8u_C1R(pCbr, stepCbr, pCbc, stepCbc);
+ ippiCopy8x8_8u_C1R(pCrr, stepCrr, pCrc, stepCrc);
+ if ((i + 1) % mbPerRow == 0) {
+ pYc += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc;
+ pCbc += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbc << 3) - stepCbc;
+ pCrc += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrc << 3) - stepCrc;
+ pYr += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYr << 4) - stepYr;
+ pCbr += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbr << 3) - stepCbr;
+ pCrr += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrr << 3) - stepCrr;
+ } else {
+ pYc += 16; pCrc += 8; pCbc += 8;
+ pYr += 16; pCrr += 8; pCbr += 8;
+ }
+ }
+}
+
+
+// added by benski
+mp4_Frame *CreateFrame(mp4_VisualObject *object)
+{
+ if (object->frame_cache)
+ {
+ mp4_Frame *ret = object->frame_cache;
+ object->frame_cache = ret->next;
+ ret->next = 0;
+ ret->reference_count = 1;
+ return ret;
+ }
+ else
+ {
+ mp4_Frame *ret = (mp4_Frame *)calloc(1, sizeof(mp4_Frame));
+ ret->reference_count = 1;
+ ret->sprite = 0;
+ ret->mbPerRow = (object->VideoObject.width + 15) >> 4;
+ ret->mbPerCol = (object->VideoObject.height + 15) >> 4;
+ AllocateInitFrame(ret);
+ return ret;
+ }
+}
+
+mp4_Frame *CreateSpriteFrame(mp4_VisualObject *object)
+{
+ if (object->sprite_cache)
+ {
+ mp4_Frame *ret = object->sprite_cache;
+ object->sprite_cache = ret->next;
+ ret->next = 0;
+ ret->reference_count = 1;
+ return ret;
+ }
+ else
+ {
+ mp4_Frame *ret = (mp4_Frame *)calloc(1, sizeof(mp4_Frame));
+ ret->reference_count = 1;
+ ret->sprite = 1;
+ ret->mbPerRow = (object->VideoObject.sprite_width + 15) >> 4;
+ ret->mbPerCol = (object->VideoObject.sprite_height + 15) >> 4;
+ AllocateInitFrame(ret);
+ return ret;
+ }
+}
+
+/* to delete
+free(decoder->dec.VisualObject.cFrame.mid);
+decoder->dec.VisualObject.cFrame.mid = 0;
+*/
+void ReleaseFrame(mp4_VisualObject *object, mp4_Frame *frame)
+{
+ if (frame && --frame->reference_count == 0)
+ {
+ if (frame->outputted == 0)
+ {
+// DebugBreak();
+ }
+ frame->outputted = 0;
+ if (frame->sprite)
+ {
+ frame->next = object->sprite_cache;
+ object->sprite_cache = frame;
+ }
+ else
+ {
+ frame->next = object->frame_cache;
+ object->frame_cache = frame;
+ }
+ }
+}
+
+mp4_Frame *GetDisplayFrame(mp4_VisualObject *object)
+{
+ mp4_Frame *ret = object->display_frames;
+ if (ret)
+ {
+ object->display_frames = ret->next;
+ ret->next = 0;
+ }
+ return ret;
+}
+
+void DisplayFrame(mp4_VisualObject *object, mp4_Frame *frame)
+{
+ if (frame)
+ {
+ mp4_Frame *tail = object->display_frames;
+ if (frame->outputted)
+ {
+ DebugBreak();
+ }
+ frame->outputted = 1;
+ frame->reference_count++;
+ if (tail)
+ {
+ while (tail->next)
+ {
+ tail = tail->next;
+ }
+ tail->next = frame;
+ frame->next = 0;
+ }
+ else
+ {
+ object->display_frames = frame;
+ frame->next = 0;
+ }
+ }
+}
+
+void FreeCache(mp4_VisualObject *object)
+{
+ while (object->display_frames)
+ {
+ mp4_Frame *frame = object->display_frames;
+ object->display_frames = frame->next;
+ free(frame->mid);
+ free(frame);
+ }
+
+ while (object->frame_cache)
+ {
+ mp4_Frame *frame = object->frame_cache;
+ object->frame_cache = frame->next;
+ free(frame->mid);
+ free(frame);
+ }
+
+ while (object->sprite_cache)
+ {
+ mp4_Frame *frame = object->frame_cache;
+ object->frame_cache = frame->next;
+ free(frame->mid);
+ free(frame);
+ }
+}
diff --git a/Src/mpeg4dec/mp4decvopb.c b/Src/mpeg4dec/mp4decvopb.c
new file mode 100644
index 000000000..7b65ae02b
--- /dev/null
+++ b/Src/mpeg4dec/mp4decvopb.c
@@ -0,0 +1,831 @@
+/* ///////////////////////////////////////////////////////////////////////
+//
+// INTEL CORPORATION PROPRIETARY INFORMATION
+// This software is supplied under the terms of a license agreement or
+// nondisclosure agreement with Intel Corporation and may not be copied
+// or disclosed except in accordance with the terms of that agreement.
+// Copyright (c) 2001-2007 Intel Corporation. All Rights Reserved.
+//
+// Description: Decodes B-VOPs
+//
+*/
+
+
+#include "mp4def.h"
+#include "mp4dec.h"
+
+/*
+// Purpose: decode MPEG-4 BVOP
+*/
+mp4_Status mp4_DecodeVOP_B(mp4_Info* pInfo)
+{
+ __ALIGN16(int16_t, coeffMB, 64*6);
+ __ALIGN16(uint8_t, tmpMB, 64*4);
+ uint32_t code;
+ uint8_t *pYc, *pCbc, *pCrc, *pYp, *pCbp, *pCrp, *pYn, *pCbn, *pCrn, *pc, *pr, *pn;
+ int32_t stepYp, stepYc, stepYn, stepCbp, stepCbc, stepCbn, stepCrp, stepCrc, stepCrn, mbPerRow, mbPerCol;
+ int32_t dx, dy, TRB, TRD, quant, mbCurr, mbInVideoPacket, colNum, rowNum;
+ IppiRect limitRectL, limitRectC;
+ int32_t quarter_sample, modb, mb_type, cbpb, dct_type, field_prediction, rvlc = 0, scan;
+ int32_t mb_ftfr, mb_fbfr, mb_btfr, mb_bbfr, fcode_forward, fcode_backward;
+ mp4_MacroBlock *pMBinfo;
+ mp4_Status sts;
+
+ sts = MP4_STATUS_OK;
+
+ if (!pInfo->VisualObject.cFrame)
+ pInfo->VisualObject.cFrame = CreateFrame(&pInfo->VisualObject);
+ stepYc = pInfo->VisualObject.cFrame->stepY;
+ stepYp = pInfo->VisualObject.rFrame->stepY;
+ stepYn = pInfo->VisualObject.nFrame->stepY;
+ stepCbc = pInfo->VisualObject.cFrame->stepCb;
+ stepCbp = pInfo->VisualObject.rFrame->stepCb;
+ stepCbn = pInfo->VisualObject.nFrame->stepCb;
+ stepCrc = pInfo->VisualObject.cFrame->stepCr;
+ stepCrp = pInfo->VisualObject.rFrame->stepCr;
+ stepCrn = pInfo->VisualObject.nFrame->stepCr;
+ pYc = pInfo->VisualObject.cFrame->pY;
+ pCbc = pInfo->VisualObject.cFrame->pCb;
+ pCrc = pInfo->VisualObject.cFrame->pCr;
+ pYp = pInfo->VisualObject.rFrame->pY;
+ pCbp = pInfo->VisualObject.rFrame->pCb;
+ pCrp = pInfo->VisualObject.rFrame->pCr;
+ pYn = pInfo->VisualObject.nFrame->pY;
+ pCbn = pInfo->VisualObject.nFrame->pCb;
+ pCrn = pInfo->VisualObject.nFrame->pCr;
+ quarter_sample = pInfo->VisualObject.VideoObject.quarter_sample;
+ scan = pInfo->VisualObject.VideoObject.VideoObjectPlane.alternate_vertical_scan_flag ? IPPVC_SCAN_VERTICAL : IPPVC_SCAN_ZIGZAG;
+ fcode_forward = pInfo->VisualObject.VideoObject.VideoObjectPlane.fcode_forward;
+ fcode_backward = pInfo->VisualObject.VideoObject.VideoObjectPlane.fcode_backward;
+ // Bounding rectangles for MV limitation
+ limitRectL.x = - 16 * MP4_NUM_EXT_MB;
+ limitRectL.y = - 16 * MP4_NUM_EXT_MB;
+ limitRectL.width = pInfo->VisualObject.VideoObject.width + 16 * 2 * MP4_NUM_EXT_MB;
+ limitRectL.height = pInfo->VisualObject.VideoObject.height + 16 * 2 * MP4_NUM_EXT_MB;
+ limitRectC.x = -8 * MP4_NUM_EXT_MB;
+ limitRectC.y = -8 * MP4_NUM_EXT_MB;
+ limitRectC.width = (pInfo->VisualObject.VideoObject.width >> 1) + 8 * 2 * MP4_NUM_EXT_MB;
+ limitRectC.height = (pInfo->VisualObject.VideoObject.height >> 1) + 8 * 2 * MP4_NUM_EXT_MB;
+ quant = pInfo->VisualObject.VideoObject.VideoObjectPlane.quant;
+ mbPerRow = pInfo->VisualObject.VideoObject.MacroBlockPerRow;
+ mbPerCol = pInfo->VisualObject.VideoObject.MacroBlockPerCol;
+ mbCurr = colNum = rowNum = 0;
+ TRD = pInfo->VisualObject.VideoObject.TRD;
+ TRB = pInfo->VisualObject.VideoObject.TRB;
+ pMBinfo = pInfo->VisualObject.VideoObject.MBinfo;
+// decode interlaced B-VOP
+ if (pInfo->VisualObject.VideoObject.interlaced) {
+ IppMotionVector mvCbCrF, mvCbCrB, mvForwT, mvBackT, mvForwB, mvBackB, mvForw[4], mvBack[4], mvCbCrFFT, mvCbCrFFB, mvCbCrBFT, mvCbCrBFB, *mvField = pInfo->VisualObject.VideoObject.FieldMV;
+
+ // warning "variable may be used without having been initialized"
+ mvCbCrF.dx = mvCbCrF.dy = mvCbCrB.dx = mvCbCrB.dy = mvCbCrFFT.dx = mvCbCrFFT.dy = mvCbCrFFB.dx = mvCbCrFFB.dy = mvCbCrBFT.dx = mvCbCrBFT.dy = mvCbCrBFB.dx = mvCbCrBFB.dy = 0;
+ mb_ftfr = mb_fbfr = mb_btfr = mb_bbfr = 0;
+ for (;;) {
+ mbInVideoPacket = 0;
+ // reset MV predictors at new VideoPacket
+ mvForwT.dx = mvForwT.dy = mvBackT.dx = mvBackT.dy = mvForwB.dx = mvForwB.dy = mvBackB.dx = mvBackB.dy = 0;
+ // decode B-VOP macroblocks
+ for (;;) {
+ if (pMBinfo->not_coded) {
+ ippiCopy16x16_8u_C1R(pYp, stepYp, pYc, stepYc);
+ ippiCopy8x8_8u_C1R(pCbp, stepCbp, pCbc, stepCbc);
+ ippiCopy8x8_8u_C1R(pCrp, stepCrp, pCrc, stepCrc);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_NOTCODED);
+ } else {
+ cbpb = 0;
+ if (mp4_GetBit(pInfo)) {
+ modb = 2;
+ mb_type = IPPVC_MBTYPE_DIRECT;
+ } else {
+ modb = mp4_GetBit(pInfo);
+ // decode mb_type
+ code = mp4_ShowBits9(pInfo, 4);
+ if (code != 0) {
+ mb_type = mp4_BVOPmb_type[code].code;
+ mp4_FlushBits(pInfo, mp4_BVOPmb_type[code].len);
+ } else {
+ mp4_Error("Error when decode mb_type of B-VOP macroblock");
+ goto Err_1;
+ }
+ if (modb == 0)
+ cbpb = mp4_GetBits9(pInfo, 6);
+ if (mb_type != IPPVC_MBTYPE_DIRECT && cbpb != 0)
+ mp4_UpdateQuant_B(pInfo, quant);
+ }
+ dct_type = 0;
+ field_prediction = 0;
+ if (cbpb != 0)
+ dct_type = mp4_GetBit(pInfo);
+ if (mb_type != IPPVC_MBTYPE_DIRECT) {
+ field_prediction = mp4_GetBit(pInfo);
+ if (field_prediction) {
+ if (mb_type != IPPVC_MBTYPE_BACKWARD) {
+ mb_ftfr = mp4_GetBit(pInfo);
+ mb_fbfr = mp4_GetBit(pInfo);
+ }
+ if (mb_type != IPPVC_MBTYPE_FORWARD) {
+ mb_btfr = mp4_GetBit(pInfo);
+ mb_bbfr = mp4_GetBit(pInfo);
+ }
+ }
+ }
+ // coordinates of current MB for limitation
+ dx = colNum * 16;
+ dy = rowNum * 16;
+ if (mb_type == IPPVC_MBTYPE_FORWARD) {
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_FORWARD);
+ if (!field_prediction) {
+ if (mp4_DecodeMV(pInfo, &mvForwT, fcode_forward) != MP4_STATUS_OK)
+ goto Err_1;
+ if (quarter_sample) {
+ mp4_LimitMVQ(&mvForwT, &mvForw[0], &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMVQ(&mvForw[0], &mvCbCrF);
+ mp4_Copy16x16QP_8u(pYp, stepYp, pYc, stepYc, &mvForw[0], 0);
+ } else {
+ mp4_LimitMV(&mvForwT, &mvForw[0], &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMV(&mvForw[0], &mvCbCrF);
+ mp4_Copy16x16HP_8u(pYp, stepYp, pYc, stepYc, &mvForw[0], 0);
+ }
+ //mvForw[1] = mvForw[2] = mvForw[3] = mvForw[0];
+ mvForwB = mvForwT;
+ } else {
+ mvForwT.dy = (int16_t)mp4_Div2(mvForwT.dy);
+ if (mp4_DecodeMV(pInfo, &mvForwT, fcode_forward) != MP4_STATUS_OK)
+ goto Err_1;
+ mvForwB.dy = (int16_t)mp4_Div2(mvForwB.dy);
+ if (mp4_DecodeMV(pInfo, &mvForwB, fcode_forward) != MP4_STATUS_OK)
+ goto Err_1;
+ if (quarter_sample) {
+ mp4_LimitFMVQ(&mvForwT, &mvForw[0], &limitRectL, dx, dy, 16);
+ mp4_Copy16x8QP_8u(pYp+(mb_ftfr ? stepYp : 0), stepYp*2, pYc, stepYc*2, &mvForw[0], 0);
+ mvForw[0].dx = (int16_t)mp4_Div2(mvForw[0].dx);
+ mvForw[0].dy = (int16_t)(mp4_Div2(mvForw[0].dy*2) >> 1);
+ mp4_LimitFMVQ(&mvForwB, &mvForw[2], &limitRectL, dx, dy, 16);
+ mp4_Copy16x8QP_8u(pYp+(mb_fbfr ? stepYp : 0), stepYp*2, pYc+stepYc, stepYc*2, &mvForw[2], 0);
+ mvForw[2].dx = (int16_t)mp4_Div2(mvForw[2].dx);
+ mvForw[2].dy = (int16_t)(mp4_Div2(mvForw[2].dy*2) >> 1);
+ } else {
+ mp4_LimitFMV(&mvForwT, &mvForw[0], &limitRectL, dx, dy, 16);
+ mp4_Copy16x8HP_8u(pYp+(mb_ftfr ? stepYp : 0), stepYp*2, pYc, stepYc*2, &mvForw[0], 0);
+ mp4_LimitFMV(&mvForwB, &mvForw[2], &limitRectL, dx, dy, 16);
+ mp4_Copy16x8HP_8u(pYp+(mb_fbfr ? stepYp : 0), stepYp*2, pYc+stepYc, stepYc*2, &mvForw[2], 0);
+ }
+ mvForwT.dy <<= 1;
+ mvForwB.dy <<= 1;
+ //mvForw[1] = mvForw[0];
+ //mvForw[3] = mvForw[2];
+ mp4_ComputeChromaMV(&mvForw[0], &mvCbCrFFT);
+ mp4_ComputeChromaMV(&mvForw[2], &mvCbCrFFB);
+ }
+ if (mp4_DecodeInterMB(pInfo, coeffMB, quant, cbpb, scan) != MP4_STATUS_OK)
+ goto Err_1;
+ if (!dct_type) {
+ mp4_AddResidual(cbpb & 32, pYc, stepYc, coeffMB);
+ mp4_AddResidual(cbpb & 16, pYc+8, stepYc, coeffMB+64);
+ mp4_AddResidual(cbpb & 8, pYc+stepYc*8, stepYc, coeffMB+128);
+ mp4_AddResidual(cbpb & 4, pYc+stepYc*8+8, stepYc, coeffMB+192);
+ } else {
+ mp4_AddResidual(cbpb & 32, pYc, stepYc*2, coeffMB);
+ mp4_AddResidual(cbpb & 16, pYc+8, stepYc*2, coeffMB+64);
+ mp4_AddResidual(cbpb & 8, pYc+stepYc, stepYc*2, coeffMB+128);
+ mp4_AddResidual(cbpb & 4, pYc+stepYc+8, stepYc*2, coeffMB+192);
+ }
+ if (!field_prediction) {
+ mp4_MC_HP(cbpb & 2, pCbp, stepCbp, pCbc, stepCbc, coeffMB+256, &mvCbCrF, 0);
+ mp4_MC_HP(cbpb & 1, pCrp, stepCrp, pCrc, stepCrc, coeffMB+320, &mvCbCrF, 0);
+ } else {
+ mp4_Copy8x4HP_8u(pCbp+(mb_ftfr ? stepCbp : 0), stepCbp*2, pCbc, stepCbc*2, &mvCbCrFFT, 0);
+ mp4_Copy8x4HP_8u(pCrp+(mb_ftfr ? stepCrp : 0), stepCrp*2, pCrc, stepCrc*2, &mvCbCrFFT, 0);
+ mp4_Copy8x4HP_8u(pCbp+(mb_fbfr ? stepCbp : 0), stepCbp*2, pCbc+stepCbc, stepCbc*2, &mvCbCrFFB, 0);
+ mp4_Copy8x4HP_8u(pCrp+(mb_fbfr ? stepCrp : 0), stepCrp*2, pCrc+stepCrc, stepCrc*2, &mvCbCrFFB, 0);
+ mp4_AddResidual(cbpb & 2, pCbc, stepCbc, coeffMB+256);
+ mp4_AddResidual(cbpb & 1, pCrc, stepCrc, coeffMB+320);
+ }
+ } else if (mb_type == IPPVC_MBTYPE_BACKWARD) {
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_BACKWARD);
+ if (!field_prediction) {
+ if (mp4_DecodeMV(pInfo, &mvBackT, fcode_backward) != MP4_STATUS_OK)
+ goto Err_1;
+ if (quarter_sample) {
+ mp4_LimitMVQ(&mvBackT, &mvBack[0], &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMVQ(&mvBack[0], &mvCbCrB);
+ mp4_Copy16x16QP_8u(pYn, stepYn, pYc, stepYc, &mvBack[0], 0);
+ } else {
+ mp4_LimitMV(&mvBackT, &mvBack[0], &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMV(&mvBack[0], &mvCbCrB);
+ mp4_Copy16x16HP_8u(pYn, stepYn, pYc, stepYc, &mvBack[0], 0);
+ }
+ //mvBack[1] = mvBack[2] = mvBack[3] = mvBack[0];
+ mvBackB = mvBackT;
+ } else {
+ mvBackT.dy = (int16_t)mp4_Div2(mvBackT.dy);
+ if (mp4_DecodeMV(pInfo, &mvBackT, fcode_backward) != MP4_STATUS_OK)
+ goto Err_1;
+ mvBackB.dy = (int16_t)mp4_Div2(mvBackB.dy);
+ if (mp4_DecodeMV(pInfo, &mvBackB, fcode_backward) != MP4_STATUS_OK)
+ goto Err_1;
+ if (quarter_sample) {
+ mp4_LimitFMVQ(&mvBackT, &mvBack[0], &limitRectL, dx, dy, 16);
+ mp4_Copy16x8QP_8u(pYn+(mb_btfr ? stepYn : 0), stepYn*2, pYc, stepYc*2, &mvBack[0], 0);
+ mvBack[0].dx = (int16_t)mp4_Div2(mvBack[0].dx);
+ mvBack[0].dy = (int16_t)(mp4_Div2(mvBack[0].dy*2) >> 1);
+ mp4_LimitFMVQ(&mvBackB, &mvBack[2], &limitRectL, dx, dy, 16);
+ mp4_Copy16x8QP_8u(pYn+(mb_bbfr ? stepYn : 0), stepYn*2, pYc+stepYc, stepYc*2, &mvBack[2], 0);
+ mvBack[2].dx = (int16_t)mp4_Div2(mvBack[2].dx);
+ mvBack[2].dy = (int16_t)(mp4_Div2(mvBack[2].dy*2) >> 1);
+ } else {
+ mp4_LimitFMV(&mvBackT, &mvBack[0], &limitRectL, dx, dy, 16);
+ mp4_Copy16x8HP_8u(pYn+(mb_btfr ? stepYn : 0), stepYn*2, pYc, stepYc*2, &mvBack[0], 0);
+ mp4_LimitFMV(&mvBackB, &mvBack[2], &limitRectL, dx, dy, 16);
+ mp4_Copy16x8HP_8u(pYn+(mb_bbfr ? stepYn : 0), stepYn*2, pYc+stepYc, stepYc*2, &mvBack[2], 0);
+ }
+ mvBackT.dy <<= 1;
+ mvBackB.dy <<= 1;
+ //mvBack[1] = mvBack[0];
+ //mvBack[3] = mvBack[2];
+ mp4_ComputeChromaMV(&mvBack[0], &mvCbCrBFT);
+ mp4_ComputeChromaMV(&mvBack[2], &mvCbCrBFB);
+ }
+ if (mp4_DecodeInterMB(pInfo, coeffMB, quant, cbpb, scan) != MP4_STATUS_OK)
+ goto Err_1;
+ if (!dct_type) {
+ mp4_AddResidual(cbpb & 32, pYc, stepYc, coeffMB);
+ mp4_AddResidual(cbpb & 16, pYc+8, stepYc, coeffMB+64);
+ mp4_AddResidual(cbpb & 8, pYc+stepYc*8, stepYc, coeffMB+128);
+ mp4_AddResidual(cbpb & 4, pYc+stepYc*8+8, stepYc, coeffMB+192);
+ } else {
+ mp4_AddResidual(cbpb & 32, pYc, stepYc*2, coeffMB);
+ mp4_AddResidual(cbpb & 16, pYc+8, stepYc*2, coeffMB+64);
+ mp4_AddResidual(cbpb & 8, pYc+stepYc, stepYc*2, coeffMB+128);
+ mp4_AddResidual(cbpb & 4, pYc+stepYc+8, stepYc*2, coeffMB+192);
+ }
+ if (!field_prediction) {
+ mp4_MC_HP(cbpb & 2, pCbn, stepCbn, pCbc, stepCbc, coeffMB+256, &mvCbCrB, 0);
+ mp4_MC_HP(cbpb & 1, pCrn, stepCrn, pCrc, stepCrc, coeffMB+320, &mvCbCrB, 0);
+ } else {
+ mp4_Copy8x4HP_8u(pCbn+(mb_btfr ? stepCbn : 0), stepCbn*2, pCbc, stepCbc*2, &mvCbCrBFT, 0);
+ mp4_Copy8x4HP_8u(pCrn+(mb_btfr ? stepCrn : 0), stepCrn*2, pCrc, stepCrc*2, &mvCbCrBFT, 0);
+ mp4_Copy8x4HP_8u(pCbn+(mb_bbfr ? stepCbn : 0), stepCbn*2, pCbc+stepCbc, stepCbc*2, &mvCbCrBFB, 0);
+ mp4_Copy8x4HP_8u(pCrn+(mb_bbfr ? stepCrn : 0), stepCrn*2, pCrc+stepCrc, stepCrc*2, &mvCbCrBFB, 0);
+ mp4_AddResidual(cbpb & 2, pCbc, stepCbc, coeffMB+256);
+ mp4_AddResidual(cbpb & 1, pCrc, stepCrc, coeffMB+320);
+ }
+ } else if (mb_type == IPPVC_MBTYPE_INTERPOLATE) {
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_INTERPOLATE);
+ if (!field_prediction) {
+ if (mp4_DecodeMV(pInfo, &mvForwT, fcode_forward) != MP4_STATUS_OK)
+ goto Err_1;
+ if (mp4_DecodeMV(pInfo, &mvBackT, fcode_backward) != MP4_STATUS_OK)
+ goto Err_1;
+ if (quarter_sample) {
+ mp4_LimitMVQ(&mvForwT, &mvForw[0], &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMVQ(&mvForw[0], &mvCbCrF);
+ mp4_Copy16x16QP_8u(pYp, stepYp, pYc, stepYc, &mvForw[0], 0);
+ mp4_LimitMVQ(&mvBackT, &mvBack[0], &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMVQ(&mvBack[0], &mvCbCrB);
+ mp4_Copy16x16QP_8u(pYn, stepYn, tmpMB, 16, &mvBack[0], 0);
+ } else {
+ mp4_LimitMV(&mvForwT, &mvForw[0], &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMV(&mvForw[0], &mvCbCrF);
+ mp4_Copy16x16HP_8u(pYp, stepYp, pYc, stepYc, &mvForw[0], 0);
+ mp4_LimitMV(&mvBackT, &mvBack[0], &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMV(&mvBack[0], &mvCbCrB);
+ mp4_Copy16x16HP_8u(pYn, stepYn, tmpMB, 16, &mvBack[0], 0);
+ }
+ //mvForw[1] = mvForw[2] = mvForw[3] = mvForw[0];
+ mvForwB = mvForwT;
+ //mvBack[1] = mvBack[2] = mvBack[3] = mvBack[0];
+ mvBackB = mvBackT;
+ } else {
+ mvForwT.dy = (int16_t)mp4_Div2(mvForwT.dy);
+ if (mp4_DecodeMV(pInfo, &mvForwT, fcode_forward) != MP4_STATUS_OK)
+ goto Err_1;
+ mvForwB.dy = (int16_t)mp4_Div2(mvForwB.dy);
+ if (mp4_DecodeMV(pInfo, &mvForwB, fcode_forward) != MP4_STATUS_OK)
+ goto Err_1;
+ mvBackT.dy = (int16_t)mp4_Div2(mvBackT.dy);
+ if (mp4_DecodeMV(pInfo, &mvBackT, fcode_backward) != MP4_STATUS_OK)
+ goto Err_1;
+ mvBackB.dy = (int16_t)mp4_Div2(mvBackB.dy);
+ if (mp4_DecodeMV(pInfo, &mvBackB, fcode_backward) != MP4_STATUS_OK)
+ goto Err_1;
+ if (quarter_sample) {
+ mp4_LimitFMVQ(&mvForwT, &mvForw[0], &limitRectL, dx, dy, 16);
+ mp4_Copy16x8QP_8u(pYp+(mb_ftfr ? stepYp : 0), stepYp*2, pYc, stepYc*2, &mvForw[0], 0);
+ mvForw[0].dx = (int16_t)mp4_Div2(mvForw[0].dx);
+ mvForw[0].dy = (int16_t)(mp4_Div2(mvForw[0].dy*2) >> 1);
+ mp4_LimitFMVQ(&mvForwB, &mvForw[2], &limitRectL, dx, dy, 16);
+ mp4_Copy16x8QP_8u(pYp+(mb_fbfr ? stepYp : 0), stepYp*2, pYc+stepYc, stepYc*2, &mvForw[2], 0);
+ mvForw[2].dx = (int16_t)mp4_Div2(mvForw[2].dx);
+ mvForw[2].dy = (int16_t)(mp4_Div2(mvForw[2].dy*2) >> 1);
+ mp4_LimitFMVQ(&mvBackT, &mvBack[0], &limitRectL, dx, dy, 16);
+ mp4_Copy16x8QP_8u(pYn+(mb_btfr ? stepYn : 0), stepYn*2, tmpMB, 32, &mvBack[0], 0);
+ mvBack[0].dx = (int16_t)mp4_Div2(mvBack[0].dx);
+ mvBack[0].dy = (int16_t)(mp4_Div2(mvBack[0].dy*2) >> 1);
+ mp4_LimitFMVQ(&mvBackB, &mvBack[2], &limitRectL, dx, dy, 16);
+ mp4_Copy16x8QP_8u(pYn+(mb_bbfr ? stepYn : 0), stepYn*2, tmpMB+16, 32, &mvBack[2], 0);
+ mvBack[2].dx = (int16_t)mp4_Div2(mvBack[2].dx);
+ mvBack[2].dy = (int16_t)(mp4_Div2(mvBack[2].dy*2) >> 1);
+ } else {
+ mp4_LimitFMV(&mvForwT, &mvForw[0], &limitRectL, dx, dy, 16);
+ mp4_Copy16x8HP_8u(pYp+(mb_ftfr ? stepYp : 0), stepYp*2, pYc, stepYc*2, &mvForw[0], 0);
+ mp4_LimitFMV(&mvForwB, &mvForw[2], &limitRectL, dx, dy, 16);
+ mp4_Copy16x8HP_8u(pYp+(mb_fbfr ? stepYp : 0), stepYp*2, pYc+stepYc, stepYc*2, &mvForw[2], 0);
+ mp4_LimitFMV(&mvBackT, &mvBack[0], &limitRectL, dx, dy, 16);
+ mp4_Copy16x8HP_8u(pYn+(mb_btfr ? stepYn : 0), stepYn*2, tmpMB, 32, &mvBack[0], 0);
+ mp4_LimitFMV(&mvBackB, &mvBack[2], &limitRectL, dx, dy, 16);
+ mp4_Copy16x8HP_8u(pYn+(mb_bbfr ? stepYn : 0), stepYn*2, tmpMB+16, 32, &mvBack[2], 0);
+ }
+ mvForwT.dy <<= 1;
+ mvForwB.dy <<= 1;
+ mvBackT.dy <<= 1;
+ mvBackB.dy <<= 1;
+ //mvForw[1] = mvForw[0];
+ //mvForw[3] = mvForw[2];
+ //mvBack[1] = mvBack[0];
+ //mvBack[3] = mvBack[2];
+ mp4_ComputeChromaMV(&mvForw[0], &mvCbCrFFT);
+ mp4_ComputeChromaMV(&mvForw[2], &mvCbCrFFB);
+ mp4_ComputeChromaMV(&mvBack[0], &mvCbCrBFT);
+ mp4_ComputeChromaMV(&mvBack[2], &mvCbCrBFB);
+ }
+ ippiAverage16x16_8u_C1IR(tmpMB, 16, pYc, stepYc);
+ if (mp4_DecodeInterMB(pInfo, coeffMB, quant, cbpb, scan) != MP4_STATUS_OK)
+ goto Err_1;
+ if (!dct_type) {
+ mp4_AddResidual(cbpb & 32, pYc, stepYc, coeffMB);
+ mp4_AddResidual(cbpb & 16, pYc+8, stepYc, coeffMB+64);
+ mp4_AddResidual(cbpb & 8, pYc+stepYc*8, stepYc, coeffMB+128);
+ mp4_AddResidual(cbpb & 4, pYc+stepYc*8+8, stepYc, coeffMB+192);
+ } else {
+ mp4_AddResidual(cbpb & 32, pYc, stepYc*2, coeffMB);
+ mp4_AddResidual(cbpb & 16, pYc+8, stepYc*2, coeffMB+64);
+ mp4_AddResidual(cbpb & 8, pYc+stepYc, stepYc*2, coeffMB+128);
+ mp4_AddResidual(cbpb & 4, pYc+stepYc+8, stepYc*2, coeffMB+192);
+ }
+ if (!field_prediction) {
+ mp4_Copy8x8HP_8u(pCbp, stepCbp, pCbc, stepCbc, &mvCbCrF, 0);
+ mp4_Copy8x8HP_8u(pCrp, stepCrp, pCrc, stepCrc, &mvCbCrF, 0);
+ mp4_Copy8x8HP_8u(pCbn, stepCbn, tmpMB, 8, &mvCbCrB, 0);
+ mp4_Copy8x8HP_8u(pCrn, stepCrn, tmpMB+64, 8, &mvCbCrB, 0);
+ } else {
+ mp4_Copy8x4HP_8u(pCbp+(mb_ftfr ? stepCbp : 0), stepCbp*2, pCbc, stepCbc*2, &mvCbCrFFT, 0);
+ mp4_Copy8x4HP_8u(pCrp+(mb_ftfr ? stepCrp : 0), stepCrp*2, pCrc, stepCrc*2, &mvCbCrFFT, 0);
+ mp4_Copy8x4HP_8u(pCbp+(mb_fbfr ? stepCbp : 0), stepCbp*2, pCbc+stepCbc, stepCbc*2, &mvCbCrFFB, 0);
+ mp4_Copy8x4HP_8u(pCrp+(mb_fbfr ? stepCrp : 0), stepCrp*2, pCrc+stepCrc, stepCrc*2, &mvCbCrFFB, 0);
+ mp4_Copy8x4HP_8u(pCbn+(mb_btfr ? stepCbn : 0), stepCbn*2, tmpMB, 16, &mvCbCrBFT, 0);
+ mp4_Copy8x4HP_8u(pCrn+(mb_btfr ? stepCrn : 0), stepCrn*2, tmpMB+64, 16, &mvCbCrBFT, 0);
+ mp4_Copy8x4HP_8u(pCbn+(mb_bbfr ? stepCbn : 0), stepCbn*2, tmpMB+8, 16, &mvCbCrBFB, 0);
+ mp4_Copy8x4HP_8u(pCrn+(mb_bbfr ? stepCrn : 0), stepCrn*2, tmpMB+64+8, 16, &mvCbCrBFB, 0);
+ }
+ ippiAverage8x8_8u_C1IR(tmpMB, 8, pCbc, stepCbc);
+ ippiAverage8x8_8u_C1IR(tmpMB+64, 8, pCrc, stepCrc);
+ mp4_AddResidual(cbpb & 2, pCbc, stepCbc, coeffMB+256);
+ mp4_AddResidual(cbpb & 1, pCrc, stepCrc, coeffMB+320);
+ } else { // IPPVC_MBTYPE_DIRECT
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_DIRECT);
+ field_prediction = pMBinfo->field_info & 1;
+ if (!field_prediction) {
+ // frame direct mode
+ if (mp4_DecodeMV_Direct(pInfo, pMBinfo->mv, mvForw, mvBack, TRB, TRD, modb, pMBinfo->type) != MP4_STATUS_OK)
+ goto Err_1;
+ if (quarter_sample) {
+ mp4_ComputeChroma4MVQ(mvForw, &mvCbCrF);
+ mp4_Limit4MVQ(mvForw, mvForw, &limitRectL, dx, dy, 8);
+ mp4_ComputeChroma4MVQ(mvBack, &mvCbCrB);
+ mp4_Limit4MVQ(mvBack, mvBack, &limitRectL, dx, dy, 8);
+ pc = pYc;
+ pr = pYp;
+ pn = pYn;
+ mp4_Copy8x8QP_8u(pr, stepYp, pc, stepYc, &mvForw[0], 0);
+ mp4_Copy8x8QP_8u(pn, stepYn, tmpMB, 16, &mvBack[0], 0);
+ mp4_Copy8x8QP_8u(pr+8, stepYp, pc+8, stepYc, &mvForw[1], 0);
+ mp4_Copy8x8QP_8u(pn+8, stepYn, tmpMB+8, 16, &mvBack[1], 0);
+ pc = pYc + stepYc * 8;
+ pr = pYp + stepYp * 8;
+ pn = pYn + stepYn * 8;
+ mp4_Copy8x8QP_8u(pr, stepYp, pc, stepYc, &mvForw[2], 0);
+ mp4_Copy8x8QP_8u(pn, stepYn, tmpMB+128, 16, &mvBack[2], 0);
+ mp4_Copy8x8QP_8u(pr+8, stepYp, pc+8, stepYc, &mvForw[3], 0);
+ mp4_Copy8x8QP_8u(pn+8, stepYn, tmpMB+136, 16, &mvBack[3], 0);
+ } else {
+ mp4_ComputeChroma4MV(mvForw, &mvCbCrF);
+ mp4_Limit4MV(mvForw, mvForw, &limitRectL, dx, dy, 8);
+ mp4_ComputeChroma4MV(mvBack, &mvCbCrB);
+ mp4_Limit4MV(mvBack, mvBack, &limitRectL, dx, dy, 8);
+ pc = pYc;
+ pr = pYp;
+ pn = pYn;
+ mp4_Copy8x8HP_8u(pr, stepYp, pc, stepYc, &mvForw[0], 0);
+ mp4_Copy8x8HP_8u(pn, stepYn, tmpMB, 16, &mvBack[0], 0);
+ mp4_Copy8x8HP_8u(pr+8, stepYp, pc+8, stepYc, &mvForw[1], 0);
+ mp4_Copy8x8HP_8u(pn+8, stepYn, tmpMB+8, 16, &mvBack[1], 0);
+ pc = pYc + stepYc * 8;
+ pr = pYp + stepYp * 8;
+ pn = pYn + stepYn * 8;
+ mp4_Copy8x8HP_8u(pr, stepYp, pc, stepYc, &mvForw[2], 0);
+ mp4_Copy8x8HP_8u(pn, stepYn, tmpMB+128, 16, &mvBack[2], 0);
+ mp4_Copy8x8HP_8u(pr+8, stepYp, pc+8, stepYc, &mvForw[3], 0);
+ mp4_Copy8x8HP_8u(pn+8, stepYn, tmpMB+136, 16, &mvBack[3], 0);
+ }
+ mp4_LimitMV(&mvCbCrF, &mvCbCrF, &limitRectC, dx >> 1, dy >> 1, 8);
+ mp4_LimitMV(&mvCbCrB, &mvCbCrB, &limitRectC, dx >> 1, dy >> 1, 8);
+ } else {
+ mb_ftfr = (pMBinfo->field_info >> 1) & 1;
+ mb_fbfr = (pMBinfo->field_info >> 2) & 1;
+ if (mp4_DecodeMV_DirectField(pInfo, mb_ftfr, mb_fbfr, &mvField[0], &mvField[1], &mvForw[0], &mvForw[2], &mvBack[0], &mvBack[2], TRB, TRD, modb) != MP4_STATUS_OK)
+ goto Err_1;
+ if (quarter_sample) {
+ mp4_LimitFMVQ(&mvForw[0], &mvForw[0], &limitRectL, dx, dy, 16);
+ mp4_LimitFMVQ(&mvForw[2], &mvForw[2], &limitRectL, dx, dy, 16);
+ mp4_LimitFMVQ(&mvBack[0], &mvBack[0], &limitRectL, dx, dy, 16);
+ mp4_LimitFMVQ(&mvBack[2], &mvBack[2], &limitRectL, dx, dy, 16);
+ mp4_Copy16x8QP_8u(pYp+(mb_ftfr ? stepYp : 0), stepYp*2, pYc, stepYc*2, &mvForw[0], 0);
+ mp4_Copy16x8QP_8u(pYp+(mb_fbfr ? stepYp : 0), stepYp*2, pYc+stepYc, stepYc*2, &mvForw[2], 0);
+ mp4_Copy16x8QP_8u(pYn/*+stepYn*mb_btfr*/, stepYn*2, tmpMB, 32, &mvBack[0], 0);
+ mp4_Copy16x8QP_8u(pYn+stepYn/**mb_bbfr*/, stepYn*2, tmpMB+16, 32, &mvBack[2], 0);
+ mvForw[0].dx = (int16_t)mp4_Div2(mvForw[0].dx);
+ mvForw[0].dy = (int16_t)(mp4_Div2(mvForw[0].dy*2) >> 1);
+ mvForw[2].dx = (int16_t)mp4_Div2(mvForw[2].dx);
+ mvForw[2].dy = (int16_t)(mp4_Div2(mvForw[2].dy*2) >> 1);
+ mvBack[0].dx = (int16_t)mp4_Div2(mvBack[0].dx);
+ mvBack[0].dy = (int16_t)(mp4_Div2(mvBack[0].dy*2) >> 1);
+ mvBack[2].dx = (int16_t)mp4_Div2(mvBack[2].dx);
+ mvBack[2].dy = (int16_t)(mp4_Div2(mvBack[2].dy*2) >> 1);
+ } else {
+ mp4_LimitFMV(&mvForw[0], &mvForw[0], &limitRectL, dx, dy, 16);
+ mp4_LimitFMV(&mvForw[2], &mvForw[2], &limitRectL, dx, dy, 16);
+ mp4_LimitFMV(&mvBack[0], &mvBack[0], &limitRectL, dx, dy, 16);
+ mp4_LimitFMV(&mvBack[2], &mvBack[2], &limitRectL, dx, dy, 16);
+ mp4_Copy16x8HP_8u(pYp+(mb_ftfr ? stepYp : 0), stepYp*2, pYc, stepYc*2, &mvForw[0], 0);
+ mp4_Copy16x8HP_8u(pYp+(mb_fbfr ? stepYp : 0), stepYp*2, pYc+stepYc, stepYc*2, &mvForw[2], 0);
+ mp4_Copy16x8HP_8u(pYn/*+stepYn*mb_btfr*/, stepYn*2, tmpMB, 32, &mvBack[0], 0);
+ mp4_Copy16x8HP_8u(pYn+stepYn/**mb_bbfr*/, stepYn*2, tmpMB+16, 32, &mvBack[2], 0);
+ }
+ mp4_ComputeChromaMV(&mvForw[0], &mvCbCrFFT);
+ mp4_ComputeChromaMV(&mvForw[2], &mvCbCrFFB);
+ mp4_ComputeChromaMV(&mvBack[0], &mvCbCrBFT);
+ mp4_ComputeChromaMV(&mvBack[2], &mvCbCrBFB);
+ }
+ ippiAverage16x16_8u_C1IR(tmpMB, 16, pYc, stepYc);
+ if (mp4_DecodeInterMB(pInfo, coeffMB, quant, cbpb, scan) != MP4_STATUS_OK)
+ goto Err_1;
+ if (!dct_type) {
+ mp4_AddResidual(cbpb & 32, pYc, stepYc, coeffMB);
+ mp4_AddResidual(cbpb & 16, pYc+8, stepYc, coeffMB+64);
+ mp4_AddResidual(cbpb & 8, pYc+stepYc*8, stepYc, coeffMB+128);
+ mp4_AddResidual(cbpb & 4, pYc+stepYc*8+8, stepYc, coeffMB+192);
+ } else {
+ mp4_AddResidual(cbpb & 32, pYc, stepYc*2, coeffMB);
+ mp4_AddResidual(cbpb & 16, pYc+8, stepYc*2, coeffMB+64);
+ mp4_AddResidual(cbpb & 8, pYc+stepYc, stepYc*2, coeffMB+128);
+ mp4_AddResidual(cbpb & 4, pYc+stepYc+8, stepYc*2, coeffMB+192);
+ }
+ if (!field_prediction) {
+ mp4_Copy8x8HP_8u(pCbp, stepCbp, pCbc, stepCbc, &mvCbCrF, 0);
+ mp4_Copy8x8HP_8u(pCrp, stepCrp, pCrc, stepCrc, &mvCbCrF, 0);
+ mp4_Copy8x8HP_8u(pCbn, stepCbn, tmpMB, 8, &mvCbCrB, 0);
+ mp4_Copy8x8HP_8u(pCrn, stepCrn, tmpMB+64, 8, &mvCbCrB, 0);
+ } else {
+ mp4_Copy8x4HP_8u(pCbp+(mb_ftfr ? stepCbp : 0), stepCbp*2, pCbc, stepCbc*2, &mvCbCrFFT, 0);
+ mp4_Copy8x4HP_8u(pCrp+(mb_ftfr ? stepCrp : 0), stepCrp*2, pCrc, stepCrc*2, &mvCbCrFFT, 0);
+ mp4_Copy8x4HP_8u(pCbp+(mb_fbfr ? stepCbp : 0), stepCbp*2, pCbc+stepCbc, stepCbc*2, &mvCbCrFFB, 0);
+ mp4_Copy8x4HP_8u(pCrp+(mb_fbfr ? stepCrp : 0), stepCrp*2, pCrc+stepCrc, stepCrc*2, &mvCbCrFFB, 0);
+ mp4_Copy8x4HP_8u(pCbn/*+(mb_btfr ? stepCbn : 0)*/, stepCbn*2, tmpMB, 16, &mvCbCrBFT, 0);
+ mp4_Copy8x4HP_8u(pCrn/*+(mb_btfr ? stepCrn : 0)*/, stepCrn*2, tmpMB+64, 16, &mvCbCrBFT, 0);
+ mp4_Copy8x4HP_8u(pCbn+/*(mb_bbfr ? */stepCbn/* : 0)*/, stepCbn*2, tmpMB+8, 16, &mvCbCrBFB, 0);
+ mp4_Copy8x4HP_8u(pCrn+/*(mb_bbfr ? */stepCrn/* : 0)*/, stepCrn*2, tmpMB+64+8, 16, &mvCbCrBFB, 0);
+ }
+ ippiAverage8x8_8u_C1IR(tmpMB, 8, pCbc, stepCbc);
+ ippiAverage8x8_8u_C1IR(tmpMB+64, 8, pCrc, stepCrc);
+ mp4_AddResidual(cbpb & 2, pCbc, stepCbc, coeffMB+256);
+ mp4_AddResidual(cbpb & 1, pCrc, stepCrc, coeffMB+320);
+ }
+ }
+ //mbCurr ++;
+ mbInVideoPacket ++;
+ colNum ++;
+ pMBinfo ++;
+ mvField += 2;
+ if (colNum == mbPerRow) {
+ colNum = 0;
+ rowNum ++;
+ if (rowNum == mbPerCol)
+ return sts;
+ pYc += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc;
+ pCbc += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbc << 3) - stepCbc;
+ pCrc += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrc << 3) - stepCrc;
+ pYp += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYp << 4) - stepYp;
+ pCbp += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbp << 3) - stepCbp;
+ pCrp += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrp << 3) - stepCrp;
+ pYn += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYn << 4) - stepYn;
+ pCbn += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbn << 3) - stepCbn;
+ pCrn += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrn << 3) - stepCrn;
+ // reset MV predictors at new row
+ mvForwT.dx = mvForwT.dy = mvBackT.dx = mvBackT.dy = mvForwB.dx = mvForwB.dy = mvBackB.dx = mvBackB.dy = 0;
+ } else {
+ pYc += 16; pCrc += 8; pCbc += 8;
+ pYp += 16; pCrp += 8; pCbp += 8;
+ pYn += 16; pCrn += 8; pCbn += 8;
+ }
+ if (!pInfo->VisualObject.VideoObject.resync_marker_disable) {
+ int32_t found;
+ErrRet_1:
+ if (mp4_CheckDecodeVideoPacket(pInfo, &found) == MP4_STATUS_OK) {
+ if (found) {
+ quant = pInfo->VisualObject.VideoObject.VideoObjectPlane.quant_scale;
+ mbCurr = pInfo->VisualObject.VideoObject.VideoObjectPlane.macroblock_num;
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, mbCurr - rowNum * mbPerRow - colNum);
+ rowNum = mbCurr / mbPerRow;
+ colNum = mbCurr % mbPerRow;
+ pYc = pInfo->VisualObject.cFrame->pY + (rowNum * stepYc + colNum) * 16; pCbc = pInfo->VisualObject.cFrame->pCb + (rowNum * stepCbc + colNum) * 8; pCrc = pInfo->VisualObject.cFrame->pCr + (rowNum * stepCrc + colNum) * 8;
+ pYp = pInfo->VisualObject.rFrame->pY + (rowNum * stepYp + colNum) * 16; pCbp = pInfo->VisualObject.rFrame->pCb + (rowNum * stepCbp + colNum) * 8; pCrp = pInfo->VisualObject.rFrame->pCr + (rowNum * stepCrp + colNum) * 8;
+ pYn = pInfo->VisualObject.nFrame->pY + (rowNum * stepYn + colNum) * 16; pCbn = pInfo->VisualObject.nFrame->pCb + (rowNum * stepCbn + colNum) * 8; pCrn = pInfo->VisualObject.nFrame->pCr + (rowNum * stepCrn + colNum) * 8;
+ pMBinfo = pInfo->VisualObject.VideoObject.MBinfo + mbCurr;
+ break;
+ }
+ } else
+ goto Err_1;
+ }
+ }
+ }
+Err_1:
+ sts = MP4_STATUS_ERROR;
+ if (pInfo->stopOnErr)
+ return sts;
+ if (pInfo->VisualObject.VideoObject.resync_marker_disable || !mp4_SeekResyncMarker(pInfo))
+ {
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, pInfo->VisualObject.VideoObject.MacroBlockPerVOP - rowNum * mbPerRow - colNum);
+ return sts;
+ }
+ goto ErrRet_1;
+ }
+// decode usual B-VOP
+ for (;;) {
+ IppMotionVector mvCbCrF, mvCbCrB, mvForw, mvBack, mvForwLim, mvBackLim;
+
+ mbInVideoPacket = 0;
+ // reset MV predictors at new VideoPacket
+ mvForw.dx = mvForw.dy = mvBack.dx = mvBack.dy = 0;
+ // decode B-VOP macroblocks
+ for (;;) {
+ if (pMBinfo->not_coded) {
+ ippiCopy16x16_8u_C1R(pYp, stepYp, pYc, stepYc);
+ ippiCopy8x8_8u_C1R(pCbp, stepCbp, pCbc, stepCbc);
+ ippiCopy8x8_8u_C1R(pCrp, stepCrp, pCrc, stepCrc);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_NOTCODED);
+ } else {
+ cbpb = 0;
+ if (mp4_GetBit(pInfo)) {
+ modb = 2;
+ mb_type = IPPVC_MBTYPE_DIRECT;
+ } else {
+ modb = mp4_GetBit(pInfo);
+ // decode mb_type
+ code = mp4_ShowBits9(pInfo, 4);
+ if (code != 0) {
+ mb_type = mp4_BVOPmb_type[code].code;
+ mp4_FlushBits(pInfo, mp4_BVOPmb_type[code].len);
+ } else {
+ mp4_Error("Error when decode mb_type of B-VOP macroblock");
+ goto Err_2;
+ }
+ if (modb == 0)
+ cbpb = mp4_GetBits9(pInfo, 6);
+ if (mb_type != IPPVC_MBTYPE_DIRECT && cbpb != 0)
+ mp4_UpdateQuant_B(pInfo, quant);
+ }
+ // coordinates of current MB for limitation
+ dx = colNum * 16;
+ dy = rowNum * 16;
+ if (mb_type == IPPVC_MBTYPE_FORWARD) {
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_FORWARD);
+ if (mp4_DecodeMV(pInfo, &mvForw, fcode_forward) != MP4_STATUS_OK)
+ goto Err_2;
+ if (quarter_sample) {
+ mp4_LimitMVQ(&mvForw, &mvForwLim, &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMVQ(&mvForwLim, &mvCbCrF);
+ mp4_Copy16x16QP_8u(pYp, stepYp, pYc, stepYc, &mvForwLim, 0);
+ mp4_DecodeReconBlockInter_MPEG4(cbpb & 32, pYc, stepYc, Err_2);
+ mp4_DecodeReconBlockInter_MPEG4(cbpb & 16, pYc+8, stepYc, Err_2);
+ mp4_DecodeReconBlockInter_MPEG4(cbpb & 8, pYc+8*stepYc, stepYc, Err_2);
+ mp4_DecodeReconBlockInter_MPEG4(cbpb & 4, pYc+8*stepYc+8, stepYc, Err_2);
+ } else {
+ mp4_LimitMV(&mvForw, &mvForwLim, &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMV(&mvForwLim, &mvCbCrF);
+ if (cbpb & 60) {
+ mp4_DecodeMCBlockInter_MPEG4(cbpb & 32, pYp, stepYp, pYc, stepYc, mvForwLim, 0, Err_2);
+ mp4_DecodeMCBlockInter_MPEG4(cbpb & 16, pYp+8, stepYp, pYc+8, stepYc, mvForwLim, 0, Err_2);
+ mp4_DecodeMCBlockInter_MPEG4(cbpb & 8, pYp+8*stepYp, stepYp, pYc+8*stepYc, stepYc, mvForwLim, 0, Err_2);
+ mp4_DecodeMCBlockInter_MPEG4(cbpb & 4, pYp+8*stepYp+8, stepYp, pYc+8*stepYc+8, stepYc, mvForwLim, 0, Err_2);
+ } else {
+ mp4_Copy16x16HP_8u(pYp, stepYp, pYc, stepYc, &mvForwLim, 0);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ }
+ }
+ mp4_DecodeMCBlockInter_MPEG4(cbpb & 2, pCbp, stepCbp, pCbc, stepCbc, mvCbCrF, 0, Err_2);
+ mp4_DecodeMCBlockInter_MPEG4(cbpb & 1, pCrp, stepCrp, pCrc, stepCrc, mvCbCrF, 0, Err_2);
+ } else if (mb_type == IPPVC_MBTYPE_BACKWARD) {
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_BACKWARD);
+ if (mp4_DecodeMV(pInfo, &mvBack, fcode_backward) != MP4_STATUS_OK)
+ goto Err_2;
+ if (quarter_sample) {
+ mp4_LimitMVQ(&mvBack, &mvBackLim, &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMVQ(&mvBackLim, &mvCbCrB);
+ mp4_Copy16x16QP_8u(pYn, stepYn, pYc, stepYc, &mvBackLim, 0);
+ mp4_DecodeReconBlockInter_MPEG4(cbpb & 32, pYc, stepYc, Err_2);
+ mp4_DecodeReconBlockInter_MPEG4(cbpb & 16, pYc+8, stepYc, Err_2);
+ mp4_DecodeReconBlockInter_MPEG4(cbpb & 8, pYc+8*stepYc, stepYc, Err_2);
+ mp4_DecodeReconBlockInter_MPEG4(cbpb & 4, pYc+8*stepYc+8, stepYc, Err_2);
+ } else {
+ mp4_LimitMV(&mvBack, &mvBackLim, &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMV(&mvBackLim, &mvCbCrB);
+ if (cbpb & 60) {
+ mp4_DecodeMCBlockInter_MPEG4(cbpb & 32, pYn, stepYn, pYc, stepYc, mvBackLim, 0, Err_2);
+ mp4_DecodeMCBlockInter_MPEG4(cbpb & 16, pYn+8, stepYn, pYc+8, stepYc, mvBackLim, 0, Err_2);
+ mp4_DecodeMCBlockInter_MPEG4(cbpb & 8, pYn+8*stepYn, stepYp, pYc+8*stepYc, stepYc, mvBackLim, 0, Err_2);
+ mp4_DecodeMCBlockInter_MPEG4(cbpb & 4, pYn+8*stepYn+8, stepYp, pYc+8*stepYc+8, stepYc, mvBackLim, 0, Err_2);
+ } else {
+ mp4_Copy16x16HP_8u(pYn, stepYn, pYc, stepYc, &mvBackLim, 0);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ }
+ }
+ mp4_DecodeMCBlockInter_MPEG4(cbpb & 2, pCbn, stepCbn, pCbc, stepCbc, mvCbCrB, 0, Err_2);
+ mp4_DecodeMCBlockInter_MPEG4(cbpb & 1, pCrn, stepCrn, pCrc, stepCrc, mvCbCrB, 0, Err_2);
+ }
+ else if (mb_type == IPPVC_MBTYPE_INTERPOLATE)
+ {
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_INTERPOLATE);
+ if (mp4_DecodeMV(pInfo, &mvForw, fcode_forward) != MP4_STATUS_OK)
+ goto Err_2;
+ if (mp4_DecodeMV(pInfo, &mvBack, fcode_backward) != MP4_STATUS_OK)
+ goto Err_2;
+ if (quarter_sample)
+ {
+ mp4_LimitMVQ(&mvForw, &mvForwLim, &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMVQ(&mvForwLim, &mvCbCrF);
+ mp4_Copy16x16QP_8u(pYp, stepYp, pYc, stepYc, &mvForwLim, 0);
+ mp4_LimitMVQ(&mvBack, &mvBackLim, &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMVQ(&mvBackLim, &mvCbCrB);
+ mp4_Copy16x16QP_8u(pYn, stepYn, tmpMB, 16, &mvBackLim, 0);
+ }
+ else
+ {
+ mp4_LimitMV(&mvForw, &mvForwLim, &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMV(&mvForwLim, &mvCbCrF);
+ mp4_Copy16x16HP_8u(pYp, stepYp, pYc, stepYc, &mvForwLim, 0);
+ mp4_LimitMV(&mvBack, &mvBackLim, &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMV(&mvBackLim, &mvCbCrB);
+ mp4_Copy16x16HP_8u(pYn, stepYn, tmpMB, 16, &mvBackLim, 0);
+ }
+ ippiAverage16x16_8u_C1IR(tmpMB, 16, pYc, stepYc);
+ mp4_DecodeReconBlockInter_MPEG4(cbpb & 32, pYc, stepYc, Err_2);
+ mp4_DecodeReconBlockInter_MPEG4(cbpb & 16, pYc+8, stepYc, Err_2);
+ mp4_DecodeReconBlockInter_MPEG4(cbpb & 8, pYc+8*stepYc, stepYc, Err_2);
+ mp4_DecodeReconBlockInter_MPEG4(cbpb & 4, pYc+8*stepYc+8, stepYc, Err_2);
+ mp4_Copy8x8HP_8u(pCbp, stepCbp, pCbc, stepCbc, &mvCbCrF, 0);
+ mp4_Copy8x8HP_8u(pCbn, stepCbn, tmpMB, 8, &mvCbCrB, 0);
+ ippiAverage8x8_8u_C1IR(tmpMB, 8, pCbc, stepCbc);
+ mp4_DecodeReconBlockInter_MPEG4(cbpb & 2, pCbc, stepCbc, Err_2);
+ mp4_Copy8x8HP_8u(pCrp, stepCrp, pCrc, stepCrc, &mvCbCrF, 0);
+ mp4_Copy8x8HP_8u(pCrn, stepCrn, tmpMB, 8, &mvCbCrB, 0);
+ ippiAverage8x8_8u_C1IR(tmpMB, 8, pCrc, stepCrc);
+ mp4_DecodeReconBlockInter_MPEG4(cbpb & 1, pCrc, stepCrc, Err_2);
+ }
+ else
+ { // IPPVC_MBTYPE_DIRECT
+ IppMotionVector mvForw[4], mvBack[4], mvForwLim[4], mvBackLim[4];
+
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_DIRECT);
+ //f MVs of collocated block of recently decoded I or P frame used in Direct mode
+ if (mp4_DecodeMV_Direct(pInfo, pMBinfo->mv, mvForw, mvBack, TRB, TRD, modb, pMBinfo->type) != MP4_STATUS_OK)
+ goto Err_2;
+ if (quarter_sample)
+ {
+ mp4_Limit4MVQ(mvForw, mvForwLim, &limitRectL, dx, dy, 8);
+ mp4_ComputeChroma4MVQ(mvForw, &mvCbCrF);
+ mp4_Limit4MVQ(mvBack, mvBackLim, &limitRectL, dx, dy, 8);
+ mp4_ComputeChroma4MVQ(mvBack, &mvCbCrB);
+ mp4_Copy8x8QP_8u(pYp, stepYp, pYc, stepYc, &mvForwLim[0], 0);
+ mp4_Copy8x8QP_8u(pYn, stepYn, tmpMB, 16, &mvBackLim[0], 0);
+ mp4_Copy8x8QP_8u(pYp+8, stepYp, pYc+8, stepYc, &mvForwLim[1], 0);
+ mp4_Copy8x8QP_8u(pYn+8, stepYn, tmpMB+8, 16, &mvBackLim[1], 0);
+ mp4_Copy8x8QP_8u(pYp+8*stepYp, stepYp, pYc+8*stepYc, stepYc, &mvForwLim[2], 0);
+ mp4_Copy8x8QP_8u(pYn+8*stepYn, stepYn, tmpMB+8*16, 16, &mvBackLim[2], 0);
+ mp4_Copy8x8QP_8u(pYp+8*stepYp+8, stepYp, pYc+8*stepYc+8, stepYc, &mvForwLim[3], 0);
+ mp4_Copy8x8QP_8u(pYn+8*stepYn+8, stepYn, tmpMB+8*16+8, 16, &mvBackLim[3], 0);
+ }
+ else
+ {
+ if (pMBinfo->type == IPPVC_MBTYPE_INTER4V) {
+ mp4_Limit4MV(mvForw, mvForwLim, &limitRectL, dx, dy, 8);
+ mp4_ComputeChroma4MV(mvForw, &mvCbCrF);
+ mp4_Limit4MV(mvBack, mvBackLim, &limitRectL, dx, dy, 8);
+ mp4_ComputeChroma4MV(mvBack, &mvCbCrB);
+ mp4_Copy8x8HP_8u(pYp, stepYp, pYc, stepYc, &mvForwLim[0], 0);
+ mp4_Copy8x8HP_8u(pYn, stepYn, tmpMB, 16, &mvBackLim[0], 0);
+ mp4_Copy8x8HP_8u(pYp+8, stepYp, pYc+8, stepYc, &mvForwLim[1], 0);
+ mp4_Copy8x8HP_8u(pYn+8, stepYn, tmpMB+8, 16, &mvBackLim[1], 0);
+ mp4_Copy8x8HP_8u(pYp+8*stepYp, stepYp, pYc+8*stepYc, stepYc, &mvForwLim[2], 0);
+ mp4_Copy8x8HP_8u(pYn+8*stepYn, stepYn, tmpMB+8*16, 16, &mvBackLim[2], 0);
+ mp4_Copy8x8HP_8u(pYp+8*stepYp+8, stepYp, pYc+8*stepYc+8, stepYc, &mvForwLim[3], 0);
+ mp4_Copy8x8HP_8u(pYn+8*stepYn+8, stepYn, tmpMB+8*16+8, 16, &mvBackLim[3], 0);
+ }
+ else
+ {
+ mp4_LimitMV(mvForw, mvForwLim, &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMV(mvForwLim, &mvCbCrF);
+ mp4_LimitMV(mvBack, mvBackLim, &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMV(mvBackLim, &mvCbCrB);
+ mp4_Copy16x16HP_8u(pYp, stepYp, pYc, stepYc, &mvForwLim[0], 0);
+ mp4_Copy16x16HP_8u(pYn, stepYn, tmpMB, 16, &mvBackLim[0], 0);
+ }
+ }
+ ippiAverage16x16_8u_C1IR(tmpMB, 16, pYc, stepYc);
+ mp4_DecodeReconBlockInter_MPEG4(cbpb & 32, pYc, stepYc, Err_2);
+ mp4_DecodeReconBlockInter_MPEG4(cbpb & 16, pYc+8, stepYc, Err_2);
+ mp4_DecodeReconBlockInter_MPEG4(cbpb & 8, pYc+8*stepYc, stepYc, Err_2);
+ mp4_DecodeReconBlockInter_MPEG4(cbpb & 4, pYc+8*stepYc+8, stepYc, Err_2);
+ mp4_LimitMV(&mvCbCrF, &mvCbCrF, &limitRectC, dx >> 1, dy >> 1, 8);
+ mp4_LimitMV(&mvCbCrB, &mvCbCrB, &limitRectC, dx >> 1, dy >> 1, 8);
+ mp4_Copy8x8HP_8u(pCbp, stepCbp, pCbc, stepCbc, &mvCbCrF, 0);
+ mp4_Copy8x8HP_8u(pCbn, stepCbn, tmpMB, 8, &mvCbCrB, 0);
+ ippiAverage8x8_8u_C1IR(tmpMB, 8, pCbc, stepCbc);
+ mp4_DecodeReconBlockInter_MPEG4(cbpb & 2, pCbc, stepCbc, Err_2);
+ mp4_Copy8x8HP_8u(pCrp, stepCrp, pCrc, stepCrc, &mvCbCrF, 0);
+ mp4_Copy8x8HP_8u(pCrn, stepCrn, tmpMB, 8, &mvCbCrB, 0);
+ ippiAverage8x8_8u_C1IR(tmpMB, 8, pCrc, stepCrc);
+ mp4_DecodeReconBlockInter_MPEG4(cbpb & 1, pCrc, stepCrc, Err_2);
+ }
+ }
+ //mbCurr ++;
+ mbInVideoPacket ++;
+ colNum ++;
+ pMBinfo ++;
+ if (colNum == mbPerRow)
+ {
+ colNum = 0;
+ rowNum ++;
+ if (rowNum == mbPerCol)
+ return sts;
+ pYc += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc;
+ pCbc += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbc << 3) - stepCbc;
+ pCrc += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrc << 3) - stepCrc;
+ pYp += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYp << 4) - stepYp;
+ pCbp += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbp << 3) - stepCbp;
+ pCrp += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrp << 3) - stepCrp;
+ pYn += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYn << 4) - stepYn;
+ pCbn += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbn << 3) - stepCbn;
+ pCrn += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrn << 3) - stepCrn;
+ // reset MV predictors at new row
+ mvForw.dx = mvForw.dy = mvBack.dx = mvBack.dy = 0;
+ }
+ else
+ {
+ pYc += 16; pCrc += 8; pCbc += 8;
+ pYp += 16; pCrp += 8; pCbp += 8;
+ pYn += 16; pCrn += 8; pCbn += 8;
+ }
+ if (!pInfo->VisualObject.VideoObject.resync_marker_disable)
+ {
+ int32_t found;
+ErrRet_2:
+ if (mp4_CheckDecodeVideoPacket(pInfo, &found) == MP4_STATUS_OK)
+ {
+ if (found)
+ {
+ quant = pInfo->VisualObject.VideoObject.VideoObjectPlane.quant_scale;
+ mbCurr = pInfo->VisualObject.VideoObject.VideoObjectPlane.macroblock_num;
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, mbCurr - rowNum * mbPerRow - colNum);
+ rowNum = mbCurr / mbPerRow;
+ colNum = mbCurr % mbPerRow;
+ pYc = pInfo->VisualObject.cFrame->pY + (rowNum * stepYc + colNum) * 16; pCbc = pInfo->VisualObject.cFrame->pCb + (rowNum * stepCbc + colNum) * 8; pCrc = pInfo->VisualObject.cFrame->pCr + (rowNum * stepCrc + colNum) * 8;
+ pYp = pInfo->VisualObject.rFrame->pY + (rowNum * stepYp + colNum) * 16; pCbp = pInfo->VisualObject.rFrame->pCb + (rowNum * stepCbp + colNum) * 8; pCrp = pInfo->VisualObject.rFrame->pCr + (rowNum * stepCrp + colNum) * 8;
+ pYn = pInfo->VisualObject.nFrame->pY + (rowNum * stepYn + colNum) * 16; pCbn = pInfo->VisualObject.nFrame->pCb + (rowNum * stepCbn + colNum) * 8; pCrn = pInfo->VisualObject.nFrame->pCr + (rowNum * stepCrn + colNum) * 8;
+ pMBinfo = pInfo->VisualObject.VideoObject.MBinfo + mbCurr;
+ break;
+ }
+ }
+ else
+ goto Err_2;
+ }
+ }
+ }
+Err_2:
+ sts = MP4_STATUS_ERROR;
+ if (pInfo->stopOnErr)
+ return sts;
+ if (pInfo->VisualObject.VideoObject.resync_marker_disable || !mp4_SeekResyncMarker(pInfo))
+ {
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, pInfo->VisualObject.VideoObject.MacroBlockPerVOP - rowNum * mbPerRow - colNum);
+ return sts;
+ }
+ goto ErrRet_2;
+}
+
diff --git a/Src/mpeg4dec/mp4decvopi.c b/Src/mpeg4dec/mp4decvopi.c
new file mode 100644
index 000000000..2ec2fb84d
--- /dev/null
+++ b/Src/mpeg4dec/mp4decvopi.c
@@ -0,0 +1,408 @@
+/* ///////////////////////////////////////////////////////////////////////
+//
+// INTEL CORPORATION PROPRIETARY INFORMATION
+// This software is supplied under the terms of a license agreement or
+// nondisclosure agreement with Intel Corporation and may not be copied
+// or disclosed except in accordance with the terms of that agreement.
+// Copyright (c) 2001-2007 Intel Corporation. All Rights Reserved.
+//
+// Description: Decodes I-VOPs
+//
+*/
+
+#include "mp4def.h"
+#include "mp4dec.h"
+
+/*
+// decode mcbpc and set MBtype and ChromaPattern
+*/
+/*static*/ mp4_Status mp4_DecodeMCBPC_I(mp4_Info* pInfo, int32_t *mbType, int32_t *mbPattern)
+{
+ uint32_t code;
+ int32_t type, pattern, fb;
+
+ code = mp4_ShowBits9(pInfo, 9);
+ if (code == 1) {
+ type = IPPVC_MB_STUFFING;
+ pattern = 0;
+ fb = 9;
+ } else if (code >= 64) {
+ type = IPPVC_MBTYPE_INTRA;
+ pattern = code >> 6;
+ if (pattern >= 4) {
+ pattern = 0;
+ fb = 1;
+ } else
+ fb = 3;
+ } else {
+ type = IPPVC_MBTYPE_INTRA_Q;
+ pattern = code >> 3;
+ if (pattern >= 4) {
+ pattern = 0;
+ fb = 4;
+ } else if (code >= 8) {
+ fb = 6;
+ } else {
+ mp4_Error("Error: decoding MCBPC");
+ return MP4_STATUS_ERROR;
+ }
+ }
+ mp4_FlushBits(pInfo, fb);
+ *mbType = type;
+ *mbPattern = pattern;
+ if (type == IPPVC_MBTYPE_INTRA)
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_INTRA);
+ else if (type == IPPVC_MBTYPE_INTRA_Q)
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_INTRA_Q);
+ return MP4_STATUS_OK;
+}
+
+
+/*
+// decode IVOP
+*/
+mp4_Status mp4_DecodeVOP_I(mp4_Info* pInfo)
+{
+ int32_t quant, quantPred, dcVLC, mb_type, cbpc, cbpy, ac_pred_flag;
+ int32_t i, j, nmb, nmbgob, stepYc, stepCbc, stepCrc, stepFc[6], mbCurr, mbInVideoPacket, colNum, rowNum, mbPerRow, mbPerCol;
+ uint8_t *pFc[6];
+ mp4_Status sts;
+
+ if (pInfo->VisualObject.cFrame)
+ {
+ DebugBreak();
+ }
+ pInfo->VisualObject.cFrame = CreateFrame(&pInfo->VisualObject);
+ stepYc = pInfo->VisualObject.cFrame->stepY;
+ stepCbc = pInfo->VisualObject.cFrame->stepCb;
+ stepCrc = pInfo->VisualObject.cFrame->stepCr;
+ mbPerRow = pInfo->VisualObject.VideoObject.MacroBlockPerRow;
+ mbPerCol = pInfo->VisualObject.VideoObject.MacroBlockPerCol;
+ stepFc[0] = stepFc[1] = stepFc[2] = stepFc[3] = stepYc; stepFc[4] = stepCbc; stepFc[5] = stepCrc;
+ pFc[0] = pInfo->VisualObject.cFrame->pY; pFc[1] = pInfo->VisualObject.cFrame->pY + 8;
+ pFc[2] = pInfo->VisualObject.cFrame->pY + 8 * stepYc; pFc[3] = pInfo->VisualObject.cFrame->pY + 8 * stepYc + 8;
+ pFc[4] = pInfo->VisualObject.cFrame->pCb; pFc[5] = pInfo->VisualObject.cFrame->pCr;
+ nmb = pInfo->VisualObject.VideoObject.MacroBlockPerVOP;
+ mbCurr = colNum = rowNum = 0;
+ sts = MP4_STATUS_OK;
+// decode short_video_header I-VOP
+ if (pInfo->VisualObject.VideoObject.short_video_header)
+ {
+ quant = pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.vop_quant;
+ nmbgob = 0;
+ pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.gob_number = 0;
+ for (;;)
+ {
+ do
+ {
+ if (mp4_DecodeMCBPC_I(pInfo, &mb_type, &cbpc) != MP4_STATUS_OK)
+ goto Err_1;
+ } while (mb_type == IPPVC_MB_STUFFING);
+ if (mp4_DecodeCBPY_I(pInfo, &cbpy) != MP4_STATUS_OK)
+ goto Err_1;
+ if (mb_type == IPPVC_MBTYPE_INTRA_Q)
+ mp4_UpdateQuant(pInfo, quant);
+ if (mp4_DecodeIntraMB_SVH(pInfo, (cbpy << 2) + cbpc, quant, pFc, stepFc) != MP4_STATUS_OK)
+ goto Err_1;
+ colNum ++;
+ if (colNum == mbPerRow) {
+ colNum = 0;
+ rowNum ++;
+ if (rowNum == mbPerCol)
+ break;
+ pFc[0] += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc;
+ pFc[1] += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc;
+ pFc[2] += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc;
+ pFc[3] += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc;
+ pFc[4] += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbc << 3) - stepCbc;
+ pFc[5] += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrc << 3) - stepCrc;
+ }
+ else
+ {
+ pFc[0] += 16; pFc[1] += 16; pFc[2] += 16; pFc[3] += 16; pFc[4] += 8; pFc[5] += 8;
+ }
+ nmbgob ++;
+ if (nmbgob == pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.num_macroblocks_in_gob && pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.gob_number < (pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.num_gobs_in_vop - 1)) {
+ErrRet_1:
+ if (mp4_CheckDecodeGOB_SVH(pInfo) != MP4_STATUS_OK)
+ goto Err_1;
+ if (!pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.gob_header_empty)
+ {
+ quant = pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.quant_scale;
+ i = pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.gob_number * pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.num_rows_in_gob;
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, (i - rowNum) * mbPerRow - colNum);
+ rowNum = i;
+ colNum = 0;
+ pFc[0] = pInfo->VisualObject.cFrame->pY + i * stepYc * 16; pFc[1] = pFc[0] + 8; pFc[2] = pFc[0] + 8 * stepYc; pFc[3] = pFc[2] + 8;
+ pFc[4] = pInfo->VisualObject.cFrame->pCb + i * stepCbc * 8; pFc[5] = pInfo->VisualObject.cFrame->pCr + i * stepCrc * 8;
+ }
+ nmbgob = 0;
+ }
+ }
+ mp4_AlignBits(pInfo);
+ return sts;
+Err_1:
+ sts = MP4_STATUS_ERROR;
+ if (pInfo->stopOnErr)
+ return sts;
+ if (!mp4_SeekGOBMarker(pInfo))
+ {
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, pInfo->VisualObject.VideoObject.MacroBlockPerVOP - rowNum * mbPerRow - colNum);
+ return sts;
+ }
+ goto ErrRet_1;
+ }
+ quant = pInfo->VisualObject.VideoObject.VideoObjectPlane.quant;
+ if (pInfo->VisualObject.VideoObject.sprite_enable != MP4_SPRITE_STATIC)
+ ippsZero_8u((uint8_t*)pInfo->VisualObject.VideoObject.MBinfo, nmb * sizeof(mp4_MacroBlock));
+// decode data_partitioned I-VOP
+ if (pInfo->VisualObject.VideoObject.data_partitioned)
+ {
+ mp4_DataPartMacroBlock *pMBdp;
+
+ for (;;)
+ {
+ // reset Intra prediction buffer on new Video_packet
+ mp4_ResetIntraPredBuffer(pInfo);
+ mbInVideoPacket = 0;
+ pMBdp = &pInfo->VisualObject.VideoObject.DataPartBuff[mbCurr];
+ // decode mb_type/cbpc/dquant/DC part
+ for (;;)
+ {
+ if (mp4_DecodeMCBPC_I(pInfo, &mb_type, &cbpc) != MP4_STATUS_OK)
+ goto Err_2;
+ if (mb_type != IPPVC_MB_STUFFING)
+ {
+ if (mbInVideoPacket == nmb - mbCurr)
+ {
+ mp4_Error("DC Marker missed");
+ goto Err_2;
+ }
+ quantPred = quant;
+ if (mb_type == IPPVC_MBTYPE_INTRA_Q)
+ mp4_UpdateQuant(pInfo, quant);
+ if (mbInVideoPacket == 0)
+ quantPred = quant;
+ dcVLC = (quantPred < mp4_DC_vlc_Threshold[pInfo->VisualObject.VideoObject.VideoObjectPlane.intra_dc_vlc_thr]) ? 1 : 0;
+ if (dcVLC) {
+ for (i = 0; i < 6; i ++) {
+ if (ippiDecodeDCIntra_MPEG4_1u16s(&pInfo->bufptr, &pInfo->bitoff, &pMBdp->dct_dc[i], (i < 4) ? IPPVC_BLOCK_LUMA : IPPVC_BLOCK_CHROMA) != ippStsNoErr)
+ goto Err_2;
+ }
+ }
+ pMBdp->quant = (uint8_t)quant;
+ pMBdp->type = (uint8_t)mb_type;
+ pMBdp->pat = (uint8_t)cbpc;
+ pMBdp ++;
+ mbInVideoPacket ++;
+ }
+ if (mp4_ShowBits(pInfo, 19) == MP4_DC_MARKER)
+ {
+ mp4_GetBits(pInfo, 19);
+ break;
+ }
+ }
+ pMBdp = &pInfo->VisualObject.VideoObject.DataPartBuff[mbCurr];
+ // decode ac_pred_flag/cbpy part
+ for (i = 0; i < mbInVideoPacket; i ++)
+ {
+ pMBdp[i].ac_pred_flag = (uint8_t)mp4_GetBit(pInfo);
+ if (mp4_DecodeCBPY_I(pInfo, &cbpy) != MP4_STATUS_OK)
+ {
+ if (pInfo->stopOnErr)
+ goto Err_2;
+ for (j = i + 1; j < mbInVideoPacket; j ++)
+ pMBdp[j].ac_pred_flag = 1;
+ break;
+ }
+ pMBdp[i].pat = (uint8_t)((cbpy << 2) + pMBdp[i].pat);
+ }
+ // decode AC part and reconstruct macroblocks
+ for (i = 0; i < mbInVideoPacket; i ++) {
+ if (colNum == 0) {
+ // reset B-prediction blocks on new row
+ mp4_ResetIntraPredBblock(pInfo);
+ }
+ quant = pMBdp[i].quant;
+ quantPred = (i == 0) ? quant : pMBdp[i-1].quant;
+ dcVLC = (quantPred < mp4_DC_vlc_Threshold[pInfo->VisualObject.VideoObject.VideoObjectPlane.intra_dc_vlc_thr]) ? 1 : 0;
+ ac_pred_flag = pMBdp[i].ac_pred_flag;
+ if (mp4_DecodeIntraMB_DP(pInfo, pMBdp[i].dct_dc, colNum, pMBdp[i].pat, quant, dcVLC, ac_pred_flag, pFc, stepFc) != MP4_STATUS_OK)
+ //if (!pInfo->VisualObject.VideoObject.reversible_vlc)
+ goto Err_2;
+ //else
+ // goto Err_RVLC;
+ colNum ++;
+ if (colNum == mbPerRow)
+ {
+ colNum = 0;
+ rowNum ++;
+ if (rowNum == mbPerCol)
+ return sts;
+ pFc[0] += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc;
+ pFc[1] += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc;
+ pFc[2] += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc;
+ pFc[3] += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc;
+ pFc[4] += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbc << 3) - stepCbc;
+ pFc[5] += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrc << 3) - stepCrc;
+ }
+ else
+ {
+ pFc[0] += 16; pFc[1] += 16; pFc[2] += 16; pFc[3] += 16; pFc[4] += 8; pFc[5] += 8;
+ }
+ }
+ mbCurr += mbInVideoPacket;
+ if (!pInfo->VisualObject.VideoObject.resync_marker_disable)
+ {
+ int32_t found;
+ErrRet_2:
+ if (mp4_CheckDecodeVideoPacket(pInfo, &found) == MP4_STATUS_OK)
+ {
+ if (found)
+ {
+ quant = pInfo->VisualObject.VideoObject.VideoObjectPlane.quant_scale;
+ mbCurr = pInfo->VisualObject.VideoObject.VideoObjectPlane.macroblock_num;
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, mbCurr - rowNum * mbPerRow - colNum);
+ rowNum = mbCurr / mbPerRow;
+ colNum = mbCurr % mbPerRow;
+ pFc[0] = pInfo->VisualObject.cFrame->pY + (rowNum * stepYc + colNum) * 16; pFc[1] = pFc[0] + 8; pFc[2] = pFc[0] + stepYc * 8; pFc[3] = pFc[2] + 8;
+ pFc[4] = pInfo->VisualObject.cFrame->pCb + (rowNum * stepCbc + colNum) * 8; pFc[5] = pInfo->VisualObject.cFrame->pCr + (rowNum * stepCrc + colNum) * 8;
+ }
+ else
+ goto Err_2;
+ }
+ else
+ goto Err_2;
+ }
+ }
+Err_2:
+ sts = MP4_STATUS_ERROR;
+ if (pInfo->stopOnErr)
+ return sts;
+ if (pInfo->VisualObject.VideoObject.resync_marker_disable || !mp4_SeekResyncMarker(pInfo))
+ {
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, pInfo->VisualObject.VideoObject.MacroBlockPerVOP - rowNum * mbPerRow - colNum);
+ return sts;
+ }
+ goto ErrRet_2;
+#if 0
+Err_RVLC:
+ {
+ uint8_t *sBufptr = pInfo->bufptr;
+ int32_t sBitoff = pInfo->bitoff;
+
+ pInfo->bitoff --;
+ if (pInfo->bitoff == -1) {
+ pInfo->bitoff = 7;
+ pInfo->bufptr --;
+ }
+ // decode AC part and reconstruct macroblocks
+ for (j = mbInVideoPacket - 1; j >= i; j --) {
+ int32_t lnz, quantPred, dcVLC;
+
+ quantPred = ((j == 0) ? pMBdp[j].quant : pMBdp[j-1].quant);
+ dcVLC = (quantPred < mp4_DC_vlc_Threshold[pInfo->VisualObject.VideoObject.VideoObjectPlane.intra_dc_vlc_thr]) ? 1 : 0;
+ if (ippiDecodeCoeffsIntraRVLCBack_MPEG4_1u16s(&pInfo->bufptr, &pInfo->bitoff, pDCTdp[j*64*6], &lnz, dcVLC) != ippStsNoErr)
+ break;
+ }
+ pInfo->bufptr = sBufptr;
+ pInfo->bitoff = sBitoff;
+ }
+ goto ErrRet_2;
+#endif
+ }
+// decode not data partitioned I-VOP
+ else {
+ int32_t stepY = stepYc, dct_type = 0, pYoff23 = 8 * stepYc;
+ for (;;) {
+ // reset Intra prediction buffer on new Video_packet
+ mp4_ResetIntraPredBuffer(pInfo);
+ mbInVideoPacket = 0;
+ // decode blocks
+ for (;;) {
+ if (colNum == 0) {
+ // reset B-prediction blocks on new row
+ mp4_ResetIntraPredBblock(pInfo);
+ }
+ if (mp4_DecodeMCBPC_I(pInfo, &mb_type, &cbpc) != MP4_STATUS_OK)
+ goto Err_3;
+ if (mb_type != IPPVC_MB_STUFFING) {
+ ac_pred_flag = mp4_GetBit(pInfo);
+ if (mp4_DecodeCBPY_I(pInfo, &cbpy) != MP4_STATUS_OK)
+ goto Err_3;
+ quantPred = quant;
+ if (mb_type == IPPVC_MBTYPE_INTRA_Q)
+ mp4_UpdateQuant(pInfo, quant);
+ if (mbInVideoPacket == 0)
+ quantPred = quant;
+ dcVLC = (quantPred < mp4_DC_vlc_Threshold[pInfo->VisualObject.VideoObject.VideoObjectPlane.intra_dc_vlc_thr]) ? 1 : 0;
+ if (pInfo->VisualObject.VideoObject.interlaced) {
+ dct_type = mp4_GetBit(pInfo);
+ if (dct_type) {
+ stepY = stepYc * 2;
+ pYoff23 = stepYc;
+ } else {
+ stepY = stepYc;
+ pYoff23 = 8 * stepYc;
+ }
+ stepFc[0] = stepFc[1] = stepFc[2] = stepFc[3] = stepY;
+ }
+ pFc[2] = pFc[0] + pYoff23; pFc[3] = pFc[1] + pYoff23;
+ if (mp4_DecodeIntraMB(pInfo, colNum, (cbpy << 2) + cbpc, quant, dcVLC, ac_pred_flag, pFc, stepFc) != MP4_STATUS_OK)
+ goto Err_3;
+ mbInVideoPacket ++;
+ colNum ++;
+ if (colNum == mbPerRow) {
+ colNum = 0;
+ rowNum ++;
+ if (rowNum == mbPerCol) {
+ // skip stuffing
+ while (mp4_ShowBits9(pInfo, 9) == 1)
+ mp4_FlushBits(pInfo, 9);
+ return sts;
+ }
+ pFc[0] += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc;
+ pFc[1] += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc;
+ pFc[4] += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbc << 3) - stepCbc;
+ pFc[5] += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrc << 3) - stepCrc;
+ } else {
+ pFc[0] += 16; pFc[1] += 16; pFc[4] += 8; pFc[5] += 8;
+ }
+ }
+ if (!pInfo->VisualObject.VideoObject.resync_marker_disable)
+ {
+ int32_t found;
+ErrRet_3:
+ if (mp4_CheckDecodeVideoPacket(pInfo, &found) == MP4_STATUS_OK)
+ {
+ if (found)
+ {
+ quant = pInfo->VisualObject.VideoObject.VideoObjectPlane.quant_scale;
+ mbCurr = pInfo->VisualObject.VideoObject.VideoObjectPlane.macroblock_num;
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, mbCurr - rowNum * mbPerRow - colNum);
+ rowNum = mbCurr / mbPerRow;
+ colNum = mbCurr % mbPerRow;
+ pFc[0] = pInfo->VisualObject.cFrame->pY + (rowNum * stepYc + colNum) * 16; pFc[1] = pFc[0] + 8;
+ pFc[4] = pInfo->VisualObject.cFrame->pCb + (rowNum * stepCbc + colNum) * 8; pFc[5] = pInfo->VisualObject.cFrame->pCr + (rowNum * stepCrc + colNum) * 8;
+ break;
+ }
+ }
+ else
+ goto Err_3;
+ }
+ }
+ }
+Err_3:
+ sts = MP4_STATUS_ERROR;
+ if (pInfo->stopOnErr)
+ return sts;
+ if (pInfo->VisualObject.VideoObject.resync_marker_disable || !mp4_SeekResyncMarker(pInfo))
+ {
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, pInfo->VisualObject.VideoObject.MacroBlockPerVOP - rowNum * mbPerRow - colNum);
+ return sts;
+ }
+ goto ErrRet_3;
+ }
+}
+
+
diff --git a/Src/mpeg4dec/mp4decvopp.c b/Src/mpeg4dec/mp4decvopp.c
new file mode 100644
index 000000000..10ec2c1d5
--- /dev/null
+++ b/Src/mpeg4dec/mp4decvopp.c
@@ -0,0 +1,1079 @@
+/* ///////////////////////////////////////////////////////////////////////
+//
+// INTEL CORPORATION PROPRIETARY INFORMATION
+// This software is supplied under the terms of a license agreement or
+// nondisclosure agreement with Intel Corporation and may not be copied
+// or disclosed except in accordance with the terms of that agreement.
+// Copyright (c) 2001-2008 Intel Corporation. All Rights Reserved.
+//
+// Description: Decodes P-VOPs
+//
+*/
+
+#include "mp4def.h"
+#include "mp4dec.h"
+
+/*
+// used for short_viseo_header
+*/
+/*static*/ mp4_Status mp4_PredictDecodeMV(mp4_Info *pInfo, mp4_MacroBlock *MBcurr, int32_t frGOB, int32_t y, int32_t x)
+{
+ IppMotionVector *mvLeft, *mvTop, *mvRight, *mvCurr;
+ int32_t mbInRow = pInfo->VisualObject.VideoObject.MacroBlockPerRow;
+
+ mvCurr = MBcurr[0].mv;
+ mvLeft = MBcurr[-1].mv;
+ mvTop = MBcurr[-mbInRow].mv;
+ mvRight = MBcurr[-mbInRow+1].mv;
+ if (y == frGOB && x == 0) {
+ mvCurr->dx = mvCurr->dy = 0;
+ } else if (x == 0) {
+ mvCurr->dx = mp4_Median(0, mvTop[0].dx, mvRight[0].dx);
+ mvCurr->dy = mp4_Median(0, mvTop[0].dy, mvRight[0].dy);
+ } else if (y == frGOB) {
+ MBcurr->mv[0] = mvLeft[0];
+ } else if (x == mbInRow - 1) {
+ mvCurr->dx = mp4_Median(0, mvLeft[0].dx, mvTop[0].dx);
+ mvCurr->dy = mp4_Median(0, mvLeft[0].dy, mvTop[0].dy);
+ } else {
+ mvCurr->dx = mp4_Median(mvLeft[0].dx, mvTop[0].dx, mvRight[0].dx);
+ mvCurr->dy = mp4_Median(mvLeft[0].dy, mvTop[0].dy, mvRight[0].dy);
+ }
+ return mp4_DecodeMV(pInfo, mvCurr, 1);
+}
+
+/*
+// decode MPEG-4 PVOP
+*/
+mp4_Status mp4_DecodeVOP_P(mp4_Info* pInfo)
+{
+ __ALIGN16(int16_t, coeffMB, 64*6);
+ int32_t stepYr, stepYc, stepCbr, stepCbc, stepCrr, stepCrc, stepFc[6];
+ int32_t i, j, nmb, nmbgob, dx, dy, mbCurr, mbInVideoPacket, colNum, rowNum, mbPerRow, mbPerCol;
+ uint8_t *pYr, *pCbr, *pCrr;
+ uint8_t *pYc, *pCbc, *pCrc, *pFc[6];
+ int32_t mb_not_coded, mb_type, cbpc, cbpy, ac_pred_flag, cbpyPrev;
+ int32_t dcVLC, quant, quantPred, rvlc, scan, obmc_disable, rt, quarter_sample;
+ IppiRect limitRectL, limitRectC;
+ IppMotionVector mvCur[4], mvPrev[4], mvTmp[4], mvCbCr;
+ mp4_MacroBlock *pMBinfo;
+ mp4_Status sts;
+#ifdef USE_NOTCODED_STATE
+ uint8_t *ncState = pInfo->VisualObject.VideoObject.ncState;
+#endif
+ if (!pInfo->VisualObject.cFrame)
+ pInfo->VisualObject.cFrame = CreateFrame(&pInfo->VisualObject);
+ mbPerRow = pInfo->VisualObject.VideoObject.MacroBlockPerRow;
+ mbPerCol = pInfo->VisualObject.VideoObject.MacroBlockPerCol;
+
+ stepYc = pInfo->VisualObject.cFrame->stepY;
+ stepYr = pInfo->VisualObject.rFrame->stepY;
+ stepCbc = pInfo->VisualObject.cFrame->stepCb;
+ stepCbr = pInfo->VisualObject.rFrame->stepCb;
+ stepCrc = pInfo->VisualObject.cFrame->stepCr;
+ stepCrr = pInfo->VisualObject.rFrame->stepCr;
+ pYc = pInfo->VisualObject.cFrame->pY;
+ pCbc = pInfo->VisualObject.cFrame->pCb;
+ pCrc = pInfo->VisualObject.cFrame->pCr;
+ pYr = pInfo->VisualObject.rFrame->pY;
+ pCbr = pInfo->VisualObject.rFrame->pCb;
+ pCrr = pInfo->VisualObject.rFrame->pCr;
+ stepFc[0] = stepFc[1] = stepFc[2] = stepFc[3] = stepYc; stepFc[4] = stepCbc; stepFc[5] = stepCrc;
+ // Bounding rectangle for MV limitation
+ limitRectL.x = - 16 * MP4_NUM_EXT_MB;
+ limitRectL.y = - 16 * MP4_NUM_EXT_MB;
+ limitRectL.width = pInfo->VisualObject.VideoObject.width + 16 * 2 * MP4_NUM_EXT_MB;
+ limitRectL.height = pInfo->VisualObject.VideoObject.height + 16 * 2 * MP4_NUM_EXT_MB;
+ pMBinfo = pInfo->VisualObject.VideoObject.MBinfo;
+ // warning "variable may be used without having been initialized"
+ cbpc = cbpy = mb_type = 0;
+ nmb = pInfo->VisualObject.VideoObject.MacroBlockPerVOP;
+ mbCurr = colNum = rowNum = 0;
+ sts = MP4_STATUS_OK;
+ // decode short_video_header P-VOP
+ if (pInfo->VisualObject.VideoObject.short_video_header)
+ {
+ int32_t frGOB;
+ IppMotionVector mvCur;
+
+ quant = pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.vop_quant;
+ nmbgob = 0;
+ pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.gob_number = 0;
+ frGOB = 0;
+ for (;;)
+ {
+ do
+ {
+ mb_not_coded = mp4_GetBit(pInfo);
+ if (mb_not_coded)
+ break;
+ if (mp4_DecodeMCBPC_P(pInfo, &mb_type, &cbpc, 1) != MP4_STATUS_OK)
+ goto Err_1;
+ } while (mb_type == IPPVC_MB_STUFFING);
+ if (mb_not_coded)
+ {
+#ifdef USE_NOTCODED_STATE
+ if (!(*ncState))
+ {
+ *ncState = 1;
+#endif
+ ippiCopy16x16_8u_C1R(pYr, stepYr, pYc, stepYc);
+ ippiCopy8x8_8u_C1R(pCbr, stepCbr, pCbc, stepCbc);
+ ippiCopy8x8_8u_C1R(pCrr, stepCrr, pCrc, stepCrc);
+#ifdef USE_NOTCODED_STATE
+ }
+#endif
+ pMBinfo->mv[0].dx = pMBinfo->mv[0].dy = 0;
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_NOTCODED);
+ }
+ else
+ {
+#ifdef USE_NOTCODED_STATE
+ // clear not_coded MB state
+ *ncState = 0;
+#endif
+ if (mb_type == IPPVC_MBTYPE_INTER4V || mb_type == IPPVC_MBTYPE_INTER4V_Q)
+ {
+ mp4_Error("Error: 4MV shall not be used for short_video_header");
+ goto Err_1;
+ }
+ if (mp4_DecodeCBPY_P(pInfo, &cbpy, mb_type) != MP4_STATUS_OK)
+ goto Err_1;
+ if (mb_type == IPPVC_MBTYPE_INTER_Q || mb_type == IPPVC_MBTYPE_INTRA_Q)
+ mp4_UpdateQuant(pInfo, quant);
+ if (mb_type >= IPPVC_MBTYPE_INTRA)
+ {
+ pFc[0] = pYc; pFc[1] = pYc + 8; pFc[2] = pYc + 8 * stepYc; pFc[3] = pYc + 8 * stepYc + 8; pFc[4] = pCbc; pFc[5] = pCrc;
+ if (mp4_DecodeIntraMB_SVH(pInfo, (cbpy << 2) + cbpc, quant, pFc, stepFc) != MP4_STATUS_OK)
+ goto Err_1;
+ pMBinfo->mv[0].dx = pMBinfo->mv[0].dy = 0;
+ }
+ else
+ {
+ if (mp4_PredictDecodeMV(pInfo, pMBinfo, frGOB, rowNum, colNum) != MP4_STATUS_OK)
+ goto Err_1;
+ mp4_LimitMV(&pMBinfo->mv[0], &mvCur, &limitRectL, colNum * 16, rowNum * 16, 16);
+ mp4_ComputeChromaMV(&mvCur, &mvCbCr);
+
+ // decode and MC blocks
+ if (cbpy)
+ {
+ mp4_DecodeMCInterBlock_SVH(pInfo, quant, cbpy & 8, pYr, pYc, stepYr, coeffMB, &mvCur, Err_1);
+ mp4_DecodeMCInterBlock_SVH(pInfo, quant, cbpy & 4, pYr+8, pYc+8, stepYr, coeffMB, &mvCur, Err_1);
+ mp4_DecodeMCInterBlock_SVH(pInfo, quant, cbpy & 2, pYr+stepYr*8, pYc+stepYc*8, stepYr, coeffMB, &mvCur, Err_1);
+ mp4_DecodeMCInterBlock_SVH(pInfo, quant, cbpy & 1, pYr+8+stepYr*8, pYc+8+stepYc*8, stepYr, coeffMB, &mvCur, Err_1);
+ }
+ else
+ {
+ mp4_Copy16x16HP_8u(pYr, stepYr, pYc, stepYc, &mvCur, 0);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ }
+ mp4_DecodeMCInterBlock_SVH(pInfo, quant, cbpc & 2, pCbr, pCbc, stepCbr, coeffMB, &mvCbCr, Err_1);
+ mp4_DecodeMCInterBlock_SVH(pInfo, quant, cbpc & 1, pCrr, pCrc, stepCrr, coeffMB, &mvCbCr, Err_1);
+ }
+ }
+ pMBinfo ++;
+#ifdef USE_NOTCODED_STATE
+ ncState ++;
+#endif
+ colNum ++;
+ if (colNum == mbPerRow)
+ {
+ colNum = 0;
+ rowNum ++;
+ if (rowNum == mbPerCol)
+ break;
+ pYc += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc;
+ pCbc += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbc << 3) - stepCbc;
+ pCrc += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrc << 3) - stepCrc;
+ pYr += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYr << 4) - stepYr;
+ pCbr += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbr << 3) - stepCbr;
+ pCrr += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrr << 3) - stepCrr;
+ }
+ else
+ {
+ pYc += 16; pCrc += 8; pCbc += 8;
+ pYr += 16; pCrr += 8; pCbr += 8;
+ }
+ nmbgob ++;
+ if (nmbgob == pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.num_macroblocks_in_gob && pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.gob_number < (pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.num_gobs_in_vop - 1))
+ {
+ErrRet_1:
+ if (mp4_CheckDecodeGOB_SVH(pInfo) != MP4_STATUS_OK)
+ goto Err_1;
+ if (!pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.gob_header_empty)
+ {
+ quant = pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.quant_scale;
+ i = pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.gob_number * pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.num_rows_in_gob;
+ frGOB = i;
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, (i - rowNum) * mbPerRow - colNum);
+ rowNum = i;
+ colNum = 0;
+ pYc = pInfo->VisualObject.cFrame->pY + i * stepYc * 16; pCbc = pInfo->VisualObject.cFrame->pCb + i * stepCbc * 8; pCrc = pInfo->VisualObject.cFrame->pCr + i * stepCrc * 8;
+ pYr = pInfo->VisualObject.rFrame->pY + i * stepYr * 16; pCbr = pInfo->VisualObject.rFrame->pCb + i * stepCbr * 8; pCrr = pInfo->VisualObject.rFrame->pCr + i * stepCrr * 8;
+ pMBinfo = pInfo->VisualObject.VideoObject.MBinfo + i * mbPerRow;
+#ifdef USE_NOTCODED_STATE
+ ncState = pInfo->VisualObject.VideoObject.ncState + i * mbPerRow;
+#endif
+ }
+ nmbgob = 0;
+ }
+ }
+ mp4_AlignBits(pInfo);
+ return sts;
+Err_1:
+ sts = MP4_STATUS_ERROR;
+ if (pInfo->stopOnErr)
+ return sts;
+ if (!mp4_SeekGOBMarker(pInfo))
+ {
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, pInfo->VisualObject.VideoObject.MacroBlockPerVOP - rowNum * mbPerRow - colNum);
+ return sts;
+ }
+ goto ErrRet_1;
+ }
+ rt = pInfo->VisualObject.VideoObject.VideoObjectPlane.rounding_type;
+ quarter_sample = pInfo->VisualObject.VideoObject.quarter_sample;
+ obmc_disable = pInfo->VisualObject.VideoObject.obmc_disable;
+ rvlc = pInfo->VisualObject.VideoObject.reversible_vlc;
+ scan = pInfo->VisualObject.VideoObject.VideoObjectPlane.alternate_vertical_scan_flag ? IPPVC_SCAN_VERTICAL : IPPVC_SCAN_ZIGZAG;
+ // Bounding rectangles for MV limitation
+ limitRectC.x = -8 * MP4_NUM_EXT_MB;
+ limitRectC.y = -8 * MP4_NUM_EXT_MB;
+ limitRectC.width = (pInfo->VisualObject.VideoObject.width >> 1) + 8 * 2 * MP4_NUM_EXT_MB;
+ limitRectC.height = (pInfo->VisualObject.VideoObject.height >> 1) + 8 * 2 * MP4_NUM_EXT_MB;
+ quant = quantPred = pInfo->VisualObject.VideoObject.VideoObjectPlane.quant;
+ // warning "variable may be used without having been initialized"
+ ac_pred_flag = cbpyPrev = 0;
+ mvCbCr.dx = mvCbCr.dy = 0;
+ //ippsZero_8u((uint8_t*)pInfo->VisualObject.VideoObject.MBinfo, nmb * sizeof(mp4_MacroBlock));
+ // decode data_partitioned P-VOP
+ if (pInfo->VisualObject.VideoObject.data_partitioned) {
+ for (;;) {
+ mp4_DataPartMacroBlock *pMBdp;
+ int32_t x, y;
+
+ x = colNum;
+ y = rowNum;
+ // reset Intra prediction buffer on new Video_packet
+ mp4_ResetIntraPredBuffer(pInfo);
+ pMBdp = &pInfo->VisualObject.VideoObject.DataPartBuff[mbCurr];
+ pMBinfo = &pInfo->VisualObject.VideoObject.MBinfo[mbCurr];
+ mbInVideoPacket = 0;
+ // decode not_coded/mb_type/cbpc/MV part
+ for (;;) {
+ mb_not_coded = mp4_GetBit(pInfo);
+ if (mb_not_coded) {
+ mb_type = IPPVC_MBTYPE_INTER;
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_NOTCODED);
+ } else {
+ if (mp4_DecodeMCBPC_P(pInfo, &mb_type, &cbpc, 1) != MP4_STATUS_OK)
+ goto Err_2;
+ }
+ if (mb_type != IPPVC_MB_STUFFING) {
+ if (mbInVideoPacket == nmb - mbCurr) {
+ mp4_Error("DC Marker missed");
+ goto Err_2;
+ }
+ pMBinfo->validPred = 1;
+ if (!mb_not_coded && (mb_type <= IPPVC_MBTYPE_INTER4V)) {
+ if (mb_type != IPPVC_MBTYPE_INTER4V) {
+ if (mp4_PredictDecode1MV(pInfo, pMBinfo, y, x) != MP4_STATUS_OK)
+ goto Err_2;
+ pMBinfo->mv[1] = pMBinfo->mv[2] = pMBinfo->mv[3] = pMBinfo->mv[0];
+ } else {
+ if (mp4_PredictDecode4MV(pInfo, pMBinfo, y, x) != MP4_STATUS_OK)
+ goto Err_2;
+ }
+ } else {
+ mp4_Zero4MV(pMBinfo->mv);
+ }
+ pMBinfo->not_coded = (uint8_t)mb_not_coded;
+ pMBinfo->type = (uint8_t)mb_type;
+ pMBinfo ++;
+ pMBdp->pat = (uint8_t)cbpc;
+ pMBdp ++;
+ mbInVideoPacket ++;
+ x ++;
+ if (x == mbPerRow) {
+ x = 0;
+ y ++;
+ }
+ }
+ if (mp4_ShowBits(pInfo, 17) == MP4_MV_MARKER) {
+ mp4_GetBits(pInfo, 17);
+ break;
+ }
+ }
+ pMBdp = &pInfo->VisualObject.VideoObject.DataPartBuff[mbCurr];
+ pMBinfo = &pInfo->VisualObject.VideoObject.MBinfo[mbCurr];
+ // decode ac_pred_flag/cbpy/dquant/IntraDC part
+ for (i = 0; i < mbInVideoPacket; i ++) {
+ if (!pMBinfo->not_coded) {
+ mb_type = pMBinfo->type;
+ if (mb_type >= IPPVC_MBTYPE_INTRA)
+ pMBdp->ac_pred_flag = (uint8_t)mp4_GetBit(pInfo);
+ if (mp4_DecodeCBPY_P(pInfo, &cbpy, mb_type) != MP4_STATUS_OK)
+ goto Err_2;
+ pMBdp->pat = (uint8_t)((cbpy << 2) + pMBdp->pat);
+ quantPred = quant;
+ if (mb_type == IPPVC_MBTYPE_INTER_Q || mb_type == IPPVC_MBTYPE_INTRA_Q)
+ mp4_UpdateQuant(pInfo, quant);
+ pMBdp->quant = (uint8_t)quant;
+ if (i == 0)
+ quantPred = quant;
+ // decode DC coefficient of Intra blocks
+ dcVLC = (quantPred < mp4_DC_vlc_Threshold[pInfo->VisualObject.VideoObject.VideoObjectPlane.intra_dc_vlc_thr]) ? 1 : 0;
+ if ((mb_type >= IPPVC_MBTYPE_INTRA) && dcVLC) {
+ for (j = 0; j < 6; j ++) {
+ if (ippiDecodeDCIntra_MPEG4_1u16s(&pInfo->bufptr, &pInfo->bitoff, &pMBdp->dct_dc[j], j < 4 ? IPPVC_BLOCK_LUMA : IPPVC_BLOCK_CHROMA) != ippStsNoErr)
+ goto Err_2;
+ }
+ }
+ }
+ pMBdp ++;
+ pMBinfo ++;
+ }
+ if (mbCurr + mbInVideoPacket < nmb)
+ pMBinfo->type = IPPVC_MBTYPE_INTRA; // for OBMC set first MB of the next videopacket as invalid for right MV
+ pMBdp = &pInfo->VisualObject.VideoObject.DataPartBuff[mbCurr];
+ pMBinfo = &pInfo->VisualObject.VideoObject.MBinfo[mbCurr];
+ // decode coeffs and reconstruct macroblocks
+ for (i = 0; i < mbInVideoPacket; i ++) {
+ if (colNum == 0) {
+ // reset B-prediction blocks on new row
+ mp4_ResetIntraPredBblock(pInfo);
+ }
+ quant = pMBdp->quant;
+ mb_type = pMBinfo->type;
+ if (mb_type >= IPPVC_MBTYPE_INTRA) {
+ quantPred = (i == 0) ? quant : pMBdp[-1].quant;
+ dcVLC = (quantPred < mp4_DC_vlc_Threshold[pInfo->VisualObject.VideoObject.VideoObjectPlane.intra_dc_vlc_thr]) ? 1 : 0;
+ pFc[0] = pYc; pFc[1] = pYc + 8; pFc[2] = pYc + 8 * stepYc; pFc[3] = pYc + 8 * stepYc + 8; pFc[4] = pCbc; pFc[5] = pCrc;
+ if (mp4_DecodeIntraMB_DP(pInfo, pMBdp->dct_dc, colNum, pMBdp->pat, quant, dcVLC, pMBdp->ac_pred_flag, pFc, stepFc) != MP4_STATUS_OK)
+ goto Err_2;
+ } else {
+ mp4_UpdateIntraPredBuffInvalid(pInfo, colNum);
+ mb_not_coded = pMBinfo->not_coded;
+ if (!mb_not_coded) {
+ dx = colNum * 16;
+ dy = rowNum * 16;
+ cbpy = pMBdp->pat >> 2;
+ cbpc = pMBdp->pat & 3;
+ if (mb_type == IPPVC_MBTYPE_INTER4V) {
+ if (quarter_sample) {
+ mp4_Limit4MVQ(pMBinfo->mv, mvCur, &limitRectL, dx, dy, 8);
+ mp4_ComputeChroma4MVQ(pMBinfo->mv, &mvCbCr);
+ } else {
+ mp4_Limit4MV(pMBinfo->mv, mvCur, &limitRectL, dx, dy, 8);
+ mp4_ComputeChroma4MV(pMBinfo->mv, &mvCbCr);
+ }
+ mp4_LimitMV(&mvCbCr, &mvCbCr, &limitRectC, dx >> 1, dy >> 1, 8);
+ } else {
+ if (quarter_sample) {
+ mp4_LimitMVQ(pMBinfo->mv, mvCur, &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMVQ(mvCur, &mvCbCr);
+ } else {
+ mp4_LimitMV(pMBinfo->mv, mvCur, &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMV(mvCur, &mvCbCr);
+ }
+ mvCur[1] = mvCur[2] = mvCur[3] = mvCur[0];
+ }
+ }
+ if (obmc_disable) {
+ if (mb_not_coded) {
+ ippiCopy16x16_8u_C1R(pYr, stepYr, pYc, stepYc);
+ ippiCopy8x8_8u_C1R(pCbr, stepCbr, pCbc, stepCbc);
+ ippiCopy8x8_8u_C1R(pCrr, stepCrr, pCrc, stepCrc);
+ } else {
+ if (quarter_sample) {
+ if (mb_type == IPPVC_MBTYPE_INTER4V) {
+ mp4_Copy8x8QP_8u(pYr, stepYr, pYc, stepYc, &mvCur[0], rt);
+ mp4_Copy8x8QP_8u(pYr+8, stepYr, pYc+8, stepYc, &mvCur[1], rt);
+ mp4_Copy8x8QP_8u(pYr+8*stepYr, stepYr, pYc+8*stepYc, stepYc, &mvCur[2], rt);
+ mp4_Copy8x8QP_8u(pYr+8*stepYr+8, stepYr, pYc+8*stepYc+8, stepYc, &mvCur[3], rt);
+ } else
+ mp4_Copy16x16QP_8u(pYr, stepYr, pYc, stepYc, &mvCur[0], rt);
+ mp4_DecodeReconBlockInter_MPEG4(cbpy & 8, pYc, stepYc, Err_2);
+ mp4_DecodeReconBlockInter_MPEG4(cbpy & 4, pYc+8, stepYc, Err_2);
+ mp4_DecodeReconBlockInter_MPEG4(cbpy & 2, pYc+8*stepYc, stepYc, Err_2);
+ mp4_DecodeReconBlockInter_MPEG4(cbpy & 1, pYc+8*stepYc+8, stepYc, Err_2);
+ } else {
+ if (cbpy || mb_type == IPPVC_MBTYPE_INTER4V) {
+ mp4_DecodeMCBlockInter_MPEG4(cbpy & 8, pYr, stepYr, pYc, stepYc, mvCur[0], rt, Err_2);
+ mp4_DecodeMCBlockInter_MPEG4(cbpy & 4, pYr+8, stepYr, pYc+8, stepYc, mvCur[1], rt, Err_2);
+ mp4_DecodeMCBlockInter_MPEG4(cbpy & 2, pYr+8*stepYr, stepYr, pYc+8*stepYc, stepYc, mvCur[2], rt, Err_2);
+ mp4_DecodeMCBlockInter_MPEG4(cbpy & 1, pYr+8*stepYr+8, stepYr, pYc+8*stepYc+8, stepYc, mvCur[3], rt, Err_2);
+ } else {
+ mp4_Copy16x16HP_8u(pYr, stepYr, pYc, stepYc, &mvCur[0], rt);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ }
+ }
+ mp4_DecodeMCBlockInter_MPEG4(cbpc & 2, pCbr, stepCbr, pCbc, stepCbc, mvCbCr, rt, Err_2);
+ mp4_DecodeMCBlockInter_MPEG4(cbpc & 1, pCrr, stepCrr, pCrc, stepCrc, mvCbCr, rt, Err_2);
+ }
+ } else {
+ if (mb_not_coded) {
+ cbpy = 0;
+ mp4_Zero4MV(mvCur);
+ ippiCopy8x8_8u_C1R(pCbr, stepCbr, pCbc, stepCbc);
+ ippiCopy8x8_8u_C1R(pCrr, stepCrr, pCrc, stepCrc);
+ } else {
+ if (mp4_DecodeInterMB(pInfo, coeffMB, quant, (cbpy << 2) + cbpc, scan) != MP4_STATUS_OK)
+ goto Err_2;
+ mp4_MC_HP(cbpc & 2, pCbr, stepCbr, pCbc, stepCbc, coeffMB+256, &mvCbCr, rt);
+ mp4_MC_HP(cbpc & 1, pCrr, stepCrr, pCrc, stepCrc, coeffMB+320, &mvCbCr, rt);
+ }
+ mp4_OBMC(pInfo, pMBinfo, mvCur, colNum, rowNum, limitRectL, pYc, stepYc, pYr, stepYr, cbpy, coeffMB, 0);
+ }
+ }
+ pMBinfo ++;
+ pMBdp ++;
+ colNum ++;
+ if (colNum == mbPerRow) {
+ colNum = 0;
+ rowNum ++;
+ if (rowNum == mbPerCol)
+ return sts;
+ pYc += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc;
+ pCbc += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbc << 3) - stepCbc;
+ pCrc += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrc << 3) - stepCrc;
+ pYr += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYr << 4) - stepYr;
+ pCbr += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbr << 3) - stepCbr;
+ pCrr += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrr << 3) - stepCrr;
+ }
+ else
+ {
+ pYc += 16; pCrc += 8; pCbc += 8;
+ pYr += 16; pCrr += 8; pCbr += 8;
+ }
+ }
+ //mbCurr += mbInVideoPacket;
+ if (!pInfo->VisualObject.VideoObject.resync_marker_disable)
+ {
+ int32_t found;
+ErrRet_2:
+ if (mp4_CheckDecodeVideoPacket(pInfo, &found) == MP4_STATUS_OK)
+ {
+ if (found)
+ {
+ quant = pInfo->VisualObject.VideoObject.VideoObjectPlane.quant_scale;
+ mbInVideoPacket = pInfo->VisualObject.VideoObject.VideoObjectPlane.macroblock_num - mbCurr;
+ mbCurr = pInfo->VisualObject.VideoObject.VideoObjectPlane.macroblock_num;
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, mbCurr - rowNum * mbPerRow - colNum);
+ rowNum = mbCurr / mbPerRow;
+ colNum = mbCurr % mbPerRow;
+ pYc = pInfo->VisualObject.cFrame->pY + (rowNum * stepYc + colNum) * 16; pCbc = pInfo->VisualObject.cFrame->pCb + (rowNum * stepCbc + colNum) * 8; pCrc = pInfo->VisualObject.cFrame->pCr + (rowNum * stepCrc + colNum) * 8;
+ pYr = pInfo->VisualObject.rFrame->pY + (rowNum * stepYr + colNum) * 16; pCbr = pInfo->VisualObject.rFrame->pCb + (rowNum * stepCbr + colNum) * 8; pCrr = pInfo->VisualObject.rFrame->pCr + (rowNum * stepCrr + colNum) * 8;
+ pMBinfo = pInfo->VisualObject.VideoObject.MBinfo + mbCurr;
+ }
+ else
+ goto Err_2;
+ }
+ else
+ goto Err_2;
+ }
+ // mark MBs the previous videopacket as invalid for prediction
+ for (i = 1; i <= IPP_MIN(mbInVideoPacket, mbPerRow + 1); i ++)
+ pMBinfo[-i].validPred = 0;
+ }
+Err_2:
+ sts = MP4_STATUS_ERROR;
+ if (pInfo->stopOnErr)
+ return sts;
+ if (pInfo->VisualObject.VideoObject.resync_marker_disable || !mp4_SeekResyncMarker(pInfo))
+ {
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, pInfo->VisualObject.VideoObject.MacroBlockPerVOP - rowNum * mbPerRow - colNum);
+ return sts;
+ }
+ goto ErrRet_2;
+ }
+ // decode interlaced P-VOP
+ if (pInfo->VisualObject.VideoObject.interlaced)
+ {
+ int32_t stepY, pYoff23, field_prediction, dct_type, dct_typePrev, mb_ftfr, mb_fbfr;
+ IppMotionVector mvCbCrT, mvCbCrB, *mvField = pInfo->VisualObject.VideoObject.FieldMV;
+
+ // warning "variable may be used without having been initialized"
+ dct_type = dct_typePrev = mb_ftfr = mb_fbfr = 0;
+ mvCbCrT.dx = mvCbCrT.dy = mvCbCrB.dx = mvCbCrB.dy = 0;
+ for (;;) {
+ // reset Intra prediction buffer on new Video_packet
+ mp4_ResetIntraPredBuffer(pInfo);
+ mbInVideoPacket = 0;
+ // decode blocks
+ for (;;)
+ {
+ if (colNum == 0)
+ {
+ // reset B-prediction blocks on new row
+ mp4_ResetIntraPredBblock(pInfo);
+ }
+ mb_not_coded = mp4_GetBit(pInfo);
+ mb_type = IPPVC_MBTYPE_INTER;
+ if (!mb_not_coded)
+ {
+ if (mp4_DecodeMCBPC_P(pInfo, &mb_type, &cbpc, 1) != MP4_STATUS_OK)
+ goto Err_3;
+ }
+ if (mb_type != IPPVC_MB_STUFFING)
+ {
+ if (!mb_not_coded)
+ {
+ if (mb_type >= IPPVC_MBTYPE_INTRA)
+ ac_pred_flag = mp4_GetBit(pInfo);
+ if (mp4_DecodeCBPY_P(pInfo, &cbpy, mb_type) != MP4_STATUS_OK)
+ goto Err_3;
+ quantPred = quant;
+ if (mb_type == IPPVC_MBTYPE_INTER_Q || mb_type == IPPVC_MBTYPE_INTRA_Q)
+ mp4_UpdateQuant(pInfo, quant);
+ dct_type = 0;
+ field_prediction = 0;
+ if (mb_type >= IPPVC_MBTYPE_INTRA || (cbpy + cbpc) != 0)
+ dct_type = mp4_GetBit(pInfo);
+ if (mb_type == IPPVC_MBTYPE_INTER || mb_type == IPPVC_MBTYPE_INTER_Q) {
+ field_prediction = mp4_GetBit(pInfo);
+ if (field_prediction) {
+ mb_ftfr = mp4_GetBit(pInfo);
+ mb_fbfr = mp4_GetBit(pInfo);
+ }
+ }
+ }
+ else
+ {
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_NOTCODED);
+ mp4_Zero4MV(pMBinfo->mv);
+ field_prediction = 0;
+ }
+ pMBinfo->validPred = 1;
+ pMBinfo->not_coded = (uint8_t)mb_not_coded;
+ pMBinfo->type = (uint8_t)mb_type;
+ pMBinfo->field_info = (uint8_t)(field_prediction + (mb_ftfr << 1) + (mb_fbfr << 2));
+ if (mb_type >= IPPVC_MBTYPE_INTRA)
+ {
+ if (mbInVideoPacket == 0)
+ quantPred = quant;
+ dcVLC = (quantPred < mp4_DC_vlc_Threshold[pInfo->VisualObject.VideoObject.VideoObjectPlane.intra_dc_vlc_thr]) ? 1 : 0;
+ if (dct_type)
+ {
+ stepY = stepYc * 2;
+ pYoff23 = stepYc;
+ }
+ else
+ {
+ stepY = stepYc;
+ pYoff23 = 8 * stepYc;
+ }
+ stepFc[0] = stepFc[1] = stepFc[2] = stepFc[3] = stepY;
+ pFc[0] = pYc; pFc[1] = pYc + 8; pFc[2] = pYc + pYoff23; pFc[3] = pYc + pYoff23 + 8; pFc[4] = pCbc; pFc[5] = pCrc;
+ if (mp4_DecodeIntraMB(pInfo, colNum, (cbpy << 2) + cbpc, quant, dcVLC, ac_pred_flag, pFc, stepFc) != MP4_STATUS_OK)
+ goto Err_3;
+ mp4_Zero4MV(pMBinfo->mv);
+#ifdef USE_NOTCODED_STATE
+ // clear not_coded MB state
+ *ncState = 0;
+#endif
+ }
+ else
+ {
+ mp4_UpdateIntraPredBuffInvalid(pInfo, colNum);
+ if (!mb_not_coded)
+ {
+ dx = colNum * 16;
+ dy = rowNum * 16;
+ if (!field_prediction)
+ {
+ if (mb_type != IPPVC_MBTYPE_INTER4V)
+ {
+ if (mp4_PredictDecode1MV(pInfo, pMBinfo, rowNum, colNum) != MP4_STATUS_OK)
+ goto Err_3;
+ pMBinfo->mv[1] = pMBinfo->mv[2] = pMBinfo->mv[3] = pMBinfo->mv[0];
+ if (quarter_sample)
+ {
+ mp4_LimitMVQ(pMBinfo->mv, mvCur, &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMVQ(mvCur, &mvCbCr);
+ }
+ else
+ {
+ mp4_LimitMV(pMBinfo->mv, mvCur, &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMV(mvCur, &mvCbCr);
+ }
+ mvCur[1] = mvCur[2] = mvCur[3] = mvCur[0];
+ }
+ else
+ {
+ if (mp4_PredictDecode4MV(pInfo, pMBinfo, rowNum, colNum) != MP4_STATUS_OK)
+ goto Err_3;
+ if (quarter_sample)
+ {
+ mp4_Limit4MVQ(pMBinfo->mv, mvCur, &limitRectL, dx, dy, 8);
+ mp4_ComputeChroma4MVQ(pMBinfo->mv, &mvCbCr);
+ }
+ else
+ {
+ mp4_Limit4MV(pMBinfo->mv, mvCur, &limitRectL, dx, dy, 8);
+ mp4_ComputeChroma4MV(pMBinfo->mv, &mvCbCr);
+ }
+ mp4_LimitMV(&mvCbCr, &mvCbCr, &limitRectC, dx >> 1, dy >> 1, 8);
+ }
+ }
+ else
+ {
+ IppMotionVector mvFT, mvFB;
+ if (mp4_PredictDecodeFMV(pInfo, pMBinfo, rowNum, colNum, &mvFT, &mvFB) != MP4_STATUS_OK)
+ goto Err_3;
+ mvField[0] = mvFT; mvField[1] = mvFB;
+ if (quarter_sample)
+ {
+ mp4_LimitFMVQ(&mvFT, &mvCur[0], &limitRectL, dx, dy, 16);
+ mp4_LimitFMVQ(&mvFB, &mvCur[2], &limitRectL, dx, dy, 16);
+ mvTmp[0].dx = (int16_t)mp4_Div2(mvCur[0].dx);
+ mvTmp[0].dy = (int16_t)(mp4_Div2(mvCur[0].dy << 1) >> 1);
+ mvTmp[2].dx = (int16_t)mp4_Div2(mvCur[2].dx);
+ mvTmp[2].dy = (int16_t)(mp4_Div2(mvCur[2].dy << 1) >> 1);
+ mp4_ComputeChromaMV(&mvTmp[0], &mvCbCrT);
+ mp4_ComputeChromaMV(&mvTmp[2], &mvCbCrB);
+ }
+ else
+ {
+ mp4_LimitFMV(&mvFT, &mvCur[0], &limitRectL, dx, dy, 16);
+ mp4_LimitFMV(&mvFB, &mvCur[2], &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMV(&mvCur[0], &mvCbCrT);
+ mp4_ComputeChromaMV(&mvCur[2], &mvCbCrB);
+ }
+ }
+ }
+ }
+ if (!obmc_disable)
+ {
+ // OBMC for previous MB
+ if (colNum > 0)
+ if (pMBinfo[-1].type < IPPVC_MBTYPE_INTRA && !(pMBinfo[-1].field_info & 1))
+ mp4_OBMC(pInfo, pMBinfo - 1, mvPrev, colNum - 1, rowNum, limitRectL, pYc - 16, stepYc, pYr - 16, stepYr, cbpyPrev, coeffMB, dct_typePrev);
+ if (mb_type < IPPVC_MBTYPE_INTRA && !field_prediction)
+ {
+ if (mb_not_coded)
+ {
+ cbpyPrev = 0;
+ mp4_Zero4MV(mvPrev);
+ ippiCopy8x8_8u_C1R(pCbr, stepCbr, pCbc, stepCbc);
+ ippiCopy8x8_8u_C1R(pCrr, stepCrr, pCrc, stepCrc);
+ }
+ else
+ {
+ cbpyPrev = cbpy;
+ dct_typePrev = dct_type;
+ mvPrev[0] = mvCur[0]; mvPrev[1] = mvCur[1]; mvPrev[2] = mvCur[2]; mvPrev[3] = mvCur[3];
+ if (mp4_DecodeInterMB(pInfo, coeffMB, quant, (cbpy << 2) + cbpc, scan) != MP4_STATUS_OK)
+ goto Err_3;
+ mp4_MC_HP(cbpc & 2, pCbr, stepCbr, pCbc, stepCbc, coeffMB+256, &mvCbCr, rt);
+ mp4_MC_HP(cbpc & 1, pCrr, stepCrr, pCrc, stepCrc, coeffMB+320, &mvCbCr, rt);
+ }
+ // OBMC current MB if it is the last in the row
+ if (colNum == mbPerRow - 1)
+ mp4_OBMC(pInfo, pMBinfo, mvPrev, colNum, rowNum, limitRectL, pYc, stepYc, pYr, stepYr, cbpyPrev, coeffMB, dct_typePrev);
+ }
+ }
+ if (mb_type < IPPVC_MBTYPE_INTRA && (obmc_disable || field_prediction))
+ {
+ if (mb_not_coded)
+ {
+#ifdef USE_NOTCODED_STATE
+ if (!(*ncState))
+ {
+ *ncState = 1;
+#endif
+ ippiCopy16x16_8u_C1R(pYr, stepYr, pYc, stepYc);
+ ippiCopy8x8_8u_C1R(pCbr, stepCbr, pCbc, stepCbc);
+ ippiCopy8x8_8u_C1R(pCrr, stepCrr, pCrc, stepCrc);
+#ifdef USE_NOTCODED_STATE
+ }
+#endif
+ }
+ else
+ {
+#ifdef USE_NOTCODED_STATE
+ // clear not_coded MB state
+ *ncState = 0;
+#endif
+ if (mp4_DecodeInterMB(pInfo, coeffMB, quant, (cbpy << 2) + cbpc, scan) != MP4_STATUS_OK)
+ goto Err_3;
+ if (quarter_sample)
+ {
+ if (!field_prediction)
+ {
+ if (mb_type == IPPVC_MBTYPE_INTER4V)
+ {
+ mp4_Copy8x8QP_8u(pYr, stepYr, pYc, stepYc, &mvCur[0], rt);
+ mp4_Copy8x8QP_8u(pYr+8, stepYr, pYc+8, stepYc, &mvCur[1], rt);
+ mp4_Copy8x8QP_8u(pYr+stepYr*8, stepYr, pYc+stepYc*8, stepYc, &mvCur[2], rt);
+ mp4_Copy8x8QP_8u(pYr+8+stepYr*8, stepYr, pYc+8+stepYc*8, stepYc, &mvCur[3], rt);
+ }
+ else
+ mp4_Copy16x16QP_8u(pYr, stepYr, pYc, stepYc, &mvCur[0], rt);
+ }
+ else
+ {
+ mp4_Copy16x8QP_8u(pYr+stepYr*mb_ftfr, stepYr*2, pYc, stepYc*2, &mvCur[0], rt);
+ mp4_Copy16x8QP_8u(pYr+stepYr*mb_fbfr, stepYr*2, pYc+stepYc, stepYc*2, &mvCur[2], rt);
+ }
+ }
+ else
+ {
+ if (!field_prediction)
+ {
+ if (mb_type == IPPVC_MBTYPE_INTER4V)
+ {
+ mp4_Copy8x8HP_8u(pYr, stepYr, pYc, stepYc, &mvCur[0], rt);
+ mp4_Copy8x8HP_8u(pYr+8, stepYr, pYc+8, stepYc, &mvCur[1], rt);
+ mp4_Copy8x8HP_8u(pYr+stepYr*8, stepYr, pYc+stepYc*8, stepYc, &mvCur[2], rt);
+ mp4_Copy8x8HP_8u(pYr+8+stepYr*8, stepYr, pYc+8+stepYc*8, stepYc, &mvCur[3], rt);
+ }
+ else
+ {
+ mp4_Copy16x16HP_8u(pYr, stepYr, pYc, stepYc, &mvCur[0], rt);
+ }
+ }
+ else
+ {
+ mp4_Copy16x8HP_8u(pYr+stepYr*mb_ftfr, stepYr*2, pYc, stepYc*2, &mvCur[0], rt);
+ mp4_Copy16x8HP_8u(pYr+stepYr*mb_fbfr, stepYr*2, pYc+stepYc, stepYc*2, &mvCur[2], rt);
+ }
+ }
+ if (!dct_type)
+ {
+ mp4_AddResidual(cbpy & 8, pYc, stepYc, coeffMB);
+ mp4_AddResidual(cbpy & 4, pYc+8, stepYc, coeffMB+64);
+ mp4_AddResidual(cbpy & 2, pYc+stepYc*8, stepYc, coeffMB+128);
+ mp4_AddResidual(cbpy & 1, pYc+stepYc*8+8, stepYc, coeffMB+192);
+ } else {
+ mp4_AddResidual(cbpy & 8, pYc, stepYc*2, coeffMB);
+ mp4_AddResidual(cbpy & 4, pYc+8, stepYc*2, coeffMB+64);
+ mp4_AddResidual(cbpy & 2, pYc+stepYc, stepYc*2, coeffMB+128);
+ mp4_AddResidual(cbpy & 1, pYc+stepYc+8, stepYc*2, coeffMB+192);
+ }
+ if (!field_prediction) {
+ mp4_MC_HP(cbpc & 2, pCbr, stepCbr, pCbc, stepCbc, coeffMB+256, &mvCbCr, rt);
+ mp4_MC_HP(cbpc & 1, pCrr, stepCrr, pCrc, stepCrc, coeffMB+320, &mvCbCr, rt);
+ } else {
+ mp4_Copy8x4HP_8u(pCbr+(mb_ftfr ? stepCbr : 0), stepCbr*2, pCbc, stepCbc*2, &mvCbCrT, rt);
+ mp4_Copy8x4HP_8u(pCrr+(mb_ftfr ? stepCrr : 0), stepCrr*2, pCrc, stepCrc*2, &mvCbCrT, rt);
+ mp4_Copy8x4HP_8u(pCbr+(mb_fbfr ? stepCbr : 0), stepCbr*2, pCbc+stepCbc, stepCbc*2, &mvCbCrB, rt);
+ mp4_Copy8x4HP_8u(pCrr+(mb_fbfr ? stepCrr : 0), stepCrr*2, pCrc+stepCrc, stepCrc*2, &mvCbCrB, rt);
+ mp4_AddResidual(cbpc & 2, pCbc, stepCbc, coeffMB+256);
+ mp4_AddResidual(cbpc & 1, pCrc, stepCrc, coeffMB+320);
+ }
+ }
+ }
+#ifdef USE_NOTCODED_STATE
+ ncState ++;
+#endif
+ pMBinfo ++;
+ mvField += 2;
+ mbInVideoPacket ++;
+ colNum ++;
+ if (colNum == mbPerRow) {
+ colNum = 0;
+ rowNum ++;
+ if (rowNum == mbPerCol) {
+ // skip stuffing
+ while (mp4_ShowBits(pInfo, 10) == 1)
+ mp4_FlushBits(pInfo, 10);
+ return sts;
+ }
+ pYc += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc;
+ pCbc += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbc << 3) - stepCbc;
+ pCrc += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrc << 3) - stepCrc;
+ pYr += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYr << 4) - stepYr;
+ pCbr += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbr << 3) - stepCbr;
+ pCrr += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrr << 3) - stepCrr;
+ } else {
+ pYc += 16; pCrc += 8; pCbc += 8;
+ pYr += 16; pCrr += 8; pCbr += 8;
+ }
+ }
+ if (!pInfo->VisualObject.VideoObject.resync_marker_disable) {
+ int32_t found;
+ErrRet_3:
+ if (mp4_CheckDecodeVideoPacket(pInfo, &found) == MP4_STATUS_OK) {
+ if (found) {
+ mbInVideoPacket = pInfo->VisualObject.VideoObject.VideoObjectPlane.macroblock_num - mbCurr;
+ quant = pInfo->VisualObject.VideoObject.VideoObjectPlane.quant_scale;
+ mbCurr = pInfo->VisualObject.VideoObject.VideoObjectPlane.macroblock_num;
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, mbCurr - rowNum * mbPerRow - colNum);
+ rowNum = mbCurr / mbPerRow;
+ colNum = mbCurr % mbPerRow;
+ pYc = pInfo->VisualObject.cFrame->pY + (rowNum * stepYc + colNum) * 16; pCbc = pInfo->VisualObject.cFrame->pCb + (rowNum * stepCbc + colNum) * 8; pCrc = pInfo->VisualObject.cFrame->pCr + (rowNum * stepCrc + colNum) * 8;
+ pYr = pInfo->VisualObject.rFrame->pY + (rowNum * stepYr + colNum) * 16; pCbr = pInfo->VisualObject.rFrame->pCb + (rowNum * stepCbr + colNum) * 8; pCrr = pInfo->VisualObject.rFrame->pCr + (rowNum * stepCrr + colNum) * 8;
+ pMBinfo = pInfo->VisualObject.VideoObject.MBinfo + mbCurr;
+#ifdef USE_NOTCODED_STATE
+ ncState = pInfo->VisualObject.VideoObject.ncState + mbCurr;
+#endif
+ mvField = pInfo->VisualObject.VideoObject.FieldMV + 2 * mbCurr;
+ break;
+ }
+ } else
+ goto Err_3;
+ }
+ }
+ // mark MBs the previous videopacket as invalid for prediction
+ for (i = 1; i <= IPP_MIN(mbInVideoPacket, mbPerRow + 1); i ++) {
+ pMBinfo[-i].validPred = 0;
+ }
+ }
+Err_3:
+ sts = MP4_STATUS_ERROR;
+ if (pInfo->stopOnErr)
+ return sts;
+ if (pInfo->VisualObject.VideoObject.resync_marker_disable || !mp4_SeekResyncMarker(pInfo))
+ {
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, pInfo->VisualObject.VideoObject.MacroBlockPerVOP - rowNum * mbPerRow - colNum);
+ return sts;
+ }
+ goto ErrRet_3;
+ }
+ // decode usual P-VOP
+ {
+ for (;;)
+ {
+ // reset Intra prediction buffer on new Video_packet
+ mp4_ResetIntraPredBuffer(pInfo);
+ mbInVideoPacket = 0;
+ // decode blocks
+ for (;;)
+ {
+ if (colNum == 0)
+ {
+ // reset B-prediction blocks on new row
+ mp4_ResetIntraPredBblock(pInfo);
+ }
+ mb_not_coded = mp4_GetBit(pInfo);
+ mb_type = IPPVC_MBTYPE_INTER;
+ if (!mb_not_coded)
+ if (mp4_DecodeMCBPC_P(pInfo, &mb_type, &cbpc, 1) != MP4_STATUS_OK)
+ goto Err_4;
+ if (mb_type != IPPVC_MB_STUFFING)
+ {
+ if (!mb_not_coded)
+ {
+ if (mb_type >= IPPVC_MBTYPE_INTRA)
+ ac_pred_flag = mp4_GetBit(pInfo);
+ if (mp4_DecodeCBPY_P(pInfo, &cbpy, mb_type) != MP4_STATUS_OK)
+ goto Err_4;
+ quantPred = quant;
+ if (mb_type == IPPVC_MBTYPE_INTER_Q || mb_type == IPPVC_MBTYPE_INTRA_Q)
+ mp4_UpdateQuant(pInfo, quant);
+ }
+ else
+ {
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_NOTCODED);
+ mp4_Zero4MV(pMBinfo->mv);
+ }
+ pMBinfo->validPred = 1;
+ pMBinfo->not_coded = (uint8_t)mb_not_coded;
+ pMBinfo->type = (uint8_t)mb_type;
+ if (mb_type >= IPPVC_MBTYPE_INTRA) {
+ if (mbInVideoPacket == 0)
+ quantPred = quant;
+ dcVLC = (quantPred < mp4_DC_vlc_Threshold[pInfo->VisualObject.VideoObject.VideoObjectPlane.intra_dc_vlc_thr]) ? 1 : 0;
+ pFc[0] = pYc; pFc[1] = pYc + 8; pFc[2] = pYc + 8 * stepYc; pFc[3] = pYc + 8 * stepYc + 8; pFc[4] = pCbc; pFc[5] = pCrc;
+ if (mp4_DecodeIntraMB(pInfo, colNum, (cbpy << 2) + cbpc, quant, dcVLC, ac_pred_flag, pFc, stepFc) != MP4_STATUS_OK)
+ goto Err_4;
+ mp4_Zero4MV(pMBinfo->mv);
+#ifdef USE_NOTCODED_STATE
+ // clear not_coded MB state
+ *ncState = 0;
+#endif
+ } else {
+ mp4_UpdateIntraPredBuffInvalid(pInfo, colNum);
+ if (!mb_not_coded) {
+ dx = colNum * 16;
+ dy = rowNum * 16;
+ if (mb_type != IPPVC_MBTYPE_INTER4V) {
+ if (mp4_PredictDecode1MV(pInfo, pMBinfo, rowNum, colNum) != MP4_STATUS_OK)
+ goto Err_4;
+ pMBinfo->mv[1] = pMBinfo->mv[2] = pMBinfo->mv[3] = pMBinfo->mv[0];
+ if (quarter_sample) {
+ mp4_LimitMVQ(pMBinfo->mv, mvCur, &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMVQ(mvCur, &mvCbCr);
+ } else {
+ mp4_LimitMV(pMBinfo->mv, mvCur, &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMV(mvCur, &mvCbCr);
+ }
+ mvCur[1] = mvCur[2] = mvCur[3] = mvCur[0];
+ } else {
+ if (mp4_PredictDecode4MV(pInfo, pMBinfo, rowNum, colNum) != MP4_STATUS_OK)
+ goto Err_4;
+ if (quarter_sample) {
+ mp4_Limit4MVQ(pMBinfo->mv, mvCur, &limitRectL, dx, dy, 8);
+ mp4_ComputeChroma4MVQ(pMBinfo->mv, &mvCbCr);
+ } else {
+ mp4_Limit4MV(pMBinfo->mv, mvCur, &limitRectL, dx, dy, 8);
+ mp4_ComputeChroma4MV(pMBinfo->mv, &mvCbCr);
+ }
+ mp4_LimitMV(&mvCbCr, &mvCbCr, &limitRectC, dx >> 1, dy >> 1, 8);
+ }
+ }
+ if (obmc_disable) {
+ if (mb_not_coded) {
+#ifdef USE_NOTCODED_STATE
+ if (!(*ncState)) {
+ *ncState = 1;
+#endif
+ ippiCopy16x16_8u_C1R(pYr, stepYr, pYc, stepYc);
+ ippiCopy8x8_8u_C1R(pCbr, stepCbr, pCbc, stepCbc);
+ ippiCopy8x8_8u_C1R(pCrr, stepCrr, pCrc, stepCrc);
+#ifdef USE_NOTCODED_STATE
+ }
+#endif
+ } else {
+#ifdef USE_NOTCODED_STATE
+ // clear not_coded MB state
+ *ncState = 0;
+#endif
+ if (quarter_sample) {
+ if (mb_type == IPPVC_MBTYPE_INTER4V) {
+ mp4_Copy8x8QP_8u(pYr, stepYr, pYc, stepYc, &mvCur[0], rt);
+ mp4_Copy8x8QP_8u(pYr+8, stepYr, pYc+8, stepYc, &mvCur[1], rt);
+ mp4_Copy8x8QP_8u(pYr+8*stepYr, stepYr, pYc+8*stepYc, stepYc, &mvCur[2], rt);
+ mp4_Copy8x8QP_8u(pYr+8*stepYr+8, stepYr, pYc+8*stepYc+8, stepYc, &mvCur[3], rt);
+ } else
+ mp4_Copy16x16QP_8u(pYr, stepYr, pYc, stepYc, &mvCur[0], rt);
+ mp4_DecodeReconBlockInter_MPEG4(cbpy & 8, pYc, stepYc, Err_4);
+ mp4_DecodeReconBlockInter_MPEG4(cbpy & 4, pYc+8, stepYc, Err_4);
+ mp4_DecodeReconBlockInter_MPEG4(cbpy & 2, pYc+8*stepYc, stepYc, Err_4);
+ mp4_DecodeReconBlockInter_MPEG4(cbpy & 1, pYc+8*stepYc+8, stepYc, Err_4);
+ } else {
+ if (cbpy || mb_type == IPPVC_MBTYPE_INTER4V) {
+ mp4_DecodeMCBlockInter_MPEG4(cbpy & 8, pYr, stepYr, pYc, stepYc, mvCur[0], rt, Err_4);
+ mp4_DecodeMCBlockInter_MPEG4(cbpy & 4, pYr+8, stepYr, pYc+8, stepYc, mvCur[1], rt, Err_4);
+ mp4_DecodeMCBlockInter_MPEG4(cbpy & 2, pYr+8*stepYr, stepYr, pYc+8*stepYc, stepYc, mvCur[2], rt, Err_4);
+ mp4_DecodeMCBlockInter_MPEG4(cbpy & 1, pYr+8*stepYr+8, stepYr, pYc+8*stepYc+8, stepYc, mvCur[3], rt, Err_4);
+ } else {
+ mp4_Copy16x16HP_8u(pYr, stepYr, pYc, stepYc, &mvCur[0], rt);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nB_INTER_NC);
+ //if (cbpy) {
+ // mp4_DecodeReconBlockInter_MPEG4(cbpy & 8, pYc, stepYc);
+ // mp4_DecodeReconBlockInter_MPEG4(cbpy & 4, pYc+8, stepYc);
+ // mp4_DecodeReconBlockInter_MPEG4(cbpy & 2, pYc+8*stepYc, stepYc);
+ // mp4_DecodeReconBlockInter_MPEG4(cbpy & 1, pYc+8*stepYc+8, stepYc);
+ //}
+ }
+ }
+ mp4_DecodeMCBlockInter_MPEG4(cbpc & 2, pCbr, stepCbr, pCbc, stepCbc, mvCbCr, rt, Err_4);
+ mp4_DecodeMCBlockInter_MPEG4(cbpc & 1, pCrr, stepCrr, pCrc, stepCrc, mvCbCr, rt, Err_4);
+ }
+ }
+ }
+ if (!obmc_disable) {
+ // OBMC for previous MB
+ if (colNum > 0)
+ if (pMBinfo[-1].type < IPPVC_MBTYPE_INTRA)
+ mp4_OBMC(pInfo, pMBinfo - 1, mvPrev, colNum - 1, rowNum, limitRectL, pYc - 16, stepYc, pYr - 16, stepYr, cbpyPrev, coeffMB, 0);
+ if (mb_type < IPPVC_MBTYPE_INTRA) {
+ if (mb_not_coded)
+ {
+ cbpyPrev = 0;
+ mp4_Zero4MV(mvPrev);
+ ippiCopy8x8_8u_C1R(pCbr, stepCbr, pCbc, stepCbc);
+ ippiCopy8x8_8u_C1R(pCrr, stepCrr, pCrc, stepCrc);
+ }
+ else
+ {
+ cbpyPrev = cbpy;
+ mvPrev[0] = mvCur[0]; mvPrev[1] = mvCur[1]; mvPrev[2] = mvCur[2]; mvPrev[3] = mvCur[3];
+ if (mp4_DecodeInterMB(pInfo, coeffMB, quant, (cbpy << 2) + cbpc, scan) != MP4_STATUS_OK)
+ goto Err_4;
+ mp4_MC_HP(cbpc & 2, pCbr, stepCbr, pCbc, stepCbc, coeffMB+256, &mvCbCr, rt);
+ mp4_MC_HP(cbpc & 1, pCrr, stepCrr, pCrc, stepCrc, coeffMB+320, &mvCbCr, rt);
+ }
+ // OBMC current MB if it is the last in the row
+ if (colNum == mbPerRow - 1)
+ mp4_OBMC(pInfo, pMBinfo, mvPrev, colNum, rowNum, limitRectL, pYc, stepYc, pYr, stepYr, cbpyPrev, coeffMB, 0);
+ }
+ }
+#ifdef USE_NOTCODED_STATE
+ ncState ++;
+#endif
+ pMBinfo ++;
+ mbInVideoPacket ++;
+ colNum ++;
+ if (colNum == mbPerRow)
+ {
+ colNum = 0;
+ rowNum ++;
+ if (rowNum == mbPerCol)
+ {
+ // skip stuffing
+ while (mp4_ShowBits(pInfo, 10) == 1)
+ mp4_FlushBits(pInfo, 10);
+ return sts;
+ }
+ pYc += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc;
+ pCbc += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbc << 3) - stepCbc;
+ pCrc += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrc << 3) - stepCrc;
+ pYr += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYr << 4) - stepYr;
+ pCbr += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbr << 3) - stepCbr;
+ pCrr += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrr << 3) - stepCrr;
+ }
+ else
+ {
+ pYc += 16; pCrc += 8; pCbc += 8;
+ pYr += 16; pCrr += 8; pCbr += 8;
+ }
+ }
+ if (!pInfo->VisualObject.VideoObject.resync_marker_disable)
+ {
+ int32_t found;
+ErrRet_4:
+ if (mp4_CheckDecodeVideoPacket(pInfo, &found) == MP4_STATUS_OK)
+ {
+ if (found) {
+ mbInVideoPacket = pInfo->VisualObject.VideoObject.VideoObjectPlane.macroblock_num - mbCurr;
+ quant = pInfo->VisualObject.VideoObject.VideoObjectPlane.quant_scale;
+ mbCurr = pInfo->VisualObject.VideoObject.VideoObjectPlane.macroblock_num;
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, mbCurr - rowNum * mbPerRow - colNum);
+ rowNum = mbCurr / mbPerRow;
+ colNum = mbCurr % mbPerRow;
+ pYc = pInfo->VisualObject.cFrame->pY + (rowNum * stepYc + colNum) * 16; pCbc = pInfo->VisualObject.cFrame->pCb + (rowNum * stepCbc + colNum) * 8; pCrc = pInfo->VisualObject.cFrame->pCr + (rowNum * stepCrc + colNum) * 8;
+ pYr = pInfo->VisualObject.rFrame->pY + (rowNum * stepYr + colNum) * 16; pCbr = pInfo->VisualObject.rFrame->pCb + (rowNum * stepCbr + colNum) * 8; pCrr = pInfo->VisualObject.rFrame->pCr + (rowNum * stepCrr + colNum) * 8;
+ pMBinfo = pInfo->VisualObject.VideoObject.MBinfo + mbCurr;
+#ifdef USE_NOTCODED_STATE
+ ncState = pInfo->VisualObject.VideoObject.ncState + mbCurr;
+#endif
+ break;
+ }
+ }
+ else
+ goto Err_4;
+ }
+ }
+ // mark MBs the previous videopacket as invalid for prediction
+ for (i = 1; i <= IPP_MIN(mbInVideoPacket, mbPerRow + 1); i ++)
+ {
+ pMBinfo[-i].validPred = 0;
+ }
+ }
+Err_4:
+ sts = MP4_STATUS_ERROR;
+ if (pInfo->stopOnErr)
+ return sts;
+ if (pInfo->VisualObject.VideoObject.resync_marker_disable || !mp4_SeekResyncMarker(pInfo))
+ {
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, pInfo->VisualObject.VideoObject.MacroBlockPerVOP - rowNum * mbPerRow - colNum);
+ return sts;
+ }
+ goto ErrRet_4;
+ }
+}
+
+
diff --git a/Src/mpeg4dec/mp4decvops.c b/Src/mpeg4dec/mp4decvops.c
new file mode 100644
index 000000000..4a3319644
--- /dev/null
+++ b/Src/mpeg4dec/mp4decvops.c
@@ -0,0 +1,655 @@
+/* ///////////////////////////////////////////////////////////////////////
+//
+// INTEL CORPORATION PROPRIETARY INFORMATION
+// This software is supplied under the terms of a license agreement or
+// nondisclosure agreement with Intel Corporation and may not be copied
+// or disclosed except in accordance with the terms of that agreement.
+// Copyright (c) 2001-2007 Intel Corporation. All Rights Reserved.
+//
+// Description: Decodes S-VOPs
+//
+*/
+
+#include "mp4def.h"
+#include "mp4dec.h"
+
+/*
+// decode MPEG-4 SVOP
+*/
+mp4_Status mp4_DecodeVOP_S(mp4_Info* pInfo)
+{
+ __ALIGN16(int16_t, coeffMB, 64*6);
+ int32_t quant, quantPred, i, j, dcVLC, nmb, dx, dy, pat;
+ int32_t stepYr, stepYc, stepCbr, stepCbc, stepCrr, stepCrc, mbPerRow, mbPerCol;
+ int32_t mbCurr, mbInVideoPacket, colNum, rowNum, stepF[6];
+ uint8_t *pYc, *pCbc, *pCrc, *pYr, *pCbr, *pCrr, *pF[6];
+ int32_t mb_not_coded, mb_type, cbpc, cbpy, ac_pred_flag, cbpyPrev, mcsel;
+ int32_t scan, obmc_disable, rt, quarter_sample, interlaced, fcode_forward;
+ IppiRect limitRectL, limitRectC;
+ IppMotionVector mvCur[4], mvPrev[4], mvTmp[4], mvCbCr;
+ mp4_MacroBlock *pMBinfo;
+ IppiRect spriteRect, vopRect;
+ mp4_Status sts;
+
+ if (!pInfo->VisualObject.cFrame)
+ pInfo->VisualObject.cFrame = CreateFrame(&pInfo->VisualObject);
+
+ mbPerRow = pInfo->VisualObject.VideoObject.MacroBlockPerRow;
+ mbPerCol = pInfo->VisualObject.VideoObject.MacroBlockPerCol;
+ stepYc = pInfo->VisualObject.cFrame->stepY;
+ stepYr = pInfo->VisualObject.rFrame->stepY;
+ stepCbc = pInfo->VisualObject.cFrame->stepCb;
+ stepCbr = pInfo->VisualObject.rFrame->stepCb;
+ stepCrc = pInfo->VisualObject.cFrame->stepCr;
+ stepCrr = pInfo->VisualObject.rFrame->stepCr;
+ pYc = pInfo->VisualObject.cFrame->pY;
+ pCbc = pInfo->VisualObject.cFrame->pCb;
+ pCrc = pInfo->VisualObject.cFrame->pCr;
+ pYr = pInfo->VisualObject.rFrame->pY;
+ pCbr = pInfo->VisualObject.rFrame->pCb;
+ pCrr = pInfo->VisualObject.rFrame->pCr;
+ stepF[0] = stepF[1] = stepF[2] = stepF[3] = stepYc; stepF[4] = stepCbc; stepF[5] = stepCrc;
+ // Bounding rectangle for MV limitation
+ limitRectL.x = - 16 * MP4_NUM_EXT_MB;
+ limitRectL.y = - 16 * MP4_NUM_EXT_MB;
+ limitRectL.width = pInfo->VisualObject.VideoObject.width + 16 * 2 * MP4_NUM_EXT_MB;
+ limitRectL.height = pInfo->VisualObject.VideoObject.height + 16 * 2 * MP4_NUM_EXT_MB;
+ limitRectC.x = -8 * MP4_NUM_EXT_MB;
+ limitRectC.y = -8 * MP4_NUM_EXT_MB;
+ limitRectC.width = (pInfo->VisualObject.VideoObject.width >> 1) + 8 * 2 * MP4_NUM_EXT_MB;
+ limitRectC.height = (pInfo->VisualObject.VideoObject.height >> 1) + 8 * 2 * MP4_NUM_EXT_MB;
+ pMBinfo = pInfo->VisualObject.VideoObject.MBinfo;
+ rt = pInfo->VisualObject.VideoObject.VideoObjectPlane.rounding_type;
+ quarter_sample = pInfo->VisualObject.VideoObject.quarter_sample;
+ obmc_disable = pInfo->VisualObject.VideoObject.obmc_disable;
+ interlaced = pInfo->VisualObject.VideoObject.interlaced;
+ scan = pInfo->VisualObject.VideoObject.VideoObjectPlane.alternate_vertical_scan_flag ? IPPVC_SCAN_VERTICAL : IPPVC_SCAN_ZIGZAG;
+ nmb = pInfo->VisualObject.VideoObject.MacroBlockPerVOP;
+ quant = quantPred = pInfo->VisualObject.VideoObject.VideoObjectPlane.quant;
+ mbCurr = colNum = rowNum = 0;
+ cbpc = 0;
+ // init WarpSpec for Sprites or GMC
+ vopRect.x = 0;
+ vopRect.y = 0;
+ vopRect.width = pInfo->VisualObject.VideoObject.width;
+ vopRect.height = pInfo->VisualObject.VideoObject.height;
+ if (pInfo->VisualObject.VideoObject.sprite_enable == MP4_SPRITE_STATIC) {
+ spriteRect.x = pInfo->VisualObject.VideoObject.sprite_left_coordinate;
+ spriteRect.y = pInfo->VisualObject.VideoObject.sprite_top_coordinate;
+ spriteRect.width = pInfo->VisualObject.VideoObject.sprite_width;
+ spriteRect.height = pInfo->VisualObject.VideoObject.sprite_height;
+ fcode_forward = 1;
+ } else {
+ spriteRect = vopRect; // for shapes they may be different !!!!!!
+ fcode_forward = pInfo->VisualObject.VideoObject.VideoObjectPlane.fcode_forward;
+ }
+ ippiWarpInit_MPEG4(pInfo->VisualObject.VideoObject.WarpSpec,
+ pInfo->VisualObject.VideoObject.VideoObjectPlane.warping_mv_code_du,
+ pInfo->VisualObject.VideoObject.VideoObjectPlane.warping_mv_code_dv,
+ pInfo->VisualObject.VideoObject.sprite_warping_points,
+ pInfo->VisualObject.VideoObject.sprite_enable,
+ pInfo->VisualObject.VideoObject.sprite_warping_accuracy,
+ rt, quarter_sample, fcode_forward,
+ &spriteRect, &vopRect);
+// decode basic sprites
+ if (pInfo->VisualObject.VideoObject.sprite_enable == MP4_SPRITE_STATIC)
+ {
+ //if (pInfo->VisualObject.VideoObject.shape != MP4_SHAPE_TYPE_RECTANGULAR) {
+ // if (mp4_InitVOPShape(pInfo) != MP4_STATUS_OK)
+ // return MP4_STATUS_ERROR;
+ //}
+ ippiWarpLuma_MPEG4_8u_C1R(pInfo->VisualObject.sFrame->pY, pInfo->VisualObject.sFrame->stepY,
+ pYc, stepYc, &vopRect, pInfo->VisualObject.VideoObject.WarpSpec);
+ if (pInfo->VisualObject.VideoObject.sprite_brightness_change)
+ ippiChangeSpriteBrightness_MPEG4_8u_C1IR(pYc, stepYc, vopRect.width, vopRect.height, pInfo->VisualObject.VideoObject.VideoObjectPlane.brightness_change_factor);
+ vopRect.width >>= 1; vopRect.height >>= 1;
+ ippiWarpChroma_MPEG4_8u_P2R(pInfo->VisualObject.sFrame->pCb, pInfo->VisualObject.sFrame->stepCb,
+ pInfo->VisualObject.sFrame->pCr, pInfo->VisualObject.sFrame->stepCr,
+ pCbc, stepCbc, pCrc, stepCrc, &vopRect, pInfo->VisualObject.VideoObject.WarpSpec);
+ return MP4_STATUS_OK;
+ }
+ sts = MP4_STATUS_OK;
+// decode data_partitioned S(GMC)-VOP
+ if (pInfo->VisualObject.VideoObject.data_partitioned) {
+ for (;;) {
+ mp4_DataPartMacroBlock *pMBdp;
+ int32_t x, y;
+
+ x = colNum;
+ y = rowNum;
+ // reset Intra prediction buffer on new Video_packet
+ mp4_ResetIntraPredBuffer(pInfo);
+ pMBdp = &pInfo->VisualObject.VideoObject.DataPartBuff[mbCurr];
+ pMBinfo = &pInfo->VisualObject.VideoObject.MBinfo[mbCurr];
+ mbInVideoPacket = 0;
+ // decode not_coded/mcsel/mb_type/cbpc/MV part
+ for (;;) {
+ mb_not_coded = mp4_GetBit(pInfo);
+ if (mb_not_coded) {
+ mb_type = IPPVC_MBTYPE_INTER;
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_NOTCODED);
+ } else {
+ if (mp4_DecodeMCBPC_P(pInfo, &mb_type, &cbpc, 1) != MP4_STATUS_OK)
+ goto Err_2;
+ }
+ if (mb_type != IPPVC_MB_STUFFING) {
+ if (mbInVideoPacket == nmb - mbCurr) {
+ mp4_Error("DC Marker missed");
+ goto Err_2;
+ }
+ pMBinfo->validPred = 1;
+ if (mb_type < IPPVC_MBTYPE_INTER4V && !mb_not_coded)
+ mcsel = mp4_GetBit(pInfo);
+ else
+ mcsel = mb_not_coded;
+ if (!mcsel) {
+ if (mb_type <= IPPVC_MBTYPE_INTER4V) {
+ if (mb_type != IPPVC_MBTYPE_INTER4V) {
+ if (mp4_PredictDecode1MV(pInfo, pMBinfo, y, x) != MP4_STATUS_OK)
+ goto Err_2;
+ pMBinfo->mv[1] = pMBinfo->mv[2] = pMBinfo->mv[3] = pMBinfo->mv[0];
+ } else {
+ if (mp4_PredictDecode4MV(pInfo, pMBinfo, y, x) != MP4_STATUS_OK)
+ goto Err_2;
+ }
+ } else {
+ mp4_Zero4MV(pMBinfo->mv);
+ }
+ } else {
+ ippiCalcGlobalMV_MPEG4(x << 4, y << 4, pMBinfo->mv, pInfo->VisualObject.VideoObject.WarpSpec);
+ pMBinfo->mv[1] = pMBinfo->mv[2] = pMBinfo->mv[3] = pMBinfo->mv[0];
+ }
+ pMBinfo->not_coded = (uint8_t)mb_not_coded;
+ pMBinfo->type = (uint8_t)mb_type;
+ pMBinfo ++;
+ pMBdp->pat = (uint8_t)cbpc;
+ pMBdp->mcsel = (uint8_t)mcsel;
+ pMBdp ++;
+ mbInVideoPacket ++;
+ x ++;
+ if (x == mbPerRow) {
+ x = 0;
+ y ++;
+ }
+ }
+ if (mp4_ShowBits(pInfo, 17) == MP4_MV_MARKER) {
+ mp4_GetBits(pInfo, 17);
+ break;
+ }
+ }
+ pMBdp = &pInfo->VisualObject.VideoObject.DataPartBuff[mbCurr];
+ pMBinfo = &pInfo->VisualObject.VideoObject.MBinfo[mbCurr];
+ // decode ac_pred_flag/cbpy/dquant/IntraDC part
+ for (i = 0; i < mbInVideoPacket; i ++) {
+ if (!pMBinfo->not_coded) {
+ mb_type = pMBinfo->type;
+ if (mb_type >= IPPVC_MBTYPE_INTRA)
+ pMBdp->ac_pred_flag = (uint8_t)mp4_GetBit(pInfo);
+ if (mp4_DecodeCBPY_P(pInfo, &cbpy, mb_type) != MP4_STATUS_OK)
+ goto Err_2;
+ pMBdp->pat = (uint8_t)((cbpy << 2) + pMBdp->pat);
+ quantPred = quant;
+ if (mb_type == IPPVC_MBTYPE_INTER_Q || mb_type == IPPVC_MBTYPE_INTRA_Q)
+ mp4_UpdateQuant(pInfo, quant);
+ pMBdp->quant = (uint8_t)quant;
+ if (i == 0)
+ quantPred = quant;
+ // decode DC coefficient of Intra blocks
+ dcVLC = (quantPred < mp4_DC_vlc_Threshold[pInfo->VisualObject.VideoObject.VideoObjectPlane.intra_dc_vlc_thr]) ? 1 : 0;
+ if ((mb_type >= IPPVC_MBTYPE_INTRA) && dcVLC) {
+ for (j = 0; j < 6; j ++) {
+ if (ippiDecodeDCIntra_MPEG4_1u16s(&pInfo->bufptr, &pInfo->bitoff, &pMBdp->dct_dc[j], j < 4 ? IPPVC_BLOCK_LUMA : IPPVC_BLOCK_CHROMA) != ippStsNoErr)
+ goto Err_2;
+ }
+ }
+ } else
+ pMBdp->pat = 0;
+ pMBinfo->not_coded = 0; // for B-VOP all MB have MVs
+ if (pMBdp->mcsel)
+ pMBinfo->type = IPPVC_MBTYPE_INTRA; // for OBMC MVs
+ pMBdp ++;
+ pMBinfo ++;
+ }
+ if (mbCurr + mbInVideoPacket < nmb)
+ pMBinfo->type = IPPVC_MBTYPE_INTRA; // for OBMC set first MB of the next videopacket as invalid for right MV
+ pMBdp = &pInfo->VisualObject.VideoObject.DataPartBuff[mbCurr];
+ pMBinfo = &pInfo->VisualObject.VideoObject.MBinfo[mbCurr];
+ // decode coeffs and reconstruct macroblocks
+ for (i = 0; i < mbInVideoPacket; i ++) {
+ if (colNum == 0) {
+ // reset B-prediction blocks on new row
+ mp4_ResetIntraPredBblock(pInfo);
+ }
+ quant = pMBdp->quant;
+ mb_type = pMBinfo->type;
+ mcsel = pMBdp->mcsel;
+ if (!mcsel && (mb_type >= IPPVC_MBTYPE_INTRA)) {
+ quantPred = (i == 0) ? quant : pMBdp[-1].quant;
+ dcVLC = (quantPred < mp4_DC_vlc_Threshold[pInfo->VisualObject.VideoObject.VideoObjectPlane.intra_dc_vlc_thr]) ? 1 : 0;
+ pF[0] = pYc; pF[1] = pYc + 8; pF[2] = pYc + 8 * stepYc; pF[3] = pYc + 8 * stepYc + 8; pF[4] = pCbc; pF[5] = pCrc;
+ if (mp4_DecodeIntraMB_DP(pInfo, pMBdp->dct_dc, colNum, pMBdp->pat, quant, dcVLC, pMBdp->ac_pred_flag, pF, stepF) != MP4_STATUS_OK)
+ goto Err_2;
+ } else {
+ mp4_UpdateIntraPredBuffInvalid(pInfo, colNum);
+ dx = colNum * 16;
+ dy = rowNum * 16;
+ pat = pMBdp->pat;
+ cbpy = pat >> 2;
+ cbpc = pat & 3;
+ if (pat)
+ if (mp4_DecodeInterMB(pInfo, coeffMB, quant, pat, scan) != MP4_STATUS_OK)
+ goto Err_2;
+ if (!mcsel) {
+ if (mb_type == IPPVC_MBTYPE_INTER4V) {
+ if (quarter_sample) {
+ mp4_Limit4MVQ(pMBinfo->mv, mvCur, &limitRectL, dx, dy, 8);
+ mp4_ComputeChroma4MVQ(pMBinfo->mv, &mvCbCr);
+ } else {
+ mp4_Limit4MV(pMBinfo->mv, mvCur, &limitRectL, dx, dy, 8);
+ mp4_ComputeChroma4MV(pMBinfo->mv, &mvCbCr);
+ }
+ mp4_LimitMV(&mvCbCr, &mvCbCr, &limitRectC, dx >> 1, dy >> 1, 8);
+ } else {
+ if (quarter_sample) {
+ mp4_LimitMVQ(pMBinfo->mv, mvCur, &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMVQ(mvCur, &mvCbCr);
+ } else {
+ mp4_LimitMV(pMBinfo->mv, mvCur, &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMV(mvCur, &mvCbCr);
+ }
+ mvCur[1] = mvCur[2] = mvCur[3] = mvCur[0];
+ }
+ if (obmc_disable) {
+ if (quarter_sample) {
+ if (mb_type == IPPVC_MBTYPE_INTER4V) {
+ mp4_Copy8x8QP_8u(pYr, stepYr, pYc, stepYc, &mvCur[0], rt);
+ mp4_Copy8x8QP_8u(pYr+8, stepYr, pYc+8, stepYc, &mvCur[1], rt);
+ mp4_Copy8x8QP_8u(pYr+8*stepYr, stepYr, pYc+8*stepYc, stepYc, &mvCur[2], rt);
+ mp4_Copy8x8QP_8u(pYr+8*stepYr+8, stepYr, pYc+8*stepYc+8, stepYc, &mvCur[3], rt);
+ } else
+ mp4_Copy16x16QP_8u(pYr, stepYr, pYc, stepYc, &mvCur[0], rt);
+ } else {
+ if (mb_type == IPPVC_MBTYPE_INTER4V) {
+ mp4_Copy8x8HP_8u(pYr, stepYr, pYc, stepYc, &mvCur[0], rt);
+ mp4_Copy8x8HP_8u(pYr+8, stepYr, pYc+8, stepYc, &mvCur[1], rt);
+ mp4_Copy8x8HP_8u(pYr+8*stepYr, stepYr, pYc+8*stepYc, stepYc, &mvCur[2], rt);
+ mp4_Copy8x8HP_8u(pYr+8*stepYr+8, stepYr, pYc+8*stepYc+8, stepYc, &mvCur[3], rt);
+ } else
+ mp4_Copy16x16HP_8u(pYr, stepYr, pYc, stepYc, &mvCur[0], rt);
+ }
+ mp4_AddResidual(cbpy & 8, pYc, stepYc, coeffMB);
+ mp4_AddResidual(cbpy & 4, pYc+8, stepYc, coeffMB+64);
+ mp4_AddResidual(cbpy & 2, pYc+stepYc*8, stepYc, coeffMB+128);
+ mp4_AddResidual(cbpy & 1, pYc+stepYc*8+8, stepYc, coeffMB+192);
+ } else {
+ mp4_OBMC(pInfo, pMBinfo, mvCur, colNum, rowNum, limitRectL, pYc, stepYc, pYr, stepYr, cbpy, coeffMB, 0);
+ }
+ mp4_MC_HP(cbpc & 2, pCbr, stepCbr, pCbc, stepCbc, coeffMB+256, &mvCbCr, rt);
+ mp4_MC_HP(cbpc & 1, pCrr, stepCrr, pCrc, stepCrc, coeffMB+320, &mvCbCr, rt);
+ } else {
+ IppiRect mbRect;
+
+ mbRect.x = dx; mbRect.y = dy; mbRect.width = mbRect.height = 16;
+ ippiWarpLuma_MPEG4_8u_C1R(pInfo->VisualObject.rFrame->pY, stepYr, pYc, stepYc, &mbRect, pInfo->VisualObject.VideoObject.WarpSpec);
+ mbRect.x >>= 1; mbRect.y >>= 1; mbRect.width = mbRect.height = 8;
+ ippiWarpChroma_MPEG4_8u_P2R(pInfo->VisualObject.rFrame->pCb, stepCbr, pInfo->VisualObject.rFrame->pCr, stepCrr, pCbc, stepCbc, pCrc, stepCrc, &mbRect, pInfo->VisualObject.VideoObject.WarpSpec);
+ if (pat) {
+ mp4_AddResidual(cbpy & 8, pYc, stepYc, coeffMB);
+ mp4_AddResidual(cbpy & 4, pYc+8, stepYc, coeffMB+64);
+ mp4_AddResidual(cbpy & 2, pYc+stepYc*8, stepYc, coeffMB+128);
+ mp4_AddResidual(cbpy & 1, pYc+stepYc*8+8, stepYc, coeffMB+192);
+ mp4_AddResidual(cbpc & 2, pCbc, stepCbc, coeffMB+256);
+ mp4_AddResidual(cbpc & 1, pCrc, stepCrc, coeffMB+320);
+ }
+ }
+ }
+ pMBinfo ++;
+ pMBdp ++;
+ colNum ++;
+ if (colNum == mbPerRow) {
+ colNum = 0;
+ rowNum ++;
+ if (rowNum == mbPerCol)
+ return sts;
+ pYc += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc;
+ pCbc += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbc << 3) - stepCbc;
+ pCrc += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrc << 3) - stepCrc;
+ pYr += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYr << 4) - stepYr;
+ pCbr += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbr << 3) - stepCbr;
+ pCrr += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrr << 3) - stepCrr;
+ }
+ else
+ {
+ pYc += 16; pCrc += 8; pCbc += 8;
+ pYr += 16; pCrr += 8; pCbr += 8;
+ }
+ }
+ //mbCurr += mbInVideoPacket;
+ if (!pInfo->VisualObject.VideoObject.resync_marker_disable)
+ {
+ int32_t found;
+ErrRet_2:
+ if (mp4_CheckDecodeVideoPacket(pInfo, &found) == MP4_STATUS_OK)
+ {
+ if (found)
+ {
+ quant = pInfo->VisualObject.VideoObject.VideoObjectPlane.quant_scale;
+ mbInVideoPacket = pInfo->VisualObject.VideoObject.VideoObjectPlane.macroblock_num - mbCurr;
+ mbCurr = pInfo->VisualObject.VideoObject.VideoObjectPlane.macroblock_num;
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, mbCurr - rowNum * mbPerRow - colNum);
+ rowNum = mbCurr / mbPerRow;
+ colNum = mbCurr % mbPerRow;
+ pYc = pInfo->VisualObject.cFrame->pY + (rowNum * stepYc + colNum) * 16; pCbc = pInfo->VisualObject.cFrame->pCb + (rowNum * stepCbc + colNum) * 8; pCrc = pInfo->VisualObject.cFrame->pCr + (rowNum * stepCrc + colNum) * 8;
+ pYr = pInfo->VisualObject.rFrame->pY + (rowNum * stepYr + colNum) * 16; pCbr = pInfo->VisualObject.rFrame->pCb + (rowNum * stepCbr + colNum) * 8; pCrr = pInfo->VisualObject.rFrame->pCr + (rowNum * stepCrr + colNum) * 8;
+ pMBinfo = pInfo->VisualObject.VideoObject.MBinfo + mbCurr;
+ } else
+ goto Err_2;
+ } else
+ goto Err_2;
+ }
+ // mark MBs the previous videopacket as invalid for prediction
+ for (i = 1; i <= IPP_MIN(mbInVideoPacket, mbPerRow + 1); i ++)
+ pMBinfo[-i].validPred = 0;
+ }
+Err_2:
+ sts = MP4_STATUS_ERROR;
+ if (pInfo->stopOnErr)
+ return sts;
+ if (pInfo->VisualObject.VideoObject.resync_marker_disable || !mp4_SeekResyncMarker(pInfo))
+ {
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, pInfo->VisualObject.VideoObject.MacroBlockPerVOP - rowNum * mbPerRow - colNum);
+ return sts;
+ }
+ goto ErrRet_2;
+ }
+// decode not data_partitioned S-VOP
+ {
+ int32_t stepY, pYoff23, field_prediction, dct_type, dct_typePrev, mb_ftfr, mb_fbfr;
+ IppMotionVector mvCbCrT, mvCbCrB, *mvField = pInfo->VisualObject.VideoObject.FieldMV;
+
+ // warning "variable may be used without having been initialized"
+ dx = dy = ac_pred_flag = cbpy = cbpyPrev = field_prediction = dct_type = dct_typePrev = mb_ftfr = mb_fbfr = 0;
+ mvCbCr.dx = mvCbCr.dy = mvCbCrT.dx = mvCbCrT.dy = mvCbCrB.dx = mvCbCrB.dy = 0;
+ for (;;) {
+ // reset Intra prediction buffer on new Video_packet
+ mp4_ResetIntraPredBuffer(pInfo);
+ mbInVideoPacket = 0;
+ // decode blocks
+ for (;;) {
+ if (colNum == 0) {
+ // reset B-prediction blocks on new row
+ mp4_ResetIntraPredBblock(pInfo);
+ }
+ mb_not_coded = mp4_GetBit(pInfo);
+ mb_type = IPPVC_MBTYPE_INTER;
+ if (!mb_not_coded) {
+ if (mp4_DecodeMCBPC_P(pInfo, &mb_type, &cbpc, 1) != MP4_STATUS_OK)
+ goto Err_3;
+ }
+ if (mb_type != IPPVC_MB_STUFFING) {
+ if (!mb_not_coded) {
+ mcsel = (mb_type < IPPVC_MBTYPE_INTER4V) ? mp4_GetBit(pInfo) : 0;
+ if (mb_type >= IPPVC_MBTYPE_INTRA)
+ ac_pred_flag = mp4_GetBit(pInfo);
+ if (mp4_DecodeCBPY_P(pInfo, &cbpy, mb_type) != MP4_STATUS_OK)
+ goto Err_3;
+ quantPred = quant;
+ if (mb_type == IPPVC_MBTYPE_INTER_Q || mb_type == IPPVC_MBTYPE_INTRA_Q)
+ mp4_UpdateQuant(pInfo, quant);
+ if (interlaced) {
+ dct_type = 0;
+ field_prediction = 0;
+ if (mb_type >= IPPVC_MBTYPE_INTRA || (cbpy + cbpc) != 0)
+ dct_type = mp4_GetBit(pInfo);
+ if ((mb_type == IPPVC_MBTYPE_INTER || mb_type == IPPVC_MBTYPE_INTER_Q) && !mcsel) {
+ field_prediction = mp4_GetBit(pInfo);
+ if (field_prediction) {
+ mb_ftfr = mp4_GetBit(pInfo);
+ mb_fbfr = mp4_GetBit(pInfo);
+ }
+ }
+ }
+ } else {
+ mp4_StatisticInc_(&pInfo->VisualObject.Statistic.nMB_NOTCODED);
+ mcsel = 1;
+ field_prediction = 0;
+ }
+ pMBinfo->validPred = 1;
+ pMBinfo->not_coded = 0; // for B-VOP all MB have MVs
+ pMBinfo->type = (uint8_t)(mcsel ? IPPVC_MBTYPE_INTRA : mb_type); // for OBMC MVs
+ pMBinfo->field_info = (uint8_t)(field_prediction + (mb_ftfr << 1) + (mb_fbfr << 2));
+ if (mb_type >= IPPVC_MBTYPE_INTRA) {
+ if (mbInVideoPacket == 0)
+ quantPred = quant;
+ dcVLC = (quantPred < mp4_DC_vlc_Threshold[pInfo->VisualObject.VideoObject.VideoObjectPlane.intra_dc_vlc_thr]) ? 1 : 0;
+ if (dct_type) {
+ stepY = stepYc * 2;
+ pYoff23 = stepYc;
+ } else {
+ stepY = stepYc;
+ pYoff23 = 8 * stepYc;
+ }
+ stepF[0] = stepF[1] = stepF[2] = stepF[3] = stepY;
+ pF[0] = pYc; pF[1] = pYc + 8; pF[2] = pYc + pYoff23; pF[3] = pYc + pYoff23 + 8; pF[4] = pCbc; pF[5] = pCrc;
+ if (mp4_DecodeIntraMB(pInfo, colNum, (cbpy << 2) + cbpc, quant, dcVLC, ac_pred_flag, pF, stepF) != MP4_STATUS_OK)
+ goto Err_3;
+ mp4_Zero4MV(pMBinfo->mv);
+ } else {
+ mp4_UpdateIntraPredBuffInvalid(pInfo, colNum);
+ dx = colNum * 16;
+ dy = rowNum * 16;
+ if (!mcsel) {
+ if (!field_prediction) {
+ if (mb_type != IPPVC_MBTYPE_INTER4V) {
+ if (mp4_PredictDecode1MV(pInfo, pMBinfo, rowNum, colNum) != MP4_STATUS_OK)
+ goto Err_3;
+ pMBinfo->mv[1] = pMBinfo->mv[2] = pMBinfo->mv[3] = pMBinfo->mv[0];
+ if (quarter_sample) {
+ mp4_LimitMVQ(pMBinfo->mv, mvCur, &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMVQ(mvCur, &mvCbCr);
+ } else {
+ mp4_LimitMV(pMBinfo->mv, mvCur, &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMV(mvCur, &mvCbCr);
+ }
+ mvCur[1] = mvCur[2] = mvCur[3] = mvCur[0];
+ } else {
+ if (mp4_PredictDecode4MV(pInfo, pMBinfo, rowNum, colNum) != MP4_STATUS_OK)
+ goto Err_3;
+ if (quarter_sample) {
+ mp4_Limit4MVQ(pMBinfo->mv, mvCur, &limitRectL, dx, dy, 8);
+ mp4_ComputeChroma4MVQ(pMBinfo->mv, &mvCbCr);
+ } else {
+ mp4_Limit4MV(pMBinfo->mv, mvCur, &limitRectL, dx, dy, 8);
+ mp4_ComputeChroma4MV(pMBinfo->mv, &mvCbCr);
+ }
+ mp4_LimitMV(&mvCbCr, &mvCbCr, &limitRectC, dx >> 1, dy >> 1, 8);
+ }
+ } else {
+ IppMotionVector mvFT, mvFB;
+ if (mp4_PredictDecodeFMV(pInfo, pMBinfo, rowNum, colNum, &mvFT, &mvFB) != MP4_STATUS_OK)
+ goto Err_3;
+ mvField[0] = mvFT; mvField[1] = mvFB;
+ if (quarter_sample) {
+ mp4_LimitFMVQ(&mvFT, &mvCur[0], &limitRectL, dx, dy, 16);
+ mp4_LimitFMVQ(&mvFB, &mvCur[2], &limitRectL, dx, dy, 16);
+ mvTmp[0].dx = (int16_t)mp4_Div2(mvCur[0].dx);
+ mvTmp[0].dy = (int16_t)(mp4_Div2(mvCur[0].dy << 1) >> 1);
+ mvTmp[2].dx = (int16_t)mp4_Div2(mvCur[2].dx);
+ mvTmp[2].dy = (int16_t)(mp4_Div2(mvCur[2].dy << 1) >> 1);
+ mp4_ComputeChromaMV(&mvTmp[0], &mvCbCrT);
+ mp4_ComputeChromaMV(&mvTmp[2], &mvCbCrB);
+ } else {
+ mp4_LimitFMV(&mvFT, &mvCur[0], &limitRectL, dx, dy, 16);
+ mp4_LimitFMV(&mvFB, &mvCur[2], &limitRectL, dx, dy, 16);
+ mp4_ComputeChromaMV(&mvCur[0], &mvCbCrT);
+ mp4_ComputeChromaMV(&mvCur[2], &mvCbCrB);
+ }
+ }
+ } else {
+ ippiCalcGlobalMV_MPEG4(dx, dy, pMBinfo->mv, pInfo->VisualObject.VideoObject.WarpSpec);
+ pMBinfo->mv[1] = pMBinfo->mv[2] = pMBinfo->mv[3] = pMBinfo->mv[0];
+ }
+ }
+ if (!obmc_disable) {
+ // OBMC for previous MB
+ if (colNum > 0)
+ if (pMBinfo[-1].type < IPPVC_MBTYPE_INTRA && !(pMBinfo[-1].field_info & 1)) // previous is marked as INTRA if it was mcsel
+ mp4_OBMC(pInfo, pMBinfo - 1, mvPrev, colNum - 1, rowNum, limitRectL, pYc - 16, stepYc, pYr - 16, stepYr, cbpyPrev, coeffMB, dct_typePrev);
+ if (mb_type < IPPVC_MBTYPE_INTRA && !field_prediction && !mcsel) {
+ cbpyPrev = cbpy;
+ dct_typePrev = dct_type;
+ mvPrev[0] = mvCur[0]; mvPrev[1] = mvCur[1]; mvPrev[2] = mvCur[2]; mvPrev[3] = mvCur[3];
+ if (mp4_DecodeInterMB(pInfo, coeffMB, quant, (cbpy << 2) + cbpc, scan) != MP4_STATUS_OK)
+ goto Err_3;
+ mp4_MC_HP(cbpc & 2, pCbr, stepCbr, pCbc, stepCbc, coeffMB+256, &mvCbCr, rt);
+ mp4_MC_HP(cbpc & 1, pCrr, stepCrr, pCrc, stepCrc, coeffMB+320, &mvCbCr, rt);
+ // OBMC current MB if it is the last in the row
+ if (colNum == mbPerRow - 1)
+ mp4_OBMC(pInfo, pMBinfo, mvPrev, colNum, rowNum, limitRectL, pYc, stepYc, pYr, stepYr, cbpyPrev, coeffMB, dct_typePrev);
+ }
+ }
+ if (mb_type < IPPVC_MBTYPE_INTRA && (obmc_disable || field_prediction || mcsel)) {
+ pat = mb_not_coded ? 0 : ((cbpy << 2) + cbpc);
+ if (pat)
+ if (mp4_DecodeInterMB(pInfo, coeffMB, quant, pat, scan) != MP4_STATUS_OK)
+ goto Err_3;
+ if (!mcsel) {
+ if (quarter_sample) {
+ if (!field_prediction) {
+ if (mb_type == IPPVC_MBTYPE_INTER4V) {
+ mp4_Copy8x8QP_8u(pYr, stepYr, pYc, stepYc, &mvCur[0], rt);
+ mp4_Copy8x8QP_8u(pYr+8, stepYr, pYc+8, stepYc, &mvCur[1], rt);
+ mp4_Copy8x8QP_8u(pYr+stepYr*8, stepYr, pYc+stepYc*8, stepYc, &mvCur[2], rt);
+ mp4_Copy8x8QP_8u(pYr+8+stepYr*8, stepYr, pYc+8+stepYc*8, stepYc, &mvCur[3], rt);
+ } else {
+ mp4_Copy16x16QP_8u(pYr, stepYr, pYc, stepYc, &mvCur[0], rt);
+ }
+ } else {
+ mp4_Copy16x8QP_8u(pYr+stepYr*mb_ftfr, stepYr*2, pYc, stepYc*2, &mvCur[0], rt);
+ mp4_Copy16x8QP_8u(pYr+stepYr*mb_fbfr, stepYr*2, pYc+stepYc, stepYc*2, &mvCur[2], rt);
+ }
+ } else {
+ if (!field_prediction) {
+ if (mb_type == IPPVC_MBTYPE_INTER4V) {
+ mp4_Copy8x8HP_8u(pYr, stepYr, pYc, stepYc, &mvCur[0], rt);
+ mp4_Copy8x8HP_8u(pYr+8, stepYr, pYc+8, stepYc, &mvCur[1], rt);
+ mp4_Copy8x8HP_8u(pYr+stepYr*8, stepYr, pYc+stepYc*8, stepYc, &mvCur[2], rt);
+ mp4_Copy8x8HP_8u(pYr+8+stepYr*8, stepYr, pYc+8+stepYc*8, stepYc, &mvCur[3], rt);
+ } else {
+ mp4_Copy16x16HP_8u(pYr, stepYr, pYc, stepYc, &mvCur[0], rt);
+ }
+ } else {
+ mp4_Copy16x8HP_8u(pYr+stepYr*mb_ftfr, stepYr*2, pYc, stepYc*2, &mvCur[0], rt);
+ mp4_Copy16x8HP_8u(pYr+stepYr*mb_fbfr, stepYr*2, pYc+stepYc, stepYc*2, &mvCur[2], rt);
+ }
+ }
+ if (!dct_type) {
+ mp4_AddResidual(cbpy & 8, pYc, stepYc, coeffMB);
+ mp4_AddResidual(cbpy & 4, pYc+8, stepYc, coeffMB+64);
+ mp4_AddResidual(cbpy & 2, pYc+stepYc*8, stepYc, coeffMB+128);
+ mp4_AddResidual(cbpy & 1, pYc+stepYc*8+8, stepYc, coeffMB+192);
+ } else {
+ mp4_AddResidual(cbpy & 8, pYc, stepYc*2, coeffMB);
+ mp4_AddResidual(cbpy & 4, pYc+8, stepYc*2, coeffMB+64);
+ mp4_AddResidual(cbpy & 2, pYc+stepYc, stepYc*2, coeffMB+128);
+ mp4_AddResidual(cbpy & 1, pYc+stepYc+8, stepYc*2, coeffMB+192);
+ }
+ if (!field_prediction) {
+ mp4_MC_HP(cbpc & 2, pCbr, stepCbr, pCbc, stepCbc, coeffMB+256, &mvCbCr, rt);
+ mp4_MC_HP(cbpc & 1, pCrr, stepCrr, pCrc, stepCrc, coeffMB+320, &mvCbCr, rt);
+ } else {
+ mp4_Copy8x4HP_8u(pCbr+(mb_ftfr ? stepCbr : 0), stepCbr*2, pCbc, stepCbc*2, &mvCbCrT, rt);
+ mp4_Copy8x4HP_8u(pCrr+(mb_ftfr ? stepCrr : 0), stepCrr*2, pCrc, stepCrc*2, &mvCbCrT, rt);
+ mp4_Copy8x4HP_8u(pCbr+(mb_fbfr ? stepCbr : 0), stepCbr*2, pCbc+stepCbc, stepCbc*2, &mvCbCrB, rt);
+ mp4_Copy8x4HP_8u(pCrr+(mb_fbfr ? stepCrr : 0), stepCrr*2, pCrc+stepCrc, stepCrc*2, &mvCbCrB, rt);
+ mp4_AddResidual(cbpc & 2, pCbc, stepCbc, coeffMB+256);
+ mp4_AddResidual(cbpc & 1, pCrc, stepCrc, coeffMB+320);
+ }
+ } else {
+ IppiRect mbRect;
+
+ mbRect.x = dx; mbRect.y = dy; mbRect.width = mbRect.height = 16;
+ ippiWarpLuma_MPEG4_8u_C1R(pInfo->VisualObject.rFrame->pY, stepYr, pYc, stepYc, &mbRect, pInfo->VisualObject.VideoObject.WarpSpec);
+ mbRect.x >>= 1; mbRect.y >>= 1; mbRect.width = mbRect.height = 8;
+ ippiWarpChroma_MPEG4_8u_P2R(pInfo->VisualObject.rFrame->pCb, stepCbr, pInfo->VisualObject.rFrame->pCr, stepCrr, pCbc, stepCbc, pCrc, stepCrc, &mbRect, pInfo->VisualObject.VideoObject.WarpSpec);
+ if (pat) {
+ if (!dct_type) {
+ mp4_AddResidual(cbpy & 8, pYc, stepYc, coeffMB);
+ mp4_AddResidual(cbpy & 4, pYc+8, stepYc, coeffMB+64);
+ mp4_AddResidual(cbpy & 2, pYc+stepYc*8, stepYc, coeffMB+128);
+ mp4_AddResidual(cbpy & 1, pYc+stepYc*8+8, stepYc, coeffMB+192);
+ } else {
+ mp4_AddResidual(cbpy & 8, pYc, stepYc*2, coeffMB);
+ mp4_AddResidual(cbpy & 4, pYc+8, stepYc*2, coeffMB+64);
+ mp4_AddResidual(cbpy & 2, pYc+stepYc, stepYc*2, coeffMB+128);
+ mp4_AddResidual(cbpy & 1, pYc+stepYc+8, stepYc*2, coeffMB+192);
+ }
+ mp4_AddResidual(cbpc & 2, pCbc, stepCbc, coeffMB+256);
+ mp4_AddResidual(cbpc & 1, pCrc, stepCrc, coeffMB+320);
+ }
+ }
+ }
+ pMBinfo ++;
+ mvField += 2;
+ mbInVideoPacket ++;
+ colNum ++;
+ if (colNum == mbPerRow) {
+ colNum = 0;
+ rowNum ++;
+ if (rowNum == mbPerCol) {
+ // skip stuffing
+ while (mp4_ShowBits(pInfo, 10) == 1)
+ mp4_FlushBits(pInfo, 10);
+ return sts;
+ }
+ pYc += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYc << 4) - stepYc;
+ pCbc += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbc << 3) - stepCbc;
+ pCrc += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrc << 3) - stepCrc;
+ pYr += (2 * MP4_NUM_EXT_MB + 1) * 16 + (stepYr << 4) - stepYr;
+ pCbr += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCbr << 3) - stepCbr;
+ pCrr += (2 * MP4_NUM_EXT_MB + 1) * 8 + (stepCrr << 3) - stepCrr;
+ } else {
+ pYc += 16; pCrc += 8; pCbc += 8;
+ pYr += 16; pCrr += 8; pCbr += 8;
+ }
+ }
+ if (!pInfo->VisualObject.VideoObject.resync_marker_disable) {
+ int32_t found;
+ErrRet_3:
+ if (mp4_CheckDecodeVideoPacket(pInfo, &found) == MP4_STATUS_OK) {
+ if (found) {
+ mbInVideoPacket = pInfo->VisualObject.VideoObject.VideoObjectPlane.macroblock_num - mbCurr;
+ quant = pInfo->VisualObject.VideoObject.VideoObjectPlane.quant_scale;
+ mbCurr = pInfo->VisualObject.VideoObject.VideoObjectPlane.macroblock_num;
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, mbCurr - rowNum * mbPerRow - colNum);
+ rowNum = mbCurr / mbPerRow;
+ colNum = mbCurr % mbPerRow;
+ pYc = pInfo->VisualObject.cFrame->pY + (rowNum * stepYc + colNum) * 16; pCbc = pInfo->VisualObject.cFrame->pCb + (rowNum * stepCbc + colNum) * 8; pCrc = pInfo->VisualObject.cFrame->pCr + (rowNum * stepCrc + colNum) * 8;
+ pYr = pInfo->VisualObject.rFrame->pY + (rowNum * stepYr + colNum) * 16; pCbr = pInfo->VisualObject.rFrame->pCb + (rowNum * stepCbr + colNum) * 8; pCrr = pInfo->VisualObject.rFrame->pCr + (rowNum * stepCrr + colNum) * 8;
+ pMBinfo = pInfo->VisualObject.VideoObject.MBinfo + mbCurr;
+ mvField = pInfo->VisualObject.VideoObject.FieldMV + 2 * mbCurr;
+ break;
+ }
+ } else
+ goto Err_3;
+ }
+ }
+ // mark MBs the previous videopacket as invalid for prediction
+ for (i = 1; i <= IPP_MIN(mbInVideoPacket, mbPerRow + 1); i ++) {
+ pMBinfo[-i].validPred = 0;
+ }
+ }
+Err_3:
+ sts = MP4_STATUS_ERROR;
+ if (pInfo->stopOnErr)
+ return sts;
+ if (pInfo->VisualObject.VideoObject.resync_marker_disable || !mp4_SeekResyncMarker(pInfo)) {
+ mp4_CopyMacroBlocks(pInfo->VisualObject.rFrame, pInfo->VisualObject.cFrame, mbPerRow, rowNum, colNum, pInfo->VisualObject.VideoObject.MacroBlockPerVOP - rowNum * mbPerRow - colNum);
+ return sts;
+ }
+ goto ErrRet_3;
+ }
+}
+
+
+
diff --git a/Src/mpeg4dec/mp4def.h b/Src/mpeg4dec/mp4def.h
new file mode 100644
index 000000000..603ebf2d7
--- /dev/null
+++ b/Src/mpeg4dec/mp4def.h
@@ -0,0 +1,975 @@
+/* ///////////////////////////////////////////////////////////////////////
+//
+// INTEL CORPORATION PROPRIETARY INFORMATION
+// This software is supplied under the terms of a license agreement or
+// nondisclosure agreement with Intel Corporation and may not be copied
+// or disclosed except in accordance with the terms of that agreement.
+// Copyright (c) 2001-2008 Intel Corporation. All Rights Reserved.
+//
+// Description: MPEG-4 header.
+//
+*/
+
+#pragma once
+
+#include <bfc/platform/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "../tools/staticlib/ipp_px.h"
+#include "ippdefs.h"
+#include "ippcore.h"
+#include "ipps.h"
+#include "ippi.h"
+#include "ippvc.h"
+//#include "vm_debug.h"
+//#include "vm_thread.h"
+
+#pragma warning(disable : 4710) // function not inlined
+#pragma warning(disable : 4514) // unreferenced inline function has been removed CL
+#pragma warning(disable : 4100) // unreferenced formal parameter CL
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//#define USE_INLINE_BITS_FUNC
+#define USE_NOTCODED_STATE
+
+#if defined(__INTEL_COMPILER) || defined(_MSC_VER)
+ #define __INLINE static __inline
+#elif defined( __GNUC__ )
+ #define __INLINE static __inline__
+#else
+ #define __INLINE static
+#endif
+
+#if defined(__INTEL_COMPILER) && !defined(_WIN32_WCE)
+ #define __ALIGN16(type, name, size) \
+ __declspec (align(16)) type name[size]
+#else
+ #if defined(_WIN64) || defined(WIN64) || defined(LINUX64)
+ #define __ALIGN16(type, name, size) \
+ uint8_t _a16_##name[(size)*sizeof(type)+15]; type *name = (type*)(((int64_t)(_a16_##name) + 15) & ~15)
+ #else
+ #define __ALIGN16(type, name, size) \
+ uint8_t _a16_##name[(size)*sizeof(type)+15]; type *name = (type*)(((int32_t)(_a16_##name) + 15) & ~15)
+ #endif
+#endif
+
+#define mp4_CLIP(x, min, max) if ((x) < (min)) (x) = (min); else if ((x) > (max)) (x) = (max)
+#define mp4_CLIPR(x, max) if ((x) > (max)) (x) = (max)
+#define mp4_SWAP(type, x, y) {mp4_Frame *t = (x); (x) = (y); (y) = t;}
+#define mp4_ABS(a) ((a) >= 0 ? (a) : -(a))
+
+/* Timer Info */
+#if defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(WIN64)
+
+#include <windows.h>
+
+ typedef struct _mp4_Timer {
+ LARGE_INTEGER count;
+ LARGE_INTEGER start;
+ LARGE_INTEGER stop;
+ int32_t calls;
+ } mp4_Timer;
+
+ __INLINE void mp4_TimerStart(mp4_Timer *t)
+ {
+ QueryPerformanceCounter(&t->start);
+ }
+
+ __INLINE void mp4_TimerStop(mp4_Timer *t)
+ {
+ QueryPerformanceCounter(&t->stop);
+ t->count.QuadPart += t->stop.QuadPart - t->start.QuadPart;
+ t->calls ++;
+ }
+
+#define TIMER_FREQ_TYPE LARGE_INTEGER
+
+ __INLINE void mp4_GetTimerFreq(TIMER_FREQ_TYPE *f)
+ {
+ QueryPerformanceFrequency(f);
+ }
+
+ __INLINE double mp4_GetTimerSec(mp4_Timer *t, TIMER_FREQ_TYPE f)
+ {
+ return (double)t->count.QuadPart / (double)f.QuadPart;
+ }
+
+#else // LINUX
+
+#include <time.h>
+
+ typedef struct _mp4_Timer {
+ clock_t count;
+ clock_t start;
+ clock_t stop;
+ int32_t calls;
+ } mp4_Timer;
+
+ __INLINE void mp4_TimerStart(mp4_Timer *t)
+ {
+ t->start = clock();
+ }
+
+ __INLINE void mp4_TimerStop(mp4_Timer *t)
+ {
+ t->stop = clock();
+ t->count += t->stop - t->start;
+ t->calls ++;
+ }
+
+#define TIMER_FREQ_TYPE int32_t
+
+ __INLINE void mp4_GetTimerFreq(TIMER_FREQ_TYPE *f)
+ {
+ *f = CLOCKS_PER_SEC;
+ }
+
+ __INLINE double mp4_GetTimerSec(mp4_Timer *t, TIMER_FREQ_TYPE f)
+ {
+ return (double)t->count / (double)f;
+ }
+
+#endif
+
+/* number of exterior MB */
+#define MP4_NUM_EXT_MB 1
+
+/* Statistic Info */
+typedef struct _mp4_Statistic {
+ // VideoObjectLayer Info
+ int32_t nVOP;
+ int32_t nVOP_I;
+ int32_t nVOP_P;
+ int32_t nVOP_B;
+ int32_t nVOP_S;
+ int32_t nMB;
+ int32_t nMB_INTER;
+ int32_t nMB_INTER_Q;
+ int32_t nMB_INTRA;
+ int32_t nMB_INTRA_Q;
+ int32_t nMB_INTER4V;
+ int32_t nMB_DIRECT;
+ int32_t nMB_INTERPOLATE;
+ int32_t nMB_BACKWARD;
+ int32_t nMB_FORWARD;
+ int32_t nMB_NOTCODED;
+ int32_t nB_INTRA_DC;
+ int32_t nB_INTRA_AC;
+ int32_t nB_INTER_C;
+ int32_t nB_INTER_NC;
+ // app Timing Info
+ mp4_Timer time_DecodeShow; // decode + draw + file reading
+ mp4_Timer time_Decode; // decode + file reading
+ mp4_Timer time_DecodeOnly; // decode only
+} mp4_Statistic;
+
+__INLINE void mp4_StatisticInc(int32_t *s)
+{
+ *s = (*s) + 1;
+}
+
+// when using Full Statistic, FPS is less
+#ifdef MP4_FULL_STAT
+#define mp4_StatisticInc_(s) mp4_StatisticInc(s)
+#define mp4_TimerStart_(t) mp4_TimerStart(t)
+#define mp4_TimerStop_(t) mp4_TimerStop(t)
+#else
+#define mp4_StatisticInc_(s)
+#define mp4_TimerStart_(t)
+#define mp4_TimerStop_(t)
+#endif
+
+/* status codes */
+typedef enum {
+ MP4_STATUS_OK = 0, // no error
+ MP4_STATUS_NO_MEM = -1, // out of memory
+ MP4_STATUS_FILE_ERROR = -2, // file error
+ MP4_STATUS_NOTSUPPORT = -3, // not supported mode
+ MP4_STATUS_PARSE_ERROR = -4, // fail in parse MPEG-4 stream
+ MP4_STATUS_ERROR = -5 // unknown/unspecified error
+} mp4_Status;
+
+/* MPEG-4 start code values */
+// ISO/IEC 14496-2: table 6-3
+enum {
+ MP4_VIDEO_OBJECT_MIN_SC = 0x00,
+ MP4_VIDEO_OBJECT_MAX_SC = 0x1F,
+ MP4_VIDEO_OBJECT_LAYER_MIN_SC = 0x20,
+ MP4_VIDEO_OBJECT_LAYER_MAX_SC = 0x2F,
+ MP4_FGS_BP_MIN_SC = 0x40,
+ MP4_FGS_BP_MAX_SC = 0x5F,
+ MP4_VISUAL_OBJECT_SEQUENCE_SC = 0xB0,
+ MP4_VISUAL_OBJECT_SEQUENCE_EC = 0xB1,
+ MP4_USER_DATA_SC = 0xB2,
+ MP4_GROUP_OF_VOP_SC = 0xB3,
+ MP4_VIDEO_SESSION_ERROR_SC = 0xB4,
+ MP4_VISUAL_OBJECT_SC = 0xB5,
+ MP4_VIDEO_OBJECT_PLANE_SC = 0xB6,
+ MP4_SLICE_SC = 0xB7,
+ MP4_EXTENSION_SC = 0xB8,
+ MP4_FGS_VOP_SC = 0xB9,
+ MP4_FBA_OBJECT_SC = 0xBA,
+ MP4_FBA_OBJECT_PLANE_SC = 0xBB,
+ MP4_MESH_OBJECT_SC = 0xBC,
+ MP4_MESH_OBJECT_PLANE_SC = 0xBD,
+ MP4_STILL_TEXTURE_OBJECT_SC = 0xBE,
+ MP4_TEXTURE_SPATIAL_LAYER_SC = 0xBF,
+ MP4_TEXTURE_SNR_LAYER_SC = 0xC0,
+ MP4_TEXTURE_TILE_SC = 0xC1,
+ MP4_TEXTURE_SHAPE_LAYER_SC = 0xC2,
+ MP4_STUFFING_SC = 0xC3
+};
+
+/* MPEG-4 code values */
+// ISO/IEC 14496-2:2004 table 6-6
+enum {
+ MP4_VISUAL_OBJECT_TYPE_VIDEO = 1,
+ MP4_VISUAL_OBJECT_TYPE_TEXTURE = 2,
+ MP4_VISUAL_OBJECT_TYPE_MESH = 3,
+ MP4_VISUAL_OBJECT_TYPE_FBA = 4,
+ MP4_VISUAL_OBJECT_TYPE_3DMESH = 5
+};
+
+// ISO/IEC 14496-2:2004 table 6-7
+enum {
+ MP4_VIDEO_FORMAT_COMPONENT = 0,
+ MP4_VIDEO_FORMAT_PAL = 1,
+ MP4_VIDEO_FORMAT_NTSC = 2,
+ MP4_VIDEO_FORMAT_SECAM = 3,
+ MP4_VIDEO_FORMAT_MAC = 4,
+ MP4_VIDEO_FORMAT_UNSPECIFIED = 5
+};
+
+// ISO/IEC 14496-2:2004 table 6-8..10
+enum {
+ MP4_VIDEO_COLORS_FORBIDDEN = 0,
+ MP4_VIDEO_COLORS_ITU_R_BT_709 = 1,
+ MP4_VIDEO_COLORS_UNSPECIFIED = 2,
+ MP4_VIDEO_COLORS_RESERVED = 3,
+ MP4_VIDEO_COLORS_ITU_R_BT_470_2_M = 4,
+ MP4_VIDEO_COLORS_ITU_R_BT_470_2_BG = 5,
+ MP4_VIDEO_COLORS_SMPTE_170M = 6,
+ MP4_VIDEO_COLORS_SMPTE_240M = 7,
+ MP4_VIDEO_COLORS_GENERIC_FILM = 8
+};
+
+// ISO/IEC 14496-2:2004 table 6-11
+enum {
+ MP4_VIDEO_OBJECT_TYPE_SIMPLE = 1,
+ MP4_VIDEO_OBJECT_TYPE_SIMPLE_SCALABLE = 2,
+ MP4_VIDEO_OBJECT_TYPE_CORE = 3,
+ MP4_VIDEO_OBJECT_TYPE_MAIN = 4,
+ MP4_VIDEO_OBJECT_TYPE_NBIT = 5,
+ MP4_VIDEO_OBJECT_TYPE_2DTEXTURE = 6,
+ MP4_VIDEO_OBJECT_TYPE_2DMESH = 7,
+ MP4_VIDEO_OBJECT_TYPE_SIMPLE_FACE = 8,
+ MP4_VIDEO_OBJECT_TYPE_STILL_SCALABLE_TEXTURE = 9,
+ MP4_VIDEO_OBJECT_TYPE_ADVANCED_REAL_TIME_SIMPLE = 10,
+ MP4_VIDEO_OBJECT_TYPE_CORE_SCALABLE = 11,
+ MP4_VIDEO_OBJECT_TYPE_ADVANCED_CODING_EFFICIENCY = 12,
+ MP4_VIDEO_OBJECT_TYPE_ADVANCED_SCALABLE_TEXTURE = 13,
+ MP4_VIDEO_OBJECT_TYPE_SIMPLE_FBA = 14,
+ MP4_VIDEO_OBJECT_TYPE_SIMPLE_STUDIO = 15,
+ MP4_VIDEO_OBJECT_TYPE_CORE_STUDIO = 16,
+ MP4_VIDEO_OBJECT_TYPE_ADVANCED_SIMPLE = 17,
+ MP4_VIDEO_OBJECT_TYPE_FINE_GRANULARITY_SCALABLE = 18
+};
+
+// ISO/IEC 14496-2:2004 table 6.17 (maximum defined video_object_layer_shape_extension)
+#define MP4_SHAPE_EXT_NUM 13
+// ISO/IEC 14496-2:2004 table 6-14
+enum {
+ MP4_ASPECT_RATIO_FORBIDDEN = 0,
+ MP4_ASPECT_RATIO_1_1 = 1,
+ MP4_ASPECT_RATIO_12_11 = 2,
+ MP4_ASPECT_RATIO_10_11 = 3,
+ MP4_ASPECT_RATIO_16_11 = 4,
+ MP4_ASPECT_RATIO_40_33 = 5,
+ MP4_ASPECT_RATIO_EXTPAR = 15
+};
+
+// ISO/IEC 14496-2:2004 table 6-15
+#define MP4_CHROMA_FORMAT_420 1
+// ISO/IEC 14496-2:2004 table 6-16
+enum {
+ MP4_SHAPE_TYPE_RECTANGULAR = 0,
+ MP4_SHAPE_TYPE_BINARY = 1,
+ MP4_SHAPE_TYPE_BINARYONLY = 2,
+ MP4_SHAPE_TYPE_GRAYSCALE = 3
+};
+
+// ISO/IEC 14496-2:2004 table 6-19
+#define MP4_SPRITE_STATIC 1
+#define MP4_SPRITE_GMC 2
+// ISO/IEC 14496-2:2004 table 6-24
+enum {
+ MP4_VOP_TYPE_I = 0,
+ MP4_VOP_TYPE_P = 1,
+ MP4_VOP_TYPE_B = 2,
+ MP4_VOP_TYPE_S = 3
+};
+
+// ISO/IEC 14496-2:2004 table 6-26
+enum {
+ MP4_SPRITE_TRANSMIT_MODE_STOP = 0,
+ MP4_SPRITE_TRANSMIT_MODE_PIECE = 1,
+ MP4_SPRITE_TRANSMIT_MODE_UPDATE = 2,
+ MP4_SPRITE_TRANSMIT_MODE_PAUSE = 3
+};
+
+// ISO/IEC 14496-2:2004 table 7-3
+enum {
+ MP4_BAB_TYPE_MVDSZ_NOUPDATE = 0,
+ MP4_BAB_TYPE_MVDSNZ_NOUPDATE = 1,
+ MP4_BAB_TYPE_TRANSPARENT = 2,
+ MP4_BAB_TYPE_OPAQUE = 3,
+ MP4_BAB_TYPE_INTRACAE = 4,
+ MP4_BAB_TYPE_MVDSZ_INTERCAE = 5,
+ MP4_BAB_TYPE_MVDSNZ_INTERCAE = 6
+};
+
+#define MP4_DC_MARKER 0x6B001 // 110 1011 0000 0000 0001
+#define MP4_MV_MARKER 0x1F001 // 1 1111 0000 0000 0001
+
+// ISO/IEC 14496-2:2004 table G.1
+enum {
+ MP4_SIMPLE_PROFILE_LEVEL_1 = 0x01,
+ MP4_SIMPLE_PROFILE_LEVEL_2 = 0x02,
+ MP4_SIMPLE_PROFILE_LEVEL_3 = 0x03,
+ MP4_SIMPLE_PROFILE_LEVEL_0 = 0x08,
+ MP4_SIMPLE_SCALABLE_PROFILE_LEVEL_0 = 0x10,
+ MP4_SIMPLE_SCALABLE_PROFILE_LEVEL_1 = 0x11,
+ MP4_SIMPLE_SCALABLE_PROFILE_LEVEL_2 = 0x12,
+ MP4_CORE_PROFILE_LEVEL_1 = 0x21,
+ MP4_CORE_PROFILE_LEVEL_2 = 0x22,
+ MP4_MAIN_PROFILE_LEVEL_2 = 0x32,
+ MP4_MAIN_PROFILE_LEVEL_3 = 0x33,
+ MP4_MAIN_PROFILE_LEVEL_4 = 0x34,
+ MP4_NBIT_PROFILE_LEVEL_2 = 0x42,
+ MP4_SCALABLE_TEXTURE_PROFILE_LEVEL_1 = 0x51,
+ MP4_SIMPLE_FACE_ANIMATION_PROFILE_LEVEL_1 = 0x61,
+ MP4_SIMPLE_FACE_ANIMATION_PROFILE_LEVEL_2 = 0x62,
+ MP4_SIMPLE_FBA_PROFILE_LEVEL_1 = 0x63,
+ MP4_SIMPLE_FBA_PROFILE_LEVEL_2 = 0x64,
+ MP4_BASIC_ANIMATED_TEXTURE_PROFILE_LEVEL_1 = 0x71,
+ MP4_BASIC_ANIMATED_TEXTURE_PROFILE_LEVEL_2 = 0x72,
+ MP4_HYBRID_PROFILE_LEVEL_1 = 0x81,
+ MP4_HYBRID_PROFILE_LEVEL_2 = 0x82,
+ MP4_ADVANCED_REAL_TIME_SIMPLE_PROFILE_LEVEL_1 = 0x91,
+ MP4_ADVANCED_REAL_TIME_SIMPLE_PROFILE_LEVEL_2 = 0x92,
+ MP4_ADVANCED_REAL_TIME_SIMPLE_PROFILE_LEVEL_3 = 0x93,
+ MP4_ADVANCED_REAL_TIME_SIMPLE_PROFILE_LEVEL_4 = 0x94,
+ MP4_CORE_SCALABLE_PROFILE_LEVEL_1 = 0xA1,
+ MP4_CORE_SCALABLE_PROFILE_LEVEL_2 = 0xA2,
+ MP4_CORE_SCALABLE_PROFILE_LEVEL_3 = 0xA3,
+ MP4_ADVANCED_CODING_EFFICIENCY_PROFILE_LEVEL_1 = 0xB1,
+ MP4_ADVANCED_CODING_EFFICIENCY_PROFILE_LEVEL_2 = 0xB2,
+ MP4_ADVANCED_CODING_EFFICIENCY_PROFILE_LEVEL_3 = 0xB3,
+ MP4_ADVANCED_CODING_EFFICIENCY_PROFILE_LEVEL_4 = 0xB4,
+ MP4_ADVANCED_CORE_PROFILE_LEVEL_1 = 0xC1,
+ MP4_ADVANCED_CORE_PROFILE_LEVEL_2 = 0xC2,
+ MP4_ADVANCED_SCALABLE_TEXTURE_PROFILE_LEVEL_1 = 0xD1,
+ MP4_ADVANCED_SCALABLE_TEXTURE_PROFILE_LEVEL_2 = 0xD2,
+ MP4_ADVANCED_SCALABLE_TEXTURE_PROFILE_LEVEL_3 = 0xD3,
+ MP4_SIMPLE_STUDIO_PROFILE_LEVEL_1 = 0xE1,
+ MP4_SIMPLE_STUDIO_PROFILE_LEVEL_2 = 0xE2,
+ MP4_SIMPLE_STUDIO_PROFILE_LEVEL_3 = 0xE3,
+ MP4_SIMPLE_STUDIO_PROFILE_LEVEL_4 = 0xE4,
+ MP4_CORE_STUDIO_PROFILE_LEVEL_1 = 0xE5,
+ MP4_CORE_STUDIO_PROFILE_LEVEL_2 = 0xE6,
+ MP4_CORE_STUDIO_PROFILE_LEVEL_3 = 0xE7,
+ MP4_CORE_STUDIO_PROFILE_LEVEL_4 = 0xE8,
+ MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_0 = 0xF0,
+ MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_1 = 0xF1,
+ MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_2 = 0xF2,
+ MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_3 = 0xF3,
+ MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_4 = 0xF4,
+ MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_5 = 0xF5,
+ MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_3B = 0xF7,
+ MP4_FGS_PROFILE_LEVEL_0 = 0xF8,
+ MP4_FGS_PROFILE_LEVEL_1 = 0xF9,
+ MP4_FGS_PROFILE_LEVEL_2 = 0xFA,
+ MP4_FGS_PROFILE_LEVEL_3 = 0xFB,
+ MP4_FGS_PROFILE_LEVEL_4 = 0xFC,
+ MP4_FGS_PROFILE_LEVEL_5 = 0xFD
+};
+
+/* Frame Info */
+typedef struct _mp4_Frame {
+ uint8_t* apY; // allocated with border
+ uint8_t* apCb; // allocated with border
+ uint8_t* apCr; // allocated with border
+ int32_t stepY;
+ int32_t stepCr;
+ int32_t stepCb;
+ uint8_t* pY; // real pointer
+ uint8_t* pCb; // real pointer
+ uint8_t* pCr; // real pointer
+ int32_t type;
+ int64_t time;
+ int32_t mbPerRow; // info for realloc VOP with Shape
+ int32_t mbPerCol;
+ uint8_t* apB; // for binary mask
+ uint8_t* pB;
+ uint8_t* apA[3]; // for aux components
+ uint8_t* pA[3];
+ uint8_t* mid;
+ uint64_t timestamp; // user-provided timestamp
+ int QP;
+ unsigned int reference_count;
+ int outputted; // for debugging purposes
+ int sprite; // 0 - frame, 1 - sprite
+ struct _mp4_Frame *next; // benski> for linked list of display & free frames
+} mp4_Frame;
+
+/* Block Info for Intra Prediction */
+typedef struct _mp4_IntraPredBlock {
+ struct _mp4_IntraPredBlock *predA;
+ struct _mp4_IntraPredBlock *predB;
+ struct _mp4_IntraPredBlock *predC;
+ int16_t dct_acA[8];
+ int16_t dct_acC[8];
+ int16_t dct_dc;
+} mp4_IntraPredBlock;
+
+/* Buffer for Intra Prediction */
+typedef struct _mp4_IntraPredBuff {
+ uint8_t *quant; // quant buffer;
+ mp4_IntraPredBlock dcB[6]; // blocks for Left-Top DC only
+ mp4_IntraPredBlock *block;
+} mp4_IntraPredBuff;
+
+/* MacroBlock Info Data Partitioned mode */
+typedef struct _mp4_DataPartMacroBlock {
+ int16_t dct_dc[6];
+ uint8_t type;
+ uint8_t not_coded;
+ uint8_t mcsel;
+ uint8_t ac_pred_flag;
+ uint8_t pat;
+ uint8_t quant;
+} mp4_DataPartMacroBlock;
+
+/* MacroBlock Info for Motion */
+typedef struct _mp4_MacroBlock {
+ IppMotionVector mv[4];
+ uint8_t validPred; // for MV pred, OBMC
+ uint8_t type; // for OBMC, BVOP
+ uint8_t not_coded; // for OBMC, BVOP
+ uint8_t field_info; // for Interlaced BVOP Direct mode
+} mp4_MacroBlock;
+
+/* Group Of Video Object Plane Info */
+typedef struct _mp4_GroupOfVideoObjectPlane {
+ int64_t time_code;
+ int32_t closed_gov;
+ int32_t broken_link;
+} mp4_GroupOfVideoObjectPlane;
+
+/* Video Object Plane Info */
+typedef struct _mp4_VideoObjectPlane {
+ int32_t coding_type;
+ int32_t modulo_time_base;
+ int32_t time_increment;
+ int32_t coded;
+ int32_t id; // verid != 1 (newpred)
+ int32_t id_for_prediction_indication; // verid != 1 (newpred)
+ int32_t id_for_prediction; // verid != 1 (newpred)
+ int32_t rounding_type;
+ int32_t reduced_resolution; // verid != 1
+ int32_t vop_width;
+ int32_t vop_height;
+ int32_t vop_horizontal_mc_spatial_ref;
+ int32_t vop_vertical_mc_spatial_ref;
+ int32_t background_composition;
+ int32_t change_conv_ratio_disable;
+ int32_t vop_constant_alpha;
+ int32_t vop_constant_alpha_value;
+ int32_t intra_dc_vlc_thr;
+ int32_t top_field_first;
+ int32_t alternate_vertical_scan_flag;
+ int32_t sprite_transmit_mode;
+ int32_t warping_mv_code_du[4];
+ int32_t warping_mv_code_dv[4];
+ int32_t brightness_change_factor;
+ int32_t quant;
+ int32_t alpha_quant[3];
+ int32_t fcode_forward;
+ int32_t fcode_backward;
+ int32_t shape_coding_type;
+ int32_t load_backward_shape;
+ int32_t ref_select_code;
+ int32_t dx;
+ int32_t dy;
+ int32_t quant_scale;
+ int32_t macroblock_num;
+ int32_t vop_id;
+ int32_t vop_id_for_prediction_indication;
+ int32_t vop_id_for_prediction;
+} mp4_VideoObjectPlane;
+
+/* mp4_ComplexityEstimation Info */
+typedef struct _mp4_ComplexityEstimation {
+ int32_t estimation_method;
+ int32_t shape_complexity_estimation_disable;
+ int32_t opaque;
+ int32_t transparent;
+ int32_t intra_cae;
+ int32_t inter_cae;
+ int32_t no_update;
+ int32_t upsampling;
+ int32_t texture_complexity_estimation_set_1_disable;
+ int32_t intra_blocks;
+ int32_t inter_blocks;
+ int32_t inter4v_blocks;
+ int32_t not_coded_blocks;
+ int32_t texture_complexity_estimation_set_2_disable;
+ int32_t dct_coefs;
+ int32_t dct_lines;
+ int32_t vlc_symbols;
+ int32_t vlc_bits;
+ int32_t motion_compensation_complexity_disable;
+ int32_t apm;
+ int32_t npm;
+ int32_t interpolate_mc_q;
+ int32_t forw_back_mc_q;
+ int32_t halfpel2;
+ int32_t halfpel4;
+ int32_t version2_complexity_estimation_disable; // verid != 1
+ int32_t sadct; // verid != 1
+ int32_t quarterpel; // verid != 1
+ int32_t dcecs_opaque;
+ int32_t dcecs_transparent;
+ int32_t dcecs_intra_cae;
+ int32_t dcecs_inter_cae;
+ int32_t dcecs_no_update;
+ int32_t dcecs_upsampling;
+ int32_t dcecs_intra_blocks;
+ int32_t dcecs_inter_blocks;
+ int32_t dcecs_inter4v_blocks;
+ int32_t dcecs_not_coded_blocks;
+ int32_t dcecs_dct_coefs;
+ int32_t dcecs_dct_lines;
+ int32_t dcecs_vlc_symbols;
+ int32_t dcecs_vlc_bits;
+ int32_t dcecs_apm;
+ int32_t dcecs_npm;
+ int32_t dcecs_interpolate_mc_q;
+ int32_t dcecs_forw_back_mc_q;
+ int32_t dcecs_halfpel2;
+ int32_t dcecs_halfpel4;
+ int32_t dcecs_sadct; // verid != 1
+ int32_t dcecs_quarterpel; // verid != 1
+} mp4_ComplexityEstimation;
+
+/* mp4_Scalability Info */
+typedef struct _mp4_ScalabilityParameters {
+ int32_t dummy;
+} mp4_ScalabilityParameters;
+
+/* VOLControlParameters Info */
+typedef struct _mp4_VOLControlParameters {
+ int32_t chroma_format;
+ int32_t low_delay;
+ int32_t vbv_parameters;
+ int32_t bit_rate;
+ int32_t vbv_buffer_size;
+ int32_t vbv_occupancy;
+} mp4_VOLControlParameters;
+
+/* Video Object Plane with int16_t header Info */
+typedef struct _mp4_VideoObjectPlaneH263 {
+ int32_t temporal_reference;
+ int32_t split_screen_indicator;
+ int32_t document_camera_indicator;
+ int32_t full_picture_freeze_release;
+ int32_t source_format;
+ int32_t picture_coding_type;
+ int32_t vop_quant;
+ int32_t gob_number;
+ int32_t num_gobs_in_vop;
+ int32_t num_macroblocks_in_gob;
+ int32_t gob_header_empty;
+ int32_t gob_frame_id;
+ int32_t quant_scale;
+ int32_t num_rows_in_gob;
+} mp4_VideoObjectPlaneH263;
+
+/* Video Object Info */
+typedef struct _mp4_VideoObject {
+// iso part
+ int32_t id;
+ int32_t short_video_header;
+ int32_t random_accessible_vol;
+ int32_t type_indication;
+ int32_t is_identifier;
+ int32_t verid;
+ int32_t priority;
+ int32_t aspect_ratio_info;
+ int32_t aspect_ratio_info_par_width;
+ int32_t aspect_ratio_info_par_height;
+ int32_t is_vol_control_parameters;
+ mp4_VOLControlParameters VOLControlParameters;
+ int32_t shape;
+ int32_t shape_extension; // verid != 1
+ int32_t vop_time_increment_resolution;
+ int32_t vop_time_increment_resolution_bits;
+ int32_t fixed_vop_rate;
+ int32_t fixed_vop_time_increment;
+ int32_t width;
+ int32_t height;
+ int32_t interlaced;
+ int32_t obmc_disable;
+ int32_t sprite_enable; // if verid != 1 (2 bit GMC is added)
+ int32_t sprite_width;
+ int32_t sprite_height;
+ int32_t sprite_left_coordinate;
+ int32_t sprite_top_coordinate;
+ int32_t sprite_warping_points;
+ int32_t sprite_warping_accuracy;
+ int32_t sprite_brightness_change;
+ int32_t low_latency_sprite_enable;
+ int32_t sadct_disable; // verid != 1
+ int32_t not_8_bit;
+ int32_t quant_precision;
+ int32_t bits_per_pixel;
+ int32_t no_gray_quant_update;
+ int32_t composition_method;
+ int32_t linear_composition;
+ int32_t quant_type;
+ int32_t load_intra_quant_mat;
+ uint8_t intra_quant_mat[64];
+ int32_t load_nonintra_quant_mat;
+ uint8_t nonintra_quant_mat[64];
+ int32_t load_intra_quant_mat_grayscale[3];
+ uint8_t intra_quant_mat_grayscale[3][64];
+ int32_t load_nonintra_quant_mat_grayscale[3];
+ uint8_t nonintra_quant_mat_grayscale[3][64];
+ int32_t quarter_sample; // verid != 1
+ int32_t complexity_estimation_disable;
+ mp4_ComplexityEstimation ComplexityEstimation;
+ int32_t resync_marker_disable;
+ int32_t data_partitioned;
+ int32_t reversible_vlc;
+ int32_t newpred_enable; // verid != 1
+ int32_t requested_upstream_message_type;// verid != 1
+ int32_t newpred_segment_type; // verid != 1
+ int32_t reduced_resolution_vop_enable; // verid != 1
+ int32_t scalability;
+ mp4_ScalabilityParameters ScalabilityParameters;
+ mp4_GroupOfVideoObjectPlane GroupOfVideoObjectPlane;
+ mp4_VideoObjectPlane VideoObjectPlane;
+ mp4_VideoObjectPlaneH263 VideoObjectPlaneH263;
+// app part
+ int32_t VOPindex;
+ int32_t MacroBlockPerRow;
+ int32_t MacroBlockPerCol;
+ int32_t MacroBlockPerVOP;
+ int32_t mbns; // num bits for MacroBlockPerVOP
+ mp4_MacroBlock* MBinfo;
+ mp4_IntraPredBuff IntraPredBuff;
+ mp4_DataPartMacroBlock* DataPartBuff;
+ IppiQuantInvIntraSpec_MPEG4* QuantInvIntraSpec;
+ IppiQuantInvInterSpec_MPEG4* QuantInvInterSpec;
+ IppiWarpSpec_MPEG4* WarpSpec;
+ // for B-VOP
+ int32_t prevPlaneIsB;
+ // for interlaced B-VOP direct mode
+ int32_t Tframe;
+ IppMotionVector* FieldMV;
+ // for B-VOP direct mode
+ int32_t TRB, TRD;
+ // time increment of past and future VOP for B-VOP
+ int64_t rTime, nTime;
+ // VOP global time
+ int64_t vop_sync_time, vop_sync_time_b;
+#ifdef USE_NOTCODED_STATE
+ // not_coded MB state
+ uint8_t* ncState;
+ int32_t ncStateCleared;
+#endif
+} mp4_VideoObject;
+
+/* StillTexture Object Info */
+typedef struct _mp4_StillTextureObject {
+ int32_t dummy;
+} mp4_StillTextureObject;
+
+/* Mesh Object Info */
+typedef struct _mp4_MeshObject {
+ int32_t dummy;
+} mp4_MeshObject;
+
+/* Face Object Info */
+typedef struct _mp4_FaceObject {
+ int32_t dummy;
+} mp4_FaceObject;
+
+/* video_signal_type Info */
+typedef struct _mp4_VideoSignalType {
+ int32_t is_video_signal_type;
+ int32_t video_format;
+ int32_t video_range;
+ int32_t is_colour_description;
+ int32_t colour_primaries;
+ int32_t transfer_characteristics;
+ int32_t matrix_coefficients;
+} mp4_VideoSignalType;
+
+/* Visual Object Info */
+typedef struct _mp4_VisualObject {
+ int32_t is_identifier;
+ int32_t verid;
+ int32_t priority;
+ int32_t type;
+ mp4_VideoSignalType VideoSignalType;
+ mp4_VideoObject VideoObject;
+ mp4_StillTextureObject StillTextureObject;
+ mp4_MeshObject MeshObject;
+ mp4_FaceObject FaceObject;
+ mp4_Frame *sFrame; // static sprite
+ mp4_Frame *cFrame; // current TODO make pointer
+ mp4_Frame *rFrame; // reference in past TODO make pointer
+ mp4_Frame *nFrame; // reference in future TODO make pointer
+ int32_t frameCount;
+ int32_t frameInterval;
+ int32_t frameScale;
+ mp4_Statistic Statistic;
+ mp4_Frame *frame_cache; // linked list of available frames (malloc cache)
+ mp4_Frame *sprite_cache; // linked list of available sprite (malloc cache)
+ mp4_Frame *display_frames; // linked list of display frames
+} mp4_VisualObject;
+
+/* Full Info */
+typedef struct _mp4_Info {
+ int32_t ftype; // 0 - raw, 1 - mp4, 2 - avi
+ int32_t ftype_f; // ftype == 1 (0 - QuickTime(tm)), ftype == 2 (0 - DivX(tm) v. < 5, XVID, 1 - DivX(tm) v. >= 5)
+ uint8_t* buffer; /* buffer header for saving MPEG-4 stream */
+ size_t buflen; /* total buffer length */
+ size_t len; /* valid data in buffer */
+ uint8_t* bufptr; /* current frame, point to header or data */
+ int32_t bitoff; /* mostly point to next frame header or PSC */
+ int32_t profile_and_level_indication;
+ mp4_VisualObject VisualObject;
+ int32_t stopOnErr;
+ int strictSyntaxCheck;
+ int noPVOPs;
+ int noBVOPs;
+} mp4_Info;
+
+/* bitstream functions */
+extern uint8_t* mp4_FindStartCodePtr(mp4_Info* pInfo);
+extern uint8_t* mp4_FindStartCodeOrShortPtr(mp4_Info* pInfo);
+extern int32_t mp4_SeekStartCodePtr(mp4_Info* pInfo);
+extern int32_t mp4_SeekStartCodeOrShortPtr(mp4_Info* pInfo);
+extern int32_t mp4_SeekStartCodeValue(mp4_Info* pInfo, uint8_t code);
+extern uint8_t* mp4_FindShortVideoStartMarkerPtr(mp4_Info* pInfo);
+extern int32_t mp4_SeekShortVideoStartMarker(mp4_Info* pInfo);
+extern int32_t mp4_SeekGOBMarker(mp4_Info* pInfo);
+extern int32_t mp4_SeekResyncMarker(mp4_Info* pInfo);
+extern int32_t mp4_FindResyncMarker(mp4_Info* pInfo);
+extern int mp4_IsStartCodeOrShort(mp4_Info* pInfo);
+extern int mp4_IsStartCodeValue(mp4_Info* pInfo, int min, int max);
+extern int mp4_IsShortCode(mp4_Info* pInfo);
+
+/* tables */
+typedef struct _mp4_VLC1 {
+ uint8_t code;
+ uint8_t len;
+} mp4_VLC1;
+
+extern const uint8_t mp4_DefaultIntraQuantMatrix[];
+extern const uint8_t mp4_DefaultNonIntraQuantMatrix[];
+extern const uint8_t mp4_ClassicalZigzag[];
+extern const uint8_t mp4_DCScalerLuma[];
+extern const uint8_t mp4_DCScalerChroma[];
+extern const uint8_t mp4_cCbCrMvRound16[];
+extern const uint8_t mp4_cCbCrMvRound12[];
+extern const uint8_t mp4_cCbCrMvRound8[];
+extern const uint8_t mp4_cCbCrMvRound4[];
+extern const Ipp8s mp4_dquant[];
+extern const mp4_VLC1 mp4_cbpy1[];
+extern const mp4_VLC1 mp4_cbpy2[];
+extern const mp4_VLC1 mp4_cbpy3[];
+extern const mp4_VLC1 mp4_cbpy4[];
+extern const mp4_VLC1* mp4_cbpy_t[];
+extern const uint8_t mp4_cbpy_b[];
+extern const int32_t mp4_DC_vlc_Threshold[];
+extern const uint8_t mp4_PVOPmb_type[];
+extern const uint8_t mp4_PVOPmb_cbpc[];
+extern const uint8_t mp4_PVOPmb_bits[];
+extern const mp4_VLC1 mp4_BVOPmb_type[];
+extern const mp4_VLC1 mp4_MVD_B12_1[];
+extern const mp4_VLC1 mp4_MVD_B12_2[];
+extern const int32_t mp4_H263_width[];
+extern const int32_t mp4_H263_height[];
+extern const int32_t mp4_H263_mbgob[];
+extern const int32_t mp4_H263_gobvop[];
+extern const int32_t mp4_H263_rowgob[];
+extern const uint8_t mp4_aux_comp_count[];
+extern const uint8_t mp4_aux_comp_is_alpha[];
+extern const uint8_t mp4_BABtypeIntra[][3];
+extern const int32_t mp4_DivIntraDivisor[];
+
+// project functions
+extern void mp4_Error(const char *str);
+//#define mp4_Error(str) puts(str)
+extern mp4_Status mp4_InitVOL(mp4_Info *pInfo);
+extern mp4_Status mp4_FreeVOL(mp4_Info *pInfo);
+extern void mp4_ResetVOL(mp4_Info *pInfo);
+//extern void mp4_ShowFrame(mp4_Frame *frame);
+#define mp4_ShowFrame(frame)
+extern mp4_Status mp4_Parse_VisualObjectSequence(mp4_Info* pInfo);
+extern mp4_Status mp4_Parse_VisualObject(mp4_Info* pInfo);
+extern mp4_Status mp4_Parse_VideoObject(mp4_Info* pInfo);
+extern mp4_Status mp4_Parse_GroupOfVideoObjectPlane(mp4_Info* pInfo);
+extern mp4_Status mp4_Parse_VideoObjectPlane(mp4_Info* pInfo);
+extern mp4_Status mp4_DecodeVideoObjectPlane(mp4_Info* pInfo);
+
+#ifndef USE_INLINE_BITS_FUNC
+extern uint32_t mp4_ShowBits(mp4_Info* pInfo, int32_t n);
+extern uint32_t mp4_ShowBit(mp4_Info* pInfo);
+extern uint32_t mp4_ShowBits9(mp4_Info* pInfo, int32_t n);
+extern void mp4_FlushBits(mp4_Info* pInfo, int32_t n);
+extern uint32_t mp4_GetBits(mp4_Info* pInfo, int32_t n);
+//extern uint32_t mp4_GetBit(mp4_Info* pInfo);
+extern uint32_t mp4_GetBits9(mp4_Info* pInfo, int32_t n);
+extern void mp4_AlignBits(mp4_Info* pInfo);
+extern void mp4_AlignBits7F(mp4_Info* pInfo);
+extern uint32_t mp4_ShowBitsAlign(mp4_Info* pInfo, int32_t n);
+extern uint32_t mp4_ShowBitsAlign7F(mp4_Info* pInfo, int32_t n);
+#else
+__INLINE uint32_t mp4_ShowBits(mp4_Info* pInfo, int32_t n)
+{
+ uint8_t* ptr = pInfo->bufptr;
+ uint32_t tmp = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
+ tmp <<= pInfo->bitoff;
+ tmp >>= 32 - n;
+ return tmp;
+}
+
+__INLINE uint32_t mp4_ShowBit(mp4_Info* pInfo)
+{
+ uint32_t tmp = pInfo->bufptr[0];
+ tmp >>= 7 - pInfo->bitoff;
+ return (tmp & 1);
+}
+
+__INLINE uint32_t mp4_ShowBits9(mp4_Info* pInfo, int32_t n)
+{
+ uint8_t* ptr = pInfo->bufptr;
+ uint32_t tmp = (ptr[0] << 8) | ptr[1];
+ tmp <<= (pInfo->bitoff + 16);
+ tmp >>= 32 - n;
+ return tmp;
+}
+
+__INLINE void mp4_FlushBits(mp4_Info* pInfo, int32_t n)
+{
+ n = n + pInfo->bitoff;
+ pInfo->bufptr += n >> 3;
+ pInfo->bitoff = n & 7;
+}
+
+__INLINE uint32_t mp4_GetBits(mp4_Info* pInfo, int32_t n)
+{
+ uint8_t* ptr = pInfo->bufptr;
+ uint32_t tmp = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
+ tmp <<= pInfo->bitoff;
+ tmp >>= 32 - n;
+ n = n + pInfo->bitoff;
+ pInfo->bufptr += n >> 3;
+ pInfo->bitoff = n & 7;
+ return tmp;
+}
+
+__INLINE uint32_t mp4_GetBits9(mp4_Info* pInfo, int32_t n)
+{
+ uint8_t* ptr = pInfo->bufptr;
+ uint32_t tmp = (ptr[0] << 8) | ptr[1];
+ tmp <<= (pInfo->bitoff + 16);
+ tmp >>= 32 - n;
+ n = n + pInfo->bitoff;
+ pInfo->bufptr += n >> 3;
+ pInfo->bitoff = n & 7;
+ return tmp;
+}
+
+__INLINE void mp4_AlignBits(mp4_Info* pInfo)
+{
+ if (pInfo->bitoff > 0) {
+ pInfo->bitoff = 0;
+ (pInfo->bufptr)++;
+ }
+}
+
+__INLINE void mp4_AlignBits7F(mp4_Info* pInfo)
+{
+ if (pInfo->bitoff > 0) {
+ pInfo->bitoff = 0;
+ (pInfo->bufptr)++;
+ } else {
+ if (*pInfo->bufptr == 0x7F)
+ (pInfo->bufptr)++;
+ }
+}
+
+__INLINE uint32_t mp4_ShowBitsAlign(mp4_Info* pInfo, int32_t n)
+{
+ uint8_t* ptr = pInfo->bitoff ? (pInfo->bufptr + 1) : pInfo->bufptr;
+ uint32_t tmp = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
+ tmp >>= 32 - n;
+ return tmp;
+}
+
+__INLINE uint32_t mp4_ShowBitsAlign7F(mp4_Info* pInfo, int32_t n)
+{
+ uint8_t* ptr = pInfo->bitoff ? (pInfo->bufptr + 1) : pInfo->bufptr;
+ uint32_t tmp;
+ if (!pInfo->bitoff) {
+ if (*ptr == 0x7F)
+ ptr ++;
+ }
+ tmp = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
+ tmp >>= 32 - n;
+ return tmp;
+}
+
+#endif // USE_INLINE_BITS_FUNC
+
+__INLINE uint32_t mp4_GetBit(mp4_Info* pInfo)
+{
+ uint32_t tmp = pInfo->bufptr[0];
+ if (pInfo->bitoff != 7) {
+ tmp >>= 7 - pInfo->bitoff;
+ pInfo->bitoff ++;
+ } else {
+ pInfo->bitoff = 0;
+ pInfo->bufptr ++;
+ }
+ return (tmp & 1);
+}
+
+__INLINE int32_t mp4_GetMarkerBit(mp4_Info* pInfo) {
+ if (!mp4_GetBit(pInfo)) {
+ mp4_Error("Error: wrong marker bit");
+ return 0;
+ }
+ return 1;
+}
+
+// added by benski
+extern mp4_Frame *CreateFrame(mp4_VisualObject *object);
+extern void ReleaseFrame(mp4_VisualObject *object, mp4_Frame *frame);
+extern mp4_Frame *GetDisplayFrame(mp4_VisualObject *object);
+extern void DisplayFrame(mp4_VisualObject *object, mp4_Frame *frame);
+extern void FreeCache(mp4_VisualObject *object);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/Src/mpeg4dec/mp4parse.c b/Src/mpeg4dec/mp4parse.c
new file mode 100644
index 000000000..2db9308b8
--- /dev/null
+++ b/Src/mpeg4dec/mp4parse.c
@@ -0,0 +1,1109 @@
+/* ///////////////////////////////////////////////////////////////////////
+//
+// INTEL CORPORATION PROPRIETARY INFORMATION
+// This software is supplied under the terms of a license agreement or
+// nondisclosure agreement with Intel Corporation and may not be copied
+// or disclosed except in accordance with the terms of that agreement.
+// Copyright (c) 2001-2007 Intel Corporation. All Rights Reserved.
+//
+// Description: Parses MPEG-4 headers
+//
+*/
+
+#include "mp4def.h"
+
+
+mp4_Status mp4_Parse_VisualObjectSequence(mp4_Info* pInfo)
+{
+ pInfo->profile_and_level_indication = mp4_GetBits9(pInfo, 8);
+ if (pInfo->profile_and_level_indication != MP4_SIMPLE_PROFILE_LEVEL_1 &&
+ pInfo->profile_and_level_indication != MP4_SIMPLE_PROFILE_LEVEL_2 &&
+ pInfo->profile_and_level_indication != MP4_SIMPLE_PROFILE_LEVEL_3 &&
+ pInfo->profile_and_level_indication != MP4_SIMPLE_PROFILE_LEVEL_0 &&
+ pInfo->profile_and_level_indication != MP4_CORE_PROFILE_LEVEL_1 &&
+ pInfo->profile_and_level_indication != MP4_CORE_PROFILE_LEVEL_2 &&
+ pInfo->profile_and_level_indication != MP4_MAIN_PROFILE_LEVEL_2 &&
+ pInfo->profile_and_level_indication != MP4_MAIN_PROFILE_LEVEL_3 &&
+ pInfo->profile_and_level_indication != MP4_MAIN_PROFILE_LEVEL_4 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_REAL_TIME_SIMPLE_PROFILE_LEVEL_1 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_REAL_TIME_SIMPLE_PROFILE_LEVEL_2 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_REAL_TIME_SIMPLE_PROFILE_LEVEL_3 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_REAL_TIME_SIMPLE_PROFILE_LEVEL_4 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_CODING_EFFICIENCY_PROFILE_LEVEL_1 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_CODING_EFFICIENCY_PROFILE_LEVEL_2 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_CODING_EFFICIENCY_PROFILE_LEVEL_3 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_CODING_EFFICIENCY_PROFILE_LEVEL_4 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_CORE_PROFILE_LEVEL_1 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_CORE_PROFILE_LEVEL_2 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_0 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_1 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_2 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_3 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_4 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_5 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_3B) {
+ mp4_Error("Warning: Unsupported profile_and_level_indication");
+ if (pInfo->strictSyntaxCheck)
+ return MP4_STATUS_NOTSUPPORT;
+ }
+ if (pInfo->profile_and_level_indication != MP4_SIMPLE_PROFILE_LEVEL_1 &&
+ pInfo->profile_and_level_indication != MP4_SIMPLE_PROFILE_LEVEL_2 &&
+ pInfo->profile_and_level_indication != MP4_SIMPLE_PROFILE_LEVEL_3 &&
+ pInfo->profile_and_level_indication != MP4_SIMPLE_PROFILE_LEVEL_0 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_0 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_1 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_2 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_3 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_4 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_5 &&
+ pInfo->profile_and_level_indication != MP4_ADVANCED_SIMPLE_PROFILE_LEVEL_3B) {
+ mp4_Error("Warning: Some features of present profile_and_level_indication may be not supported");
+ }
+ return MP4_STATUS_OK;
+}
+
+
+mp4_Status mp4_Parse_VisualObject(mp4_Info* pInfo)
+{
+ mp4_VisualObject *VO = &pInfo->VisualObject;
+
+ VO->is_identifier = mp4_GetBit(pInfo);
+ if (VO->is_identifier) {
+ VO->verid = mp4_GetBits9(pInfo, 4);
+ if ((VO->verid != 1) && (VO->verid != 2) && (VO->verid != 4) && (VO->verid != 5)) {
+ VO->verid = 1;
+ mp4_Error("Warning: Unsupported visual_object_verid");
+ //f if (pInfo->strictSyntaxCheck)
+ //f return MP4_STATUS_NOTSUPPORT;
+ }
+ VO->priority = mp4_GetBits9(pInfo, 3);
+ if (VO->priority == 0) {
+ mp4_Error("Warning: Wrong value of visual_object_priority");
+ //f if (pInfo->strictSyntaxCheck)
+ //f return MP4_STATUS_PARSE_ERROR;
+ }
+ } else
+ VO->verid = 1;
+ VO->type = mp4_GetBits9(pInfo, 4);
+ if (VO->type != MP4_VISUAL_OBJECT_TYPE_VIDEO) {
+ mp4_Error("Error: Unsupported object: visual_object_type != video ID");
+ return MP4_STATUS_NOTSUPPORT;
+ }
+ VO->VideoSignalType.video_format = MP4_VIDEO_FORMAT_UNSPECIFIED;
+ VO->VideoSignalType.video_range = 0;
+ VO->VideoSignalType.colour_primaries = MP4_VIDEO_COLORS_ITU_R_BT_709;
+ VO->VideoSignalType.transfer_characteristics = MP4_VIDEO_COLORS_ITU_R_BT_709;
+ VO->VideoSignalType.matrix_coefficients = MP4_VIDEO_COLORS_ITU_R_BT_709;
+ if (VO->type == MP4_VISUAL_OBJECT_TYPE_VIDEO || VO->type == MP4_VISUAL_OBJECT_TYPE_TEXTURE) {
+ VO->VideoSignalType.is_video_signal_type = mp4_GetBit(pInfo);
+ if (VO->VideoSignalType.is_video_signal_type) {
+ VO->VideoSignalType.video_format = mp4_GetBits9(pInfo, 3);
+ if (VO->VideoSignalType.video_format > MP4_VIDEO_FORMAT_UNSPECIFIED) {
+ mp4_Error("Warning: Wrong value of video_format");
+ //f if (pInfo->strictSyntaxCheck)
+ //f return MP4_STATUS_PARSE_ERROR;
+ }
+ VO->VideoSignalType.video_range = mp4_GetBit(pInfo);
+ VO->VideoSignalType.is_colour_description = mp4_GetBit(pInfo);
+ if (VO->VideoSignalType.is_colour_description) {
+ VO->VideoSignalType.colour_primaries = mp4_GetBits9(pInfo, 8);
+ if (VO->VideoSignalType.colour_primaries == MP4_VIDEO_COLORS_FORBIDDEN) {
+ mp4_Error("Error: Wrong value of colour_primaries");
+ if (pInfo->strictSyntaxCheck)
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ if (VO->VideoSignalType.colour_primaries > MP4_VIDEO_COLORS_GENERIC_FILM) {
+ mp4_Error("Warning: Wrong value of colour_primaries");
+ //f if (pInfo->strictSyntaxCheck)
+ //f return MP4_STATUS_PARSE_ERROR;
+ }
+ VO->VideoSignalType.transfer_characteristics = mp4_GetBits9(pInfo, 8);
+ if (VO->VideoSignalType.transfer_characteristics == 0) {
+ mp4_Error("Error: Wrong value of transfer_characteristics");
+ if (pInfo->strictSyntaxCheck)
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ if (VO->VideoSignalType.transfer_characteristics > 10) {
+ mp4_Error("Warning: Wrong value of transfer_characteristics");
+ //f if (pInfo->strictSyntaxCheck)
+ //f return MP4_STATUS_PARSE_ERROR;
+ }
+ VO->VideoSignalType.matrix_coefficients = mp4_GetBits9(pInfo, 8);
+ if (VO->VideoSignalType.matrix_coefficients == 0) {
+ mp4_Error("Error: Wrong value of matrix_coefficients");
+ if (pInfo->strictSyntaxCheck)
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ if (VO->VideoSignalType.matrix_coefficients > 8) {
+ mp4_Error("Warning: Wrong value of matrix_coefficients");
+ //f if (pInfo->strictSyntaxCheck)
+ //f return MP4_STATUS_PARSE_ERROR;
+ }
+ }
+ }
+ }
+ return MP4_STATUS_OK;
+}
+
+
+static mp4_Status mp4_Parse_QuantMatrix(mp4_Info* pInfo, uint8_t pQM[64])
+{
+ uint32_t code;
+ int32_t i;
+
+ for (i = 0; i < 64; i ++) {
+ code = mp4_GetBits9(pInfo, 8);
+ if (code == 0) break;
+ pQM[mp4_ClassicalZigzag[i]] = (uint8_t)code;
+ }
+ if (i > 0) {
+ code = pQM[mp4_ClassicalZigzag[i-1]];
+ for (; i < 64; i ++)
+ pQM[mp4_ClassicalZigzag[i]] = (uint8_t)code;
+ } else {
+ for (i = 1; i < 64; i ++)
+ pQM[mp4_ClassicalZigzag[i]] = (uint8_t)mp4_ClassicalZigzag[0];
+ }
+ return MP4_STATUS_OK;
+}
+
+
+mp4_Status mp4_Parse_VideoObject(mp4_Info* pInfo)
+{
+ uint32_t code;
+ int32_t i;
+ mp4_VisualObject *VO = &pInfo->VisualObject;
+ mp4_VideoObject *VOL = &pInfo->VisualObject.VideoObject;
+
+ code = mp4_ShowBits(pInfo, 32);
+ // check short_video_start_marker
+ if ((code & (~0x3FF)) == 0x8000) {
+ VOL->short_video_header = 1;
+ VOL->quant_precision = 5;
+ VOL->shape = MP4_SHAPE_TYPE_RECTANGULAR;
+ VOL->obmc_disable = 1;
+ VOL->quant_type = 0;
+ VOL->resync_marker_disable = 1;
+ VOL->data_partitioned = 0;
+ VOL->reversible_vlc = 0;
+ VOL->VideoObjectPlane.rounding_type = 0;
+ VOL->VideoObjectPlane.fcode_forward = 1;
+ VOL->VideoObjectPlane.coded = 1;
+ VOL->interlaced = 0;
+ VOL->complexity_estimation_disable = 1;
+ VOL->scalability = 0;
+ VOL->not_8_bit = 0;
+ VOL->bits_per_pixel = 8;
+ VO->VideoSignalType.colour_primaries = 1;
+ VO->VideoSignalType.transfer_characteristics = 1;
+ VO->VideoSignalType.matrix_coefficients = 6;
+ VO->VideoObject.VideoObjectPlaneH263.source_format = (pInfo->bufptr[4] >> 2) & 0x7;
+ i = VO->VideoObject.VideoObjectPlaneH263.source_format - 1;
+ if (i < 0 || i > 4) {
+ mp4_Error("Error: Bad value for VideoPlaneWithShortHeader.source_format");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ VOL->width = mp4_H263_width[i];
+ VOL->height = mp4_H263_height[i];
+ VOL->VideoObjectPlaneH263.num_gobs_in_vop = mp4_H263_gobvop[i];
+ VOL->VideoObjectPlaneH263.num_macroblocks_in_gob = mp4_H263_mbgob[i];
+ VOL->VideoObjectPlaneH263.num_rows_in_gob = mp4_H263_rowgob[i];
+ VOL->vop_time_increment_resolution = 30000;
+ // VOL->VideoObjectPlane.time_increment = -1001;
+ VOL->VOLControlParameters.low_delay = 1;
+ return MP4_STATUS_OK;
+ }
+ if (code < 256 + MP4_VIDEO_OBJECT_LAYER_MIN_SC || code > 256 + MP4_VIDEO_OBJECT_LAYER_MAX_SC) {
+ mp4_Error("Error: Bad start code for VideoObjectLayer");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ mp4_FlushBits(pInfo, 32);
+ // video_object_start_code is founded
+ VOL->id = code & 15;
+ VOL->short_video_header = 0;
+ VOL->random_accessible_vol = mp4_GetBit(pInfo);
+ VOL->type_indication = mp4_GetBits9(pInfo, 8);
+ if (VOL->type_indication != MP4_VIDEO_OBJECT_TYPE_SIMPLE &&
+ VOL->type_indication != MP4_VIDEO_OBJECT_TYPE_CORE &&
+ VOL->type_indication != MP4_VIDEO_OBJECT_TYPE_MAIN &&
+ VOL->type_indication != MP4_VIDEO_OBJECT_TYPE_ADVANCED_REAL_TIME_SIMPLE &&
+ VOL->type_indication != MP4_VIDEO_OBJECT_TYPE_ADVANCED_CODING_EFFICIENCY &&
+ VOL->type_indication != MP4_VIDEO_OBJECT_TYPE_ADVANCED_SIMPLE) {
+ mp4_Error("Warning: Unsupported video_object_type_indication, some features may be not supported");
+ //f if (pInfo->strictSyntaxCheck)
+ //f return MP4_STATUS_NOTSUPPORT;
+ }
+ VOL->is_identifier = mp4_GetBit(pInfo);
+ if (VOL->is_identifier) {
+ VOL->verid = mp4_GetBits9(pInfo, 4);
+ if ((VOL->verid != 1) && (VOL->verid != 2) && (VOL->verid != 4) && (VOL->verid != 5)) {
+ mp4_Error("Warning: Unsupported video_object_layer_verid");
+ VOL->verid = VO->verid;
+ //f if (pInfo->strictSyntaxCheck)
+ //f return MP4_STATUS_NOTSUPPORT;
+ }
+ VOL->priority = mp4_GetBits9(pInfo, 3);
+ if (VOL->priority == 0) {
+ mp4_Error("Warning: Wrong value of video_object_layer_priority");
+ //f if (pInfo->strictSyntaxCheck)
+ //f return MP4_STATUS_PARSE_ERROR;
+ }
+ } else
+ VOL->verid = VO->verid;
+ VOL->aspect_ratio_info = mp4_GetBits9(pInfo, 4);
+ if (VOL->aspect_ratio_info == MP4_ASPECT_RATIO_FORBIDDEN) {
+ mp4_Error("Error: Wrong value of aspect_ratio_info");
+ if (pInfo->strictSyntaxCheck)
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ if (VOL->aspect_ratio_info > MP4_ASPECT_RATIO_40_33 && VOL->aspect_ratio_info < MP4_ASPECT_RATIO_EXTPAR) {
+ mp4_Error("Warning: Wrong value of aspect_ratio_info");
+ //f if (pInfo->strictSyntaxCheck)
+ //f return MP4_STATUS_PARSE_ERROR;
+ }
+ if (VOL->aspect_ratio_info == MP4_ASPECT_RATIO_EXTPAR) {
+ VOL->aspect_ratio_info_par_width = mp4_GetBits9(pInfo, 8);
+ if (VOL->aspect_ratio_info_par_width == 0) {
+ mp4_Error("Error: Wrong value of par_width");
+ if (pInfo->strictSyntaxCheck)
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ VOL->aspect_ratio_info_par_height = mp4_GetBits9(pInfo, 8);
+ if (VOL->aspect_ratio_info_par_height == 0) {
+ mp4_Error("Error: Wrong value of par_height");
+ if (pInfo->strictSyntaxCheck)
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ }
+ VOL->is_vol_control_parameters = mp4_GetBit(pInfo);
+ if (VOL->type_indication == MP4_VIDEO_OBJECT_TYPE_SIMPLE || VOL->type_indication != MP4_VIDEO_OBJECT_TYPE_ADVANCED_REAL_TIME_SIMPLE)
+ VOL->VOLControlParameters.low_delay = 1;
+ if (VOL->is_vol_control_parameters) {
+ VOL->VOLControlParameters.chroma_format = mp4_GetBits9(pInfo, 2);
+ if (VOL->VOLControlParameters.chroma_format != MP4_CHROMA_FORMAT_420) {
+ mp4_Error("Error: chroma_format != 4:2:0");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ VOL->VOLControlParameters.low_delay = mp4_GetBit(pInfo);
+ VOL->VOLControlParameters.vbv_parameters = mp4_GetBit(pInfo);
+ if (VOL->VOLControlParameters.vbv_parameters) {
+ VOL->VOLControlParameters.bit_rate = mp4_GetBits(pInfo, 15) << 15;
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ VOL->VOLControlParameters.bit_rate += mp4_GetBits(pInfo, 15);
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ if (VOL->VOLControlParameters.bit_rate == 0) {
+ mp4_Error("Error: vbv_parameters bit_rate == 0");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ VOL->VOLControlParameters.vbv_buffer_size = mp4_GetBits(pInfo, 15) << 3;
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ VOL->VOLControlParameters.vbv_buffer_size += mp4_GetBits9(pInfo, 3);
+ if (VOL->VOLControlParameters.vbv_buffer_size == 0) {
+ mp4_Error("Error: vbv_parameters vbv_buffer_size == 0");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ VOL->VOLControlParameters.vbv_occupancy = mp4_GetBits(pInfo, 11) << 15;
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ VOL->VOLControlParameters.vbv_occupancy += mp4_GetBits(pInfo, 15);
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ }
+ }
+ VOL->shape = mp4_GetBits9(pInfo, 2);
+ if (VOL->shape != MP4_SHAPE_TYPE_RECTANGULAR) {
+ mp4_Error("Error: video_object_layer_shape != rectangular (not supported)");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ if (VOL->verid != 1 && VOL->shape == MP4_SHAPE_TYPE_GRAYSCALE) {
+ VOL->shape_extension = mp4_GetBits9(pInfo, 4);
+ if (VOL->shape_extension >= MP4_SHAPE_EXT_NUM) {
+ mp4_Error("Error: wrong value of video_object_layer_shape_extension");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ } else
+ VOL->shape_extension = MP4_SHAPE_EXT_NUM;
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ VOL->vop_time_increment_resolution = mp4_GetBits(pInfo, 16);
+ if (VOL->vop_time_increment_resolution == 0) {
+ mp4_Error("Error: wrong value of vop_time_increment_resolution");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ // define number bits in vop_time_increment_resolution
+ code = VOL->vop_time_increment_resolution - 1;
+ i = 0;
+ do {
+ code >>= 1;
+ i ++;
+ } while (code);
+ VOL->vop_time_increment_resolution_bits = i;
+ VOL->fixed_vop_rate = mp4_GetBit(pInfo);
+ if (VOL->fixed_vop_rate) {
+ VOL->fixed_vop_time_increment = mp4_GetBits(pInfo, VOL->vop_time_increment_resolution_bits);
+ if (VOL->fixed_vop_time_increment == 0) {
+ mp4_Error("Error: wrong value of fixed_vop_time_increment");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ }
+ if (VOL->shape != MP4_SHAPE_TYPE_BINARYONLY) {
+ if (VOL->shape == MP4_SHAPE_TYPE_RECTANGULAR) {
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ VOL->width = mp4_GetBits(pInfo, 13);
+ if (VOL->width == 0) {
+ mp4_Error("Error: wrong value of video_object_layer_width");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ VOL->height = mp4_GetBits(pInfo, 13);
+ if (VOL->height == 0) {
+ mp4_Error("Error: wrong value of video_object_layer_height");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ }
+ VOL->interlaced = mp4_GetBit(pInfo);
+ VOL->obmc_disable = mp4_GetBit(pInfo);
+ VOL->sprite_enable = mp4_GetBits9(pInfo, VOL->verid != 1 ? 2 : 1);
+ if (VOL->sprite_enable == MP4_SPRITE_STATIC || VOL->sprite_enable == MP4_SPRITE_GMC) {
+ if (VOL->sprite_enable == MP4_SPRITE_STATIC) {
+ VOL->sprite_width = mp4_GetBits(pInfo, 13);
+ if (VOL->sprite_width == 0) {
+ mp4_Error("Error: wrong value of sprite_width");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ VOL->sprite_height = mp4_GetBits(pInfo, 13);
+ if (VOL->sprite_height == 0) {
+ mp4_Error("Error: wrong value of sprite_height");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ VOL->sprite_left_coordinate = mp4_GetBits(pInfo, 13);
+ VOL->sprite_left_coordinate <<= (32 - 13);
+ VOL->sprite_left_coordinate >>= (32 - 13);
+ if (VOL->sprite_left_coordinate & 1) {
+ mp4_Error("Error: sprite_left_coordinate must be divisible by 2");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ VOL->sprite_top_coordinate = mp4_GetBits(pInfo, 13);
+ VOL->sprite_top_coordinate <<= (32 - 13);
+ VOL->sprite_top_coordinate >>= (32 - 13);
+ if (VOL->sprite_top_coordinate & 1) {
+ mp4_Error("Error: sprite_top_coordinate must be divisible by 2");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ }
+ VOL->sprite_warping_points = mp4_GetBits9(pInfo, 6);
+ if (VOL->sprite_warping_points > 4 || (VOL->sprite_warping_points == 4 && VOL->sprite_enable == MP4_SPRITE_GMC)) {
+ mp4_Error("Error: bad no_of_sprite_warping_points");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ VOL->sprite_warping_accuracy = mp4_GetBits9(pInfo, 2);
+ VOL->sprite_brightness_change = mp4_GetBit(pInfo);
+ if (VOL->sprite_enable == MP4_SPRITE_GMC) {
+ if (VOL->sprite_brightness_change) {
+ mp4_Error("Error: sprite_brightness_change should be 0 for GMC sprites");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ }
+ if (VOL->sprite_enable != MP4_SPRITE_GMC) {
+ VOL->low_latency_sprite_enable = mp4_GetBit(pInfo);
+ if (VOL->low_latency_sprite_enable) {
+ mp4_Error("Error: low_latency_sprite is not supported");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ }
+ }
+ if (VOL->verid != 1 && VOL->shape != MP4_SHAPE_TYPE_RECTANGULAR) {
+ VOL->sadct_disable = mp4_GetBit(pInfo);
+ if (!VOL->sadct_disable) {
+ mp4_Error("Error: Shape Adaptive DCT is not supported");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ }
+ VOL->not_8_bit = mp4_GetBit(pInfo);
+ if (VOL->not_8_bit) {
+ mp4_Error("Error: only 8-bits data is supported");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ if (VOL->not_8_bit) {
+ VOL->quant_precision = mp4_GetBits9(pInfo, 4);
+ if (VOL->quant_precision < 3 || VOL->quant_precision > 9) {
+ mp4_Error("Error: quant_precision must be in range [3; 9]");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ VOL->bits_per_pixel = mp4_GetBits9(pInfo, 4);
+ if (VOL->bits_per_pixel < 4 || VOL->bits_per_pixel > 12) {
+ mp4_Error("Error: bits_per_pixel must be in range [4; 12]");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ } else {
+ VOL->quant_precision = 5;
+ VOL->bits_per_pixel = 8;
+ }
+ if (VOL->shape == MP4_SHAPE_TYPE_GRAYSCALE) {
+ VOL->no_gray_quant_update = mp4_GetBit(pInfo);
+ VOL->composition_method = mp4_GetBit(pInfo);
+ VOL->linear_composition = mp4_GetBit(pInfo);
+ }
+ VOL->quant_type = mp4_GetBit(pInfo);
+ if (VOL->quant_type) {
+ VOL->load_intra_quant_mat = mp4_GetBit(pInfo);
+ if (VOL->load_intra_quant_mat) {
+ if (mp4_Parse_QuantMatrix(pInfo, VOL->intra_quant_mat) != MP4_STATUS_OK)
+ return MP4_STATUS_PARSE_ERROR;
+ } else
+ ippsCopy_8u(mp4_DefaultIntraQuantMatrix, VOL->intra_quant_mat, 64);
+ VOL->load_nonintra_quant_mat = mp4_GetBit(pInfo);
+ if (VOL->load_nonintra_quant_mat) {
+ if (mp4_Parse_QuantMatrix(pInfo, VOL->nonintra_quant_mat) != MP4_STATUS_OK)
+ return MP4_STATUS_PARSE_ERROR;
+ } else
+ ippsCopy_8u(mp4_DefaultNonIntraQuantMatrix, VOL->nonintra_quant_mat, 64);
+ if (VOL->shape == MP4_SHAPE_TYPE_GRAYSCALE) {
+ int32_t ac, i;
+
+ ac = mp4_aux_comp_count[VOL->shape_extension];
+ for (i = 0; i < ac; i ++) {
+ VOL->load_intra_quant_mat_grayscale[i] = mp4_GetBit(pInfo);
+ if (VOL->load_intra_quant_mat_grayscale[i]) {
+ if (mp4_Parse_QuantMatrix(pInfo, VOL->intra_quant_mat_grayscale[i]) != MP4_STATUS_OK)
+ return MP4_STATUS_PARSE_ERROR;
+ } else
+ ippsCopy_8u(mp4_DefaultIntraQuantMatrix, VOL->intra_quant_mat_grayscale[i], 64);
+ VOL->load_nonintra_quant_mat_grayscale[i] = mp4_GetBit(pInfo);
+ if (VOL->load_nonintra_quant_mat_grayscale[i]) {
+ if (mp4_Parse_QuantMatrix(pInfo, VOL->nonintra_quant_mat_grayscale[i]) != MP4_STATUS_OK)
+ return MP4_STATUS_PARSE_ERROR;
+ } else
+ ippsCopy_8u(mp4_DefaultNonIntraQuantMatrix, VOL->nonintra_quant_mat_grayscale[i], 64);
+ }
+ }
+ }
+ if (VOL->verid != 1)
+ VOL->quarter_sample = mp4_GetBit(pInfo);
+ VOL->complexity_estimation_disable = mp4_GetBit(pInfo);
+ if (!VOL->complexity_estimation_disable) {
+ VOL->ComplexityEstimation.estimation_method = mp4_GetBits9(pInfo, 2);
+ if (VOL->ComplexityEstimation.estimation_method <= 1) {
+ VOL->ComplexityEstimation.shape_complexity_estimation_disable = mp4_GetBit(pInfo);
+ if (!VOL->ComplexityEstimation.shape_complexity_estimation_disable) {
+ VOL->ComplexityEstimation.opaque = mp4_GetBit(pInfo);
+ VOL->ComplexityEstimation.transparent = mp4_GetBit(pInfo);
+ VOL->ComplexityEstimation.intra_cae = mp4_GetBit(pInfo);
+ VOL->ComplexityEstimation.inter_cae = mp4_GetBit(pInfo);
+ VOL->ComplexityEstimation.no_update = mp4_GetBit(pInfo);
+ VOL->ComplexityEstimation.upsampling = mp4_GetBit(pInfo);
+ }
+ VOL->ComplexityEstimation.texture_complexity_estimation_set_1_disable = mp4_GetBit(pInfo);
+ if (!VOL->ComplexityEstimation.texture_complexity_estimation_set_1_disable) {
+ VOL->ComplexityEstimation.intra_blocks = mp4_GetBit(pInfo);
+ VOL->ComplexityEstimation.inter_blocks = mp4_GetBit(pInfo);
+ VOL->ComplexityEstimation.inter4v_blocks = mp4_GetBit(pInfo);
+ VOL->ComplexityEstimation.not_coded_blocks = mp4_GetBit(pInfo);
+ }
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ VOL->ComplexityEstimation.texture_complexity_estimation_set_2_disable = mp4_GetBit(pInfo);
+ if (!VOL->ComplexityEstimation.texture_complexity_estimation_set_2_disable) {
+ VOL->ComplexityEstimation.dct_coefs = mp4_GetBit(pInfo);
+ VOL->ComplexityEstimation.dct_lines = mp4_GetBit(pInfo);
+ VOL->ComplexityEstimation.vlc_symbols = mp4_GetBit(pInfo);
+ VOL->ComplexityEstimation.vlc_bits = mp4_GetBit(pInfo);
+ }
+ VOL->ComplexityEstimation.motion_compensation_complexity_disable = mp4_GetBit(pInfo);
+ if (!VOL->ComplexityEstimation.motion_compensation_complexity_disable) {
+ VOL->ComplexityEstimation.apm = mp4_GetBit(pInfo);
+ VOL->ComplexityEstimation.npm = mp4_GetBit(pInfo);
+ VOL->ComplexityEstimation.interpolate_mc_q = mp4_GetBit(pInfo);
+ VOL->ComplexityEstimation.forw_back_mc_q = mp4_GetBit(pInfo);
+ VOL->ComplexityEstimation.halfpel2 = mp4_GetBit(pInfo);
+ VOL->ComplexityEstimation.halfpel4 = mp4_GetBit(pInfo);
+ }
+ }
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ if (VOL->ComplexityEstimation.estimation_method == 1) {
+ // verid != 1
+ VOL->ComplexityEstimation.version2_complexity_estimation_disable = mp4_GetBit(pInfo);
+ if (!VOL->ComplexityEstimation.version2_complexity_estimation_disable) {
+ VOL->ComplexityEstimation.sadct = mp4_GetBit(pInfo);
+ VOL->ComplexityEstimation.quarterpel = mp4_GetBit(pInfo);
+ }
+ }
+ }
+ VOL->resync_marker_disable = mp4_GetBit(pInfo);
+ VOL->data_partitioned = mp4_GetBit(pInfo);
+//f GrayScale Shapes does not support data_part
+ if (VOL->data_partitioned)
+ VOL->reversible_vlc = mp4_GetBit(pInfo);
+ if (VOL->verid != 1) {
+ VOL->newpred_enable = mp4_GetBit(pInfo);
+ if (VOL->newpred_enable) {
+ VOL->requested_upstream_message_type = mp4_GetBits9(pInfo, 2);
+ VOL->newpred_segment_type = mp4_GetBit(pInfo);
+ mp4_Error("Warning: NEWPRED mode is not fully supported");
+//f return MP4_STATUS_PARSE_ERROR;
+ }
+ VOL->reduced_resolution_vop_enable = mp4_GetBit(pInfo);
+ if (VOL->reduced_resolution_vop_enable) {
+ mp4_Error("Error: Reduced Resolution VOP is not supported");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ }
+ VOL->scalability = mp4_GetBit(pInfo);
+ if (VOL->scalability) {
+ mp4_Error("Error: VOL scalability is not supported");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ } else {
+ if (VOL->verid != 1) {
+ VOL->scalability = mp4_GetBit(pInfo);
+ if (VOL->scalability) {
+ mp4_Error("Error: VOL scalability is not supported");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ }
+ VOL->resync_marker_disable = mp4_GetBit(pInfo);
+ }
+ VOL->VideoObjectPlane.sprite_transmit_mode = MP4_SPRITE_TRANSMIT_MODE_PIECE;
+#if 0
+ {
+ uint8_t *sbp = pInfo->bufptr;
+ int32_t v, b, i;
+ if (mp4_SeekStartCodeValue(pInfo, MP4_USER_DATA_SC)) {
+ if (pInfo->bufptr[0] == 'D' && pInfo->bufptr[1] == 'i' && pInfo->bufptr[2] == 'v' && pInfo->bufptr[3] == 'X') {
+ pInfo->ftype = 2;
+ v = (pInfo->bufptr[4] - '0') * 100 + (pInfo->bufptr[5] - '0') * 10 + (pInfo->bufptr[6] - '0');
+ if (v < 503)
+ pInfo->ftype_f = 1;
+ else if (v == 503) {
+ i = 8;
+ b = 0;
+ while (pInfo->bufptr[i] != 0) {
+ if (pInfo->bufptr[i] >= '0' && pInfo->bufptr[i] <= '9')
+ b = b * 10 + (pInfo->bufptr[i] - '0');
+ i ++;
+ }
+ pInfo->ftype_f = (b < 959) ? 1 : 0;
+ } else
+ pInfo->ftype_f = 0;
+ }
+ }
+ pInfo->bufptr = sbp;
+ }
+#else
+ {
+ uint8_t *sbp = pInfo->bufptr;
+ if (mp4_SeekStartCodeValue(pInfo, MP4_USER_DATA_SC)) {
+ if (pInfo->bufptr[0] == 'D' && pInfo->bufptr[1] == 'i' && pInfo->bufptr[2] == 'v' && pInfo->bufptr[3] == 'X') {
+ pInfo->ftype = 2;
+ pInfo->ftype_f = 1;
+ }
+ }
+ pInfo->bufptr = sbp;
+ }
+#endif
+ return MP4_STATUS_OK;
+}
+
+
+/*static */mp4_Status mp4_Sprite_Trajectory(mp4_Info* pInfo) {
+ int32_t i, dmv_code, dmv_length, fb;
+ uint32_t code;
+
+ for (i = 0; i < pInfo->VisualObject.VideoObject.sprite_warping_points; i ++) {
+ code = mp4_ShowBits9(pInfo, 3);
+ if (code == 7) {
+ mp4_FlushBits(pInfo, 3);
+ code = mp4_ShowBits9(pInfo, 9);
+ fb = 1;
+ while (code & 256) {
+ code <<= 1;
+ fb ++;
+ }
+ if (fb > 9) {
+ mp4_Error("Error when decode sprite_trajectory");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ dmv_length = fb + 5;
+ } else {
+ fb = (code <= 1) ? 2 : 3;
+ dmv_length = code - 1;
+ }
+ mp4_FlushBits(pInfo, fb);
+ if (dmv_length <= 0)
+ dmv_code = 0;
+ else {
+ dmv_code = mp4_GetBits(pInfo, dmv_length);
+ if ((dmv_code & (1 << (dmv_length - 1))) == 0)
+ dmv_code -= (1 << dmv_length) - 1;
+ }
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ pInfo->VisualObject.VideoObject.VideoObjectPlane.warping_mv_code_du[i] = dmv_code;
+ code = mp4_ShowBits9(pInfo, 3);
+ if (code == 7) {
+ mp4_FlushBits(pInfo, 3);
+ code = mp4_ShowBits9(pInfo, 9);
+ fb = 1;
+ while (code & 256) {
+ code <<= 1;
+ fb ++;
+ }
+ if (fb > 9) {
+ mp4_Error("Error when decode sprite_trajectory");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ dmv_length = fb + 5;
+ } else {
+ fb = (code <= 1) ? 2 : 3;
+ dmv_length = code - 1;
+ }
+ mp4_FlushBits(pInfo, fb);
+ if (dmv_length <= 0)
+ dmv_code = 0;
+ else {
+ dmv_code = mp4_GetBits(pInfo, dmv_length);
+ if ((dmv_code & (1 << (dmv_length - 1))) == 0)
+ dmv_code -= (1 << dmv_length) - 1;
+ }
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ pInfo->VisualObject.VideoObject.VideoObjectPlane.warping_mv_code_dv[i] = dmv_code;
+ }
+ return MP4_STATUS_OK;
+}
+
+
+mp4_Status mp4_Parse_GroupOfVideoObjectPlane(mp4_Info* pInfo)
+{
+ uint32_t hour, min, sec;
+
+ hour = mp4_GetBits9(pInfo, 5);
+ min = mp4_GetBits9(pInfo, 6);
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ sec = mp4_GetBits9(pInfo, 6);
+ pInfo->VisualObject.VideoObject.GroupOfVideoObjectPlane.time_code = sec + min * 60 + hour * 3600;
+ pInfo->VisualObject.VideoObject.GroupOfVideoObjectPlane.time_code *= pInfo->VisualObject.VideoObject.vop_time_increment_resolution;
+ pInfo->VisualObject.VideoObject.GroupOfVideoObjectPlane.closed_gov = mp4_GetBit(pInfo);
+ pInfo->VisualObject.VideoObject.GroupOfVideoObjectPlane.broken_link = mp4_GetBit(pInfo);
+ return MP4_STATUS_OK;
+}
+
+
+mp4_Status mp4_Parse_VideoObjectPlane(mp4_Info* pInfo)
+{
+ uint32_t code;
+ mp4_VideoObject *VOL = &pInfo->VisualObject.VideoObject;
+ mp4_VideoObjectPlane *VOP = &pInfo->VisualObject.VideoObject.VideoObjectPlane;
+ mp4_VideoObjectPlaneH263 *VOPSH = &pInfo->VisualObject.VideoObject.VideoObjectPlaneH263;
+
+ if (VOL->short_video_header) {
+ code = mp4_GetBits9(pInfo, 6); // read rest bits of short_video_start_marker
+ VOPSH->temporal_reference = mp4_GetBits9(pInfo, 8);
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ code = mp4_GetBit(pInfo); // zero_bit
+ VOPSH->split_screen_indicator = mp4_GetBit(pInfo);
+ VOPSH->document_camera_indicator = mp4_GetBit(pInfo);
+ VOPSH->full_picture_freeze_release = mp4_GetBit(pInfo);
+ VOPSH->source_format = mp4_GetBits9(pInfo, 3);
+ if (VOPSH->source_format == 0 || VOPSH->source_format > 5) {
+ mp4_Error("Error: Bad value for VideoPlaneWithShortHeader.source_format");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ VOPSH->picture_coding_type = mp4_GetBit(pInfo);
+ VOP->coding_type = VOPSH->picture_coding_type;
+ code = mp4_GetBits9(pInfo, 4); // four_reserved_zero_bits
+ VOPSH->vop_quant = mp4_GetBits9(pInfo, 5);
+ code = mp4_GetBit(pInfo); // zero_bit
+ for (;;) {
+ code = mp4_GetBit(pInfo); // pei
+ if (!code)
+ break;
+ code = mp4_GetBits9(pInfo, 8); // psupp
+ }
+ return MP4_STATUS_OK;
+ }
+ VOP->coding_type = mp4_GetBits9(pInfo, 2);
+ if (((VOP->coding_type != MP4_VOP_TYPE_I) && (pInfo->noPVOPs)) || ((VOP->coding_type == MP4_VOP_TYPE_B) && (pInfo->noBVOPs))) {
+ mp4_Error("Error: Bad vop_coding_type");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ VOP->modulo_time_base = 0;
+ do {
+ code = mp4_GetBit(pInfo);
+ VOP->modulo_time_base += code;
+ } while (code);
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ if (VOL->vop_time_increment_resolution_bits != 0 ) {
+ VOP->time_increment = mp4_GetBits(pInfo, VOL->vop_time_increment_resolution_bits);
+ }
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ VOP->coded = mp4_GetBit(pInfo);
+ if (!VOP->coded)
+ return MP4_STATUS_OK;
+ if (VOL->newpred_enable) {
+ int vop_id_length = VOL->vop_time_increment_resolution_bits + 3;
+ if (vop_id_length > 15)
+ vop_id_length = 15;
+ VOP->vop_id = mp4_GetBits(pInfo, vop_id_length);
+ VOP->vop_id_for_prediction_indication = mp4_GetBit(pInfo);
+ if (VOP->vop_id_for_prediction_indication)
+ VOP->vop_id_for_prediction = mp4_GetBits(pInfo, vop_id_length);
+ if (!mp4_GetMarkerBit(pInfo))
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ if (VOL->shape != MP4_SHAPE_TYPE_BINARYONLY && (VOP->coding_type == MP4_VOP_TYPE_P ||
+ (VOP->coding_type == MP4_VOP_TYPE_S && VOL->sprite_enable == MP4_SPRITE_GMC)))
+ VOP->rounding_type = mp4_GetBit(pInfo);
+ if (VOL->reduced_resolution_vop_enable && VOL->shape == MP4_SHAPE_TYPE_RECTANGULAR &&
+ (VOP->coding_type == MP4_VOP_TYPE_I || VOP->coding_type == MP4_VOP_TYPE_P)) {
+ VOP->reduced_resolution = mp4_GetBit(pInfo);
+ if (VOP->reduced_resolution) {
+ mp4_Error("Error: Reduced Resolution VOP is not supported");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ }
+ if (VOL->shape != MP4_SHAPE_TYPE_RECTANGULAR) {
+ if (!(VOL->sprite_enable == MP4_SPRITE_STATIC && VOP->coding_type == MP4_VOP_TYPE_I)) {
+ VOP->vop_width = mp4_GetBits(pInfo, 13);
+ if (VOP->vop_width == 0) {
+ mp4_Error("Error: wrong value of vop_width");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ VOP->vop_height = mp4_GetBits(pInfo, 13);
+ if (VOP->vop_height == 0) {
+ mp4_Error("Error: wrong value of vop_height");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ VOP->vop_horizontal_mc_spatial_ref = mp4_GetBits(pInfo, 13);
+ VOP->vop_horizontal_mc_spatial_ref <<= (32 - 13);
+ VOP->vop_horizontal_mc_spatial_ref >>= (32 - 13);
+ if (VOP->vop_horizontal_mc_spatial_ref & 1) {
+ mp4_Error("Error: vop_horizontal_mc_spatial_ref must be divisible by 2");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ VOP->vop_vertical_mc_spatial_ref = mp4_GetBits(pInfo, 13);
+ VOP->vop_vertical_mc_spatial_ref <<= (32 - 13);
+ VOP->vop_vertical_mc_spatial_ref >>= (32 - 13);
+ if (VOP->vop_vertical_mc_spatial_ref & 1) {
+ mp4_Error("Error: vop_vertical_mc_spatial_ref must be divisible by 2");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ if (!mp4_GetMarkerBit(pInfo)) return MP4_STATUS_PARSE_ERROR;
+ }
+//f if ((VOL->shape != MP4_SHAPE_TYPE_BINARYONLY) && VOL->scalability && enhancement_type)
+//f background_composition = mp4_GetBit(pInfo);
+ VOP->change_conv_ratio_disable = mp4_GetBit(pInfo);
+ VOP->vop_constant_alpha = mp4_GetBit(pInfo);
+ if (VOP->vop_constant_alpha)
+ VOP->vop_constant_alpha_value = mp4_GetBits9(pInfo, 8);
+ else
+ VOP->vop_constant_alpha_value = 255;
+ }
+ if (VOL->shape != MP4_SHAPE_TYPE_BINARYONLY) {
+ if (!VOL->complexity_estimation_disable) {
+ if (VOL->ComplexityEstimation.estimation_method == 0) {
+ if (VOP->coding_type == MP4_VOP_TYPE_I) {
+ if (VOL->ComplexityEstimation.opaque) VOL->ComplexityEstimation.dcecs_opaque = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.transparent) VOL->ComplexityEstimation.dcecs_transparent = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.intra_cae) VOL->ComplexityEstimation.dcecs_intra_cae = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.inter_cae) VOL->ComplexityEstimation.dcecs_inter_cae = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.no_update) VOL->ComplexityEstimation.dcecs_no_update = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.upsampling) VOL->ComplexityEstimation.dcecs_upsampling = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.intra_blocks) VOL->ComplexityEstimation.dcecs_intra_blocks = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.not_coded_blocks) VOL->ComplexityEstimation.dcecs_not_coded_blocks = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.dct_coefs) VOL->ComplexityEstimation.dcecs_dct_coefs = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.dct_lines) VOL->ComplexityEstimation.dcecs_dct_lines = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.vlc_symbols) VOL->ComplexityEstimation.dcecs_vlc_symbols = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.vlc_bits) VOL->ComplexityEstimation.dcecs_vlc_bits = mp4_GetBits9(pInfo, 4);
+ if (VOL->ComplexityEstimation.sadct) VOL->ComplexityEstimation.dcecs_sadct = mp4_GetBits9(pInfo, 8);
+ }
+ if (VOP->coding_type == MP4_VOP_TYPE_P) {
+ if (VOL->ComplexityEstimation.opaque) VOL->ComplexityEstimation.dcecs_opaque = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.transparent) VOL->ComplexityEstimation.dcecs_transparent = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.intra_cae) VOL->ComplexityEstimation.dcecs_intra_cae = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.inter_cae) VOL->ComplexityEstimation.dcecs_inter_cae = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.no_update) VOL->ComplexityEstimation.dcecs_no_update = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.upsampling) VOL->ComplexityEstimation.dcecs_upsampling = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.intra_blocks) VOL->ComplexityEstimation.dcecs_intra_blocks = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.not_coded_blocks) VOL->ComplexityEstimation.dcecs_not_coded_blocks = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.dct_coefs) VOL->ComplexityEstimation.dcecs_dct_coefs = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.dct_lines) VOL->ComplexityEstimation.dcecs_dct_lines = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.vlc_symbols) VOL->ComplexityEstimation.dcecs_vlc_symbols = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.vlc_bits) VOL->ComplexityEstimation.dcecs_vlc_bits = mp4_GetBits9(pInfo, 4);
+ if (VOL->ComplexityEstimation.inter_blocks) VOL->ComplexityEstimation.dcecs_inter_blocks = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.inter4v_blocks) VOL->ComplexityEstimation.dcecs_inter4v_blocks = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.apm) VOL->ComplexityEstimation.dcecs_apm = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.npm) VOL->ComplexityEstimation.dcecs_npm = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.forw_back_mc_q) VOL->ComplexityEstimation.dcecs_forw_back_mc_q = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.halfpel2) VOL->ComplexityEstimation.dcecs_halfpel2 = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.halfpel4) VOL->ComplexityEstimation.dcecs_halfpel4 = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.sadct) VOL->ComplexityEstimation.dcecs_sadct = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.quarterpel) VOL->ComplexityEstimation.dcecs_quarterpel = mp4_GetBits9(pInfo, 8);
+ }
+ if (VOP->coding_type == MP4_VOP_TYPE_B) {
+ if (VOL->ComplexityEstimation.opaque) VOL->ComplexityEstimation.dcecs_opaque = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.transparent) VOL->ComplexityEstimation.dcecs_transparent = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.intra_cae) VOL->ComplexityEstimation.dcecs_intra_cae = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.inter_cae) VOL->ComplexityEstimation.dcecs_inter_cae = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.no_update) VOL->ComplexityEstimation.dcecs_no_update = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.upsampling) VOL->ComplexityEstimation.dcecs_upsampling = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.intra_blocks) VOL->ComplexityEstimation.dcecs_intra_blocks = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.not_coded_blocks) VOL->ComplexityEstimation.dcecs_not_coded_blocks = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.dct_coefs) VOL->ComplexityEstimation.dcecs_dct_coefs = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.dct_lines) VOL->ComplexityEstimation.dcecs_dct_lines = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.vlc_symbols) VOL->ComplexityEstimation.dcecs_vlc_symbols = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.vlc_bits) VOL->ComplexityEstimation.dcecs_vlc_bits = mp4_GetBits9(pInfo, 4);
+ if (VOL->ComplexityEstimation.inter_blocks) VOL->ComplexityEstimation.dcecs_inter_blocks = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.inter4v_blocks) VOL->ComplexityEstimation.dcecs_inter4v_blocks = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.apm) VOL->ComplexityEstimation.dcecs_apm = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.npm) VOL->ComplexityEstimation.dcecs_npm = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.forw_back_mc_q) VOL->ComplexityEstimation.dcecs_forw_back_mc_q = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.halfpel2) VOL->ComplexityEstimation.dcecs_halfpel2 = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.halfpel4) VOL->ComplexityEstimation.dcecs_halfpel4 = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.interpolate_mc_q) VOL->ComplexityEstimation.dcecs_interpolate_mc_q = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.sadct) VOL->ComplexityEstimation.dcecs_sadct = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.quarterpel) VOL->ComplexityEstimation.dcecs_quarterpel = mp4_GetBits9(pInfo, 8);
+ }
+ if (VOP->coding_type == MP4_VOP_TYPE_S && VOL->sprite_enable == MP4_SPRITE_STATIC) {
+ if (VOL->ComplexityEstimation.intra_blocks) VOL->ComplexityEstimation.dcecs_intra_blocks = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.not_coded_blocks) VOL->ComplexityEstimation.dcecs_not_coded_blocks = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.dct_coefs) VOL->ComplexityEstimation.dcecs_dct_coefs = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.dct_lines) VOL->ComplexityEstimation.dcecs_dct_lines = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.vlc_symbols) VOL->ComplexityEstimation.dcecs_vlc_symbols = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.vlc_bits) VOL->ComplexityEstimation.dcecs_vlc_bits = mp4_GetBits9(pInfo, 4);
+ if (VOL->ComplexityEstimation.inter_blocks) VOL->ComplexityEstimation.dcecs_inter_blocks = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.inter4v_blocks) VOL->ComplexityEstimation.dcecs_inter4v_blocks = mp4_GetBits(pInfo, 8);
+ if (VOL->ComplexityEstimation.apm) VOL->ComplexityEstimation.dcecs_apm = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.npm) VOL->ComplexityEstimation.dcecs_npm = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.forw_back_mc_q) VOL->ComplexityEstimation.dcecs_forw_back_mc_q = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.halfpel2) VOL->ComplexityEstimation.dcecs_halfpel2 = mp4_GetBits9(pInfo, 8);
+ if (VOL->ComplexityEstimation.halfpel4) VOL->ComplexityEstimation.dcecs_halfpel4 = mp4_GetBits(pInfo, 8);
+ if (VOL->ComplexityEstimation.interpolate_mc_q) VOL->ComplexityEstimation.dcecs_interpolate_mc_q = mp4_GetBits9(pInfo, 8);
+ }
+ }
+ }
+ VOP->intra_dc_vlc_thr = mp4_GetBits9(pInfo, 3);
+ if (VOL->interlaced) {
+ VOP->top_field_first = mp4_GetBit(pInfo);
+ VOP->alternate_vertical_scan_flag = mp4_GetBit(pInfo);
+ }
+ }
+ if ((VOL->sprite_enable == MP4_SPRITE_STATIC || VOL->sprite_enable == MP4_SPRITE_GMC) && VOP->coding_type == MP4_VOP_TYPE_S) {
+ if (VOL->sprite_warping_points > 0)
+ if (mp4_Sprite_Trajectory(pInfo) != MP4_STATUS_OK)
+ return MP4_STATUS_PARSE_ERROR;
+ if (VOL->sprite_brightness_change) {
+ code = mp4_ShowBits9(pInfo, 4);
+ if (code == 15) {
+ mp4_FlushBits(pInfo, 4);
+ VOP->brightness_change_factor = 625 + mp4_GetBits(pInfo, 10);
+ } else if (code == 14) {
+ mp4_FlushBits(pInfo, 4);
+ VOP->brightness_change_factor = 113 + mp4_GetBits9(pInfo, 9);
+ } else if (code >= 12) {
+ mp4_FlushBits(pInfo, 3);
+ code = mp4_GetBits9(pInfo, 7);
+ VOP->brightness_change_factor = (code < 64) ? code - 112 : code - 15;
+ } else if (code >= 8) {
+ mp4_FlushBits(pInfo, 2);
+ code = mp4_GetBits9(pInfo, 6);
+ VOP->brightness_change_factor = (code < 32) ? code - 48 : code - 15;
+ } else {
+ mp4_FlushBits(pInfo, 1);
+ code = mp4_GetBits9(pInfo, 5);
+ VOP->brightness_change_factor = (code < 16) ? code - 16 : code - 15;
+ }
+ } else
+ VOP->brightness_change_factor = 0;
+ if (VOL->sprite_enable == MP4_SPRITE_STATIC)
+ return MP4_STATUS_OK;
+ }
+ if (VOL->shape != MP4_SHAPE_TYPE_BINARYONLY) {
+ VOP->quant = mp4_GetBits9(pInfo, VOL->quant_precision);
+ if (VOL->shape == MP4_SHAPE_TYPE_GRAYSCALE) {
+ int32_t ac, i;
+
+ ac = mp4_aux_comp_count[VOL->shape_extension];
+ for (i = 0; i < ac; i ++)
+ VOP->alpha_quant[i] = mp4_GetBits9(pInfo, 6);
+ }
+ if (VOP->coding_type != MP4_VOP_TYPE_I) {
+ VOP->fcode_forward = mp4_GetBits9(pInfo, 3);
+ if (VOP->fcode_forward == 0) {
+ mp4_Error("Error: vop_fcode_forward == 0");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ }
+ if (VOP->coding_type == MP4_VOP_TYPE_B) {
+ VOP->fcode_backward = mp4_GetBits9(pInfo, 3);
+ if (VOP->fcode_backward == 0) {
+ mp4_Error("Error: vop_fcode_backward == 0");
+ return MP4_STATUS_PARSE_ERROR;
+ }
+ }
+ if (!VOL->scalability) {
+ if (VOL->shape != MP4_SHAPE_TYPE_RECTANGULAR && VOP->coding_type != MP4_VOP_TYPE_I)
+ VOP->shape_coding_type = mp4_GetBit(pInfo);
+ } else {
+ //f if (VOL->enhancement_type) {
+ //f VOP->load_backward_shape = mp4_GetBit(pInfo);
+ //f if (VOP->load_backward_shape) {
+ //f shape
+ //f }
+ //f }
+ VOP->ref_select_code = mp4_GetBits9(pInfo, 2);
+ }
+ }
+ return MP4_STATUS_OK;
+}
+
+/*
+// decode VideoPacket
+*/
+mp4_Status mp4_CheckDecodeVideoPacket(mp4_Info* pInfo, int32_t *found)
+{
+ uint32_t code;
+ int32_t header_extension_code, rml;
+ mp4_VideoObject *VOL = &pInfo->VisualObject.VideoObject;
+ mp4_VideoObjectPlane *VOP = &pInfo->VisualObject.VideoObject.VideoObjectPlane;
+
+ *found = 0;
+ // check stuffing bits
+ if (mp4_ShowBit(pInfo) != 0)
+ return MP4_STATUS_OK;
+ if (mp4_ShowBits9(pInfo, 8 - pInfo->bitoff) != (uint32_t)((1 << (7 - pInfo->bitoff)) - 1))
+ return MP4_STATUS_OK;
+ if (VOP->coding_type == MP4_VOP_TYPE_I)
+ rml = 17;
+ else if (VOP->coding_type == MP4_VOP_TYPE_B)
+ rml = 16 + IPP_MAX(VOP->fcode_forward, VOP->fcode_backward);
+ else
+ rml = 16 + VOP->fcode_forward;
+ code = (pInfo->bufptr[1] << 16) | (pInfo->bufptr[2] << 8) | pInfo->bufptr[3];
+ code >>= 24 - rml;
+ if (code == 1) { // is resync_marker
+ mp4_FlushBits(pInfo, rml + 8 - pInfo->bitoff);
+ header_extension_code = 0;
+ if (VOL->shape != MP4_SHAPE_TYPE_RECTANGULAR) {
+ header_extension_code = mp4_GetBit(pInfo);
+ if (header_extension_code && !(VOL->sprite_enable == MP4_SPRITE_STATIC && VOP->coding_type == MP4_VOP_TYPE_I)) {
+ VOP->vop_width = mp4_GetBits(pInfo, 13);
+ if (!mp4_GetBit(pInfo))
+ if (pInfo->stopOnErr)
+ goto Err;
+ VOP->vop_height = mp4_GetBits(pInfo, 13);
+ if (!mp4_GetBit(pInfo))
+ if (pInfo->stopOnErr)
+ goto Err;
+ VOP->vop_horizontal_mc_spatial_ref = mp4_GetBits(pInfo, 13);
+ if (!mp4_GetBit(pInfo))
+ if (pInfo->stopOnErr)
+ goto Err;
+ VOP->vop_vertical_mc_spatial_ref = mp4_GetBits(pInfo, 13);
+ if (!mp4_GetBit(pInfo))
+ if (pInfo->stopOnErr)
+ goto Err;
+ }
+ }
+ pInfo->VisualObject.VideoObject.VideoObjectPlane.macroblock_num = mp4_GetBits(pInfo, pInfo->VisualObject.VideoObject.mbns);
+ if (pInfo->VisualObject.VideoObject.VideoObjectPlane.macroblock_num >= pInfo->VisualObject.VideoObject.MacroBlockPerVOP)
+ goto Err;
+ if (VOL->shape != MP4_SHAPE_TYPE_BINARYONLY) {
+ pInfo->VisualObject.VideoObject.VideoObjectPlane.quant_scale = mp4_GetBits9(pInfo, VOL->quant_precision); // quant_scale
+ }
+ if (VOL->shape == MP4_SHAPE_TYPE_RECTANGULAR) {
+ header_extension_code = mp4_GetBit(pInfo);
+ }
+ if (header_extension_code) {
+ //f ignore modulo_time_base
+ do {
+ code = mp4_GetBit(pInfo);
+ } while (code);
+ if (!mp4_GetBit(pInfo))
+ if (pInfo->stopOnErr)
+ goto Err;
+ //f ignore vop_time_increment
+ if (VOL->vop_time_increment_resolution_bits != 0 ) {
+ code = mp4_GetBits(pInfo, VOL->vop_time_increment_resolution_bits);
+ }
+ if (!mp4_GetBit(pInfo))
+ if (pInfo->stopOnErr)
+ goto Err;
+ //f ignore vop_coding_type
+ code = mp4_GetBits9(pInfo, 2);
+ if (VOL->shape != MP4_SHAPE_TYPE_RECTANGULAR) {
+ VOP->change_conv_ratio_disable = mp4_GetBit(pInfo);
+ if (VOP->coding_type != MP4_VOP_TYPE_I)
+ VOP->shape_coding_type = mp4_GetBit(pInfo);
+ }
+ if (VOL->shape != MP4_SHAPE_TYPE_BINARYONLY) {
+ //f ignore intra_dc_vlc_thr
+ code = mp4_GetBits9(pInfo, 3);
+ if (VOL->sprite_enable == MP4_SPRITE_GMC && VOP->coding_type == MP4_VOP_TYPE_S && VOL->sprite_warping_points > 0)
+ if (mp4_Sprite_Trajectory(pInfo) != MP4_STATUS_OK)
+ if (pInfo->stopOnErr)
+ goto Err;
+ //f ignore vop_reduced_resolution
+ if (VOL->reduced_resolution_vop_enable && VOL->shape == MP4_SHAPE_TYPE_RECTANGULAR &&
+ (VOP->coding_type == MP4_VOP_TYPE_I || VOP->coding_type == MP4_VOP_TYPE_P))
+ code = mp4_GetBit(pInfo);
+ if (VOP->coding_type != MP4_VOP_TYPE_I)
+ VOP->fcode_forward = mp4_GetBits9(pInfo, 3);
+ if (VOP->coding_type == MP4_VOP_TYPE_B)
+ VOP->fcode_backward = mp4_GetBits9(pInfo, 3);
+ }
+ }
+ if (VOL->newpred_enable) {
+ int vop_id_length = VOL->vop_time_increment_resolution_bits + 3;
+ if (vop_id_length > 15)
+ vop_id_length = 15;
+ VOP->vop_id = mp4_GetBits(pInfo, vop_id_length);
+ VOP->vop_id_for_prediction_indication = mp4_GetBit(pInfo);
+ if (VOP->vop_id_for_prediction_indication)
+ VOP->vop_id_for_prediction = mp4_GetBits(pInfo, vop_id_length);
+ if (!mp4_GetMarkerBit(pInfo))
+ if (pInfo->stopOnErr)
+ goto Err;
+ }
+ *found = 1;
+ return MP4_STATUS_OK;
+ }
+ return MP4_STATUS_OK;
+Err:
+ mp4_Error("Error: decoding Video Packet Header");
+ return MP4_STATUS_PARSE_ERROR;
+}
+
+int32_t mp4_CheckDecodeGOB_SVH(mp4_Info* pInfo)
+{
+ int32_t code;
+
+ pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.gob_number ++;
+ pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.gob_header_empty = 1;
+ code = mp4_ShowBits(pInfo, 17); /* check gob_resync_marker */
+ if (code != 1) {
+ code = mp4_ShowBitsAlign(pInfo, 17); /* check next aligned bits are gob_resync_marker */
+ if (code == 1)
+ mp4_AlignBits(pInfo);
+ }
+ if (code == 1) {
+ mp4_FlushBits(pInfo, 17);
+ pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.gob_header_empty = 0;
+ code = mp4_GetBits9(pInfo, 5); /* gob_number */
+ pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.gob_frame_id = mp4_GetBits9(pInfo, 2);
+ pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.quant_scale = mp4_GetBits9(pInfo, 5);
+ // check gob_number is valid
+ //if (code > pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.gob_number && code <= pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.num_gobs_in_vop)
+ if (code <= pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.num_gobs_in_vop)
+ pInfo->VisualObject.VideoObject.VideoObjectPlaneH263.gob_number = code;
+ else {
+ mp4_Error("Error: bad gob_number in GOB header");
+ return MP4_STATUS_ERROR;
+ }
+ }
+ return MP4_STATUS_OK;
+}
+
diff --git a/Src/mpeg4dec/mp4stream.c b/Src/mpeg4dec/mp4stream.c
new file mode 100644
index 000000000..9c11d169f
--- /dev/null
+++ b/Src/mpeg4dec/mp4stream.c
@@ -0,0 +1,326 @@
+/* ///////////////////////////////////////////////////////////////////////
+//
+// INTEL CORPORATION PROPRIETARY INFORMATION
+// This software is supplied under the terms of a license agreement or
+// nondisclosure agreement with Intel Corporation and may not be copied
+// or disclosed except in accordance with the terms of that agreement.
+// Copyright (c) 2001-2008 Intel Corporation. All Rights Reserved.
+//
+// Description: Decodes MPEG-4 bitstream.
+//
+*/
+
+
+#include "mp4def.h"
+
+#ifndef USE_INLINE_BITS_FUNC
+
+uint32_t mp4_ShowBits(mp4_Info* pInfo, int32_t n)
+{
+ uint8_t* ptr = pInfo->bufptr;
+ uint32_t tmp = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
+ tmp <<= pInfo->bitoff;
+ tmp >>= 32 - n;
+ return tmp;
+}
+
+uint32_t mp4_ShowBit(mp4_Info* pInfo)
+{
+ uint32_t tmp = pInfo->bufptr[0];
+ tmp >>= 7 - pInfo->bitoff;
+ return (tmp & 1);
+}
+
+uint32_t mp4_ShowBits9(mp4_Info* pInfo, int32_t n)
+{
+ uint8_t* ptr = pInfo->bufptr;
+ uint32_t tmp = (ptr[0] << 8) | ptr[1];
+ tmp <<= (pInfo->bitoff + 16);
+ tmp >>= 32 - n;
+ return tmp;
+}
+
+void mp4_FlushBits(mp4_Info* pInfo, int32_t n)
+{
+ n = n + pInfo->bitoff;
+ pInfo->bufptr += n >> 3;
+ pInfo->bitoff = n & 7;
+}
+
+uint32_t mp4_GetBits(mp4_Info* pInfo, int32_t n)
+{
+ uint8_t* ptr = pInfo->bufptr;
+ uint32_t tmp = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
+ tmp <<= pInfo->bitoff;
+ tmp >>= 32 - n;
+ n = n + pInfo->bitoff;
+ pInfo->bufptr += n >> 3;
+ pInfo->bitoff = n & 7;
+ return tmp;
+}
+
+uint32_t mp4_GetBits9(mp4_Info* pInfo, int32_t n)
+{
+ uint8_t* ptr = pInfo->bufptr;
+ uint32_t tmp = (ptr[0] << 8) | ptr[1];
+ tmp <<= (pInfo->bitoff + 16);
+ tmp >>= 32 - n;
+ n = n + pInfo->bitoff;
+ pInfo->bufptr += n >> 3;
+ pInfo->bitoff = n & 7;
+ return tmp;
+}
+
+void mp4_AlignBits(mp4_Info* pInfo)
+{
+ if (pInfo->bitoff > 0) {
+ pInfo->bitoff = 0;
+ (pInfo->bufptr)++;
+ }
+}
+
+void mp4_AlignBits7F(mp4_Info* pInfo)
+{
+ if (pInfo->bitoff > 0) {
+ pInfo->bitoff = 0;
+ (pInfo->bufptr)++;
+ } else {
+ if (*pInfo->bufptr == 0x7F)
+ (pInfo->bufptr)++;
+ }
+}
+
+uint32_t mp4_ShowBitsAlign(mp4_Info* pInfo, int32_t n)
+{
+ uint8_t* ptr = pInfo->bitoff ? (pInfo->bufptr + 1) : pInfo->bufptr;
+ uint32_t tmp = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
+ tmp >>= 32 - n;
+ return tmp;
+}
+
+uint32_t mp4_ShowBitsAlign7F(mp4_Info* pInfo, int32_t n)
+{
+ uint8_t* ptr = pInfo->bitoff ? (pInfo->bufptr + 1) : pInfo->bufptr;
+ uint32_t tmp;
+ if (!pInfo->bitoff) {
+ if (*ptr == 0x7F)
+ ptr ++;
+ }
+ tmp = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3]);
+ tmp >>= 32 - n;
+ return tmp;
+}
+
+#endif
+
+uint8_t* mp4_FindStartCodePtr(mp4_Info* pInfo)
+{
+ int32_t i, len = pInfo->buflen - (pInfo->bufptr - pInfo->buffer);
+ uint8_t* ptr = pInfo->bufptr;
+ for (i = 0; i < len - 3; i++) {
+ if (ptr[i] == 0 && ptr[i + 1] == 0 && ptr[i + 2] == 1) {
+ return ptr + i + 3;
+ }
+ }
+ return NULL;
+}
+
+uint8_t* mp4_FindStartCodeOrShortPtr(mp4_Info* pInfo)
+{
+ int32_t i, len = pInfo->buflen - (pInfo->bufptr - pInfo->buffer);
+ uint8_t* ptr = pInfo->bufptr;
+ for (i = 0; i < len - 3; i++) {
+ if (ptr[i] == 0 && ptr[i + 1] == 0 && ptr[i + 2] == 1) {
+ return ptr + i + 3;
+ }
+ // short_video_header
+ if (ptr[i] == 0 && ptr[i + 1] == 0 && (ptr[i + 2] & 0xFC) == 0x80) {
+ return ptr + i;
+ }
+ }
+ return NULL;
+}
+
+int32_t mp4_SeekStartCodePtr(mp4_Info* pInfo)
+{
+ uint8_t* ptr;
+
+ if (pInfo->bitoff) {
+ pInfo->bufptr ++;
+ pInfo->bitoff = 0;
+ }
+ ptr = mp4_FindStartCodePtr(pInfo);
+ if (ptr) {
+ pInfo->bufptr = ptr;
+ return 1;
+ } else {
+ pInfo->bufptr = pInfo->buffer + (pInfo->buflen > 3 ? pInfo->buflen - 3 : 0);
+ return 0;
+ }
+}
+
+int32_t mp4_SeekStartCodeOrShortPtr(mp4_Info* pInfo)
+{
+ uint8_t* ptr;
+
+ if (pInfo->bitoff) {
+ pInfo->bufptr ++;
+ pInfo->bitoff = 0;
+ }
+ ptr = mp4_FindStartCodeOrShortPtr(pInfo);
+ if (ptr) {
+ pInfo->bufptr = ptr;
+ return 1;
+ } else {
+ pInfo->bufptr = pInfo->buffer + (pInfo->buflen > 3 ? pInfo->buflen - 3 : 0);
+ return 0;
+ }
+}
+
+int32_t mp4_SeekStartCodeValue(mp4_Info* pInfo, uint8_t code)
+{
+ while (mp4_SeekStartCodePtr(pInfo)) {
+ if (*(pInfo->bufptr) == code) {
+ (pInfo->bufptr) ++;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+uint8_t* mp4_FindShortVideoStartMarkerPtr(mp4_Info* pInfo)
+{
+ int32_t i, len = pInfo->buflen - (pInfo->bufptr - pInfo->buffer);
+ uint8_t* ptr = pInfo->bufptr;
+ for (i = 0; i < len - 3; i++) {
+ if (ptr[i] == 0 && ptr[i + 1] == 0 && (ptr[i + 2] & (~3)) == 0x80) {
+ return ptr + i + 2;
+ }
+ }
+ return NULL;
+}
+
+int32_t mp4_SeekShortVideoStartMarker(mp4_Info* pInfo)
+{
+ uint8_t* ptr;
+
+ if (pInfo->bitoff) {
+ pInfo->bufptr ++;
+ pInfo->bitoff = 0;
+ }
+ ptr = mp4_FindShortVideoStartMarkerPtr(pInfo);
+ if (ptr) {
+ pInfo->bufptr = ptr;
+ return 1;
+ } else {
+ pInfo->bufptr = pInfo->buffer + (pInfo->buflen > 3 ? pInfo->buflen - 3 : 0);
+ return 0;
+ }
+}
+
+//changed pInfo->len on pInfo->buflen!!!
+int32_t mp4_SeekGOBMarker(mp4_Info* pInfo)
+{
+ for (; pInfo->bufptr < pInfo->buffer + pInfo->buflen - 2; pInfo->bufptr ++) {
+ if (pInfo->bufptr[0] == 0) {
+ pInfo->bitoff = 0;
+ if (pInfo->bufptr[0] == 0 && pInfo->bufptr[1] == 0 && (pInfo->bufptr[2] & (~3)) == 0x80)
+ return 0;
+ pInfo->bufptr --;
+ for (pInfo->bitoff = 1; pInfo->bitoff <= 7; pInfo->bitoff ++) {
+ if (mp4_ShowBits(pInfo, 17) == 1)
+ return 1;
+ }
+ pInfo->bufptr ++;
+ for (pInfo->bitoff = 0; pInfo->bitoff <= 7; pInfo->bitoff ++) {
+ if (mp4_ShowBits(pInfo, 17) == 1)
+ return 1;
+ }
+ pInfo->bufptr ++;
+ }
+ }
+ return 0;
+}
+
+int32_t mp4_SeekResyncMarker(mp4_Info* pInfo)
+{
+ int32_t rml;
+
+ if (pInfo->VisualObject.VideoObject.VideoObjectPlane.coding_type == MP4_VOP_TYPE_I)
+ rml = 17;
+ else if (pInfo->VisualObject.VideoObject.VideoObjectPlane.coding_type == MP4_VOP_TYPE_B)
+ rml = 16 + IPP_MAX(pInfo->VisualObject.VideoObject.VideoObjectPlane.fcode_forward, pInfo->VisualObject.VideoObject.VideoObjectPlane.fcode_backward);
+ else
+ rml = 16 + pInfo->VisualObject.VideoObject.VideoObjectPlane.fcode_forward;
+ pInfo->bitoff = 0;
+ for (; pInfo->bufptr < pInfo->buffer + pInfo->buflen - 2; pInfo->bufptr ++) {
+ if (pInfo->bufptr[0] == 0) {
+ if (pInfo->bufptr[0] == 0 && pInfo->bufptr[1] == 0 && pInfo->bufptr[2] == 1)
+ return 0;
+ if (mp4_ShowBits(pInfo, rml) == 1) {
+ // check stuffing bits
+ pInfo->bufptr --;
+ pInfo->bitoff = 7;
+ while (pInfo->bitoff > 0 && mp4_ShowBit(pInfo))
+ pInfo->bitoff --;
+ if (pInfo->bitoff == 0 && mp4_ShowBit(pInfo)) {
+ // stuffing bits are invalid
+ pInfo->bufptr[0] = 0x7f;
+ }
+ return 1;
+ }
+ pInfo->bufptr += 2;
+ }
+ }
+ return 0;
+}
+
+int32_t mp4_FindResyncMarker(mp4_Info* pInfo)
+{
+ int32_t rml;
+
+ if (pInfo->VisualObject.VideoObject.VideoObjectPlane.coding_type == MP4_VOP_TYPE_I)
+ rml = 17;
+ else if (pInfo->VisualObject.VideoObject.VideoObjectPlane.coding_type == MP4_VOP_TYPE_B)
+ rml = 16 + IPP_MAX(pInfo->VisualObject.VideoObject.VideoObjectPlane.fcode_forward, pInfo->VisualObject.VideoObject.VideoObjectPlane.fcode_backward);
+ else
+ rml = 16 + pInfo->VisualObject.VideoObject.VideoObjectPlane.fcode_forward;
+ pInfo->bitoff = 0;
+ for (; pInfo->bufptr < pInfo->buffer + pInfo->buflen - 2; pInfo->bufptr ++) {
+ if (pInfo->bufptr[0] == 0)
+ {
+ if (pInfo->bufptr[0] == 0 && pInfo->bufptr[1] == 0 && pInfo->bufptr[2] == 1)
+ return 0;
+ if (mp4_ShowBits(pInfo, rml) == 1)
+ {
+ return rml;
+ }
+ }
+ }
+ return 0;
+}
+
+int mp4_IsStartCodeOrShort(mp4_Info* pInfo)
+{
+ if (pInfo->bufptr[0] == 0 && pInfo->bufptr[1] == 0 && (pInfo->bufptr[2] == 1 || ((pInfo->bufptr[2] & 0xFC) == 0x80)))
+ return 1;
+ return 0;
+}
+
+
+int mp4_IsStartCodeValue(mp4_Info* pInfo, int min, int max)
+{
+ if (pInfo->bufptr[0-3] == 0 && pInfo->bufptr[1-3] == 0 && pInfo->bufptr[2-3] == 1)
+ if (pInfo->bufptr[3-3] >= min && pInfo->bufptr[3-3] <= max)
+ return 1;
+ return 0;
+}
+
+
+int mp4_IsShortCode(mp4_Info* pInfo)
+{
+ if (pInfo->bufptr[0] == 0 && pInfo->bufptr[1] == 0 && ((pInfo->bufptr[2] & 0xFC) == 0x80))
+ return 1;
+ return 0;
+}
+
diff --git a/Src/mpeg4dec/mp4tbl.c b/Src/mpeg4dec/mp4tbl.c
new file mode 100644
index 000000000..7c0521d76
--- /dev/null
+++ b/Src/mpeg4dec/mp4tbl.c
@@ -0,0 +1,153 @@
+/* ///////////////////////////////////////////////////////////////////////
+//
+// INTEL CORPORATION PROPRIETARY INFORMATION
+// This software is supplied under the terms of a license agreement or
+// nondisclosure agreement with Intel Corporation and may not be copied
+// or disclosed except in accordance with the terms of that agreement.
+// Copyright (c) 2001-2007 Intel Corporation. All Rights Reserved.
+//
+// Description: MPEG-4 related tables.
+//
+*/
+
+
+
+#include "mp4def.h"
+
+#define DI(b) ((1 << 18) + b) / b
+
+const int32_t mp4_DivIntraDivisor[47] = {
+ DI( 1), DI( 1), DI( 2), DI( 3), DI( 4), DI( 5), DI( 6), DI( 7), DI( 8), DI( 9),
+ DI(10), DI(11), DI(12), DI(13), DI(14), DI(15), DI(16), DI(17), DI(18), DI(19),
+ DI(20), DI(21), DI(22), DI(23), DI(24), DI(25), DI(26), DI(27), DI(28), DI(29),
+ DI(30), DI(31), DI(32), DI(33), DI(34), DI(35), DI(36), DI(37), DI(38), DI(39),
+ DI(40), DI(41), DI(42), DI(43), DI(44), DI(45), DI(46)
+};
+
+#define DCSL(q) (q <= 4) ? 8 : (q <= 8) ? (q << 1) : (q <= 24) ? (q + 8) : ((q << 1) - 16)
+
+const uint8_t mp4_DCScalerLuma[32] = {
+ DCSL( 0), DCSL( 1), DCSL( 2), DCSL( 3), DCSL( 4), DCSL( 5), DCSL( 6), DCSL( 7),
+ DCSL( 8), DCSL( 9), DCSL(10), DCSL(11), DCSL(12), DCSL(13), DCSL(14), DCSL(15),
+ DCSL(16), DCSL(17), DCSL(18), DCSL(19), DCSL(20), DCSL(21), DCSL(22), DCSL(23),
+ DCSL(24), DCSL(25), DCSL(26), DCSL(27), DCSL(28), DCSL(29), DCSL(30), DCSL(31)
+};
+
+#define DCSC(q) (q <= 4) ? 8 : (q <= 24) ? ((q + 13) >> 1) : (q - 6)
+
+const uint8_t mp4_DCScalerChroma[32] = {
+ DCSC( 0), DCSC( 1), DCSC( 2), DCSC( 3), DCSC( 4), DCSC( 5), DCSC( 6), DCSC( 7),
+ DCSC( 8), DCSC( 9), DCSC(10), DCSC(11), DCSC(12), DCSC(13), DCSC(14), DCSC(15),
+ DCSC(16), DCSC(17), DCSC(18), DCSC(19), DCSC(20), DCSC(21), DCSC(22), DCSC(23),
+ DCSC(24), DCSC(25), DCSC(26), DCSC(27), DCSC(28), DCSC(29), DCSC(30), DCSC(31)
+};
+
+const uint8_t mp4_DefaultIntraQuantMatrix[64] = {
+ 8, 17, 18, 19, 21, 23, 25, 27, 17, 18, 19, 21, 23, 25, 27, 28,
+ 20, 21, 22, 23, 24, 26, 28, 30, 21, 22, 23, 24, 26, 28, 30, 32,
+ 22, 23, 24, 26, 28, 30, 32, 35, 23, 24, 26, 28, 30, 32, 35, 38,
+ 25, 26, 28, 30, 32, 35, 38, 41, 27, 28, 30, 32, 35, 38, 41, 45
+};
+
+const uint8_t mp4_DefaultNonIntraQuantMatrix[64] = {
+ 16, 17, 18, 19, 20, 21, 22, 23, 17, 18, 19, 20, 21, 22, 23, 24,
+ 18, 19, 20, 21, 22, 23, 24, 25, 19, 20, 21, 22, 23, 24, 26, 27,
+ 20, 21, 22, 23, 25, 26, 27, 28, 21, 22, 23, 24, 26, 27, 28, 30,
+ 22, 23, 24, 26, 27, 28, 30, 31, 23, 24, 25, 27, 28, 30, 31, 33
+};
+
+const uint8_t mp4_ClassicalZigzag[64] = {
+ 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5,
+ 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63
+};
+
+const uint8_t mp4_cCbCrMvRound16[16] = {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2};
+const uint8_t mp4_cCbCrMvRound12[12] = {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2};
+const uint8_t mp4_cCbCrMvRound8[8] = {0, 0, 1, 1, 1, 1, 1, 2};
+const uint8_t mp4_cCbCrMvRound4[4] = {0, 1, 1, 1};
+
+const Ipp8s mp4_dquant[4] = {-1, -2, 1, 2};
+
+const mp4_VLC1 mp4_cbpy1[4] = {{0,255},{0,2},{1,1},{1,1}};
+const mp4_VLC1 mp4_cbpy2[16] = {{0,255},{0,4},{1,3},{1,3},{2,2},{2,2},{2,2},{2,2},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1}};
+const mp4_VLC1 mp4_cbpy3[64] = {{1,255},{1,6},{2,5},{2,5},{4,5},{4,5},{5,5},{5,5},{6,3},{6,3},{6,3},{6,3},{6,3},{6,3},{6,3},{6,3},{3,3},{3,3},{3,3},{3,3},{3,3},{3,3},{3,3},{3,3},{0,3},{0,3},{0,3},{0,3},{0,3},{0,3},{0,3},{0,3},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1},{7,1}};
+const mp4_VLC1 mp4_cbpy4[64] = {{16,255},{16,255},{6,6},{9,6},{8,5},{8,5},{4,5},{4,5},{2,5},{2,5},{1,5},{1,5},{0,4},{0,4},{0,4},{0,4},{12,4},{12,4},{12,4},{12,4},{10,4},{10,4},{10,4},{10,4},{14,4},{14,4},{14,4},{14,4},{5,4},{5,4},{5,4},{5,4},{13,4},{13,4},{13,4},{13,4},{3,4},{3,4},{3,4},{3,4},{11,4},{11,4},{11,4},{11,4},{7,4},{7,4},{7,4},{7,4},{15,2},{15,2},{15,2},{15,2},{15,2},{15,2},{15,2},{15,2},{15,2},{15,2},{15,2},{15,2},{15,2},{15,2},{15,2},{15,2}};
+const mp4_VLC1* mp4_cbpy_t[4] = {mp4_cbpy1, mp4_cbpy2, mp4_cbpy3, mp4_cbpy4};
+const uint8_t mp4_cbpy_b[4] = {2, 4, 6, 6};
+
+const int32_t mp4_DC_vlc_Threshold[8] = {512, 13, 15, 17, 19, 21, 23, 0};
+
+const uint8_t mp4_PVOPmb_type[256] = {255,255,4,4,4,1,3,3,3,3,2,2,3,3,3,3,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
+const uint8_t mp4_PVOPmb_cbpc[256] = {0,0,3,2,1,3,2,2,1,1,3,3,3,3,3,3,2,2,2,2,1,1,1,1,2,2,2,2,1,1,1,1,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+const uint8_t mp4_PVOPmb_bits[256] = {9,9,9,9,9,9,8,8,8,8,8,8,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3};
+
+const mp4_VLC1 mp4_BVOPmb_type[16] = {
+ {255, 255}, {IPPVC_MBTYPE_FORWARD, 4}, {IPPVC_MBTYPE_BACKWARD, 3}, {IPPVC_MBTYPE_BACKWARD, 3},
+ {IPPVC_MBTYPE_INTERPOLATE, 2}, {IPPVC_MBTYPE_INTERPOLATE, 2}, {IPPVC_MBTYPE_INTERPOLATE, 2}, {IPPVC_MBTYPE_INTERPOLATE, 2},
+ {IPPVC_MBTYPE_DIRECT, 1}, {IPPVC_MBTYPE_DIRECT, 1}, {IPPVC_MBTYPE_DIRECT, 1}, {IPPVC_MBTYPE_DIRECT, 1},
+ {IPPVC_MBTYPE_DIRECT, 1}, {IPPVC_MBTYPE_DIRECT, 1}, {IPPVC_MBTYPE_DIRECT, 1}, {IPPVC_MBTYPE_DIRECT, 1}
+};
+
+const mp4_VLC1 mp4_MVD_B12_1[] = {
+ {32,12},{31,12},
+ {30,11},{30,11},{29,11},{29,11},{28,11},{28,11},
+ {27,11},{27,11},{26,11},{26,11},{25,11},{25,11},
+ {24,10},{24,10},{24,10},{24,10},{23,10},{23,10},{23,10},{23,10},
+ {22,10},{22,10},{22,10},{22,10},{21,10},{21,10},{21,10},{21,10},
+ {20,10},{20,10},{20,10},{20,10},{19,10},{19,10},{19,10},{19,10},
+ {18,10},{18,10},{18,10},{18,10},{17,10},{17,10},{17,10},{17,10},
+ {16,10},{16,10},{16,10},{16,10},{15,10},{15,10},{15,10},{15,10},
+ {14,10},{14,10},{14,10},{14,10},{13,10},{13,10},{13,10},{13,10},
+ {12,10},{12,10},{12,10},{12,10},{11,10},{11,10},{11,10},{11,10},
+ {10, 9},{10, 9},{10, 9},{10, 9},{10, 9},{10, 9},{10, 9},{10, 9},
+ { 9, 9},{ 9, 9},{ 9, 9},{ 9, 9},{ 9, 9},{ 9, 9},{ 9, 9},{ 9, 9},
+ { 8, 9},{ 8, 9},{ 8, 9},{ 8, 9},{ 8, 9},{ 8, 9},{ 8, 9},{ 8, 9},
+ {0x7, 7},{ 7, 7},{ 7, 7},{ 7, 7},{ 7, 7},{ 7, 7},{ 7, 7},{ 7, 7},
+ {0x7, 7},{ 7, 7},{ 7, 7},{ 7, 7},{ 7, 7},{ 7, 7},{ 7, 7},{ 7, 7},
+ {0x7, 7},{ 7, 7},{ 7, 7},{ 7, 7},{ 7, 7},{ 7, 7},{ 7, 7},{ 7, 7},
+ {0x7, 7},{ 7, 7},{ 7, 7},{ 7, 7},{ 7, 7},{ 7, 7},{ 7, 7},{ 7, 7},
+};
+
+const mp4_VLC1 mp4_MVD_B12_2[] = {
+ { 6, 7},{ 5, 7},{ 4, 6},{ 4, 6},
+ { 3, 4},{ 3, 4},{ 3, 4},{ 3, 4},{ 3, 4},{ 3, 4},{ 3, 4},{ 3, 4},
+ { 2, 3},{ 2, 3},{ 2, 3},{ 2, 3},{ 2, 3},{ 2, 3},{ 2, 3},{ 2, 3},
+ { 2, 3},{ 2, 3},{ 2, 3},{ 2, 3},{ 2, 3},{ 2, 3},{ 2, 3},{ 2, 3},
+ { 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},
+ { 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},
+ { 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},
+ { 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},{ 1, 2},
+ { 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},
+ { 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},
+ { 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},
+ { 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},
+ { 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},
+ { 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},
+ { 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},
+ { 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},{ 0, 1},
+};
+
+const int32_t mp4_H263_width[5] = {128, 176, 352, 704, 1408};
+const int32_t mp4_H263_height[5] = {96, 144, 288, 576, 1152};
+const int32_t mp4_H263_mbgob[5] = {8, 11, 22, 88, 352};
+const int32_t mp4_H263_gobvop[5] = {6, 9, 18, 18, 18};
+const int32_t mp4_H263_rowgob[5] = {1, 1, 1, 2, 4};
+
+const uint8_t mp4_aux_comp_count[MP4_SHAPE_EXT_NUM+1] = {1, 1, 2, 2, 3, 1, 2, 1, 1, 2, 3, 2, 3, 0};
+const uint8_t mp4_aux_comp_is_alpha[MP4_SHAPE_EXT_NUM+1] = {1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0};
+const uint8_t mp4_BABtypeIntra[81][3] = {
+ 2, 4, 3, 4, 3, 2, 4, 2, 3, 2, 4, 3, 2, 3, 4, 2, 3, 4, 2, 4, 3, 2, 3, 4,
+ 4, 2, 3, 4, 3, 2, 2, 3, 4, 2, 3, 4, 4, 3, 2, 2, 3, 4, 3, 2, 4, 4, 3, 2,
+ 2, 3, 4, 2, 3, 4, 4, 2, 3, 2, 3, 4, 4, 3, 2, 4, 2, 3, 2, 3, 4, 4, 3, 2,
+ 4, 2, 3, 4, 3, 2, 4, 3, 2, 2, 3, 4, 2, 3, 4, 2, 3, 4, 2, 3, 4, 2, 3, 4,
+ 2, 3, 4, 2, 3, 4, 2, 3, 4, 4, 3, 2, 2, 3, 4, 4, 3, 2, 4, 3, 2, 2, 3, 4,
+ 3, 4, 2, 4, 3, 2, 2, 3, 4, 3, 4, 2, 4, 3, 2, 2, 3, 4, 4, 3, 2, 4, 2, 3,
+ 2, 3, 4, 4, 3, 2, 4, 2, 3, 2, 4, 3, 3, 4, 2, 4, 2, 3, 2, 4, 3, 4, 2, 3,
+ 4, 2, 3, 2, 3, 4, 2, 3, 4, 2, 3, 4, 2, 3, 4, 2, 3, 4, 4, 2, 3, 2, 3, 4,
+ 4, 3, 2, 4, 3, 2, 4, 2, 3, 3, 4, 2, 3, 4, 2, 4, 2, 3, 3, 4, 2, 4, 3, 2,
+ 2, 4, 3, 4, 3, 2, 4, 2, 3, 4, 2, 3, 3, 4, 2, 4, 3, 2, 2, 4, 3, 3, 4, 2,
+ 4, 3, 2
+};
+
diff --git a/Src/mpeg4dec/mpeg4dec.sln b/Src/mpeg4dec/mpeg4dec.sln
new file mode 100644
index 000000000..47c193340
--- /dev/null
+++ b/Src/mpeg4dec/mpeg4dec.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mpeg4dec", "mpeg4dec.vcproj", "{F082AB20-F012-4CB0-AA60-A8F7177AEBC1}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {F082AB20-F012-4CB0-AA60-A8F7177AEBC1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {F082AB20-F012-4CB0-AA60-A8F7177AEBC1}.Debug|Win32.Build.0 = Debug|Win32
+ {F082AB20-F012-4CB0-AA60-A8F7177AEBC1}.Release|Win32.ActiveCfg = Release|Win32
+ {F082AB20-F012-4CB0-AA60-A8F7177AEBC1}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Src/mpeg4dec/mpeg4dec.vcproj b/Src/mpeg4dec/mpeg4dec.vcproj
new file mode 100644
index 000000000..eb5685a9e
--- /dev/null
+++ b/Src/mpeg4dec/mpeg4dec.vcproj
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="mpeg4dec"
+ ProjectGUID="{F082AB20-F012-4CB0-AA60-A8F7177AEBC1}"
+ RootNamespace="mpeg4dec"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../Wasabi;&quot;$(ProgramFiles)\Intel\IPP\6.1.1.035\ia32\include&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="1"
+ AdditionalIncludeDirectories="../Wasabi;&quot;$(ProgramFiles)\Intel\IPP\6.1.1.035\ia32\include&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ BufferSecurityCheck="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\mp4decvop.c"
+ >
+ </File>
+ <File
+ RelativePath=".\mp4decvopb.c"
+ >
+ </File>
+ <File
+ RelativePath=".\mp4decvopi.c"
+ >
+ </File>
+ <File
+ RelativePath=".\mp4decvopp.c"
+ >
+ </File>
+ <File
+ RelativePath=".\mp4decvops.c"
+ >
+ </File>
+ <File
+ RelativePath=".\mp4parse.c"
+ >
+ </File>
+ <File
+ RelativePath=".\mp4stream.c"
+ >
+ </File>
+ <File
+ RelativePath=".\mp4tbl.c"
+ >
+ </File>
+ <File
+ RelativePath=".\mpeg4vid_api.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\mp4dec.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mp4def.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mpeg4vid_api.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Src/mpeg4dec/mpeg4vid_api.c b/Src/mpeg4dec/mpeg4vid_api.c
new file mode 100644
index 000000000..3c8004629
--- /dev/null
+++ b/Src/mpeg4dec/mpeg4vid_api.c
@@ -0,0 +1,661 @@
+#include "mpeg4vid_api.h"
+#include "mp4def.h"
+#include "mp4dec.h"
+
+/* TODO: we havn't implemented "end of stream" yet, but when we do
+we need to flush out the buffered frames
+m_decInfo->VisualObject.vFrame = m_decInfo->VisualObject.VideoObject.prevPlaneIsB ?
+&m_decInfo->VisualObject.nFrame : &m_decInfo->VisualObject.cFrame;
+*/
+
+// disable post processing for now, doesn't seem to be working out too well
+//#define MP4V_DO_POST_PROCESS
+
+#define MAX_CODED_FRAME 8000000 // TODO: benski> verify
+typedef struct
+{
+ mp4_Info dec;
+ int initted;
+ int resetting;
+ int skip_b_frames;
+#ifdef MP4V_DO_POST_PROCESS
+ mp4_Frame ppFrame0, ppFrame1;
+#endif
+ __declspec(align(32)) uint8_t buffer[MAX_CODED_FRAME];
+} MPEG4VideoDecoder;
+
+static int FreeBuffers(MPEG4VideoDecoder *decoder);
+
+void mp4_Error(const char *str)
+{
+ puts(str);
+}
+
+mpeg4vid_decoder_t MPEG4Video_CreateDecoder(int filetype, int codec)
+{
+ MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)malloc(sizeof(MPEG4VideoDecoder));
+ memset(decoder, 0, sizeof(MPEG4VideoDecoder));
+
+ // set configuration stuff
+ decoder->dec.stopOnErr = 0;
+ decoder->dec.strictSyntaxCheck = 0;
+ decoder->dec.VisualObject.verid = 1;
+ decoder->dec.ftype = filetype;
+ decoder->dec.ftype_f = codec;
+
+ return decoder;
+}
+
+void MPEG4Video_DestroyDecoder(mpeg4vid_decoder_t d)
+{
+ MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
+ if (decoder)
+ {
+#ifdef MP4V_DO_POST_PROCESS
+ free(decoder->ppFrame0.mid);
+ free(decoder->ppFrame1.mid);
+#endif
+ FreeBuffers(decoder);
+ free(decoder);
+ }
+}
+
+void MPEG4Video_Flush(mpeg4vid_decoder_t d)
+{
+ MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
+ if (decoder && decoder->initted)
+ {
+ mp4_ResetVOL(&decoder->dec);
+ decoder->resetting = 1;
+ }
+}
+
+static int AllocateInitFrame(mp4_Frame* pFrame)
+{
+ int32_t w, h;
+
+ w = (pFrame->mbPerRow + 2 * MP4_NUM_EXT_MB) << 4;
+ h = (pFrame->mbPerCol + 2 * MP4_NUM_EXT_MB) << 4;
+ pFrame->mid = malloc(w * h + (w * h >> 1));
+ if (!pFrame->mid)
+ return 1; // out of memory
+
+ ippsSet_8u(0, pFrame->mid, w * h);
+ ippsSet_8u(128, pFrame->mid + w * h, w * h >> 1);
+
+ pFrame->stepY = w;
+ pFrame->stepCb = w >> 1;
+ pFrame->stepCr = w >> 1;
+
+ /* benski> stuff from LockFrame... */
+ pFrame->apY = pFrame->mid;
+ pFrame->pY = pFrame->apY + w * 16 + 16;
+ pFrame->apCb = pFrame->apY + w * h;
+ w >>= 1;
+ h >>= 1;
+ pFrame->pCb = pFrame->apCb + w * 8 + 8;
+ pFrame->apCr = pFrame->apCb + w * h;
+ pFrame->pCr = pFrame->apCr + w * 8 + 8;
+
+ return 0;
+}
+
+static int AllocateBuffers(MPEG4VideoDecoder *decoder)
+{
+ if (mp4_InitVOL(&decoder->dec) != MP4_STATUS_OK)
+ {
+ mp4_Error("Error: No memory to allocate internal buffers\n");
+ return 1;//UMC_ERR_ALLOC;
+ }
+ return 0;
+}
+
+static int InsideInit(MPEG4VideoDecoder *decoder)
+{
+ int status;
+ uint32_t code;
+ int h_vo_found = 0, h_vos_found = 0;
+
+ for (;;)
+ {
+ if (!mp4_SeekStartCodeOrShortPtr(&decoder->dec))
+ {
+ mp4_Error("Error: Can't find Visual Object or Video Object start codes or short_video_start_marker\n");
+ return 1;//UMC_ERR_SYNC;
+ }
+ // check short_video_start_marker
+ if (mp4_IsShortCode(&decoder->dec))
+ {
+ if ((mp4_Parse_VideoObject(&decoder->dec)) != MP4_STATUS_OK)
+ return 1;//UMC_ERR_INVALID_STREAM;
+ break;
+ }
+ code = mp4_GetBits(&decoder->dec, 8);
+ if (!h_vos_found && code == MP4_VISUAL_OBJECT_SEQUENCE_SC)
+ {
+ h_vos_found = 1;
+ if ((mp4_Parse_VisualObjectSequence(&decoder->dec)) != MP4_STATUS_OK)
+ return 1;//UMC_ERR_INVALID_STREAM;
+ }
+
+ if (!h_vo_found && code == MP4_VISUAL_OBJECT_SC)
+ {
+ h_vo_found = 1;
+ if ((mp4_Parse_VisualObject(&decoder->dec)) != MP4_STATUS_OK)
+ return 1;//UMC_ERR_INVALID_STREAM;
+ }
+ // some streams can start with video_object_layer
+ if ((int32_t)code >= MP4_VIDEO_OBJECT_LAYER_MIN_SC && code <= MP4_VIDEO_OBJECT_LAYER_MAX_SC) {
+ decoder->dec.bufptr -= 4;
+ if ((mp4_Parse_VideoObject(&decoder->dec)) != MP4_STATUS_OK)
+ return 1;//UMC_ERR_INVALID_STREAM;
+ break;
+ }
+ }
+
+ status = AllocateBuffers(decoder);
+ if (status)
+ return status;
+
+
+#if 0 // don't really care about this, but might be useful code for later?
+ // set profile/level info
+ decoder->profile = decoder->dec.profile_and_level_indication >> 4;
+ decoder->level = decoder->dec.profile_and_level_indication & 15;
+ if (decoder->profile == MPEG4_PROFILE_SIMPLE)
+ if (decoder->level == 8)
+ decoder->level = MPEG4_LEVEL_0;
+ if (decoder->profile == MPEG4_PROFILE_ADVANCED_SIMPLE) {
+ if (decoder->level == 7)
+ decoder->level = MPEG4_LEVEL_3B;
+ if (decoder->level > 7) {
+ decoder->profile = MPEG4_PROFILE_FGS;
+ decoder->level -= 8;
+ }
+ }
+#endif
+ decoder->initted = 1;
+
+ return 0;
+}
+
+static int FreeBuffers(MPEG4VideoDecoder *decoder)
+{
+ int status = 0;
+
+ ReleaseFrame(&decoder->dec.VisualObject, decoder->dec.VisualObject.cFrame);
+ decoder->dec.VisualObject.cFrame=0;
+ ReleaseFrame(&decoder->dec.VisualObject, decoder->dec.VisualObject.rFrame);
+ decoder->dec.VisualObject.rFrame=0;
+ ReleaseFrame(&decoder->dec.VisualObject, decoder->dec.VisualObject.nFrame);
+ decoder->dec.VisualObject.nFrame=0;
+ ReleaseFrame(&decoder->dec.VisualObject, decoder->dec.VisualObject.sFrame);
+ decoder->dec.VisualObject.sFrame=0;
+ FreeCache(&decoder->dec.VisualObject);
+
+ mp4_FreeVOL(&decoder->dec);
+ return status;
+}
+
+static int PostProcess(MPEG4VideoDecoder *decoder, mp4_Frame *inout)
+{
+#ifdef MP4V_DO_POST_PROCESS
+ int w, h, i, j, k, QP, width, height;
+ IppiSize size;
+ Ipp8u *pSrc[3], *pDst[3];
+ int srcPitch[3], dstPitch[3], threshold[6];
+ int m_DeblockingProcPlane[3] = {1,1,1}; // TODO: configurable
+ int m_DeringingProcPlane[3] = {1,1,1}; // TODO: configurable
+ int32_t m_DeblockingTHR1 = 2; // TODO
+ int32_t m_DeblockingTHR2 = 6; // TODO
+ QP = inout->QP;
+ width = (decoder->dec.VisualObject.VideoObject.width + 7) & (~7);
+ height = (decoder->dec.VisualObject.VideoObject.height + 7) & (~7);
+ if (m_DeblockingProcPlane[0] || m_DeblockingProcPlane[1] || m_DeblockingProcPlane[2]) {
+ pSrc[0] = inout->pY;
+ srcPitch[0] = inout->stepY;
+ pDst[0] = decoder->ppFrame0.pY;
+ dstPitch[0] = decoder->ppFrame0.stepY;
+ pSrc[1] = inout->pCb;
+ srcPitch[1] = inout->stepCb;
+ pDst[1] = decoder->ppFrame0.pCb;
+ dstPitch[1] = decoder->ppFrame0.stepCb;
+ pSrc[2] = inout->pCr;
+ srcPitch[2] = inout->stepCr;
+ pDst[2] = decoder->ppFrame0.pCr;
+ dstPitch[2] = decoder->ppFrame0.stepCr;
+ for (k = 0; k < 3; k ++) {
+ if (m_DeblockingProcPlane[k]) {
+ size.height = 8;
+ if (k == 0) {
+ size.width = width;
+ h = height >> 3;
+ w = width >> 3;
+ } else {
+ size.width = width >> 1;
+ h = height >> 4;
+ w = width >> 4;
+ }
+ for (i = 0; i < h; i ++) {
+ ippiCopy_8u_C1R(pSrc[k], srcPitch[k], pDst[k], dstPitch[k], size);
+ if (i > 0) {
+ for (j = 0; j < w; j ++)
+ ippiFilterDeblocking8x8HorEdge_MPEG4_8u_C1IR(pDst[k] + 8 * j, dstPitch[k], QP, m_DeblockingTHR1, m_DeblockingTHR2);
+ for (j = 1; j < w; j ++)
+ ippiFilterDeblocking8x8VerEdge_MPEG4_8u_C1IR(pDst[k] - 8 * dstPitch[k] + 8 * j, dstPitch[k], QP, m_DeblockingTHR1, m_DeblockingTHR2);
+ }
+ if (i == h - 1) {
+ for (j = 1; j < w; j ++)
+ ippiFilterDeblocking8x8VerEdge_MPEG4_8u_C1IR(pDst[k] + 8 * j, dstPitch[k], QP, m_DeblockingTHR1, m_DeblockingTHR2);
+ }
+ pSrc[k] += srcPitch[k] * 8;
+ pDst[k] += dstPitch[k] * 8;
+ }
+ } else {
+ if (k == 0) {
+ size.width = width;
+ size.height = height;
+ } else {
+ size.width = width >> 1;
+ size.height = height >> 1;
+ }
+ ippiCopy_8u_C1R(pSrc[k], srcPitch[k], pDst[k], dstPitch[k], size);
+ }
+ }
+ *inout = decoder->ppFrame0;
+ }
+ if (m_DeringingProcPlane[0] || m_DeringingProcPlane[1] || m_DeringingProcPlane[2]) {
+ pSrc[0] = inout->pY;
+ srcPitch[0] = inout->stepY;
+ pDst[0] = decoder->ppFrame1.pY;
+ dstPitch[0] = decoder->ppFrame1.stepY;
+ if (!m_DeringingProcPlane[0]) {
+ size.width = width;
+ size.height = height;
+ ippiCopy_8u_C1R(pSrc[0], srcPitch[0], pDst[0], dstPitch[0], size);
+ }
+ pSrc[1] = inout->pCb;
+ srcPitch[1] = inout->stepCb;
+ pDst[1] = decoder->ppFrame1.pCb;
+ dstPitch[1] = decoder->ppFrame1.stepCb;
+ if (!m_DeringingProcPlane[1]) {
+ size.width = width >> 1;
+ size.height = height >> 1;
+ ippiCopy_8u_C1R(pSrc[1], srcPitch[1], pDst[1], dstPitch[1], size);
+ }
+ pSrc[2] = inout->pCr;
+ srcPitch[2] = inout->stepCr;
+ pDst[2] = decoder->ppFrame1.pCr;
+ dstPitch[2] = decoder->ppFrame1.stepCr;
+ if (!m_DeringingProcPlane[2]) {
+ size.width = width >> 1;
+ size.height = height >> 1;
+ ippiCopy_8u_C1R(pSrc[2], srcPitch[2], pDst[2], dstPitch[2], size);
+ }
+ h = inout->mbPerCol;
+ w = inout->mbPerRow;
+ for (i = 0; i < h; i ++) {
+ for (j = 0; j < w; j ++) {
+ ippiFilterDeringingThreshold_MPEG4_8u_P3R(pSrc[0]+ 16 * j, srcPitch[0], pSrc[1] + 8 * j, srcPitch[1], pSrc[2] + 8 * j, srcPitch[2], threshold);
+ // copy border macroblocks
+ if (i == 0 || i == h - 1 || j == 0 || j == w - 1) {
+ if (m_DeringingProcPlane[0])
+ ippiCopy16x16_8u_C1R(pSrc[0] + 16 * j, srcPitch[0], pDst[0] + 16 * j, dstPitch[0]);
+ if (m_DeringingProcPlane[1])
+ ippiCopy8x8_8u_C1R(pSrc[1] + 8 * j, srcPitch[1], pDst[1] + 8 * j, dstPitch[1]);
+ if (m_DeringingProcPlane[2])
+ ippiCopy8x8_8u_C1R(pSrc[2] + 8 * j, srcPitch[2], pDst[2] + 8 * j, dstPitch[2]);
+ }
+ if (m_DeringingProcPlane[0]) {
+ if (i != 0 && j != 0)
+ ippiFilterDeringingSmooth8x8_MPEG4_8u_C1R(pSrc[0] + 16 * j, srcPitch[0], pDst[0] + 16 * j, dstPitch[0], QP, threshold[0]);
+ if (i != 0 && j != w - 1)
+ ippiFilterDeringingSmooth8x8_MPEG4_8u_C1R(pSrc[0] + 16 * j + 8, srcPitch[0], pDst[0] + 16 * j + 8, dstPitch[0], QP, threshold[1]);
+ if (i != h - 1 && j != 0)
+ ippiFilterDeringingSmooth8x8_MPEG4_8u_C1R(pSrc[0] + 16 * j + 8 * srcPitch[0], srcPitch[0], pDst[0] + 16 * j + 8 * dstPitch[0], dstPitch[0], QP, threshold[2]);
+ if (i != h - 1 && j != w - 1)
+ ippiFilterDeringingSmooth8x8_MPEG4_8u_C1R(pSrc[0] + 16 * j + 8 * srcPitch[0] + 8, srcPitch[0], pDst[0] + 16 * j + 8 * dstPitch[0] + 8, dstPitch[0], QP, threshold[3]);
+ }
+ if (i != 0 && j != 0 && i != h - 1 && j != w - 1) {
+ if (m_DeringingProcPlane[1])
+ ippiFilterDeringingSmooth8x8_MPEG4_8u_C1R(pSrc[1] + 8 * j, srcPitch[1], pDst[1] + 8 * j, dstPitch[1], QP, threshold[4]);
+ if (m_DeringingProcPlane[2])
+ ippiFilterDeringingSmooth8x8_MPEG4_8u_C1R(pSrc[2] + 8 * j, srcPitch[2], pDst[2] + 8 * j, dstPitch[2], QP, threshold[5]);
+ }
+ }
+ pSrc[0] += srcPitch[0] * 16;
+ pDst[0] += dstPitch[0] * 16;
+ pSrc[1] += srcPitch[1] * 8;
+ pDst[1] += dstPitch[1] * 8;
+ pSrc[2] += srcPitch[2] * 8;
+ pDst[2] += dstPitch[2] * 8;
+ }
+ *inout = decoder->ppFrame1;
+ }
+#endif
+ return 0;
+}
+
+void MPEG4Video_DecodeFrame(mpeg4vid_decoder_t d, const void *buffer, size_t bufferlen, uint64_t time_code)
+{
+ int status=0;
+ int code;
+ MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
+
+ if (bufferlen > (MAX_CODED_FRAME-32))
+ return;
+
+ if (buffer)
+ {
+ memcpy(decoder->buffer, buffer, bufferlen);
+ memset(decoder->buffer+bufferlen, 0, 32);
+ decoder->dec.bitoff = 0;
+ decoder->dec.bufptr = decoder->dec.buffer = (uint8_t *)decoder->buffer;
+ decoder->dec.buflen = bufferlen;
+ }
+
+ if (!decoder->initted) // initialize off the first packet
+ {
+ status = InsideInit(decoder);
+ if (status)
+ return;
+ }
+
+ for (;;)
+ {
+ // Seeking the VOP start_code, and then begin the vop decoding
+ if (decoder->dec.VisualObject.VideoObject.short_video_header)
+ {
+ if (!mp4_SeekShortVideoStartMarker(&decoder->dec))
+ {
+ mp4_Error("Error: Failed seeking short_video_start_marker\n");
+ status = 1;//UMC_ERR_SYNC;
+ break;
+ }
+ }
+ else
+ {
+ for (;;)
+ {
+ if (!mp4_SeekStartCodePtr(&decoder->dec)) {
+ mp4_Error("Error: Failed seeking GOV or VOP Start Code");
+ status = 1;//UMC_ERR_SYNC;
+ break;
+ }
+ code = decoder->dec.bufptr[0];
+ decoder->dec.bufptr++;
+ // parse repeated VOS, VO and VOL headers because stream may be glued from different streams
+ if (code == MP4_VISUAL_OBJECT_SEQUENCE_SC)
+ {
+ if (mp4_Parse_VisualObjectSequence(&decoder->dec) != MP4_STATUS_OK)
+ {
+ status = 1;//UMC_ERR_INVALID_STREAM;
+ break;
+ }
+ }
+ else if (code == MP4_VISUAL_OBJECT_SC)
+ {
+ if (mp4_Parse_VisualObject(&decoder->dec) != MP4_STATUS_OK)
+ {
+ status = 1;//UMC_ERR_INVALID_STREAM;
+ break;
+ }
+ }
+ else if (code >= MP4_VIDEO_OBJECT_LAYER_MIN_SC && code <= MP4_VIDEO_OBJECT_LAYER_MAX_SC)
+ {
+ // save parameters which can affect on reinit
+ Ipp32s interlaced = decoder->dec.VisualObject.VideoObject.interlaced;
+ Ipp32s data_partitioned = decoder->dec.VisualObject.VideoObject.data_partitioned;
+ Ipp32s sprite_enable = decoder->dec.VisualObject.VideoObject.sprite_enable;
+ Ipp32s width = decoder->dec.VisualObject.VideoObject.width;
+ Ipp32s height = decoder->dec.VisualObject.VideoObject.height;
+
+ // in repeated headers check only VOL header
+ decoder->dec.bufptr -= 4;
+
+ if (mp4_Parse_VideoObject(&decoder->dec) != MP4_STATUS_OK) {
+ status = 1;//UMC_ERR_INVALID_STREAM;
+ break;
+ }
+ // realloc if something was changed
+ if (interlaced != decoder->dec.VisualObject.VideoObject.interlaced ||
+ data_partitioned != decoder->dec.VisualObject.VideoObject.data_partitioned ||
+ sprite_enable != decoder->dec.VisualObject.VideoObject.sprite_enable ||
+ width != decoder->dec.VisualObject.VideoObject.width ||
+ height != decoder->dec.VisualObject.VideoObject.height)
+ {
+ // TODO: return a code so we can return MP4_VIDEO_OUTPUT_FORMAT_CHANGED
+ if (decoder->dec.strictSyntaxCheck)
+ {
+ mp4_Error("Error: Repeated VOL header is different from previous");
+ status = 1;//UMC_ERR_INVALID_STREAM;
+ break;
+ }
+
+ // UnlockBuffers();
+ status = FreeBuffers(decoder);
+ if (status)
+ break;
+
+ status = AllocateBuffers(decoder);
+ if (status)
+ break;
+
+ // free buffers for MPEG-4 post-processing
+#ifdef MP4V_DO_POST_PROCESS
+ free(decoder->ppFrame0.mid);
+ decoder->ppFrame0.mid = 0;
+
+ free(decoder->ppFrame1.mid);
+ decoder->ppFrame1.mid = 0;
+#endif
+
+ // TODO: clear cache and display frames
+ }
+ // reinit quant matrix
+ ippiQuantInvIntraInit_MPEG4(decoder->dec.VisualObject.VideoObject.quant_type ? decoder->dec.VisualObject.VideoObject.intra_quant_mat : NULL, decoder->dec.VisualObject.VideoObject.QuantInvIntraSpec, 8);
+ ippiQuantInvInterInit_MPEG4(decoder->dec.VisualObject.VideoObject.quant_type ? decoder->dec.VisualObject.VideoObject.nonintra_quant_mat : NULL, decoder->dec.VisualObject.VideoObject.QuantInvInterSpec, 8);
+ }
+ else if (code == MP4_GROUP_OF_VOP_SC)
+ {
+ if (mp4_Parse_GroupOfVideoObjectPlane(&decoder->dec) != MP4_STATUS_OK)
+ {
+ status = 1;//UMC_ERR_INVALID_STREAM;
+ break;
+ }
+ }
+ else if (decoder->dec.bufptr[-1] == MP4_VIDEO_OBJECT_PLANE_SC)
+ {
+ break;
+ }
+ }
+ if (status)
+ break;
+
+ }
+
+ // parse VOP header
+ if ((mp4_Parse_VideoObjectPlane(&decoder->dec)) != MP4_STATUS_OK)
+ {
+ //status = UMC_WRN_INVALID_STREAM;
+ status = 0;
+ break;
+ }
+
+ if (decoder->resetting && decoder->dec.VisualObject.VideoObject.VideoObjectPlane.coding_type != MP4_VOP_TYPE_I)
+ {
+ //UnlockBuffers();
+ //return UMC_ERR_NOT_ENOUGH_DATA;
+// decoder->dec.VisualObject.vFrame = NULL;
+ status = 1;//UMC_ERR_NOT_ENOUGH_DATA;
+ break;
+ }
+ if (decoder->dec.VisualObject.VideoObject.VideoObjectPlane.coding_type == MP4_VOP_TYPE_B)
+ {
+ if (decoder->skip_b_frames)
+ {
+ decoder->dec.bufptr = decoder->dec.buffer+ decoder->dec.buflen;
+ status = 1;//UMC_ERR_NOT_ENOUGH_DATA;
+ break;
+ }
+ }
+
+ // decode VOP
+ if ((mp4_DecodeVideoObjectPlane(&decoder->dec)) != MP4_STATUS_OK)
+ {
+ status = 1;//UMC_WRN_INVALID_STREAM;
+ }
+ if (decoder->dec.VisualObject.cFrame)
+ {
+ decoder->dec.VisualObject.cFrame->timestamp = time_code;
+ decoder->dec.VisualObject.cFrame->QP = decoder->dec.VisualObject.VideoObject.short_video_header ? decoder->dec.VisualObject.VideoObject.VideoObjectPlaneH263.vop_quant : decoder->dec.VisualObject.VideoObject.VideoObjectPlane.quant;
+ }
+
+ // after reset it is need to skip first B-frames
+ if (decoder->dec.VisualObject.VideoObject.VOPindex < 2 && decoder->dec.VisualObject.VideoObject.VideoObjectPlane.coding_type == MP4_VOP_TYPE_B)
+ {
+ status = 1;//UMC_ERR_NOT_ENOUGH_DATA;
+ break;
+ }
+
+ // do not count not_coded P frames with same vop_time as reference (in AVI)
+
+ if (decoder->dec.VisualObject.VideoObject.VideoObjectPlane.coded ||
+ (
+ decoder->dec.VisualObject.cFrame &&
+ (!decoder->dec.VisualObject.rFrame || (decoder->dec.VisualObject.rFrame->time != decoder->dec.VisualObject.cFrame->time)) &&
+ (!decoder->dec.VisualObject.nFrame || (decoder->dec.VisualObject.nFrame->time != decoder->dec.VisualObject.cFrame->time))
+ )
+ )
+ {
+ decoder->dec.VisualObject.VideoObject.VOPindex++;
+ }
+ else
+ {
+ status = 1;//UMC_ERR_NOT_ENOUGH_DATA;
+ break;
+ }
+ if (decoder->resetting && decoder->dec.VisualObject.VideoObject.VideoObjectPlane.coding_type == MP4_VOP_TYPE_I)
+ {
+ // TODO: ???m_time_reset = (Ipp32s)decoder->dec.VisualObject.cFrame.time;
+ //decoder->dec.VisualObject.vFrame = NULL;
+ decoder->resetting = 0;
+ }
+
+ }
+ // return status;
+}
+
+void MPEG4Video_GetPicture(mpeg4vid_decoder_t d, mp4_Frame **frame)
+{
+ int status = 0;
+ MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
+
+ mp4_Frame *rendFrame = GetDisplayFrame(&decoder->dec.VisualObject);
+ if (rendFrame)
+ {
+ uint64_t timestamp = rendFrame->timestamp;
+#ifdef MP4V_DO_POST_PROCESS
+ if (1 /* TODO: disable deblocking and deringing on request*/)
+ {
+ if (!decoder->ppFrame0.mid)
+ {
+ decoder->ppFrame0.mbPerRow = decoder->dec.VisualObject.vFrame->mbPerRow;
+ decoder->ppFrame0.mbPerCol = decoder->dec.VisualObject.vFrame->mbPerCol;
+ status = AllocateInitFrame(&decoder->ppFrame0);
+ if (status)
+ return ;
+ }
+ if (!decoder->ppFrame1.mid)
+ {
+ decoder->ppFrame1.mbPerRow = decoder->dec.VisualObject.vFrame->mbPerRow;
+ decoder->ppFrame1.mbPerCol = decoder->dec.VisualObject.vFrame->mbPerCol;
+ status = AllocateInitFrame(&decoder->ppFrame1);
+ if (status)
+ return ;
+ }
+
+ PostProcess(decoder, rendFrame);
+ }
+#endif
+ //if (m_LastDecodedFrame.GetColorFormat() != YUV420) {
+ // m_LastDecodedFrame.Init(decoder->dec.VisualObject.VideoObject.width, decoder->dec.VisualObject.VideoObject.height, YUV420);
+ //}
+
+ // TODO ??? m_LastDecodedFrame.SetTime(pts);
+ *frame = rendFrame;
+ rendFrame->timestamp = timestamp;
+ }
+ else
+ *frame = 0;
+}
+
+void MPEG4Video_ReleaseFrame(mpeg4vid_decoder_t d, mp4_Frame *frame)
+{
+ MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
+ ReleaseFrame(&decoder->dec.VisualObject, frame);
+}
+
+static double GetAspectRatio(mp4_VideoObject *video_object)
+{
+ int aspect_ratio_width=1, aspect_ratio_height=1;
+ switch (video_object->aspect_ratio_info)
+ {
+ case MP4_ASPECT_RATIO_FORBIDDEN:
+ case MP4_ASPECT_RATIO_1_1:
+ aspect_ratio_width = 1;
+ aspect_ratio_height = 1;
+ break;
+ case MP4_ASPECT_RATIO_12_11:
+ aspect_ratio_width = 12;
+ aspect_ratio_height = 11;
+ break;
+ case MP4_ASPECT_RATIO_10_11:
+ aspect_ratio_width = 10;
+ aspect_ratio_height = 11;
+ break;
+ case MP4_ASPECT_RATIO_16_11:
+ aspect_ratio_width = 16;
+ aspect_ratio_height = 11;
+ break;
+ case MP4_ASPECT_RATIO_40_33:
+ aspect_ratio_width = 40;
+ aspect_ratio_height = 33;
+ break;
+ default:
+ aspect_ratio_width = video_object->aspect_ratio_info_par_width;
+ aspect_ratio_height = video_object->aspect_ratio_info_par_height;
+ break;
+ }
+ return (double)aspect_ratio_width / (double)aspect_ratio_height;
+}
+
+int MPEG4Video_GetOutputFormat(mpeg4vid_decoder_t d, int *width, int *height, double *aspect_ratio)
+{
+ MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
+ if (decoder && decoder->initted)
+ {
+ *width = decoder->dec.VisualObject.VideoObject.width;
+ *height = decoder->dec.VisualObject.VideoObject.height;
+ *aspect_ratio = GetAspectRatio(&decoder->dec.VisualObject.VideoObject);
+ return 0;
+ }
+ return 1;
+}
+
+void MPEG4Video_HurryUp(mpeg4vid_decoder_t d, int state)
+{
+ MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
+ if (decoder)
+ {
+ decoder->skip_b_frames = state;
+ }
+}
+void MPEG4Video_EndOfStream(mpeg4vid_decoder_t d)
+{
+ MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
+ if (decoder)
+ {
+ // TODO
+ }
+} \ No newline at end of file
diff --git a/Src/mpeg4dec/mpeg4vid_api.h b/Src/mpeg4dec/mpeg4vid_api.h
new file mode 100644
index 000000000..bdfdbad89
--- /dev/null
+++ b/Src/mpeg4dec/mpeg4vid_api.h
@@ -0,0 +1,54 @@
+#pragma once
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#include <bfc/platform/types.h>
+#include "mp4def.h"
+typedef void *mpeg4vid_decoder_t;
+
+mpeg4vid_decoder_t MPEG4Video_CreateDecoder(int filetype, int codec);
+void MPEG4Video_DestroyDecoder(mpeg4vid_decoder_t decoder);
+void MPEG4Video_DecodeFrame(mpeg4vid_decoder_t decoder, const void *buffer, size_t bufferlen, uint64_t time_code);
+void MPEG4Video_GetPicture(mpeg4vid_decoder_t decoder, mp4_Frame **frame);
+int MPEG4Video_GetOutputFormat(mpeg4vid_decoder_t decoder, int *width, int *height, double *aspect_ratio);
+void MPEG4Video_Flush(mpeg4vid_decoder_t decoder);
+void MPEG4Video_HurryUp(mpeg4vid_decoder_t decoder, int state);
+void MPEG4Video_EndOfStream(mpeg4vid_decoder_t decoder);
+void MPEG4Video_ReleaseFrame(mpeg4vid_decoder_t d, mp4_Frame *frame);
+#define MPEG4_PROFILE_SIMPLE 0
+#define MPEG4_PROFILE_SIMPLE_SCALABLE 1
+#define MPEG4_PROFILE_CORE 2
+#define MPEG4_PROFILE_MAIN 3
+#define MPEG4_PROFILE_NBIT 4
+#define MPEG4_PROFILE_SCALABLE_TEXTURE 5
+#define MPEG4_PROFILE_SIMPLE_FACE 6
+#define MPEG4_PROFILE_BASIC_ANIMATED_TEXTURE 7
+#define MPEG4_PROFILE_HYBRID 8
+#define MPEG4_PROFILE_ADVANCED_REAL_TIME_SIMPLE 9
+#define MPEG4_PROFILE_CORE_SCALABLE 10
+#define MPEG4_PROFILE_ADVANCED_CODE_EFFICIENCY 11
+#define MPEG4_PROFILE_ADVANCED_CORE 12
+#define MPEG4_PROFILE_ADVANCED_SCALABLE_TEXTURE 13
+#define MPEG4_PROFILE_STUDIO 14
+#define MPEG4_PROFILE_ADVANCED_SIMPLE 15
+#define MPEG4_PROFILE_FGS 16
+
+#define MPEG4_LEVEL_0 0
+#define MPEG4_LEVEL_1 1
+#define MPEG4_LEVEL_2 2
+#define MPEG4_LEVEL_3 3
+#define MPEG4_LEVEL_4 4
+#define MPEG4_LEVEL_5 5
+#define MPEG4_LEVEL_3B 13
+
+#define MPEG4_FILETYPE_RAW 0
+#define MPEG4_FILETYPE_MP4 1
+#define MPEG4_FILETYPE_AVI 2
+
+#define MPEG4_CODEC_DEFAULT 0
+#define MPEG4_CODEC_DIVX5 1
+
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file