blob: 8ab097e5a26f6b51d6e46314660ba1f567652d33 [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 "../../decoder/utils/vdec.h"
#include "../../decoder/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 = kzalloc(512, GFP_ATOMIC);
int len = 0;
va_list args;
if (!buf)
return 0;
va_start(args, fmt);
len = sprintf(buf, "%d: ", index);
vsnprintf(buf + len, 512-len, fmt, args);
pr_debug("%s", buf);
va_end(args);
kfree(buf);
}
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 = kzalloc(512, GFP_ATOMIC);
int len = 0;
va_list args;
if (!buf)
return 0;
va_start(args, fmt);
vsnprintf(buf + len, 512-len, fmt, args);
pr_info("%s", buf);
va_end(args);
kfree(buf);
}
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);
p_H264_Dpb->long_term_reference_flag = pSlice->long_term_reference_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 == 0) {
/* 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 == 0) {
/* 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 == 0)
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;
}
if ((fs->frame != NULL) &&
((fs->bottom_field != NULL) || (fs->top_field != NULL))) {
fs->last_field_timestamp = fs->timestamp;
fs->timestamp = p->timestamp;
} else {
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;
}
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;
}
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--;
}
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;
/*
* When the sei data(dv data) after the PIC done and no flush,
* it is necessary to output a frame of data until
* the number of frames not displayed is greater than the reorder.
*/
if ((p_H264_Dpb->wait_aux_data_flag) && (!flush_flag)) {
int no_output_num = 0;
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)))
no_output_num++;
}
if (no_output_num <= p_H264_Dpb->reorder_output)
return 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]->show_frame != false)
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) {
int i;
for (i = 0; i < p_Dpb->used_size; i++) {
unmark_for_reference(p_Dpb, p_Dpb->fs[i]);
if (p_Dpb->fs[i]->is_long_term)
unmark_for_long_term_reference(p_Dpb->fs[i]);
if (!p_Dpb->fs[i]->is_output && !p_Dpb->fs[i]->pre_output)
set_frame_output_flag(p_H264_Dpb, i);
}
#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 int i;
unsigned char *buf = NULL;
unsigned int buf_size = 512, len = 0;
struct h264_dpb_stru *p_H264_Dpb =
container_of(p_Dpb, struct h264_dpb_stru, mDPB);
#define DPB_STRCAT(args...) do { \
len += snprintf(buf + len, \
buf_size - len, ##args);\
} while (0)
if ((h264_debug_flag & PRINT_FLAG_DUMP_DPB) == 0 &&
force == 0)
return;
buf = kzalloc(buf_size, GFP_ATOMIC);
if (buf == NULL)
return;
for (i = 0; i < p_Dpb->used_size; i++) {
len = 0;
memset(buf, 0, buf_size);
DPB_STRCAT("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_STRCAT("T: poc=%d pic_num=%d ",
p_Dpb->fs[i]->top_field->poc,
p_Dpb->fs[i]->top_field->pic_num);
else
DPB_STRCAT("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_STRCAT("B: poc=%d pic_num=%d ",
p_Dpb->fs[i]->bottom_field->poc,
p_Dpb->fs[i]->bottom_field->pic_num);
else
DPB_STRCAT("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_STRCAT("F: poc=%d pic_num=%d ",
p_Dpb->fs[i]->frame->poc,
p_Dpb->fs[i]->frame->pic_num);
else
DPB_STRCAT("fs[%d] frame is null ", i);
}
DPB_STRCAT("G: poc=%d) ", p_Dpb->fs[i]->poc);
if (p_Dpb->fs[i]->is_reference)
DPB_STRCAT("ref (%d) ", p_Dpb->fs[i]->is_reference);
if (p_Dpb->fs[i]->is_long_term)
DPB_STRCAT("lt_ref (%d) ", p_Dpb->fs[i]->is_reference);
if (p_Dpb->fs[i]->is_output)
DPB_STRCAT("out(displayed) ");
if (p_Dpb->fs[i]->pre_output)
DPB_STRCAT("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_STRCAT("non_existing ");
else
DPB_STRCAT("fs[%d] frame is null ", i);
}
DPB_STRCAT("dpb_frame_count %d ",
p_Dpb->fs[i]->dpb_frame_count);
#if (MVC_EXTENSION_ENABLE)
if (p_Dpb->fs[i]->is_reference)
DPB_STRCAT("view_id (%d) ", p_Dpb->fs[i]->view_id);
#endif
if (p_Dpb->fs[i]->data_flag) {
DPB_STRCAT("data_flag(0x%x)",
p_Dpb->fs[i]->data_flag);
}
DPB_STRCAT(" bufspec %d\n",
p_Dpb->fs[i]->buf_spec_num);
dpb_print(p_H264_Dpb->decoder_index, 0, "%s", buf);
}
kfree(buf);
}
/*!
************************************************************************
* \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;
}
}
}
}
}
/*!
************************************************************************
* \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->fs_ltref[i]->is_long_term == 3)) {
if (p_Dpb->fs_ltref[i]->frame->
long_term_pic_num ==
long_term_pic_num) {
unmark_for_long_term_reference(
p_Dpb->fs_ltref[i]);
}
}
} else {
if ((p_Dpb->fs_ltref[i]->is_reference & 1) &&
((p_Dpb->fs_ltref[i]->is_long_term & 1))) {
if (p_Dpb->fs_ltref[i]->top_field->
long_term_pic_num ==
long_term_pic_num) {
p_Dpb->fs_ltref[i]->top_field->
used_for_reference = 0;
p_Dpb->fs_ltref[i]->top_field->
is_long_term = 0;
p_Dpb->fs_ltref[i]->is_reference &= 2;
p_Dpb->fs_ltref[i]->is_long_term &= 2;
if (p_Dpb->fs_ltref[i]->is_used == 3) {
p_Dpb->fs_ltref[i]->frame->
used_for_reference = 0;
p_Dpb->fs_ltref[i]->frame->
is_long_term = 0;
}
return;
}
}
if ((p_Dpb->fs_ltref[i]->is_reference & 2) &&
((p_Dpb->fs_ltref[i]->is_long_term & 2))) {
if (p_Dpb->fs_ltref[i]->bottom_field->
long_term_pic_num ==
long_term_pic_num) {
p_Dpb->fs_ltref[i]->bottom_field->
used_for_reference = 0;
p_Dpb->fs_ltref[i]->bottom_field->
is_long_term = 0;
p_Dpb->fs_ltref[i]->is_reference &= 1;
p_Dpb->fs_ltref[i]->is_long_term &= 1;
if (p_Dpb->fs_ltref[i]->is_used == 3) {
p_Dpb->fs_ltref[i]->frame->
used_for_reference = 0;
p_Dpb->fs_ltref[i]->frame->
is_long_term = 0;
}
return;
}
}
}
}
}
/*!
************************************************************************
* \brief
* Mark a long-term reference frame or complementary
* field pair unused for referemce
************************************************************************
*/
static void unmark_long_term_frame_for_reference_by_frame_idx(
struct DecodedPictureBuffer *p_Dpb, int long_term_frame_idx)
{
unsigned int i;
for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
if (p_Dpb->fs_ltref[i]->long_term_frame_idx ==
long_term_frame_idx)
unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
}
}
static void unmark1(struct DecodedPictureBuffer *p_Dpb,
unsigned int curr_frame_num, int i)
{
if (p_Dpb->last_picture) {
/*if ((p_Dpb->last_picture != p_Dpb->fs_ltref[i]) ||
p_Dpb->last_picture->frame_num != curr_frame_num) {*/
unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
/*} else {
unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
}*/
}
}
static void unmark2(struct DecodedPictureBuffer *p_Dpb,
int curr_pic_num, int i)
{
if ((p_Dpb->fs_ltref[i]->frame_num) !=
(unsigned int)(curr_pic_num >> 1))
unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
}
static void unmark3_top(struct DecodedPictureBuffer *p_Dpb,
unsigned int curr_frame_num, int curr_pic_num, int mark_current, int i)
{
if (p_Dpb->fs_ltref[i]->is_long_term == 3) {
unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
} else {
if (p_Dpb->fs_ltref[i]->is_long_term == 1) {
unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
} else {
if (mark_current)
unmark1(p_Dpb, curr_frame_num, i);
else
unmark2(p_Dpb, curr_pic_num, i);
}
}
}
static void unmark3_bottom(struct DecodedPictureBuffer *p_Dpb,
unsigned int curr_frame_num, int curr_pic_num, int mark_current, int i)
{
if (p_Dpb->fs_ltref[i]->is_long_term == 2) {
unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
} else {
if (mark_current)
unmark1(p_Dpb, curr_frame_num, i);
else
unmark2(p_Dpb, curr_pic_num, i);
}
}
static void unmark_long_term_field_for_reference_by_frame_idx(
struct DecodedPictureBuffer *p_Dpb, enum PictureStructure structure,
int long_term_frame_idx, int mark_current, unsigned int curr_frame_num,
int curr_pic_num)
{
struct VideoParameters *p_Vid = p_Dpb->p_Vid;
unsigned int i;
/* assert(structure!=FRAME); */
if (curr_pic_num < 0)
curr_pic_num += (2 * p_Vid->max_frame_num);
for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
if (p_Dpb->fs_ltref[i]->long_term_frame_idx ==
long_term_frame_idx) {
if (structure == TOP_FIELD)
unmark3_top(p_Dpb, curr_frame_num,
curr_pic_num, mark_current, i);
if (structure == BOTTOM_FIELD)
unmark3_bottom(p_Dpb, curr_frame_num,
curr_pic_num, mark_current, i);
}
}
}
/*!
************************************************************************
* \brief
* mark a picture as long-term reference
************************************************************************
*/
static void mark_pic_long_term(struct DecodedPictureBuffer *p_Dpb,
struct StorablePicture *p,
int long_term_frame_idx, int picNumX)
{
struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
struct h264_dpb_stru, mDPB);
unsigned int i;
int add_top, add_bottom;
if (p->structure == FRAME) {
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 == 3) {
#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->
is_long_term) &&
(p_Dpb->fs_ref[i]->frame->pic_num ==
picNumX)) {
p_Dpb->fs_ref[i]->
long_term_frame_idx =
p_Dpb->fs_ref[i]->frame->
long_term_frame_idx =
long_term_frame_idx;
p_Dpb->fs_ref[i]->frame->
long_term_pic_num =
long_term_frame_idx;
p_Dpb->fs_ref[i]->frame->
is_long_term = 1;
if (p_Dpb->fs_ref[i]->top_field &&
p_Dpb->fs_ref[i]->bottom_field) {
p_Dpb->fs_ref[i]->top_field->
long_term_frame_idx =
p_Dpb->fs_ref[i]->
bottom_field->
long_term_frame_idx =
long_term_frame_idx;
p_Dpb->fs_ref[i]->top_field->
long_term_pic_num =
long_term_frame_idx;
p_Dpb->fs_ref[i]->
bottom_field->
long_term_pic_num =
long_term_frame_idx;
p_Dpb->fs_ref[i]->top_field->
is_long_term =
p_Dpb->fs_ref[i]->
bottom_field->
is_long_term
= 1;
}
p_Dpb->fs_ref[i]->is_long_term = 3;
return;
}
}
}
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"Warning: reference frame for long term marking not found\n");
} else {
if (p->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 & 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->
is_long_term) &&
(p_Dpb->fs_ref[i]->top_field->pic_num ==
picNumX)) {
if ((p_Dpb->fs_ref[i]->
is_long_term) &&
(p_Dpb->fs_ref[i]->
long_term_frame_idx !=
long_term_frame_idx)) {
dpb_print(p_H264_Dpb->
decoder_index,
PRINT_FLAG_DPB_DETAIL,
"Warning: assigning long_term_frame_idx different from other field\n");
}
p_Dpb->fs_ref[i]->
long_term_frame_idx =
p_Dpb->fs_ref[i]->top_field->
long_term_frame_idx
= long_term_frame_idx;
p_Dpb->fs_ref[i]->top_field->
long_term_pic_num =
2 * long_term_frame_idx +
add_top;
p_Dpb->fs_ref[i]->top_field->
is_long_term = 1;
p_Dpb->fs_ref[i]->is_long_term |= 1;
if ((p_Dpb->fs_ref[i]->is_long_term
== 3)
#ifdef ERROR_CHECK
&& p_Dpb->fs_ref[i]->frame
#endif
) {
p_Dpb->fs_ref[i]->frame->
is_long_term = 1;
p_Dpb->fs_ref[i]->frame->
long_term_frame_idx =
p_Dpb->fs_ref[i]->
frame->
long_term_pic_num =
long_term_frame_idx;
}
return;
}
}
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
if ((!p_Dpb->fs_ref[i]->bottom_field->
is_long_term) &&
(p_Dpb->fs_ref[i]->bottom_field->pic_num
== picNumX)) {
if ((p_Dpb->fs_ref[i]->
is_long_term) &&
(p_Dpb->fs_ref[i]->
long_term_frame_idx !=
long_term_frame_idx)) {
dpb_print(p_H264_Dpb->
decoder_index,
PRINT_FLAG_DPB_DETAIL,
"Warning: assigning long_term_frame_idx different from other field\n");
}
p_Dpb->fs_ref[i]->
long_term_frame_idx =
p_Dpb->fs_ref[i]->bottom_field
->long_term_frame_idx
= long_term_frame_idx;
p_Dpb->fs_ref[i]->bottom_field->
long_term_pic_num = 2 *
long_term_frame_idx +
add_bottom;
p_Dpb->fs_ref[i]->bottom_field->
is_long_term = 1;
p_Dpb->fs_ref[i]->is_long_term |= 2;
if ((p_Dpb->fs_ref[i]->
is_long_term == 3)
#ifdef ERROR_CHECK
&& p_Dpb->fs_ref[i]->frame
#endif
) {
p_Dpb->fs_ref[i]->frame->
is_long_term = 1;
p_Dpb->fs_ref[i]->frame->
long_term_frame_idx =
p_Dpb->fs_ref[i]->
frame->
long_term_pic_num =
long_term_frame_idx;
}
return;
}
}
}
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"Warning: reference field for long term marking not found\n");
}
}
/*!
************************************************************************
* \brief
* Assign a long term frame index to a short term picture
************************************************************************
*/
static void mm_assign_long_term_frame_idx(struct DecodedPictureBuffer *p_Dpb,
struct StorablePicture *p, int difference_of_pic_nums_minus1,
int long_term_frame_idx)
{
struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
struct h264_dpb_stru, mDPB);
int picNumX = get_pic_num_x(p, difference_of_pic_nums_minus1);
/* remove frames/fields with same long_term_frame_idx */
if (p->structure == FRAME) {
unmark_long_term_frame_for_reference_by_frame_idx(p_Dpb,
long_term_frame_idx);
} else {
unsigned int i;
enum PictureStructure structure = FRAME;
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 & 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) {
structure = TOP_FIELD;
break;
}
}
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
if (p_Dpb->fs_ref[i]->bottom_field->
pic_num == picNumX) {
structure = BOTTOM_FIELD;
break;
}
}
}
if (structure == FRAME) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"field for long term marking not found %d",
200);
}
unmark_long_term_field_for_reference_by_frame_idx(p_Dpb,
structure,
long_term_frame_idx, 0, 0, picNumX);
}
mark_pic_long_term(p_Dpb, p, long_term_frame_idx, picNumX);
}
/*!
************************************************************************
* \brief
* Set new max long_term_frame_idx
************************************************************************
*/
static void mm_update_max_long_term_frame_idx(struct DecodedPictureBuffer
*p_Dpb, int max_long_term_frame_idx_plus1)
{
unsigned int i;
p_Dpb->max_long_term_pic_idx = max_long_term_frame_idx_plus1 - 1;
/* check for invalid frames */
for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
if (p_Dpb->fs_ltref[i]->long_term_frame_idx >
p_Dpb->max_long_term_pic_idx) {
unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
}
}
}
/*!
************************************************************************
* \brief
* Mark all long term reference pictures unused for reference
************************************************************************
*/
static void mm_unmark_all_long_term_for_reference(struct DecodedPictureBuffer
*p_Dpb)
{
mm_update_max_long_term_frame_idx(p_Dpb, 0);
}
/*!
************************************************************************
* \brief
* Mark all short term reference pictures unused for reference
************************************************************************
*/
static void mm_unmark_all_short_term_for_reference(struct DecodedPictureBuffer
*p_Dpb)
{
unsigned int i;
for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++)
unmark_for_reference(p_Dpb, p_Dpb->fs_ref[i]);
update_ref_list(p_Dpb);
}
/*!
************************************************************************
* \brief
* Mark the current picture used for long term reference
************************************************************************
*/
static void mm_mark_current_picture_long_term(struct DecodedPictureBuffer
*p_Dpb, struct StorablePicture *p, int long_term_frame_idx)
{
/* remove long term pictures with same long_term_frame_idx */
if (p->structure == FRAME) {
unmark_long_term_frame_for_reference_by_frame_idx(p_Dpb,
long_term_frame_idx);
} else {
unmark_long_term_field_for_reference_by_frame_idx(p_Dpb,
p->structure, long_term_frame_idx,
1, p->pic_num, 0);
}
p->is_long_term = 1;
p->long_term_frame_idx = long_term_frame_idx;
}
static void adaptive_memory_management(struct h264_dpb_stru *p_H264_Dpb,
struct StorablePicture *p)
{
struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
struct DecRefPicMarking_s *tmp_drpm;
struct VideoParameters *p_Vid = p_Dpb->p_Vid;
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s\n", __func__);
p_Vid->last_has_mmco_5 = 0;
/* assert (!p->idr_flag); */
/* assert (p->adaptive_ref_pic_buffering_flag); */
while (p->dec_ref_pic_marking_buffer) {
tmp_drpm = p->dec_ref_pic_marking_buffer;
switch (tmp_drpm->memory_management_control_operation) {
case 0:
if (tmp_drpm->Next != NULL)
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_ERROR,
"error, memory_management_control_operation = 0 not last operation in buffer\n");
break;
case 1:
mm_unmark_short_term_for_reference(p_Dpb, p,
tmp_drpm->difference_of_pic_nums_minus1);
update_ref_list(p_Dpb);
break;
case 2:
mm_unmark_long_term_for_reference(p_Dpb, p,
tmp_drpm->long_term_pic_num);
update_ltref_list(p_Dpb);
break;
case 3:
mm_assign_long_term_frame_idx(p_Dpb, p,
tmp_drpm->difference_of_pic_nums_minus1,
tmp_drpm->long_term_frame_idx);
update_ref_list(p_Dpb);
update_ltref_list(p_Dpb);
break;
case 4:
mm_update_max_long_term_frame_idx(p_Dpb,
tmp_drpm->max_long_term_frame_idx_plus1);
update_ltref_list(p_Dpb);
break;
case 5:
mm_unmark_all_short_term_for_reference(p_Dpb);
mm_unmark_all_long_term_for_reference(p_Dpb);
p_Vid->last_has_mmco_5 = 1;
break;
case 6:
mm_mark_current_picture_long_term(p_Dpb, p,
tmp_drpm->long_term_frame_idx);
check_num_ref(p_Dpb);
break;
default:
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_ERROR,
"error, invalid memory_management_control_operation in buffer\n");
}
p->dec_ref_pic_marking_buffer = tmp_drpm->Next;
/* free (tmp_drpm); */
}
if (p_Vid->last_has_mmco_5) {
p->pic_num = p->frame_num = 0;
switch (p->structure) {
case TOP_FIELD: {
/* p->poc = p->top_poc = p_Vid->toppoc =0; */
p->poc = p->top_poc = 0;
break;
}
case BOTTOM_FIELD: {
/* p->poc = p->bottom_poc = p_Vid->bottompoc = 0; */
p->poc = p->bottom_poc = 0;
break;
}
case FRAME: {
p->top_poc -= p->poc;
p->bottom_poc -= p->poc;
/* p_Vid->toppoc = p->top_poc; */
/* p_Vid->bottompoc = p->bottom_poc; */
p->poc = imin(p->top_poc, p->bottom_poc);
/* p_Vid->framepoc = p->poc; */
break;
}
}
/* currSlice->ThisPOC = p->poc; */
#if (MVC_EXTENSION_ENABLE)
if (p->view_id == 0) {
flush_dpb(p_Vid->p_Dpb_layer[0]);
flush_dpb(p_Vid->p_Dpb_layer[1]);
} else {
flush_dpb(p_Dpb);
}
#else
flush_dpb(p_H264_Dpb);
#endif
}
}
int store_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb,
struct StorablePicture *p,
unsigned char data_flag)
{
/* struct VideoParameters *p_Vid = p_Dpb->p_Vid; */
struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo;
struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
unsigned int i, frame_outside_count = 0;
#if 0
int poc, pos;
#endif
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s p_Vid %p\n", __func__, p_Vid);
/* picture error concealment */
/* diagnostics */
/* dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
* "Storing (%s) non-ref pic with frame_num #%d\n",
* (p->type == FRAME)?"FRAME":(p->type == TOP_FIELD)?
* "TOP_FIELD":"BOTTOM_FIELD", p->pic_num);
*/
/* if frame, check for new store, */
/* assert (p!=NULL); */
p_Vid->last_has_mmco_5 = 0;
p_Vid->last_pic_bottom_field = (p->structure == BOTTOM_FIELD);
if (p->idr_flag) {
idr_memory_management(p_H264_Dpb, p);
if (p_H264_Dpb->first_insert_frame == FirstInsertFrm_OUT)
p_H264_Dpb->first_insert_frame = FirstInsertFrm_SKIPDONE;
#if 0
/* ??? */
/* picture error concealment */
memset(p_Vid->pocs_in_dpb, 0, sizeof(int) * 100);
#endif
} else {
#if 1
/* ??? */
/* adaptive memory management */
if (p->used_for_reference &&
(p->adaptive_ref_pic_buffering_flag))
adaptive_memory_management(p_H264_Dpb, p);
#endif
}
if ((p->structure == TOP_FIELD) || (p->structure == BOTTOM_FIELD)) {
/* check for frame store with same pic_number */
if (p_Dpb->last_picture) {
if ((int)p_Dpb->last_picture->frame_num ==
p->pic_num) {
if (((p->structure == TOP_FIELD) &&
(p_Dpb->last_picture->is_used == 2)) ||
((p->structure == BOTTOM_FIELD) &&
(p_Dpb->last_picture->is_used == 1))) {
if ((p->used_for_reference &&
(p_Dpb->last_picture->
is_orig_reference != 0)) ||
(!p->used_for_reference &&
(p_Dpb->last_picture->
is_orig_reference == 0))) {
insert_picture_in_dpb(
p_H264_Dpb,
p_Dpb->last_picture,
p, data_flag);
update_ref_list(p_Dpb);
update_ltref_list(p_Dpb);
dump_dpb(p_Dpb, 0);
p_Dpb->last_picture = NULL;
return 0;
}
}
}
}
}
/* this is a frame or a field which has no stored
* complementary field
*/
/* sliding window, if necessary */
if ((!p->idr_flag) && (p->used_for_reference &&
(!p->adaptive_ref_pic_buffering_flag))) {
sliding_window_memory_management(p_Dpb, p);
}
/* picture error concealment */
if (p_Vid->conceal_mode != 0) {
for (i = 0; i < p_Dpb->size; i++)
if (p_Dpb->fs[i]->is_reference)
p_Dpb->fs[i]->concealment_reference = 1;
}
while (remove_unused_frame_from_dpb(p_H264_Dpb))
;
while (output_frames(p_H264_Dpb, 0))
;
/* check for duplicate frame number in short term reference buffer */
if ((p->used_for_reference) && (!p->is_long_term)) {
for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
#ifdef ERROR_CHECK
if (p_Dpb->fs_ref[i] == NULL)
continue;
#endif
if (p_Dpb->fs_ref[i]->frame_num == p->frame_num) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"duplicate frame_num in short-term reference picture buffer %d\n",
500);
if (p_Dpb->fs_ref[i]->dpb_frame_count == p_H264_Dpb->dpb_frame_count) {
dpb_print(p_H264_Dpb->decoder_index,
0, "duplicate frame, no insert to dpb\n");
return -2;
} else {
dpb_print(p_H264_Dpb->decoder_index,
0, "duplicate frame_num release defore ref\n");
unmark_for_reference(p_Dpb, p_Dpb->fs_ref[i]);
update_ref_list(p_Dpb);
}
}
}
}
/* store at end of buffer */
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s p_Dpb->used_size %d\n", __func__, p_Dpb->used_size);
if (p_Dpb->used_size >= p_Dpb->size) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_ERROR,
"%s Error: used_sizd %d is large than dpb size\r\n",
__func__, p_Dpb->used_size);
/*h264_debug_flag |= PRINT_FLAG_DUMP_DPB;*/
dump_dpb(p_Dpb, 0);
return -1;
}
insert_picture_in_dpb(p_H264_Dpb, p_Dpb->fs[p_Dpb->used_size],
p, data_flag);
/* picture error concealment */
if (p->idr_flag)
p_Vid->earlier_missing_poc = 0;
if (p->structure != FRAME)
p_Dpb->last_picture = p_Dpb->fs[p_Dpb->used_size];
else
p_Dpb->last_picture = NULL;
p_Dpb->used_size++;
#if 0
/* ??? */
if (p_Vid->conceal_mode != 0)
p_Vid->pocs_in_dpb[p_Dpb->used_size - 1] = p->poc;
#endif
update_ref_list(p_Dpb);
update_ltref_list(p_Dpb);
check_num_ref(p_Dpb);
for (i = 0; i < p_Dpb->used_size; i++) {
if (p_Dpb->fs[i]->pre_output)
frame_outside_count++;
}
if (p_H264_Dpb->fast_output_enable == H264_OUTPUT_MODE_FAST)
i = 1;
else
i = 0;
if (i || (p_H264_Dpb->first_insert_frame < FirstInsertFrm_SKIPDONE)) {
while (output_frames(p_H264_Dpb, i))
;
}
dump_dpb(p_Dpb, 0);
p_Dpb->first_pic_done = 1; /*by rain*/
return 0;
}
void bufmgr_post(struct h264_dpb_stru *p_H264_Dpb)
{
/*VideoParameters *p_Vid = p_Dpb->p_Vid;*/
struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo;
if (p_Vid->last_has_mmco_5)
p_Vid->pre_frame_num = 0;
}
/**********************************
*
* Initialize reference lists
**********************************
*/
#define __COMPARE(context, p1, p2) comp(p1, p2)
#define __SHORTSORT(lo, hi, width, comp, context) \
shortsort(lo, hi, width, comp)
#define CUTOFF 8 /* testing shows that this is good value */
#define STKSIZ (8*sizeof(void *) - 2)
#undef swap
static void swap(
char *a,
char *b,
size_t width
)
{
char tmp;
if (a != b)
/* Do the swap one character at a time to avoid potential
* alignment problems.
*/
while (width--) {
tmp = *a;
*a++ = *b;
*b++ = tmp;
}
}
static void shortsort(
char *lo,
char *hi,
size_t width,
int (*comp)(const void *, const void *)
)
{
char *p, *max;
/* Note: in assertions below, i and j are alway inside original
* bound of array to sort.
*/
while (hi > lo) {
/* A[i] <= A[j] for i <= j, j > hi */
max = lo;
for (p = lo + width; p <= hi; p += width) {
/* A[i] <= A[max] for lo <= i < p */
if (__COMPARE(context, p, max) > 0)
max = p;
/* A[i] <= A[max] for lo <= i <= p */
}
/* A[i] <= A[max] for lo <= i <= hi */
swap(max, hi, width);
/* A[i] <= A[hi] for i <= hi, so A[i] <= A[j] for i <= j,
* j >= hi
*/
hi -= width;
/* A[i] <= A[j] for i <= j, j > hi, loop top condition
* established
*/
}
/* A[i] <= A[j] for i <= j, j > lo, which implies A[i] <= A[j]
* for i < j, so array is sorted
*/
}
static void qsort(
void *base,
size_t num,
size_t width,
int (*comp)(const void *, const void *)
)
{
char *lo, *hi; /* ends of sub-array currently sorting */
char *mid; /* points to middle of subarray */
char *loguy, *higuy; /* traveling pointers for partition step */
size_t size; /* size of the sub-array */
char *lostk[STKSIZ], *histk[STKSIZ];
int stkptr;
/* stack for saving sub-array to be
* processed
*/
#if 0
/* validation section */
_VALIDATE_RETURN_VOID(base != NULL || num == 0, EINVAL);
_VALIDATE_RETURN_VOID(width > 0, EINVAL);
_VALIDATE_RETURN_VOID(comp != NULL, EINVAL);
#endif
if (num < 2)
return; /* nothing to do */
stkptr = 0; /* initialize stack */
lo = (char *)base;
hi = (char *)base + width * (num - 1); /* initialize limits */
/* this entry point is for pseudo-recursion calling: setting
* lo and hi and jumping to here is like recursion, but stkptr is
* preserved, locals aren't, so we preserve stuff on the stack
*/
recurse:
size = (hi - lo) / width + 1; /* number of el's to sort */
/* below a certain size, it is faster to use a O(n^2) sorting method */
if (size <= CUTOFF) {
__SHORTSORT(lo, hi, width, comp, context);
} else {
/* First we pick a partitioning element. The efficiency of
* the algorithm demands that we find one that is approximately
* the median of the values, but also that we select one fast.
* We choose the median of the first, middle, and last
* elements, to avoid bad performance in the face of already
* sorted data, or data that is made up of multiple sorted
* runs appended together. Testing shows that a
* median-of-three algorithm provides better performance than
* simply picking the middle element for the latter case.
*/
mid = lo + (size / 2) * width; /* find middle element */
/* Sort the first, middle, last elements into order */
if (__COMPARE(context, lo, mid) > 0)
swap(lo, mid, width);
if (__COMPARE(context, lo, hi) > 0)
swap(lo, hi, width);
if (__COMPARE(context, mid, hi) > 0)
swap(mid, hi, width);
/* We now wish to partition the array into three pieces, one
* consisting of elements <= partition element, one of elements
* equal to the partition element, and one of elements > than
* it. This is done below; comments indicate conditions
* established at every step.
*/
loguy = lo;
higuy = hi;
/* Note that higuy decreases and loguy increases on every
* iteration, so loop must terminate.
*/
for (;;) {
/* lo <= loguy < hi, lo < higuy <= hi,
* A[i] <= A[mid] for lo <= i <= loguy,
* A[i] > A[mid] for higuy <= i < hi,
* A[hi] >= A[mid]
*/
/* The doubled loop is to avoid calling comp(mid,mid),
* since some existing comparison funcs don't work
* when passed the same value for both pointers.
*/
if (mid > loguy) {
do {
loguy += width;
} while (loguy < mid &&
__COMPARE(context, loguy, mid) <= 0);
}
if (mid <= loguy) {
do {
loguy += width;
} while (loguy <= hi &&
__COMPARE(context, loguy, mid) <= 0);
}
/* lo < loguy <= hi+1, A[i] <= A[mid] for
* lo <= i < loguy,
* either loguy > hi or A[loguy] > A[mid]
*/
do {
higuy -= width;
} while (higuy > mid &&
__COMPARE(context, higuy, mid) > 0);
/* lo <= higuy < hi, A[i] > A[mid] for higuy < i < hi,
* either higuy == lo or A[higuy] <= A[mid]
*/
if (higuy < loguy)
break;
/* if loguy > hi or higuy == lo, then we would have
* exited, so A[loguy] > A[mid], A[higuy] <= A[mid],
* loguy <= hi, higuy > lo
*/
swap(loguy, higuy, width);
/* If the partition element was moved, follow it.
* Only need to check for mid == higuy, since before
* the swap, A[loguy] > A[mid] implies loguy != mid.
*/
if (mid == higuy)
mid = loguy;
/* A[loguy] <= A[mid], A[higuy] > A[mid]; so condition
* at top of loop is re-established
*/
}
/* A[i] <= A[mid] for lo <= i < loguy,
* A[i] > A[mid] for higuy < i < hi,
* A[hi] >= A[mid]
* higuy < loguy
* implying:
* higuy == loguy-1
* or higuy == hi - 1, loguy == hi + 1, A[hi] == A[mid]
*/
/* Find adjacent elements equal to the partition element. The
* doubled loop is to avoid calling comp(mid,mid), since some
* existing comparison funcs don't work when passed the same
* value for both pointers.
*/
higuy += width;
if (mid < higuy) {
do {
higuy -= width;
} while (higuy > mid &&
__COMPARE(context, higuy, mid) == 0);
}
if (mid >= higuy) {
do {
higuy -= width;
} while (higuy > lo &&
__COMPARE(context, higuy, mid) == 0);
}
/* OK, now we have the following:
* higuy < loguy
* lo <= higuy <= hi
* A[i] <= A[mid] for lo <= i <= higuy
* A[i] == A[mid] for higuy < i < loguy
* A[i] > A[mid] for loguy <= i < hi
* A[hi] >= A[mid]
*/
/* We've finished the partition, now we want to sort the
* subarrays [lo, higuy] and [loguy, hi].
* We do the smaller one first to minimize stack usage.
* We only sort arrays of length 2 or more.
*/
if (higuy - lo >= hi - loguy) {
if (lo < higuy) {
lostk[stkptr] = lo;
histk[stkptr] = higuy;
++stkptr;
} /* save big recursion for later */
if (loguy < hi) {
lo = loguy;
goto recurse; /* do small recursion */
}
} else {
if (loguy < hi) {
lostk[stkptr] = loguy;
histk[stkptr] = hi;
++stkptr; /* save big recursion for later */
}
if (lo < higuy) {
hi = higuy;
goto recurse; /* do small recursion */
}
}
}
/* We have sorted the array, except for any pending sorts on the stack.
* Check if there are any, and do them.
*/
--stkptr;
if (stkptr >= 0) {
lo = lostk[stkptr];
hi = histk[stkptr];
goto recurse; /* pop subarray from stack */
} else
return; /* all subarrays done */
}
/*!
************************************************************************
* \brief
* compares two stored pictures by picture number for qsort in
* descending order
*
************************************************************************
*/
static inline int compare_pic_by_pic_num_desc(const void *arg1,
const void *arg2)
{
int pic_num1 = (*(struct StorablePicture **)arg1)->pic_num;
int pic_num2 = (*(struct StorablePicture **)arg2)->pic_num;
if (pic_num1 < pic_num2)
return 1;
if (pic_num1 > pic_num2)
return -1;
else
return 0;
}
/*!
************************************************************************
* \brief
* compares two stored pictures by picture number for qsort in
* descending order
*
************************************************************************
*/
static inline int compare_pic_by_lt_pic_num_asc(const void *arg1,
const void *arg2)
{
int long_term_pic_num1 =
(*(struct StorablePicture **)arg1)->long_term_pic_num;
int long_term_pic_num2 =
(*(struct StorablePicture **)arg2)->long_term_pic_num;
if (long_term_pic_num1 < long_term_pic_num2)
return -1;
if (long_term_pic_num1 > long_term_pic_num2)
return 1;
else
return 0;
}
/*!
************************************************************************
* \brief
* compares two frame stores by pic_num for qsort in descending order
*
************************************************************************
*/
static inline int compare_fs_by_frame_num_desc(const void *arg1,
const void *arg2)
{
int frame_num_wrap1 = (*(struct FrameStore **)arg1)->frame_num_wrap;
int frame_num_wrap2 = (*(struct FrameStore **)arg2)->frame_num_wrap;
if (frame_num_wrap1 < frame_num_wrap2)
return 1;
if (frame_num_wrap1 > frame_num_wrap2)
return -1;
else
return 0;
}
/*!
************************************************************************
* \brief
* compares two frame stores by lt_pic_num for qsort in descending order
*
************************************************************************
*/
static inline int compare_fs_by_lt_pic_idx_asc(const void *arg1,
const void *arg2)
{
int long_term_frame_idx1 =
(*(struct FrameStore **)arg1)->long_term_frame_idx;
int long_term_frame_idx2 =
(*(struct FrameStore **)arg2)->long_term_frame_idx;
if (long_term_frame_idx1 < long_term_frame_idx2)
return -1;
else if (long_term_frame_idx1 > long_term_frame_idx2)
return 1;
else
return 0;
}
/*!
************************************************************************
* \brief
* compares two stored pictures by poc for qsort in ascending order
*
************************************************************************
*/
static inline int compare_pic_by_poc_asc(const void *arg1, const void *arg2)
{
int poc1 = (*(struct StorablePicture **)arg1)->poc;
int poc2 = (*(struct StorablePicture **)arg2)->poc;
if (poc1 < poc2)
return -1;
else if (poc1 > poc2)
return 1;
else
return 0;
}
/*!
************************************************************************
* \brief
* compares two stored pictures by poc for qsort in descending order
*
************************************************************************
*/
static inline int compare_pic_by_poc_desc(const void *arg1, const void *arg2)
{
int poc1 = (*(struct StorablePicture **)arg1)->poc;
int poc2 = (*(struct StorablePicture **)arg2)->poc;
if (poc1 < poc2)
return 1;
else if (poc1 > poc2)
return -1;
else
return 0;
}
/*!
************************************************************************
* \brief
* compares two frame stores by poc for qsort in ascending order
*
************************************************************************
*/
static inline int compare_fs_by_poc_asc(const void *arg1, const void *arg2)
{
int poc1 = (*(struct FrameStore **)arg1)->poc;
int poc2 = (*(struct FrameStore **)arg2)->poc;
if (poc1 < poc2)
return -1;
else if (poc1 > poc2)
return 1;
else
return 0;
}
/*!
************************************************************************
* \brief
* compares two frame stores by poc for qsort in descending order
*
************************************************************************
*/
static inline int compare_fs_by_poc_desc(const void *arg1, const void *arg2)
{
int poc1 = (*(struct FrameStore **)arg1)->poc;
int poc2 = (*(struct FrameStore **)arg2)->poc;
if (poc1 < poc2)
return 1;
else if (poc1 > poc2)
return -1;
else
return 0;
}
/*!
************************************************************************
* \brief
* returns true, if picture is short term reference picture
*
************************************************************************
*/
static inline int is_short_ref(struct StorablePicture *s)
{
#ifdef ERROR_CHECK
return (s &&
(s->used_for_reference) && (!(s->is_long_term)));
#else
return (s->used_for_reference) && (!(s->is_long_term));
#endif
}
/*!
************************************************************************
* \brief
* returns true, if picture is long term reference picture
*
************************************************************************
*/
static inline int is_long_ref(struct StorablePicture *s)
{
#ifdef ERROR_CHECK
return (s &&
s->used_for_reference) && (s->is_long_term);
#else
return (s->used_for_reference) && (s->is_long_term);
#endif
}
/*!
************************************************************************
* \brief
* Initialize reference lists for a P Slice
*
************************************************************************
*/
/*!
************************************************************************
* \brief
* Generates a alternating field list from a given FrameStore list
*
************************************************************************
*/
static void gen_pic_list_from_frame_list(enum PictureStructure currStructure,
struct FrameStore **fs_list, int list_idx,
struct StorablePicture **list,
char *list_size, int long_term)
{
int top_idx = 0;
int bot_idx = 0;
int (*is_ref)(struct StorablePicture *s) = (long_term) ? is_long_ref :
is_short_ref;
if (currStructure == TOP_FIELD) {
while ((top_idx < list_idx) || (bot_idx < list_idx)) {
for (; top_idx < list_idx; top_idx++) {
if (fs_list[top_idx]->is_used & 1) {
if (is_ref(fs_list[top_idx]->
top_field)) {
/* short term ref pic */
list[(short) *list_size] =
fs_list[top_idx]->top_field;
(*list_size)++;
top_idx++;
break;
}
}
}
for (; bot_idx < list_idx; bot_idx++) {
if (fs_list[bot_idx]->is_used & 2) {
if (is_ref(fs_list[bot_idx]->
bottom_field)) {
/* short term ref pic */
list[(short) *list_size] =
fs_list[bot_idx]->bottom_field;
(*list_size)++;
bot_idx++;
break;
}
}
}
}
}
if (currStructure == BOTTOM_FIELD) {
while ((top_idx < list_idx) || (bot_idx < list_idx)) {
for (; bot_idx < list_idx; bot_idx++) {
if (fs_list[bot_idx]->is_used & 2) {
if (is_ref(fs_list[bot_idx]->
bottom_field)) {
/* short term ref pic */
list[(short) *list_size] =
fs_list[bot_idx]->bottom_field;
(*list_size)++;
bot_idx++;
break;
}
}
}
for (; top_idx < list_idx; top_idx++) {
if (fs_list[top_idx]->is_used & 1) {
if (is_ref(fs_list[top_idx]->
top_field)) {
/* short term ref pic */
list[(short) *list_size] =
fs_list[top_idx]->top_field;
(*list_size)++;
top_idx++;
break;
}
}
}
}
}
}
static void init_lists_p_slice(struct Slice *currSlice)
{
struct VideoParameters *p_Vid = currSlice->p_Vid;
struct DecodedPictureBuffer *p_Dpb = currSlice->p_Dpb;
struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
struct h264_dpb_stru, mDPB);
unsigned int i;
int list0idx = 0;
int listltidx = 0;
struct FrameStore **fs_list0;
struct FrameStore **fs_listlt;
#if (MVC_EXTENSION_ENABLE)
currSlice->listinterviewidx0 = 0;
currSlice->listinterviewidx1 = 0;
#endif
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)) {
currSlice->listX[0][list0idx++] =
p_Dpb->fs_ref[i]->frame;
}
}
}
/* order list 0 by PicNum */
qsort((void *)currSlice->listX[0], list0idx,
sizeof(struct StorablePicture *),
compare_pic_by_pic_num_desc);
currSlice->listXsize[0] = (char) list0idx;
CHECK_VALID(currSlice->listXsize[0], 0);
if (h264_debug_flag & PRINT_FLAG_DPB_DETAIL) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"listX[0] (PicNum): ");
for (i = 0; i < list0idx; i++) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "%d ",
currSlice->listX[0][i]->pic_num);
}
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "\n");
}
/* long term handling */
for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
if (p_Dpb->fs_ltref[i]->is_used == 3) {
if (p_Dpb->fs_ltref[i]->frame->is_long_term) {
currSlice->listX[0][list0idx++] =
p_Dpb->fs_ltref[i]->frame;
}
}
}
qsort((void *)&currSlice->listX[0][
(short) currSlice->listXsize[0]],
list0idx - currSlice->listXsize[0],
sizeof(struct StorablePicture *),
compare_pic_by_lt_pic_num_asc);
currSlice->listXsize[0] = (char) list0idx;
CHECK_VALID(currSlice->listXsize[0], 0);
} else {
#if 0
fs_list0 = calloc(p_Dpb->size, sizeof(struct FrameStore *));
if (fs_list0 == NULL)
no_mem_exit("init_lists: fs_list0");
fs_listlt = calloc(p_Dpb->size, sizeof(struct FrameStore *));
if (fs_listlt == NULL)
no_mem_exit("init_lists: fs_listlt");
#else
fs_list0 = &(p_Dpb->fs_list0[0]);
fs_listlt = &(p_Dpb->fs_listlt[0]);
#endif
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)
fs_list0[list0idx++] = p_Dpb->fs_ref[i];
}
qsort((void *)fs_list0, list0idx, sizeof(struct FrameStore *),
compare_fs_by_frame_num_desc);
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"fs_list0 (FrameNum): ");
for (i = 0; i < list0idx; i++) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "%d ",
fs_list0[i]->frame_num_wrap);
}
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"\n");
currSlice->listXsize[0] = 0;
gen_pic_list_from_frame_list(currSlice->structure, fs_list0,
list0idx, currSlice->listX[0],
&currSlice->listXsize[0], 0);
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"listX[0] (PicNum): ");
for (i = 0; i < currSlice->listXsize[0]; i++) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "%d ",
currSlice->listX[0][i]->pic_num);
}
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"\n");
/* long term handling */
for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++)
fs_listlt[listltidx++] = p_Dpb->fs_ltref[i];
qsort((void *)fs_listlt, listltidx, sizeof(struct FrameStore *),
compare_fs_by_lt_pic_idx_asc);
gen_pic_list_from_frame_list(currSlice->structure, fs_listlt,
listltidx, currSlice->listX[0],
&currSlice->listXsize[0], 1);
/* free(fs_list0); */
/* free(fs_listlt); */
}
currSlice->listXsize[1] = 0;
/* set max size */
currSlice->listXsize[0] = (char) imin(currSlice->listXsize[0],
currSlice->num_ref_idx_active[LIST_0]);
currSlice->listXsize[1] = (char) imin(currSlice->listXsize[1],
currSlice->num_ref_idx_active[LIST_1]);
CHECK_VALID(currSlice->listXsize[0], 0);
CHECK_VALID(currSlice->listXsize[1], 1);
/* set the unused list entries to NULL */
for (i = currSlice->listXsize[0]; i < (MAX_LIST_SIZE); i++)
currSlice->listX[0][i] = p_Vid->no_reference_picture;
for (i = currSlice->listXsize[1]; i < (MAX_LIST_SIZE); i++)
currSlice->listX[1][i] = p_Vid->no_reference_picture;
#if PRINTREFLIST
#if (MVC_EXTENSION_ENABLE)
/* print out for h264_debug_flag purpose */
if ((p_Vid->profile_idc == MVC_HIGH ||
p_Vid->profile_idc == STEREO_HIGH) &&
currSlice->current_slice_nr == 0) {
if (currSlice->listXsize[0] > 0) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "\n");
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
" ** (CurViewID:%d %d) %s Ref Pic List 0 ****\n",
currSlice->view_id,
currSlice->ThisPOC,
currSlice->structure == FRAME ? "FRM" :
(currSlice->structure == TOP_FIELD ?
"TOP" : "BOT"));
for (i = 0; i < (unsigned int)(currSlice->
listXsize[0]); i++) { /* ref list 0 */
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
" %2d -> POC: %4d PicNum: %4d ViewID: %d\n",
i,
currSlice->listX[0][i]->poc,
currSlice->listX[0][i]->pic_num,
currSlice->listX[0][i]->view_id);
}
}
}
#endif
#endif
}
/*!
************************************************************************
* \brief
* Initialize reference lists
*
************************************************************************
*/
static void init_mbaff_lists(struct h264_dpb_stru *p_H264_Dpb,
struct Slice *currSlice)
{
unsigned int j;
int i;
struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo;
for (i = 2; i < 6; i++) {
for (j = 0; j < MAX_LIST_SIZE; j++)
currSlice->listX[i][j] = p_Vid->no_reference_picture;
currSlice->listXsize[i] = 0;
}
for (i = 0; i < currSlice->listXsize[0]; i++) {
#ifdef ERROR_CHECK
if (currSlice->listX[0][i] == NULL) {
p_H264_Dpb->dpb_error_flag = __LINE__;
pr_info(
"error currSlice->listX[0][%d] is NULL\r\n", i);
break;
}
#endif
currSlice->listX[2][2 * i] =
currSlice->listX[0][i]->top_field;
currSlice->listX[2][2 * i + 1] =
currSlice->listX[0][i]->bottom_field;
currSlice->listX[4][2 * i] =
currSlice->listX[0][i]->bottom_field;
currSlice->listX[4][2 * i + 1] =
currSlice->listX[0][i]->top_field;
}
currSlice->listXsize[2] = currSlice->listXsize[4] =
currSlice->listXsize[0] * 2;
for (i = 0; i < currSlice->listXsize[1]; i++) {
#ifdef ERROR_CHECK
if (currSlice->listX[1][i] == NULL) {
p_H264_Dpb->dpb_error_flag = __LINE__;
pr_info(
"error currSlice->listX[1][%d] is NULL\r\n", i);
break;
}
#endif
currSlice->listX[3][2 * i] =
currSlice->listX[1][i]->top_field;
currSlice->listX[3][2 * i + 1] =
currSlice->listX[1][i]->bottom_field;
currSlice->listX[5][2 * i] =
currSlice->listX[1][i]->bottom_field;
currSlice->listX[5][2 * i + 1] =
currSlice->listX[1][i]->top_field;
}
currSlice->listXsize[3] = currSlice->listXsize[5] =
currSlice->listXsize[1] * 2;
}
static void init_lists_i_slice(struct Slice *currSlice)
{
#if (MVC_EXTENSION_ENABLE)
currSlice->listinterviewidx0 = 0;
currSlice->listinterviewidx1 = 0;
#endif
currSlice->listXsize[0] = 0;
currSlice->listXsize[1] = 0;
}
static void init_lists_b_slice(struct Slice *currSlice)
{
struct VideoParameters *p_Vid = currSlice->p_Vid;
struct DecodedPictureBuffer *p_Dpb = currSlice->p_Dpb;
struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
struct h264_dpb_stru, mDPB);
unsigned int i;
int j;
int list0idx = 0;
int list0idx_1 = 0;
int listltidx = 0;
struct FrameStore **fs_list0;
struct FrameStore **fs_list1;
struct FrameStore **fs_listlt;
#if (MVC_EXTENSION_ENABLE)
currSlice->listinterviewidx0 = 0;
currSlice->listinterviewidx1 = 0;
#endif
{
/* B-Slice */
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) &&
((p_Dpb->fs_ref[i]->frame->
used_for_reference) &&
(!p_Dpb->fs_ref[i]->frame->
is_long_term)) &&
(currSlice->framepoc >=
p_Dpb->fs_ref[i]->frame->poc)) {
/* !KS use >= for error
* concealment
*/
currSlice->listX[0][list0idx++] =
p_Dpb->fs_ref[i]->frame;
}
}
qsort((void *)currSlice->listX[0], list0idx,
sizeof(struct StorablePicture *),
compare_pic_by_poc_desc);
/* get the backward reference picture
* (POC>current POC) in list0;
*/
list0idx_1 = list0idx;
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) &&
((p_Dpb->fs_ref[i]->frame->
used_for_reference) &&
(!p_Dpb->fs_ref[i]->frame->
is_long_term)) &&
(currSlice->framepoc <
p_Dpb->fs_ref[i]->frame->poc)) {
currSlice->
listX[0][list0idx++] =
p_Dpb->fs_ref[i]->frame;
}
}
qsort((void *)&currSlice->listX[0][list0idx_1],
list0idx - list0idx_1,
sizeof(struct StorablePicture *),
compare_pic_by_poc_asc);
for (j = 0; j < list0idx_1; j++) {
currSlice->
listX[1][list0idx - list0idx_1 + j] =
currSlice->listX[0][j];
}
for (j = list0idx_1; j < list0idx; j++) {
currSlice->listX[1][j - list0idx_1] =
currSlice->listX[0][j];
}
currSlice->listXsize[0] = currSlice->listXsize[1] =
(char) list0idx;
CHECK_VALID(currSlice->listXsize[0], 0);
CHECK_VALID(currSlice->listXsize[1], 1);
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"listX[0] (PicNum): ");
for (i = 0; i < currSlice->listXsize[0]; i++) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "%d ",
currSlice->listX[0][i]->pic_num);
}
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "\n");
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"listX[1] (PicNum): ");
for (i = 0; i < currSlice->listXsize[1]; i++) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "%d ",
currSlice->listX[1][i]->pic_num);
}
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "\n");
/* dpb_print(p_H264_Dpb->decoder_index,
* PRINT_FLAG_DPB_DETAIL,
* "currSlice->listX[0] currPoc=%d (Poc): ",
* p_Vid->framepoc);
* for (i=0; i<currSlice->listXsize[0]; i++) {
* dpb_print(p_H264_Dpb->decoder_index,
* PRINT_FLAG_DPB_DETAIL,
* "%d ", currSlice->listX[0][i]->poc);
* }
* dpb_print(p_H264_Dpb->decoder_index,
* PRINT_FLAG_DPB_DETAIL, "\n");
* dpb_print(p_H264_Dpb->decoder_index,
* PRINT_FLAG_DPB_DETAIL,
* "currSlice->listX[1] currPoc=%d (Poc): ",
* p_Vid->framepoc);
* for (i=0; i<currSlice->listXsize[1]; i++) {
* dpb_print(p_H264_Dpb->decoder_index,
* PRINT_FLAG_DPB_DETAIL,
* "%d ",
* currSlice->listX[1][i]->poc);
* }
* dpb_print(p_H264_Dpb->decoder_index,
* PRINT_FLAG_DPB_DETAIL, "\n");
*/
/* long term handling */
for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
if (p_Dpb->fs_ltref[i]->is_used == 3) {
if (p_Dpb->fs_ltref[i]->frame->
is_long_term) {
currSlice->
listX[0][list0idx] =
p_Dpb->fs_ltref[i]->frame;
currSlice->
listX[1][list0idx++] =
p_Dpb->fs_ltref[i]->frame;
}
}
}
qsort((void *)&currSlice->
listX[0][(short) currSlice->listXsize[0]],
list0idx - currSlice->listXsize[0],
sizeof(struct StorablePicture *),
compare_pic_by_lt_pic_num_asc);
qsort((void *)&currSlice->
listX[1][(short) currSlice->listXsize[0]],
list0idx - currSlice->listXsize[0],
sizeof(struct StorablePicture *),
compare_pic_by_lt_pic_num_asc);
currSlice->listXsize[0] = currSlice->listXsize[1] =
(char) list0idx;
CHECK_VALID(currSlice->listXsize[0], 0);
CHECK_VALID(currSlice->listXsize[1], 1);
} else {
#if 0
fs_list0 = calloc(p_Dpb->size,
sizeof(struct FrameStore *));
if (fs_list0 == NULL)
no_mem_exit("init_lists: fs_list0");
fs_list1 = calloc(p_Dpb->size,
sizeof(struct FrameStore *));
if (fs_list1 == NULL)
no_mem_exit("init_lists: fs_list1");
fs_listlt = calloc(p_Dpb->size,
sizeof(struct FrameStore *));
if (fs_listlt == NULL)
no_mem_exit("init_lists: fs_listlt");
#else
fs_list0 = &(p_Dpb->fs_list0[0]);
fs_list1 = &(p_Dpb->fs_list1[0]);
fs_listlt = &(p_Dpb->fs_listlt[0]);
#endif
currSlice->listXsize[0] = 0;
currSlice->listXsize[1] = 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_used) {
if (currSlice->ThisPOC >=
p_Dpb->fs_ref[i]->poc) {
fs_list0[list0idx++] =
p_Dpb->fs_ref[i];
}
}
}
qsort((void *)fs_list0, list0idx,
sizeof(struct FrameStore *),
compare_fs_by_poc_desc);
list0idx_1 = list0idx;
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_used) {
if (currSlice->ThisPOC <
p_Dpb->fs_ref[i]->poc) {
fs_list0[list0idx++] =
p_Dpb->fs_ref[i];
}
}
}
qsort((void *)&fs_list0[list0idx_1],
list0idx - list0idx_1,
sizeof(struct FrameStore *),
compare_fs_by_poc_asc);
for (j = 0; j < list0idx_1; j++) {
fs_list1[list0idx - list0idx_1 + j] =
fs_list0[j];
}
for (j = list0idx_1; j < list0idx; j++)
fs_list1[j - list0idx_1] = fs_list0[j];
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"fs_list0 currPoc=%d (Poc): ",
currSlice->ThisPOC);
for (i = 0; i < list0idx; i++) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "%d ",
fs_list0[i]->poc);
}
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "\n");
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"fs_list1 currPoc=%d (Poc): ",
currSlice->ThisPOC);
for (i = 0; i < list0idx; i++) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "%d ",
fs_list1[i]->poc);
}
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "\n");
currSlice->listXsize[0] = 0;
currSlice->listXsize[1] = 0;
gen_pic_list_from_frame_list(currSlice->structure,
fs_list0, list0idx,
currSlice->listX[0],
&currSlice->listXsize[0], 0);
gen_pic_list_from_frame_list(currSlice->structure,
fs_list1, list0idx,
currSlice->listX[1],
&currSlice->listXsize[1], 0);
/* dpb_print(p_H264_Dpb->decoder_index,
* PRINT_FLAG_DPB_DETAIL,
* "currSlice->listX[0] currPoc=%d (Poc): ",
* p_Vid->framepoc);
* for (i=0; i<currSlice->listXsize[0]; i++) {
* dpb_print(p_H264_Dpb->decoder_index,
* PRINT_FLAG_DPB_DETAIL, "%d ",
* currSlice->listX[0][i]->poc);
* }
* dpb_print(p_H264_Dpb->decoder_index,
* PRINT_FLAG_DPB_DETAIL, "\n");
*/
/* dpb_print(p_H264_Dpb->decoder_index,
* PRINT_FLAG_DPB_DETAIL,
* "currSlice->listX[1] currPoc=%d (Poc): ",
* p_Vid->framepoc);
* for (i=0; i<currSlice->listXsize[1]; i++) {
* dpb_print(p_H264_Dpb->decoder_index,
* PRINT_FLAG_DPB_DETAIL, "%d ",
* currSlice->listX[1][i]->poc);
* }
* dpb_print(p_H264_Dpb->decoder_index,
* PRINT_FLAG_DPB_DETAIL,
* "\n");
*/
/* long term handling */
for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++)
fs_listlt[listltidx++] = p_Dpb->fs_ltref[i];
qsort((void *)fs_listlt, listltidx,
sizeof(struct FrameStore *),
compare_fs_by_lt_pic_idx_asc);
gen_pic_list_from_frame_list(currSlice->structure,
fs_listlt, listltidx,
currSlice->listX[0],
&currSlice->listXsize[0], 1);
gen_pic_list_from_frame_list(currSlice->structure,
fs_listlt, listltidx,
currSlice->listX[1],
&currSlice->listXsize[1], 1);
/* free(fs_list0); */
/* free(fs_list1); */
/* free(fs_listlt); */
}
}
if ((currSlice->listXsize[0] == currSlice->listXsize[1]) &&
(currSlice->listXsize[0] > 1)) {
/* check if lists are identical,
*if yes swap first two elements of currSlice->listX[1]
*/
int diff = 0;
for (j = 0; j < currSlice->listXsize[0]; j++) {
if (currSlice->listX[0][j] !=
currSlice->listX[1][j]) {
diff = 1;
break;
}
}
if (!diff) {
struct StorablePicture *tmp_s =
currSlice->listX[1][0];
currSlice->listX[1][0] = currSlice->listX[1][1];
currSlice->listX[1][1] = tmp_s;
}
}
/* set max size */
currSlice->listXsize[0] = (char) imin(currSlice->listXsize[0],
currSlice->num_ref_idx_active[LIST_0]);
currSlice->listXsize[1] = (char) imin(currSlice->listXsize[1],
currSlice->num_ref_idx_active[LIST_1]);
CHECK_VALID(currSlice->listXsize[0], 0);
CHECK_VALID(currSlice->listXsize[1], 1);
/* set the unused list entries to NULL */
for (i = currSlice->listXsize[0]; i < (MAX_LIST_SIZE); i++)
currSlice->listX[0][i] = p_Vid->no_reference_picture;
for (i = currSlice->listXsize[1]; i < (MAX_LIST_SIZE); i++)
currSlice->listX[1][i] = p_Vid->no_reference_picture;
#if PRINTREFLIST
#if (MVC_EXTENSION_ENABLE)
/* print out for h264_debug_flag purpose */
if ((p_Vid->profile_idc == MVC_HIGH ||
p_Vid->profile_idc == STEREO_HIGH) &&
currSlice->current_slice_nr == 0) {
if ((currSlice->listXsize[0] > 0) ||
(currSlice->listXsize[1] > 0))
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "\n");
if (currSlice->listXsize[0] > 0) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
" ** (CurViewID:%d %d) %s Ref Pic List 0 ****\n",
currSlice->view_id,
currSlice->ThisPOC,
currSlice->structure == FRAME ? "FRM" :
(currSlice->structure == TOP_FIELD ?
"TOP" : "BOT"));
for (i = 0; i < (unsigned int)(currSlice->
listXsize[0]); i++) { /* ref list 0 */
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
" %2d -> POC: %4d PicNum: %4d ViewID: %d\n",
i,
currSlice->listX[0][i]->poc,
currSlice->listX[0][i]->pic_num,
currSlice->listX[0][i]->view_id);
}
}
if (currSlice->listXsize[1] > 0) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
" ** (CurViewID:%d %d) %s Ref Pic List 1 ****\n",
currSlice->view_id,
currSlice->ThisPOC,
currSlice->structure == FRAME ? "FRM" :
(currSlice->structure == TOP_FIELD ? "TOP" :
"BOT"));
for (i = 0; i < (unsigned int)(currSlice->
listXsize[1]); i++) { /* ref list 1 */
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
" %2d -> POC: %4d PicNum: %4d ViewID: %d\n",
i,
currSlice->listX[1][i]->poc,
currSlice->listX[1][i]->pic_num,
currSlice->listX[1][i]->view_id);
}
}
}
#endif
#endif
}
static struct StorablePicture *get_short_term_pic(struct Slice *currSlice,
struct DecodedPictureBuffer *p_Dpb, int picNum)
{
unsigned int i;
struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
struct h264_dpb_stru, mDPB);
for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
if (currSlice->structure == FRAME) {
#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 == 3) {
#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->
is_long_term) &&
(p_Dpb->fs_ref[i]->frame->
pic_num == picNum))
return p_Dpb->fs_ref[i]->frame;
}
} else {
#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 & 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->
is_long_term) &&
(p_Dpb->fs_ref[i]->top_field->
pic_num == picNum))
return p_Dpb->fs_ref[i]->top_field;
}
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
if ((!p_Dpb->fs_ref[i]->bottom_field->
is_long_term) &&
(p_Dpb->fs_ref[i]->bottom_field->
pic_num == picNum))
return p_Dpb->fs_ref[i]->bottom_field;
}
}
}
return currSlice->p_Vid->no_reference_picture;
}
static void reorder_short_term(struct Slice *currSlice, int cur_list,
int num_ref_idx_lX_active_minus1,
int picNumLX, int *refIdxLX)
{
struct h264_dpb_stru *p_H264_Dpb = container_of(currSlice->p_Vid,
struct h264_dpb_stru, mVideo);
struct StorablePicture **RefPicListX = currSlice->listX[cur_list];
int cIdx, nIdx;
struct StorablePicture *picLX;
picLX = get_short_term_pic(currSlice, currSlice->p_Dpb, picNumLX);
for (cIdx = num_ref_idx_lX_active_minus1 + 1; cIdx > *refIdxLX;
cIdx--) {
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s: RefPicListX[ %d ] = RefPicListX[ %d ]\n",
__func__, cIdx, cIdx - 1);
RefPicListX[cIdx] = RefPicListX[cIdx - 1];
}
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s: RefPicListX[ %d ] = pic %x (%d)\n", __func__,
*refIdxLX, picLX, picNumLX);
RefPicListX[(*refIdxLX)++] = picLX;
nIdx = *refIdxLX;
for (cIdx = *refIdxLX; cIdx <= num_ref_idx_lX_active_minus1 + 1;
cIdx++) {
if (RefPicListX[cIdx])
if ((RefPicListX[cIdx]->is_long_term) ||
(RefPicListX[cIdx]->pic_num != picNumLX)) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"%s: RefPicListX[ %d ] = RefPicListX[ %d ]\n",
__func__, nIdx, cIdx);
RefPicListX[nIdx++] = RefPicListX[cIdx];
}
}
}
static struct StorablePicture *get_long_term_pic(struct Slice *currSlice,
struct DecodedPictureBuffer *p_Dpb, int LongtermPicNum)
{
unsigned int i;
for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
if (currSlice->structure == FRAME) {
if (p_Dpb->fs_ltref[i]->is_reference == 3)
if ((p_Dpb->fs_ltref[i]->frame) &&
(p_Dpb->fs_ltref[i]->frame->
is_long_term) &&
(p_Dpb->fs_ltref[i]->frame->
long_term_pic_num ==
LongtermPicNum))
return p_Dpb->fs_ltref[i]->frame;
} else {
if (p_Dpb->fs_ltref[i]->is_reference & 1)
if ((p_Dpb->fs_ltref[i]->top_field) &&
(p_Dpb->fs_ltref[i]->top_field->
is_long_term) &&
(p_Dpb->fs_ltref[i]->top_field->
long_term_pic_num == LongtermPicNum))
return p_Dpb->fs_ltref[i]->top_field;
if (p_Dpb->fs_ltref[i]->is_reference & 2)
if ((p_Dpb->fs_ltref[i]->bottom_field) &&
(p_Dpb->fs_ltref[i]->bottom_field->
is_long_term) &&
(p_Dpb->fs_ltref[i]->bottom_field->
long_term_pic_num ==
LongtermPicNum))
return p_Dpb->fs_ltref[i]->
bottom_field;
}
}
return NULL;
}
/*!
************************************************************************
* \brief
* Reordering process for long-term reference pictures
*
************************************************************************
*/
static void reorder_long_term(struct Slice *currSlice,
struct StorablePicture **RefPicListX,
int num_ref_idx_lX_active_minus1,
int LongTermPicNum, int *refIdxLX)
{
int cIdx, nIdx;
struct StorablePicture *picLX;
picLX = get_long_term_pic(currSlice, currSlice->p_Dpb, LongTermPicNum);
for (cIdx = num_ref_idx_lX_active_minus1 + 1; cIdx > *refIdxLX; cIdx--)
RefPicListX[cIdx] = RefPicListX[cIdx - 1];
RefPicListX[(*refIdxLX)++] = picLX;
nIdx = *refIdxLX;
for (cIdx = *refIdxLX; cIdx <= num_ref_idx_lX_active_minus1 + 1;
cIdx++) {
if (RefPicListX[cIdx]) {
if ((!RefPicListX[cIdx]->is_long_term) ||
(RefPicListX[cIdx]->long_term_pic_num !=
LongTermPicNum))
RefPicListX[nIdx++] = RefPicListX[cIdx];
}
}
}
static void reorder_ref_pic_list(struct Slice *currSlice, int cur_list)
{
int *modification_of_pic_nums_idc =
currSlice->modification_of_pic_nums_idc[cur_list];
int *abs_diff_pic_num_minus1 =
currSlice->abs_diff_pic_num_minus1[cur_list];
int *long_term_pic_idx = currSlice->long_term_pic_idx[cur_list];
int num_ref_idx_lX_active_minus1 =
currSlice->num_ref_idx_active[cur_list] - 1;
struct VideoParameters *p_Vid = currSlice->p_Vid;
int i;
int maxPicNum, currPicNum, picNumLXNoWrap, picNumLXPred, picNumLX;
int refIdxLX = 0;
if (currSlice->structure == FRAME) {
maxPicNum = p_Vid->max_frame_num;
currPicNum = currSlice->frame_num;
} else {
maxPicNum = 2 * p_Vid->max_frame_num;
currPicNum = 2 * currSlice->frame_num + 1;
}
picNumLXPred = currPicNum;
for (i = 0; i < REORDERING_COMMAND_MAX_SIZE &&
modification_of_pic_nums_idc[i] != 3; i++) {
if (modification_of_pic_nums_idc[i] > 3) {
struct h264_dpb_stru *p_H264_Dpb =
container_of(p_Vid, struct h264_dpb_stru, mVideo);
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_ERROR,
"error, Invalid modification_of_pic_nums_idc command\n");
/*h264_debug_flag = 0x1f;*/
break;
}
if (modification_of_pic_nums_idc[i] < 2) {
if (modification_of_pic_nums_idc[i] == 0) {
if (picNumLXPred - (abs_diff_pic_num_minus1[i]
+ 1) < 0)
picNumLXNoWrap = picNumLXPred -
(abs_diff_pic_num_minus1[i] + 1) +
maxPicNum;
else
picNumLXNoWrap = picNumLXPred -
(abs_diff_pic_num_minus1[i] + 1);
} else { /* (modification_of_pic_nums_idc[i] == 1) */
if (picNumLXPred + (abs_diff_pic_num_minus1[i]
+ 1) >= maxPicNum)
picNumLXNoWrap = picNumLXPred +
(abs_diff_pic_num_minus1[i] + 1) -
maxPicNum;
else
picNumLXNoWrap = picNumLXPred +
(abs_diff_pic_num_minus1[i] + 1);
}
picNumLXPred = picNumLXNoWrap;
if (picNumLXNoWrap > currPicNum)
picNumLX = picNumLXNoWrap - maxPicNum;
else
picNumLX = picNumLXNoWrap;
#if (MVC_EXTENSION_ENABLE)
reorder_short_term(currSlice, cur_list,
num_ref_idx_lX_active_minus1, picNumLX,
&refIdxLX, -1);
#else
reorder_short_term(currSlice, cur_list,
num_ref_idx_lX_active_minus1, picNumLX,
&refIdxLX);
#endif
} else { /* (modification_of_pic_nums_idc[i] == 2) */
#if (MVC_EXTENSION_ENABLE)
reorder_long_term(currSlice, currSlice->listX[cur_list],
num_ref_idx_lX_active_minus1,
long_term_pic_idx[i], &refIdxLX, -1);
#else
reorder_long_term(currSlice, currSlice->listX[cur_list],
num_ref_idx_lX_active_minus1,
long_term_pic_idx[i], &refIdxLX);
#endif
}
}
/* that's a definition */
currSlice->listXsize[cur_list] =
(char)(num_ref_idx_lX_active_minus1 + 1);
}
static void reorder_lists(struct Slice *currSlice)
{
struct VideoParameters *p_Vid = currSlice->p_Vid;
struct h264_dpb_stru *p_H264_Dpb = container_of(p_Vid,
struct h264_dpb_stru, mVideo);
int i;
if ((currSlice->slice_type != I_SLICE) &&
(currSlice->slice_type != SI_SLICE)) {
if (currSlice->ref_pic_list_reordering_flag[LIST_0])
reorder_ref_pic_list(currSlice, LIST_0);
if (p_Vid->no_reference_picture ==
currSlice->
listX[0][currSlice->num_ref_idx_active[LIST_0] - 1]) {
if (p_Vid->non_conforming_stream)
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"RefPicList0[ %d ] is equal to 'no reference picture'\n",
currSlice->
num_ref_idx_active[LIST_0] - 1);
else
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"RefPicList0 [ num_ref_idx_l0_active_minus1 ] is equal to 'no reference picture', invalid bitstream %d\n",
500);
}
/* that's a definition */
currSlice->listXsize[0] =
(char) imin(currSlice->listXsize[0],
currSlice->num_ref_idx_active[LIST_0]);
CHECK_VALID(currSlice->listXsize[0], 0);
if (h264_debug_flag & PRINT_FLAG_DPB_DETAIL) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"listX[0] reorder (PicNum): ");
for (i = 0; i < currSlice->listXsize[0]; i++) {
dpb_print_cont(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "%d ",
currSlice->listX[0][i]->pic_num);
}
dpb_print_cont(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "\n");
}
}
if (currSlice->slice_type == B_SLICE) {
if (currSlice->ref_pic_list_reordering_flag[LIST_1])
reorder_ref_pic_list(currSlice, LIST_1);
if (p_Vid->no_reference_picture ==
currSlice->listX[1][currSlice->
num_ref_idx_active[LIST_1] - 1]) {
if (p_Vid->non_conforming_stream)
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"RefPicList1[ %d ] is equal to 'no reference picture'\n",
currSlice->
num_ref_idx_active[LIST_1] - 1);
else
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"RefPicList1 [ num_ref_idx_l1_active_minus1 ] is equal to 'no reference picture', invalid bitstream %d\n",
500);
}
/* that's a definition */
currSlice->listXsize[1] =
(char)currSlice->num_ref_idx_active[LIST_1];
if (h264_debug_flag & PRINT_FLAG_DPB_DETAIL) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"listX[1] reorder (PicNum): ");
for (i = 0; i < currSlice->listXsize[1]; i++) {
if (currSlice->listX[1][i])
dpb_print_cont(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "%d ",
currSlice->listX[1][i]->pic_num);
}
dpb_print_cont(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "\n");
}
}
/* free_ref_pic_list_reordering_buffer(currSlice); */
if (currSlice->slice_type == P_SLICE) {
#if PRINTREFLIST
unsigned int i;
#if (MVC_EXTENSION_ENABLE)
/* print out for h264_debug_flag purpose */
if ((p_Vid->profile_idc == MVC_HIGH ||
p_Vid->profile_idc == STEREO_HIGH) &&
currSlice->current_slice_nr == 0) {
if (currSlice->listXsize[0] > 0
&& (h264_debug_flag & PRINT_FLAG_DPB_DETAIL)) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "\n");
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
" ** (FinalViewID:%d) %s Ref Pic List 0 ****\n",
currSlice->view_id,
currSlice->structure == FRAME ?
"FRM" :
(currSlice->structure == TOP_FIELD ?
"TOP" : "BOT"));
for (i = 0; i < (unsigned int)(currSlice->
listXsize[0]); i++) { /* ref list 0 */
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
" %2d -> POC: %4d PicNum: %4d ViewID: %d\n",
i,
currSlice->listX[0][i]->poc,
currSlice->listX[0][i]->
pic_num,
currSlice->listX[0][i]->
view_id);
}
}
}
#endif
#endif
} else if (currSlice->slice_type == B_SLICE) {
#if PRINTREFLIST
unsigned int i;
#if (MVC_EXTENSION_ENABLE)
/* print out for h264_debug_flag purpose */
if ((p_Vid->profile_idc == MVC_HIGH ||
p_Vid->profile_idc == STEREO_HIGH) &&
currSlice->current_slice_nr == 0) {
if ((currSlice->listXsize[0] > 0) ||
(currSlice->listXsize[1] > 0))
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL, "\n");
if (currSlice->listXsize[0] > 0
&& (h264_debug_flag & PRINT_FLAG_DPB_DETAIL)) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
" ** (FinalViewID:%d) %s Ref Pic List 0 ****\n",
currSlice->view_id,
currSlice->structure == FRAME ?
"FRM" :
(currSlice->structure == TOP_FIELD ?
"TOP" : "BOT"));
for (i = 0; i < (unsigned int)(currSlice->
listXsize[0]); i++) { /* ref list 0 */
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
" %2d -> POC: %4d PicNum: %4d ViewID: %d\n",
i,
currSlice->listX[0][i]->poc,
currSlice->listX[0][i]->
pic_num,
currSlice->listX[0][i]->
view_id);
}
}
if (currSlice->listXsize[1] > 0
&& (h264_debug_flag & PRINT_FLAG_DPB_DETAIL)) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
" ** (FinalViewID:%d) %s Ref Pic List 1 ****\n",
currSlice->view_id,
currSlice->structure == FRAME ?
"FRM" :
(currSlice->structure == TOP_FIELD ?
"TOP" : "BOT"));
for (i = 0; i < (unsigned int)(currSlice->
listXsize[1]); i++) { /* ref list 1 */
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
" %2d -> POC: %4d PicNum: %4d ViewID: %d\n",
i,
currSlice->listX[1][i]->poc,
currSlice->listX[1][i]->
pic_num,
currSlice->listX[1][i]->
view_id);
}
}
}
#endif
#endif
}
}
void init_colocate_buf(struct h264_dpb_stru *p_H264_Dpb, int count)
{
p_H264_Dpb->colocated_buf_map = 0;
p_H264_Dpb->colocated_buf_count = count;
}
int allocate_colocate_buf(struct h264_dpb_stru *p_H264_Dpb)
{
int i;
for (i = 0; i < p_H264_Dpb->colocated_buf_count; i++) {
if (((p_H264_Dpb->colocated_buf_map >> i) & 0x1) == 0) {
p_H264_Dpb->colocated_buf_map |= (1 << i);
break;
}
}
if (i == p_H264_Dpb->colocated_buf_count) {
i = -1;
p_H264_Dpb->buf_alloc_fail = 1;
}
return i;
}
int release_colocate_buf(struct h264_dpb_stru *p_H264_Dpb, int index)
{
if (index >= 0) {
if (index >= p_H264_Dpb->colocated_buf_count) {
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_ERROR,
"%s error, index %d is bigger than buf count %d\n",
__func__, index,
p_H264_Dpb->colocated_buf_count);
} else {
if (((p_H264_Dpb->colocated_buf_map >>
index) & 0x1) == 0x1) {
p_H264_Dpb->colocated_buf_map &=
(~(1 << index));
} else {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_ERROR,
"%s error, index %d is not allocated\n",
__func__, index);
}
}
}
return 0;
}
void set_frame_output_flag(struct h264_dpb_stru *p_H264_Dpb, int index)
{
struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
p_H264_Dpb->mFrameStore[index].is_output = 1;
p_H264_Dpb->mFrameStore[index].pre_output = 0;
p_H264_Dpb->mFrameStore[index].show_frame = false;
dump_dpb(p_Dpb, 0);
}
#if 0
void init_old_slice(OldSliceParams *p_old_slice)
{
p_old_slice->field_pic_flag = 0;
p_old_slice->pps_id = INT_MAX;
p_old_slice->frame_num = INT_MAX;
p_old_slice->nal_ref_idc = INT_MAX;
p_old_slice->idr_flag = 0;
p_old_slice->pic_oder_cnt_lsb = UINT_MAX;
p_old_slice->delta_pic_oder_cnt_bottom = INT_MAX;
p_old_slice->delta_pic_order_cnt[0] = INT_MAX;
p_old_slice->delta_pic_order_cnt[1] = INT_MAX;
}
void copy_slice_info(struct Slice *currSlice, OldSliceParams *p_old_slice)
{
struct VideoParameters *p_Vid = currSlice->p_Vid;
p_old_slice->pps_id = currSlice->pic_parameter_set_id;
p_old_slice->frame_num = currSlice->frame_num;
/* p_Vid->frame_num; */
p_old_slice->field_pic_flag =
currSlice->field_pic_flag;
/* p_Vid->field_pic_flag; */
if (currSlice->field_pic_flag)
p_old_slice->bottom_field_flag = currSlice->bottom_field_flag;
p_old_slice->nal_ref_idc = currSlice->nal_reference_idc;
p_old_slice->idr_flag = (byte) currSlice->idr_flag;
if (currSlice->idr_flag)
p_old_slice->idr_pic_id = currSlice->idr_pic_id;
if (p_Vid->active_sps->pic_order_cnt_type == 0) {
p_old_slice->pic_oder_cnt_lsb =
currSlice->pic_order_cnt_lsb;
p_old_slice->delta_pic_oder_cnt_bottom =
currSlice->delta_pic_order_cnt_bottom;
}
if (p_Vid->active_sps->pic_order_cnt_type == 1) {
p_old_slice->delta_pic_order_cnt[0] =
currSlice->delta_pic_order_cnt[0];
p_old_slice->delta_pic_order_cnt[1] =
currSlice->delta_pic_order_cnt[1];
}
#if (MVC_EXTENSION_ENABLE)
p_old_slice->view_id = currSlice->view_id;
p_old_slice->inter_view_flag = currSlice->inter_view_flag;
p_old_slice->anchor_pic_flag = currSlice->anchor_pic_flag;
#endif
p_old_slice->layer_id = currSlice->layer_id;
}
int is_new_picture(StorablePicture *dec_picture, struct Slice *currSlice,
OldSliceParams *p_old_slice)
{
struct VideoParameters *p_Vid = currSlice->p_Vid;
int result = 0;
result |= (dec_picture == NULL);
result |= (p_old_slice->pps_id != currSlice->pic_parameter_set_id);
result |= (p_old_slice->frame_num != currSlice->frame_num);
result |= (p_old_slice->field_pic_flag != currSlice->field_pic_flag);
if (currSlice->field_pic_flag && p_old_slice->field_pic_flag) {
result |= (p_old_slice->bottom_field_flag !=
currSlice->bottom_field_flag);
}
result |= (p_old_slice->nal_ref_idc !=
currSlice->nal_reference_idc) &&
((p_old_slice->nal_ref_idc == 0) ||
(currSlice->nal_reference_idc == 0));
result |= (p_old_slice->idr_flag != currSlice->idr_flag);
if (currSlice->idr_flag && p_old_slice->idr_flag)
result |= (p_old_slice->idr_pic_id != currSlice->idr_pic_id);
if (p_Vid->active_sps->pic_order_cnt_type == 0) {
result |= (p_old_slice->pic_oder_cnt_lsb !=
currSlice->pic_order_cnt_lsb);
if (p_Vid->active_pps->
bottom_field_pic_order_in_frame_present_flag == 1 &&
!currSlice->field_pic_flag) {
result |= (p_old_slice->delta_pic_oder_cnt_bottom !=
currSlice->delta_pic_order_cnt_bottom);
}
}
if (p_Vid->active_sps->pic_order_cnt_type == 1) {
if (!p_Vid->active_sps->delta_pic_order_always_zero_flag) {
result |= (p_old_slice->delta_pic_order_cnt[0] !=
currSlice->delta_pic_order_cnt[0]);
if (p_Vid->active_pps->
bottom_field_pic_order_in_frame_present_flag == 1 &&
!currSlice->field_pic_flag) {
result |= (p_old_slice->
delta_pic_order_cnt[1] !=
currSlice->delta_pic_order_cnt[1]);
}
}
}
#if (MVC_EXTENSION_ENABLE)
result |= (currSlice->view_id != p_old_slice->view_id);
result |= (currSlice->inter_view_flag != p_old_slice->inter_view_flag);
result |= (currSlice->anchor_pic_flag != p_old_slice->anchor_pic_flag);
#endif
result |= (currSlice->layer_id != p_old_slice->layer_id);
return result;
}
#else
int is_new_picture(struct StorablePicture *dec_picture,
struct h264_dpb_stru *p_H264_Dpb,
struct OldSliceParams *p_old_slice)
{
int ret = 0;
if (p_H264_Dpb->dpb_param.l.data[FIRST_MB_IN_SLICE] == 0)
ret = 1;
return ret;
}
#endif
/*
* release bufspec and pic for picture not in dpb buf
*/
int release_picture(struct h264_dpb_stru *p_H264_Dpb,
struct StorablePicture *pic)
{
struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
if (p_Dpb->last_picture == NULL) {
if (pic->colocated_buf_index >= 0) {
release_colocate_buf(p_H264_Dpb,
pic->colocated_buf_index);
pic->colocated_buf_index = -1;
}
release_buf_spec_num(p_H264_Dpb->vdec, pic->buf_spec_num);
} else {
if (pic->buf_spec_is_alloced == 1)
release_buf_spec_num(p_H264_Dpb->vdec,
pic->buf_spec_num);
}
free_picture(p_H264_Dpb, pic);
return 0;
}
#ifdef ERROR_HANDLE_TEST
/*
* remove all pictures in dpb and release bufspec/pic of them
*/
void remove_dpb_pictures(struct h264_dpb_stru *p_H264_Dpb)
{
/* struct VideoParameters *p_Vid = p_Dpb->p_Vid; */
struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
struct Slice *currSlice = &p_H264_Dpb->mSlice;
unsigned i, j;
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"%s\n", __func__);
if (!p_Dpb->init_done)
return;
for (i = 0; i < p_Dpb->used_size; i++) {
if (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;
}
if (!p_Dpb->fs[i]->pre_output) {
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);
}
for (i = 0; i < p_Dpb->used_size; i++) {
p_Dpb->fs_ref[i] = NULL;
p_Dpb->fs_ltref[i] = NULL;
p_Dpb->fs_list0[i] = NULL;
p_Dpb->fs_list1[i] = NULL;
p_Dpb->fs_listlt[i] = NULL;
}
for (i = 0; i < 2; i++) {
currSlice->listXsize[i] = 0;
for (j = 0; j < (MAX_LIST_SIZE * 2); j++)
currSlice->listX[i][j] = NULL;
}
p_Dpb->ref_frames_in_buffer = 0;
p_Dpb->ltref_frames_in_buffer = 0;
p_Dpb->last_output_poc = INT_MIN;
}
#endif
static void check_frame_store_same_pic_num(struct DecodedPictureBuffer *p_Dpb,
struct StorablePicture *p, struct Slice *currSlice)
{
if (p_Dpb->last_picture) {
if ((int)p_Dpb->last_picture->frame_num == p->pic_num) {
if (((p->structure == TOP_FIELD) &&
(p_Dpb->last_picture->is_used == 2)) ||
((p->structure == BOTTOM_FIELD) &&
(p_Dpb->last_picture->is_used == 1))) {
if ((p->used_for_reference &&
(p_Dpb->last_picture->
is_orig_reference != 0)) ||
(!p->used_for_reference &&
(p_Dpb->last_picture->
is_orig_reference == 0))) {
p->buf_spec_num =
p_Dpb->last_picture->
buf_spec_num;
p->buf_spec_is_alloced = 0;
p->colocated_buf_index = p_Dpb->
last_picture->
colocated_buf_index;
if (currSlice->structure ==
TOP_FIELD) {
p->bottom_poc =
p_Dpb->last_picture->
bottom_field->poc;
} else {
p->top_poc =
p_Dpb->last_picture->
top_field->poc;
}
p->frame_poc = imin(p->bottom_poc,
p->top_poc);
}
}
}
}
}
int h264_slice_header_process(struct h264_dpb_stru *p_H264_Dpb, int *frame_num_gap)
{
int new_pic_flag = 0;
struct Slice *currSlice = &p_H264_Dpb->mSlice;
struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo;
struct DecodedPictureBuffer *p_Dpb =
&p_H264_Dpb->mDPB;
#if 0
new_pic_flag = is_new_picture(p_H264_Dpb->mVideo.dec_picture,
p_H264_Dpb,
&p_H264_Dpb->mVideo.old_slice);
if (new_pic_flag) { /* new picture */
if (p_H264_Dpb->mVideo.dec_picture) {
store_picture_in_dpb(p_H264_Dpb,
p_H264_Dpb->mVideo.dec_picture);
/* dump_dpb(&p_H264_Dpb->mDPB); */
}
}
#else
new_pic_flag = (p_H264_Dpb->mVideo.dec_picture == NULL);
#endif
p_H264_Dpb->buf_alloc_fail = 0;
p_H264_Dpb->dpb_error_flag = 0;
slice_prepare(p_H264_Dpb, &p_H264_Dpb->mDPB, &p_H264_Dpb->mVideo,
&p_H264_Dpb->mSPS, &p_H264_Dpb->mSlice);
if (p_Dpb->num_ref_frames != p_H264_Dpb->mSPS.num_ref_frames) {
dpb_print(p_H264_Dpb->decoder_index, 0,
"num_ref_frames change from %d to %d\r\n",
p_Dpb->num_ref_frames, p_H264_Dpb->mSPS.num_ref_frames);
p_Dpb->num_ref_frames = p_H264_Dpb->mSPS.num_ref_frames;
}
/* if (p_Vid->active_sps != sps) { */
if (p_H264_Dpb->mDPB.init_done == 0) {
/*init_global_buffers(p_Vid, 0);
* ** * *if (!p_Vid->no_output_of_prior_pics_flag)
** * *{
** * * flush_dpb(p_Vid->p_Dpb_layer[0]);
** * *}
** * *init_dpb(p_Vid, p_Vid->p_Dpb_layer[0], 0);
*/
init_dpb(p_H264_Dpb, 0);
}
if (new_pic_flag) { /* new picture */
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"check frame_num gap: cur frame_num %d pre_frame_num %d max_frmae_num %d\r\n",
currSlice->frame_num,
p_Vid->pre_frame_num,
p_Vid->max_frame_num);
if (p_Vid->recovery_point == 0 &&
p_Vid->max_frame_num <= FRAME_NUM_MAX_SIZE &&
currSlice->frame_num != p_Vid->pre_frame_num &&
currSlice->frame_num !=
(p_Vid->pre_frame_num + 1) % p_Vid->max_frame_num) {
struct SPSParameters *active_sps = p_Vid->active_sps;
/*if (active_sps->
*gaps_in_frame_num_value_allowed_flag
*== 0) {
* error("An unintentional
* loss of pictures occurs! Exit\n",
* 100);
*}
*if (p_Vid->conceal_mode == 0)
*/
if (active_sps->frame_num_gap_allowed)
fill_frame_num_gap(p_Vid, currSlice);
*frame_num_gap = 1;
}
if (currSlice->nal_reference_idc) {
dpb_print(p_H264_Dpb->decoder_index,
PRINT_FLAG_DPB_DETAIL,
"nal_reference_idc not 0, set pre_frame_num(%d) to frame_num (%d)\n",
p_Vid->pre_frame_num, currSlice->frame_num);
p_Vid->pre_frame_num = currSlice->frame_num;
}
decode_poc(&p_H264_Dpb->mVideo, &p_H264_Dpb->mSlice);
p_H264_Dpb->mVideo.dec_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 (p_H264_Dpb->mVideo.dec_picture) {
u32 offset_lo, offset_hi;
struct DecodedPictureBuffer *p_Dpb =
&p_H264_Dpb->mDPB;
struct StorablePicture *p =
p_H264_Dpb->mVideo.dec_picture;
init_picture(p_H264_Dpb, &p_H264_Dpb->mSlice,
p_H264_Dpb->mVideo.dec_picture);
#if 1
/* rain */
offset_lo =
p_H264_Dpb->dpb_param.l.data[OFFSET_DELIMITER_LO];
offset_hi =
p_H264_Dpb->dpb_param.l.data[OFFSET_DELIMITER_HI];
p_H264_Dpb->mVideo.dec_picture->offset_delimiter =
(offset_lo | offset_hi << 16);
p_H264_Dpb->mVideo.dec_picture->buf_spec_num = -1;
p_H264_Dpb->mVideo.dec_picture->
colocated_buf_index = -1;
update_pic_num(p_H264_Dpb);
if ((currSlice->structure == TOP_FIELD) ||
(currSlice->structure == BOTTOM_FIELD)) {
/* check for frame store with same
* pic_number
*/
check_frame_store_same_pic_num(p_Dpb, p,
currSlice);
}
if (p_H264_Dpb->mVideo.dec_picture->buf_spec_num ==
-1) {
p_H264_Dpb->mVideo.dec_picture->buf_spec_num =
get_free_buf_idx(p_H264_Dpb->vdec);
if (p_H264_Dpb->mVideo.dec_picture->buf_spec_num
< 0) {
p_H264_Dpb->buf_alloc_fail = 1;
p_H264_Dpb->mVideo.dec_picture->
buf_spec_is_alloced = 0;
} else
p_H264_Dpb->mVideo.dec_picture->
buf_spec_is_alloced = 1;
if (p_H264_Dpb->mVideo.dec_picture->
used_for_reference) {
p_H264_Dpb->mVideo.dec_picture->
colocated_buf_index =
allocate_colocate_buf(
p_H264_Dpb);
}
}
#endif
if (post_picture_early(p_H264_Dpb->vdec,
p_H264_Dpb->mVideo.dec_picture->buf_spec_num))
return -1;
}
}
if (p_H264_Dpb->buf_alloc_fail)
return -1;
if (p_H264_Dpb->mSlice.slice_type == P_SLICE)
init_lists_p_slice(&p_H264_Dpb->mSlice);
else if (p_H264_Dpb->mSlice.slice_type == B_SLICE)
init_lists_b_slice(&p_H264_Dpb->mSlice);
else
init_lists_i_slice(&p_H264_Dpb->mSlice);
reorder_lists(&p_H264_Dpb->mSlice);
if (p_H264_Dpb->mSlice.structure == FRAME)
init_mbaff_lists(p_H264_Dpb, &p_H264_Dpb->mSlice);
if (new_pic_flag)
return 1;
return 0;
}
enum PictureStructure get_cur_slice_picture_struct(
struct h264_dpb_stru *p_H264_Dpb)
{
struct Slice *currSlice = &p_H264_Dpb->mSlice;
return currSlice->structure;
}
static unsigned char is_pic_in_dpb(struct h264_dpb_stru *p_H264_Dpb,
struct StorablePicture *pic)
{
unsigned char ret = 0;
int i;
struct DecodedPictureBuffer *p_Dpb =
&p_H264_Dpb->mDPB;
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) {
ret = 1;
break;
}
}
return ret;
}
int dpb_check_ref_list_error(
struct h264_dpb_stru *p_H264_Dpb)
{
int i;
/*int j;*/
struct Slice *currSlice = &p_H264_Dpb->mSlice;
/* in first output, ignore ref check */
if ((p_H264_Dpb->first_insert_frame == FirstInsertFrm_OUT) &&
(p_H264_Dpb->mVideo.dec_picture) &&
p_H264_Dpb->first_output_poc > p_H264_Dpb->mVideo.dec_picture->poc) {
dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
"p_H264_Dpb->first_output_poc %d, p_H264_Dpb->mVideo.dec_picture->poc %d\n",
p_H264_Dpb->first_output_poc, p_H264_Dpb->mVideo.dec_picture->poc);
return 0;
}
if ((currSlice->slice_type != I_SLICE) &&
(currSlice->slice_type != SI_SLICE)) {
for (i = 0; i < currSlice->listXsize[0]; i++) {
/*for (j = i + 1; j < currSlice->listXsize[0]; j++) {
if(currSlice->listX[0][i]->pic_num ==
currSlice->listX[0][j]->pic_num)
return 1;
}*/
if (currSlice->listX[0][i] == NULL)
return 5;
if (!is_pic_in_dpb(p_H264_Dpb,
currSlice->listX[0][i]))
return 1;
if (currSlice->listX[0][i]->frame &&
currSlice->listX[0][i]->frame->non_existing)
return 3;
}
}
if (currSlice->slice_type == B_SLICE) {
for (i = 0; i < currSlice->listXsize[1]; i++) {
/*for (j = i + 1; j < currSlice->listXsize[1]; j++) {
if(currSlice->listX[1][i]->pic_num ==
currSlice->listX[1][j]->pic_num)
return 2;
}
for (j = 0; j < currSlice->listXsize[0]; j++) {
if(currSlice->listX[1][i]->pic_num ==
currSlice->listX[0][j]->pic_num)
return 3;
}*/
if (currSlice->listX[1][i] == NULL)
return 6;
if (!is_pic_in_dpb(p_H264_Dpb,
currSlice->listX[1][i]))
return 2;
if (currSlice->listX[1][i]->frame &&
currSlice->listX[1][i]->frame->non_existing)
return 4;
#if 0
if (currSlice->listXsize[0] == 1 &&
currSlice->listXsize[1] == 1 &&
currSlice->listX[1][0] ==
currSlice->listX[0][0])
return 3;
#endif
}
}
return 0;
}