| /* ------------------------------------------------------------------ |
| * 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 "log/log.h" |
| |
| #include "mp4dec_lib.h" |
| #include "bitstream.h" |
| #include "vlc_decode.h" |
| #include "zigzag.h" |
| |
| #define OSCL_DISABLE_WARNING_CONV_POSSIBLE_LOSS_OF_DATA |
| |
| #ifdef PV_SUPPORT_MAIN_PROFILE |
| /* INTRA */ |
| const static int mpeg_iqmat_def[NCOEFF_BLOCK] = |
| { |
| 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 |
| }; |
| |
| /* INTER */ |
| const static int mpeg_nqmat_def[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 |
| }; |
| #endif |
| |
| /* ======================================================================== */ |
| /* Function : CalcNumBits() */ |
| /* Purpose : */ |
| /* In/out : */ |
| /* Return : Calculate the minimum number of bits required to */ |
| /* represent x. */ |
| /* Note : This is an equivalent implementation of */ |
| /* (long)ceil(log((double)x)/log(2.0)) */ |
| /* Modified : */ |
| /* ======================================================================== */ |
| int CalcNumBits(uint x) |
| { |
| int i = 1; |
| while (x >>= 1) i++; |
| return i; |
| } |
| |
| |
| |
| /***********************************************************CommentBegin****** |
| * |
| * -- DecodeVolHeader -- Decode the header of a VOL |
| * |
| * 04/10/2000 : initial modification to the new PV-Decoder Lib format. |
| * 10/12/2001 : reject non compliant bitstreams |
| * |
| ***********************************************************CommentEnd********/ |
| PV_STATUS DecodeVOLHeader(VideoDecData *video, int layer) |
| { |
| PV_STATUS status; |
| Vol *currVol; |
| BitstreamDecVideo *stream; |
| uint32 tmpvar, vol_shape; |
| uint32 startCode; |
| #ifdef PV_SUPPORT_MAIN_PROFILE |
| int *qmat, i, j; |
| #endif |
| int version_id = 1; |
| #ifdef PV_TOLERATE_VOL_ERRORS |
| uint32 profile = 0x01; |
| #endif |
| /* There's a "currLayer" variable inside videoDecData. */ |
| /* However, we don't maintain it until we decode frame data. 04/05/2000 */ |
| currVol = video->vol[layer]; |
| stream = currVol->bitstream; |
| currVol->moduloTimeBase = 0; |
| |
| /* Determine which start code for the decoder to begin with */ |
| status = BitstreamShowBits32HC(stream, &startCode); |
| |
| if (startCode == VISUAL_OBJECT_SEQUENCE_START_CODE) |
| { /* Bitstream Exhchange Fix 9/99 */ |
| /* Bitstream Exchange requires we allow start with Video Object Sequence */ |
| /* visual_object_sequence_start_code */ |
| (void) BitstreamReadBits32HC(stream); |
| tmpvar = (uint32) BitstreamReadBits16(stream, 8); /* profile */ |
| #ifndef PV_TOLERATE_VOL_ERRORS |
| if (layer) /* */ |
| { |
| /* support SSPL0-2 */ |
| if (tmpvar != 0x10 && tmpvar != 0x11 && tmpvar != 0x12 && |
| tmpvar != 0xA1 && tmpvar != 0xA2 && tmpvar != 0xA3/* Core SP@L1-L3 */) |
| return PV_FAIL; |
| } |
| else |
| { |
| /* support SPL0-3 & SSPL0-2 */ |
| if (tmpvar != 0x01 && tmpvar != 0x02 && tmpvar != 0x03 && tmpvar != 0x08 && |
| /* While not technically supported, try to decode SPL4&SPL5 files as well. */ |
| /* We'll fail later if the size is too large. This is to allow playback of */ |
| /* some <=CIF files generated by other encoders. */ |
| tmpvar != 0x04 && tmpvar != 0x05 && |
| tmpvar != 0x10 && tmpvar != 0x11 && tmpvar != 0x12 && |
| tmpvar != 0x21 && tmpvar != 0x22 && /* Core Profile Levels */ |
| tmpvar != 0xA1 && tmpvar != 0xA2 && tmpvar != 0xA3 && |
| tmpvar != 0xF0 && tmpvar != 0xF1 && /* Advanced Simple Profile Levels*/ |
| tmpvar != 0xF2 && tmpvar != 0xF3 && |
| tmpvar != 0xF4 && tmpvar != 0xF5) |
| return PV_FAIL; |
| } |
| #else |
| profile = tmpvar; |
| #endif |
| |
| // save the profile and level for the query |
| currVol->profile_level_id = (uint)tmpvar; // 6/10/04 |
| |
| |
| |
| status = BitstreamShowBits32HC(stream, &tmpvar); |
| if (tmpvar == USER_DATA_START_CODE) |
| { |
| /* Something has to be done with user data 11/11/99 */ |
| status = DecodeUserData(stream); |
| if (status != PV_SUCCESS) return PV_FAIL; |
| } |
| /* visual_object_start_code */ |
| BitstreamShowBits32HC(stream, &tmpvar); |
| if (tmpvar != VISUAL_OBJECT_START_CODE) |
| { |
| do |
| { |
| /* Search for VOL_HEADER */ |
| status = PVSearchNextM4VFrame(stream); /* search 0x00 0x00 0x01 */ |
| if (status != PV_SUCCESS) return PV_FAIL; /* breaks the loop */ |
| BitstreamShowBits32(stream, VOL_START_CODE_LENGTH, &tmpvar); |
| PV_BitstreamFlushBits(stream, 8); |
| } |
| while (tmpvar != VOL_START_CODE); |
| goto decode_vol; |
| } |
| else |
| { |
| BitstreamReadBits32HC(stream); |
| } |
| |
| /* is_visual_object_identifier */ |
| tmpvar = (uint32) BitstreamRead1Bits(stream); |
| if (tmpvar) |
| { |
| /* visual_object_verid */ |
| tmpvar = (uint32) BitstreamReadBits16(stream, 4); |
| /* visual_object_priority */ |
| tmpvar = (uint32) BitstreamReadBits16(stream, 3); |
| } |
| /* visual_object_type */ |
| BitstreamShowBits32(stream, 4, &tmpvar); |
| if (tmpvar == 1) |
| { /* video_signal_type */ |
| PV_BitstreamFlushBits(stream, 4); |
| tmpvar = (uint32) BitstreamRead1Bits(stream); |
| if (tmpvar == 1) |
| { |
| /* video_format */ |
| tmpvar = (uint32) BitstreamReadBits16(stream, 3); |
| /* video_range */ |
| tmpvar = (uint32) BitstreamRead1Bits(stream); |
| /* color_description */ |
| tmpvar = (uint32) BitstreamRead1Bits(stream); |
| if (tmpvar == 1) |
| { |
| /* color_primaries */ |
| tmpvar = (uint32) BitstreamReadBits16(stream, 8); |
| /* transfer_characteristics */ |
| tmpvar = (uint32) BitstreamReadBits16(stream, 8); |
| /* matrix_coefficients */ |
| tmpvar = (uint32) BitstreamReadBits16(stream, 8); |
| } |
| } |
| } |
| else |
| { |
| do |
| { |
| /* Search for VOL_HEADER */ |
| status = PVSearchNextM4VFrame(stream); /* search 0x00 0x00 0x01 */ |
| if (status != PV_SUCCESS) return PV_FAIL; /* breaks the loop */ |
| BitstreamShowBits32(stream, VOL_START_CODE_LENGTH, &tmpvar); |
| PV_BitstreamFlushBits(stream, 8); |
| } |
| while (tmpvar != VOL_START_CODE); |
| goto decode_vol; |
| } |
| |
| /* next_start_code() */ |
| status = PV_BitstreamByteAlign(stream); /* 10/12/01 */ |
| status = BitstreamShowBits32HC(stream, &tmpvar); |
| |
| if (tmpvar == USER_DATA_START_CODE) |
| { |
| /* Something has to be done to deal with user data (parse it) 11/11/99 */ |
| status = DecodeUserData(stream); |
| if (status != PV_SUCCESS) return PV_FAIL; |
| } |
| status = BitstreamShowBits32(stream, 27, &tmpvar); /* 10/12/01 */ |
| } |
| else |
| { |
| /* tmpvar = 0; */ /* 10/12/01 */ |
| status = BitstreamShowBits32(stream, 27, &tmpvar); /* uncomment this line if you want |
| to start decoding with a |
| video_object_start_code */ |
| } |
| |
| if (tmpvar == VO_START_CODE) |
| { |
| /***** |
| * |
| * Read the VOL header entries from the bitstream |
| * |
| *****/ |
| /* video_object_start_code */ |
| tmpvar = BitstreamReadBits32(stream, 27); |
| tmpvar = (uint32) BitstreamReadBits16(stream, 5); |
| |
| |
| /* video_object_layer_start_code */ |
| BitstreamShowBits32(stream, VOL_START_CODE_LENGTH, &tmpvar); |
| if (tmpvar != VOL_START_CODE) |
| { |
| status = BitstreamCheckEndBuffer(stream); |
| if (status == PV_END_OF_VOP) |
| { |
| video->shortVideoHeader = TRUE; |
| return PV_SUCCESS; |
| } |
| else |
| { |
| do |
| { |
| /* Search for VOL_HEADER */ |
| status = PVSearchNextM4VFrame(stream);/* search 0x00 0x00 0x01 */ |
| if (status != PV_SUCCESS) return PV_FAIL; /* breaks the loop */ |
| BitstreamShowBits32(stream, VOL_START_CODE_LENGTH, &tmpvar); |
| PV_BitstreamFlushBits(stream, 8); /* advance the byte ptr */ |
| } |
| while (tmpvar != VOL_START_CODE); |
| } |
| } |
| else |
| { |
| PV_BitstreamFlushBits(stream, 8); |
| } |
| |
| decode_vol: |
| PV_BitstreamFlushBits(stream, VOL_START_CODE_LENGTH - 8); |
| video->shortVideoHeader = 0; |
| |
| /* vol_id (4 bits) */ |
| currVol->volID = (int) BitstreamReadBits16(stream, 4); |
| |
| /* RandomAccessible flag */ |
| tmpvar = (uint32) BitstreamRead1Bits(stream); |
| |
| /* object type */ |
| tmpvar = (uint32) BitstreamReadBits16(stream, 8); /* */ |
| |
| #ifdef PV_TOLERATE_VOL_ERRORS |
| if (tmpvar == 0) |
| { |
| if (layer) /* */ |
| { |
| /* support SSPL0-2 */ |
| if (profile != 0x10 && profile != 0x11 && profile != 0x12) |
| return PV_FAIL; |
| tmpvar = 0x02; |
| } |
| else |
| { |
| /* support SPL0-3 & SSPL0-2 */ |
| if (profile != 0x01 && profile != 0x02 && profile != 0x03 && profile != 0x08 && |
| profile != 0x10 && profile != 0x11 && profile != 0x12) |
| return PV_FAIL; |
| tmpvar = 0x01; |
| } |
| profile |= 0x0100; |
| } |
| #endif |
| |
| if (layer) |
| { |
| if (tmpvar != 0x02) return PV_FAIL; |
| } |
| else |
| { |
| if (tmpvar != 0x01) return PV_FAIL; |
| } |
| |
| /* version id specified? */ |
| tmpvar = (uint32) BitstreamRead1Bits(stream); |
| if (tmpvar == 1) |
| { |
| /* version ID */ |
| version_id = (uint32) BitstreamReadBits16(stream, 4); |
| /* priority */ |
| tmpvar = (uint32) BitstreamReadBits16(stream, 3); |
| |
| } |
| |
| /* aspect ratio info */ |
| tmpvar = (uint32) BitstreamReadBits16(stream, 4); |
| if (tmpvar == 0) return PV_FAIL; |
| if (tmpvar == 0xf /* extended_par */) |
| { |
| /* width */ |
| tmpvar = (uint32) BitstreamReadBits16(stream, 8); |
| /* height */ |
| tmpvar = (uint32) BitstreamReadBits16(stream, 8); |
| } |
| |
| |
| /* control parameters present? */ |
| tmpvar = (uint32) BitstreamRead1Bits(stream); |
| |
| /* Get the parameters (skipped) */ |
| /* 03/10/99 */ |
| if (tmpvar) |
| { |
| /* chroma_format */ |
| tmpvar = BitstreamReadBits16(stream, 2); |
| if (tmpvar != 1) return PV_FAIL; |
| /* low_delay */ |
| tmpvar = BitstreamRead1Bits(stream); |
| |
| /* vbv_parameters present? */ |
| tmpvar = (uint32) BitstreamRead1Bits(stream); |
| if (tmpvar) |
| { |
| /* first_half_bit_rate */ |
| BitstreamReadBits16(stream, 15); |
| if (!BitstreamRead1Bits(stream)) return PV_FAIL; |
| /* latter_half_bit_rate */ |
| BitstreamReadBits16(stream, 15); |
| if (!BitstreamRead1Bits(stream)) return PV_FAIL; |
| /* first_half_vbv_buffer_size */ |
| BitstreamReadBits16(stream, 15); |
| if (!BitstreamRead1Bits(stream)) return PV_FAIL; |
| /* latter_half_vbv_buffer_size */ |
| BitstreamReadBits16(stream, 3); |
| /* first_half_vbv_occupancy */ |
| BitstreamReadBits16(stream, 11); |
| if (!BitstreamRead1Bits(stream)) return PV_FAIL; |
| /* latter_half_vbv_occupancy */ |
| BitstreamReadBits16(stream, 15); |
| if (!BitstreamRead1Bits(stream)) return PV_FAIL; |
| } |
| } |
| |
| /* video_object_layer_shape (2 bits), only 00 (rect) is supported for now */ |
| vol_shape = (uint32) BitstreamReadBits16(stream, 2); |
| if (vol_shape) return PV_FAIL; |
| |
| /* marker bit, 03/10/99 */ |
| if (!BitstreamRead1Bits(stream)) return PV_FAIL; |
| |
| /* vop_time_increment_resolution */ |
| currVol->timeIncrementResolution = BitstreamReadBits16(stream, 16); |
| if (currVol->timeIncrementResolution == 0) return PV_FAIL; |
| |
| /* . since nbitsTimeIncRes will be used over and over again, */ |
| /* we should put it in Vol structure. 04/12/2000. */ |
| currVol->nbitsTimeIncRes = CalcNumBits((uint)currVol->timeIncrementResolution - 1); |
| |
| if (!BitstreamRead1Bits(stream)) return PV_FAIL; |
| |
| /* fixed_vop_rate */ |
| currVol->fixedVopRate = (int) BitstreamRead1Bits(stream); |
| if (currVol->fixedVopRate) |
| { |
| /* fixed_vop_time_increment */ |
| tmpvar = BitstreamReadBits16(stream, currVol->nbitsTimeIncRes); |
| } |
| |
| /* marker bit */ |
| if (!BitstreamRead1Bits(stream)) return PV_FAIL; |
| |
| /* video_object_layer_width (13 bits) */ |
| video->displayWidth = video->width = (int) BitstreamReadBits16(stream, 13); |
| |
| /* round up to a multiple of MB_SIZE. 08/09/2000 */ |
| video->width = (video->width + 15) & -16; |
| // video->displayWidth += (video->displayWidth & 0x1); /* displayed image should be even size */ |
| |
| /* marker bit */ |
| if (!BitstreamRead1Bits(stream)) return PV_FAIL; |
| |
| /* video_object_layer_height (13 bits) */ |
| video->displayHeight = video->height = (int) BitstreamReadBits16(stream, 13); |
| |
| /* round up to a multiple of MB_SIZE. 08/09/2000 */ |
| video->height = (video->height + 15) & -16; |
| // video->displayHeight += (video->displayHeight & 0x1); /* displayed image should be even size */ |
| if (!BitstreamRead1Bits(stream)) return PV_FAIL; |
| |
| /* 03/10/99 */ |
| /* interlaced */ |
| tmpvar = (uint32) BitstreamRead1Bits(stream); |
| if (tmpvar != 0) |
| { |
| mp4dec_log("DecodeVOLHeader(): Interlaced video is not supported.\n"); |
| return PV_FAIL; |
| } |
| |
| /* obmc_disable */ |
| tmpvar = (uint32) BitstreamRead1Bits(stream); |
| if (tmpvar == 0) return PV_FAIL; |
| |
| if (version_id == 1) |
| { |
| /* sprite_enable (1 bits) */ |
| tmpvar = (uint32) BitstreamRead1Bits(stream); |
| if (tmpvar) |
| { |
| mp4dec_log("DecodeVOLHeader(): Sprite is not supported.\n"); |
| return PV_FAIL; |
| } |
| } |
| else |
| { |
| /* For version 2, vol_sprite_usage has two bits. */ |
| /* sprite_enable */ |
| tmpvar = (uint32) BitstreamReadBits16(stream, 2); |
| if (tmpvar) |
| { |
| mp4dec_log("DecodeVOLHeader(): Sprite is not supported.\n"); |
| return PV_FAIL; |
| } |
| } |
| |
| /* not_8_bit */ |
| if (BitstreamRead1Bits(stream)) |
| { |
| /* quant_precision */ |
| currVol->quantPrecision = BitstreamReadBits16(stream, 4); |
| /* bits_per_pixel */ |
| currVol->bitsPerPixel = BitstreamReadBits16(stream, 4); |
| mp4dec_log("DecodeVOLHeader(): not an 8-bit stream.\n"); // For the time being we do not support != 8 bits |
| |
| return PV_FAIL; |
| } |
| else |
| { |
| currVol->quantPrecision = 5; |
| currVol->bitsPerPixel = 8; |
| } |
| |
| /* quant_type (1 bit) */ |
| currVol->quantType = BitstreamRead1Bits(stream); |
| if (currVol->quantType) |
| { |
| #ifdef PV_SUPPORT_MAIN_PROFILE |
| /* load quantization matrices. 5/22/2000 */ |
| /* load_intra_quant_mat (1 bit) */ |
| qmat = currVol->iqmat; |
| currVol->loadIntraQuantMat = BitstreamRead1Bits(stream); |
| if (currVol->loadIntraQuantMat) |
| { |
| /* intra_quant_mat (8*64 bits) */ |
| i = 0; |
| do |
| { |
| qmat[*(zigzag_inv+i)] = (int) BitstreamReadBits16(stream, 8); |
| } |
| while ((qmat[*(zigzag_inv+i)] != 0) && (++i < 64)); |
| |
| for (j = i; j < 64; j++) |
| qmat[*(zigzag_inv+j)] = qmat[*(zigzag_inv+i-1)]; |
| } |
| else |
| { |
| oscl_memcpy(qmat, mpeg_iqmat_def, 64*sizeof(int)); |
| } |
| |
| qmat[0] = 0; /* necessary for switched && MPEG quant 07/09/01 */ |
| |
| /* load_nonintra_quant_mat (1 bit) */ |
| qmat = currVol->niqmat; |
| currVol->loadNonIntraQuantMat = BitstreamRead1Bits(stream); |
| if (currVol->loadNonIntraQuantMat) |
| { |
| /* nonintra_quant_mat (8*64 bits) */ |
| i = 0; |
| do |
| { |
| qmat[*(zigzag_inv+i)] = (int) BitstreamReadBits16(stream, 8); |
| } |
| while ((qmat[*(zigzag_inv+i)] != 0) && (++i < 64)); |
| |
| for (j = i; j < 64; j++) |
| qmat[*(zigzag_inv+j)] = qmat[*(zigzag_inv+i-1)]; |
| } |
| else |
| { |
| oscl_memcpy(qmat, mpeg_nqmat_def, 64*sizeof(int)); |
| } |
| #else |
| return PV_FAIL; |
| #endif |
| } |
| |
| if (version_id != 1) |
| { |
| /* quarter_sample enabled */ |
| tmpvar = BitstreamRead1Bits(stream); |
| if (tmpvar) return PV_FAIL; |
| } |
| |
| /* complexity_estimation_disable */ |
| currVol->complexity_estDisable = BitstreamRead1Bits(stream); |
| if (currVol->complexity_estDisable == 0) |
| { |
| currVol->complexity_estMethod = BitstreamReadBits16(stream, 2); |
| |
| if (currVol->complexity_estMethod < 2) |
| { |
| /* shape_complexity_estimation_disable */ |
| tmpvar = BitstreamRead1Bits(stream); |
| if (tmpvar == 0) |
| { |
| mp4dec_log("DecodeVOLHeader(): Shape Complexity estimation is not supported.\n"); |
| return PV_FAIL; |
| } |
| /* texture_complexity_estimation_set_1_disable */ |
| tmpvar = BitstreamRead1Bits(stream); |
| if (tmpvar == 0) |
| { |
| currVol->complexity.text_1 = BitstreamReadBits16(stream, 4); |
| } |
| /* marker bit */ |
| if (!BitstreamRead1Bits(stream)) return PV_FAIL; |
| /* texture_complexity_estimation_set_2_disable */ |
| tmpvar = BitstreamRead1Bits(stream); |
| if (tmpvar == 0) |
| { |
| currVol->complexity.text_2 = BitstreamReadBits16(stream, 4); |
| } |
| /* motion_compensation_complexity_disable */ |
| tmpvar = BitstreamRead1Bits(stream); |
| if (tmpvar == 0) |
| { |
| currVol->complexity.mc = BitstreamReadBits16(stream, 6); |
| } |
| /* marker bit */ |
| if (!BitstreamRead1Bits(stream)) return PV_FAIL; |
| |
| if (currVol->complexity_estMethod == 1) |
| { /* version2_complexity_estimation_disable */ |
| tmpvar = BitstreamRead1Bits(stream); |
| if (tmpvar == 0) |
| { |
| mp4dec_log("DecodeVOLHeader(): sadct, quarter pel not supported.\n"); |
| return PV_FAIL; |
| } |
| } |
| } |
| } |
| |
| /* 03/10/99 */ |
| /* resync_marker_disable */ |
| currVol->errorResDisable = (int) BitstreamRead1Bits(stream); |
| /* data_partititioned */ |
| currVol->dataPartitioning = (int) BitstreamRead1Bits(stream); |
| |
| video->vlcDecCoeffIntra = &VlcDecTCOEFIntra; |
| video->vlcDecCoeffInter = &VlcDecTCOEFInter; |
| |
| if (currVol->dataPartitioning) |
| { |
| if (layer) return PV_FAIL; /* */ |
| /* reversible_vlc */ |
| currVol->useReverseVLC = (int)BitstreamRead1Bits(stream); |
| if (currVol->useReverseVLC) |
| { |
| video->vlcDecCoeffIntra = &RvlcDecTCOEFIntra; |
| video->vlcDecCoeffInter = &RvlcDecTCOEFInter; |
| } |
| currVol->errorResDisable = 0; |
| } |
| else |
| { |
| currVol->useReverseVLC = 0; |
| } |
| |
| if (version_id != 1) |
| { |
| /* newpred_enable */ |
| tmpvar = BitstreamRead1Bits(stream); |
| if (tmpvar) return PV_FAIL; |
| |
| /* reduced_resolution_vop */ |
| tmpvar = BitstreamRead1Bits(stream); |
| if (tmpvar) return PV_FAIL; |
| |
| } |
| |
| /* Intra AC/DC prediction is always true */ |
| video->intra_acdcPredDisable = 0; |
| /* scalability */ |
| currVol->scalability = (int) BitstreamRead1Bits(stream); |
| |
| if (currVol->scalability) |
| { |
| if (layer == 0) return PV_FAIL; /* */ |
| /* hierarchy_type: 1 : temporal, 0 : spatial */ |
| /* 03/10/99 */ |
| currVol->scalType = (int) BitstreamRead1Bits(stream); /* */ |
| if (!currVol->scalType) return PV_FAIL; |
| |
| /* ref_layer_id (4 bits) */ |
| currVol->refVolID = (int) BitstreamReadBits16(stream, 4); |
| if (layer) /* */ |
| { |
| if (currVol->refVolID != video->vol[0]->volID) return PV_FAIL; |
| } |
| /* ref_layer_sampling_direc (1 bits) */ |
| /* 1 : ref. layer has higher resolution */ |
| /* 0 : ref. layer has equal or lower resolution */ |
| currVol->refSampDir = (int) BitstreamRead1Bits(stream); |
| if (currVol->refSampDir) return PV_FAIL; |
| |
| /* hor_sampling_factor_n (5 bits) */ |
| currVol->horSamp_n = (int) BitstreamReadBits16(stream, 5); |
| |
| /* hor_sampling_factor_m (5 bits) */ |
| currVol->horSamp_m = (int) BitstreamReadBits16(stream, 5); |
| |
| if (currVol->horSamp_m == 0) return PV_FAIL; |
| if (currVol->horSamp_n != currVol->horSamp_m) return PV_FAIL; |
| |
| /* ver_sampling_factor_n (5 bits) */ |
| currVol->verSamp_n = (int) BitstreamReadBits16(stream, 5); |
| |
| /* ver_sampling_factor_m (5 bits) */ |
| currVol->verSamp_m = (int) BitstreamReadBits16(stream, 5); |
| |
| if (currVol->verSamp_m == 0) return PV_FAIL; |
| if (currVol->verSamp_n != currVol->verSamp_m) return PV_FAIL; |
| |
| |
| /* enhancement_type: 1 : partial region, 0 : full region */ |
| /* 04/10/2000: we only support full region enhancement layer. */ |
| if (BitstreamRead1Bits(stream)) return PV_FAIL; |
| } |
| |
| PV_BitstreamByteAlign(stream); |
| |
| status = BitstreamShowBits32HC(stream, &tmpvar); |
| |
| /* if we hit the end of buffer, tmpvar == 0. 08/30/2000 */ |
| if (tmpvar == USER_DATA_START_CODE) |
| { |
| status = DecodeUserData(stream); |
| /* you should not check for status here 03/19/2002 */ |
| status = PV_SUCCESS; |
| } |
| |
| /* Compute some convenience variables: 04/13/2000 */ |
| video->nMBPerRow = video->width / MB_SIZE; |
| video->nMBPerCol = video->height / MB_SIZE; |
| video->nTotalMB = video->nMBPerRow * video->nMBPerCol; |
| video->nBitsForMBID = CalcNumBits((uint)video->nTotalMB - 1); |
| #ifdef PV_ANNEX_IJKT_SUPPORT |
| video->modified_quant = 0; |
| video->advanced_INTRA = 0; |
| video->deblocking = 0; |
| video->slice_structure = 0; |
| #endif |
| } |
| else |
| { |
| /* SHORT_HEADER */ |
| status = BitstreamShowBits32(stream, SHORT_VIDEO_START_MARKER_LENGTH, &tmpvar); |
| |
| if (tmpvar == SHORT_VIDEO_START_MARKER) |
| { |
| video->shortVideoHeader = TRUE; |
| } |
| else |
| { |
| do |
| { |
| /* Search for VOL_HEADER */ |
| status = PVSearchNextM4VFrame(stream); /* search 0x00 0x00 0x01 */ |
| if (status != PV_SUCCESS) return PV_FAIL; /* breaks the loop */ |
| BitstreamShowBits32(stream, VOL_START_CODE_LENGTH, &tmpvar); |
| PV_BitstreamFlushBits(stream, 8); |
| } |
| while (tmpvar != VOL_START_CODE); |
| goto decode_vol; |
| } |
| } |
| #ifdef PV_TOLERATE_VOL_ERRORS |
| if (profile > 0xFF || profile == 0) |
| { |
| return PV_BAD_VOLHEADER; |
| } |
| #endif |
| |
| return status; |
| } |
| |
| |
| /***********************************************************CommentBegin****** |
| * |
| * -- DecodeGOV -- Decodes the Group of VOPs from bitstream |
| * |
| * 04/20/2000 initial modification to the new PV-Decoder Lib format. |
| * |
| ***********************************************************CommentEnd********/ |
| PV_STATUS DecodeGOVHeader(BitstreamDecVideo *stream, uint32 *time_base) |
| { |
| uint32 tmpvar, time_s; |
| int closed_gov, broken_link; |
| |
| /* group_start_code (32 bits) */ |
| // tmpvar = BitstreamReadBits32(stream, 32); |
| |
| /* hours */ |
| tmpvar = (uint32) BitstreamReadBits16(stream, 5); |
| time_s = tmpvar * 3600; |
| |
| /* minutes */ |
| tmpvar = (uint32) BitstreamReadBits16(stream, 6); |
| time_s += tmpvar * 60; |
| |
| /* marker bit */ |
| tmpvar = (uint32) BitstreamRead1Bits(stream); |
| |
| /* seconds */ |
| tmpvar = (uint32) BitstreamReadBits16(stream, 6); |
| time_s += tmpvar; |
| |
| /* We have to check the timestamp here. If the sync timestamp is */ |
| /* earlier than the previous timestamp or longer than 60 sec. */ |
| /* after the previous timestamp, assume the GOV header is */ |
| /* corrupted. 05/12/2000 */ |
| *time_base = time_s; /* 02/27/2002 */ |
| // *time_base = *time_base/1000; |
| // tmpvar = time_s - *time_base; |
| // if (tmpvar <= 60) *time_base = time_s; |
| // else return PV_FAIL; |
| |
| tmpvar = (uint32) BitstreamRead1Bits(stream); |
| closed_gov = tmpvar; |
| tmpvar = (uint32) BitstreamRead1Bits(stream); |
| broken_link = tmpvar; |
| |
| if ((closed_gov == 0) && (broken_link == 1)) |
| { |
| return PV_SUCCESS; /* 03/15/2002 you can also return PV_FAIL */ |
| } |
| |
| PV_BitstreamByteAlign(stream); |
| |
| BitstreamShowBits32HC(stream, &tmpvar); |
| |
| while (tmpvar == USER_DATA_START_CODE) /* 03/15/2002 */ |
| { |
| DecodeUserData(stream); |
| BitstreamShowBits32HC(stream, &tmpvar); |
| } |
| |
| return PV_SUCCESS; |
| } |
| |
| /***********************************************************CommentBegin****** |
| * |
| * -- DecodeVopHeader -- Decodes the VOPheader information from the bitstream |
| * |
| * 04/12/2000 Initial port to the new PV decoder library format. |
| * 05/10/2000 Error resilient decoding of vop header. |
| * |
| ***********************************************************CommentEnd********/ |
| PV_STATUS DecodeVOPHeader(VideoDecData *video, Vop *currVop, Bool use_ext_timestamp) |
| { |
| PV_STATUS status = PV_SUCCESS; |
| Vol *currVol = video->vol[video->currLayer]; |
| BitstreamDecVideo *stream = currVol->bitstream; |
| uint32 tmpvar; |
| int time_base; |
| |
| /***** |
| * Read the VOP header from the bitstream (No shortVideoHeader Mode here!) |
| *****/ |
| BitstreamShowBits32HC(stream, &tmpvar); |
| |
| /* check if we have a GOV header here. 08/30/2000 */ |
| if (tmpvar == GROUP_START_CODE) |
| { |
| tmpvar = BitstreamReadBits32HC(stream); |
| // rewindBitstream(stream, START_CODE_LENGTH); /* for backward compatibility */ |
| status = DecodeGOVHeader(stream, &tmpvar); |
| if (status != PV_SUCCESS) |
| { |
| return status; |
| } |
| // use_ext_timestamp = TRUE; /* 02/08/2002 */ |
| /* We should have a VOP header following the GOV header. 03/15/2001 */ |
| BitstreamShowBits32HC(stream, &tmpvar); |
| } |
| #ifdef PV_SUPPORT_TEMPORAL_SCALABILITY |
| currVop->timeStamp = -1; |
| #endif |
| if (tmpvar == VOP_START_CODE) |
| { |
| tmpvar = BitstreamReadBits32HC(stream); |
| } |
| else |
| { |
| PV_BitstreamFlushBits(stream, 8); // advance by a byte |
| status = PV_FAIL; |
| goto return_point; |
| } |
| |
| |
| |
| /* vop_prediction_type (2 bits) */ |
| currVop->predictionType = (int) BitstreamReadBits16(stream, 2); |
| |
| /* modulo_time_base (? bits) */ |
| time_base = -1; |
| do |
| { |
| time_base++; |
| tmpvar = (uint32) BitstreamRead1Bits(stream); |
| } |
| while (tmpvar == 1); |
| |
| |
| |
| if (!use_ext_timestamp) |
| { |
| currVol->moduloTimeBase += 1000 * time_base; /* milliseconds based MTB 11/12/01 */ |
| } |
| |
| /* marker_bit (1 bit) */ |
| if (!BitstreamRead1Bits(stream)) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| |
| /* vop_time_increment (1-15 bits) in Nov_Compliant (1-16 bits) */ |
| /* we always assumes fixed vop rate here */ |
| currVop->timeInc = BitstreamReadBits16(stream, currVol->nbitsTimeIncRes); |
| |
| |
| /* marker_bit (1 bit) */ |
| if (!BitstreamRead1Bits(stream)) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| |
| /* vop_coded */ |
| currVop->vopCoded = (int) BitstreamRead1Bits(stream); |
| |
| |
| if (currVop->vopCoded == 0) |
| { |
| status = PV_SUCCESS; |
| goto return_point; |
| } |
| |
| |
| /* read vop_rounding_type */ |
| if (currVop->predictionType == P_VOP) |
| { |
| currVop->roundingType = (int) BitstreamRead1Bits(stream); |
| } |
| else |
| { |
| currVop->roundingType = 0; |
| } |
| |
| if (currVol->complexity_estDisable == 0) |
| { |
| if (currVol->complexity_estMethod < 2) /* OCT 2002 */ |
| { |
| if ((currVol->complexity.text_1 >> 3) & 0x1) /* intra */ |
| BitstreamReadBits16(stream, 8); |
| if (currVol->complexity.text_1 & 0x1) /* not_coded */ |
| BitstreamReadBits16(stream, 8); |
| if ((currVol->complexity.text_2 >> 3) & 0x1) /* dct_coefs */ |
| BitstreamReadBits16(stream, 8); |
| if ((currVol->complexity.text_2 >> 2) & 0x1) /* dct_lines */ |
| BitstreamReadBits16(stream, 8); |
| if ((currVol->complexity.text_2 >> 1) & 0x1) /* vlc_symbols */ |
| BitstreamReadBits16(stream, 8); |
| if (currVol->complexity.text_2 & 0x1) /* vlc_bits */ |
| BitstreamReadBits16(stream, 4); |
| |
| if (currVop->predictionType != I_VOP) |
| { |
| if ((currVol->complexity.text_1 >> 2) & 0x1) /* inter */ |
| BitstreamReadBits16(stream, 8); |
| if ((currVol->complexity.text_1 >> 1) & 0x1) /* inter_4v */ |
| BitstreamReadBits16(stream, 8); |
| if ((currVol->complexity.mc >> 5) & 0x1) /* apm */ |
| BitstreamReadBits16(stream, 8); |
| if ((currVol->complexity.mc >> 4) & 0x1) /* npm */ |
| BitstreamReadBits16(stream, 8); |
| /* interpolate_mc_q */ |
| if ((currVol->complexity.mc >> 2) & 0x1) /* forw_back_mc_q */ |
| BitstreamReadBits16(stream, 8); |
| if ((currVol->complexity.mc >> 1) & 0x1) /* halfpel2 */ |
| BitstreamReadBits16(stream, 8); |
| if (currVol->complexity.mc & 0x1) /* halfpel4 */ |
| BitstreamReadBits16(stream, 8); |
| } |
| if (currVop->predictionType == B_VOP) |
| { |
| if ((currVol->complexity.mc >> 3) & 0x1) /* interpolate_mc_q */ |
| BitstreamReadBits16(stream, 8); |
| } |
| } |
| } |
| |
| /* read intra_dc_vlc_thr */ |
| currVop->intraDCVlcThr = (int) BitstreamReadBits16(stream, 3); |
| |
| /* read vop_quant (currVol->quantPrecision bits) */ |
| currVop->quantizer = (int16) BitstreamReadBits16(stream, currVol->quantPrecision); |
| if (currVop->quantizer == 0) |
| { |
| currVop->quantizer = video->prevVop->quantizer; |
| status = PV_FAIL; |
| goto return_point; |
| } |
| |
| |
| /* read vop_fcode_forward */ |
| if (currVop->predictionType != I_VOP) |
| { |
| tmpvar = (uint32) BitstreamReadBits16(stream, 3); |
| if (tmpvar < 1) |
| { |
| currVop->fcodeForward = 1; |
| status = PV_FAIL; |
| goto return_point; |
| } |
| currVop->fcodeForward = tmpvar; |
| } |
| else |
| { |
| currVop->fcodeForward = 0; |
| } |
| |
| /* read vop_fcode_backward */ |
| if (currVop->predictionType == B_VOP) |
| { |
| tmpvar = (uint32) BitstreamReadBits16(stream, 3); |
| if (tmpvar < 1) |
| { |
| currVop->fcodeBackward = 1; |
| status = PV_FAIL; |
| goto return_point; |
| } |
| currVop->fcodeBackward = tmpvar; |
| } |
| else |
| { |
| currVop->fcodeBackward = 0; |
| } |
| |
| if (currVol->scalability) |
| { |
| currVop->refSelectCode = (int) BitstreamReadBits16(stream, 2); |
| } |
| |
| return_point: |
| return status; |
| } |
| |
| |
| /***********************************************************CommentBegin****** |
| * |
| * -- VideoPlaneWithShortHeader -- Decodes the short_video_header information from the bitstream |
| * Modified : |
| 04/23/2001. Remove the codes related to the |
| "first pass" decoding. We use a different function |
| to set up the decoder now. |
| ***********************************************************CommentEnd********/ |
| PV_STATUS DecodeShortHeader(VideoDecData *video, Vop *currVop) |
| { |
| PV_STATUS status = PV_SUCCESS; |
| Vol *currVol = video->vol[0]; |
| BitstreamDecVideo *stream = currVol->bitstream; |
| uint32 tmpvar; |
| int32 size; |
| |
| int extended_PTYPE = FALSE; |
| int UFEP = 0, custom_PFMT = 0, custom_PCF = 0; |
| |
| status = BitstreamShowBits32(stream, SHORT_VIDEO_START_MARKER_LENGTH, &tmpvar); |
| |
| if (tmpvar != SHORT_VIDEO_START_MARKER) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| |
| |
| PV_BitstreamFlushBits(stream, SHORT_VIDEO_START_MARKER_LENGTH); |
| |
| /* Temporal reference. Using vop_time_increment_resolution = 30000 */ |
| tmpvar = (uint32) BitstreamReadBits16(stream, 8); |
| currVop->temporalRef = (int) tmpvar; |
| |
| |
| currVop->timeInc = 0xff & (256 + currVop->temporalRef - video->prevVop->temporalRef); |
| currVol->moduloTimeBase += currVop->timeInc; /* mseconds 11/12/01 */ |
| /* Marker Bit */ |
| if (!BitstreamRead1Bits(stream)) |
| { |
| mp4dec_log("DecodeShortHeader(): Marker bit wrong.\n"); |
| status = PV_FAIL; |
| goto return_point; |
| } |
| |
| /* Zero Bit */ |
| if (BitstreamRead1Bits(stream)) |
| { |
| mp4dec_log("DecodeShortHeader(): Zero bit wrong.\n"); |
| status = PV_FAIL; |
| goto return_point; |
| } |
| |
| /*split_screen_indicator*/ |
| if (BitstreamRead1Bits(stream)) |
| { |
| mp4dec_log("DecodeShortHeader(): Split Screen not supported.\n"); |
| VideoDecoderErrorDetected(video); |
| } |
| |
| /*document_freeze_camera*/ |
| if (BitstreamRead1Bits(stream)) |
| { |
| mp4dec_log("DecodeShortHeader(): Freeze Camera not supported.\n"); |
| VideoDecoderErrorDetected(video); |
| } |
| |
| /*freeze_picture_release*/ |
| if (BitstreamRead1Bits(stream)) |
| { |
| mp4dec_log("DecodeShortHeader(): Freeze Release not supported.\n"); |
| VideoDecoderErrorDetected(video); |
| } |
| /* source format */ |
| switch (BitstreamReadBits16(stream, 3)) |
| { |
| case 1: |
| if (video->size < 128*96) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| video->displayWidth = video->width = 128; |
| video->displayHeight = video->height = 96; |
| break; |
| |
| case 2: |
| if (video->size < 176*144) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| video->displayWidth = video->width = 176; |
| video->displayHeight = video->height = 144; |
| break; |
| |
| case 3: |
| if (video->size < 352*288) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| video->displayWidth = video->width = 352; |
| video->displayHeight = video->height = 288; |
| break; |
| |
| case 4: |
| if (video->size < 704*576) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| video->displayWidth = video->width = 704; |
| video->displayHeight = video->height = 576; |
| break; |
| |
| case 5: |
| if (video->size < 1408*1152) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| video->displayWidth = video->width = 1408; |
| video->displayHeight = video->height = 1152; |
| break; |
| |
| case 7: |
| extended_PTYPE = TRUE; |
| break; |
| |
| default: |
| /* Msg("H.263 source format not legal\n"); */ |
| status = PV_FAIL; |
| goto return_point; |
| } |
| |
| |
| currVop->roundingType = 0; |
| |
| if (extended_PTYPE == FALSE) |
| { |
| currVop->predictionType = (int) BitstreamRead1Bits(stream); |
| |
| /* four_reserved_zero_bits */ |
| if (BitstreamReadBits16(stream, 4)) |
| { |
| mp4dec_log("DecodeShortHeader(): Reserved bits wrong.\n"); |
| status = PV_FAIL; |
| goto return_point; |
| } |
| } |
| else |
| { |
| UFEP = BitstreamReadBits16(stream, 3); |
| if (UFEP == 1) |
| { |
| /* source format */ |
| switch (BitstreamReadBits16(stream, 3)) |
| { |
| case 1: |
| if (video->size < 128*96) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| video->displayWidth = video->width = 128; |
| video->displayHeight = video->height = 96; |
| break; |
| |
| case 2: |
| if (video->size < 176*144) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| video->displayWidth = video->width = 176; |
| video->displayHeight = video->height = 144; |
| break; |
| |
| case 3: |
| if (video->size < 352*288) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| video->displayWidth = video->width = 352; |
| video->displayHeight = video->height = 288; |
| break; |
| |
| case 4: |
| if (video->size < 704*576) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| video->displayWidth = video->width = 704; |
| video->displayHeight = video->height = 576; |
| break; |
| |
| case 5: |
| if (video->size < 1408*1152) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| video->displayWidth = video->width = 1408; |
| video->displayHeight = video->height = 1152; |
| break; |
| |
| case 6: |
| custom_PFMT = TRUE; |
| break; |
| |
| default: |
| /* Msg("H.263 source format not legal\n"); */ |
| status = PV_FAIL; |
| goto return_point; |
| } |
| |
| custom_PCF = BitstreamRead1Bits(stream); |
| /* unrestricted MV */ |
| if (BitstreamRead1Bits(stream)) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| /* SAC */ |
| if (BitstreamRead1Bits(stream)) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| |
| /* AP */ |
| if (BitstreamRead1Bits(stream)) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| |
| video->advanced_INTRA = BitstreamRead1Bits(stream); |
| |
| video->deblocking = BitstreamRead1Bits(stream); |
| |
| video->slice_structure = BitstreamRead1Bits(stream); |
| |
| /* RPS, ISD, AIV */ |
| if (BitstreamReadBits16(stream, 3)) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| video->modified_quant = BitstreamRead1Bits(stream); |
| |
| /* Marker Bit and reserved*/ |
| if (BitstreamReadBits16(stream, 4) != 8) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| } |
| #ifndef PV_ANNEX_IJKT_SUPPORT |
| if (video->advanced_INTRA | video->deblocking | video->modified_quant | video->modified_quant) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| #endif |
| |
| if (UFEP == 0 || UFEP == 1) |
| { |
| tmpvar = BitstreamReadBits16(stream, 3); |
| if (tmpvar > 1) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| currVop->predictionType = tmpvar; |
| /* RPR */ |
| if (BitstreamRead1Bits(stream)) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| |
| /* RRU */ |
| if (BitstreamRead1Bits(stream)) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| currVop->roundingType = (int) BitstreamRead1Bits(stream); |
| if (BitstreamReadBits16(stream, 3) != 1) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| } |
| else |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| /* CPM */ |
| if (BitstreamRead1Bits(stream)) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| /* CPFMT */ |
| if (custom_PFMT == 1 && UFEP == 1) |
| { |
| /* aspect ratio */ |
| tmpvar = BitstreamReadBits16(stream, 4); |
| if (tmpvar == 0) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| /* Extended PAR */ |
| if (tmpvar == 0xF) |
| { |
| /* Read par_width and par_height but do nothing */ |
| /* par_width */ |
| tmpvar = BitstreamReadBits16(stream, 8); |
| |
| /* par_height */ |
| tmpvar = BitstreamReadBits16(stream, 8); |
| } |
| tmpvar = BitstreamReadBits16(stream, 9); |
| |
| int tmpDisplayWidth = (tmpvar + 1) << 2; |
| /* marker bit */ |
| if (!BitstreamRead1Bits(stream)) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| tmpvar = BitstreamReadBits16(stream, 9); |
| if (tmpvar == 0) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| int tmpDisplayHeight = tmpvar << 2; |
| int tmpHeight = (tmpDisplayHeight + 15) & -16; |
| int tmpWidth = (tmpDisplayWidth + 15) & -16; |
| |
| if (tmpWidth > video->width) |
| { |
| // while allowed by the spec, this decoder does not actually |
| // support an increase in size. |
| ALOGE("width increase not supported"); |
| status = PV_FAIL; |
| goto return_point; |
| } |
| if (tmpHeight * tmpWidth > video->size) |
| { |
| // This is just possibly "b/37079296". |
| ALOGE("b/37079296"); |
| status = PV_FAIL; |
| goto return_point; |
| } |
| video->displayWidth = tmpDisplayWidth; |
| video->width = tmpWidth; |
| video->displayHeight = tmpDisplayHeight; |
| video->height = tmpHeight; |
| |
| video->nTotalMB = video->width / MB_SIZE * video->height / MB_SIZE; |
| |
| if (video->nTotalMB <= 48) |
| { |
| video->nBitsForMBID = 6; |
| } |
| else if (video->nTotalMB <= 99) |
| { |
| video->nBitsForMBID = 7; |
| } |
| else if (video->nTotalMB <= 396) |
| { |
| video->nBitsForMBID = 9; |
| } |
| else if (video->nTotalMB <= 1584) |
| { |
| video->nBitsForMBID = 11; |
| } |
| else if (video->nTotalMB <= 6336) |
| { |
| video->nBitsForMBID = 13 ; |
| } |
| else if (video->nTotalMB <= 9216) |
| { |
| video->nBitsForMBID = 14 ; |
| } |
| else |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| } |
| if (UFEP == 1 && custom_PCF == 1) |
| { |
| BitstreamRead1Bits(stream); |
| |
| tmpvar = BitstreamReadBits16(stream, 7); |
| if (tmpvar == 0) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| } |
| |
| if (custom_PCF == 1) |
| { |
| currVop->ETR = BitstreamReadBits16(stream, 2); |
| } |
| |
| if (UFEP == 1 && video->slice_structure == 1) |
| { |
| /* SSS */ |
| tmpvar = BitstreamReadBits16(stream, 2); |
| if (tmpvar != 0) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| } |
| } |
| |
| /* Recalculate number of macroblocks per row & col since */ |
| /* the frame size can change. 04/23/2001. */ |
| video->nMBinGOB = video->nMBPerRow = video->width / MB_SIZE; |
| video->nGOBinVop = video->nMBPerCol = video->height / MB_SIZE; |
| video->nTotalMB = video->nMBPerRow * video->nMBPerCol; |
| if (custom_PFMT == 0 || UFEP == 0) |
| { |
| video->nBitsForMBID = CalcNumBits((uint)video->nTotalMB - 1); /* otherwise calculate above */ |
| } |
| size = (int32)video->width * video->height; |
| if (currVop->predictionType == P_VOP && size > video->videoDecControls->size) |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| video->videoDecControls->size = size; |
| video->currVop->uChan = video->currVop->yChan + size; |
| video->currVop->vChan = video->currVop->uChan + (size >> 2); |
| video->prevVop->uChan = video->prevVop->yChan + size; |
| video->prevVop->vChan = video->prevVop->uChan + (size >> 2); |
| |
| |
| currVop->quantizer = (int16) BitstreamReadBits16(stream, 5); |
| |
| if (currVop->quantizer == 0) /* 04/03/01 */ |
| { |
| currVop->quantizer = video->prevVop->quantizer; |
| status = PV_FAIL; |
| goto return_point; |
| } |
| |
| |
| /* Zero bit */ |
| if (extended_PTYPE == FALSE) |
| { |
| if (BitstreamRead1Bits(stream)) |
| { |
| mp4dec_log("DecodeShortHeader(): Zero bit wrong.\n"); |
| status = PV_FAIL; |
| goto return_point; |
| } |
| } |
| /* pei */ |
| tmpvar = (uint32) BitstreamRead1Bits(stream); |
| |
| while (tmpvar) |
| { |
| tmpvar = (uint32) BitstreamReadBits16(stream, 8); /* "PSPARE" */ |
| tmpvar = (uint32) BitstreamRead1Bits(stream); /* "PEI" */ |
| } |
| |
| if (video->slice_structure) /* ANNEX_K */ |
| { |
| if (!BitstreamRead1Bits(stream)) /* SEPB1 */ |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| |
| // if (currVol->nBitsForMBID // |
| if (BitstreamReadBits16(stream, video->nBitsForMBID)) |
| { |
| status = PV_FAIL; /* no ASO, RS support for Annex K */ |
| goto return_point; |
| } |
| |
| if (!BitstreamRead1Bits(stream)) /*SEPB3 */ |
| { |
| status = PV_FAIL; |
| goto return_point; |
| } |
| |
| } |
| /* Setting of other VOP-header parameters */ |
| currVop->gobNumber = 0; |
| currVop->vopCoded = 1; |
| |
| currVop->intraDCVlcThr = 0; |
| currVop->gobFrameID = 0; /* initial value, 05/22/00 */ |
| currVol->errorResDisable = 0; |
| /*PutVopInterlaced(0,curr_vop); no implemented yet */ |
| if (currVop->predictionType != I_VOP) |
| currVop->fcodeForward = 1; |
| else |
| currVop->fcodeForward = 0; |
| |
| return_point: |
| |
| return status; |
| } |
| /***********************************************************CommentBegin****** |
| * |
| * -- PV_DecodeVop -- Decodes the VOP information from the bitstream |
| * |
| * 04/12/2000 |
| * Initial port to the new PV decoder library format. |
| * This function is different from the one in MoMuSys MPEG-4 |
| * visual decoder. We handle combined mode with or withput |
| * error resilience and H.263 mode through the sam path now. |
| * |
| * 05/04/2000 |
| * Added temporal scalability to the decoder. |
| * |
| ***********************************************************CommentEnd********/ |
| PV_STATUS PV_DecodeVop(VideoDecData *video) |
| { |
| Vol *currVol = video->vol[video->currLayer]; |
| PV_STATUS status; |
| uint32 tmpvar; |
| |
| /***** |
| * Do scalable or non-scalable decoding of the current VOP |
| *****/ |
| |
| if (!currVol->scalability) |
| { |
| if (currVol->dataPartitioning) |
| { |
| /* Data partitioning mode comes here */ |
| status = DecodeFrameDataPartMode(video); |
| } |
| else |
| { |
| /* Combined mode with or without error resilience */ |
| /* and short video header comes here. */ |
| status = DecodeFrameCombinedMode(video); |
| } |
| } |
| else |
| { |
| #ifdef DO_NOT_FOLLOW_STANDARD |
| /* according to the standard, only combined mode is allowed */ |
| /* in the enhancement layer. 06/01/2000. */ |
| if (currVol->dataPartitioning) |
| { |
| /* Data partitioning mode comes here */ |
| status = DecodeFrameDataPartMode(video); |
| } |
| else |
| { |
| /* Combined mode with or without error resilience */ |
| /* and short video header comes here. */ |
| status = DecodeFrameCombinedMode(video); |
| } |
| #else |
| status = DecodeFrameCombinedMode(video); |
| #endif |
| } |
| |
| /* This part is for consuming Visual_object_sequence_end_code and EOS Code */ /* 10/15/01 */ |
| if (!video->shortVideoHeader) |
| { |
| /* at this point bitstream is expected to be byte aligned */ |
| BitstreamByteAlignNoForceStuffing(currVol->bitstream); |
| |
| status = BitstreamShowBits32HC(currVol->bitstream, &tmpvar); /* 07/07/01 */ |
| if (tmpvar == VISUAL_OBJECT_SEQUENCE_END_CODE)/* VOS_END_CODE */ |
| { |
| PV_BitstreamFlushBits(currVol->bitstream, 16); |
| PV_BitstreamFlushBits(currVol->bitstream, 16); |
| } |
| |
| } |
| else |
| { |
| #ifdef PV_ANNEX_IJKT_SUPPORT |
| if (video->deblocking) |
| { |
| H263_Deblock(video->currVop->yChan, video->width, video->height, video->QPMB, video->headerInfo.Mode, 0, 0); |
| H263_Deblock(video->currVop->uChan, video->width >> 1, video->height >> 1, video->QPMB, video->headerInfo.Mode, 1, video->modified_quant); |
| H263_Deblock(video->currVop->vChan, video->width >> 1, video->height >> 1, video->QPMB, video->headerInfo.Mode, 1, video->modified_quant); |
| } |
| #endif |
| /* Read EOS code for shortheader bitstreams */ |
| status = BitstreamShowBits32(currVol->bitstream, 22, &tmpvar); |
| if (tmpvar == SHORT_VIDEO_END_MARKER) |
| { |
| PV_BitstreamFlushBits(currVol->bitstream, 22); |
| } |
| else |
| { |
| status = PV_BitstreamShowBitsByteAlign(currVol->bitstream, 22, &tmpvar); |
| if (tmpvar == SHORT_VIDEO_END_MARKER) |
| { |
| PV_BitstreamByteAlign(currVol->bitstream); |
| PV_BitstreamFlushBits(currVol->bitstream, 22); |
| } |
| } |
| } |
| return status; |
| } |
| |
| |
| /***********************************************************CommentBegin****** |
| * |
| * -- CalcVopDisplayTime -- calculate absolute time when VOP is to be displayed |
| * |
| * 04/12/2000 Initial port to the new PV decoder library format. |
| * |
| ***********************************************************CommentEnd********/ |
| uint32 CalcVopDisplayTime(Vol *currVol, Vop *currVop, int shortVideoHeader) |
| { |
| uint32 display_time; |
| |
| |
| /***** |
| * Calculate the time when the VOP is to be displayed next |
| *****/ |
| |
| if (!shortVideoHeader) |
| { |
| display_time = (uint32)(currVol->moduloTimeBase + (((int32)currVop->timeInc - (int32)currVol->timeInc_offset) * 1000) / ((int32)currVol->timeIncrementResolution)); /* 11/12/2001 */ |
| if (currVop->timeStamp >= display_time) |
| { |
| display_time += 1000; /* this case is valid if GOVHeader timestamp is ignored */ |
| } |
| } |
| else |
| { |
| display_time = (uint32)(currVol->moduloTimeBase * 33 + (currVol->moduloTimeBase * 11) / 30); /* 11/12/2001 */ |
| } |
| |
| return(display_time); |
| } |
| |