summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/codecs/avc/dec/src/avcdec_api.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/codecs/avc/dec/src/avcdec_api.cpp')
-rw-r--r--media/libstagefright/codecs/avc/dec/src/avcdec_api.cpp1036
1 files changed, 1036 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/avc/dec/src/avcdec_api.cpp b/media/libstagefright/codecs/avc/dec/src/avcdec_api.cpp
new file mode 100644
index 0000000..0a75f17
--- /dev/null
+++ b/media/libstagefright/codecs/avc/dec/src/avcdec_api.cpp
@@ -0,0 +1,1036 @@
+/* ------------------------------------------------------------------
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/**
+This file contains application function interfaces to the AVC decoder library.
+@publishedAll
+*/
+
+#include <string.h>
+
+#include "avcdec_api.h"
+#include "avcdec_lib.h"
+#include "avcdec_bitstream.h"
+
+/* ======================================================================== */
+/* Function : EBSPtoRBSP() */
+/* Date : 11/4/2003 */
+/* Purpose : Convert EBSP to RBSP and overwrite it. */
+/* Assuming that forbidden_zero, nal_ref_idc and nal_unit_type */
+/* (first byte), has been taken out of the nal_unit. */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+/**
+@pseudocode "
+ NumBytesInRBSP = 0;
+ for(i=0:i< *size; i++){
+ if(i+2 < *size && next_bits(24)==0x000003){
+ rbsp_byte[NumBytesInRBSP++];
+ rbsp_byte[NumBytesInRBSP++];
+ i+=2;
+ emulation_prevention_three_byte (0x03)
+ }
+ else
+ rbsp_byte[NumBytesInRBSP++];
+ }"
+*/
+AVCDec_Status EBSPtoRBSP(uint8 *nal_unit, int *size)
+{
+ int i, j;
+ int count = 0;
+
+ /* This code is based on EBSPtoRBSP of JM */
+ j = 0;
+
+ for (i = 0; i < *size; i++)
+ {
+ if (count == 2 && nal_unit[i] == 0x03)
+ {
+ i++;
+ count = 0;
+ }
+ nal_unit[j] = nal_unit[i];
+ if (nal_unit[i] == 0x00)
+ count++;
+ else
+ count = 0;
+ j++;
+ }
+
+ *size = j;
+
+ return AVCDEC_SUCCESS;
+}
+
+/* ======================================================================== */
+/* Function : PVAVCAnnexBGetNALUnit() */
+/* Date : 11/3/2003 */
+/* Purpose : Parse a NAL from byte stream format. */
+/* In/out : */
+/* Return : AVCDEC_SUCCESS if succeed, AVC_FAIL if fail. */
+/* Modified : */
+/* ======================================================================== */
+/**
+@pseudocode "
+ byte_stream_nal_unit(NumBytesInNalunit){
+ while(next_bits(24) != 0x000001)
+ zero_byte
+ if(more_data_in_byte_stream()){
+ start_code_prefix_one_3bytes // equal 0x000001
+ nal_unit(NumBytesInNALunit)
+ }
+ }"
+*/
+OSCL_EXPORT_REF AVCDec_Status PVAVCAnnexBGetNALUnit(uint8 *bitstream, uint8 **nal_unit,
+ int *size)
+{
+ int i, j, FoundStartCode = 0;
+ int end;
+
+ i = 0;
+ while (bitstream[i] == 0 && i < *size)
+ {
+ i++;
+ }
+ if (i >= *size)
+ {
+ *nal_unit = bitstream;
+ return AVCDEC_FAIL; /* cannot find any start_code_prefix. */
+ }
+ else if (bitstream[i] != 0x1)
+ {
+ i = -1; /* start_code_prefix is not at the beginning, continue */
+ }
+
+ i++;
+ *nal_unit = bitstream + i; /* point to the beginning of the NAL unit */
+
+ j = end = i;
+ while (!FoundStartCode)
+ {
+ while ((j + 1 < *size) && (bitstream[j] != 0 || bitstream[j+1] != 0)) /* see 2 consecutive zero bytes */
+ {
+ j++;
+ }
+ end = j; /* stop and check for start code */
+ while (j + 2 < *size && bitstream[j+2] == 0) /* keep reading for zero byte */
+ {
+ j++;
+ }
+ if (j + 2 >= *size)
+ {
+ *size -= i;
+ return AVCDEC_NO_NEXT_SC; /* cannot find the second start_code_prefix */
+ }
+ if (bitstream[j+2] == 0x1)
+ {
+ FoundStartCode = 1;
+ }
+ else
+ {
+ /* could be emulation code 0x3 */
+ j += 2; /* continue the search */
+ }
+ }
+
+ *size = end - i;
+
+ return AVCDEC_SUCCESS;
+}
+
+/* ======================================================================== */
+/* Function : PVAVCGetNALType() */
+/* Date : 11/4/2003 */
+/* Purpose : Sniff NAL type from the bitstream */
+/* In/out : */
+/* Return : AVCDEC_SUCCESS if succeed, AVC_FAIL if fail. */
+/* Modified : */
+/* ======================================================================== */
+OSCL_EXPORT_REF AVCDec_Status PVAVCDecGetNALType(uint8 *bitstream, int size,
+ int *nal_type, int *nal_ref_idc)
+{
+ int forbidden_zero_bit;
+ if (size > 0)
+ {
+ forbidden_zero_bit = bitstream[0] >> 7;
+ if (forbidden_zero_bit != 0)
+ return AVCDEC_FAIL;
+ *nal_ref_idc = (bitstream[0] & 0x60) >> 5;
+ *nal_type = bitstream[0] & 0x1F;
+ return AVCDEC_SUCCESS;
+ }
+
+ return AVCDEC_FAIL;
+}
+
+/* ======================================================================== */
+/* Function : PVAVCDecSeqParamSet() */
+/* Date : 11/4/2003 */
+/* Purpose : Initialize sequence, memory allocation if necessary. */
+/* In/out : */
+/* Return : AVCDEC_SUCCESS if succeed, AVC_FAIL if fail. */
+/* Modified : */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF AVCDec_Status PVAVCDecSeqParamSet(AVCHandle *avcHandle, uint8 *nal_unit,
+ int nal_size)
+{
+ AVCDec_Status status;
+ AVCDecObject *decvid;
+ AVCCommonObj *video;
+ AVCDecBitstream *bitstream;
+ void *userData = avcHandle->userData;
+ bool first_seq = FALSE;
+ int i;
+
+
+ DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "PVAVCDecSeqParamSet", -1, -1);
+
+ if (avcHandle->AVCObject == NULL)
+ {
+ first_seq = TRUE;
+
+ //avcHandle->memory_usage = 0;
+ /* allocate AVCDecObject */
+ avcHandle->AVCObject = (void*)avcHandle->CBAVC_Malloc(userData, sizeof(AVCDecObject), 0/*DEFAULT_ATTR*/);
+ if (avcHandle->AVCObject == NULL)
+ {
+ return AVCDEC_MEMORY_FAIL;
+ }
+
+ decvid = (AVCDecObject*) avcHandle->AVCObject;
+
+ memset(decvid, 0, sizeof(AVCDecObject));
+
+ decvid->common = (AVCCommonObj*)avcHandle->CBAVC_Malloc(userData, sizeof(AVCCommonObj), 0);
+ if (decvid->common == NULL)
+ {
+ return AVCDEC_MEMORY_FAIL;
+ }
+
+ video = decvid->common;
+ memset(video, 0, sizeof(AVCCommonObj));
+
+ video->seq_parameter_set_id = 9999; /* set it to some illegal value */
+
+ decvid->bitstream = (AVCDecBitstream *) avcHandle->CBAVC_Malloc(userData, sizeof(AVCDecBitstream), 1/*DEFAULT_ATTR*/);
+ if (decvid->bitstream == NULL)
+ {
+ return AVCDEC_MEMORY_FAIL;
+ }
+
+ decvid->bitstream->userData = avcHandle->userData; /* callback for more data */
+ decvid->avcHandle = avcHandle;
+ decvid->debugEnable = avcHandle->debugEnable;
+ }
+
+ decvid = (AVCDecObject*) avcHandle->AVCObject;
+ video = decvid->common;
+ bitstream = decvid->bitstream;
+
+ /* check if we can reuse the memory without re-allocating it. */
+ /* always check if(first_seq==TRUE) */
+
+ /* Conversion from EBSP to RBSP */
+ video->forbidden_bit = nal_unit[0] >> 7;
+ if (video->forbidden_bit) return AVCDEC_FAIL;
+ video->nal_ref_idc = (nal_unit[0] & 0x60) >> 5;
+ video->nal_unit_type = (AVCNalUnitType)(nal_unit[0] & 0x1F);
+
+ if (video->nal_unit_type != AVC_NALTYPE_SPS) /* not a SPS NAL */
+ {
+ return AVCDEC_FAIL;
+ }
+
+ /* Initialize bitstream structure*/
+ BitstreamInit(bitstream, nal_unit + 1, nal_size - 1);
+
+ /* if first_seq == TRUE, allocate the following memory */
+ if (first_seq == TRUE)
+ {
+ video->currSeqParams = NULL; /* initialize it to NULL */
+ video->currPicParams = NULL;
+
+ /* There are 32 pointers to sequence param set, seqParams.
+ There are 255 pointers to picture param set, picParams.*/
+ for (i = 0; i < 32; i++)
+ decvid->seqParams[i] = NULL;
+
+ for (i = 0; i < 256; i++)
+ decvid->picParams[i] = NULL;
+
+ video->MbToSliceGroupMap = NULL;
+
+ video->mem_mgr_ctrl_eq_5 = FALSE;
+ video->newPic = TRUE;
+ video->newSlice = TRUE;
+ video->currPic = NULL;
+ video->currFS = NULL;
+ video->prevRefPic = NULL;
+
+ video->mbNum = 0; // MC_Conceal
+ /* Allocate sliceHdr. */
+
+ video->sliceHdr = (AVCSliceHeader*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCSliceHeader), 5/*DEFAULT_ATTR*/);
+ if (video->sliceHdr == NULL)
+ {
+ return AVCDEC_MEMORY_FAIL;
+ }
+
+ video->decPicBuf = (AVCDecPicBuffer*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCDecPicBuffer), 3/*DEFAULT_ATTR*/);
+ if (video->decPicBuf == NULL)
+ {
+ return AVCDEC_MEMORY_FAIL;
+ }
+ memset(video->decPicBuf, 0, sizeof(AVCDecPicBuffer));
+ }
+
+ /* Decode SPS, allocate video->seqParams[i] and assign video->currSeqParams */
+ status = DecodeSPS(decvid, bitstream);
+
+ if (status != AVCDEC_SUCCESS)
+ {
+ return status;
+ }
+ return AVCDEC_SUCCESS;
+}
+
+/* ======================================================================== */
+/* Function : PVAVCDecGetSeqInfo() */
+/* Date : 11/4/2003 */
+/* Purpose : Get sequence parameter info. after SPS NAL is decoded. */
+/* In/out : */
+/* Return : AVCDEC_SUCCESS if succeed, AVC_FAIL if fail. */
+/* Modified : */
+/* 12/20/03: change input argument, use structure instead. */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF AVCDec_Status PVAVCDecGetSeqInfo(AVCHandle *avcHandle, AVCDecSPSInfo *seqInfo)
+{
+ AVCDecObject *decvid = (AVCDecObject*) avcHandle->AVCObject;
+ AVCCommonObj *video;
+ int PicWidthInMbs, PicHeightInMapUnits, FrameHeightInMbs;
+
+ if (decvid == NULL || decvid->seqParams[0] == NULL)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ video = decvid->common;
+
+ PicWidthInMbs = decvid->seqParams[0]->pic_width_in_mbs_minus1 + 1;
+ PicHeightInMapUnits = decvid->seqParams[0]->pic_height_in_map_units_minus1 + 1 ;
+ FrameHeightInMbs = (2 - decvid->seqParams[0]->frame_mbs_only_flag) * PicHeightInMapUnits ;
+
+ seqInfo->FrameWidth = PicWidthInMbs << 4;
+ seqInfo->FrameHeight = FrameHeightInMbs << 4;
+
+ seqInfo->frame_only_flag = decvid->seqParams[0]->frame_mbs_only_flag;
+
+ if (decvid->seqParams[0]->frame_cropping_flag)
+ {
+ seqInfo->frame_crop_left = 2 * decvid->seqParams[0]->frame_crop_left_offset;
+ seqInfo->frame_crop_right = seqInfo->FrameWidth - (2 * decvid->seqParams[0]->frame_crop_right_offset + 1);
+
+ if (seqInfo->frame_only_flag)
+ {
+ seqInfo->frame_crop_top = 2 * decvid->seqParams[0]->frame_crop_top_offset;
+ seqInfo->frame_crop_bottom = seqInfo->FrameHeight - (2 * decvid->seqParams[0]->frame_crop_bottom_offset + 1);
+ /* Note in 7.4.2.1, there is a contraint on the value of frame_crop_left and frame_crop_top
+ such that they have to be less than or equal to frame_crop_right/2 and frame_crop_bottom/2, respectively. */
+ }
+ else
+ {
+ seqInfo->frame_crop_top = 4 * decvid->seqParams[0]->frame_crop_top_offset;
+ seqInfo->frame_crop_bottom = seqInfo->FrameHeight - (4 * decvid->seqParams[0]->frame_crop_bottom_offset + 1);
+ /* Note in 7.4.2.1, there is a contraint on the value of frame_crop_left and frame_crop_top
+ such that they have to be less than or equal to frame_crop_right/2 and frame_crop_bottom/4, respectively. */
+ }
+ }
+ else /* no cropping flag, just give the first and last pixel */
+ {
+ seqInfo->frame_crop_bottom = seqInfo->FrameHeight - 1;
+ seqInfo->frame_crop_right = seqInfo->FrameWidth - 1;
+ seqInfo->frame_crop_top = seqInfo->frame_crop_left = 0;
+ }
+
+ return AVCDEC_SUCCESS;
+}
+
+/* ======================================================================== */
+/* Function : PVAVCDecPicParamSet() */
+/* Date : 11/4/2003 */
+/* Purpose : Initialize picture */
+/* create reference picture list. */
+/* In/out : */
+/* Return : AVCDEC_SUCCESS if succeed, AVC_FAIL if fail. */
+/* Modified : */
+/* ======================================================================== */
+/**
+Since PPS doesn't contain much data, most of the picture initialization will
+be done after decoding the slice header in PVAVCDecodeSlice. */
+OSCL_EXPORT_REF AVCDec_Status PVAVCDecPicParamSet(AVCHandle *avcHandle, uint8 *nal_unit,
+ int nal_size)
+{
+ AVCDec_Status status;
+ AVCDecObject *decvid = (AVCDecObject*) avcHandle->AVCObject;
+ AVCCommonObj *video;
+ AVCDecBitstream *bitstream;
+
+ if (decvid == NULL)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ video = decvid->common;
+ bitstream = decvid->bitstream;
+ /* 1. Convert EBSP to RBSP. Create bitstream structure */
+ video->forbidden_bit = nal_unit[0] >> 7;
+ video->nal_ref_idc = (nal_unit[0] & 0x60) >> 5;
+ video->nal_unit_type = (AVCNalUnitType)(nal_unit[0] & 0x1F);
+
+ if (video->nal_unit_type != AVC_NALTYPE_PPS) /* not a PPS NAL */
+ {
+ return AVCDEC_FAIL;
+ }
+
+
+ /* 2. Initialize bitstream structure*/
+ BitstreamInit(bitstream, nal_unit + 1, nal_size - 1);
+
+ /* 2. Decode pic_parameter_set_rbsp syntax. Allocate video->picParams[i] and assign to currPicParams */
+ status = DecodePPS(decvid, video, bitstream);
+ if (status != AVCDEC_SUCCESS)
+ {
+ return status;
+ }
+
+ video->SliceGroupChangeRate = video->currPicParams->slice_group_change_rate_minus1 + 1 ;
+
+ return AVCDEC_SUCCESS;
+}
+
+OSCL_EXPORT_REF AVCDec_Status PVAVCDecSEI(AVCHandle *avcHandle, uint8 *nal_unit,
+ int nal_size)
+{
+ OSCL_UNUSED_ARG(avcHandle);
+ OSCL_UNUSED_ARG(nal_unit);
+ OSCL_UNUSED_ARG(nal_size);
+
+ return AVCDEC_SUCCESS;
+}
+/* ======================================================================== */
+/* Function : PVAVCDecodeSlice() */
+/* Date : 11/4/2003 */
+/* Purpose : Decode one NAL unit. */
+/* In/out : */
+/* Return : See enum AVCDec_Status for return values. */
+/* Modified : */
+/* ======================================================================== */
+OSCL_EXPORT_REF AVCDec_Status PVAVCDecodeSlice(AVCHandle *avcHandle, uint8 *buffer,
+ int buf_size)
+{
+ AVCDecObject *decvid = (AVCDecObject*) avcHandle->AVCObject;
+ AVCCommonObj *video;
+ AVCDecBitstream *bitstream;
+ AVCDec_Status status;
+
+ if (decvid == NULL)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ video = decvid->common;
+ bitstream = decvid->bitstream;
+
+ if (video->mem_mgr_ctrl_eq_5)
+ {
+ return AVCDEC_PICTURE_OUTPUT_READY; // to flushout frame buffers
+ }
+
+ if (video->newSlice)
+ {
+ /* 2. Check NAL type */
+ if (buffer == NULL)
+ {
+ return AVCDEC_FAIL;
+ }
+ video->prev_nal_unit_type = video->nal_unit_type;
+ video->forbidden_bit = buffer[0] >> 7;
+ video->nal_ref_idc = (buffer[0] & 0x60) >> 5;
+ video->nal_unit_type = (AVCNalUnitType)(buffer[0] & 0x1F);
+
+
+ if (video->nal_unit_type == AVC_NALTYPE_AUD)
+ {
+ return AVCDEC_SUCCESS;
+ }
+
+ if (video->nal_unit_type != AVC_NALTYPE_SLICE &&
+ video->nal_unit_type != AVC_NALTYPE_IDR)
+ {
+ return AVCDEC_FAIL; /* not supported */
+ }
+
+
+
+ if (video->nal_unit_type >= 2 && video->nal_unit_type <= 4)
+ {
+ return AVCDEC_FAIL; /* not supported */
+ }
+ else
+ {
+ video->slice_data_partitioning = FALSE;
+ }
+
+ video->newSlice = FALSE;
+ /* Initialize bitstream structure*/
+ BitstreamInit(bitstream, buffer + 1, buf_size - 1);
+
+
+ /* 2.1 Decode Slice Header (separate function)*/
+ status = DecodeSliceHeader(decvid, video, bitstream);
+ if (status != AVCDEC_SUCCESS)
+ {
+ video->newSlice = TRUE;
+ return status;
+ }
+
+ if (video->sliceHdr->frame_num != video->prevFrameNum || (video->sliceHdr->first_mb_in_slice < (uint)video->mbNum && video->currSeqParams->constrained_set1_flag == 1))
+ {
+ video->newPic = TRUE;
+ if (video->numMBs > 0)
+ {
+ // Conceal missing MBs of previously decoded frame
+ ConcealSlice(decvid, video->PicSizeInMbs - video->numMBs, video->PicSizeInMbs); // Conceal
+ video->numMBs = 0;
+
+ // DeblockPicture(video); // No need to deblock
+
+ /* 3.2 Decoded frame reference marking. */
+ /* 3.3 Put the decoded picture in output buffers */
+ /* set video->mem_mge_ctrl_eq_5 */
+ AVCNalUnitType temp = video->nal_unit_type;
+ video->nal_unit_type = video->prev_nal_unit_type;
+ StorePictureInDPB(avcHandle, video);
+ video->nal_unit_type = temp;
+ video->mbNum = 0; // MC_Conceal
+ return AVCDEC_PICTURE_OUTPUT_READY;
+ }
+ }
+
+ if (video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ video->prevFrameNum = 0;
+ video->PrevRefFrameNum = 0;
+ }
+
+ if (!video->currSeqParams->gaps_in_frame_num_value_allowed_flag)
+ { /* no gaps allowed, frame_num has to increase by one only */
+ /* if(sliceHdr->frame_num != (video->PrevRefFrameNum + 1)%video->MaxFrameNum) */
+ if (video->sliceHdr->frame_num != video->PrevRefFrameNum && video->sliceHdr->frame_num != (video->PrevRefFrameNum + 1) % video->MaxFrameNum)
+ {
+ // Conceal missing MBs of previously decoded frame
+ video->numMBs = 0;
+ video->newPic = TRUE;
+ video->prevFrameNum++; // FIX
+ video->PrevRefFrameNum++;
+ AVCNalUnitType temp = video->nal_unit_type;
+ video->nal_unit_type = AVC_NALTYPE_SLICE; //video->prev_nal_unit_type;
+ status = (AVCDec_Status)DPBInitBuffer(avcHandle, video);
+ if (status != AVCDEC_SUCCESS)
+ {
+ return status;
+ }
+ video->currFS->IsOutputted = 0x01;
+ video->currFS->IsReference = 3;
+ video->currFS->IsLongTerm = 0;
+
+ DecodePOC(video);
+ /* find an empty memory from DPB and assigned to currPic */
+ DPBInitPic(video, video->PrevRefFrameNum % video->MaxFrameNum);
+ RefListInit(video);
+ ConcealSlice(decvid, 0, video->PicSizeInMbs); // Conceal
+ video->currFS->IsOutputted |= 0x02;
+ //conceal frame
+ /* 3.2 Decoded frame reference marking. */
+ /* 3.3 Put the decoded picture in output buffers */
+ /* set video->mem_mge_ctrl_eq_5 */
+ video->mbNum = 0; // Conceal
+ StorePictureInDPB(avcHandle, video);
+ video->nal_unit_type = temp;
+
+ return AVCDEC_PICTURE_OUTPUT_READY;
+ }
+ }
+ }
+
+ if (video->newPic == TRUE)
+ {
+ status = (AVCDec_Status)DPBInitBuffer(avcHandle, video);
+ if (status != AVCDEC_SUCCESS)
+ {
+ return status;
+ }
+ }
+
+ video->newSlice = TRUE;
+
+ /* function pointer setting at slice-level */
+ // OPTIMIZE
+ decvid->residual_block = &residual_block_cavlc;
+
+ /* derive picture order count */
+ if (video->newPic == TRUE)
+ {
+ video->numMBs = video->PicSizeInMbs;
+
+ if (video->nal_unit_type != AVC_NALTYPE_IDR && video->currSeqParams->gaps_in_frame_num_value_allowed_flag)
+ {
+ if (video->sliceHdr->frame_num != (video->PrevRefFrameNum + 1) % video->MaxFrameNum)
+ {
+ status = fill_frame_num_gap(avcHandle, video);
+ if (status != AVCDEC_SUCCESS)
+ {
+ video->numMBs = 0;
+ return status;
+ }
+
+ status = (AVCDec_Status)DPBInitBuffer(avcHandle, video);
+ if (status != AVCDEC_SUCCESS)
+ {
+ video->numMBs = 0;
+ return status;
+ }
+
+
+ }
+ }
+ /* if there's gap in the frame_num, we have to fill in the gap with
+ imaginary frames that won't get used for short-term ref. */
+ /* see fill_frame_num_gap() in JM */
+
+
+ DecodePOC(video);
+ /* find an empty memory from DPB and assigned to currPic */
+ DPBInitPic(video, video->CurrPicNum);
+
+ video->currPic->isReference = TRUE; // FIX
+
+ if (video->nal_ref_idc == 0)
+ {
+ video->currPic->isReference = FALSE;
+ video->currFS->IsOutputted |= 0x02; /* The MASK 0x02 means not needed for reference, or returned */
+ /* node need to check for freeing of this buffer */
+ }
+
+ FMOInit(video);
+
+ if (video->currPic->isReference)
+ {
+ video->PrevRefFrameNum = video->sliceHdr->frame_num;
+ }
+
+
+ video->prevFrameNum = video->sliceHdr->frame_num;
+ }
+
+ video->newPic = FALSE;
+
+
+ /* Initialize refListIdx for this picture */
+ RefListInit(video);
+
+ /* Re-order the reference list according to the ref_pic_list_reordering() */
+ status = (AVCDec_Status)ReOrderList(video);
+ if (status != AVCDEC_SUCCESS)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ /* 2.2 Decode Slice. */
+ status = (AVCDec_Status)DecodeSlice(decvid);
+
+ video->slice_id++; // slice
+
+ if (status == AVCDEC_PICTURE_READY)
+ {
+ /* 3. Check complete picture */
+#ifndef MB_BASED_DEBLOCK
+ /* 3.1 Deblock */
+ DeblockPicture(video);
+#endif
+ /* 3.2 Decoded frame reference marking. */
+ /* 3.3 Put the decoded picture in output buffers */
+ /* set video->mem_mge_ctrl_eq_5 */
+ status = (AVCDec_Status)StorePictureInDPB(avcHandle, video); // CHECK check the retunr status
+ if (status != AVCDEC_SUCCESS)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ if (video->mem_mgr_ctrl_eq_5)
+ {
+ video->PrevRefFrameNum = 0;
+ video->prevFrameNum = 0;
+ video->prevPicOrderCntMsb = 0;
+ video->prevPicOrderCntLsb = video->TopFieldOrderCnt;
+ video->prevFrameNumOffset = 0;
+ }
+ else
+ {
+ video->prevPicOrderCntMsb = video->PicOrderCntMsb;
+ video->prevPicOrderCntLsb = video->sliceHdr->pic_order_cnt_lsb;
+ video->prevFrameNumOffset = video->FrameNumOffset;
+ }
+
+ return AVCDEC_PICTURE_READY;
+ }
+ else if (status != AVCDEC_SUCCESS)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ return AVCDEC_SUCCESS;
+}
+
+/* ======================================================================== */
+/* Function : PVAVCDecGetOutput() */
+/* Date : 11/3/2003 */
+/* Purpose : Get the next picture according to PicOrderCnt. */
+/* In/out : */
+/* Return : AVCFrameIO structure */
+/* Modified : */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF AVCDec_Status PVAVCDecGetOutput(AVCHandle *avcHandle, int *indx, int *release, AVCFrameIO *output)
+{
+ AVCDecObject *decvid = (AVCDecObject*) avcHandle->AVCObject;
+ AVCCommonObj *video;
+ AVCDecPicBuffer *dpb;
+ AVCFrameStore *oldestFrame = NULL;
+ int i, first = 1;
+ int count_frame = 0;
+ int index = 0;
+ int min_poc = 0;
+
+ if (decvid == NULL)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ video = decvid->common;
+ dpb = video->decPicBuf;
+
+ if (dpb->num_fs == 0)
+ {
+ return AVCDEC_FAIL;
+ }
+
+ /* search for the oldest frame_num in dpb */
+ /* extension to field decoding, we have to search for every top_field/bottom_field within
+ each frame in the dpb. This code only works for frame based.*/
+
+ if (video->mem_mgr_ctrl_eq_5 == FALSE)
+ {
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+ if ((dpb->fs[i]->IsOutputted & 0x01) == 0)
+ {
+ count_frame++;
+ if (first)
+ {
+ min_poc = dpb->fs[i]->PicOrderCnt;
+ first = 0;
+ oldestFrame = dpb->fs[i];
+ index = i;
+ }
+ if (dpb->fs[i]->PicOrderCnt < min_poc)
+ {
+ min_poc = dpb->fs[i]->PicOrderCnt;
+ oldestFrame = dpb->fs[i];
+ index = i;
+ }
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+ if ((dpb->fs[i]->IsOutputted & 0x01) == 0 && dpb->fs[i] != video->currFS)
+ {
+ count_frame++;
+ if (first)
+ {
+ min_poc = dpb->fs[i]->PicOrderCnt;
+ first = 0;
+ oldestFrame = dpb->fs[i];
+ index = i;
+ }
+ if (dpb->fs[i]->PicOrderCnt < min_poc)
+ {
+ min_poc = dpb->fs[i]->PicOrderCnt;
+ oldestFrame = dpb->fs[i];
+ index = i;
+ }
+ }
+ }
+
+ if (count_frame < 2 && video->nal_unit_type != AVC_NALTYPE_IDR)
+ {
+ video->mem_mgr_ctrl_eq_5 = FALSE; // FIX
+ }
+ else if (count_frame < 1 && video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+ if (dpb->fs[i] == video->currFS && (dpb->fs[i]->IsOutputted & 0x01) == 0)
+ {
+ oldestFrame = dpb->fs[i];
+ index = i;
+ break;
+ }
+ }
+ video->mem_mgr_ctrl_eq_5 = FALSE;
+ }
+ }
+
+ if (oldestFrame == NULL)
+ {
+
+ /* Check for Mem_mgmt_operation_5 based forced output */
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+ /* looking for the one not used or not reference and has been outputted */
+ if (dpb->fs[i]->IsReference == 0 && dpb->fs[i]->IsOutputted == 3)
+ {
+ break;
+ }
+ }
+ if (i < dpb->num_fs)
+ {
+ /* there are frames available for decoding */
+ return AVCDEC_FAIL; /* no frame to be outputted */
+ }
+
+
+ /* no free frame available, we have to release one to continue decoding */
+ int MinIdx = 0;
+ int32 MinFrameNumWrap = 0x7FFFFFFF;
+
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+ if (dpb->fs[i]->IsReference && !dpb->fs[i]->IsLongTerm)
+ {
+ if (dpb->fs[i]->FrameNumWrap < MinFrameNumWrap)
+ {
+ MinFrameNumWrap = dpb->fs[i]->FrameNumWrap;
+ MinIdx = i;
+ }
+ }
+ }
+ /* mark the frame with smallest PicOrderCnt to be unused for reference */
+ dpb->fs[MinIdx]->IsReference = 0;
+ dpb->fs[MinIdx]->IsLongTerm = 0;
+ dpb->fs[MinIdx]->frame.isReference = FALSE;
+ dpb->fs[MinIdx]->frame.isLongTerm = FALSE;
+ dpb->fs[MinIdx]->IsOutputted |= 0x02;
+#ifdef PV_MEMORY_POOL
+ if (dpb->fs[MinIdx]->IsOutputted == 3)
+ {
+ avcHandle->CBAVC_FrameUnbind(avcHandle->userData, MinIdx);
+ }
+#endif
+ return AVCDEC_FAIL;
+ }
+ /* MASK 0x01 means the frame is outputted (for display). A frame gets freed when it is
+ outputted (0x01) and not needed for reference (0x02) */
+ oldestFrame->IsOutputted |= 0x01;
+
+ if (oldestFrame->IsOutputted == 3)
+ {
+ *release = 1; /* flag to release the buffer */
+ }
+ else
+ {
+ *release = 0;
+ }
+ /* do not release buffer here, release it after it is sent to the sink node */
+
+ output->YCbCr[0] = oldestFrame->frame.Sl;
+ output->YCbCr[1] = oldestFrame->frame.Scb;
+ output->YCbCr[2] = oldestFrame->frame.Scr;
+ output->height = oldestFrame->frame.height;
+ output->pitch = oldestFrame->frame.width;
+ output->disp_order = oldestFrame->PicOrderCnt;
+ output->coding_order = oldestFrame->FrameNum;
+ output->id = (uint32) oldestFrame->base_dpb; /* use the pointer as the id */
+ *indx = index;
+
+
+
+ return AVCDEC_SUCCESS;
+}
+
+
+/* ======================================================================== */
+/* Function : PVAVCDecReset() */
+/* Date : 03/04/2004 */
+/* Purpose : Reset decoder, prepare it for a new IDR frame. */
+/* In/out : */
+/* Return : void */
+/* Modified : */
+/* ======================================================================== */
+OSCL_EXPORT_REF void PVAVCDecReset(AVCHandle *avcHandle)
+{
+ AVCDecObject *decvid = (AVCDecObject*) avcHandle->AVCObject;
+ AVCCommonObj *video;
+ AVCDecPicBuffer *dpb;
+ int i;
+
+ if (decvid == NULL)
+ {
+ return;
+ }
+
+ video = decvid->common;
+ dpb = video->decPicBuf;
+
+ /* reset the DPB */
+
+
+ for (i = 0; i < dpb->num_fs; i++)
+ {
+ dpb->fs[i]->IsLongTerm = 0;
+ dpb->fs[i]->IsReference = 0;
+ dpb->fs[i]->IsOutputted = 3;
+ dpb->fs[i]->frame.isReference = 0;
+ dpb->fs[i]->frame.isLongTerm = 0;
+ }
+
+ video->mem_mgr_ctrl_eq_5 = FALSE;
+ video->newPic = TRUE;
+ video->newSlice = TRUE;
+ video->currPic = NULL;
+ video->currFS = NULL;
+ video->prevRefPic = NULL;
+ video->prevFrameNum = 0;
+ video->PrevRefFrameNum = 0;
+ video->prevFrameNumOffset = 0;
+ video->FrameNumOffset = 0;
+ video->mbNum = 0;
+ video->numMBs = 0;
+
+ return ;
+}
+
+
+/* ======================================================================== */
+/* Function : PVAVCCleanUpDecoder() */
+/* Date : 11/4/2003 */
+/* Purpose : Clean up the decoder, free all memories allocated. */
+/* In/out : */
+/* Return : void */
+/* Modified : */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF void PVAVCCleanUpDecoder(AVCHandle *avcHandle)
+{
+ AVCDecObject *decvid = (AVCDecObject*) avcHandle->AVCObject;
+ AVCCommonObj *video;
+ void *userData = avcHandle->userData;
+ int i;
+
+ DEBUG_LOG(userData, AVC_LOGTYPE_INFO, "PVAVCCleanUpDecoder", -1, -1);
+
+ if (decvid != NULL)
+ {
+ video = decvid->common;
+ if (video != NULL)
+ {
+ if (video->MbToSliceGroupMap != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)video->MbToSliceGroupMap);
+ }
+
+#ifdef MB_BASED_DEBLOCK
+ if (video->intra_pred_top != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)video->intra_pred_top);
+ }
+ if (video->intra_pred_top_cb != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)video->intra_pred_top_cb);
+ }
+ if (video->intra_pred_top_cr != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)video->intra_pred_top_cr);
+ }
+#endif
+ if (video->mblock != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)video->mblock);
+ }
+
+ if (video->decPicBuf != NULL)
+ {
+ CleanUpDPB(avcHandle, video);
+ avcHandle->CBAVC_Free(userData, (int)video->decPicBuf);
+ }
+
+ if (video->sliceHdr != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)video->sliceHdr);
+ }
+
+ avcHandle->CBAVC_Free(userData, (int)video); /* last thing to do */
+
+ }
+
+ for (i = 0; i < 256; i++)
+ {
+ if (decvid->picParams[i] != NULL)
+ {
+ if (decvid->picParams[i]->slice_group_id != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)decvid->picParams[i]->slice_group_id);
+ }
+ avcHandle->CBAVC_Free(userData, (int)decvid->picParams[i]);
+ }
+ }
+ for (i = 0; i < 32; i++)
+ {
+ if (decvid->seqParams[i] != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)decvid->seqParams[i]);
+ }
+ }
+ if (decvid->bitstream != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)decvid->bitstream);
+ }
+
+
+ avcHandle->CBAVC_Free(userData, (int)decvid);
+ }
+
+
+ return ;
+}