| /* |
| * Copyright (C) 2017 Amlogic, Inc. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| * more details. |
| * |
| * You should have received a copy of the GNU General Public License along |
| * with this program; if not, write to the Free Software Foundation, Inc., |
| * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| * |
| * Description: |
| */ |
| #define DEBUG |
| #include <linux/kernel.h> |
| #include <linux/types.h> |
| #include <linux/errno.h> |
| |
| #include <linux/amlogic/media/utils/vdec_reg.h> |
| #include "../utils/vdec.h" |
| #include "../utils/amvdec.h" |
| |
| #include "h264_dpb.h" |
| |
| #define FRAME_NUM_MAX_SIZE 0x10000 |
| |
| #undef pr_info |
| #define pr_info printk |
| int dpb_print(int index, int debug_flag, const char *fmt, ...) |
| { |
| if (((h264_debug_flag & debug_flag) && |
| ((1 << index) & h264_debug_mask)) |
| || (debug_flag == PRINT_FLAG_ERROR)) { |
| unsigned char *buf = 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; |
| } |
| 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; |
| 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) |
| { |