| /* ------------------------------------------------------------------ |
| * 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 |
| |