blob: b583a8294959b5594686457821532b80adc293f2 [file] [log] [blame]
/*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Description:
*/
#define DEBUG
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/amlogic/media/utils/vdec_reg.h>
#include "../utils/vdec.h"
#include "../utils/amvdec.h"
#include "h264_dpb.h"
#define FRAME_NUM_MAX_SIZE 0x10000
#undef pr_info
#define pr_info printk
int dpb_print(int index, int debug_flag, const char *fmt, ...)
{
if (((h264_debug_flag & debug_flag) &&
((1 << index) & h264_debug_mask))
|| (debug_flag == PRINT_FLAG_ERROR)) {
unsigned char buf[512];
int len = 0;
va_list args;
va_start(args, fmt);
len = sprintf(buf, "%d: ", index);
vsnprintf(buf + len, 512-len, fmt, args);
pr_debug("%s", buf);
va_end(args);
}
return 0;
}
int dpb_print_cont(int index, int debug_flag, const char *fmt, ...)
{
if (((h264_debug_flag & debug_flag) &&
((1 << index) & h264_debug_mask))
|| (debug_flag == PRINT_FLAG_ERROR)) {
unsigned char buf[512];
int len = 0;
va_list args;
va_start(args, fmt);
vsnprintf(buf + len, 512-len, fmt, args);
pr_info("%s", buf);
va_end(args);
}
return 0;
}
unsigned char dpb_is_debug(int index, int debug_flag)
{
if (((h264_debug_flag & debug_flag) &&
((1 << index) & h264_debug_mask))
|| (debug_flag == PRINT_FLAG_ERROR))
return 1;
return 0;
}
#define CHECK_VALID(list_size, mark) {\
if (list_size > MAX_LIST_SIZE || list_size < 0) { \
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_ERROR, \
"%s(%d): listXsize[%d] %d is larger than max size\r\n",\
__func__, __LINE__, mark, list_size);\
list_size = 0; \
p_H264_Dpb->dpb_error_flag = __LINE__;\
} \
}
static struct DecRefPicMarking_s
dummy_dec_ref_pic_marking_buffer
[DEC_REF_PIC_MARKING_BUFFER_NUM_MAX];
static struct StorablePicture dummy_pic;
static struct FrameStore dummy_fs;
static struct StorablePicture *get_new_pic(
struct h264_dpb_stru *p_H264_Dpb,
enum PictureStructure structure, unsigned char is_output);
static void init_dummy_fs(void)
{
dummy_fs.frame = &dummy_pic;
dummy_fs.top_field = &dummy_pic;
dummy_fs.bottom_field = &dummy_pic;
dummy_pic.top_field = &dummy_pic;
dummy_pic.bottom_field = &dummy_pic;
dummy_pic.frame = &dummy_pic;
dummy_pic.dec_ref_pic_marking_buffer =
&dummy_dec_ref_pic_marking_buffer[0];
}
enum {
LIST_0 = 0,
LIST_1 = 1,
BI_PRED = 2,
BI_PRED_L0 = 3,
BI_PRED_L1 = 4
};
void ref_pic_list_reordering(struct h264_dpb_stru *p_H264_Dpb,
struct Slice *currSlice)
{
/* struct VideoParameters *p_Vid = currSlice->p_Vid;
* byte dP_nr = assignSE2partition[currSlice->dp_mode][SE_HEADER];
* DataPartition *partition = &(currSlice->partArr[dP_nr]);
* Bitstream *currStream = partition->bitstream;
*/
int i, j, val;
unsigned short *reorder_cmd =
&p_H264_Dpb->dpb_param.mmco.l0_reorder_cmd[0];
/* alloc_ref_pic_list_reordering_buffer(currSlice); */
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s\n", __func__);
if (currSlice->slice_type != I_SLICE &&
currSlice->slice_type != SI_SLICE) {
/* val = currSlice->ref_pic_list_reordering_flag[LIST_0] =
* read_u_1 ("SH: ref_pic_list_reordering_flag_l0",
* currStream, &p_Dec->UsedBits);
*/
if (reorder_cmd[0] != 3) {
val = currSlice->
ref_pic_list_reordering_flag[LIST_0] = 1;
} else {
val = currSlice->
ref_pic_list_reordering_flag[LIST_0] = 0;
}
if (val) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"%s, ref_pic_list_reordering_flag[LIST_0] is 1\n",
__func__);
j = 0;
i = 0;
do {
val = currSlice->
modification_of_pic_nums_idc[LIST_0][i] =
reorder_cmd[j++];
/* read_ue_v(
* "SH: modification_of_pic_nums_idc_l0",
* currStream, &p_Dec->UsedBits);
*/
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"%d(%d):val %x\n", i, j, val);
if (j >= 66) {
currSlice->
ref_pic_list_reordering_flag[LIST_0] =
0; /* by rain */
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_ERROR,
"%s error\n", __func__);
break;
}
if (val == 0 || val == 1) {
currSlice->
abs_diff_pic_num_minus1[LIST_0][i] =
reorder_cmd[j++];
/* read_ue_v("SH: "
*"abs_diff_pic_num_minus1_l0",
*currStream, &p_Dec->UsedBits);
*/
} else {
if (val == 2) {
currSlice->
long_term_pic_idx[LIST_0][i] =
reorder_cmd[j++];
/* read_ue_v(
*"SH: long_term_pic_idx_l0",
*currStream,
*&p_Dec->UsedBits);
*/
}
}
i++;
/* assert (i>currSlice->
* num_ref_idx_active[LIST_0]);
*/
if (
/*
* i>currSlice->num_ref_idx_active[LIST_0] ||
*/
i >= REORDERING_COMMAND_MAX_SIZE) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"%s error %d %d\n",
__func__, i,
currSlice->
num_ref_idx_active[LIST_0]);
currSlice->
ref_pic_list_reordering_flag[LIST_0] =
0; /* by rain */
break;
}
if (j >= 66) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_ERROR, "%s error\n",
__func__);
currSlice->
ref_pic_list_reordering_flag[LIST_0] =
0; /* by rain */
break;
}
} while (val != 3);
}
}
if (currSlice->slice_type == B_SLICE) {
reorder_cmd = &p_H264_Dpb->dpb_param.mmco.l1_reorder_cmd[0];
/* val = currSlice->ref_pic_list_reordering_flag[LIST_1]
*= read_u_1 ("SH: ref_pic_list_reordering_flag_l1",
*currStream,
*&p_Dec->UsedBits);
*/
if (reorder_cmd[0] != 3) {
val =
currSlice->ref_pic_list_reordering_flag[LIST_1] = 1;
} else {
val =
currSlice->ref_pic_list_reordering_flag[LIST_1] = 0;
}
if (val) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"%s, ref_pic_list_reordering_flag[LIST_1] is 1\n",
__func__);
j = 0;
i = 0;
do {
val = currSlice->
modification_of_pic_nums_idc[LIST_1][i] =
reorder_cmd[j++];
/* read_ue_v(
*"SH: modification_of_pic_nums_idc_l1",
*currStream,
*&p_Dec->UsedBits);
*/
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"%d(%d):val %x\n",
i, j, val);
if (j >= 66) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_ERROR, "%s error\n",
__func__);
currSlice->
ref_pic_list_reordering_flag[LIST_1] =
0; /* by rain */
break;
}
if (val == 0 || val == 1) {
currSlice->
abs_diff_pic_num_minus1[LIST_1][i] =
reorder_cmd[j++];
/* read_ue_v(
*"SH: abs_diff_pic_num_minus1_l1",
*currStream, &p_Dec->UsedBits);
*/
} else {
if (val == 2) {
currSlice->
long_term_pic_idx[LIST_1][i] =
reorder_cmd[j++];
/* read_ue_v(
*"SH: long_term_pic_idx_l1",
*currStream,
*&p_Dec->UsedBits);
*/
}
}
i++;
/* assert(i>currSlice->
* num_ref_idx_active[LIST_1]);
*/
if (
/*i>currSlice->num_ref_idx_active[LIST_1] || */
i >= REORDERING_COMMAND_MAX_SIZE) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"%s error %d %d\n",
__func__, i,
currSlice->
num_ref_idx_active[LIST_0]);
currSlice->
ref_pic_list_reordering_flag[LIST_1] =
0; /* by rain */
break;
}
if (j >= 66) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_ERROR,
"%s error\n", __func__);
break;
}
} while (val != 3);
}
}
/* set reference index of redundant slices. */
/*
*if (currSlice->redundant_pic_cnt &&
*(currSlice->slice_type != I_SLICE))
*{
* currSlice->redundant_slice_ref_idx =
* currSlice->abs_diff_pic_num_minus1[LIST_0][0] + 1;
*}
*/
}
void slice_prepare(struct h264_dpb_stru *p_H264_Dpb,
struct DecodedPictureBuffer *p_Dpb,
struct VideoParameters *p_Vid,
struct SPSParameters *sps, struct Slice *pSlice)
{
int i, j;
/* p_Vid->active_sps = sps; */
unsigned short *mmco_cmd = &p_H264_Dpb->dpb_param.mmco.mmco_cmd[0];
/* for decode_poc */
sps->pic_order_cnt_type =
p_H264_Dpb->dpb_param.l.data[PIC_ORDER_CNT_TYPE];
sps->log2_max_pic_order_cnt_lsb_minus4 =
p_H264_Dpb->dpb_param.l.data[LOG2_MAX_PIC_ORDER_CNT_LSB] - 4;
sps->num_ref_frames_in_pic_order_cnt_cycle =
p_H264_Dpb->
dpb_param.l.data[NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE];
for (i = 0; i < 128; i++)
sps->offset_for_ref_frame[i] =
(short) p_H264_Dpb->
dpb_param.mmco.offset_for_ref_frame_base[i];
sps->offset_for_non_ref_pic =
(short) p_H264_Dpb->dpb_param.l.data[OFFSET_FOR_NON_REF_PIC];
sps->offset_for_top_to_bottom_field =
(short) p_H264_Dpb->dpb_param.l.data
[OFFSET_FOR_TOP_TO_BOTTOM_FIELD];
pSlice->frame_num = p_H264_Dpb->dpb_param.dpb.frame_num;
pSlice->idr_flag =
(p_H264_Dpb->dpb_param.dpb.NAL_info_mmco & 0x1f)
== 5 ? 1 : 0;
pSlice->nal_reference_idc =
(p_H264_Dpb->dpb_param.dpb.NAL_info_mmco >> 5)
& 0x3;
pSlice->pic_order_cnt_lsb =
p_H264_Dpb->dpb_param.dpb.pic_order_cnt_lsb;
pSlice->field_pic_flag = 0;
pSlice->bottom_field_flag = 0;
pSlice->delta_pic_order_cnt_bottom = val(
p_H264_Dpb->dpb_param.dpb.delta_pic_order_cnt_bottom);
pSlice->delta_pic_order_cnt[0] = val(
p_H264_Dpb->dpb_param.dpb.delta_pic_order_cnt_0);
pSlice->delta_pic_order_cnt[1] = val(
p_H264_Dpb->dpb_param.dpb.delta_pic_order_cnt_1);
p_Vid->last_has_mmco_5 = 0;
/* last memory_management_control_operation is 5 */
p_Vid->last_pic_bottom_field = 0;
p_Vid->max_frame_num = 1 <<
(p_H264_Dpb->dpb_param.l.data[LOG2_MAX_FRAME_NUM]);
/**/
pSlice->structure = (p_H264_Dpb->
dpb_param.l.data[NEW_PICTURE_STRUCTURE] == 3) ?
FRAME : p_H264_Dpb->dpb_param.l.data[NEW_PICTURE_STRUCTURE];
if (pSlice->structure == FRAME) {
pSlice->field_pic_flag = 0;
pSlice->bottom_field_flag = 0;
} else {
pSlice->field_pic_flag = 1;
if (pSlice->structure == TOP_FIELD)
pSlice->bottom_field_flag = 0;
else
pSlice->bottom_field_flag = 1;
}
pSlice->pic_struct = p_H264_Dpb->dpb_param.l.data[PICTURE_STRUCT];
sps->num_ref_frames = p_H264_Dpb->
dpb_param.l.data[MAX_REFERENCE_FRAME_NUM];
sps->profile_idc =
(p_H264_Dpb->dpb_param.l.data[PROFILE_IDC_MMCO] >> 8) & 0xff;
/*sps->max_dpb_size = p_H264_Dpb->dpb_param.l.data[MAX_DPB_SIZE];*/
if (pSlice->idr_flag) {
pSlice->long_term_reference_flag = mmco_cmd[0] & 1;
pSlice->no_output_of_prior_pics_flag = (mmco_cmd[0] >> 1) & 1;
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"IDR: long_term_reference_flag %d no_output_of_prior_pics_flag %d\r\n",
pSlice->long_term_reference_flag,
pSlice->no_output_of_prior_pics_flag);
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"idr set pre_frame_num(%d) to frame_num (%d)\n",
p_Vid->pre_frame_num, pSlice->frame_num);
p_Vid->pre_frame_num = pSlice->frame_num;
} else if (p_H264_Dpb->mDPB.first_pic_done == 0) {
/* by rain
handle the case when first slice is I instead of IDR
*/
p_Vid->pre_frame_num = pSlice->frame_num;
}
/* pSlice->adaptive_ref_pic_buffering_flag; */
sps->log2_max_frame_num_minus4 =
p_H264_Dpb->dpb_param.l.data[LOG2_MAX_FRAME_NUM] - 4;
sps->frame_num_gap_allowed = p_H264_Dpb->dpb_param.l.data[FRAME_NUM_GAP_ALLOWED];
p_Vid->non_conforming_stream =
p_H264_Dpb->dpb_param.l.data[NON_CONFORMING_STREAM];
p_Vid->recovery_point =
p_H264_Dpb->dpb_param.l.data[RECOVERY_POINT];
switch (p_H264_Dpb->dpb_param.l.data[SLICE_TYPE]) {
case I_Slice:
pSlice->slice_type = I_SLICE;
break;
case P_Slice:
pSlice->slice_type = P_SLICE;
break;
case B_Slice:
pSlice->slice_type = B_SLICE;
break;
default:
pSlice->slice_type = NUM_SLICE_TYPES;
break;
}
pSlice->num_ref_idx_active[LIST_0] =
p_H264_Dpb->dpb_param.dpb.num_ref_idx_l0_active_minus1 +
1;
/* p_H264_Dpb->dpb_param.l.data[PPS_NUM_REF_IDX_L0_ACTIVE_MINUS1]; */
pSlice->num_ref_idx_active[LIST_1] =
p_H264_Dpb->dpb_param.dpb.num_ref_idx_l1_active_minus1 +
1;
/* p_H264_Dpb->dpb_param.l.data[PPS_NUM_REF_IDX_L1_ACTIVE_MINUS1]; */
pSlice->p_Vid = p_Vid;
pSlice->p_Dpb = p_Dpb;
/*
p_H264_Dpb->colocated_buf_size =
p_H264_Dpb->dpb_param.l.data[FRAME_SIZE_IN_MB] * 96;*/
pSlice->first_mb_in_slice =
p_H264_Dpb->dpb_param.l.data[FIRST_MB_IN_SLICE];
pSlice->mode_8x8_flags = p_H264_Dpb->dpb_param.l.data[MODE_8X8_FLAGS];
pSlice->picture_structure_mmco =
p_H264_Dpb->dpb_param.dpb.picture_structure_mmco;
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s slice_type is %d, num_ref_idx_active[0,1]=%d,%d nal_reference_idc %d pic struct 0x%x(mmco stru 0x%x)\n",
__func__, pSlice->slice_type,
pSlice->num_ref_idx_active[LIST_0],
pSlice->num_ref_idx_active[LIST_1],
pSlice->nal_reference_idc,
pSlice->structure,
pSlice->picture_structure_mmco);
#ifdef ERROR_CHECK
if (pSlice->num_ref_idx_active[LIST_0] >= MAX_LIST_SIZE) {
pSlice->num_ref_idx_active[LIST_0] = MAX_LIST_SIZE - 1;
p_H264_Dpb->dpb_error_flag = __LINE__;
}
if (pSlice->num_ref_idx_active[LIST_1] >= MAX_LIST_SIZE) {
pSlice->num_ref_idx_active[LIST_1] = MAX_LIST_SIZE - 1;
p_H264_Dpb->dpb_error_flag = __LINE__;
}
#endif
#if 1
/* dec_ref_pic_marking_buffer */
pSlice->adaptive_ref_pic_buffering_flag = 0;
if (pSlice->nal_reference_idc) {
for (i = 0, j = 0; i < 44; j++) {
unsigned short val;
struct DecRefPicMarking_s *tmp_drpm =
&pSlice->dec_ref_pic_marking_buffer[j];
memset(tmp_drpm, 0, sizeof(struct DecRefPicMarking_s));
val = tmp_drpm->
memory_management_control_operation =
mmco_cmd[i++];
tmp_drpm->Next = NULL;
if (j > 0) {
pSlice->
dec_ref_pic_marking_buffer[j - 1].Next =
tmp_drpm;
}
if (val == 0 || i >= 44)
break;
pSlice->adaptive_ref_pic_buffering_flag = 1;
if ((val == 1) || (val == 3)) {
tmp_drpm->difference_of_pic_nums_minus1 =
mmco_cmd[i++];
}
if (val == 2)
tmp_drpm->long_term_pic_num = mmco_cmd[i++];
if (i >= 44)
break;
if ((val == 3) || (val == 6))
tmp_drpm->long_term_frame_idx = mmco_cmd[i++];
if (val == 4) {
tmp_drpm->max_long_term_frame_idx_plus1 =
mmco_cmd[i++];
}
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"dec_ref_pic_marking_buffer[%d]:operation %x diff_pic_minus1 %x long_pic_num %x long_frame_idx %x max_long_frame_idx_plus1 %x\n",
j,
tmp_drpm->memory_management_control_operation,
tmp_drpm->difference_of_pic_nums_minus1,
tmp_drpm->long_term_pic_num,
tmp_drpm->long_term_frame_idx,
tmp_drpm->max_long_term_frame_idx_plus1);
}
}
ref_pic_list_reordering(p_H264_Dpb, pSlice);
#endif
/*VUI*/
p_H264_Dpb->vui_status = p_H264_Dpb->dpb_param.l.data[VUI_STATUS];
p_H264_Dpb->aspect_ratio_idc =
p_H264_Dpb->dpb_param.l.data[ASPECT_RATIO_IDC];
p_H264_Dpb->aspect_ratio_sar_width =
p_H264_Dpb->dpb_param.l.data[ASPECT_RATIO_SAR_WIDTH];
p_H264_Dpb->aspect_ratio_sar_height =
p_H264_Dpb->dpb_param.l.data[ASPECT_RATIO_SAR_HEIGHT];
p_H264_Dpb->fixed_frame_rate_flag = p_H264_Dpb->dpb_param.l.data[
FIXED_FRAME_RATE_FLAG];
p_H264_Dpb->num_units_in_tick =
p_H264_Dpb->dpb_param.l.data[NUM_UNITS_IN_TICK];
p_H264_Dpb->time_scale = p_H264_Dpb->dpb_param.l.data[TIME_SCALE] |
(p_H264_Dpb->dpb_param.l.data[TIME_SCALE + 1] << 16);
p_H264_Dpb->bitstream_restriction_flag =
(p_H264_Dpb->dpb_param.l.data[SPS_FLAGS2] >> 3) & 0x1;
p_H264_Dpb->num_reorder_frames =
p_H264_Dpb->dpb_param.l.data[NUM_REORDER_FRAMES];
p_H264_Dpb->max_dec_frame_buffering =
p_H264_Dpb->dpb_param.l.data[MAX_BUFFER_FRAME];
/**/
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s return\n", __func__);
}
static void decode_poc(struct VideoParameters *p_Vid, struct Slice *pSlice)
{
struct h264_dpb_stru *p_H264_Dpb = container_of(p_Vid,
struct h264_dpb_stru, mVideo);
struct SPSParameters *active_sps = p_Vid->active_sps;
int i;
/* for POC mode 0: */
unsigned int MaxPicOrderCntLsb = (1 <<
(active_sps->log2_max_pic_order_cnt_lsb_minus4 + 4));
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DEBUG_POC,
"%s:pic_order_cnt_type %d, idr_flag %d last_has_mmco_5 %d last_pic_bottom_field %d pic_order_cnt_lsb %d PrevPicOrderCntLsb %d\r\n",
__func__,
active_sps->pic_order_cnt_type,
pSlice->idr_flag,
p_Vid->last_has_mmco_5,
p_Vid->last_pic_bottom_field,
pSlice->pic_order_cnt_lsb,
p_Vid->PrevPicOrderCntLsb
);
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DEBUG_POC,
"%s:field_pic_flag %d, bottom_field_flag %d frame_num %d PreviousFrameNum %d PreviousFrameNumOffset %d ax_frame_num %d num_ref_frames_in_pic_order_cnt_cycle %d offset_for_non_ref_pic %d\r\n",
__func__,
pSlice->field_pic_flag,
pSlice->bottom_field_flag,
pSlice->frame_num,
p_Vid->PreviousFrameNum,
p_Vid->PreviousFrameNumOffset,
p_Vid->max_frame_num,
active_sps->num_ref_frames_in_pic_order_cnt_cycle,
active_sps->offset_for_non_ref_pic
);
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DEBUG_POC,
"%s: delta_pic_order_cnt %d %d nal_reference_idc %d\r\n",
__func__,
pSlice->delta_pic_order_cnt[0], pSlice->delta_pic_order_cnt[1],
pSlice->nal_reference_idc
);
switch (active_sps->pic_order_cnt_type) {
case 0: /* POC MODE 0 */
/* 1st */
if (pSlice->idr_flag) {
p_Vid->PrevPicOrderCntMsb = 0;
p_Vid->PrevPicOrderCntLsb = 0;
} else {
if (p_Vid->last_has_mmco_5) {
if (p_Vid->last_pic_bottom_field) {
p_Vid->PrevPicOrderCntMsb = 0;
p_Vid->PrevPicOrderCntLsb = 0;
} else {
p_Vid->PrevPicOrderCntMsb = 0;
p_Vid->PrevPicOrderCntLsb =
pSlice->toppoc;
}
}
}
/* Calculate the MSBs of current picture */
if (pSlice->pic_order_cnt_lsb < p_Vid->PrevPicOrderCntLsb &&
(p_Vid->PrevPicOrderCntLsb - pSlice->pic_order_cnt_lsb) >=
(MaxPicOrderCntLsb / 2))
pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb +
MaxPicOrderCntLsb;
else if (pSlice->pic_order_cnt_lsb >
p_Vid->PrevPicOrderCntLsb &&
(pSlice->pic_order_cnt_lsb -
p_Vid->PrevPicOrderCntLsb) >
(MaxPicOrderCntLsb / 2))
pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb -
MaxPicOrderCntLsb;
else
pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb;
/* 2nd */
if (pSlice->field_pic_flag == 0) {
/* frame pix */
pSlice->toppoc = pSlice->PicOrderCntMsb +
pSlice->pic_order_cnt_lsb;
pSlice->bottompoc = pSlice->toppoc +
pSlice->delta_pic_order_cnt_bottom;
pSlice->ThisPOC = pSlice->framepoc =
(pSlice->toppoc < pSlice->bottompoc) ?
pSlice->toppoc : pSlice->bottompoc;
/* POC200301 */
} else if (pSlice->bottom_field_flag == FALSE) {
/* top field */
pSlice->ThisPOC = pSlice->toppoc =
pSlice->PicOrderCntMsb +
pSlice->pic_order_cnt_lsb;
} else {
/* bottom field */
pSlice->ThisPOC = pSlice->bottompoc =
pSlice->PicOrderCntMsb +
pSlice->pic_order_cnt_lsb;
}
pSlice->framepoc = pSlice->ThisPOC;
p_Vid->ThisPOC = pSlice->ThisPOC;
/* if ( pSlice->frame_num != p_Vid->PreviousFrameNum)
* Seems redundant
*/
p_Vid->PreviousFrameNum = pSlice->frame_num;
if (pSlice->nal_reference_idc) {
p_Vid->PrevPicOrderCntLsb = pSlice->pic_order_cnt_lsb;
p_Vid->PrevPicOrderCntMsb = pSlice->PicOrderCntMsb;
}
break;
case 1: /* POC MODE 1 */
/* 1st */
if (pSlice->idr_flag) {
p_Vid->FrameNumOffset = 0; /* first pix of IDRGOP */
if (pSlice->frame_num)
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"frame_num not equal to zero in IDR picture %d",
-1020);
} else {
if (p_Vid->last_has_mmco_5) {
p_Vid->PreviousFrameNumOffset = 0;
p_Vid->PreviousFrameNum = 0;
}
if (pSlice->frame_num < p_Vid->PreviousFrameNum) {
/* not first pix of IDRGOP */
p_Vid->FrameNumOffset =
p_Vid->PreviousFrameNumOffset +
p_Vid->max_frame_num;
} else {
p_Vid->FrameNumOffset =
p_Vid->PreviousFrameNumOffset;
}
}
/* 2nd */
if (active_sps->num_ref_frames_in_pic_order_cnt_cycle)
pSlice->AbsFrameNum =
p_Vid->FrameNumOffset + pSlice->frame_num;
else
pSlice->AbsFrameNum = 0;
if ((!pSlice->nal_reference_idc) && pSlice->AbsFrameNum > 0)
pSlice->AbsFrameNum--;
/* 3rd */
p_Vid->ExpectedDeltaPerPicOrderCntCycle = 0;
if (active_sps->num_ref_frames_in_pic_order_cnt_cycle)
for (i = 0; i < (int) active_sps->
num_ref_frames_in_pic_order_cnt_cycle; i++) {
p_Vid->ExpectedDeltaPerPicOrderCntCycle +=
active_sps->offset_for_ref_frame[i];
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DEBUG_POC,
"%s: offset_for_ref_frame %d\r\n",
__func__,
active_sps->
offset_for_ref_frame[i]);
}
if (pSlice->AbsFrameNum) {
p_Vid->PicOrderCntCycleCnt =
(pSlice->AbsFrameNum - 1) /
active_sps->
num_ref_frames_in_pic_order_cnt_cycle;
p_Vid->FrameNumInPicOrderCntCycle =
(pSlice->AbsFrameNum - 1) %
active_sps->
num_ref_frames_in_pic_order_cnt_cycle;
p_Vid->ExpectedPicOrderCnt =
p_Vid->PicOrderCntCycleCnt *
p_Vid->ExpectedDeltaPerPicOrderCntCycle;
for (i = 0; i <= (int)p_Vid->
FrameNumInPicOrderCntCycle; i++) {
p_Vid->ExpectedPicOrderCnt +=
active_sps->offset_for_ref_frame[i];
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DEBUG_POC,
"%s: offset_for_ref_frame %d\r\n",
__func__,
active_sps->
offset_for_ref_frame[i]);
}
} else
p_Vid->ExpectedPicOrderCnt = 0;
if (!pSlice->nal_reference_idc)
p_Vid->ExpectedPicOrderCnt +=
active_sps->offset_for_non_ref_pic;
if (pSlice->field_pic_flag == 0) {
/* frame pix */
pSlice->toppoc = p_Vid->ExpectedPicOrderCnt +
pSlice->delta_pic_order_cnt[0];
pSlice->bottompoc = pSlice->toppoc +
active_sps->offset_for_top_to_bottom_field +
pSlice->delta_pic_order_cnt[1];
pSlice->ThisPOC = pSlice->framepoc =
(pSlice->toppoc < pSlice->bottompoc) ?
pSlice->toppoc : pSlice->bottompoc;
/* POC200301 */
} else if (pSlice->bottom_field_flag == FALSE) {
/* top field */
pSlice->ThisPOC = pSlice->toppoc =
p_Vid->ExpectedPicOrderCnt +
pSlice->delta_pic_order_cnt[0];
} else {
/* bottom field */
pSlice->ThisPOC = pSlice->bottompoc =
p_Vid->ExpectedPicOrderCnt +
active_sps->offset_for_top_to_bottom_field +
pSlice->delta_pic_order_cnt[0];
}
pSlice->framepoc = pSlice->ThisPOC;
p_Vid->PreviousFrameNum = pSlice->frame_num;
p_Vid->PreviousFrameNumOffset = p_Vid->FrameNumOffset;
break;
case 2: /* POC MODE 2 */
if (pSlice->idr_flag) { /* IDR picture */
p_Vid->FrameNumOffset = 0; /* first pix of IDRGOP */
pSlice->ThisPOC = pSlice->framepoc = pSlice->toppoc =
pSlice->bottompoc = 0;
if (pSlice->frame_num)
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"frame_num not equal to zero in IDR picture %d",
-1020);
} else {
if (p_Vid->last_has_mmco_5) {
p_Vid->PreviousFrameNum = 0;
p_Vid->PreviousFrameNumOffset = 0;
}
if (pSlice->frame_num < p_Vid->PreviousFrameNum)
p_Vid->FrameNumOffset =
p_Vid->PreviousFrameNumOffset +
p_Vid->max_frame_num;
else
p_Vid->FrameNumOffset =
p_Vid->PreviousFrameNumOffset;
pSlice->AbsFrameNum = p_Vid->FrameNumOffset +
pSlice->frame_num;
if (!pSlice->nal_reference_idc)
pSlice->ThisPOC =
(2 * pSlice->AbsFrameNum - 1);
else
pSlice->ThisPOC = (2 * pSlice->AbsFrameNum);
if (pSlice->field_pic_flag == 0)
pSlice->toppoc = pSlice->bottompoc =
pSlice->framepoc = pSlice->ThisPOC;
else if (pSlice->bottom_field_flag == FALSE)
pSlice->toppoc = pSlice->framepoc =
pSlice->ThisPOC;
else
pSlice->bottompoc = pSlice->framepoc =
pSlice->ThisPOC;
}
p_Vid->PreviousFrameNum = pSlice->frame_num;
p_Vid->PreviousFrameNumOffset = p_Vid->FrameNumOffset;
break;
default:
/* error must occurs */
/* assert( 1==0 ); */
break;
}
}
void fill_frame_num_gap(struct VideoParameters *p_Vid, struct Slice *currSlice)
{
struct h264_dpb_stru *p_H264_Dpb =
container_of(p_Vid, struct h264_dpb_stru, mVideo);
struct SPSParameters *active_sps = p_Vid->active_sps;
int CurrFrameNum;
int UnusedShortTermFrameNum;
struct StorablePicture *picture = NULL;
int tmp1 = currSlice->delta_pic_order_cnt[0];
int tmp2 = currSlice->delta_pic_order_cnt[1];
int ret;
currSlice->delta_pic_order_cnt[0] =
currSlice->delta_pic_order_cnt[1] = 0;
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"A gap in frame number is found, try to fill it.(pre_frame_num %d, max_frame_num %d\n",
p_Vid->pre_frame_num, p_Vid->max_frame_num
);
UnusedShortTermFrameNum = (p_Vid->pre_frame_num + 1)
% p_Vid->max_frame_num;
CurrFrameNum = currSlice->frame_num; /*p_Vid->frame_num;*/
while (CurrFrameNum != UnusedShortTermFrameNum) {
/*pr_err("CurrFrameNum = %d, UnusedShortTermFrameNum = %d\n", CurrFrameNum, UnusedShortTermFrameNum);*/
/*picture = alloc_storable_picture
*(p_Vid, FRAME, p_Vid->width,
*p_Vid->height,
*p_Vid->width_cr,
*p_Vid->height_cr, 1);
*/
picture = get_new_pic(p_H264_Dpb,
p_H264_Dpb->mSlice.structure,
/*p_Vid->width, p_Vid->height,
*p_Vid->width_cr,
p_Vid->height_cr,*/ 1);
if (picture == NULL) {
struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_ERROR,
"%s Error: get_new_pic return NULL\r\n",
__func__);
/*h264_debug_flag |= PRINT_FLAG_DUMP_DPB;*/
dump_dpb(p_Dpb, 0);
return;
}
picture->colocated_buf_index = -1;
picture->buf_spec_num = -1;
picture->buf_spec_is_alloced = 0;
picture->coded_frame = 1;
picture->pic_num = UnusedShortTermFrameNum;
picture->frame_num = UnusedShortTermFrameNum;
picture->non_existing = 1;
picture->is_output = 1;
picture->used_for_reference = 1;
picture->adaptive_ref_pic_buffering_flag = 0;
#if (MVC_EXTENSION_ENABLE)
picture->view_id = currSlice->view_id;
#endif
currSlice->frame_num = UnusedShortTermFrameNum;
if (active_sps->pic_order_cnt_type != 0) {
/*decode_poc(p_Vid, p_Vid->ppSliceList[0]);*/
decode_poc(&p_H264_Dpb->mVideo, &p_H264_Dpb->mSlice);
}
picture->top_poc = currSlice->toppoc;
picture->bottom_poc = currSlice->bottompoc;
picture->frame_poc = currSlice->framepoc;
picture->poc = currSlice->framepoc;
ret = store_picture_in_dpb(p_H264_Dpb, picture, 0);
if (ret == -1) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_ERROR,
"%s Error: store_picture_in_dpb failed, break\n",
__func__);
release_picture(p_H264_Dpb, picture);
bufmgr_force_recover(p_H264_Dpb);
return;
} else if (ret == -2)
release_picture(p_H264_Dpb, picture);
picture = NULL;
p_Vid->pre_frame_num = UnusedShortTermFrameNum;
UnusedShortTermFrameNum =
(UnusedShortTermFrameNum + 1) %
p_Vid->max_frame_num;
}
currSlice->delta_pic_order_cnt[0] = tmp1;
currSlice->delta_pic_order_cnt[1] = tmp2;
currSlice->frame_num = CurrFrameNum;
}
void dpb_init_global(struct h264_dpb_stru *p_H264_Dpb,
int id, int actual_dpb_size, int max_reference_size)
{
int i;
init_dummy_fs();
memset(&p_H264_Dpb->mDPB, 0, sizeof(struct DecodedPictureBuffer));
memset(&p_H264_Dpb->mSlice, 0, sizeof(struct Slice));
memset(&p_H264_Dpb->mVideo, 0, sizeof(struct VideoParameters));
memset(&p_H264_Dpb->mSPS, 0, sizeof(struct SPSParameters));
for (i = 0; i < DPB_SIZE_MAX; i++) {
memset(&(p_H264_Dpb->mFrameStore[i]), 0,
sizeof(struct FrameStore));
}
for (i = 0; i < MAX_PIC_BUF_NUM; i++) {
memset(&(p_H264_Dpb->m_PIC[i]), 0,
sizeof(struct StorablePicture));
p_H264_Dpb->m_PIC[i].index = i;
}
p_H264_Dpb->decoder_index = id;
/* make sure dpb_init_global
*can be called during decoding
*(in DECODE_STATE_IDLE or DECODE_STATE_READY state)
*/
p_H264_Dpb->mDPB.size = actual_dpb_size;
p_H264_Dpb->max_reference_size = max_reference_size;
p_H264_Dpb->poc_even_odd_flag = 0;
}
static void init_picture(struct h264_dpb_stru *p_H264_Dpb,
struct Slice *currSlice,
struct StorablePicture *dec_picture)
{
/* struct VideoParameters *p_Vid = &(p_H264_Dpb->mVideo); */
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s dec_picture %p\n", __func__, dec_picture);
dec_picture->top_poc = currSlice->toppoc;
dec_picture->bottom_poc = currSlice->bottompoc;
dec_picture->frame_poc = currSlice->framepoc;
switch (currSlice->structure) {
case TOP_FIELD: {
dec_picture->poc = currSlice->toppoc;
/* p_Vid->number *= 2; */
break;
}
case BOTTOM_FIELD: {
dec_picture->poc = currSlice->bottompoc;
/* p_Vid->number = p_Vid->number * 2 + 1; */
break;
}
case FRAME: {
dec_picture->poc = currSlice->framepoc;
break;
}
default:
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"p_Vid->structure not initialized %d\n", 235);
}
/* dec_picture->slice_type = p_Vid->type; */
dec_picture->used_for_reference = (currSlice->nal_reference_idc != 0);
dec_picture->idr_flag = currSlice->idr_flag;
dec_picture->no_output_of_prior_pics_flag =
currSlice->no_output_of_prior_pics_flag;
dec_picture->long_term_reference_flag =
currSlice->long_term_reference_flag;
#if 1
dec_picture->adaptive_ref_pic_buffering_flag =
currSlice->adaptive_ref_pic_buffering_flag;
dec_picture->dec_ref_pic_marking_buffer =
&currSlice->dec_ref_pic_marking_buffer[0];
#endif
/* currSlice->dec_ref_pic_marking_buffer = NULL; */
/* dec_picture->mb_aff_frame_flag = currSlice->mb_aff_frame_flag; */
/* dec_picture->PicWidthInMbs = p_Vid->PicWidthInMbs; */
/* p_Vid->get_mb_block_pos =
* dec_picture->mb_aff_frame_flag ? get_mb_block_pos_mbaff :
* get_mb_block_pos_normal;
*/
/* p_Vid->getNeighbour =
* dec_picture->mb_aff_frame_flag ? getAffNeighbour :
* getNonAffNeighbour;
*/
dec_picture->pic_num = currSlice->frame_num;
dec_picture->frame_num = currSlice->frame_num;
/* dec_picture->recovery_frame =
* (unsigned int) ((int) currSlice->frame_num ==
* p_Vid->recovery_frame_num);
*/
dec_picture->coded_frame = (currSlice->structure == FRAME);
/* dec_picture->chroma_format_idc = active_sps->chroma_format_idc; */
/* dec_picture->frame_mbs_only_flag =
* active_sps->frame_mbs_only_flag;
*/
/* dec_picture->frame_cropping_flag =
* active_sps->frame_cropping_flag;
*/
if ((currSlice->picture_structure_mmco & 0x3) == 3) {
dec_picture->mb_aff_frame_flag = 1;
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s, picture_structure_mmco is %x, set mb_aff_frame_flag to 1\n",
__func__,
currSlice->picture_structure_mmco);
}
if (currSlice->pic_struct < PIC_INVALID) {
dec_picture->pic_struct = currSlice->pic_struct;
} else {
dec_picture->pic_struct = PIC_INVALID;
}
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s pic_struct = %d\n", __func__, dec_picture->pic_struct);
}
void dump_pic(struct h264_dpb_stru *p_H264_Dpb)
{
int ii;
struct StorablePicture *pic;
for (ii = 0; ii < MAX_PIC_BUF_NUM; ii++) {
pic = &(p_H264_Dpb->m_PIC[ii]);
if (pic->is_used) {
dpb_print(p_H264_Dpb->decoder_index, 0,
"pic(%d,%d) poc %d is_used %d bufspec %d colbuf %d for_ref %d long_term %d pre_out %d output %d nonexist %d data_flag 0x%x\n",
ii, pic->index,
pic->poc,
pic->is_used,
pic->buf_spec_num,
pic->colocated_buf_index,
pic->used_for_reference,
pic->is_long_term,
pic->pre_output,
pic->is_output,
pic->non_existing,
pic->data_flag);
}
}
}
/*
static void is_pic_used_by_dpb(struct h264_dpb_stru *p_H264_Dpb,
struct StorablePicture *pic)
{
struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
unsigned i;
for (i = 0; i < p_Dpb->used_size; i++) {
if (p_Dpb->fs[i]->top_field == pic ||
p_Dpb->fs[i]->bottom_field == pic ||
p_Dpb->fs[i]->frame == pic
)
break;
}
if (i < p_Dpb->used_size)
return 1;
return 0;
}
*/
static struct StorablePicture *get_new_pic(struct h264_dpb_stru *p_H264_Dpb,
enum PictureStructure structure, unsigned char is_output)
{
struct StorablePicture *s = NULL;
struct StorablePicture *pic;
struct VideoParameters *p_Vid = &(p_H264_Dpb->mVideo);
/* recycle un-used pic */
int ii = 0;
for (ii = 0; ii < MAX_PIC_BUF_NUM; ii++) {
pic = &(p_H264_Dpb->m_PIC[ii]);
if (pic->is_used == 0) {
pic->is_used = 1;
s = pic;
break;
}
}
if (s) {
s->buf_spec_is_alloced = 0;
s->pic_num = 0;
s->frame_num = 0;
s->long_term_frame_idx = 0;
s->long_term_pic_num = 0;
s->used_for_reference = 0;
s->is_long_term = 0;
s->non_existing = 0;
s->is_output = 0;
s->pre_output = 0;
s->max_slice_id = 0;
s->data_flag &= ~(ERROR_FLAG | NODISP_FLAG);
#if (MVC_EXTENSION_ENABLE)
s->view_id = -1;
#endif
s->structure = structure;
#if 0
s->size_x = size_x;
s->size_y = size_y;
s->size_x_cr = size_x_cr;
s->size_y_cr = size_y_cr;
s->size_x_m1 = size_x - 1;
s->size_y_m1 = size_y - 1;
s->size_x_cr_m1 = size_x_cr - 1;
s->size_y_cr_m1 = size_y_cr - 1;
s->top_field = p_Vid->no_reference_picture;
s->bottom_field = p_Vid->no_reference_picture;
s->frame = p_Vid->no_reference_picture;
#endif
/* s->dec_ref_pic_marking_buffer = NULL; */
s->coded_frame = 0;
s->mb_aff_frame_flag = 0;
s->top_poc = s->bottom_poc = s->poc = 0;
s->seiHasTone_mapping = 0;
s->frame_mbs_only_flag = p_Vid->active_sps->frame_mbs_only_flag;
if (!p_Vid->active_sps->frame_mbs_only_flag &&
structure != FRAME) {
int i, j;
for (j = 0; j < MAX_NUM_SLICES; j++) {
for (i = 0; i < 2; i++) {
/* s->listX[j][i] =
*calloc(MAX_LIST_SIZE,
*sizeof (struct StorablePicture *));
*+1 for reordering ???
*if (NULL == s->listX[j][i])
*no_mem_exit("alloc_storable_picture:
*s->listX[i]");
*/
}
}
}
} else
p_H264_Dpb->buf_alloc_fail = 1;
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s %p\n", __func__, s);
return s;
}
static void free_picture(struct h264_dpb_stru *p_H264_Dpb,
struct StorablePicture *pic)
{
if (pic == NULL || pic->index < 0 ||
pic->index >= MAX_PIC_BUF_NUM)
return;
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s %p %d\n", __func__, pic, pic->index);
/* assert(pic->index<MAX_PIC_BUF_NUM); */
p_H264_Dpb->m_PIC[pic->index].is_used = 0;
}
static void gen_field_ref_ids(struct VideoParameters *p_Vid,
struct StorablePicture *p)
{
int i, j;
struct h264_dpb_stru *p_H264_Dpb = container_of(p_Vid,
struct h264_dpb_stru, mVideo);
/* ! Generate Frame parameters from field information. */
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s\n", __func__);
/* copy the list; */
for (j = 0; j < p_Vid->iSliceNumOfCurrPic; j++) {
if (p->listX[j][LIST_0]) {
p->listXsize[j][LIST_0] =
p_Vid->ppSliceList[j]->listXsize[LIST_0];
for (i = 0; i < p->listXsize[j][LIST_0]; i++)
p->listX[j][LIST_0][i] =
p_Vid->ppSliceList[j]->listX[LIST_0][i];
}
if (p->listX[j][LIST_1]) {
p->listXsize[j][LIST_1] =
p_Vid->ppSliceList[j]->listXsize[LIST_1];
for (i = 0; i < p->listXsize[j][LIST_1]; i++)
p->listX[j][LIST_1][i] =
p_Vid->ppSliceList[j]->listX[LIST_1][i];
}
}
}
static void init_dpb(struct h264_dpb_stru *p_H264_Dpb, int type)
{
unsigned int i;
struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo;
struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
struct SPSParameters *active_sps = &p_H264_Dpb->mSPS;
p_Vid->active_sps = active_sps;
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s\n", __func__);
p_Dpb->p_Vid = p_Vid;
if (p_Dpb->init_done) {
/* free_dpb(p_Dpb); */
if (p_Vid->no_reference_picture) {
free_picture(p_H264_Dpb, p_Vid->no_reference_picture);
p_Vid->no_reference_picture = NULL;
}
p_Dpb->init_done = 0;
}
/* p_Dpb->size = 10; //active_sps->max_dpb_size; //16;
* getDpbSize(p_Vid, active_sps) +
* p_Vid->p_Inp->dpb_plus[type==2? 1: 0];
* p_Dpb->size = active_sps->max_dpb_size; //16;
* getDpbSize(p_Vid, active_sps) +
* p_Vid->p_Inp->dpb_plus[type==2? 1: 0];
* p_Dpb->size initialzie in vh264.c
*/
p_Dpb->num_ref_frames = active_sps->num_ref_frames;
/* p_Dpb->num_ref_frames initialzie in vh264.c */
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s dpb_size is %d num_ref_frames = %d (%d)\n",
__func__, p_Dpb->size,
p_Dpb->num_ref_frames,
active_sps->num_ref_frames);
if (active_sps->num_ref_frames == 0xffff) {
dpb_print(p_H264_Dpb->decoder_index, 0,
"!!!Warning, num_ref_frames = %d is invalid\n",
active_sps->num_ref_frames);
}
#if 0
/* ??? */
#if (MVC_EXTENSION_ENABLE)
if ((unsigned int)active_sps->max_dec_frame_buffering <
active_sps->num_ref_frames) {
#else
if (p_Dpb->size < active_sps->num_ref_frames) {
#endif
error(
"DPB size at specified level is smaller than the specified number of reference frames. This is not allowed.\n",
1000);
}
#endif
p_Dpb->used_size = 0;
p_Dpb->last_picture = NULL;
p_Dpb->ref_frames_in_buffer = 0;
p_Dpb->ltref_frames_in_buffer = 0;
#if 0
p_Dpb->fs = calloc(p_Dpb->size, sizeof(struct FrameStore *));
if (NULL == p_Dpb->fs)
no_mem_exit("init_dpb: p_Dpb->fs");
p_Dpb->fs_ref = calloc(p_Dpb->size, sizeof(struct FrameStore *));
if (NULL == p_Dpb->fs_ref)
no_mem_exit("init_dpb: p_Dpb->fs_ref");
p_Dpb->fs_ltref = calloc(p_Dpb->size, sizeof(struct FrameStore *));
if (NULL == p_Dpb->fs_ltref)
no_mem_exit("init_dpb: p_Dpb->fs_ltref");
#endif
#if (MVC_EXTENSION_ENABLE)
p_Dpb->fs_ilref = calloc(1, sizeof(struct FrameStore *));
if (NULL == p_Dpb->fs_ilref)
no_mem_exit("init_dpb: p_Dpb->fs_ilref");
#endif
for (i = 0; i < p_Dpb->size; i++) {
p_Dpb->fs[i] = &(p_H264_Dpb->mFrameStore[i]);
/* alloc_frame_store(); */
p_Dpb->fs[i]->index = i;
p_Dpb->fs_ref[i] = NULL;
p_Dpb->fs_ltref[i] = NULL;
p_Dpb->fs[i]->layer_id = 0; /* MVC_INIT_VIEW_ID; */
#if (MVC_EXTENSION_ENABLE)
p_Dpb->fs[i]->view_id = MVC_INIT_VIEW_ID;
p_Dpb->fs[i]->inter_view_flag[0] =
p_Dpb->fs[i]->inter_view_flag[1] = 0;
p_Dpb->fs[i]->anchor_pic_flag[0] =
p_Dpb->fs[i]->anchor_pic_flag[1] = 0;
#endif
}
#if (MVC_EXTENSION_ENABLE)
if (type == 2) {
p_Dpb->fs_ilref[0] = alloc_frame_store();
/* These may need some cleanups */
p_Dpb->fs_ilref[0]->view_id = MVC_INIT_VIEW_ID;
p_Dpb->fs_ilref[0]->inter_view_flag[0] =
p_Dpb->fs_ilref[0]->inter_view_flag[1] = 0;
p_Dpb->fs_ilref[0]->anchor_pic_flag[0] =
p_Dpb->fs_ilref[0]->anchor_pic_flag[1] = 0;
/* given that this is in a different buffer,
* do we even need proc_flag anymore?
*/
} else
p_Dpb->fs_ilref[0] = NULL;
#endif
/*
*for (i = 0; i < 6; i++)
*{
*currSlice->listX[i] =
* calloc(MAX_LIST_SIZE, sizeof (struct StorablePicture *));
* +1 for reordering
*if (NULL == currSlice->listX[i])
*no_mem_exit("init_dpb: currSlice->listX[i]");
*}
*/
/* allocate a dummy storable picture */
if (!p_Vid->no_reference_picture) {
p_Vid->no_reference_picture = get_new_pic(p_H264_Dpb,
FRAME,
/*p_Vid->width, p_Vid->height,
*p_Vid->width_cr, p_Vid->height_cr,
*/
1);
p_Vid->no_reference_picture->top_field =
p_Vid->no_reference_picture;
p_Vid->no_reference_picture->bottom_field =
p_Vid->no_reference_picture;
p_Vid->no_reference_picture->frame =
p_Vid->no_reference_picture;
}
p_Dpb->last_output_poc = INT_MIN;
#if (MVC_EXTENSION_ENABLE)
p_Dpb->last_output_view_id = -1;
#endif
p_Vid->last_has_mmco_5 = 0;
init_colocate_buf(p_H264_Dpb, p_H264_Dpb->max_reference_size);
p_Dpb->init_done = 1;
#if 0
/* ??? */
/* picture error concealment */
if (p_Vid->conceal_mode != 0 && !p_Vid->last_out_fs)
p_Vid->last_out_fs = alloc_frame_store();
#endif
}
static void dpb_split_field(struct h264_dpb_stru *p_H264_Dpb,
struct FrameStore *fs)
{
struct StorablePicture *fs_top = NULL, *fs_btm = NULL;
struct StorablePicture *frame = fs->frame;
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s %p %p\n", __func__, fs, frame);
fs->poc = frame->poc;
if (!frame->frame_mbs_only_flag) {
fs_top = fs->top_field = get_new_pic(p_H264_Dpb,
TOP_FIELD,
/* frame->size_x, frame->size_y,
*frame->size_x_cr, frame->size_y_cr,
*/
1);
fs_btm = fs->bottom_field = get_new_pic(p_H264_Dpb,
BOTTOM_FIELD,
/*frame->size_x, frame->size_y,
*frame->size_x_cr, frame->size_y_cr,
*/
1);
if (fs_top == NULL || fs_btm == NULL)
return;
#if 1
/* rain */
fs_top->buf_spec_num = frame->buf_spec_num;
fs_btm->buf_spec_num = frame->buf_spec_num;
fs_top->colocated_buf_index = frame->colocated_buf_index;
fs_btm->colocated_buf_index = frame->colocated_buf_index;
fs_top->data_flag = frame->data_flag;
fs_btm->data_flag = frame->data_flag;
#endif
fs_top->poc = frame->top_poc;
fs_btm->poc = frame->bottom_poc;
#if (MVC_EXTENSION_ENABLE)
fs_top->view_id = frame->view_id;
fs_btm->view_id = frame->view_id;
#endif
fs_top->frame_poc = frame->frame_poc;
fs_top->bottom_poc = fs_btm->bottom_poc = frame->bottom_poc;
fs_top->top_poc = fs_btm->top_poc = frame->top_poc;
fs_btm->frame_poc = frame->frame_poc;
fs_top->used_for_reference = fs_btm->used_for_reference
= frame->used_for_reference;
fs_top->is_long_term = fs_btm->is_long_term
= frame->is_long_term;
fs->long_term_frame_idx = fs_top->long_term_frame_idx
= fs_btm->long_term_frame_idx
= frame->long_term_frame_idx;
fs_top->coded_frame = fs_btm->coded_frame = 1;
fs_top->mb_aff_frame_flag = fs_btm->mb_aff_frame_flag
= frame->mb_aff_frame_flag;
frame->top_field = fs_top;
frame->bottom_field = fs_btm;
frame->frame = frame;
fs_top->bottom_field = fs_btm;
fs_top->frame = frame;
fs_top->top_field = fs_top;
fs_btm->top_field = fs_top;
fs_btm->frame = frame;
fs_btm->bottom_field = fs_btm;
#if (MVC_EXTENSION_ENABLE)
fs_top->view_id = fs_btm->view_id = fs->view_id;
fs_top->inter_view_flag = fs->inter_view_flag[0];
fs_btm->inter_view_flag = fs->inter_view_flag[1];
#endif
fs_top->chroma_format_idc = fs_btm->chroma_format_idc =
frame->chroma_format_idc;
fs_top->iCodingType = fs_btm->iCodingType = frame->iCodingType;
} else {
fs->top_field = NULL;
fs->bottom_field = NULL;
frame->top_field = NULL;
frame->bottom_field = NULL;
frame->frame = frame;
}
}
static void dpb_combine_field(struct h264_dpb_stru *p_H264_Dpb,
struct FrameStore *fs)
{
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s\n", __func__);
if (!fs->frame) {
fs->frame = get_new_pic(p_H264_Dpb,
FRAME,
/* fs->top_field->size_x, fs->top_field->size_y*2,
*fs->top_field->size_x_cr, fs->top_field->size_y_cr*2,
*/
1);
}
if (!fs->frame)
return;
#if 1
/* rain */
fs->frame->buf_spec_num = fs->top_field->buf_spec_num;
fs->frame->colocated_buf_index = fs->top_field->colocated_buf_index;
fs->frame->data_flag = fs->top_field->data_flag;
fs->frame->slice_type = fs->top_field->slice_type;
if (fs->bottom_field)
fs->frame->data_flag |= (fs->bottom_field->data_flag & 0xf0);
#endif
if (fs->bottom_field) {
fs->poc = fs->frame->poc = fs->frame->frame_poc = imin(
fs->top_field->poc, fs->bottom_field->poc);
fs->bottom_field->frame_poc = fs->top_field->frame_poc = fs->frame->poc;
fs->bottom_field->top_poc = fs->frame->top_poc = fs->top_field->poc;
fs->top_field->bottom_poc = fs->frame->bottom_poc =
fs->bottom_field->poc;
fs->frame->used_for_reference = (fs->top_field->used_for_reference &&
fs->bottom_field->used_for_reference);
fs->frame->is_long_term = (fs->top_field->is_long_term &&
fs->bottom_field->is_long_term);
}
if (fs->frame->is_long_term)
fs->frame->long_term_frame_idx = fs->long_term_frame_idx;
fs->frame->top_field = fs->top_field;
if (fs->bottom_field)
fs->frame->bottom_field = fs->bottom_field;
fs->frame->frame = fs->frame;
fs->frame->coded_frame = 0;
fs->frame->chroma_format_idc = fs->top_field->chroma_format_idc;
fs->frame->frame_cropping_flag = fs->top_field->frame_cropping_flag;
if (fs->frame->frame_cropping_flag) {
fs->frame->frame_crop_top_offset =
fs->top_field->frame_crop_top_offset;
fs->frame->frame_crop_bottom_offset =
fs->top_field->frame_crop_bottom_offset;
fs->frame->frame_crop_left_offset =
fs->top_field->frame_crop_left_offset;
fs->frame->frame_crop_right_offset =
fs->top_field->frame_crop_right_offset;
}
if (fs->bottom_field) {
fs->top_field->frame = fs->bottom_field->frame = fs->frame;
fs->top_field->top_field = fs->top_field;
fs->top_field->bottom_field = fs->bottom_field;
fs->bottom_field->top_field = fs->top_field;
fs->bottom_field->bottom_field = fs->bottom_field;
}
/**/
#if (MVC_EXTENSION_ENABLE)
fs->frame->view_id = fs->view_id;
#endif
fs->frame->iCodingType = fs->top_field->iCodingType;
if (fs->bottom_field && fs->top_field->poc < fs->bottom_field->poc) {
fs->pts = fs->top_field->pts;
fs->pts64 = fs->top_field->pts64;
/*SWPL-7105 fix */
if ((fs->frame->slice_type == B_SLICE)
&& (!fs->bottom_field->pts) &&(!fs->bottom_field->pts64)) {
fs->pts = 0;
fs->pts64 = 0;
}
fs->offset_delimiter = fs->top_field->offset_delimiter;
fs->decoded_frame_size = fs->top_field->pic_size + fs->bottom_field->pic_size;
} else if (fs->bottom_field) {
fs->pts = fs->bottom_field->pts;
fs->pts64 = fs->bottom_field->pts64;
fs->offset_delimiter = fs->bottom_field->offset_delimiter;
fs->decoded_frame_size = fs->top_field->pic_size + fs->bottom_field->pic_size;
}
/* FIELD_CODING ;*/
}
static void calculate_frame_no(struct VideoParameters *p_Vid,
struct StorablePicture *p)
{
#if 0
/* ??? */
InputParameters *p_Inp = p_Vid->p_Inp;
/* calculate frame number */
int psnrPOC = p_Vid->active_sps->mb_adaptive_frame_field_flag ?
p->poc / (p_Inp->poc_scale) : p->poc / (p_Inp->poc_scale);
if (psnrPOC == 0) { /* && p_Vid->psnr_number) */
p_Vid->idr_psnr_number =
p_Vid->g_nFrame * p_Vid->ref_poc_gap / (p_Inp->poc_scale);
}
p_Vid->psnr_number = imax(p_Vid->psnr_number,
p_Vid->idr_psnr_number + psnrPOC);
p_Vid->frame_no = p_Vid->idr_psnr_number + psnrPOC;
#endif
}
static void insert_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb,
struct FrameStore *fs,
struct StorablePicture *p,
unsigned char data_flag)
{
struct vdec_frames_s *mvfrm = p_H264_Dpb->vdec->mvfrm;
struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo;
/* InputParameters *p_Inp = p_Vid->p_Inp;
* dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
* "insert (%s) pic with frame_num #%d, poc %d\n",
* (p->structure == FRAME)?"FRAME":
* (p->structure == TOP_FIELD)?"TOP_FIELD":
* "BOTTOM_FIELD", p->pic_num, p->poc);
* assert (p!=NULL);
* assert (fs!=NULL);
*/
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s %p %p\n", __func__, fs, p);
p_H264_Dpb->dpb_frame_count++;
fs->dpb_frame_count = p_H264_Dpb->dpb_frame_count;
#if 1
/* rain */
/* p->buf_spec_num = fs->index; */
p->data_flag = data_flag;
fs->data_flag |= data_flag;
fs->buf_spec_num = p->buf_spec_num;
fs->colocated_buf_index = p->colocated_buf_index;
#endif
p->slice_type = p_H264_Dpb->mSlice.slice_type;
switch (p->structure) {
case FRAME:
fs->frame = p;
fs->is_used = 3;
fs->slice_type = p->slice_type;
fs->frame_size = p->frame_size;
fs->offset_delimiter = p->offset_delimiter;
fs->decoded_frame_size = p->pic_size;
if (p->used_for_reference) {
fs->is_reference = 3;
fs->is_orig_reference = 3;
if (p->is_long_term) {
fs->is_long_term = 3;
fs->long_term_frame_idx =
p->long_term_frame_idx;
}
}
fs->pts = p->pts;
fs->pts64 = p->pts64;
fs->layer_id = p->layer_id;
#if (MVC_EXTENSION_ENABLE)
fs->view_id = p->view_id;
fs->inter_view_flag[0] = fs->inter_view_flag[1] =
p->inter_view_flag;
fs->anchor_pic_flag[0] = fs->anchor_pic_flag[1] =
p->anchor_pic_flag;
#endif
/* generate field views */
/* return; */
dpb_split_field(p_H264_Dpb, fs);
/* return; */
break;
case TOP_FIELD:
fs->top_field = p;
fs->is_used |= 1;
fs->layer_id = p->layer_id;
if (fs->frame_size == 0) {
fs->slice_type = p->slice_type;
// fs->pts = p->pts;
// fs->pts64 = p->pts64;
}
fs->frame_size += p->frame_size;
#if (MVC_EXTENSION_ENABLE)
fs->view_id = p->view_id;
fs->inter_view_flag[0] = p->inter_view_flag;
fs->anchor_pic_flag[0] = p->anchor_pic_flag;
#endif
if (p->used_for_reference) {
fs->is_reference |= 1;
fs->is_orig_reference |= 1;
if (p->is_long_term) {
fs->is_long_term |= 1;
fs->long_term_frame_idx =
p->long_term_frame_idx;
}
}
if (fs->is_used == 3) {
/* generate frame view */
dpb_combine_field(p_H264_Dpb, fs);
} else {
fs->poc = p->poc;
}
gen_field_ref_ids(p_Vid, p);
break;
case BOTTOM_FIELD:
fs->bottom_field = p;
fs->is_used |= 2;
fs->layer_id = p->layer_id;
if (fs->frame_size == 0) {
fs->slice_type = p->slice_type;
// fs->pts = p->pts;
// fs->pts64 = p->pts64;
}
fs->frame_size += p->frame_size;
#if (MVC_EXTENSION_ENABLE)
fs->view_id = p->view_id;
fs->inter_view_flag[1] = p->inter_view_flag;
fs->anchor_pic_flag[1] = p->anchor_pic_flag;
#endif
if (p->used_for_reference) {
fs->is_reference |= 2;
fs->is_orig_reference |= 2;
if (p->is_long_term) {
fs->is_long_term |= 2;
fs->long_term_frame_idx =
p->long_term_frame_idx;
}
}
if (fs->is_used == 3) {
/* generate frame view */
dpb_combine_field(p_H264_Dpb, fs);
} else {
fs->poc = p->poc;
}
gen_field_ref_ids(p_Vid, p);
break;
}
fs->frame_num = p->pic_num;
fs->recovery_frame = p->recovery_frame;
fs->is_output = p->is_output;
fs->pre_output = p->pre_output;
/* picture qos infomation*/
fs->max_mv = p->max_mv;
fs->avg_mv = p->avg_mv;
fs->min_mv = p->min_mv;
fs->max_qp = p->max_qp;
fs->avg_qp = p->avg_qp;
fs->min_qp = p->min_qp;
fs->max_skip = p->max_skip;
fs->avg_skip = p->avg_skip;
fs->min_skip = p->min_skip;
if (fs->is_used == 3) {
calculate_frame_no(p_Vid, p);
#if 0
/* ??? */
if (-1 != p_Vid->p_ref && !p_Inp->silent)
find_snr(p_Vid, fs->frame, &p_Vid->p_ref);
#endif
//fs->pts = p->pts;
//fs->pts64 = p->pts64;
}
fs->timestamp = p->timestamp;
if (mvfrm) {
fs->frame_size2 = mvfrm->frame_size;
fs->hw_decode_time = mvfrm->hw_decode_time;
}
}
void reset_frame_store(struct h264_dpb_stru *p_H264_Dpb,
struct FrameStore *f)
{
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s\n", __func__);
if (f) {
if (f->frame) {
free_picture(p_H264_Dpb, f->frame);
f->frame = NULL;
}
if (f->top_field) {
free_picture(p_H264_Dpb, f->top_field);
f->top_field = NULL;
}
if (f->bottom_field) {
free_picture(p_H264_Dpb, f->bottom_field);
f->bottom_field = NULL;
}
/**/
f->is_used = 0;
f->is_reference = 0;
f->is_long_term = 0;
f->is_orig_reference = 0;
f->is_output = 0;
f->pre_output = 0;
f->show_frame = false;
f->frame = NULL;
f->top_field = NULL;
f->bottom_field = NULL;
/* free(f); */
}
}
void unmark_for_reference(struct DecodedPictureBuffer *p_Dpb,
struct FrameStore *fs)
{
struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
struct h264_dpb_stru, mDPB);
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s %p %p %p %p\n", __func__,
fs, fs->frame, fs->top_field, fs->bottom_field);
/* return; */
if (fs->is_used & 1) {
if (fs->top_field)
fs->top_field->used_for_reference = 0;
}
if (fs->is_used & 2) {
if (fs->bottom_field)
fs->bottom_field->used_for_reference = 0;
}
if (fs->is_used == 3) {
if (fs->top_field && fs->bottom_field) {
fs->top_field->used_for_reference = 0;
fs->bottom_field->used_for_reference = 0;
}
fs->frame->used_for_reference = 0;
}
fs->is_reference = 0;
}
int get_long_term_flag_by_buf_spec_num(struct h264_dpb_stru *p_H264_Dpb,
int buf_spec_num)
{
struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
unsigned int i;
for (i = 0; i < p_Dpb->used_size; i++) {
if (p_Dpb->fs[i]->buf_spec_num == buf_spec_num)
return p_Dpb->fs[i]->is_long_term;
}
return -1;
}
static void update_pic_num(struct h264_dpb_stru *p_H264_Dpb)
{
unsigned int i;
struct Slice *currSlice = &p_H264_Dpb->mSlice;
struct VideoParameters *p_Vid = currSlice->p_Vid;
struct DecodedPictureBuffer *p_Dpb = currSlice->p_Dpb;
struct SPSParameters *active_sps = p_Vid->active_sps;
int add_top = 0, add_bottom = 0;
int max_frame_num = 1 << (active_sps->log2_max_frame_num_minus4 + 4);
if (currSlice->structure == FRAME) {
for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
#ifdef ERROR_CHECK
if (p_Dpb->fs_ref[i] == NULL ||
p_Dpb->fs_ref[i]->frame == NULL) {
p_H264_Dpb->dpb_error_flag = __LINE__;
continue;
}
#endif
if (p_Dpb->fs_ref[i]->is_used == 3) {
if ((p_Dpb->fs_ref[i]->frame->
used_for_reference) &&
(!p_Dpb->fs_ref[i]->frame->
is_long_term)) {
if (p_Dpb->fs_ref[i]->frame_num >
currSlice->frame_num) {
p_Dpb->fs_ref[i]->
frame_num_wrap =
p_Dpb->fs_ref[i]->frame_num
- max_frame_num;
} else {
p_Dpb->fs_ref[i]->
frame_num_wrap =
p_Dpb->fs_ref[i]->frame_num;
}
p_Dpb->fs_ref[i]->frame->pic_num =
p_Dpb->fs_ref[i]->frame_num_wrap;
}
}
}
/* update long_term_pic_num */
for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
#ifdef ERROR_CHECK
if (p_Dpb->fs_ltref[i] == NULL ||
p_Dpb->fs_ltref[i]->frame == NULL) {
p_H264_Dpb->dpb_error_flag = __LINE__;
continue;
}
#endif
if (p_Dpb->fs_ltref[i]->is_used == 3) {
if (p_Dpb->fs_ltref[i]->frame->is_long_term) {
p_Dpb->fs_ltref[i]->frame->
long_term_pic_num =
p_Dpb->fs_ltref[i]->frame->
long_term_frame_idx;
}
}
}
} else {
if (currSlice->structure == TOP_FIELD) {
add_top = 1;
add_bottom = 0;
} else {
add_top = 0;
add_bottom = 1;
}
for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
#ifdef ERROR_CHECK
if (p_Dpb->fs_ref[i] == NULL) {
p_H264_Dpb->dpb_error_flag = __LINE__;
continue;
}
#endif
if (p_Dpb->fs_ref[i]->is_reference) {
if (p_Dpb->fs_ref[i]->frame_num > currSlice->
frame_num) {
p_Dpb->fs_ref[i]->frame_num_wrap =
p_Dpb->fs_ref[i]->frame_num -
max_frame_num;
} else {
p_Dpb->fs_ref[i]->frame_num_wrap =
p_Dpb->fs_ref[i]->frame_num;
}
if (p_Dpb->fs_ref[i]->is_reference & 1) {
#ifdef ERROR_CHECK
if (p_Dpb->fs_ref[i]->top_field
== NULL) {
p_H264_Dpb->dpb_error_flag =
__LINE__;
continue;
}
#endif
p_Dpb->fs_ref[i]->top_field->
pic_num = (2 * p_Dpb->fs_ref[i]->
frame_num_wrap) + add_top;
}
if (p_Dpb->fs_ref[i]->is_reference & 2) {
#ifdef ERROR_CHECK
if (p_Dpb->fs_ref[i]->bottom_field
== NULL) {
p_H264_Dpb->dpb_error_flag =
__LINE__;
continue;
}
#endif
p_Dpb->fs_ref[i]->bottom_field->
pic_num = (2 * p_Dpb->fs_ref[i]->
frame_num_wrap) + add_bottom;
}
}
}
/* update long_term_pic_num */
for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
#ifdef ERROR_CHECK
if (p_Dpb->fs_ltref[i] == NULL) {
p_H264_Dpb->dpb_error_flag = __LINE__;
continue;
}
#endif
if (p_Dpb->fs_ltref[i]->is_long_term & 1) {
#ifdef ERROR_CHECK
if (p_Dpb->fs_ltref[i]->top_field == NULL) {
p_H264_Dpb->dpb_error_flag = __LINE__;
continue;
}
#endif
p_Dpb->fs_ltref[i]->top_field->
long_term_pic_num = 2 *
p_Dpb->fs_ltref[i]->top_field->
long_term_frame_idx + add_top;
}
if (p_Dpb->fs_ltref[i]->is_long_term & 2) {
#ifdef ERROR_CHECK
if (p_Dpb->fs_ltref[i]->bottom_field == NULL) {
p_H264_Dpb->dpb_error_flag = __LINE__;
continue;
}
#endif
p_Dpb->fs_ltref[i]->bottom_field->
long_term_pic_num = 2 *
p_Dpb->fs_ltref[i]->bottom_field->
long_term_frame_idx + add_bottom;
}
}
}
}
static void remove_frame_from_dpb(struct h264_dpb_stru *p_H264_Dpb, int pos)
{
struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
struct FrameStore *fs = p_Dpb->fs[pos];
struct FrameStore *tmp;
unsigned int i;
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s pos %d %p\n", __func__, pos, fs);
/* dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
* "remove frame with frame_num #%d\n", fs->frame_num);
*/
switch (fs->is_used) {
case 3:
free_picture(p_H264_Dpb, fs->frame);
free_picture(p_H264_Dpb, fs->top_field);
free_picture(p_H264_Dpb, fs->bottom_field);
fs->frame = NULL;
fs->top_field = NULL;
fs->bottom_field = NULL;
break;
case 2:
free_picture(p_H264_Dpb, fs->bottom_field);
fs->bottom_field = NULL;
break;
case 1:
free_picture(p_H264_Dpb, fs->top_field);
fs->top_field = NULL;
break;
case 0:
break;
default:
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"invalid frame store type %x", 500);
}
fs->data_flag = 0;
fs->is_used = 0;
fs->is_long_term = 0;
fs->is_reference = 0;
fs->is_orig_reference = 0;
fs->frame_size = 0;
/* move empty framestore to end of buffer */
tmp = p_Dpb->fs[pos];
for (i = pos; i < p_Dpb->used_size - 1; i++)
p_Dpb->fs[i] = p_Dpb->fs[i + 1];
p_Dpb->fs[p_Dpb->used_size - 1] = tmp;
if (p_Dpb->used_size)
p_Dpb->used_size--;
}
static int is_used_for_reference(struct FrameStore *fs)
{
if (fs->is_reference)
return 1;
if (fs->is_used == 3) { /* frame */
if (fs->frame->used_for_reference)
return 1;
}
if (fs->is_used & 1) { /* top field */
if (fs->top_field) {
if (fs->top_field->used_for_reference)
return 1;
}
}
if (fs->is_used & 2) { /* bottom field */
if (fs->bottom_field) {
if (fs->bottom_field->used_for_reference)
return 1;
}
}
return 0;
}
static int remove_unused_frame_from_dpb(struct h264_dpb_stru *p_H264_Dpb)
{
unsigned int i;
struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
/* check for frames that were already output and no longer
* used for reference
*/
for (i = 0; i < p_Dpb->used_size; i++) {
if ((!is_used_for_reference(p_Dpb->fs[i])) &&
(p_Dpb->fs[i]->colocated_buf_index >= 0)) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"release_colocate_buf[%d] for fs[%d]\n",
p_Dpb->fs[i]->colocated_buf_index, i);
release_colocate_buf(p_H264_Dpb,
p_Dpb->fs[i]->colocated_buf_index); /* rain */
p_Dpb->fs[i]->colocated_buf_index = -1;
}
}
for (i = 0; i < p_Dpb->used_size; i++) {
if (p_Dpb->fs[i]->is_output &&
(!is_used_for_reference(p_Dpb->fs[i]))) {
release_buf_spec_num(p_H264_Dpb->vdec,
p_Dpb->fs[i]->buf_spec_num);
p_Dpb->fs[i]->buf_spec_num = -1;
remove_frame_from_dpb(p_H264_Dpb, i);
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "%s[%d]\n",
__func__, i);
return 1;
}
}
return 0;
}
static int unmark_one_error_out_frame(struct h264_dpb_stru *p_H264_Dpb)
{
int ret = 0;
unsigned i;
struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
for (i = 0; i < p_Dpb->used_size; i++) {
if (p_Dpb->fs[i]->is_output &&
((p_Dpb->fs[i]->data_flag & ERROR_FLAG) ||
(p_Dpb->fs[i]->data_flag & NULL_FLAG))
) {
unmark_for_reference(p_Dpb, p_Dpb->fs[i]);
ret = 1;
break;
}
}
return ret;
}
static int unmark_one_out_frame(struct h264_dpb_stru *p_H264_Dpb)
{
int ret = 0;
unsigned i;
struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
for (i = 0; i < p_Dpb->used_size; i++) {
if (p_Dpb->fs[i]->is_output) {
unmark_for_reference(p_Dpb, p_Dpb->fs[i]);
ret = 1;
}
}
return ret;
}
/*
force_flag,
1, remove one error buf (is_out is 1) if there is no un-used buf
2, remove one buf (is_out is 1) if there is no un-used buf
*/
void bufmgr_h264_remove_unused_frame(struct h264_dpb_stru *p_H264_Dpb,
u8 force_flag)
{
struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
int ret = 0;
unsigned char removed_flag = 0;
do {
ret = remove_unused_frame_from_dpb(p_H264_Dpb);
if (ret != 0)
removed_flag = 1;
} while (ret != 0);
if (removed_flag) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "%s\r\n", __func__);
dump_dpb(p_Dpb, 0);
} else if (force_flag == 2) {
if (unmark_one_out_frame(p_H264_Dpb)) {
dpb_print(p_H264_Dpb->decoder_index,
0, "%s, Warnning, force unmark one frame\r\n",
__func__);
update_ref_list(p_Dpb);
remove_unused_frame_from_dpb(p_H264_Dpb);
dump_dpb(p_Dpb, 0);
}
} else if (force_flag == 1) {
if (unmark_one_error_out_frame(p_H264_Dpb)) {
dpb_print(p_H264_Dpb->decoder_index,
0, "%s, unmark error frame\r\n",
__func__);
update_ref_list(p_Dpb);
remove_unused_frame_from_dpb(p_H264_Dpb);
dump_dpb(p_Dpb, 0);
}
}
}
#ifdef OUTPUT_BUFFER_IN_C
int is_there_unused_frame_from_dpb(struct DecodedPictureBuffer *p_Dpb)
{
unsigned int i;
/* check for frames that were already output and no longer
* used for reference
*/
for (i = 0; i < p_Dpb->used_size; i++) {
if (p_Dpb->fs[i]->is_output &&
(!is_used_for_reference(p_Dpb->fs[i]))) {
return 1;
}
}
return 0;
}
#endif
static void get_smallest_poc(struct DecodedPictureBuffer *p_Dpb, int *poc,
int *pos)
{
unsigned int i;
unsigned long flags;
struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
struct h264_dpb_stru, mDPB);
struct vdec_s *vdec= (struct vdec_s *)p_H264_Dpb->vdec;
void *p = vh264_get_bufspec_lock(vdec);
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "%s\n", __func__);
if (p_Dpb->used_size < 1) {
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"Cannot determine smallest POC, DPB empty. %d\n",
150);
}
*pos = -1;
*poc = INT_MAX;
if (p == NULL)
return;
spin_lock_irqsave(p, flags);
for (i = 0; i < p_Dpb->used_size; i++) {
#ifdef OUTPUT_BUFFER_IN_C
/* rain */
if ((*poc > p_Dpb->fs[i]->poc) &&
(!p_Dpb->fs[i]->is_output) &&
(!p_Dpb->fs[i]->pre_output)) {
#else
if ((*poc > p_Dpb->fs[i]->poc) && (!p_Dpb->fs[i]->is_output)) {
#endif
*poc = p_Dpb->fs[i]->poc;
*pos = i;
}
}
spin_unlock_irqrestore(p, flags);
}
int output_frames(struct h264_dpb_stru *p_H264_Dpb, unsigned char flush_flag)
{
int poc, pos;
struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
int i;
int none_displayed_num = 0;
unsigned char fast_output_flag = 0;
if (!flush_flag) {
for (i = 0; i < p_Dpb->used_size; i++) {
if ((!p_Dpb->fs[i]->is_output) &&
(!p_Dpb->fs[i]->pre_output) &&((p_Dpb->fs[i]->is_used == 3
||p_Dpb->fs[i]->data_flag & ERROR_FLAG ))) {
none_displayed_num++;
if ((p_H264_Dpb->first_insert_frame == FirstInsertFrm_IDLE ||
p_H264_Dpb->first_insert_frame == FirstInsertFrm_RESET)
&& (p_Dpb->fs[i]->is_used == 3)
&& (p_Dpb->last_output_poc == INT_MIN)) {
if (p_H264_Dpb->first_insert_frame == FirstInsertFrm_IDLE)
fast_output_flag = 1;
p_H264_Dpb->first_insert_frame = FirstInsertFrm_OUT;
p_H264_Dpb->first_output_poc = p_Dpb->fs[i]->poc;
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s first insert frame i %d poc %d frame_num %x\n",
__func__, i, p_Dpb->fs[i]->poc, p_Dpb->fs[i]->frame_num);
}
/*check poc even/odd*/
if (p_H264_Dpb->poc_even_odd_flag == 0 &&
p_H264_Dpb->decode_pic_count >= 3)
p_H264_Dpb->poc_even_odd_flag = 2;
if (p_Dpb->fs[i]->poc & 0x1)
p_H264_Dpb->poc_even_odd_flag = 1;
/**/
if ((p_H264_Dpb->fast_output_enable & 0x1) &&
(p_Dpb->fs[i]->data_flag & IDR_FLAG))
fast_output_flag = 1;
if ((p_H264_Dpb->fast_output_enable & 0x2) &&
((p_Dpb->fs[i]->poc -
p_Dpb->last_output_poc)
== 1))
fast_output_flag = 1;
if ((p_H264_Dpb->fast_output_enable & 0x4) &&
(p_H264_Dpb->poc_even_odd_flag == 2) &&
(p_Dpb->fs[i]->is_used == 3) &&
((p_Dpb->fs[i]->poc -
p_Dpb->last_output_poc)
== 2))
fast_output_flag = 1;
}
}
if (fast_output_flag)
;
else if (none_displayed_num <
p_H264_Dpb->reorder_output)
return 0;
}
get_smallest_poc(p_Dpb, &poc, &pos);
if (pos == -1)
return 0;
#if 0
if (is_used_for_reference(p_Dpb->fs[pos]))
return 0;
#endif
if (p_H264_Dpb->first_insert_frame == FirstInsertFrm_OUT) {
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s pos %d pos->poc %d first_output_poc %d \n",
__func__, pos, p_Dpb->fs[pos]->poc, p_H264_Dpb->first_output_poc);
if (p_Dpb->fs[pos]->poc < p_H264_Dpb->first_output_poc)
p_Dpb->fs[pos]->data_flag |= NODISP_FLAG;
else if (p_Dpb->last_output_poc != INT_MIN)
p_H264_Dpb->first_insert_frame = FirstInsertFrm_SKIPDONE;
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s first_insert_frame %d \n", __func__, p_H264_Dpb->first_insert_frame);
}
if (prepare_display_buf(p_H264_Dpb->vdec, p_Dpb->fs[pos]) >= 0) {
if (!p_H264_Dpb->without_display_mode)
p_Dpb->fs[pos]->pre_output = 1;
} else {
if (h264_debug_flag & PRINT_FLAG_DPB_DETAIL) {
dpb_print(p_H264_Dpb->decoder_index, 0,
"%s[%d] poc:%d last_output_poc:%d poc_even_odd_flag:%d\n",
__func__, pos, poc,
p_Dpb->last_output_poc,
p_H264_Dpb->poc_even_odd_flag);
dump_dpb(p_Dpb, 1);
}
return 0;
}
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s[%d] poc %d last_output_poc %d poc_even_odd_flag %d\n",
__func__, pos, poc,
p_Dpb->last_output_poc,
p_H264_Dpb->poc_even_odd_flag);
p_Dpb->last_output_poc = poc;
return 1;
}
void flush_dpb(struct h264_dpb_stru *p_H264_Dpb)
{
/* struct VideoParameters *p_Vid = p_Dpb->p_Vid; */
struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
unsigned int i;
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s\n", __func__);
/* diagnostics */
/* dpb_print(p_H264_Dpb->decoder_index,
*PRINT_FLAG_DPB_DETAIL,
*"Flush remaining frames from the dpb."
*"p_Dpb->size = %d, p_Dpb->used_size = %d\n",
*p_Dpb->size, p_Dpb->used_size);
*/
if (!p_Dpb->init_done)
return;
/* if(p_Vid->conceal_mode == 0) */
#if 0
/* ??? */
if (p_Vid->conceal_mode != 0)
conceal_non_ref_pics(p_Dpb, 0);
#endif
/* mark all frames unused */
for (i = 0; i < p_Dpb->used_size; i++) {
#if MVC_EXTENSION_ENABLE
assert(p_Dpb->fs[i]->view_id == p_Dpb->layer_id);
#endif
unmark_for_reference(p_Dpb, p_Dpb->fs[i]);
}
while (remove_unused_frame_from_dpb(p_H264_Dpb))
;
/* output frames in POC order */
while (output_frames(p_H264_Dpb, 1))
;
p_Dpb->last_output_poc = INT_MIN;
}
static int is_short_term_reference(struct DecodedPictureBuffer *p_Dpb,
struct FrameStore *fs)
{
struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
struct h264_dpb_stru, mDPB);
if (fs->is_used == 3) { /* frame */
if ((fs->frame->used_for_reference) &&
(!fs->frame->is_long_term)) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "[[%s 1]]",
__func__);
return 1;
}
}
if (fs->is_used & 1) { /* top field */
if (fs->top_field) {
if ((fs->top_field->used_for_reference) &&
(!fs->top_field->is_long_term)) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "[[%s 2]]",
__func__);
return 1;
}
}
}
if (fs->is_used & 2) { /* bottom field */
if (fs->bottom_field) {
if ((fs->bottom_field->used_for_reference) &&
(!fs->bottom_field->is_long_term)) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "[[%s 3]]",
__func__);
return 1;
}
}
}
return 0;
}
static int is_long_term_reference(struct FrameStore *fs)
{
if (fs->is_used == 3) { /* frame */
if ((fs->frame->used_for_reference) &&
(fs->frame->is_long_term)) {
return 1;
}
}
if (fs->is_used & 1) { /* top field */
if (fs->top_field) {
if ((fs->top_field->used_for_reference) &&
(fs->top_field->is_long_term)) {
return 1;
}
}
}
if (fs->is_used & 2) { /* bottom field */
if (fs->bottom_field) {
if ((fs->bottom_field->used_for_reference) &&
(fs->bottom_field->is_long_term)) {
return 1;
}
}
}
return 0;
}
void update_ref_list(struct DecodedPictureBuffer *p_Dpb)
{
unsigned int i, j;
struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
struct h264_dpb_stru, mDPB);
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s (%d, %d)\n", __func__, p_Dpb->size, p_Dpb->used_size);
for (i = 0, j = 0; i < p_Dpb->used_size; i++) {
#if 1
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"fs[%d]: fs %p frame %p is_reference %d %d %d\n",
i, p_Dpb->fs[i], p_Dpb->fs[i]->frame,
p_Dpb->fs[i]->frame != NULL ?
p_Dpb->fs[i]->frame->used_for_reference : 0,
p_Dpb->fs[i]->top_field != NULL ?
p_Dpb->fs[i]->top_field->used_for_reference :
0,
p_Dpb->fs[i]->bottom_field != NULL ?
p_Dpb->fs[i]->bottom_field->used_for_reference : 0);
#endif
if (is_short_term_reference(p_Dpb, p_Dpb->fs[i])) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"fs_ref[%d]=fs[%d]: fs %p\n", j, i, p_Dpb->fs[i]);
p_Dpb->fs_ref[j++] = p_Dpb->fs[i];
}
}
p_Dpb->ref_frames_in_buffer = j;
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s dpb size is %d, %d\n", __func__, p_Dpb->size, j);
while (j < p_Dpb->size) {
/* dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
*"fs_ref[%d]=null\n", j);
*/
p_Dpb->fs_ref[j++] = NULL;
}
#ifdef ERROR_CHECK
for (i = 0; i < DPB_SIZE_MAX; i++) {
if (p_Dpb->fs_ref[i] == NULL)
p_Dpb->fs_ref[i] = &dummy_fs;
}
#endif
}
static void update_ltref_list(struct DecodedPictureBuffer *p_Dpb)
{
unsigned int i, j;
struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
struct h264_dpb_stru, mDPB);
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s\n", __func__);
for (i = 0, j = 0; i < p_Dpb->used_size; i++) {
if (is_long_term_reference(p_Dpb->fs[i]))
p_Dpb->fs_ltref[j++] = p_Dpb->fs[i];
}
p_Dpb->ltref_frames_in_buffer = j;
while (j < p_Dpb->size)
p_Dpb->fs_ltref[j++] = NULL;
#ifdef ERROR_CHECK
for (i = 0; i < DPB_SIZE_MAX; i++) {
if (p_Dpb->fs_ltref[i] == NULL)
p_Dpb->fs_ltref[i] = &dummy_fs;
}
#endif
}
static void idr_memory_management(struct h264_dpb_stru *p_H264_Dpb,
struct StorablePicture *p)
{
struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s ref_frames_in_buffer %d ltref_frames_in_buffer %d\n",
__func__, p_Dpb->ref_frames_in_buffer,
p_Dpb->ltref_frames_in_buffer);
if (p->no_output_of_prior_pics_flag) {
#if 0
/*???*/
/* free all stored pictures */
int i;
for (i = 0; i < p_Dpb->used_size; i++) {
/* reset all reference settings
* free_frame_store(p_Dpb->fs[i]);
* p_Dpb->fs[i] = alloc_frame_store();
*/
reset_frame_store(p_H264_Dpb, p_Dpb->fs[i]); /* ??? */
}
for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++)
p_Dpb->fs_ref[i] = NULL;
for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++)
p_Dpb->fs_ltref[i] = NULL;
p_Dpb->used_size = 0;
#endif
} else {
flush_dpb(p_H264_Dpb);
}
p_Dpb->last_picture = NULL;
update_ref_list(p_Dpb);
update_ltref_list(p_Dpb);
p_Dpb->last_output_poc = INT_MIN;
if (p->long_term_reference_flag) {
p_Dpb->max_long_term_pic_idx = 0;
p->is_long_term = 1;
p->long_term_frame_idx = 0;
} else {
p_Dpb->max_long_term_pic_idx = -1;
p->is_long_term = 0;
}
#if (MVC_EXTENSION_ENABLE)
p_Dpb->last_output_view_id = -1;
#endif
}
static void sliding_window_memory_management(
struct DecodedPictureBuffer *p_Dpb,
struct StorablePicture *p)
{
unsigned int i;
struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
struct h264_dpb_stru, mDPB);
unsigned char slide_flag = 0;
unsigned int sliding_margin = imax(
1, p_Dpb->num_ref_frames) - p_Dpb->ltref_frames_in_buffer;
/* assert (!p->idr_flag); */
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s ref_frames_in_buffer %d ltref_frames_in_buffer %d\n",
__func__, p_Dpb->ref_frames_in_buffer,
p_Dpb->ltref_frames_in_buffer);
/* if this is a reference pic with sliding window,
unmark first ref frame */
if (p_Dpb->ref_frames_in_buffer == sliding_margin)
slide_flag = 1;
/*else if ((h264_error_proc_policy & 0x8) &&
(p_Dpb->ref_frames_in_buffer > sliding_margin))
slide_flag = 1;*/
if (slide_flag) {
for (i = 0; i < p_Dpb->used_size; i++) {
if (p_Dpb->fs[i]->is_reference &&
(!(p_Dpb->fs[i]->is_long_term))) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "unmark %d\n", i);
unmark_for_reference(p_Dpb, p_Dpb->fs[i]);
update_ref_list(p_Dpb);
break;
}
}
}
p->is_long_term = 0;
}
static void check_num_ref(struct DecodedPictureBuffer *p_Dpb)
{
if ((int)(p_Dpb->ltref_frames_in_buffer +
p_Dpb->ref_frames_in_buffer) >
imax(1, p_Dpb->num_ref_frames)) {
struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
struct h264_dpb_stru, mDPB);
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"Max. number of reference frames exceeded. Invalid stream. lt %d ref %d mum_ref %d\n",
p_Dpb->ltref_frames_in_buffer,
p_Dpb->ref_frames_in_buffer,
p_Dpb->num_ref_frames);
}
}
void dump_dpb(struct DecodedPictureBuffer *p_Dpb, u8 force)
{
unsigned i;
struct h264_dpb_stru *p_H264_Dpb =
container_of(p_Dpb, struct h264_dpb_stru, mDPB);
if ((h264_debug_flag & PRINT_FLAG_DUMP_DPB) == 0 &&
force == 0)
return;
for (i = 0; i < p_Dpb->used_size; i++) {
dpb_print(p_H264_Dpb->decoder_index,
0,
"(");
dpb_print_cont(p_H264_Dpb->decoder_index,
0,
"fn=%d is_used %d ",
p_Dpb->fs[i]->frame_num,
p_Dpb->fs[i]->is_used);
if (p_Dpb->fs[i]->is_used & 1) {
if (p_Dpb->fs[i]->top_field)
dpb_print_cont(p_H264_Dpb->decoder_index,
0,
"T: poc=%d pic_num=%d ",
p_Dpb->fs[i]->top_field->poc,
p_Dpb->fs[i]->top_field->pic_num);
else
dpb_print_cont(p_H264_Dpb->decoder_index,
0,
"T: poc=%d ",
p_Dpb->fs[i]->frame->top_poc);
}
if (p_Dpb->fs[i]->is_used & 2) {
if (p_Dpb->fs[i]->bottom_field)
dpb_print_cont(p_H264_Dpb->decoder_index,
0,
"B: poc=%d pic_num=%d ",
p_Dpb->fs[i]->bottom_field->poc,
p_Dpb->fs[i]->bottom_field->pic_num);
else
dpb_print_cont(p_H264_Dpb->decoder_index,
0,
"B: poc=%d ",
p_Dpb->fs[i]->frame->bottom_poc);
}
if (p_Dpb->fs[i]->is_used == 3) {
if (p_Dpb->fs[i]->frame != NULL)
dpb_print_cont(p_H264_Dpb->decoder_index,
0,
"F: poc=%d pic_num=%d ",
p_Dpb->fs[i]->frame->poc,
p_Dpb->fs[i]->frame->pic_num);
else
dpb_print_cont(p_H264_Dpb->decoder_index,
0, "fs[%d] frame is null ", i);
}
dpb_print_cont(p_H264_Dpb->decoder_index,
0,
"G: poc=%d) ", p_Dpb->fs[i]->poc);
if (p_Dpb->fs[i]->is_reference)
dpb_print_cont(p_H264_Dpb->decoder_index,
0,
"ref (%d) ", p_Dpb->fs[i]->is_reference);
if (p_Dpb->fs[i]->is_long_term)
dpb_print_cont(p_H264_Dpb->decoder_index,
0,
"lt_ref (%d) ", p_Dpb->fs[i]->is_reference);
if (p_Dpb->fs[i]->is_output)
dpb_print_cont(p_H264_Dpb->decoder_index,
0,
"out(displayed) ");
if (p_Dpb->fs[i]->pre_output)
dpb_print_cont(p_H264_Dpb->decoder_index,
0,
"pre_output(in dispq or displaying) ");
if (p_Dpb->fs[i]->is_used == 3) {
if (p_Dpb->fs[i]->frame != NULL && p_Dpb->fs[i]->frame->non_existing)
dpb_print_cont(p_H264_Dpb->decoder_index,
0,
"non_existing ");
else
dpb_print_cont(p_H264_Dpb->decoder_index,
0, "fs[%d] frame is null ", i);
}
dpb_print_cont(p_H264_Dpb->decoder_index,
0,
"dpb_frame_count %d ",
p_Dpb->fs[i]->dpb_frame_count);
#if (MVC_EXTENSION_ENABLE)
if (p_Dpb->fs[i]->is_reference)
dpb_print_cont(p_H264_Dpb->decoder_index,
0,
"view_id (%d) ", p_Dpb->fs[i]->view_id);
#endif
if (p_Dpb->fs[i]->data_flag) {
dpb_print_cont(p_H264_Dpb->decoder_index,
0,
"data_flag(0x%x)",
p_Dpb->fs[i]->data_flag);
}
dpb_print_cont(p_H264_Dpb->decoder_index,
0,
" bufspec %d\n",
p_Dpb->fs[i]->buf_spec_num);
}
}
/*!
************************************************************************
* \brief
* adaptive memory management
*
************************************************************************
*/
static int get_pic_num_x(struct StorablePicture *p,
int difference_of_pic_nums_minus1)
{
int currPicNum;
if (p->structure == FRAME)
currPicNum = p->frame_num;
else
currPicNum = 2 * p->frame_num + 1;
return currPicNum - (difference_of_pic_nums_minus1 + 1);
}
/*!
************************************************************************
* \brief
* Adaptive Memory Management: Mark short term picture unused
************************************************************************
*/
static void mm_unmark_short_term_for_reference(struct DecodedPictureBuffer
*p_Dpb, struct StorablePicture *p,
int difference_of_pic_nums_minus1)
{
struct h264_dpb_stru *p_H264_Dpb =
container_of(p_Dpb, struct h264_dpb_stru, mDPB);
int picNumX;
unsigned int i;
picNumX = get_pic_num_x(p, difference_of_pic_nums_minus1);
for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
#ifdef ERROR_CHECK
if (p_Dpb->fs_ref[i] == NULL) {
p_H264_Dpb->dpb_error_flag = __LINE__;
continue;
}
#endif
if (p->structure == FRAME) {
if ((p_Dpb->fs_ref[i]->is_reference == 3) &&
(p_Dpb->fs_ref[i]->is_long_term == 0)) {
#ifdef ERROR_CHECK
if (p_Dpb->fs_ref[i]->frame == NULL) {
p_H264_Dpb->dpb_error_flag = __LINE__;
continue;
}
#endif
if (p_Dpb->fs_ref[i]->frame->pic_num ==
picNumX) {
unmark_for_reference(p_Dpb,
p_Dpb->fs_ref[i]);
return;
}
}
} else {
if ((p_Dpb->fs_ref[i]->is_reference & 1) &&
(!(p_Dpb->fs_ref[i]->is_long_term & 1))) {
#ifdef ERROR_CHECK
if (p_Dpb->fs_ref[i]->top_field == NULL) {
p_H264_Dpb->dpb_error_flag = __LINE__;
continue;
}
#endif
if (p_Dpb->fs_ref[i]->top_field->pic_num ==
picNumX) {
p_Dpb->fs_ref[i]->
top_field->used_for_reference = 0;
p_Dpb->fs_ref[i]->is_reference &= 2;
if ((p_Dpb->fs_ref[i]->is_used == 3)
#ifdef ERROR_CHECK
&& p_Dpb->fs_ref[i]->frame
#endif
) {
p_Dpb->fs_ref[i]->frame->
used_for_reference = 0;
}
return;
}
}
if ((p_Dpb->fs_ref[i]->is_reference & 2) &&
(!(p_Dpb->fs_ref[i]->is_long_term & 2))) {
#ifdef ERROR_CHECK
if (p_Dpb->fs_ref[i]->bottom_field == NULL) {
p_H264_Dpb->dpb_error_flag = __LINE__;
continue;
}
#endif
if (p_Dpb->fs_ref[i]->bottom_field->pic_num ==
picNumX) {
p_Dpb->fs_ref[i]->bottom_field->
used_for_reference = 0;
p_Dpb->fs_ref[i]->is_reference &= 1;
if ((p_Dpb->fs_ref[i]->is_used == 3)
#ifdef ERROR_CHECK
&& p_Dpb->fs_ref[i]->frame
#endif
) {
p_Dpb->fs_ref[i]->frame->
used_for_reference = 0;
}
return;
}
}
}
}
}
static void unmark_for_long_term_reference(struct FrameStore *fs)
{
if (fs->is_used & 1) {
if (fs->top_field) {
fs->top_field->used_for_reference = 0;
fs->top_field->is_long_term = 0;
}
}
if (fs->is_used & 2) {
if (fs->bottom_field) {
fs->bottom_field->used_for_reference = 0;
fs->bottom_field->is_long_term = 0;
}
}
if (fs->is_used == 3) {
if (fs->top_field && fs->bottom_field) {
fs->top_field->used_for_reference = 0;
fs->top_field->is_long_term = 0;
fs->bottom_field->used_for_reference = 0;
fs->bottom_field->is_long_term = 0;
}
fs->frame->used_for_reference = 0;
fs->frame->is_long_term = 0;
}
fs->is_reference = 0;
fs->is_long_term = 0;
}
/*!
************************************************************************
* \brief
* Adaptive Memory Management: Mark long term picture unused
************************************************************************
*/
static void mm_unmark_long_term_for_reference(struct DecodedPictureBuffer
*p_Dpb, struct StorablePicture *p, int long_term_pic_num)
{
unsigned int i;
for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
if (p->structure == FRAME) {
if ((p_Dpb->fs_ltref[i]->is_reference == 3) &&
(p_Dpb->