📄 swdec_videopacket.c
字号:
/*------------------------------------------------------------------------------
-- --
-- This software is confidential and proprietary and may be used --
-- only as expressly authorized by a licensing agreement from --
-- --
-- Hantro Products Oy. --
-- --
-- In the event of publication, the following notice is applicable: --
-- --
-- (C) COPYRIGHT 2004 HANTRO PRODUCTS OY --
-- ALL RIGHTS RESERVED --
-- --
-- The entire notice above must be reproduced on all copies. --
-- --
--------------------------------------------------------------------------------
--
-- Abstract : Video packet decoding functionality
--
-------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
Table of contents
1. Include headers
2. External identifiers
3. Module defines
4. Module identifiers
5. Fuctions
5.1 SwDec_DecodeVideoPacketHeader
5.2 SwDec_DecodeVideoPacket
5.3 SwDec_CheckNextVpMbNumber
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
1. Include headers
------------------------------------------------------------------------------*/
#include "SwDec_VideoPacket.h"
#include "SwDec_Utils.h"
#include "SwDec_MotionTexture.h"
/*------------------------------------------------------------------------------
2. External identifiers
------------------------------------------------------------------------------*/
#ifndef MP4DEC_H263_ONLY
/*------------------------------------------------------------------------------
3. Module defines
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
4. Module indentifiers
------------------------------------------------------------------------------*/
static const u32 stuffingTable[8] = {0x0,0x1,0x3,0x7,0xF,0x1F,0x3F,0x7F};
STATIC u32 SwDec_DecodeVideoPacketHeader(decContainer_t *pDecContainer);
/*------------------------------------------------------------------------------
5.1 Function name: SwDec_DecodeVideoPacketHeader
Purpose: Decode video packet header
Input:
Pointer to decContainer_t structure
Output:
HANTRO_OK/HANTRO_NOK/END_OF_STREAM
------------------------------------------------------------------------------*/
u32 SwDec_DecodeVideoPacketHeader(decContainer_t *pDecContainer)
{
u32 i,tmp;
i32 itmp;
pDecContainer->StrmStorage.vpNumMbs = 0;
/* length of macro_block_number determined by size of the VOP in mbs */
tmp = SwDec_NumBits(pDecContainer->VopDesc.totalMbInVop-1);
tmp = SwDec_GetBits(pDecContainer, tmp);
CHECK_END_OF_STREAM(tmp);
/* erroneous macro block number */
if (tmp != pDecContainer->StrmStorage.vpMbNumber)
{
return(HANTRO_NOK);
}
/* QP */
tmp = SwDec_GetBits(pDecContainer, 5);
CHECK_END_OF_STREAM(tmp);
if (tmp == 0)
{
return(HANTRO_NOK);
}
pDecContainer->StrmStorage.QP = tmp;
pDecContainer->StrmStorage.prevQP = tmp;
pDecContainer->StrmStorage.vpQP = tmp;
/* HEC */
tmp = SwDec_GetOneBit(pDecContainer);
CHECK_END_OF_STREAM(tmp);
/* decode header extension. Values are used only if vop header was
* lost for any reason. Otherwise values are just compared to ones
* received in vop header and errors are reported if they do not match */
if (tmp)
{
/* modulo time base */
i = 0;
while ((tmp = SwDec_GetOneBit(pDecContainer)) == 1)
i++;
CHECK_END_OF_STREAM(tmp);
/* update time codes if vop header not valid */
if (!pDecContainer->StrmStorage.validVopHeader)
{
pDecContainer->VopDesc.timeCodeSeconds += i;
/* to support modulo_time_base values higher than 60 -> while */
while (pDecContainer->VopDesc.timeCodeSeconds >= 60)
{
pDecContainer->VopDesc.timeCodeSeconds -= 60;
pDecContainer->VopDesc.timeCodeMinutes++;
if (pDecContainer->VopDesc.timeCodeMinutes >= 60)
{
pDecContainer->VopDesc.timeCodeMinutes -= 60;
pDecContainer->VopDesc.timeCodeHours++;
}
}
pDecContainer->VopDesc.moduloTimeBase = i;
}
else if (i != pDecContainer->VopDesc.moduloTimeBase)
{
return(HANTRO_NOK);
}
/* marker */
tmp = SwDec_GetOneBit(pDecContainer);
CHECK_END_OF_STREAM(tmp);
if (tmp == 0)
{
return(HANTRO_NOK);
}
/* number of bits needed to represent
* [0,vop_time_increment_resolution) */
i = SwDec_NumBits(pDecContainer->Hdrs.vopTimeIncrementResolution
- 1);
tmp = SwDec_GetBits(pDecContainer, i);
CHECK_END_OF_STREAM(tmp);
if (!pDecContainer->StrmStorage.validVopHeader)
{
if (tmp >= pDecContainer->Hdrs.vopTimeIncrementResolution)
{
return(HANTRO_NOK);
}
/* compute tics since previous picture */
itmp = (i32)tmp - (i32)(pDecContainer->VopDesc.vopTimeIncrement +
pDecContainer->VopDesc.moduloTimeBase*
pDecContainer->Hdrs.vopTimeIncrementResolution);
pDecContainer->VopDesc.ticsFromPrev = (itmp >= 0) ? (u32)itmp:
(u32)(itmp + (i32)pDecContainer->Hdrs.vopTimeIncrementResolution);
pDecContainer->VopDesc.vopTimeIncrement = tmp;
}
else if (tmp != pDecContainer->VopDesc.vopTimeIncrement)
{
return(HANTRO_NOK);
}
/* marker */
tmp = SwDec_GetOneBit(pDecContainer);
CHECK_END_OF_STREAM(tmp);
if (tmp == 0)
{
return(HANTRO_NOK);
}
tmp = SwDec_GetBits(pDecContainer,2); /* vop_coding_type */
CHECK_END_OF_STREAM(tmp);
if (pDecContainer->StrmStorage.validVopHeader)
{
if (tmp != pDecContainer->VopDesc.vopCodingType)
{
return(HANTRO_NOK);
}
}
else
{
if ((tmp != IVOP) && (tmp != PVOP))
{
return(HANTRO_NOK);
}
else
{
pDecContainer->VopDesc.vopCodingType = tmp;
}
}
tmp = SwDec_GetBits(pDecContainer,3); /* intra_dc_vlc_thr */
CHECK_END_OF_STREAM(tmp);
if (pDecContainer->StrmStorage.validVopHeader)
{
if (tmp != pDecContainer->VopDesc.intraDcVlcThr)
{
return(HANTRO_NOK);
}
}
else
{
pDecContainer->VopDesc.intraDcVlcThr = tmp;
}
if (pDecContainer->VopDesc.vopCodingType == PVOP)
{
tmp = SwDec_GetBits(pDecContainer,3); /* vop_fcode_fwd */
CHECK_END_OF_STREAM(tmp);
if (pDecContainer->StrmStorage.validVopHeader)
{
if (tmp != pDecContainer->VopDesc.fcodeFwd)
{
return(HANTRO_NOK);
}
}
else
{
if (tmp == 0)
{
return(HANTRO_NOK);
}
pDecContainer->VopDesc.fcodeFwd = tmp;
pDecContainer->VopDesc.vopRoundingType = 0;
}
}
else
{
/* set vop_fcode_fwd of intra VOP to 1 for resync marker length
* computation */
pDecContainer->VopDesc.fcodeFwd = 1;
}
pDecContainer->StrmStorage.resyncMarkerLength =
pDecContainer->VopDesc.fcodeFwd + 16;
if (!pDecContainer->StrmStorage.validVopHeader)
{
pDecContainer->StrmStorage.validVopHeader = 1;
}
}
if (pDecContainer->StrmStorage.validVopHeader)
{
return(HANTRO_OK);
}
else
{
return(HANTRO_NOK);
}
}
/*------------------------------------------------------------------------------
5.2 Function name: SwDec_DecodeVideoPacket
Purpose: Decode video packet
Input:
Pointer to decContainer_t structure
Output:
HANTRO_OK/HANTRO_NOK/END_OF_STREAM
------------------------------------------------------------------------------*/
u32 SwDec_DecodeVideoPacket(decContainer_t *pDecContainer)
{
u32 tmp;
u32 isEndOfVop;
u32 stuffingLength;
u32 isResyncMarker = 0;
u32 status = HANTRO_OK;
ASSERT(pDecContainer);
ASSERT(!pDecContainer->StrmStorage.shortVideo);
status = SwDec_DecodeVideoPacketHeader(pDecContainer);
if (status != HANTRO_OK) return(status);
status = SwDec_DecodeMotionTexture(pDecContainer);
if (status != HANTRO_OK) return(status);
isEndOfVop = (pDecContainer->StrmStorage.vpMbNumber +
pDecContainer->StrmStorage.vpNumMbs) ==
pDecContainer->VopDesc.totalMbInVop;
status = SwDec_GetStuffing(pDecContainer);
if ( (status != HANTRO_OK) && isEndOfVop )
{
/* read stuffing until stream ends or resync marker or
* startcode found */
while( !IS_END_OF_STREAM(pDecContainer) )
{
tmp = SwDec_ShowBits(pDecContainer,32);
isResyncMarker =
(tmp>>(32-pDecContainer->StrmStorage.resyncMarkerLength));
/* break if there is resync marker or startcode */
if ( (isResyncMarker == 0x1) || ((tmp>>8) == 0x1) )
break;
/* read stuffing byte */
stuffingLength = 8-pDecContainer->StrmDesc.bitPosInWord;
tmp = SwDec_GetBits(pDecContainer,stuffingLength);
/* check that stuffing is valid H.263 or MPEG-4 stuffing */
if ( (tmp != 0) && (tmp != stuffingTable[stuffingLength - 1]))
return (HANTRO_NOK);
}
}
else if ( status != HANTRO_OK )
return (HANTRO_NOK);
/* there might be extra stuffing byte if next start code is video
* object sequence start or end code */
tmp = SwDec_ShowBitsAligned(pDecContainer,32,1);
if ((tmp == SC_VOS_START) || (tmp == SC_VOS_END))
{
tmp = SwDec_GetStuffing(pDecContainer);
if (tmp != HANTRO_OK) return(tmp);
}
/* stuffing ok -> check that there is proper start code or marker or
* stream ends */
tmp = SwDec_ShowBits(pDecContainer,32);
if (/* END_OF_STREAM */
IS_END_OF_STREAM(pDecContainer) ||
/* RESYNC_MARKER */
(((tmp>>(32-pDecContainer->StrmStorage.resyncMarkerLength)) == 0x01) &&
!isEndOfVop) ||
/* end of VOP and START_CODE or SC_ERROR (i.e. at least 23 zeros) */
(isEndOfVop && !(tmp>>9)))
{
/* whole video packet decoded and stuffing ok -> set vpMbNumber in
* StrmStorage so that this video packet won't be touched/concealed
* anymore. Also set VpQP to QP so that concealment will use qp of last
* decoded macro block */
pDecContainer->StrmStorage.vpMbNumber +=
pDecContainer->StrmStorage.vpNumMbs;
pDecContainer->StrmStorage.vpQP = pDecContainer->StrmStorage.QP;
pDecContainer->StrmStorage.vpNumMbs = 0;
return(HANTRO_OK);
}
else
{
return(HANTRO_NOK);
}
}
/*------------------------------------------------------------------------------
5.3 Function name: SwDec_CheckNextVpMbNumber
Purpose:
Input:
Pointer to decContainer_t structure
Output:
macro block number
0 if non-valid number found in stream
------------------------------------------------------------------------------*/
u32 SwDec_CheckNextVpMbNumber(decContainer_t *pDecContainer)
{
u32 tmp;
u32 mbNumber;
tmp = SwDec_NumBits(pDecContainer->VopDesc.totalMbInVop-1);
/* if not enough bits left -> return 0 */
if ((i32)tmp <= ( (i32)pDecContainer->StrmDesc.strmBuffSize*8 -
(i32)pDecContainer->StrmDesc.strmBuffReadBits ))
{
mbNumber = SwDec_ShowBits(pDecContainer, tmp);
/* use zero value to indicate non valid macro block number */
if (mbNumber >= pDecContainer->VopDesc.totalMbInVop)
{
mbNumber = 0;
}
}
else
{
mbNumber = 0;
}
return(mbNumber);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -