Initial community commit

This commit is contained in:
Jef 2024-09-24 14:54:57 +02:00
parent 537bcbc862
commit fc06254474
16440 changed files with 4239995 additions and 2 deletions

708
Src/mpeg4dec/mp4dec.h Normal file
View file

@ -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

1983
Src/mpeg4dec/mp4decvop.c Normal file

File diff suppressed because it is too large Load diff

831
Src/mpeg4dec/mp4decvopb.c Normal file
View file

@ -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;
}

408
Src/mpeg4dec/mp4decvopi.c Normal file
View file

@ -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;
}
}

1079
Src/mpeg4dec/mp4decvopp.c Normal file

File diff suppressed because it is too large Load diff

655
Src/mpeg4dec/mp4decvops.c Normal file
View file

@ -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;
}
}

975
Src/mpeg4dec/mp4def.h Normal file
View file

@ -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

1109
Src/mpeg4dec/mp4parse.c Normal file

File diff suppressed because it is too large Load diff

326
Src/mpeg4dec/mp4stream.c Normal file
View file

@ -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;
}

153
Src/mpeg4dec/mp4tbl.c Normal file
View file

@ -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
};

20
Src/mpeg4dec/mpeg4dec.sln Normal file
View file

@ -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

View file

@ -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>

661
Src/mpeg4dec/mpeg4vid_api.c Normal file
View file

@ -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
}
}

View file

@ -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