blob: 48414d7b32a93caa5515c8f4821b95ddc3a7013f [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
* -------------------------------------------------------------------
*/
#include "mp4dec_lib.h"
#include "vlc_decode.h"
#include "bitstream.h"
/***********************************************************CommentBegin******
* 04/13/2000 : initial modification to the new PV-Decoder
* Lib format.
* 04/16/2001 : Removed PV_END_OF_BUFFER case, error resilience
***********************************************************CommentEnd********/
PV_STATUS PV_ReadVideoPacketHeader(VideoDecData *video, int *next_MB)
{
PV_STATUS status;
Vol *currVol = video->vol[video->currLayer];
Vop *currVop = video->currVop;
BitstreamDecVideo *stream = video->bitstream;
int fcode_forward;
int resync_marker_length;
int nbits = video->nBitsForMBID;
uint32 tmpvar32;
uint tmpvar16;
int16 quantizer;
int nTotalMB = video->nTotalMB;
fcode_forward = currVop->fcodeForward;
resync_marker_length = 17;
if (currVop->predictionType != I_VOP) resync_marker_length = 16 + fcode_forward;
status = PV_BitstreamShowBitsByteAlign(stream, resync_marker_length, &tmpvar32);
/* if (status != PV_SUCCESS && status != PV_END_OF_BUFFER) return status; */
if (tmpvar32 == RESYNC_MARKER)
{
// DecNextStartCode(stream);
PV_BitstreamByteAlign(stream);
BitstreamReadBits32(stream, resync_marker_length);
*next_MB = (int) BitstreamReadBits16(stream, nbits);
// if (*next_MB <= video->mbnum) /* needs more investigation */
// *next_MB = video->mbnum+1;
if (*next_MB >= nTotalMB) /* fix 04/05/01 */
{
*next_MB = video->mbnum + 1;
if (*next_MB >= nTotalMB) /* this check is needed */
*next_MB = nTotalMB - 1;
}
quantizer = (int16) BitstreamReadBits16(stream, currVol->quantPrecision);
if (quantizer == 0) return PV_FAIL; /* 04/03/01 */
currVop->quantizer = quantizer;
/* if we have HEC, read some redundant VOP header information */
/* this part needs improvement 04/05/01 */
if (BitstreamRead1Bits(stream))
{
int time_base = -1;
/* modulo_time_base (? bits) */
do
{
time_base++;
tmpvar16 = BitstreamRead1Bits(stream);
}
while (tmpvar16 == 1);
/* marker bit */
BitstreamRead1Bits(stream);
/* vop_time_increment (1-15 bits) */
BitstreamReadBits16(stream, currVol->nbitsTimeIncRes);
/* marker bit */
BitstreamRead1Bits(stream);
/* vop_prediction_type (2 bits) */
BitstreamReadBits16(stream, 2);
/* Added intra_dc_vlc_thr reading */
BitstreamReadBits16(stream, 3);
/* fcodes */
if (currVop->predictionType != I_VOP)
{
fcode_forward = (int) BitstreamReadBits16(stream, 3);
if (currVop->predictionType == B_VOP)
{
BitstreamReadBits16(stream, 3);
}
}
}
}
else
{
PV_BitstreamByteAlign(stream); /* */
status = BitstreamCheckEndBuffer(stream); /* return end_of_VOP 03/30/01 */
if (status != PV_SUCCESS)
{
return status;
}
status = BitstreamShowBits32HC(stream, &tmpvar32); /* 07/07/01 */
/* -16 = 0xFFFFFFF0*/
if ((tmpvar32 & 0xFFFFFFF0) == VISUAL_OBJECT_SEQUENCE_START_CODE) /* start code mask 00 00 01 */
{
/* we don't have to check for legl stuffing here. 05/08/2000 */
return PV_END_OF_VOP;
}
else
{
return PV_FAIL;
}
}
return PV_SUCCESS;
}
/***********************************************************CommentBegin******
* 3/10/00 : initial modification to the
* new PV-Decoder Lib format.
* 04/17/01 : remove PV_END_OF_BUFFER, error checking
***********************************************************CommentEnd********/
PV_STATUS PV_GobHeader(VideoDecData *video)
{
uint32 tmpvar;
Vop *currVop = video->currVop;
BitstreamDecVideo *stream = video->bitstream;
int quantPrecision = 5;
int16 quantizer;
BitstreamShowBits32(stream, GOB_RESYNC_MARKER_LENGTH, &tmpvar);
if (tmpvar != GOB_RESYNC_MARKER)
{
PV_BitstreamShowBitsByteAlign(stream, GOB_RESYNC_MARKER_LENGTH, &tmpvar);
if (tmpvar != GOB_RESYNC_MARKER)
{
return PV_FAIL;
}
else
PV_BitstreamByteAlign(stream); /* if bytealigned GOBHEADER search is performed */
/* then no more noforcestuffing */
}
/* we've got a GOB header info here */
BitstreamShowBits32(stream, GOB_RESYNC_MARKER_LENGTH + 5, &tmpvar);
tmpvar &= 0x1F;
if (tmpvar == 0)
{
return PV_END_OF_VOP;
}
if (tmpvar == 31)
{
PV_BitstreamFlushBits(stream, GOB_RESYNC_MARKER_LENGTH + 5);
BitstreamByteAlignNoForceStuffing(stream);
return PV_END_OF_VOP;
}
PV_BitstreamFlushBits(stream, GOB_RESYNC_MARKER_LENGTH + 5);
currVop->gobNumber = (int) tmpvar;
if (currVop->gobNumber >= video->nGOBinVop) return PV_FAIL;
currVop->gobFrameID = (int) BitstreamReadBits16(stream, 2);
quantizer = (int16) BitstreamReadBits16(stream, quantPrecision);
if (quantizer == 0) return PV_FAIL; /* 04/03/01 */
currVop->quantizer = quantizer;
return PV_SUCCESS;
}
#ifdef PV_ANNEX_IJKT_SUPPORT
PV_STATUS PV_H263SliceHeader(VideoDecData *video, int *next_MB)
{
PV_STATUS status;
uint32 tmpvar;
Vop *currVop = video->currVop;
BitstreamDecVideo *stream = video->bitstream;
int nTotalMB = video->nTotalMB;
int16 quantizer;
PV_BitstreamShowBitsByteAlignNoForceStuffing(stream, 17, &tmpvar);
if (tmpvar == RESYNC_MARKER)
{
BitstreamByteAlignNoForceStuffing(stream);
PV_BitstreamFlushBits(stream, 17);
if (!BitstreamRead1Bits(stream))
{
return PV_FAIL;
}
*next_MB = BitstreamReadBits16(stream, video->nBitsForMBID);
if (*next_MB >= nTotalMB) /* fix 04/05/01 */
{
*next_MB = video->mbnum + 1;
if (*next_MB >= nTotalMB) /* this check is needed */
*next_MB = nTotalMB - 1;
}
/* we will not parse sebp2 for large pictures 3GPP */
quantizer = (int16) BitstreamReadBits16(stream, 5);
if (quantizer == 0) return PV_FAIL;
currVop->quantizer = quantizer;
if (!BitstreamRead1Bits(stream))
{
return PV_FAIL;
}
currVop->gobFrameID = (int) BitstreamReadBits16(stream, 2);
}
else
{
status = BitstreamCheckEndBuffer(stream); /* return end_of_VOP 03/30/01 */
if (status != PV_SUCCESS)
{
return status;
}
PV_BitstreamShowBitsByteAlign(stream, SHORT_VIDEO_START_MARKER_LENGTH, &tmpvar);
if (tmpvar == SHORT_VIDEO_START_MARKER)
{
/* we don't have to check for legal stuffing here. 05/08/2000 */
return PV_END_OF_VOP;
}
else
{
return PV_FAIL;
}
}
return PV_SUCCESS;
}
#endif