blob: 54c96dba535eecd6ae1085122a69a78097827838 [file] [log] [blame]
/* Any workload management goes in this file */
#include "viddec_fw_debug.h"
#include "viddec_parser_ops.h"
#include "h264.h"
#include "h264parse.h"
#include "viddec_fw_item_types.h"
#include "h264parse_dpb.h"
#include "viddec_fw_workload.h"
#include <auto_eas/gen4_mfd.h>
#include "viddec_pm_utils_bstream.h"
// picture parameter 1
#define PUT_BSD_PP1_IMG_DISPOSABLE_FLAG_BIT(w) (((uint32_t)w)&0x1)
#define PUT_BSD_PP1_SLICE_TYPE_BITS(w) ((((uint32_t)w)&0x7)<<1)
#define PUT_BSD_PP1_WEIGHTED_BIPRED_IDC_BITS(w) ((((uint32_t)w)&0x3)<<4)
#define PUT_BSD_PP1_WEIGHTED_PRED_FLAG_BIT(w) ((((uint32_t)w)&0x1)<<6)
#define PUT_BSD_PP1_NUM_REF_IDX_L0_BITS(w) ((((uint32_t)w)&0x3F)<<8)
#define PUT_BSD_PP1_NUM_REF_IDX_L1_BITS(w) ((((uint32_t)w)&0x3F)<<16)
// picture parameter 2
#define PUT_BSD_PP2_CABAC_INIT_IDC_BITS(w) (((uint32_t)w)&0x3)
#define PUT_BSD_PP2_QP_BITS(w) ((((uint32_t)w)&0x3F)<<2)
#define PUT_BSD_PP2_DISABLE_DBF_IDC_BITS(w) ((((uint32_t)w)&0x3)<<8)
#define PUT_BSD_PP2_ALPHA_C0_OFFSET_DIV2_BITS(w) ((((uint32_t)w)&0xF)<<10)
#define PUT_BSD_PP2_BETA_OFFSET_DIV2_BITS(w) ((((uint32_t)w)&0xF)<<14)
#define PUT_BSD_PP2_IMG_DIRECT_TYPE_BIT(w) ((((uint32_t)w)&0x1)<<18)
#define PUT_BSD_PP2_CHROMA_QP_OFFSET_BITS(w) ((((uint32_t)w)&0x1F)<<19)
#define PUT_BSD_PP2_CHROMA_QP_OFFSET_2_BITS(w) ((((uint32_t)w)&0x1F)<<24)
// slice start parameter
#define PUT_BSD_SS_START_ADDR_BITS(w) (((uint32_t)w)&0x7fff) // 14:0 current slice start address
#define PUT_BSD_SS_SKIP_FS_IDC_BITS(w) ((((uint32_t)w)&0x3f)<<16) // [5:0], [4:0] frame store idc, [5] - 0: top-filed, 1: bottom field
#define PUT_BSD_SS_SKIP_TYPE_BIT(w) ((((uint32_t)w)&0x1)<<24) // 0: P-skip, 1: I-skip
#define PUT_BSD_SS_SKIP_REWIND_BITS(w) ((((uint32_t)w)&0xf)<<28) // number of MB or MBAFF pairs to rewind before skip
//h264_dpb_init
#define PUT_FRAME_WIDTH_MB_BITS(w) (((uint32_t)w)&0x7F)
#define PUT_FRAME_HEIGHT_MB_BITS(w) ((((uint32_t)w)&0x7F)<<16)
//dpb lut table init
//#define PUT_BSD_IMAGE_FRAME_STORE_IDC_BITS(w) ((((uint32_t)w)&0x1F)<<8)
//h264 img init
#define PUT_BSD_IMAGE_STRUCTURE_BITS(w) (((uint32_t)w)&0x3)
#define PUT_BSD_IMAGE_IDR_BIT(w) ((((uint32_t)w)&0x1)<<2)
#define PUT_BSD_IMAGE_MBAFF_FRAME_FLAG_BIT(w) ((((uint32_t)w)&0x1)<<3)
#define PUT_BSD_IMAGE_ENTROPY_CODING_MODE_FLAG_BIT(w) ((((uint32_t)w)&0x1)<<4)
#define PUT_BSD_IMAGE_CONSTRAINED_INTRA_PRED_FLAG_BIT(w) ((((uint32_t)w)&0x1)<<5)
#define PUT_BSD_IMG_FRAME_MBS_ONLY_FLAG_BIT(w) ((((uint32_t)w)&0x1)<<6)
#define PUT_BSD_IMG_DIRECT_8X8_INFER_FLAG_BIT(w) ((((uint32_t)w)&0x1)<<7)
#define PUT_BSD_IMAGE_FRAME_STORE_IDC_BITS(w) ((((uint32_t)w)&0x1F)<<8)
#define PUT_HPD_BSD_IMG_TRANSFORM_8X8_MODE_FLAG_BIT(w) ((((uint32_t)w)&0x1)<<13)
#define PUT_HPD_BSD_IMG_MONOCHROME_FLAG_BIT(w) ((((uint32_t)w)&0x1)<<14)
#define PUT_HPD_BSD_IMG_GREY_NONEXISTING_FLAG_BIT(w) ((((uint32_t)w)&0x1)<<15)
#define PUT_HPD_BSD_IMG_QM_PRESENT_FLAG_BIT(w) ((((uint32_t)w)&0x1)<<16)
#define PUT_HPD_BSD_IMG_QM_LIST_FLAGS_BITS(w) ((((uint32_t)w)&0xFF)<<17)
#define PUT_HPD_BSD_IMG_MONOCHROME_PWT_FLAG_BIT(w) ((((uint32_t)w)&0x1)<<25)
extern void h264_dpb_store_previous_picture_in_dpb(h264_Info * pInfo,
int32_t NonExisting,
int32_t use_old);
extern void h264_dpb_flush_dpb (h264_Info * pInfo,int32_t output_all, int32_t keep_complement, int32_t num_ref_frames);
void h264_translate_parser_info_to_frame_attributes(viddec_workload_t *wl, h264_Info *pInfo)
{
viddec_frame_attributes_t *attrs = &wl->attrs;
//// Cont_size
attrs->cont_size.height = pInfo->img.FrameHeightInMbs*16;
attrs->cont_size.width = pInfo->img.PicWidthInMbs*16;
//// The following attributes will be updated in slice level
attrs->h264.used_for_reference = 0;
attrs->h264.top_field_first = 0;
attrs->h264.top_field_poc = 0;
attrs->h264.bottom_field_poc = 0;
attrs->h264.field_pic_flag = 0;
#if 1
/// Double check the size late!!!!!
//attrs->h264.cropped_size.width = pInfo->img.PicWidthInMbs*16;
//attrs->h264.cropped_size.height = pInfo->img.PicWidthInMbs*16;
if ( (pInfo->active_SPS.sps_disp.frame_cropping_flag) &&
(pInfo->active_SPS.sps_disp.chroma_format_idc < 4))
{
int32_t CropUnitX, CropUnitY;
int32_t SubWidthC, SubHeightC;
if (pInfo->active_SPS.sps_disp.chroma_format_idc == 0)
{
CropUnitX = 1;
CropUnitY = 2 - pInfo->active_SPS.sps_disp.frame_mbs_only_flag;
}
else
{
SubWidthC = 2 - ((pInfo->active_SPS.sps_disp.chroma_format_idc - 1) >> 1);
SubHeightC = 2 - ((pInfo->active_SPS.sps_disp.chroma_format_idc - 1) >>1)
- ((pInfo->active_SPS.sps_disp.chroma_format_idc - 1) & 0x1);
CropUnitX = SubWidthC;
CropUnitY = SubHeightC * (2 - pInfo->active_SPS.sps_disp.frame_mbs_only_flag);
}
if ((int32_t)attrs->cont_size.height >(pInfo->active_SPS.sps_disp.frame_crop_rect_bottom_offset*CropUnitY))
{
attrs->cont_size.height -= (pInfo->active_SPS.sps_disp.frame_crop_rect_bottom_offset*CropUnitY);
//attrs->h264.cropped_size.height-= (pInfo->active_SPS.sps_disp.frame_crop_rect_bottom_offset*CropUnitY);
}
}
/// Pan-Scan Info
#endif
}
static void h264_parse_update_frame_attributes(void *parent, h264_Info *pInfo)
{
viddec_workload_t *wl_cur, *wl_next;
viddec_frame_attributes_t *attrs;
uint8_t frame_type=0;
if (pInfo->push_to_cur) //cur is empty, fill new frame in cur
{
wl_cur = viddec_pm_get_header( parent );
attrs = &wl_cur->attrs;
}
else
{
wl_next = viddec_pm_get_next_header (parent);
attrs = &wl_next->attrs;
}
/////////update frame type
if ((pInfo->dpb.fs[pInfo->dpb.fs_dec_idc].pic_type)&(0x1 << FRAME_TYPE_STRUCTRUE_OFFSET))
{
frame_type = ( (pInfo->dpb.fs[pInfo->dpb.fs_dec_idc].pic_type)&((0x7 << FRAME_TYPE_FRAME_OFFSET)) )>> FRAME_TYPE_FRAME_OFFSET;
switch (frame_type)
{
case FRAME_TYPE_IDR:
attrs->frame_type = VIDDEC_FRAME_TYPE_IDR;
break;
case FRAME_TYPE_I:
attrs->frame_type = VIDDEC_FRAME_TYPE_I;
break;
case FRAME_TYPE_P:
attrs->frame_type = VIDDEC_FRAME_TYPE_P;
break;
case FRAME_TYPE_B:
attrs->frame_type = VIDDEC_FRAME_TYPE_B;
break;
default:
attrs->frame_type = VIDDEC_FRAME_TYPE_INVALID;
break;
}
attrs->bottom_field_type = VIDDEC_FRAME_TYPE_INVALID;
}
else
{
frame_type = ( (pInfo->dpb.fs[pInfo->dpb.fs_dec_idc].pic_type)&((0x7 << FRAME_TYPE_TOP_OFFSET)) )>> FRAME_TYPE_TOP_OFFSET;
switch (frame_type)
{
case FRAME_TYPE_IDR:
attrs->frame_type = VIDDEC_FRAME_TYPE_IDR;
break;
case FRAME_TYPE_I:
attrs->frame_type = VIDDEC_FRAME_TYPE_I;
break;
case FRAME_TYPE_P:
attrs->frame_type = VIDDEC_FRAME_TYPE_P;
break;
case FRAME_TYPE_B:
attrs->frame_type = VIDDEC_FRAME_TYPE_B;
break;
default:
attrs->frame_type = VIDDEC_FRAME_TYPE_INVALID;
break;
}
frame_type = ( (pInfo->dpb.fs[pInfo->dpb.fs_dec_idc].pic_type)&((0x7 << FRAME_TYPE_BOTTOM_OFFSET)) )>> FRAME_TYPE_BOTTOM_OFFSET;
switch (frame_type)
{
case FRAME_TYPE_IDR:
attrs->bottom_field_type = VIDDEC_FRAME_TYPE_IDR;
break;
case FRAME_TYPE_I:
attrs->bottom_field_type = VIDDEC_FRAME_TYPE_I;
break;
case FRAME_TYPE_P:
attrs->bottom_field_type = VIDDEC_FRAME_TYPE_P;
break;
case FRAME_TYPE_B:
attrs->bottom_field_type = VIDDEC_FRAME_TYPE_B;
break;
default:
attrs->bottom_field_type = VIDDEC_FRAME_TYPE_INVALID;
break;
}
}
/////////update is_referece flag
attrs->h264.used_for_reference |= (pInfo->SliceHeader.nal_ref_idc == 0)? 0: 1;
/////////update POC
attrs->h264.top_field_poc = pInfo->img.toppoc;
attrs->h264.bottom_field_poc = pInfo->img.bottompoc;
//////// update TFF
if (attrs->h264.top_field_poc <= attrs->h264.bottom_field_poc) {
attrs->h264.top_field_first = 1;
} else {
attrs->h264.top_field_first = 0;
}
/////// update field_pic_flag
//attrs->h264.field_pic_flag |= (pInfo->SliceHeader.field_pic_flag << pInfo->SliceHeader.bottom_field_flag);
attrs->h264.field_pic_flag |= pInfo->SliceHeader.field_pic_flag;
return;
}
static void h264_fill_slice_data(h264_Info *pInfo, h264_slice_data * p_slice_data)
{
uint32_t data=0;
uint32_t first_mb_in_slice =0;
////////////fill pic parameters 1
data = PUT_BSD_PP1_IMG_DISPOSABLE_FLAG_BIT( (pInfo->SliceHeader.nal_ref_idc == 0) ) +
PUT_BSD_PP1_SLICE_TYPE_BITS(pInfo->SliceHeader.slice_type) +
PUT_BSD_PP1_WEIGHTED_BIPRED_IDC_BITS(pInfo->active_PPS.weighted_bipred_idc) +
PUT_BSD_PP1_WEIGHTED_PRED_FLAG_BIT(pInfo->active_PPS.weighted_pred_flag) +
PUT_BSD_PP1_NUM_REF_IDX_L0_BITS(pInfo->SliceHeader.num_ref_idx_l0_active) +
PUT_BSD_PP1_NUM_REF_IDX_L1_BITS(pInfo->SliceHeader.num_ref_idx_l1_active);
p_slice_data->h264_bsd_slice_p1 = data;
///////////fill pic parameters 2
data = PUT_BSD_PP2_CABAC_INIT_IDC_BITS(pInfo->SliceHeader.cabac_init_idc) +
PUT_BSD_PP2_QP_BITS( (pInfo->SliceHeader.slice_qp_delta + pInfo->active_PPS.pic_init_qp_minus26+26) ) +
PUT_BSD_PP2_DISABLE_DBF_IDC_BITS(pInfo->SliceHeader.disable_deblocking_filter_idc) +
PUT_BSD_PP2_ALPHA_C0_OFFSET_DIV2_BITS(pInfo->SliceHeader.slice_alpha_c0_offset_div2) +
PUT_BSD_PP2_BETA_OFFSET_DIV2_BITS(pInfo->SliceHeader.slice_beta_offset_div2) +
PUT_BSD_PP2_IMG_DIRECT_TYPE_BIT(pInfo->SliceHeader.direct_spatial_mv_pred_flag) +
PUT_BSD_PP2_CHROMA_QP_OFFSET_BITS(pInfo->active_PPS.chroma_qp_index_offset) +
PUT_BSD_PP2_CHROMA_QP_OFFSET_2_BITS(pInfo->active_PPS.second_chroma_qp_index_offset);
p_slice_data->h264_bsd_slice_p2 = data;
/////////fill slice start
first_mb_in_slice = pInfo->SliceHeader.first_mb_in_slice;
data = PUT_BSD_SS_START_ADDR_BITS(first_mb_in_slice);
data |= PUT_BSD_SS_SKIP_FS_IDC_BITS( pInfo->h264_list_replacement) |
PUT_BSD_SS_SKIP_TYPE_BIT(0) |
PUT_BSD_SS_SKIP_REWIND_BITS((pInfo->img.MbaffFrameFlag? 2: 3));
p_slice_data->h264_bsd_slice_start = data;
}
static void h264_parse_emit_4X4_scaling_matrix( void *parent, h264_Info *pInfo )
{
viddec_workload_item_t wi;
uint32_t i=0, n_items=0;
uint32_t qm_type=0;
for ( i = 0; i < 6; i++ )
{
qm_type = FB_QM;
if (pInfo->active_SPS.seq_scaling_matrix_present_flag) // check sps first
{
if (pInfo->active_SPS.seq_scaling_list_present_flag[i])
{
pInfo->qm_present_list |= ((0x1)<<i);
if (pInfo->active_SPS.UseDefaultScalingMatrix4x4Flag[i]) {
qm_type = DEFAULT_QM;
} else {
qm_type = SPS_QM;
}
}
}
if (pInfo->active_PPS.pic_scaling_matrix_present_flag) // then check pps
{
if (pInfo->active_PPS.pic_scaling_list_present_flag[i])
{
pInfo->qm_present_list |= ((0x1)<<i);
if (pInfo->active_PPS.UseDefaultScalingMatrix4x4Flag[i]) {
qm_type = DEFAULT_QM;
} else {
qm_type = PPS_QM;
}
}
else
{
if ((i != 0) && (i != 3) && (i < 6)) {
pInfo->qm_present_list &= ~((0x1)<<i);
qm_type = FB_QM;
}
}
}
///////////////////// Emit out Scaling_matrix//////////////////////
wi.vwi_type = VIDDEC_WORKLOAD_H264_SCALING_MATRIX;
// data_offset 0x aa bb cc dd
// bb is the workload item offset
// cc is the qm_type
// dd is the matrix number
//
switch (qm_type)
{
case (SPS_QM): {
for (n_items =0; n_items<2; n_items++)
{
wi.data.data_offset = i + (SPS_QM << 4) + (n_items <<8);
wi.data.data_payload[0] = ((uint32_t)(pInfo->active_SPS.ScalingList4x4[i][n_items*8+0]))+
(((uint32_t)(pInfo->active_SPS.ScalingList4x4[i][n_items*8+1]))<<8)+
(((uint32_t)(pInfo->active_SPS.ScalingList4x4[i][n_items*8+2]))<<16)+
(((uint32_t)(pInfo->active_SPS.ScalingList4x4[i][n_items*8+3]))<<24);
wi.data.data_payload[1] = ((uint32_t)(pInfo->active_SPS.ScalingList4x4[i][n_items*8+4]))+
(((uint32_t)(pInfo->active_SPS.ScalingList4x4[i][n_items*8+5]))<<8)+
(((uint32_t)(pInfo->active_SPS.ScalingList4x4[i][n_items*8+6]))<<16)+
(((uint32_t)(pInfo->active_SPS.ScalingList4x4[i][n_items*8+7]))<<24);
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
}
break;
}
case (PPS_QM): {
for (n_items =0; n_items<2; n_items++)
{
wi.data.data_offset = i + (PPS_QM << 4) + (n_items <<8);
wi.data.data_payload[0] = ((uint32_t)(pInfo->active_PPS.ScalingList4x4[i][n_items*8+0]))+
(((uint32_t)(pInfo->active_PPS.ScalingList4x4[i][n_items*8+1]))<<8)+
(((uint32_t)(pInfo->active_PPS.ScalingList4x4[i][n_items*8+2]))<<16)+
(((uint32_t)(pInfo->active_PPS.ScalingList4x4[i][n_items*8+3]))<<24);
wi.data.data_payload[1] = ((uint32_t)(pInfo->active_PPS.ScalingList4x4[i][n_items*8+4]))+
(((uint32_t)(pInfo->active_PPS.ScalingList4x4[i][n_items*8+5]))<<8)+
(((uint32_t)(pInfo->active_PPS.ScalingList4x4[i][n_items*8+6]))<<16)+
(((uint32_t)(pInfo->active_PPS.ScalingList4x4[i][n_items*8+7]))<<24);
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
}
break;
}
case (DEFAULT_QM):
{
wi.data.data_offset = i + (DEFAULT_QM << 4);
wi.data.data_payload[0] = 0;
wi.data.data_payload[1] = 0;
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
break;
}
default:
{
break;
}
}
}
}
static void h264_parse_emit_8X8_scaling_matrix( void *parent, h264_Info *pInfo )
{
viddec_workload_item_t wi;
uint32_t i=0, n_items=0;
uint32_t qm_type=0;
for ( i = 6; i < 8; i++ )
{
qm_type = FB_QM;
if (pInfo->active_SPS.seq_scaling_matrix_present_flag) // check sps first
{
if (pInfo->active_SPS.seq_scaling_list_present_flag[i])
{
pInfo->qm_present_list |= ((0x1)<<i);
if (pInfo->active_SPS.UseDefaultScalingMatrix8x8Flag[i-6])
{
qm_type = DEFAULT_QM;
}
else
{
qm_type = SPS_QM;
}
}
}
if (pInfo->active_PPS.pic_scaling_matrix_present_flag) // then check pps
{
if (pInfo->active_PPS.pic_scaling_list_present_flag[i])
{
pInfo->qm_present_list |= ((0x1)<<i);
if (pInfo->active_PPS.UseDefaultScalingMatrix8x8Flag[i-6])
{
qm_type = DEFAULT_QM;
}
else
{
qm_type = PPS_QM;
}
}
}
wi.vwi_type = VIDDEC_WORKLOAD_H264_SCALING_MATRIX;
// data_offset 0x aa bb cc dd
// bb is the workload item offset
// cc is the qm_type
// dd is the matrix number
//
switch (qm_type)
{
case (SPS_QM):
{
for (n_items =0; n_items<8; n_items++)
{
wi.data.data_offset = i + (SPS_QM << 4) + (n_items <<8);
wi.data.data_payload[0] = ((uint32_t)(pInfo->active_SPS.ScalingList8x8[i-6][n_items*8+0]))+
(((uint32_t)(pInfo->active_SPS.ScalingList8x8[i-6][n_items*8+1]))<<8)+
(((uint32_t)(pInfo->active_SPS.ScalingList8x8[i-6][n_items*8+2]))<<16)+
(((uint32_t)(pInfo->active_SPS.ScalingList8x8[i-6][n_items*8+3]))<<24);
wi.data.data_payload[1] = ((uint32_t)(pInfo->active_SPS.ScalingList8x8[i-6][n_items*8+4]))+
(((uint32_t)(pInfo->active_SPS.ScalingList8x8[i-6][n_items*8+5]))<<8)+
(((uint32_t)(pInfo->active_SPS.ScalingList8x8[i-6][n_items*8+6]))<<16)+
(((uint32_t)(pInfo->active_SPS.ScalingList8x8[i-6][n_items*8+7]))<<24);
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
}
break;
}
case (PPS_QM):
{
for (n_items =0; n_items<8; n_items++)
{
wi.data.data_offset = i + (PPS_QM << 4) + (n_items <<8);
wi.data.data_payload[0] = ((uint32_t)(pInfo->active_PPS.ScalingList8x8[i-6][n_items*8+0]))+
(((uint32_t)(pInfo->active_PPS.ScalingList8x8[i-6][n_items*8+1]))<<8)+
(((uint32_t)(pInfo->active_PPS.ScalingList8x8[i-6][n_items*8+2]))<<16)+
(((uint32_t)(pInfo->active_PPS.ScalingList8x8[i-6][n_items*8+3]))<<24);
wi.data.data_payload[1] = ((uint32_t)(pInfo->active_PPS.ScalingList8x8[i-6][n_items*8+4]))+
(((uint32_t)(pInfo->active_PPS.ScalingList8x8[i-6][n_items*8+5]))<<8)+
(((uint32_t)(pInfo->active_PPS.ScalingList8x8[i-6][n_items*8+6]))<<16)+
(((uint32_t)(pInfo->active_PPS.ScalingList8x8[i-6][n_items*8+7]))<<24);
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
}
break;
}
case (DEFAULT_QM):
{
wi.data.data_offset = i + (DEFAULT_QM << 4);
wi.data.data_payload[0] = 0;
wi.data.data_payload[1] = 0;
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
break;
}
default: {
break;
}
}
}
}
static void h264_fill_pic_data(h264_Info *pInfo, h264_pic_data * p_pic_data)
{
uint32_t data=0;
uint32_t dec_idc =0;
uint32_t frame_structure =0;
//fill h264_dpb_init
data = PUT_FRAME_WIDTH_MB_BITS(pInfo->dpb.PicWidthInMbs) +
PUT_FRAME_HEIGHT_MB_BITS(pInfo->dpb.FrameHeightInMbs);
p_pic_data->h264_dpb_init = data;
////////////////////////////////file current pic info
data = 0;
dec_idc = pInfo->dpb.fs_dec_idc;
frame_structure = pInfo->img.structure;
if (frame_structure == FRAME)
frame_structure=0;
//data = PUT_BSD_IMAGE_FRAME_STORE_IDC_BITS(pInfo->dpb.fs[dec_idc].fs_idc);
//p_pic_data->h264_cur_bsd_img_init= data;
data = PUT_BSD_IMAGE_STRUCTURE_BITS(frame_structure) +
PUT_BSD_IMAGE_IDR_BIT(pInfo->nal_unit_type == h264_NAL_UNIT_TYPE_IDR) +
PUT_BSD_IMAGE_MBAFF_FRAME_FLAG_BIT(pInfo->img.MbaffFrameFlag) +
PUT_BSD_IMAGE_ENTROPY_CODING_MODE_FLAG_BIT(pInfo->active_PPS.entropy_coding_mode_flag) +
PUT_BSD_IMAGE_CONSTRAINED_INTRA_PRED_FLAG_BIT(pInfo->active_PPS.constrained_intra_pred_flag) +
PUT_BSD_IMG_FRAME_MBS_ONLY_FLAG_BIT(pInfo->active_SPS.sps_disp.frame_mbs_only_flag) +
PUT_BSD_IMG_DIRECT_8X8_INFER_FLAG_BIT(pInfo->active_SPS.sps_disp.direct_8x8_inference_flag) +
PUT_HPD_BSD_IMG_TRANSFORM_8X8_MODE_FLAG_BIT(pInfo->active_PPS.transform_8x8_mode_flag) +
PUT_HPD_BSD_IMG_MONOCHROME_FLAG_BIT(((pInfo->active_SPS.sps_disp.chroma_format_idc==0)? 0x1: 0x0)) +
PUT_HPD_BSD_IMG_GREY_NONEXISTING_FLAG_BIT(0x0) +
PUT_HPD_BSD_IMG_QM_PRESENT_FLAG_BIT((pInfo->active_PPS.pic_scaling_matrix_present_flag||pInfo->active_SPS.seq_scaling_matrix_present_flag)) +
PUT_HPD_BSD_IMG_QM_LIST_FLAGS_BITS(pInfo->qm_present_list) +
PUT_HPD_BSD_IMG_MONOCHROME_PWT_FLAG_BIT(0x1) +
PUT_BSD_IMAGE_FRAME_STORE_IDC_BITS(pInfo->dpb.fs[dec_idc].fs_idc);
p_pic_data->h264_cur_bsd_img_init= data;
//to do: add qm list
//PUT_HPD_BSD_IMG_QM_LIST_FLAGS_BITS(pInfo->img.q .qm_present_list) +
//printf("structure = %d, tpoc = %d, bpoc = %d\n", pInfo->img.structure, pInfo->img.toppoc, pInfo->img.bottompoc);
if (pInfo->img.structure == FRAME)
{
// Write down POC
p_pic_data->h264_cur_mpr_tf_poc = pInfo->img.toppoc;
p_pic_data->h264_cur_mpr_bf_poc = pInfo->img.bottompoc;
} else if (pInfo->img.structure == TOP_FIELD)
{
// Write down POC
p_pic_data->h264_cur_mpr_tf_poc = pInfo->img.toppoc;
p_pic_data->h264_cur_mpr_bf_poc = 0;
}
else if (pInfo->img.structure == BOTTOM_FIELD)
{
// Write down POC
p_pic_data->h264_cur_mpr_tf_poc = 0;
p_pic_data->h264_cur_mpr_bf_poc = pInfo->img.bottompoc;
}
else
{
// Write down POC
p_pic_data->h264_cur_mpr_tf_poc = 0;
p_pic_data->h264_cur_mpr_bf_poc = 0;
}
return;
}
static void h264_parse_emit_sps(void *parent, h264_Info *pInfo)
{
viddec_workload_item_t wi;
if (pInfo->Is_SPS_updated)
{
viddec_fw_reset_workload_item(&wi);
wi.vwi_type = VIDDEC_WORKLOAD_SEQUENCE_INFO;
viddec_fw_h264_sps_set_profile_idc(&(wi.h264_sps), pInfo->active_SPS.profile_idc);
viddec_fw_h264_sps_set_level_idc(&(wi.h264_sps), pInfo->active_SPS.level_idc);
viddec_fw_h264_sps_set_chroma_format_idc(&(wi.h264_sps), pInfo->active_SPS.sps_disp.chroma_format_idc);
viddec_fw_h264_sps_set_num_ref_frames(&(wi.h264_sps), pInfo->active_SPS.num_ref_frames);
viddec_fw_h264_sps_set_gaps_in_frame_num_value_allowed_flag(&(wi.h264_sps), pInfo->active_SPS.gaps_in_frame_num_value_allowed_flag);
viddec_fw_h264_sps_set_frame_mbs_only_flag(&(wi.h264_sps), pInfo->active_SPS.sps_disp.frame_mbs_only_flag);
viddec_fw_h264_sps_set_frame_cropping_flag(&(wi.h264_sps), pInfo->active_SPS.sps_disp.frame_cropping_flag);
viddec_fw_h264_sps_set_vui_parameters_present_flag(&(wi.h264_sps), pInfo->active_SPS.sps_disp.vui_parameters_present_flag);
wi.h264_sps.pic_width_in_mbs_minus1 = pInfo->active_SPS.sps_disp.pic_width_in_mbs_minus1;
wi.h264_sps.pic_height_in_map_units_minus1 = pInfo->active_SPS.sps_disp.pic_height_in_map_units_minus1;
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
viddec_fw_reset_workload_item(&wi);
if (pInfo->active_SPS.sps_disp.frame_cropping_flag)
{
wi.vwi_type = VIDDEC_WORKLOAD_H264_CROPPING;
viddec_fw_h264_cropping_set_left(&(wi.h264_cropping), pInfo->active_SPS.sps_disp.frame_crop_rect_left_offset);
viddec_fw_h264_cropping_set_right(&(wi.h264_cropping), pInfo->active_SPS.sps_disp.frame_crop_rect_right_offset);
viddec_fw_h264_cropping_set_top(&(wi.h264_cropping), pInfo->active_SPS.sps_disp.frame_crop_rect_top_offset);
viddec_fw_h264_cropping_set_bottom(&(wi.h264_cropping), pInfo->active_SPS.sps_disp.frame_crop_rect_bottom_offset);
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
}
viddec_fw_reset_workload_item(&wi);
if (pInfo->active_SPS.sps_disp.vui_parameters_present_flag == 1)
{
wi.vwi_type = VIDDEC_WORKLOAD_DISPLAY_INFO;
viddec_fw_h264_vui_set_aspect_ratio_info_present_flag(&(wi.h264_vui), pInfo->active_SPS.sps_disp.vui_seq_parameters.aspect_ratio_info_present_flag);
viddec_fw_h264_vui_set_video_signal_type_present_flag(&(wi.h264_vui), pInfo->active_SPS.sps_disp.vui_seq_parameters.video_signal_type_present_flag);
viddec_fw_h264_vui_set_pic_struct_present_flag(&(wi.h264_vui), pInfo->active_SPS.sps_disp.vui_seq_parameters.pic_struct_present_flag);
viddec_fw_h264_vui_set_timing_info_present_flag(&(wi.h264_vui), pInfo->active_SPS.sps_disp.vui_seq_parameters.timing_info_present_flag);
viddec_fw_h264_vui_set_nal_hrd_parameters_present_flag(&(wi.h264_vui), pInfo->active_SPS.sps_disp.vui_seq_parameters.nal_hrd_parameters_present_flag);
viddec_fw_h264_vui_set_vcl_hrd_parameters_present_flag(&(wi.h264_vui), pInfo->active_SPS.sps_disp.vui_seq_parameters.vcl_hrd_parameters_present_flag);
if (pInfo->active_SPS.sps_disp.vui_seq_parameters.aspect_ratio_info_present_flag == 1)
{
viddec_fw_h264_vui_set_aspect_ratio_idc(&(wi.h264_vui), pInfo->active_SPS.sps_disp.vui_seq_parameters.aspect_ratio_idc);
if (h264_AR_Extended_SAR == pInfo->active_SPS.sps_disp.vui_seq_parameters.aspect_ratio_idc)
{
viddec_fw_h264_vui_set_sar_width(&(wi.h264_vui), pInfo->active_SPS.sps_disp.vui_seq_parameters.sar_width);
viddec_fw_h264_vui_set_sar_height(&(wi.h264_vui), pInfo->active_SPS.sps_disp.vui_seq_parameters.sar_height);
}
}
if (pInfo->active_SPS.sps_disp.vui_seq_parameters.video_signal_type_present_flag)
{
viddec_fw_h264_vui_set_colour_description_present_flag(&(wi.h264_vui), pInfo->active_SPS.sps_disp.vui_seq_parameters.colour_description_present_flag);
if (pInfo->active_SPS.sps_disp.vui_seq_parameters.colour_description_present_flag)
{
viddec_fw_h264_vui_set_colour_primaries(&(wi.h264_vui), pInfo->active_SPS.sps_disp.vui_seq_parameters.colour_primaries);
viddec_fw_h264_vui_set_transfer_characteristics(&(wi.h264_vui), pInfo->active_SPS.sps_disp.vui_seq_parameters.transfer_characteristics);
}
viddec_fw_h264_vui_set_video_format(&(wi.h264_vui), pInfo->active_SPS.sps_disp.vui_seq_parameters.video_format);
}
if (pInfo->active_SPS.sps_disp.vui_seq_parameters.timing_info_present_flag == 1)
{
viddec_fw_h264_vui_set_fixed_frame_rate_flag(&(wi.h264_vui), pInfo->active_SPS.sps_disp.vui_seq_parameters.fixed_frame_rate_flag);
}
if ( (pInfo->active_SPS.sps_disp.vui_seq_parameters.nal_hrd_parameters_present_flag == 1)
|| (pInfo->active_SPS.sps_disp.vui_seq_parameters.vcl_hrd_parameters_present_flag == 1))
{
viddec_fw_h264_vui_set_low_delay_hrd_flag(&(wi.h264_vui), pInfo->active_SPS.sps_disp.vui_seq_parameters.low_delay_hrd_flag);
}
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
}
viddec_fw_reset_workload_item(&wi);
if (pInfo->active_SPS.sps_disp.vui_seq_parameters.timing_info_present_flag == 1)
{
wi.vwi_type = VIDDEC_WORKLOAD_H264_VUI_TIMING_INFO;
wi.h264_vui_time_info.num_units_in_tick = pInfo->active_SPS.sps_disp.vui_seq_parameters.num_units_in_tick;
wi.h264_vui_time_info.time_scale = pInfo->active_SPS.sps_disp.vui_seq_parameters.time_scale;
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
}
pInfo->Is_SPS_updated =0;
}
return;
}
static void h264_parse_emit_ref_list( void *parent, h264_Info *pInfo, uint32_t list_id)
{
uint32_t i=0, nitems=0, byte_index=0, data=0, data_writed=0;
uint8_t *p_list;
viddec_workload_item_t wi;
if (0 == list_id)
{
wi.vwi_type = VIDDEC_WORKLOAD_H264_REFR_LIST_0;
if ( (h264_PtypeB==pInfo->SliceHeader.slice_type)||(h264_PtypeP==pInfo->SliceHeader.slice_type) )
{
nitems = pInfo->SliceHeader.num_ref_idx_l0_active;
if (pInfo->SliceHeader.sh_refpic_l0.ref_pic_list_reordering_flag)
{
p_list = pInfo->slice_ref_list0;
}
else
{
p_list = pInfo->dpb.listX_0;
}
}
else
{
nitems =0;
p_list = pInfo->dpb.listX_0;
}
}
else
{
wi.vwi_type = VIDDEC_WORKLOAD_H264_REFR_LIST_1;
if ( h264_PtypeB==pInfo->SliceHeader.slice_type)
{
nitems = pInfo->SliceHeader.num_ref_idx_l1_active;
if (pInfo->SliceHeader.sh_refpic_l1.ref_pic_list_reordering_flag)
{
p_list = pInfo->slice_ref_list1;
}
else
{
p_list = pInfo->dpb.listX_1;
}
}
else
{
nitems = 0;
p_list = pInfo->dpb.listX_1;
}
}
if (0 == nitems)
{
return;
}
byte_index =0;
data_writed=0;
for (i=0; i < 32; i++)
{
if (byte_index == 0) data = 0;
if (i<nitems)
{
if ( viddec_h264_get_is_non_existent(&(pInfo->dpb.fs[ (p_list[i]&0x1f) ])))
{
data |= (pInfo->h264_list_replacement) << byte_index;
}
else
{
data |= (p_list[i] & 0x7f) << byte_index;
}
}
else
{
data |= (0x80) << byte_index;
}
if (byte_index == 24)
{
byte_index = 0;
wi.data.data_offset = data_writed&(~0x1);
wi.data.data_payload[data_writed&0x1]=data;
data =0;
if (data_writed&0x1)
{
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
}
data_writed ++;
}
else
{
byte_index += 8;
}
}
}
void h264_parse_emit_current_slice( void *parent, h264_Info *pInfo )
{
viddec_workload_item_t wi;
h264_slice_data slice_data;
uint32_t i=0, nitems=0, data=0;
uint32_t bits_offset =0, byte_offset =0;
uint8_t is_emul =0;
////////////////////// Update frame attributes/////////////////
h264_parse_update_frame_attributes(parent,pInfo);
if (pInfo->SliceHeader.sh_error) {
// Error type definition, refer to viddec_fw_common_defs.h
// if error in top field, VIDDEC_FW_WORKLOAD_ERR_TOPFIELD = (1 << 17)
// if error in bottom field, VIDDEC_FW_WORKLOAD_ERR_BOTTOMFIELD = (1 << 18)
// if this is frame based, both 2 bits should be set
if (pInfo->push_to_cur) {
pInfo->wl_err_curr |= VIDDEC_FW_WORKLOAD_ERR_NOTDECODABLE;
pInfo->wl_err_curr |= (pInfo->SliceHeader.structure << FIELD_ERR_OFFSET);
} else {
pInfo->wl_err_next |= VIDDEC_FW_WORKLOAD_ERR_NOTDECODABLE;
pInfo->wl_err_next |= (pInfo->SliceHeader.structure << FIELD_ERR_OFFSET);
}
}
////////////////////// Update Reference list //////////////////
if ( (h264_PtypeB==pInfo->SliceHeader.slice_type)||(h264_PtypeP==pInfo->SliceHeader.slice_type) )
{
if (pInfo->SliceHeader.sh_refpic_l0.ref_pic_list_reordering_flag)
{
nitems = pInfo->SliceHeader.num_ref_idx_l0_active;
for (i=0; i<nitems; i++)
{
if (viddec_h264_get_is_non_existent(&(pInfo->dpb.fs[pInfo->slice_ref_list0[i]&0x1f]))==0)
{
pInfo->h264_list_replacement = (pInfo->slice_ref_list0[i]&0xFF)|0x80;
break;
}
}
}
else
{
nitems = pInfo->dpb.listXsize[0];
for (i=0; i<nitems; i++)
{
if (viddec_h264_get_is_non_existent(&(pInfo->dpb.fs[pInfo->dpb.listX_0[i]&0x1f]))==0)
{
pInfo->h264_list_replacement = (pInfo->dpb.listX_0[i]&0xFF)|0x80;
break;
}
}
}
}
else
{
nitems =0;
}
/////file ref list 0
h264_parse_emit_ref_list(parent, pInfo, 0);
/////file ref list 1
h264_parse_emit_ref_list(parent, pInfo, 1);
///////////////////////////////////// Slice Data ////////////////////////////////
h264_fill_slice_data(pInfo, &slice_data);
wi.vwi_type = VIDDEC_WORKLOAD_H264_SLICE_REG;
wi.data.data_offset = slice_data.h264_bsd_slice_start;
wi.data.data_payload[0] = slice_data.h264_bsd_slice_p1;
wi.data.data_payload[1] = slice_data.h264_bsd_slice_p2;
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
///////////////////////////predict weight table item and data if have///////////////////////////
if (pInfo->h264_pwt_enabled)
{
wi.vwi_type = VIDDEC_WORKLOAD_H264_PWT_BITS_OFFSET;
wi.data.data_offset = pInfo->h264_pwt_end_byte_offset- pInfo->h264_pwt_start_byte_offset+1;
wi.data.data_payload[0] = pInfo->h264_pwt_start_bit_offset;
wi.data.data_payload[1] = pInfo->h264_pwt_end_bit_offset;
if (pInfo->push_to_cur) //cur is empty, fill new frame in cur
{
viddec_pm_append_workitem( parent , &wi, false);
wi.vwi_type = VIDDEC_WORKLOAD_H264_PWT_ES_BYTES;
wi.es.es_flags = 0;
viddec_pm_append_misc_tags(parent, pInfo->h264_pwt_start_byte_offset, pInfo->h264_pwt_end_byte_offset,&wi,1);
}
else
{
viddec_pm_append_workitem( parent , &wi, true);
wi.vwi_type = VIDDEC_WORKLOAD_H264_PWT_ES_BYTES;
wi.es.es_flags = 0;
viddec_pm_append_misc_tags(parent, pInfo->h264_pwt_start_byte_offset, pInfo->h264_pwt_end_byte_offset,&wi,0);
}
}
////////////////////////////////// Update ES Buffer for Slice ///////////////////////
viddec_pm_get_au_pos(parent, &bits_offset, &byte_offset, &is_emul);
//OS_INFO("DEBUG---entropy_coding_mode_flag:%d, bits_offset: %d\n", pInfo->active_PPS.entropy_coding_mode_flag, bits_offset);
if (pInfo->active_PPS.entropy_coding_mode_flag)
{
if (0!=bits_offset) {
viddec_pm_get_bits(parent, &data, 8-bits_offset);
}
}
else
{
if (0!=bits_offset) {
wi.vwi_type = VIDDEC_WORKLOAD_H264_SH_BITS_OFFSET;
wi.data.data_offset = bits_offset;
wi.data.data_payload[0]=0;
wi.data.data_payload[1]=0;
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
}
}
if (pInfo->push_to_cur) //cur is empty, fill new frame in cur
{
viddec_pm_append_pixeldata( parent );
}
else
{
viddec_pm_append_pixeldata_next( parent);
}
return;
}
void h264_parse_emit_current_pic( void *parent, h264_Info *pInfo )
{
viddec_workload_item_t wi;
const uint32_t *pl;
uint32_t i=0,nitems=0;
h264_pic_data pic_data;
pInfo->qm_present_list=0;
h264_parse_emit_4X4_scaling_matrix(parent, pInfo);
h264_parse_emit_8X8_scaling_matrix(parent, pInfo);
h264_fill_pic_data(pInfo, &pic_data);
// How many payloads must be generated
nitems = (sizeof(h264_pic_data) + 7) / 8; // In QWORDs rounded up
pl = (const uint32_t *) &pic_data;
// Dump slice data to an array of workitems, to do pl access non valid mem
for ( i = 0; i < nitems; i++ )
{
wi.vwi_type = VIDDEC_WORKLOAD_H264_PIC_REG;
wi.data.data_offset = (unsigned int)pl - (unsigned int)&pic_data; // offset within struct
wi.data.data_payload[0] = pl[0];
wi.data.data_payload[1] = pl[1];
pl += 2;
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
}
return;
}
void h264_parse_emit_start_new_frame( void *parent, h264_Info *pInfo )
{
viddec_workload_item_t wi;
uint32_t i=0,nitems=0;
///////////////////////// Frame attributes//////////////////////////
//Push data into current workload if first frame or frame_boundary already detected by non slice nal
if ( (pInfo->Is_first_frame_in_stream)||(pInfo->is_frame_boundary_detected_by_non_slice_nal))
{
viddec_workload_t *wl_cur = viddec_pm_get_header( parent );
//pInfo->img.g_new_frame = 0;
pInfo->Is_first_frame_in_stream =0;
pInfo->is_frame_boundary_detected_by_non_slice_nal=0;
pInfo->push_to_cur = 1;
h264_translate_parser_info_to_frame_attributes(wl_cur, pInfo);
}
else // move to cur if frame boundary detected by previous non slice nal, or move to next if not
{
viddec_workload_t *wl_next = viddec_pm_get_next_header (parent);
pInfo->push_to_cur = 0;
h264_translate_parser_info_to_frame_attributes(wl_next, pInfo);
pInfo->is_current_workload_done=1;
}
///////////////////// SPS/////////////////////
h264_parse_emit_sps(parent, pInfo);
/////////////////////display frames/////////////////////
nitems = pInfo->dpb.frame_numbers_need_to_be_displayed;
for (i=0; i<nitems; i++)
{
wi.vwi_type = VIDDEC_WORKLOAD_REF_FRAME_DISPLAY_0 + pInfo->dpb.frame_id_need_to_be_displayed[i];
wi.ref_frame.reference_id = pInfo->dpb.frame_id_need_to_be_displayed[i];
wi.ref_frame.luma_phys_addr = 0;
wi.ref_frame.chroma_phys_addr = 0;
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
}
pInfo->dpb.frame_numbers_need_to_be_displayed =0;
/////////////////////release frames/////////////////////
nitems = pInfo->dpb.frame_numbers_need_to_be_removed;
for (i=0; i<nitems; i++)
{
wi.vwi_type = VIDDEC_WORKLOAD_REF_FRAME_RELEASE_0 + pInfo->dpb.frame_id_need_to_be_removed[i];
wi.ref_frame.reference_id = pInfo->dpb.frame_id_need_to_be_removed[i];
wi.ref_frame.luma_phys_addr = 0;
wi.ref_frame.chroma_phys_addr = 0;
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
}
pInfo->dpb.frame_numbers_need_to_be_removed =0;
/////////////////////flust frames (do not display)/////////////////////
nitems = pInfo->dpb.frame_numbers_need_to_be_dropped;
for (i=0; i<nitems; i++)
{
wi.vwi_type = VIDDEC_WORKLOAD_REF_FRAME_DROPOUT_0 + pInfo->dpb.frame_id_need_to_be_dropped[i];
wi.ref_frame.reference_id = pInfo->dpb.frame_id_need_to_be_dropped[i];
wi.ref_frame.luma_phys_addr = 0;
wi.ref_frame.chroma_phys_addr = 0;
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
}
pInfo->dpb.frame_numbers_need_to_be_dropped =0;
/////////////////////updata DPB frames/////////////////////
nitems = pInfo->dpb.used_size;
for (i=0; i<nitems; i++)
{
uint8_t fs_id = pInfo->dpb.fs_dpb_idc[i];
if (viddec_h264_get_is_non_existent(&(pInfo->dpb.fs[fs_id])) == 0)
{
wi.vwi_type = VIDDEC_WORKLOAD_DPB_ACTIVE_FRAME_0+fs_id;
wi.ref_frame.reference_id = fs_id;
wi.ref_frame.luma_phys_addr = 0;
wi.ref_frame.chroma_phys_addr = 0;
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
}
}
/////////////////////updata dpb frames info (poc)/////////////////////
nitems = pInfo->dpb.used_size;
for (i=0; i<nitems; i++)
{
uint8_t fs_id = pInfo->dpb.fs_dpb_idc[i];
if (viddec_h264_get_is_non_existent(&(pInfo->dpb.fs[fs_id])) == 0)
{
wi.vwi_type = VIDDEC_WORKLOAD_H264_DPB_FRAME_POC;
wi.data.data_offset = fs_id;
//printf("is_used = %d, tpoc = %d, bpoc = %d\n", pInfo->dpb.fs[fs_id].is_used, pInfo->dpb.fs[fs_id].top_field.poc, pInfo->dpb.fs[fs_id].bottom_field.poc);
switch (viddec_h264_get_is_used(&(pInfo->dpb.fs[fs_id])))
{
case (FRAME): {
wi.data.data_payload[0] = pInfo->dpb.fs[fs_id].top_field.poc;
wi.data.data_payload[1] = pInfo->dpb.fs[fs_id].bottom_field.poc;
break;
};
case (TOP_FIELD): {
wi.data.data_payload[0] = pInfo->dpb.fs[fs_id].top_field.poc;
wi.data.data_payload[1] = 0;
break;
};
case (BOTTOM_FIELD): {
wi.data.data_payload[0] = 0;
wi.data.data_payload[1] = pInfo->dpb.fs[fs_id].bottom_field.poc;
break;
};
default : {
wi.data.data_payload[0] = 0;
wi.data.data_payload[1] = 0;
break;
};
}
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
}
}
/////////////////////Alloc buffer for current Existing frame/////////////////////
if (0!=pInfo->dpb.frame_numbers_need_to_be_allocated)
{
if (pInfo->push_to_cur)
{
viddec_workload_t *wl_cur = viddec_pm_get_header (parent);
wl_cur->is_reference_frame |= WORKLOAD_REFERENCE_FRAME | (pInfo->dpb.frame_id_need_to_be_allocated & 0x1f);
}
else
{
viddec_workload_t *wl_next = viddec_pm_get_next_header (parent);
wl_next->is_reference_frame |= WORKLOAD_REFERENCE_FRAME | (pInfo->dpb.frame_id_need_to_be_allocated & 0x1f);
}
}
pInfo->dpb.frame_numbers_need_to_be_allocated =0;
return;
}
void h264_parse_emit_eos( void *parent, h264_Info *pInfo )
{
uint32_t nitems=0, i=0;
viddec_workload_item_t wi;
wi.vwi_type = VIDDEC_WORKLOAD_EOS_BEGIN_BOUNDARY;
wi.ref_frame.reference_id = 0;
wi.ref_frame.luma_phys_addr = 0;
wi.ref_frame.chroma_phys_addr = 0;
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
//// Now we can flush out all frames in DPB fro display
if (MPD_DPB_FS_NULL_IDC != pInfo->dpb.fs_dec_idc)
{
if (viddec_h264_get_is_used(&(pInfo->dpb.fs[pInfo->dpb.fs_dec_idc])) != 3)
{
h264_dpb_mark_dangling_field(&pInfo->dpb, pInfo->dpb.fs_dec_idc); //, DANGLING_TYPE_GAP_IN_FRAME
}
}
h264_dpb_store_previous_picture_in_dpb(pInfo, 0,0);
h264_dpb_flush_dpb(pInfo, 1, 0, pInfo->active_SPS.num_ref_frames);
/////////////////////display frames/////////////////////
nitems = pInfo->dpb.frame_numbers_need_to_be_displayed;
for (i=0; i<nitems; i++)
{
wi.vwi_type = VIDDEC_WORKLOAD_EOS_DISPLAY_FRAME_0 + pInfo->dpb.frame_id_need_to_be_displayed[i];
wi.ref_frame.reference_id = pInfo->dpb.frame_id_need_to_be_displayed[i];
wi.ref_frame.luma_phys_addr = 0;
wi.ref_frame.chroma_phys_addr = 0;
//cur is empty, fill new frame in cur
viddec_pm_append_workitem( parent, &wi , !pInfo->push_to_cur);
}
pInfo->dpb.frame_numbers_need_to_be_displayed =0;
/////////////////////release frames/////////////////////
nitems = pInfo->dpb.frame_numbers_need_to_be_removed;
for (i=0; i<nitems; i++)
{
wi.vwi_type = VIDDEC_WORKLOAD_EOS_RELEASE_FRAME_0 + pInfo->dpb.frame_id_need_to_be_removed[i];
wi.ref_frame.reference_id = pInfo->dpb.frame_id_need_to_be_removed[i];
wi.ref_frame.luma_phys_addr = 0;
wi.ref_frame.chroma_phys_addr = 0;
if (pInfo->push_to_cur) //cur is empty, fill new frame in cur
{
viddec_pm_append_workitem( parent, &wi , false);
viddec_pm_set_next_frame_error_on_eos(parent, VIDDEC_FW_WORKLOAD_ERR_NOTDECODABLE);
}
else
{
viddec_pm_append_workitem( parent, &wi , true);
viddec_pm_set_next_frame_error_on_eos(parent, pInfo->wl_err_next);
}
}
pInfo->dpb.frame_numbers_need_to_be_removed =0;
return;
}