diff --git a/inc/rk_mpi.h b/inc/rk_mpi.h index bc011d3a..8d160eb2 100644 --- a/inc/rk_mpi.h +++ b/inc/rk_mpi.h @@ -75,7 +75,7 @@ typedef enum { MPP_DEC_CMD_BASE = 0x40000, MPP_DEC_SET_EXT_BUF_GROUP, /* IMPORTANT: set external buffer group to mpp decoder */ - MPP_DEC_USE_PRESENT_TIME_ORDER, + MPP_DEC_SET_INTERNAL_PTS_ENABLE, MPP_DEC_SET_VC1_EXTRA_DATA, MPP_DEC_SET_PARSER_SPLIT_MODE, /* Need to setup before init */ MPP_DEC_SET_PARSER_FAST_MODE, /* Need to setup before init */ diff --git a/mpp/codec/dec/mpg4/mpg4d_api.c b/mpp/codec/dec/mpg4/mpg4d_api.c index ad0baf26..c611a4b8 100644 --- a/mpp/codec/dec/mpg4/mpg4d_api.c +++ b/mpp/codec/dec/mpg4/mpg4d_api.c @@ -19,10 +19,11 @@ #include +#include "rk_mpi.h" + #include "mpp_log.h" #include "mpp_mem.h" #include "mpp_common.h" -#include "mpp_packet.h" #include "mpg4d_api.h" #include "mpg4d_parser.h" @@ -43,6 +44,7 @@ typedef struct { // runtime parameter RK_U32 need_split; RK_U32 frame_count; + RK_U32 internal_pts; IOInterruptCB notify_cb; // parser context @@ -89,8 +91,9 @@ MPP_RET mpg4d_init(void *dec, ParserCfg *cfg) p = (Mpg4dCtx *)dec; p->frame_slots = cfg->frame_slots; p->packet_slots = cfg->packet_slots; - p->need_split = cfg->need_split; p->task_count = cfg->task_count = 2; + p->need_split = cfg->need_split; + p->internal_pts = cfg->internal_pts; p->notify_cb = cfg->notify_cb; p->stream = stream; p->stream_size = stream_size; @@ -140,7 +143,8 @@ MPP_RET mpg4d_reset(void *dec) mpp_err_f("found NULL intput\n"); return MPP_ERR_NULL_PTR; } - return MPP_OK; + + return mpp_mpg4_parser_reset(dec); } @@ -150,17 +154,26 @@ MPP_RET mpg4d_flush(void *dec) mpp_err_f("found NULL intput\n"); return MPP_ERR_NULL_PTR; } - return MPP_OK; + + return mpp_mpg4_parser_flush(dec); } MPP_RET mpg4d_control(void *dec, RK_S32 cmd_type, void *param) { + Mpg4dCtx *p; + if (NULL == dec) { mpp_err_f("found NULL intput\n"); return MPP_ERR_NULL_PTR; } - (void)cmd_type; + + p = (Mpg4dCtx *)dec; + switch (cmd_type) { + case MPP_DEC_SET_INTERNAL_PTS_ENABLE : { + mpp_mpg4_parser_set_pts_mode(p, 1); + } break; + } (void)param; return MPP_OK; } @@ -254,6 +267,7 @@ MPP_RET mpg4d_prepare(void *dec, MppPacket pkt, HalDecTask *task) task->input_packet = p->task_pkt; task->flags.eos = p->task_eos; + return MPP_OK; } @@ -271,14 +285,14 @@ MPP_RET mpg4d_parse(void *dec, HalDecTask *task) if (ret) { // found error on decoding drop this task and clear remaining length task->output = -1; - mpp_packet_set_length(&task->input_packet, 0); + mpp_packet_set_length(task->input_packet, 0); return MPP_NOK; } - mpp_mpg4_parser_setup_syntax(p->parser, task->syntax); - mpp_mpg4_parser_setup_output(p->parser, &task->output); + mpp_mpg4_parser_setup_syntax(p->parser, &task->syntax); + mpp_mpg4_parser_setup_hal_output(p->parser, &task->output); mpp_mpg4_parser_setup_refer(p->parser, task->refer, MAX_DEC_REF_NUM); - mpp_mpg4_parser_setup_display(p->parser); + mpp_mpg4_parser_update_dpb(p->parser); p->frame_count++; @@ -291,6 +305,7 @@ MPP_RET mpg4d_callback(void *dec, void *err_info) (void)err_info; return MPP_OK; } + const ParserApi api_mpg4d_parser = { "api_mpg4d_parser", MPP_VIDEO_CodingMPEG4, diff --git a/mpp/codec/dec/mpg4/mpg4d_parser.c b/mpp/codec/dec/mpg4/mpg4d_parser.c index 5e60e6db..f60f5520 100644 --- a/mpp/codec/dec/mpg4/mpg4d_parser.c +++ b/mpp/codec/dec/mpg4/mpg4d_parser.c @@ -15,48 +15,1061 @@ * limitations under the License. */ -/* - * @file api_mpg4d_parser.c - * @brief - * @author gzl(lance.gao@rock-chips.com) - * @version 1.0.0 - * @history - * 2015.7.15 : Create - */ - #include +#include "mpp_env.h" #include "mpp_log.h" #include "mpp_mem.h" -#include "mpp_common.h" #include "mpp_packet.h" +#include "mpp_bitread.h" #include "mpg4d_parser.h" +#include "mpg4d_syntax.h" + + +RK_U32 mpg4d_debug = 0; +#define mpg4d_dbg(flag, fmt, ...) _mpp_dbg(mpg4d_debug, flag, fmt, ## __VA_ARGS__) +#define mpg4d_dbg_f(flag, fmt, ...) _mpp_dbg_f(mpg4d_debug, flag, fmt, ## __VA_ARGS__) + +#define mpg4d_dbg_bit(fmt, ...) mpg4d_dbg(MPG4D_DBG_BITS, fmt, ## __VA_ARGS__) + +#define MPEG4_VIDOBJ_START_CODE 0x00000100 /* ..0x0000011f */ +#define MPEG4_VIDOBJLAY_START_CODE 0x00000120 /* ..0x0000012f */ +#define MPEG4_VISOBJSEQ_START_CODE 0x000001b0 +#define MPEG4_VISOBJSEQ_STOP_CODE 0x000001b1 +#define MPEG4_USERDATA_START_CODE 0x000001b2 +#define MPEG4_GRPOFVOP_START_CODE 0x000001b3 +#define MPEG4_VISOBJ_START_CODE 0x000001b5 +#define MPEG4_VOP_START_CODE 0x000001b6 + +#define MPG4_VOL_STARTCODE 0x120 +#define MPG4_VOL_STOPCODE 0x12F +#define MPG4_VOS_STARTCODE 0x1B0 +#define MPG4_VOS_STOPCODE 0x1B1 +#define MPG4_USER_DATA_STARTCODE 0x1B2 +#define MPG4_GOP_STARTCODE 0x1B3 +#define MPG4_VISUAL_OBJ_STARTCODE 0x1B5 +#define MPG4_VOP_STARTCODE 0x1B6 typedef struct { - MppBufSlots frame_slots; - RK_S32 output; - RK_U32 width; - RK_U32 height; - RK_S64 pts; - RK_U32 eos; + RK_S32 method; + + RK_S32 opaque; + RK_S32 transparent; + RK_S32 intra_cae; + RK_S32 inter_cae; + RK_S32 no_update; + RK_S32 upsampling; + + RK_S32 intra_blocks; + RK_S32 inter_blocks; + RK_S32 inter4v_blocks; + RK_S32 gmc_blocks; + RK_S32 not_coded_blocks; + + RK_S32 dct_coefs; + RK_S32 dct_lines; + RK_S32 vlc_symbols; + RK_S32 vlc_bits; + + RK_S32 apm; + RK_S32 npm; + RK_S32 interpolate_mc_q; + RK_S32 forw_back_mc_q; + RK_S32 halfpel2; + RK_S32 halfpel4; + + RK_S32 sadct; + RK_S32 quarterpel; +} Mpeg4Estimation; + +typedef struct Mp4HdrVol_t { + RK_S32 vo_type; + RK_U32 low_delay; + RK_U32 shape; + RK_S32 time_inc_resolution; + RK_U32 time_inc_bits; + RK_S32 width; + RK_S32 height; + RK_U32 mb_width; + RK_U32 mb_height; + RK_S32 hor_stride; + RK_S32 ver_stride; + RK_U32 totalMbInVop; + RK_U32 interlacing; + RK_S32 sprite_enable; + RK_U32 quant_bits; + RK_U32 quant_type; + RK_S32 quarter_sample; + RK_S32 complexity_estimation_disable; + RK_U32 resync_marker_disable; + RK_S32 newpred_enable; + RK_S32 reduced_resolution_enable; + RK_S32 scalability; + RK_S32 ver_id; +} Mp4HdrVol; + +typedef struct Mp4HdrUserData_t { + RK_S32 packed_mode; /* bframes packed bits? (1 = yes) */ +} Mp4HdrUserData; + +typedef struct Mp4HdrVop_t { + RK_S32 coding_type; + RK_U32 last_time_base; + RK_U32 time_base; + RK_U32 time; + RK_U32 time_pp; + RK_U32 time_bp; + RK_U32 last_non_b_time; + RK_U32 frameNumber; + RK_U32 rounding; + RK_U32 intra_dc_vlc_threshold; + RK_U32 top_field_first; + RK_U32 alternate_vertical_scan; + RK_U32 fcode_forward; + RK_U32 fcode_backward; + RK_U32 quant; // OFFSET_OF_QUANT_IN_DEC + RK_U32 hdr_bits; +} Mp4HdrVop; + +typedef struct Mpg4Hdr_t { + // vol parameter + Mp4HdrVol vol; + + // user data parameter + Mp4HdrUserData usr; + + // vop header parameter + Mp4HdrVop vop; + + // frame related parameter + RK_S64 pts; + RK_S32 slot_idx; +} Mpg4Hdr; + + +typedef struct { + // global paramter + MppBufSlots frame_slots; + RK_U32 use_internal_pts; + + // frame size parameter + RK_S32 width; + RK_S32 height; + RK_S32 hor_stride; + RK_S32 ver_stride; + RK_U32 info_change; + RK_U32 eos; // spliter parameter - RK_S32 pos_frm_start; // negtive - not found; non-negtive - position of frame start - RK_S32 pos_frm_end; // negtive - not found; non-negtive - position of frame end + RK_S32 pos_frm_start; // negtive - not found; non-negtive - position of frame start + RK_S32 pos_frm_end; // negtive - not found; non-negtive - position of frame end + + // bit read context + BitReadCtx_t *bit_ctx; + // vos infomation + RK_U32 profile; + RK_U32 level; + RK_U32 custorm_version; + + // commom buffer for header information + /* + * NOTE: We assume that quant matrix only used for current frame decoding + * So we use only one quant matrix buffer and only support + */ + RK_U32 new_qm[2]; // [0] - intra [1] - inter + RK_U8 quant_matrices[128]; // 0-63: intra 64-127: inter + Mpeg4Estimation estimation; + Mpg4Hdr hdr_curr; /* header for current decoding frame */ + Mpg4Hdr hdr_ref0; /* header for reference frame 0 */ + Mpg4Hdr hdr_ref1; /* header for reference frame 1 */ + + // dpb/output information + RK_S32 output; + RK_S64 last_pts; + RK_S64 pts_inc; + RK_S64 pts; + + // syntax for hal + mpeg4d_dxva2_picture_context_t *syntax; } Mpg4dParserImpl; +static RK_S32 log2bin(RK_U32 value) +{ + RK_S32 n = 0; + + while (value) { + value >>= 1; + n++; + } + + return n; +} + +static MPP_RET mpg4d_parse_matrix(BitReadCtx_t *gb, RK_U8 * matrix) +{ + RK_S32 i = 0; + RK_S32 last, value = 0; + + do { + last = value; + READ_BITS(gb, 8, &value); + matrix[i++] = value; + } while (value != 0 && i < 64); + + if (value != 0) + return MPP_ERR_STREAM; + + i--; + + while (i < 64) { + matrix[i++ ] = last; + } + + return MPP_OK; + +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static void mpg4d_set_intra_matrix(RK_U8 * quant_matrices, RK_U8 * matrix) +{ + RK_S32 i; + RK_U8 *intra_matrix = quant_matrices + 0 * 64; + + for (i = 0; i < 64; i++) { + intra_matrix[i] = (!i) ? (RK_U8)8 : (RK_U8)matrix[i]; + } +} + +static void mpg4d_set_inter_matrix(RK_U8 * quant_matrices, RK_U8 * matrix) +{ + RK_S32 i; + RK_U8 *inter_matrix = quant_matrices + 1 * 64; + + for (i = 0; i < 64; i++) { + inter_matrix[i] = (RK_U8) (matrix[i]); + } +} + +static MPP_RET read_vol_complexity_estimation_header(Mpeg4Estimation *e, BitReadCtx_t *gb) +{ + RK_U32 val; + + READ_BITS(gb, 2, &(e->method)); /* estimation_method */ + + if (e->method == 0 || e->method == 1) { + READ_BITS(gb, 1, &val); + if (!val) { /* shape_complexity_estimation_disable */ + READ_BITS(gb, 1, &(e->opaque)); /* opaque */ + READ_BITS(gb, 1, &(e->transparent)); /* transparent */ + READ_BITS(gb, 1, &(e->intra_cae)); /* intra_cae */ + READ_BITS(gb, 1, &(e->inter_cae)); /* inter_cae */ + READ_BITS(gb, 1, &(e->no_update)); /* no_update */ + READ_BITS(gb, 1, &(e->upsampling)); /* upsampling */ + } + + READ_BITS(gb, 1, &val); + if (!val) { /* texture_complexity_estimation_set_1_disable */ + READ_BITS(gb, 1, &(e->intra_blocks)); /* intra_blocks */ + READ_BITS(gb, 1, &(e->inter_blocks)); /* inter_blocks */ + READ_BITS(gb, 1, &(e->inter4v_blocks)); /* inter4v_blocks */ + READ_BITS(gb, 1, &(e->not_coded_blocks)); /* not_coded_blocks */ + } + } + + SKIP_BITS(gb, 1); + + READ_BITS(gb, 1, &val); + if (!val) { /* texture_complexity_estimation_set_2_disable */ + READ_BITS(gb, 1, &(e->dct_coefs)); /* dct_coefs */ + READ_BITS(gb, 1, &(e->dct_lines)); /* dct_lines */ + READ_BITS(gb, 1, &(e->vlc_symbols)); /* vlc_symbols */ + READ_BITS(gb, 1, &(e->vlc_bits)); /* vlc_bits */ + } + + READ_BITS(gb, 1, &val); + if (!val) { /* motion_compensation_complexity_disable */ + READ_BITS(gb, 1, &(e->apm)); /* apm */ + READ_BITS(gb, 1, &(e->npm)); /* npm */ + READ_BITS(gb, 1, &(e->interpolate_mc_q)); /* interpolate_mc_q */ + READ_BITS(gb, 1, &(e->forw_back_mc_q)); /* forw_back_mc_q */ + READ_BITS(gb, 1, &(e->halfpel2)); /* halfpel2 */ + READ_BITS(gb, 1, &(e->halfpel4)); /* halfpel4 */ + } + + SKIP_BITS(gb, 1); + + if (e->method == 1) { + READ_BITS(gb, 1, &val); + if (!val) { /* version2_complexity_estimation_disable */ + READ_BITS(gb, 1, &(e->sadct)); /* sadct */ + READ_BITS(gb, 1, &(e->quarterpel)); /* quarterpel */ + } + } + + return MPP_OK; + +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +/* vop estimation header */ +static MPP_RET read_vop_complexity_estimation_header(Mpeg4Estimation *e, BitReadCtx_t *gb, Mpg4Hdr *mp4Hdr, int coding_type) +{ + if (e->method == 0 || e->method == 1) { + if (coding_type == MPEG4_I_VOP) { + if (e->opaque) SKIP_BITS(gb, 8); /* dcecs_opaque */ + if (e->transparent) SKIP_BITS(gb, 8); /* */ + if (e->intra_cae) SKIP_BITS(gb, 8); /* */ + if (e->inter_cae) SKIP_BITS(gb, 8); /* */ + if (e->no_update) SKIP_BITS(gb, 8); /* */ + if (e->upsampling) SKIP_BITS(gb, 8); /* */ + if (e->intra_blocks) SKIP_BITS(gb, 8); /* */ + if (e->not_coded_blocks) SKIP_BITS(gb, 8); /* */ + if (e->dct_coefs) SKIP_BITS(gb, 8); /* */ + if (e->dct_lines) SKIP_BITS(gb, 8); /* */ + if (e->vlc_symbols) SKIP_BITS(gb, 8); /* */ + if (e->vlc_bits) SKIP_BITS(gb, 8); /* */ + if (e->sadct) SKIP_BITS(gb, 8); /* */ + } + + if (coding_type == MPEG4_P_VOP) { + if (e->opaque) SKIP_BITS(gb, 8); /* */ + if (e->transparent) SKIP_BITS(gb, 8); /* */ + if (e->intra_cae) SKIP_BITS(gb, 8); /* */ + if (e->inter_cae) SKIP_BITS(gb, 8); /* */ + if (e->no_update) SKIP_BITS(gb, 8); /* */ + if (e->upsampling) SKIP_BITS(gb, 8); /* */ + if (e->intra_blocks) SKIP_BITS(gb, 8); /* */ + if (e->not_coded_blocks) SKIP_BITS(gb, 8); /* */ + if (e->dct_coefs) SKIP_BITS(gb, 8); /* */ + if (e->dct_lines) SKIP_BITS(gb, 8); /* */ + if (e->vlc_symbols) SKIP_BITS(gb, 8); /* */ + if (e->vlc_bits) SKIP_BITS(gb, 8); /* */ + if (e->inter_blocks) SKIP_BITS(gb, 8); /* */ + if (e->inter4v_blocks) SKIP_BITS(gb, 8); /* */ + if (e->apm) SKIP_BITS(gb, 8); /* */ + if (e->npm) SKIP_BITS(gb, 8); /* */ + if (e->forw_back_mc_q) SKIP_BITS(gb, 8); /* */ + if (e->halfpel2) SKIP_BITS(gb, 8); /* */ + if (e->halfpel4) SKIP_BITS(gb, 8); /* */ + if (e->sadct) SKIP_BITS(gb, 8); /* */ + if (e->quarterpel) SKIP_BITS(gb, 8); /* */ + } + + if (coding_type == MPEG4_B_VOP) { + if (e->opaque) SKIP_BITS(gb, 8); /* */ + if (e->transparent) SKIP_BITS(gb, 8); /* */ + if (e->intra_cae) SKIP_BITS(gb, 8); /* */ + if (e->inter_cae) SKIP_BITS(gb, 8); /* */ + if (e->no_update) SKIP_BITS(gb, 8); /* */ + if (e->upsampling) SKIP_BITS(gb, 8); /* */ + if (e->intra_blocks) SKIP_BITS(gb, 8); /* */ + if (e->not_coded_blocks) SKIP_BITS(gb, 8); /* */ + if (e->dct_coefs) SKIP_BITS(gb, 8); /* */ + if (e->dct_lines) SKIP_BITS(gb, 8); /* */ + if (e->vlc_symbols) SKIP_BITS(gb, 8); /* */ + if (e->vlc_bits) SKIP_BITS(gb, 8); /* */ + if (e->inter_blocks) SKIP_BITS(gb, 8); /* */ + if (e->inter4v_blocks) SKIP_BITS(gb, 8); /* */ + if (e->apm) SKIP_BITS(gb, 8); /* */ + if (e->npm) SKIP_BITS(gb, 8); /* */ + if (e->forw_back_mc_q) SKIP_BITS(gb, 8); /* */ + if (e->halfpel2) SKIP_BITS(gb, 8); /* */ + if (e->halfpel4) SKIP_BITS(gb, 8); /* */ + if (e->interpolate_mc_q) SKIP_BITS(gb, 8); /* */ + if (e->sadct) SKIP_BITS(gb, 8); /* */ + if (e->quarterpel) SKIP_BITS(gb, 8); /* */ + } + +#ifdef GMC_SUPPORT + if (coding_type == MPEG4_S_VOP && mp4Hdr->vol.sprite_enable == MPEG4_SPRITE_STATIC) { + if (e->intra_blocks) SKIP_BITS(gb, 8); /* */ + if (e->not_coded_blocks) SKIP_BITS(gb, 8); /* */ + if (e->dct_coefs) SKIP_BITS(gb, 8); /* */ + if (e->dct_lines) SKIP_BITS(gb, 8); /* */ + if (e->vlc_symbols) SKIP_BITS(gb, 8); /* */ + if (e->vlc_bits) SKIP_BITS(gb, 8); /* */ + if (e->inter_blocks) SKIP_BITS(gb, 8); /* */ + if (e->inter4v_blocks) SKIP_BITS(gb, 8); /* */ + if (e->apm) SKIP_BITS(gb, 8); /* */ + if (e->npm) SKIP_BITS(gb, 8); /* */ + if (e->forw_back_mc_q) SKIP_BITS(gb, 8); /* */ + if (e->halfpel2) SKIP_BITS(gb, 8); /* */ + if (e->halfpel4) SKIP_BITS(gb, 8); /* */ + if (e->interpolate_mc_q) SKIP_BITS(gb, 8); /* */ + } +#else + (void)mp4Hdr; +#endif + } + + return MPP_OK; + +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static void init_mpg4_hdr_vol(Mpg4Hdr *header) +{ + memset(&header->vol, 0, sizeof(header->vol)); + header->vol.ver_id = 1; +} + +static void init_mpg4_hdr_vop(Mpg4Hdr *header) +{ + memset(&header->vop, 0, sizeof(header->vop)); + header->vop.coding_type = MPEG4_INVALID_VOP; +} + +static void init_mpg4_header(Mpg4Hdr *header) +{ + init_mpg4_hdr_vol(header); + header->usr.packed_mode = 0; + init_mpg4_hdr_vop(header); + header->pts = 0; + header->slot_idx = -1; +} + +static MPP_RET mpg4d_parse_vol_header(Mpg4dParserImpl *p, BitReadCtx_t *cb) +{ + RK_U32 val = 0; + Mpg4Hdr *mp4Hdr = &p->hdr_curr; + RK_S32 vol_ver_id; + RK_S32 aspect_ratio; + RK_S32 vol_control_parameters; + + SKIP_BITS(cb, 1); /* random_accessible_vol */ + READ_BITS(cb, 8, &(mp4Hdr->vol.vo_type), "vo_type"); + + READ_BITS(cb, 1, &val, "is_object_layer_identifier"); + if (val) { + READ_BITS(cb, 4, &vol_ver_id, "video_object_layer_verid"); + SKIP_BITS(cb, 3); /* video_object_layer_priority */ + } else { + vol_ver_id = mp4Hdr->vol.ver_id; + } + + READ_BITS(cb, 4, &aspect_ratio); + + if (aspect_ratio == MPEG4_VIDOBJLAY_AR_EXTPAR) { /* aspect_ratio_info */ + RK_S32 par_width, par_height; + + READ_BITS(cb, 8, &par_width); /* par_width */ + READ_BITS(cb, 8, &par_height); /* par_height */ + } + + READ_BITS(cb, 1, &vol_control_parameters); + + if (vol_control_parameters) { /* vol_control_parameters */ + SKIP_BITS(cb, 2); /* chroma_format */ + READ_BITS(cb, 1, &(mp4Hdr->vol.low_delay)); /* low_delay flage (1 means no B_VOP) */ + + READ_BITS(cb, 1, &val, "vbv_parameters"); + if (val) { + RK_U32 bitrate; + RK_U32 buffer_size; + RK_U32 occupancy; + + READ_BITS(cb, 15, &val, "first_half_bit_rate"); + bitrate = val << 15; + SKIP_BITS(cb, 1); + READ_BITS(cb, 15, &val, "latter_half_bit_rate"); + bitrate |= val; + SKIP_BITS(cb, 1); + + READ_BITS(cb, 15, &val, "first_half_vbv_buffer_size"); + buffer_size = val << 3; + SKIP_BITS(cb, 1); + READ_BITS(cb, 3, &val); + buffer_size |= val; /* latter_half_vbv_buffer_size */ + + READ_BITS(cb, 11, &val); + occupancy = val << 15; /* first_half_vbv_occupancy */ + SKIP_BITS(cb, 1); + READ_BITS(cb, 15, &val); + occupancy |= val; /* latter_half_vbv_occupancy */ + SKIP_BITS(cb, 1); + } + } else { + mp4Hdr->vol.low_delay = 0; + } + + if (mp4Hdr->vol.vo_type == 0 && vol_control_parameters == 0 && mp4Hdr->vop.frameNumber == 0) { + mpp_log("looks like this file was encoded with (divx4/(old)xvid/opendivx)\n"); + return MPEG4_INVALID_VOP; + } + + READ_BITS(cb, 2, &(mp4Hdr->vol.shape)); /* video_object_layer_shape */ + + if (mp4Hdr->vol.shape != MPEG4_VIDOBJLAY_SHAPE_RECTANGULAR) { + mpp_log("unsupported shape %d\n", mp4Hdr->vol.shape); + return MPEG4_INVALID_VOP; + } + + if (mp4Hdr->vol.shape == MPEG4_VIDOBJLAY_SHAPE_GRAYSCALE && vol_ver_id != 1) { + SKIP_BITS(cb, 4); /* video_object_layer_shape_extension */ + } + + SKIP_BITS(cb, 1); + + READ_BITS(cb, 16, &(mp4Hdr->vol.time_inc_resolution)); /* vop_time_increment_resolution */ + + if (mp4Hdr->vol.time_inc_resolution > 0) { + mp4Hdr->vol.time_inc_bits = MPP_MAX(log2bin(mp4Hdr->vol.time_inc_resolution - 1), 1); + } else { + /* for "old" xvid compatibility, set time_inc_bits = 1 */ + mp4Hdr->vol.time_inc_bits = 1; + } + + SKIP_BITS(cb, 1); + + READ_BITS(cb, 1, &val); + if (val) { /* fixed_vop_rate */ + SKIP_BITS(cb, mp4Hdr->vol.time_inc_bits); /* fixed_vop_time_increment */ + } + + if (mp4Hdr->vol.shape != MPEG4_VIDOBJLAY_SHAPE_BINARY_ONLY) { + if (mp4Hdr->vol.shape == MPEG4_VIDOBJLAY_SHAPE_RECTANGULAR) { + RK_S32 width, height; + + SKIP_BITS(cb, 1); + READ_BITS(cb, 13, &width); /* video_object_layer_width */ + SKIP_BITS(cb, 1); + READ_BITS(cb, 13, &height); /* video_object_layer_height */ + SKIP_BITS(cb, 1); + + mpg4d_dbg_bit("width %4d height %4d\n", width, height); + + mp4Hdr->vol.width = width; + mp4Hdr->vol.height = height; + mp4Hdr->vol.mb_width = (mp4Hdr->vol.width + 15) >> 4; + mp4Hdr->vol.mb_height = (mp4Hdr->vol.height + 15) >> 4; + mp4Hdr->vol.totalMbInVop = mp4Hdr->vol.mb_width * mp4Hdr->vol.mb_height; + mp4Hdr->vol.hor_stride = 16 * mp4Hdr->vol.mb_width; + mp4Hdr->vol.ver_stride = 16 * mp4Hdr->vol.mb_height; + } + + READ_BITS(cb, 1, &(mp4Hdr->vol.interlacing)); + + READ_BITS(cb, 1, &val); + if (!val) { /* obmc_disable */ + /* TODO */ + /* fucking divx4.02 has this enabled */ + } + + /* sprite_enable */ + READ_BITS(cb, (vol_ver_id == 1 ? 1 : 2), &(mp4Hdr->vol.sprite_enable)); + + if (mp4Hdr->vol.sprite_enable != MPEG4_SPRITE_NONE) { + mpp_err("GMC is not supported\n"); + return MPP_ERR_PROTOL; + } + + if (vol_ver_id != 1 && + mp4Hdr->vol.shape != MPEG4_VIDOBJLAY_SHAPE_RECTANGULAR) { + SKIP_BITS(cb, 1); /* sadct_disable */ + } + + READ_BITS(cb, 1, &val); + if (val) { /* not_8_bit */ + READ_BITS(cb, 4, &(mp4Hdr->vol.quant_bits));/* quant_precision */ + SKIP_BITS(cb, 4); /* bits_per_pixel */ + } else { + mp4Hdr->vol.quant_bits = 5; + } + + if (mp4Hdr->vol.shape == MPEG4_VIDOBJLAY_SHAPE_GRAYSCALE) { + SKIP_BITS(cb, 1); /* no_gray_quant_update */ + SKIP_BITS(cb, 1); /* composition_method */ + SKIP_BITS(cb, 1); /* linear_composition */ + } + + READ_BITS(cb, 1, &(mp4Hdr->vol.quant_type)); /* quant_type */ + + if (mp4Hdr->vol.quant_type) { + RK_U8 matrix[64]; + + READ_BITS(cb, 1, &val); + p->new_qm[0] = val; + if (val) { /* load_intra_quant_mat */ + mpg4d_parse_matrix(cb, matrix); + mpg4d_set_intra_matrix(p->quant_matrices, matrix); + } + + READ_BITS(cb, 1, &val); + p->new_qm[1] = val; + if (val) { /* load_inter_quant_mat */ + mpg4d_parse_matrix(cb, matrix); + mpg4d_set_inter_matrix(p->quant_matrices, matrix); + } + + if (mp4Hdr->vol.shape == MPEG4_VIDOBJLAY_SHAPE_GRAYSCALE) { + mpp_err("SHAPE_GRAYSCALE is not supported\n"); + return MPEG4_INVALID_VOP; + } + } else { + p->new_qm[0] = 0; + p->new_qm[1] = 0; + } + + if (vol_ver_id != 1) { + READ_BITS(cb, 1, &(mp4Hdr->vol.quarter_sample), "quarter_sample"); + } else + mp4Hdr->vol.quarter_sample = 0; + + /* complexity estimation disable */ + READ_BITS(cb, 1, &(mp4Hdr->vol.complexity_estimation_disable)); + + if (!mp4Hdr->vol.complexity_estimation_disable) { + mpg4d_dbg_bit("read_vol_complexity_estimation_header\n"); + if (read_vol_complexity_estimation_header(&p->estimation, cb)) + return MPP_ERR_STREAM; + } + + /* resync_marker_disable */ + READ_BITS(cb, 1, &(mp4Hdr->vol.resync_marker_disable)); + if (!mp4Hdr->vol.resync_marker_disable) { + mpp_log("resync marker enabled\n"); + // return MPEG4_RESYNC_VOP; + } + + READ_BITS(cb, 1, &val); + if (val) { /* data_partitioned */ + SKIP_BITS(cb, 1); /* reversible_vlc */ + } + + if (vol_ver_id != 1) { + READ_BITS(cb, 1, &(mp4Hdr->vol.newpred_enable)); + + if (mp4Hdr->vol.newpred_enable) { /* newpred_enable */ + SKIP_BITS(cb, 2); /* requested_upstream_message_type */ + SKIP_BITS(cb, 1); /* newpred_segment_type */ + } + + /* reduced_resolution_vop_enable */ + READ_BITS(cb, 1, &(mp4Hdr->vol.reduced_resolution_enable)); + } else { + mp4Hdr->vol.newpred_enable = 0; + mp4Hdr->vol.reduced_resolution_enable = 0; + } + + READ_BITS(cb, 1, &mp4Hdr->vol.scalability); /* scalability */ + + if (mp4Hdr->vol.scalability) { + SKIP_BITS(cb, 1); /* hierarchy_type */ + SKIP_BITS(cb, 4); /* ref_layer_id */ + SKIP_BITS(cb, 1); /* ref_layer_sampling_direc */ + SKIP_BITS(cb, 5); /* hor_sampling_factor_n */ + SKIP_BITS(cb, 5); /* hor_sampling_factor_m */ + SKIP_BITS(cb, 5); /* vert_sampling_factor_n */ + SKIP_BITS(cb, 5); /* vert_sampling_factor_m */ + SKIP_BITS(cb, 1); /* enhancement_type */ + + if (mp4Hdr->vol.shape == MPEG4_VIDOBJLAY_SHAPE_BINARY /* && hierarchy_type==0 */) { + /* use_ref_shape and so on*/ + SKIP_BITS(cb, ( 1 + 1 + 1 + 5 + 5 + 5 + 5)); + } + + mpp_err("scalability is not supported\n"); + return MPEG4_INVALID_VOP; + } + } else { /* mp4Hdr->shape == BINARY_ONLY */ + mpp_err("shape %d is not supported\n"); + return MPEG4_INVALID_VOP; + } + + return MPP_OK; + +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static MPP_RET mpg4d_parse_user_data(Mpg4dParserImpl *p, BitReadCtx_t *gb) +{ + RK_U8 tmp[256]; + Mpg4Hdr *mp4Hdr = &p->hdr_curr; + RK_U32 remain_bit = gb->bytes_left_ * 8 + gb->num_remaining_bits_in_curr_byte_; + RK_S32 i; + + memset(tmp, 0, 256); + + for (i = 0; i < 256 && gb->bytes_left_; i++) { + RK_U32 show_bit = MPP_MIN(remain_bit, 23); + RK_U32 val; + + SHOW_BITS(gb, show_bit, &val); + if (val == 0) + break; + + READ_BITS(gb, 8, &val); + tmp[i] = val; + remain_bit -= 8; + } + + tmp[i] = 0; + + if (!mp4Hdr->usr.packed_mode) { + RK_U32 packed = 0; + + if ((tmp[0] == 'D') && + (tmp[1] == 'i') && + (tmp[2] == 'v') && + (tmp[3] == 'X')) { + RK_U32 j = 4; + + if (tmp[j] <= '4') { + p->custorm_version = 4; + } else { + p->custorm_version = 5; + } + + while ((tmp[j] >= '0') && + (tmp[j] <= '9')) + j++; + + if (tmp[j] == 'b') { + j++; + + while ((tmp[j] >= '0') && + (tmp[j] <= '9')) + j++; + + packed = tmp[j]; + } else if ((tmp[j + 0] == 'B') && + (tmp[j + 1] == 'u') && + (tmp[j + 2] == 'i') && + (tmp[j + 3] == 'l') && + (tmp[j + 4] == 'd')) { + j += 5; + + while ((tmp[j] >= '0') && (tmp[j] <= '9')) + j++; + + packed = tmp[j]; + } + + mp4Hdr->usr.packed_mode = ((packed == 'p') ? (1) : (0)); + } else { + mp4Hdr->usr.packed_mode = 0; + } + } + + return MPP_OK; + +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static MPP_RET mpeg4_parse_gop_header(Mpg4dParserImpl *p, BitReadCtx_t *gb) +{ + (void) p; + RK_S32 hours, minutes, seconds; + + READ_BITS(gb, 5, &hours); + READ_BITS(gb, 6, &minutes); + SKIP_BITS(gb, 1); + READ_BITS(gb, 6, &seconds); + + SKIP_BITS(gb, 1); /* closed_gov */ + SKIP_BITS(gb, 1); /* broken_link */ + + return MPP_OK; + +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static MPP_RET mpeg4_parse_profile_level(Mpg4dParserImpl *p, BitReadCtx_t *bc) +{ + READ_BITS(bc, 4, &p->profile); + READ_BITS(bc, 4, &p->level); + mpp_log("mpeg4 stream profile %d level %d\n", p->profile, p->level); + return MPP_OK; + +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static MPP_RET mpeg4_parse_vop_header(Mpg4dParserImpl *p, BitReadCtx_t *gb) +{ + RK_U32 val; + RK_U32 time_incr = 0; + RK_S32 time_increment = 0; + Mpg4Hdr *mp4Hdr = &p->hdr_curr; + + READ_BITS(gb, 2, &(mp4Hdr->vop.coding_type)); /* vop_coding_type */ + mpg4d_dbg_bit("coding_type %d\n", mp4Hdr->vop.coding_type); + if (mp4Hdr->vop.coding_type == MPEG4_B_VOP && + (p->hdr_ref0.slot_idx == -1 || p->hdr_ref1.slot_idx == -1)) { + mpp_log("MPEG4 DIVX 5 PBBI case found!\n"); + return MPP_OK; + } + + READ_BITS(gb, 1, &val); + while (val != 0) { + time_incr++; /* time_base */ + READ_BITS(gb, 1, &val); + } + + SKIP_BITS(gb, 1); + + if (mp4Hdr->vol.time_inc_bits) { + /* vop_time_increment */ + READ_BITS(gb, mp4Hdr->vol.time_inc_bits, &time_increment); + } + + if (mp4Hdr->vop.coding_type != MPEG4_B_VOP) { + mp4Hdr->vop.last_time_base = mp4Hdr->vop.time_base; + mp4Hdr->vop.time_base += time_incr; + mp4Hdr->vop.time = mp4Hdr->vop.time_base * mp4Hdr->vol.time_inc_resolution + time_increment; + mp4Hdr->vop.time_pp = (RK_S32)(mp4Hdr->vop.time - mp4Hdr->vop.last_non_b_time); + mp4Hdr->vop.last_non_b_time = mp4Hdr->vop.time; + } else { + mp4Hdr->vop.time = (mp4Hdr->vop.last_time_base + time_incr) * mp4Hdr->vol.time_inc_resolution + time_increment; + mp4Hdr->vop.time_bp = mp4Hdr->vop.time_pp - (RK_S32)(mp4Hdr->vop.last_non_b_time - mp4Hdr->vop.time); + } + + mp4Hdr->pts = (RK_S64)mp4Hdr->vop.time; + + if (p->use_internal_pts) { + p->pts = mp4Hdr->vop.time; + } + + SKIP_BITS(gb, 1); + + READ_BITS(gb, 1, &val); + if (!val) { /* vop_coded */ + mp4Hdr->vop.coding_type = MPEG4_N_VOP; + mpp_log("found N frame\n"); + return MPP_OK; + } + + if (mp4Hdr->vol.newpred_enable) { + RK_S32 vop_id; + RK_S32 vop_id_for_prediction; + + READ_BITS(gb, (MPP_MIN(mp4Hdr->vol.time_inc_bits + 3, 15)), &vop_id); + + READ_BITS(gb, 1, &val); + if (val) { + /* vop_id_for_prediction_indication */ + READ_BITS(gb, MPP_MIN(mp4Hdr->vol.time_inc_bits + 3, 15), &vop_id_for_prediction); + } + + SKIP_BITS(gb, 1); + } + + if ((mp4Hdr->vol.shape != MPEG4_VIDOBJLAY_SHAPE_BINARY_ONLY) && + ((mp4Hdr->vop.coding_type == MPEG4_P_VOP) || + (mp4Hdr->vop.coding_type == MPEG4_S_VOP && + mp4Hdr->vol.sprite_enable == MPEG4_SPRITE_GMC))) { + READ_BITS(gb, 1, &(mp4Hdr->vop.rounding)); /* rounding_type */ + } + + if (mp4Hdr->vol.reduced_resolution_enable && + mp4Hdr->vol.shape == MPEG4_VIDOBJLAY_SHAPE_RECTANGULAR && + (mp4Hdr->vop.coding_type == MPEG4_P_VOP || mp4Hdr->vop.coding_type == MPEG4_I_VOP)) { + + READ_BITS(gb, 1, &val); + } + + mpp_assert(mp4Hdr->vol.shape == MPEG4_VIDOBJLAY_SHAPE_RECTANGULAR); + + if (mp4Hdr->vol.shape != MPEG4_VIDOBJLAY_SHAPE_BINARY_ONLY) { + if (!mp4Hdr->vol.complexity_estimation_disable) { + read_vop_complexity_estimation_header(&p->estimation, gb, mp4Hdr, mp4Hdr->vop.coding_type); + } + + READ_BITS(gb, 3, &val); + /* intra_dc_vlc_threshold */ + mp4Hdr->vop.intra_dc_vlc_threshold = val; + mp4Hdr->vop.top_field_first = 0; + mp4Hdr->vop.alternate_vertical_scan = 0; + + if (mp4Hdr->vol.interlacing) { + READ_BITS(gb, 1, &(mp4Hdr->vop.top_field_first)); + READ_BITS(gb, 1, &(mp4Hdr->vop.alternate_vertical_scan)); + } + } + + if ((mp4Hdr->vol.sprite_enable == MPEG4_SPRITE_STATIC || + mp4Hdr->vol.sprite_enable == MPEG4_SPRITE_GMC) && + mp4Hdr->vop.coding_type == MPEG4_S_VOP) { + mpp_err("unsupport split mode %d coding type %d\n", + mp4Hdr->vol.sprite_enable, mp4Hdr->vop.coding_type); + return MPP_ERR_STREAM; + } + + READ_BITS(gb, mp4Hdr->vol.quant_bits, &(mp4Hdr->vop.quant)); + if (mp4Hdr->vop.quant < 1) /* vop_quant */ + mp4Hdr->vop.quant = 1; + + if (mp4Hdr->vop.coding_type != MPEG4_I_VOP) { + READ_BITS(gb, 3, &(mp4Hdr->vop.fcode_forward)); /* fcode_forward */ + } + + if (mp4Hdr->vop.coding_type == MPEG4_B_VOP) { + READ_BITS(gb, 3, &(mp4Hdr->vop.fcode_backward)); /* fcode_backward */ + } + + if (!mp4Hdr->vol.scalability) { + if ((mp4Hdr->vol.shape != MPEG4_VIDOBJLAY_SHAPE_RECTANGULAR) && + (mp4Hdr->vop.coding_type != MPEG4_I_VOP)) { + SKIP_BITS(gb, 1); /* vop_shape_coding_type */ + } + } + + // NOTE: record header used bits here + mp4Hdr->vop.hdr_bits = gb->used_bits; + + return MPP_OK; +__BITREAD_ERR: + return MPP_ERR_STREAM; +} + +static void mpg4d_fill_picture_parameters(const Mpg4dParserImpl *p, + DXVA_PicParams_MPEG4_PART2 *pp) +{ + const Mpg4Hdr *hdr_curr = &p->hdr_curr; + const Mpg4Hdr *hdr_ref0 = &p->hdr_ref0; + const Mpg4Hdr *hdr_ref1 = &p->hdr_ref1; + + pp->short_video_header = 0; + pp->vop_coding_type = hdr_curr->vop.coding_type; + pp->vop_quant = hdr_curr->vop.quant; + pp->wDecodedPictureIndex = hdr_curr->slot_idx; + pp->wForwardRefPictureIndex = hdr_ref0->slot_idx; + pp->wBackwardRefPictureIndex = hdr_ref1->slot_idx; + pp->vop_time_increment_resolution = hdr_curr->vol.time_inc_resolution; + pp->TRB[0] = 0; /* FIXME: */ + pp->TRD[0] = 0; /* FIXME: */ + pp->unPicPostProc = 0; /* FIXME: */ + pp->interlaced = hdr_curr->vol.interlacing; + pp->quant_type = hdr_curr->vol.quant_type; + pp->quarter_sample = hdr_curr->vol.quarter_sample; + pp->resync_marker_disable = 0; /* FIXME: */ + pp->data_partitioned = 0; /* FIXME: */ + pp->reversible_vlc = 0; /* FIXME: */ + pp->reduced_resolution_vop_enable = hdr_curr->vol.reduced_resolution_enable; + pp->vop_coded = (hdr_curr->vop.coding_type != MPEG4_N_VOP); + pp->vop_rounding_type = hdr_curr->vop.rounding; + pp->intra_dc_vlc_thr = hdr_curr->vop.intra_dc_vlc_threshold; + pp->top_field_first = hdr_curr->vop.top_field_first; + pp->alternate_vertical_scan_flag = hdr_curr->vop.alternate_vertical_scan; + pp->profile_and_level_indication = (p->profile << 4) | p->level; + pp->video_object_layer_verid = hdr_curr->vol.ver_id; + pp->vop_width = hdr_curr->vol.width; + pp->vop_height = hdr_curr->vol.height; + pp->sprite_enable = hdr_curr->vol.sprite_enable; + pp->no_of_sprite_warping_points = 0; /* FIXME: */ + pp->sprite_warping_accuracy = 0; /* FIXME: */ + memset(pp->warping_mv, 0, sizeof(pp->warping_mv)); + pp->vop_fcode_forward = hdr_curr->vop.fcode_forward; + pp->vop_fcode_backward = hdr_curr->vop.fcode_backward; + pp->StatusReportFeedbackNumber = 0; /* FIXME: */ + pp->Reserved16BitsA = 0; /* FIXME: */ + pp->Reserved16BitsB = 0; /* FIXME: */ + + // Rockchip special data + pp->custorm_version = p->custorm_version; + pp->prev_coding_type = (hdr_ref0->vop.coding_type == MPEG4_INVALID_VOP) ? (0) : (hdr_ref0->vop.coding_type); + pp->time_bp = hdr_curr->vop.time_bp; + pp->time_pp = hdr_curr->vop.time_pp; + pp->header_bits = hdr_curr->vop.hdr_bits; +} + +static void mpg4d_fill_quantization_matrices(const Mpg4dParserImpl *p, + DXVA_QmatrixData *qm) +{ + RK_S32 i = 0; + + qm->bNewQmatrix[0] = p->new_qm[0]; + qm->bNewQmatrix[1] = p->new_qm[1]; + qm->bNewQmatrix[2] = 0; + qm->bNewQmatrix[3] = 0; + + // intra Y + if (p->new_qm[0]) { + for (i = 0; i < 64; i++) { + qm->Qmatrix[0][i] = p->quant_matrices[i]; + } + } else { + memset(qm->Qmatrix[0], 0, sizeof(qm->Qmatrix[0])); + } + + // inter Y + if (p->new_qm[1]) { + for (i = 0; i < 64; i++) { + qm->Qmatrix[1][i] = p->quant_matrices[64 + i]; + } + } else { + memset(qm->Qmatrix[1], 0, sizeof(qm->Qmatrix[1])); + } + + memset(qm->Qmatrix[2], 0, sizeof(qm->Qmatrix[2])); + memset(qm->Qmatrix[3], 0, sizeof(qm->Qmatrix[3])); +} + +static void mpg4_syntax_init(mpeg4d_dxva2_picture_context_t *syntax) +{ + DXVA2_DecodeBufferDesc *data = &syntax->desc[0]; + + //!< commit picture paramters + memset(data, 0, sizeof(*data)); + data->CompressedBufferType = DXVA2_PictureParametersBufferType; + data->pvPVPState = (void *)&syntax->pp; + data->DataSize = sizeof(syntax->pp); + syntax->data[0] = data; + + //!< commit Qmatrix + data = &syntax->desc[1]; + memset(data, 0, sizeof(*data)); + data->CompressedBufferType = DXVA2_InverseQuantizationMatrixBufferType; + data->pvPVPState = (void *)&syntax->qm; + data->DataSize = sizeof(syntax->qm); + data->NumMBsInBuffer = 0; + syntax->data[1] = data; + + //!< commit bitstream + data = &syntax->desc[2]; + memset(data, 0, sizeof(*data)); + data->CompressedBufferType = DXVA2_BitStreamDateBufferType; + syntax->data[2] = data; +} + MPP_RET mpp_mpg4_parser_init(Mpg4dParser *ctx, MppBufSlots frame_slots) { + BitReadCtx_t *bit_ctx = mpp_calloc(BitReadCtx_t, 1); Mpg4dParserImpl *p = mpp_calloc(Mpg4dParserImpl, 1); - if (NULL == p) { + mpeg4d_dxva2_picture_context_t *syntax = mpp_calloc(mpeg4d_dxva2_picture_context_t, 1); + + if (NULL == p || NULL == bit_ctx || NULL == syntax) { mpp_err_f("malloc context failed\n"); + if (p) + mpp_free(p); + if (bit_ctx) + mpp_free(bit_ctx); + if (syntax) + mpp_free(syntax); return MPP_NOK; } + mpp_buf_slot_setup(frame_slots, 8); - p->frame_slots = frame_slots; - p->pos_frm_start = -1; - p->pos_frm_end = -1; + p->frame_slots = frame_slots; + p->use_internal_pts = 0; + p->pos_frm_start = -1; + p->pos_frm_end = -1; + p->bit_ctx = bit_ctx; + init_mpg4_header(&p->hdr_curr); + init_mpg4_header(&p->hdr_ref0); + init_mpg4_header(&p->hdr_ref1); + mpg4_syntax_init(syntax); + p->syntax = syntax; + + mpp_env_get_u32("mpg4d_debug", &mpg4d_debug, 0); + *ctx = p; return MPP_OK; } @@ -64,7 +1077,17 @@ MPP_RET mpp_mpg4_parser_init(Mpg4dParser *ctx, MppBufSlots frame_slots) MPP_RET mpp_mpg4_parser_deinit(Mpg4dParser ctx) { Mpg4dParserImpl *p = (Mpg4dParserImpl *)ctx; - mpp_free(p); + if (p) { + if (p->bit_ctx) { + mpp_free(p->bit_ctx); + p->bit_ctx = NULL; + } + if (p->syntax) { + mpp_free(p->syntax); + p->syntax = NULL; + } + mpp_free(p); + } return MPP_OK; } @@ -87,37 +1110,54 @@ MPP_RET mpp_mpg4_parser_split(Mpg4dParser ctx, MppPacket dst, MppPacket src) RK_U8 *dst_buf = mpp_packet_get_data(dst); size_t dst_len = mpp_packet_get_length(dst); RK_U8 *src_buf = mpp_packet_get_pos(src); - size_t src_len = mpp_packet_get_length(src); + RK_S32 src_len = (RK_S32)mpp_packet_get_length(src); RK_S32 pos_frm_start = p->pos_frm_start; RK_S32 pos_frm_end = p->pos_frm_end; - size_t src_pos = 0; - RK_U32 state = 0; + RK_U32 src_eos = mpp_packet_get_eos(src); + RK_S32 src_pos = 0; + RK_U32 state = (RK_U32)-1; mpp_assert(src_len); + if (dst_len) { + mpp_assert(dst_len >= 4); + state = ((RK_U32)(dst_buf[dst_len - 1]) << 0) | + ((RK_U32)(dst_buf[dst_len - 2]) << 8) | + ((RK_U32)(dst_buf[dst_len - 3]) << 16) | + ((RK_U32)(dst_buf[dst_len - 4]) << 24); + } + if (pos_frm_start < 0) { // scan for frame start for (src_pos = 0; src_pos < src_len; src_pos++) { state = (state << 8) | src_buf[src_pos]; - if (state == 0x1B6) { + if (state == MPG4_VOP_STARTCODE) { src_pos++; - pos_frm_start = src_pos; + pos_frm_start = src_pos - 4; break; } } } - if (pos_frm_start) { + if (pos_frm_start >= 0) { // scan for frame end for (; src_pos < src_len; src_pos++) { state = (state << 8) | src_buf[src_pos]; - if ((state & 0xFFFFFF00) == 0x100) { + + if ((state & 0xFFFFFFFF) == MPG4_VOP_STARTCODE) { pos_frm_end = src_pos - 3; break; } } + if (src_eos && src_pos == src_len) { + pos_frm_end = src_len; + mpp_packet_set_eos(dst); + } } + //mpp_log("pkt pos: start %d end %d len: left %d in %d\n", + // pos_frm_start, pos_frm_end, dst_len, src_len); + if (pos_frm_start < 0 || pos_frm_end < 0) { // do not found frame start or do not found frame end, just copy the hold buffer to dst memcpy(dst_buf + dst_len, src_buf, src_len); @@ -129,8 +1169,12 @@ MPP_RET mpp_mpg4_parser_split(Mpg4dParser ctx, MppPacket dst, MppPacket src) // found both frame start and frame end - only copy frame memcpy(dst_buf + dst_len, src_buf, pos_frm_end); mpp_packet_set_length(dst, dst_len + pos_frm_end); + // set src buffer pos to end to src buffer mpp_packet_set_pos(src, src_buf + pos_frm_end); + mpp_assert((RK_S32)mpp_packet_get_length(src) == (src_len - pos_frm_end)); + mpp_packet_set_length(src, src_len - pos_frm_end); + // return ok indicate the frame is ready and reset frame start/end position ret = MPP_OK; pos_frm_start = -1; @@ -145,87 +1189,299 @@ MPP_RET mpp_mpg4_parser_split(Mpg4dParser ctx, MppPacket dst, MppPacket src) MPP_RET mpp_mpg4_parser_decode(Mpg4dParser ctx, MppPacket pkt) { + MPP_RET ret = MPP_OK; Mpg4dParserImpl *p = (Mpg4dParserImpl *)ctx; + BitReadCtx_t *gb = p->bit_ctx; RK_U8 *buf = mpp_packet_get_data(pkt); + RK_S32 len = (RK_S32)mpp_packet_get_length(pkt); + RK_U32 vol_found = 0; + RK_U32 vop_found = 0; + RK_U32 startcode = 0xff; - p->width = 1920; - p->height = 1080; + // setup bit read context + mpp_set_bitread_ctx(gb, buf, len); + while (gb->bytes_left_) { + RK_U32 val = 0; + + READ_BITS(gb, 8, &val); + startcode = (startcode << 8) | val; + + if ((startcode & 0xFFFFFF00) != 0x100) + continue; + + if (mpg4d_debug & MPG4D_DBG_STARTCODE) { + mpp_log_f("start code %03x\n", startcode); + if (startcode <= 0x11F) + mpp_log_f("Video Object Start"); + else if (startcode <= 0x12F) + mpp_log_f("Video Object Layer Start"); + else if (startcode <= 0x13F) + mpp_log_f("Reserved"); + else if (startcode <= 0x15F) + mpp_log_f("FGS bp start"); + else if (startcode <= 0x1AF) + mpp_log_f("Reserved"); + else if (startcode == 0x1B0) + mpp_log_f("Visual Object Seq Start"); + else if (startcode == 0x1B1) + mpp_log_f("Visual Object Seq End"); + else if (startcode == 0x1B2) + mpp_log_f("User Data"); + else if (startcode == 0x1B3) + mpp_log_f("Group of VOP start"); + else if (startcode == 0x1B4) + mpp_log_f("Video Session Error"); + else if (startcode == 0x1B5) + mpp_log_f("Visual Object Start"); + else if (startcode == 0x1B6) + mpp_log_f("Video Object Plane start"); + else if (startcode == 0x1B7) + mpp_log_f("slice start"); + else if (startcode == 0x1B8) + mpp_log_f("extension start"); + else if (startcode == 0x1B9) + mpp_log_f("fgs start"); + else if (startcode == 0x1BA) + mpp_log_f("FBA Object start"); + else if (startcode == 0x1BB) + mpp_log_f("FBA Object Plane start"); + else if (startcode == 0x1BC) + mpp_log_f("Mesh Object start"); + else if (startcode == 0x1BD) + mpp_log_f("Mesh Object Plane start"); + else if (startcode == 0x1BE) + mpp_log_f("Still Texture Object start"); + else if (startcode == 0x1BF) + mpp_log_f("Texture Spatial Layer start"); + else if (startcode == 0x1C0) + mpp_log_f("Texture SNR Layer start"); + else if (startcode == 0x1C1) + mpp_log_f("Texture Tile start"); + else if (startcode == 0x1C2) + mpp_log_f("Texture Shape Layer start"); + else if (startcode == 0x1C3) + mpp_log_f("stuffing start"); + else if (startcode <= 0x1C5) + mpp_log_f("reserved"); + else if (startcode <= 0x1FF) + mpp_log_f("System start"); + } + + if (startcode >= MPG4_VOL_STARTCODE && startcode <= MPG4_VOL_STOPCODE) { + ret = mpg4d_parse_vol_header(p, gb); + if (!vol_found) + vol_found = (ret == MPP_OK); + } else if (startcode == MPG4_USER_DATA_STARTCODE) { + ret = mpg4d_parse_user_data(p, gb); + } else if (startcode == MPG4_GOP_STARTCODE) { + ret = mpeg4_parse_gop_header(p, gb); + } else if (startcode == MPG4_VOS_STARTCODE) { + ret = mpeg4_parse_profile_level(p, gb); + } else if (startcode == MPG4_VOP_STARTCODE) { + ret = mpeg4_parse_vop_header(p, gb); + if (!vop_found) + vop_found = (ret == MPP_OK); + } + + if (ret) { + mpp_assert(0); + goto __BITREAD_ERR; + } + + if (gb->num_remaining_bits_in_curr_byte_) { + mpg4d_dbg_bit("byte align skip %d\n", gb->num_remaining_bits_in_curr_byte_); + SKIP_BITS(gb, gb->num_remaining_bits_in_curr_byte_); + } + } + + if (vol_found) { + p->width = p->hdr_curr.vol.width; + p->height = p->hdr_curr.vol.height; + } + + if (!p->use_internal_pts) + p->pts = mpp_packet_get_pts(pkt); + + ret = (vop_found && (ret == MPP_OK)) ? (MPP_OK) : (MPP_NOK); + +__BITREAD_ERR: mpp_packet_set_pos(pkt, buf); mpp_packet_set_length(pkt, 0); - - p->pts = mpp_packet_get_pts(pkt); p->eos = mpp_packet_get_eos(pkt); - return MPP_OK; + return ret; } -MPP_RET mpp_mpg4_parser_setup_syntax(Mpg4dParser ctx, MppSyntax syntax) -{ - (void) ctx; - (void) syntax; - return MPP_OK; -} - -MPP_RET mpp_mpg4_parser_setup_output(Mpg4dParser ctx, RK_S32 *output) +MPP_RET mpp_mpg4_parser_setup_syntax(Mpg4dParser ctx, MppSyntax *syntax) { Mpg4dParserImpl *p = (Mpg4dParserImpl *)ctx; - MppBufSlots slots = p->frame_slots; - MppFrame frame = NULL; + mpeg4d_dxva2_picture_context_t *syn = p->syntax; + + mpg4d_fill_picture_parameters(p, &syn->pp); + mpg4d_fill_quantization_matrices(p, &syn->qm); + + // fill bit stream parameter + syn->data[2]->DataSize = p->bit_ctx->buf_len; + syn->data[2]->DataOffset = p->hdr_curr.vop.hdr_bits; + syn->data[2]->pvPVPState = p->bit_ctx->buf; + + syntax->number = 3; + syntax->data = syn->data; + + return MPP_OK; +} + +MPP_RET mpp_mpg4_parser_setup_hal_output(Mpg4dParser ctx, RK_S32 *output) +{ + Mpg4dParserImpl *p = (Mpg4dParserImpl *)ctx; + Mpg4Hdr *hdr_curr = &p->hdr_curr; RK_S32 index = -1; - mpp_frame_init(&frame); - mpp_frame_set_width(frame, p->width); - mpp_frame_set_height(frame, p->height); - mpp_frame_set_hor_stride(frame, MPP_ALIGN(p->width, 16)); - mpp_frame_set_ver_stride(frame, MPP_ALIGN(p->height, 16)); + if (hdr_curr->vop.coding_type != MPEG4_N_VOP) { + MppBufSlots slots = p->frame_slots; + RK_U32 frame_mode = MPP_FRAME_FLAG_FRAME; + MppFrame frame = NULL; + + mpp_frame_init(&frame); + mpp_frame_set_width(frame, p->width); + mpp_frame_set_height(frame, p->height); + mpp_frame_set_hor_stride(frame, MPP_ALIGN(p->width, 16)); + mpp_frame_set_ver_stride(frame, MPP_ALIGN(p->height, 16)); + + /* + * set slots information + * 1. output index MUST be set + * 2. get unused index for output if needed + * 3. set output index as hal_input + * 4. set frame information to output index + * 5. if one frame can be display, it SHOULD be enqueued to display queue + */ + mpp_buf_slot_get_unused(slots, &index); + mpp_buf_slot_set_flag(slots, index, SLOT_HAL_OUTPUT); + mpp_frame_set_pts(frame, p->pts); + mpp_frame_set_eos(frame, p->eos); + + if (hdr_curr->vol.interlacing) { + frame_mode = (hdr_curr->vop.top_field_first) ? + (MPP_FRAME_FLAG_TOP_FIELD) : + (MPP_FRAME_FLAG_BOT_FIELD); + } + mpp_frame_set_mode(frame, frame_mode); + + mpp_buf_slot_set_prop(slots, index, SLOT_FRAME, frame); + mpp_frame_deinit(&frame); + mpp_assert(NULL == frame); + + hdr_curr->slot_idx = index; + } - /* - * set slots information - * 1. output index MUST be set - * 2. get unused index for output if needed - * 3. set output index as hal_input - * 4. set frame information to output index - * 5. if one frame can be display, it SHOULD be enqueued to display queue - */ - mpp_buf_slot_get_unused(slots, &index); - mpp_buf_slot_set_flag(slots, index, SLOT_HAL_OUTPUT); - mpp_frame_set_pts(frame, p->pts); - mpp_frame_set_eos(frame, p->eos); - mpp_buf_slot_set_prop(slots, index, SLOT_FRAME, frame); - mpp_frame_deinit(&frame); - mpp_assert(NULL == frame); p->output = index; *output = index; + return MPP_OK; } MPP_RET mpp_mpg4_parser_setup_refer(Mpg4dParser ctx, RK_S32 *refer, RK_S32 max_ref) { - (void) ctx; - /* - * setup output task - * 1. valid flag MUST be set if need hardware to run once - * 2. set output slot index - * 3. set reference slot index - */ + Mpg4dParserImpl *p = (Mpg4dParserImpl *)ctx; + Mpg4Hdr *hdr_curr = &p->hdr_curr; + MppBufSlots slots = p->frame_slots; + RK_S32 index; + memset(refer, -1, sizeof(max_ref * sizeof(*refer))); + if (hdr_curr->vop.coding_type != MPEG4_N_VOP) { + index = p->hdr_ref0.slot_idx; + if (index >= 0) { + mpp_buf_slot_set_flag(slots, index, SLOT_HAL_INPUT); + refer[0] = index; + } + index = p->hdr_ref1.slot_idx; + if (index >= 0) { + mpp_buf_slot_set_flag(slots, index, SLOT_HAL_INPUT); + refer[1] = index; + } + } + return MPP_OK; } -MPP_RET mpp_mpg4_parser_setup_display(Mpg4dParser ctx) +MPP_RET mpp_mpg4_parser_update_dpb(Mpg4dParser ctx) { Mpg4dParserImpl *p = (Mpg4dParserImpl *)ctx; MppBufSlots slots = p->frame_slots; - RK_S32 output = p->output; + Mpg4Hdr *hdr_curr = &p->hdr_curr; + Mpg4Hdr *hdr_ref0 = &p->hdr_ref0; + Mpg4Hdr *hdr_ref1 = &p->hdr_ref1; + RK_S32 coding_type = hdr_curr->vop.coding_type; + RK_S32 index = p->output; + // update pts increacement + if (p->pts != p->last_pts) + p->pts_inc = p->pts - p->last_pts; + + switch (coding_type) { + case MPEG4_B_VOP : { + mpp_assert((hdr_ref0->slot_idx >= 0) && (hdr_ref1->slot_idx >= 0)); + // B frame -> index current frame + // output current frame and do not change ref0 and ref1 + index = hdr_curr->slot_idx; + mpp_buf_slot_set_flag(slots, index, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(slots, index, QUEUE_DISPLAY); + } /* - * update dpb status assuming that hw has decoded the frame + * NOTE: here fallback to N vop - do nothing */ - mpp_buf_slot_set_flag(slots, output, SLOT_QUEUE_USE); - mpp_buf_slot_enqueue(slots, output, QUEUE_DISPLAY); + case MPEG4_INVALID_VOP : + case MPEG4_N_VOP : { + } break; + case MPEG4_I_VOP : + case MPEG4_P_VOP : + case MPEG4_S_VOP : + // the other case -> index reference 0 + index = hdr_ref0->slot_idx; + if (index >= 0) { + mpp_buf_slot_set_flag(slots, index, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(slots, index, QUEUE_DISPLAY); + } + // non B frame send this frame to reference queue + mpp_buf_slot_set_flag(slots, hdr_curr->slot_idx, SLOT_CODEC_USE); + + // release ref1 + index = hdr_ref1->slot_idx; + if (index >= 0) + mpp_buf_slot_clr_flag(slots, index, SLOT_CODEC_USE); + + // swap ref0 to ref1, current to ref0 + *hdr_ref1 = *hdr_ref0; + *hdr_ref0 = *hdr_curr; + init_mpg4_hdr_vop(hdr_curr); + hdr_curr->slot_idx = -1; + hdr_curr->pts = 0; + } + + if (p->eos) { + index = hdr_ref0->slot_idx; + if (index >= 0) { + mpp_buf_slot_set_flag(slots, index, SLOT_QUEUE_USE); + mpp_buf_slot_enqueue(slots, index, QUEUE_DISPLAY); + mpp_buf_slot_clr_flag(slots, index, SLOT_CODEC_USE); + } + + index = hdr_ref1->slot_idx; + if (index >= 0) + mpp_buf_slot_clr_flag(slots, index, SLOT_CODEC_USE); + } + + p->last_pts = p->pts; return MPP_OK; } +MPP_RET mpp_mpg4_parser_set_pts_mode(Mpg4dParser ctx, RK_U32 use_internal_pts) +{ + Mpg4dParserImpl *p = (Mpg4dParserImpl *)ctx; + p->use_internal_pts = use_internal_pts; + return MPP_OK; +} diff --git a/mpp/codec/dec/mpg4/mpg4d_parser.h b/mpp/codec/dec/mpg4/mpg4d_parser.h index abbed7b3..d413f86b 100644 --- a/mpp/codec/dec/mpg4/mpg4d_parser.h +++ b/mpp/codec/dec/mpg4/mpg4d_parser.h @@ -18,20 +18,15 @@ #ifndef __MPG4D_PARSER_H__ #define __MPG4D_PARSER_H__ -#include "mpp_log.h" #include "mpp_packet.h" #include "mpp_buf_slot.h" #include "hal_task.h" -extern RK_U32 mpg4d_debug; #define MPG4D_DBG_FUNCTION (0x00000001) -#define MPG4D_DBG_PPS (0x00000008) -#define MPG4D_DBG_SLICE_HDR (0x00000010) -#define MPG4D_DBG_REF (0x00000080) +#define MPG4D_DBG_STARTCODE (0x00000002) +#define MPG4D_DBG_BITS (0x00000004) #define MPG4D_DBG_TIME (0x00000100) -#define mpg4d_dbg(flag, fmt, ...) _mpp_dbg(mpg4d_debug, flag, fmt, ## __VA_ARGS__) - typedef void* Mpg4dParser; #ifdef __cplusplus @@ -45,10 +40,11 @@ MPP_RET mpp_mpg4_parser_reset(Mpg4dParser ctx); MPP_RET mpp_mpg4_parser_split(Mpg4dParser ctx, MppPacket dst, MppPacket src); MPP_RET mpp_mpg4_parser_decode(Mpg4dParser ctx, MppPacket pkt); -MPP_RET mpp_mpg4_parser_setup_syntax(Mpg4dParser ctx, MppSyntax syntax); -MPP_RET mpp_mpg4_parser_setup_output(Mpg4dParser ctx, RK_S32 *output); +MPP_RET mpp_mpg4_parser_setup_syntax(Mpg4dParser ctx, MppSyntax *syntax); +MPP_RET mpp_mpg4_parser_setup_hal_output(Mpg4dParser ctx, RK_S32 *output); MPP_RET mpp_mpg4_parser_setup_refer(Mpg4dParser ctx, RK_S32 *refer, RK_S32 max_ref); -MPP_RET mpp_mpg4_parser_setup_display(Mpg4dParser ctx); +MPP_RET mpp_mpg4_parser_update_dpb(Mpg4dParser ctx); +MPP_RET mpp_mpg4_parser_set_pts_mode(Mpg4dParser ctx, RK_U32 use_internal_pts); #ifdef __cplusplus } diff --git a/mpp/common/mpg4d_syntax.h b/mpp/common/mpg4d_syntax.h index 27c329e9..8f780af0 100644 --- a/mpp/common/mpg4d_syntax.h +++ b/mpp/common/mpg4d_syntax.h @@ -26,6 +26,44 @@ #ifndef __MPG4D_SYNTAX__ #define __MPG4D_SYNTAX__ +#include "dxva_syntax.h" + +#define MPEG4_VIDOBJLAY_AR_SQUARE 1 +#define MPEG4_VIDOBJLAY_AR_625TYPE_43 2 +#define MPEG4_VIDOBJLAY_AR_525TYPE_43 3 +#define MPEG4_VIDOBJLAY_AR_625TYPE_169 8 +#define MPEG4_VIDOBJLAY_AR_525TYPE_169 9 +#define MPEG4_VIDOBJLAY_AR_EXTPAR 15 + +#define MPEG4_VIDOBJLAY_SHAPE_RECTANGULAR 0 +#define MPEG4_VIDOBJLAY_SHAPE_BINARY 1 +#define MPEG4_VIDOBJLAY_SHAPE_BINARY_ONLY 2 +#define MPEG4_VIDOBJLAY_SHAPE_GRAYSCALE 3 + +/*video sprite specific*/ +#define MPEG4_SPRITE_NONE 0 +#define MPEG4_SPRITE_STATIC 1 +#define MPEG4_SPRITE_GMC 2 + +/*video vop specific*/ +typedef enum { + MPEG4_RESYNC_VOP = -2, + MPEG4_INVALID_VOP = -1, + MPEG4_I_VOP = 0, + MPEG4_P_VOP = 1, + MPEG4_B_VOP = 2, + MPEG4_S_VOP = 3, + MPEG4_N_VOP = 4, + MPEG4_D_VOP = 5, /*Drop Frame*/ +} MPEG4VOPType; + +#define MPEG4_HDR_ERR -2 +#define MPEG4_DEC_ERR -4 +#define MPEG4_VLD_ERR -5 +#define MPEG4_FORMAT_ERR -6 +#define MPEG4_DIVX_PBBI -7 +#define MPEG4_INFO_CHANGE -10 + /* MPEG4PT2 Picture Parameter structure */ typedef struct _DXVA_PicParams_MPEG4_PART2 { RK_U8 short_video_header; @@ -81,37 +119,27 @@ typedef struct _DXVA_PicParams_MPEG4_PART2 { RK_U16 Reserved16BitsA; RK_U16 Reserved16BitsB; - // add by lance 2016.04.15 - RK_U32 consumed_bits; - RK_U32 buf_len; + // FIXME: added for rockchip hardware information + RK_U32 custorm_version; + RK_U32 prev_coding_type; RK_U32 time_bp; RK_U32 time_pp; - MppBuffer q_table_buffer; - RK_S32 quarterpel; - RK_U32 version; - RK_U32 intra_dc_threshold; + RK_U32 header_bits; } DXVA_PicParams_MPEG4_PART2, *LPDXVA_PicParams_MPEG4_PART2; typedef struct _DXVA_QmatrixData { - RK_U8 bNewQmatrix[4]; //intra Y, inter Y, intra chroma, inter chroma - RK_U16 Qmatrix[4][64]; + RK_U8 bNewQmatrix[4]; // intra Y, inter Y, intra chroma, inter chroma + RK_U8 Qmatrix[4][64]; // NOTE: here we change U16 to U8 } DXVA_QmatrixData, *LPDXVA_QmatrixData; -typedef struct _DXVA_SliceInfo { - RK_U16 wHorizontalPosition; - RK_U16 wVerticalPosition; - RK_U32 dwSliceBitsInBuffer; - RK_U32 dwSliceDataLocation; - RK_U8 bStartCodeBitOffset; - RK_U8 bReservedBits; - RK_U16 wMBbitOffset; - RK_U16 wNumberMBsInSlice; - RK_U16 wQuantizerScaleCode; - RK_U16 wBadSliceChopping; -} DXVA_SliceInfo, *LPDXVA_SliceInfo; - typedef struct mpeg4d_dxva2_picture_context { DXVA_PicParams_MPEG4_PART2 pp; + DXVA_QmatrixData qm; + + // pointer and storage for buffer descriptor + DXVA2_DecodeBufferDesc *data[3]; + DXVA2_DecodeBufferDesc desc[3]; + RK_U32 frame_count; const RK_U8 *bitstream; RK_U32 bitstream_size; diff --git a/mpp/hal/inc/hal_mpg4d_api.h b/mpp/hal/inc/hal_mpg4d_api.h index 346b3956..1bd9c38b 100644 --- a/mpp/hal/inc/hal_mpg4d_api.h +++ b/mpp/hal/inc/hal_mpg4d_api.h @@ -32,12 +32,15 @@ #include "mpp_err.h" #include "mpp_hal.h" - +#define MPG4D_HAL_DBG_REG_PUT (0x00000001) +#define MPG4D_HAL_DBG_REG_GET (0x00000002) #ifdef __cplusplus extern "C" { #endif +extern RK_U32 mpg4d_hal_debug; + extern const MppHalApi hal_api_mpg4d; MPP_RET hal_vpu_mpg4d_init(void *hal, MppHalCfg *cfg); diff --git a/mpp/hal/vpu/mpg4d/hal_mpg4d_reg.c b/mpp/hal/vpu/mpg4d/hal_mpg4d_reg.c index 9175b396..851de92b 100644 --- a/mpp/hal/vpu/mpg4d/hal_mpg4d_reg.c +++ b/mpp/hal/vpu/mpg4d/hal_mpg4d_reg.c @@ -1,19 +1,19 @@ /* - * * - * * Copyright 2016 Rockchip Electronics Co. LTD - * * - * * Licensed under the Apache License, Version 2.0 (the "License"); - * * you may not use this file except in compliance with the License. - * * You may obtain a copy of the License at - * * - * * http://www.apache.org/licenses/LICENSE-2.0 - * * - * * Unless required by applicable law or agreed to in writing, software - * * distributed under the License is distributed on an "AS IS" BASIS, - * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * * See the License for the specific language governing permissions and - * * limitations under the License. - * */ + * + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ /* * @file hal_vpu_mpg4d_reg.c @@ -36,34 +36,341 @@ #include "mpp_env.h" #include "mpp_buffer.h" +#include "vpu.h" #include "mpp_dec.h" #include "mpg4d_syntax.h" -#include "vpu.h" +#include "hal_mpg4d_api.h" +#include "hal_mpg4d_reg.h" + +#define MPEG4_MAX_MV_BUF_SIZE ((1920/16)*(1088/16)*sizeof(RK_U32)) typedef struct mpeg4d_reg_context { - RK_S32 vpu_fd; - MppBufSlots slots; - MppBufSlots packet_slots; - MppBufferGroup group; - MppBuffer directMV_Addr; - int addr_init_flag; - void* hw_regs; - IOInterruptCB int_cb; + RK_S32 mpg4d_fill_quantization_matrices; + MppBufSlots frm_slots; + MppBufSlots pkt_slots; + MppBufferGroup group; + IOInterruptCB int_cb; + + // save fd for curr/ref0/ref1 for reg_gen + RK_S32 vpu_fd; + RK_S32 fd_curr; + RK_S32 fd_ref0; + RK_S32 fd_ref1; + + // mv info buffer + // NOTE: mv buffer fix to 1080p size for convenience + MppBuffer mv_buf; + MppBuffer qp_table; + + VpuMpg4dRegSet_t* regs; } hal_mpg4_ctx; +RK_U32 mpg4d_hal_debug = 0; + +static RK_U8 default_intra_matrix[64] = { + 8, 17, 18, 19, 21, 23, 25, 27, + 17, 18, 19, 21, 23, 25, 27, 28, + 20, 21, 22, 23, 24, 26, 28, 30, + 21, 22, 23, 24, 26, 28, 30, 32, + 22, 23, 24, 26, 28, 30, 32, 35, + 23, 24, 26, 28, 30, 32, 35, 38, + 25, 26, 28, 30, 32, 35, 38, 41, + 27, 28, 30, 32, 35, 38, 41, 45 +}; + +static RK_U8 default_inter_matrix[64] = { + 16, 17, 18, 19, 20, 21, 22, 23, + 17, 18, 19, 20, 21, 22, 23, 24, + 18, 19, 20, 21, 22, 23, 24, 25, + 19, 20, 21, 22, 23, 24, 26, 27, + 20, 21, 22, 23, 25, 26, 27, 28, + 21, 22, 23, 24, 26, 27, 28, 30, + 22, 23, 24, 26, 27, 28, 30, 31, + 23, 24, 25, 27, 28, 30, 31, 33 +}; + +static void vpu_mpg4d_get_buffer_by_index(hal_mpg4_ctx *ctx, RK_S32 index, MppBuffer *buffer) +{ + if (index >= 0) { + mpp_buf_slot_get_prop(ctx->frm_slots, index, SLOT_BUFFER, buffer); + mpp_assert(*buffer); + } +} + +static void vpu_mpg4d_setup_regs_by_syntax(hal_mpg4_ctx *ctx, MppSyntax syntax) +{ + VpuMpg4dRegSet_t *regs = ctx->regs; + DXVA2_DecodeBufferDesc **data = syntax.data; + DXVA_PicParams_MPEG4_PART2 *pp = NULL; + DXVA_QmatrixData *qm = NULL; + RK_S32 mv_buf_fd = mpp_buffer_get_fd(ctx->mv_buf); + RK_U32 stream_length = 0; + RK_U32 stream_used = 0; + RK_U32 i; + + for (i = 0; i < syntax.number; i++) { + DXVA2_DecodeBufferDesc *desc = data[i]; + switch (desc->CompressedBufferType) { + case DXVA2_PictureParametersBufferType : { + pp = (DXVA_PicParams_MPEG4_PART2 *)desc->pvPVPState; + } break; + case DXVA2_InverseQuantizationMatrixBufferType : { + qm = (DXVA_QmatrixData *)desc->pvPVPState; + } break; + case DXVA2_BitStreamDateBufferType : { + stream_length = desc->DataSize; + stream_used = desc->DataOffset; + } break; + default : { + mpp_err_f("found invalid buffer descriptor type %d\n", desc->CompressedBufferType); + } break; + } + } + + mpp_assert(pp); + mpp_assert(qm); + mpp_assert(stream_length); + mpp_assert(stream_used); + + // copy qp table to buffer + { + RK_U8 *dst = (RK_U8 *)mpp_buffer_get_ptr(ctx->qp_table); + RK_U8 *src = (qm->bNewQmatrix[0]) ? (qm->Qmatrix[0]) : (default_intra_matrix); + + memcpy(dst, src, 64); + dst += 64; + + src = (qm->bNewQmatrix[1]) ? (qm->Qmatrix[1]) : (default_inter_matrix); + memcpy(dst, src, 64); + } + + regs->reg120.sw_pic_mb_width = (pp->vop_width + 15) >> 4; + regs->reg120.sw_pic_mb_hight_p = (pp->vop_height + 15) >> 4; + if (pp->custorm_version == 4) { + regs->reg120.sw_mb_width_off = pp->vop_width & 0xf; + regs->reg120.sw_mb_height_off = pp->vop_height & 0xf; + } else { + regs->reg120.sw_mb_width_off = 0; + regs->reg120.sw_mb_height_off = 0; + } + regs->reg53_dec_mode = 1; + regs->reg120.sw_alt_scan_e = pp->alternate_vertical_scan_flag; + regs->reg52_error_concealment.sw_startmb_x = 0; + regs->reg52_error_concealment.sw_startmb_y = 0; + regs->reg50_dec_ctrl.sw_filtering_dis = 1; + regs->reg136.sw_rounding = pp->vop_rounding_type; + regs->reg122.sw_intradc_vlc_thr = pp->intra_dc_vlc_thr; + regs->reg51_stream_info.sw_init_qp = pp->vop_quant; + regs->reg122.sw_sync_markers_en = 1; + + { + /* + * update stream base address here according to consumed bit length + * 1. hardware start address has to be 64 bit align + * 2. hardware need to know which is the start bit in + * 2. pass (10bit fd + (offset << 10)) register value to kernel + */ + RK_U32 val = regs->reg64_input_stream_base; + RK_U32 consumed_bytes = stream_used >> 3; + RK_U32 consumed_bytes_align = consumed_bytes & (~0x7); + RK_U32 start_bit_offset = stream_used & 0x3F; + RK_U32 left_bytes = stream_length - consumed_bytes_align; + + val += (consumed_bytes_align << 10); + regs->reg64_input_stream_base = val; + regs->reg122.sw_stream_start_word = start_bit_offset; + regs->reg51_stream_info.sw_stream_len = left_bytes; + } + regs->reg122.sw_vop_time_incr = pp->vop_time_increment_resolution; + + switch (pp->vop_coding_type) { + case MPEG4_B_VOP : { + RK_U32 time_bp = pp->time_bp; + RK_U32 time_pp = pp->time_pp; + + RK_U32 trb_per_trd_d0 = ((((RK_S64)(1 * time_bp + 0)) << 27) + 1 * (time_pp - 1)) / time_pp; + RK_U32 trb_per_trd_d1 = ((((RK_S64)(2 * time_bp + 1)) << 27) + 2 * (time_pp - 0)) / (2 * time_pp + 1); + RK_U32 trb_per_trd_dm1 = ((((RK_S64)(2 * time_bp - 1)) << 27) + 2 * (time_pp - 1)) / (2 * time_pp - 1); + + regs->reg57_enable_ctrl.sw_pic_b_e = 1; + regs->reg57_enable_ctrl.sw_pic_inter_e = 1; + regs->reg136.sw_rounding = 0; + regs->reg131_ref0_base = 1; + + mpp_assert(ctx->fd_ref1 >= 0); + if (ctx->fd_ref1 >= 0) { + regs->reg131_ref0_base = (RK_U32)ctx->fd_ref1; + regs->reg148_ref1_base = (RK_U32)ctx->fd_ref1; + } else { + regs->reg131_ref0_base = (RK_U32)ctx->fd_curr; + regs->reg148_ref1_base = (RK_U32)ctx->fd_curr; + } + + mpp_assert(ctx->fd_ref0 >= 0); + if (ctx->fd_ref0 >= 0) { + regs->reg134_ref2_base = (RK_U32)ctx->fd_ref0; + regs->reg135_ref3_base = (RK_U32)ctx->fd_ref0; + } else { + regs->reg134_ref2_base = (RK_U32)ctx->fd_curr; + regs->reg135_ref3_base = (RK_U32)ctx->fd_curr; + } + + regs->reg136.sw_hrz_bit_of_fwd_mv = pp->vop_fcode_forward; + regs->reg136.sw_vrz_bit_of_fwd_mv = pp->vop_fcode_forward; + regs->reg136.sw_hrz_bit_of_bwd_mv = pp->vop_fcode_backward; + regs->reg136.sw_vrz_bit_of_bwd_mv = pp->vop_fcode_backward; + regs->reg57_enable_ctrl.sw_write_mvs_e = 0; + regs->reg62_directmv_base = mv_buf_fd; + regs->reg137.sw_trb_per_trd_d0 = trb_per_trd_d0; + regs->reg139.sw_trb_per_trd_d1 = trb_per_trd_d1; + regs->reg138.sw_trb_per_trd_dm1 = trb_per_trd_dm1; + } break; + case MPEG4_P_VOP : { + regs->reg57_enable_ctrl.sw_pic_b_e = 0; + regs->reg57_enable_ctrl.sw_pic_inter_e = 1; + + if (ctx->fd_ref0 >= 0) { + regs->reg131_ref0_base = (RK_U32)ctx->fd_ref0; + regs->reg148_ref1_base = (RK_U32)ctx->fd_ref0; + } else { + regs->reg131_ref0_base = (RK_U32)ctx->fd_curr; + regs->reg148_ref1_base = (RK_U32)ctx->fd_curr; + } + + regs->reg136.sw_hrz_bit_of_fwd_mv = pp->vop_fcode_forward; + regs->reg136.sw_vrz_bit_of_fwd_mv = pp->vop_fcode_forward; + regs->reg57_enable_ctrl.sw_write_mvs_e = 1; + regs->reg62_directmv_base = mv_buf_fd; + } break; + case MPEG4_I_VOP : { + regs->reg57_enable_ctrl.sw_pic_b_e = 0; + regs->reg57_enable_ctrl.sw_pic_inter_e = 0; + + regs->reg131_ref0_base = (RK_U32)ctx->fd_curr; + regs->reg148_ref1_base = (RK_U32)ctx->fd_curr; + + regs->reg57_enable_ctrl.sw_write_mvs_e = 0; + regs->reg62_directmv_base = mv_buf_fd; + + regs->reg136.sw_hrz_bit_of_fwd_mv = 1; + regs->reg136.sw_vrz_bit_of_fwd_mv = 1; + } break; + default : { + /* no nothing */ + } break; + } + + if (pp->interlaced) { + regs->reg57_enable_ctrl.sw_pic_interlace_e = 1; + regs->reg57_enable_ctrl.sw_pic_fieldmode_e = 0; + regs->reg120.sw_topfieldfirst_e = pp->top_field_first; + } + + regs->reg136.sw_prev_pic_type = pp->prev_coding_type; + regs->reg122.sw_quant_type_1_en = pp->quant_type; + regs->reg61_qtable_base = mpp_buffer_get_fd(ctx->qp_table); + regs->reg136.sw_fwd_mv_y_resolution = pp->quarter_sample; + +} + MPP_RET hal_vpu_mpg4d_init(void *hal, MppHalCfg *cfg) { MPP_RET ret = MPP_OK; - hal_mpg4_ctx *reg_ctx = (hal_mpg4_ctx *)hal; + VpuMpg4dRegSet_t *regs = NULL; + MppBufferGroup group = NULL; + MppBuffer mv_buf = NULL; + MppBuffer qp_table = NULL; + hal_mpg4_ctx *ctx = (hal_mpg4_ctx *)hal; + RK_S32 vpu_fd = -1; - if (NULL == reg_ctx) { - mpp_err("hal instan no alloc"); - return MPP_ERR_UNKNOW; + mpp_assert(hal); + + + ret = mpp_buffer_group_get_internal(&group, MPP_BUFFER_TYPE_ION); + if (ret) { + mpp_err_f("failed to get buffer group ret %d\n", ret); + goto ERR_RET; } - reg_ctx->slots = cfg->frame_slots; - reg_ctx->int_cb = cfg->hal_int_cb; - reg_ctx->packet_slots = cfg->packet_slots; + ret = mpp_buffer_get(group, &mv_buf, MPEG4_MAX_MV_BUF_SIZE); + if (ret) { + mpp_err_f("failed to get mv buffer ret %d\n", ret); + goto ERR_RET; + } + + ret = mpp_buffer_get(group, &qp_table, 64 * 2 * sizeof(RK_U8)); + if (ret) { + mpp_err_f("failed to get qp talbe buffer ret %d\n", ret); + goto ERR_RET; + } + + regs = mpp_calloc(VpuMpg4dRegSet_t, 1); + if (NULL == regs) { + mpp_err_f("failed to malloc register ret\n"); + ret = MPP_ERR_MALLOC; + goto ERR_RET; + } + +#ifdef RKPLATFORM + vpu_fd = VPUClientInit(VPU_DEC); + if (vpu_fd < 0) { + mpp_err_f("failed to open vpu client\n"); + ret = MPP_ERR_UNKNOW; + goto ERR_RET; + } +#endif + + /* + * basic register configuration setup here + */ + regs->reg54_endian.sw_dec_out_endian = 1; + regs->reg54_endian.sw_dec_in_endian = 1; + regs->reg54_endian.sw_dec_inswap32_e = 1; + regs->reg54_endian.sw_dec_outswap32_e = 1; + regs->reg54_endian.sw_dec_strswap32_e = 1; + regs->reg54_endian.sw_dec_strendian_e = 1; + regs->reg56_axi_ctrl.sw_dec_max_burst = 16; + regs->reg52_error_concealment.sw_apf_threshold = 1; + regs->reg57_enable_ctrl.sw_dec_timeout_e = 1; + regs->reg57_enable_ctrl.sw_dec_clk_gate_e = 1; + regs->reg57_enable_ctrl.sw_dec_e = 1; + regs->reg59.sw_pred_bc_tap_0_0 = -1; + regs->reg59.sw_pred_bc_tap_0_1 = 3; + regs->reg59.sw_pred_bc_tap_0_2 = -6; + regs->reg153.sw_pred_bc_tap_0_3 = 20; + + ctx->frm_slots = cfg->frame_slots; + ctx->pkt_slots = cfg->packet_slots; + ctx->int_cb = cfg->hal_int_cb; + ctx->group = group; + ctx->vpu_fd = vpu_fd; + ctx->mv_buf = mv_buf; + ctx->qp_table = qp_table; + ctx->regs = regs; + + mpp_env_get_u32("mpg4d_hal_debug", &mpg4d_hal_debug, 0); + + return ret; +ERR_RET: + if (regs) { + mpp_free(regs); + regs = NULL; + } + + if (qp_table) { + mpp_buffer_put(qp_table); + qp_table = NULL; + } + + if (mv_buf) { + mpp_buffer_put(mv_buf); + mv_buf = NULL; + } + + if (group) { + mpp_buffer_group_put(group); + group = NULL; + } return ret; } @@ -71,7 +378,36 @@ MPP_RET hal_vpu_mpg4d_init(void *hal, MppHalCfg *cfg) MPP_RET hal_vpu_mpg4d_deinit(void *hal) { MPP_RET ret = MPP_OK; - (void) hal; + hal_mpg4_ctx *ctx = (hal_mpg4_ctx *)hal; + + mpp_assert(hal); + + if (ctx->regs) { + mpp_free(ctx->regs); + ctx->regs = NULL; + } + + if (ctx->qp_table) { + mpp_buffer_put(ctx->qp_table); + ctx->qp_table = NULL; + } + + if (ctx->mv_buf) { + mpp_buffer_put(ctx->mv_buf); + ctx->mv_buf = NULL; + } + + if (ctx->group) { + mpp_buffer_group_put(ctx->group); + ctx->group = NULL; + } + +#ifdef RKPLATFORM + if (ctx->vpu_fd >= 0) { + VPUClientRelease(ctx->vpu_fd); + ctx->vpu_fd = -1; + } +#endif return ret; } @@ -79,15 +415,57 @@ MPP_RET hal_vpu_mpg4d_deinit(void *hal) MPP_RET hal_vpu_mpg4d_gen_regs(void *hal, HalTaskInfo *syn) { MPP_RET ret = MPP_OK; - (void) hal; - (void) syn; + hal_mpg4_ctx *ctx = (hal_mpg4_ctx *)hal; + HalDecTask *task = &syn->dec; + MppBuffer buf_frm_curr = NULL; + MppBuffer buf_frm_ref0 = NULL; + MppBuffer buf_frm_ref1 = NULL; + MppBuffer buf_pkt = NULL; + VpuMpg4dRegSet_t *regs = ctx->regs; + + mpp_assert(task->valid); + mpp_assert(task->input >= 0); + mpp_assert(task->output >= 0); + + /* setup buffer for input / output / reference */ + mpp_buf_slot_get_prop(ctx->pkt_slots, task->input, SLOT_BUFFER, &buf_pkt); + mpp_assert(buf_pkt); + vpu_mpg4d_get_buffer_by_index(ctx, task->output, &buf_frm_curr); + vpu_mpg4d_get_buffer_by_index(ctx, task->refer[0], &buf_frm_ref0); + vpu_mpg4d_get_buffer_by_index(ctx, task->refer[1], &buf_frm_ref1); + + /* address registers setup first */ + ctx->fd_curr = mpp_buffer_get_fd(buf_frm_curr); + ctx->fd_ref0 = (buf_frm_ref0) ? (mpp_buffer_get_fd(buf_frm_ref0)) : (-1); + ctx->fd_ref1 = (buf_frm_ref1) ? (mpp_buffer_get_fd(buf_frm_ref1)) : (-1); + regs->reg63_cur_pic_base = (RK_U32)ctx->fd_curr; + regs->reg64_input_stream_base = mpp_buffer_get_fd(buf_pkt); + + /* setup other registers, here will update packet address */ + vpu_mpg4d_setup_regs_by_syntax(ctx, task->syntax); + return ret; } MPP_RET hal_vpu_mpg4d_start(void *hal, HalTaskInfo *task) { MPP_RET ret = MPP_OK; - (void)hal; + hal_mpg4_ctx *ctx = (hal_mpg4_ctx *)hal; + +#ifdef RKPLATFORM + RK_U32 reg_count = (sizeof(*ctx->regs) / sizeof(RK_U32)); + RK_U32* regs = (RK_U32 *)ctx->regs; + + if (mpg4d_hal_debug & MPG4D_HAL_DBG_REG_PUT) { + RK_U32 i = 0; + for (i = 0; i < reg_count; i++) { + mpp_log("reg[%03d]: %08x\n", i, regs[i]); + } + } + + ret = VPUClientSendReg(ctx->vpu_fd, regs, reg_count); +#endif + (void)ret; (void)task; return ret; } @@ -95,8 +473,27 @@ MPP_RET hal_vpu_mpg4d_start(void *hal, HalTaskInfo *task) MPP_RET hal_vpu_mpg4d_wait(void *hal, HalTaskInfo *task) { MPP_RET ret = MPP_OK; + hal_mpg4_ctx *ctx = (hal_mpg4_ctx *)hal; +#ifdef RKPLATFORM + VpuMpg4dRegSet_t reg_out; + RK_U32* regs = (RK_U32 *)®_out; + RK_U32 reg_count = (sizeof(reg_out) / sizeof(RK_U32)); + VPU_CMD_TYPE cmd = 0; + RK_S32 length = 0; + + ret = VPUClientWaitResult(ctx->vpu_fd, regs, (sizeof(reg_out) / sizeof(RK_U32)), + &cmd, &length); + + if (mpg4d_hal_debug & MPG4D_HAL_DBG_REG_GET) { + RK_U32 i = 0; + + for (i = 0; i < reg_count; i++) { + mpp_log("reg[%03d]: %08x\n", i, regs[i]); + } + } +#endif + (void)ret; (void)task; - (void) hal; return ret; } diff --git a/mpp/hal/vpu/mpg4d/hal_mpg4d_reg.h b/mpp/hal/vpu/mpg4d/hal_mpg4d_reg.h index e31d5790..d4861e78 100644 --- a/mpp/hal/vpu/mpg4d/hal_mpg4d_reg.h +++ b/mpp/hal/vpu/mpg4d/hal_mpg4d_reg.h @@ -1,35 +1,398 @@ /* - * * - * * Copyright 2016 Rockchip Electronics Co. LTD - * * - * * Licensed under the Apache License, Version 2.0 (the "License"); - * * you may not use this file except in compliance with the License. - * * You may obtain a copy of the License at - * * - * * http://www.apache.org/licenses/LICENSE-2.0 - * * - * * Unless required by applicable law or agreed to in writing, software - * * distributed under the License is distributed on an "AS IS" BASIS, - * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * * See the License for the specific language governing permissions and - * * limitations under the License. - * */ - -/* -* @file hal_mpeg4d_reg.h -* @brief -* @author gzl(lance.gao@rock-chips.com) - -* @version 1.0.0 -* @history -* 2016.04.11 : Create -*/ + * Copyright 2016 Rockchip Electronics Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #ifndef __HAL_MPG4D_REG_H__ #define __HAL_MPG4D_REG_H__ -#include "mpp_log.h" +#include "rk_type.h" +typedef struct { + RK_U32 reg00_49[50]; + + struct { + RK_U32 sw_dec_out_tiled_e : 1; + RK_U32 sw_dec_latency : 6; + RK_U32 sw_pic_fixed_quant : 1; + RK_U32 sw_filtering_dis : 1; + RK_U32 sw_divx_enable : 1; + RK_U32 sw_dec_scmd_dis : 1; + RK_U32 sw_dec_adv_pre_dis : 1; + RK_U32 sw_priority_mode : 1; + RK_U32 sw_refbu2_thr : 12; + RK_U32 sw_refbu2_picid : 5; + RK_U32 reserve1 : 2; + } reg50_dec_ctrl; + + struct { + RK_U32 sw_stream_len : 24; + RK_U32 reserve1 : 1; + RK_U32 sw_init_qp : 6; + RK_U32 reserve2 : 1; + } reg51_stream_info; + + struct { + RK_U32 sw_startmb_y : 8; + RK_U32 sw_startmb_x : 9; + RK_U32 sw_apf_threshold : 14; + RK_U32 sw_reserve : 1; + } reg52_error_concealment; + + RK_U32 reg53_dec_mode; + + struct { + RK_U32 sw_dec_in_endian : 1; + RK_U32 sw_dec_out_endian : 1; + RK_U32 sw_dec_inswap32_e : 1; + RK_U32 sw_dec_outswap32_e : 1; + RK_U32 sw_dec_strswap32_e : 1; + RK_U32 sw_dec_strendian_e : 1; + RK_U32 reserve3 : 26; + } reg54_endian; + + struct { + RK_U32 sw_dec_irq : 1; + RK_U32 sw_dec_irq_dis : 1; + RK_U32 reserve0 : 2; + RK_U32 sw_dec_rdy_int : 1; + RK_U32 sw_dec_bus_int : 1; + RK_U32 sw_dec_buf_empty_int: 1; + RK_U32 reserve1 : 1; + RK_U32 sw_dec_aso_int : 1; + RK_U32 sw_dec_slice_int : 1; + RK_U32 sw_dec_b_pic_inf : 1; + RK_U32 reserve2 : 1; + RK_U32 sw_dec_error_int : 1; + RK_U32 sw_dec_timeout : 1; + RK_U32 reserve3 : 18; + } reg55_Interrupt; + + struct { + RK_U32 sw_dec_axi_rn_id : 8; + RK_U32 sw_dec_axi_wr_id : 8; + RK_U32 sw_dec_max_burst : 5; + RK_U32 reserve0 : 1; + RK_U32 sw_dec_data_disc_e : 1; + RK_U32 reserve1 : 9; + } reg56_axi_ctrl; + + struct { + RK_U32 sw_dec_e : 1; + RK_U32 sw_refbu2_buf_e : 1; + RK_U32 sw_dec_out_dis : 1; + RK_U32 reserve : 1; + RK_U32 sw_dec_clk_gate_e : 1; + RK_U32 sw_dec_timeout_e : 1; + RK_U32 sw_picord_count_e : 1; + RK_U32 sw_seq_mbaff_e : 1; + RK_U32 sw_reftopfirst_e : 1; + RK_U32 sw_ref_topfield_e : 1; + RK_U32 sw_write_mvs_e : 1; + RK_U32 sw_sorenson_e : 1; + RK_U32 sw_fwd_interlace_e : 1; + RK_U32 sw_pic_topfield_e : 1; + RK_U32 sw_pic_inter_e : 1; + RK_U32 sw_pic_b_e : 1; + RK_U32 sw_pic_fieldmode_e : 1; + RK_U32 sw_pic_interlace_e : 1; + RK_U32 sw_pjpeg_e : 1; + RK_U32 sw_divx3_e : 1; + RK_U32 sw_rlc_mode_e : 1; + RK_U32 sw_ch_8pix_ileav_e : 1; + RK_U32 sw_start_code_e : 1; + RK_U32 reserve1 : 8; + RK_U32 sw_dec_ahb_hlock_e : 1; + } reg57_enable_ctrl; + + struct { + RK_U32 sw_soft_rst : 1; + RK_U32 reverse0 : 31; + } reg58; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_0_2 : 10; + RK_U32 sw_pred_bc_tap_0_1 : 10; + RK_U32 sw_pred_bc_tap_0_0 : 10; + } reg59; + + RK_U32 reg60_addit_ch_st_base; + RK_U32 reg61_qtable_base; + RK_U32 reg62_directmv_base; + RK_U32 reg63_cur_pic_base; + RK_U32 reg64_input_stream_base; + + struct { + RK_U32 sw_refbu_y_offset : 9; + RK_U32 sw_reserve : 3; + RK_U32 sw_refbu_fparmod_e : 1; + RK_U32 sw_refbu_eval_e : 1; + RK_U32 sw_refbu_picid : 5; + RK_U32 sw_refbu_thr : 12; + RK_U32 sw_refbu_e : 1; + } reg65_refpicbuf_ctrl; + + struct { + RK_U32 build_version : 3; + RK_U32 product_IDen : 1; + RK_U32 minor_version : 8; + RK_U32 major_version : 4; + RK_U32 product_numer : 16; + } reg66_id; + + struct { + RK_U32 sw_reserve : 25; + RK_U32 sw_dec_rtl_rom : 1; + RK_U32 sw_dec_rv_prof : 2; + RK_U32 sw_ref_buff2_exist : 1; + RK_U32 sw_dec_divx_prof : 1; + RK_U32 sw_dec_refbu_ilace : 1; + RK_U32 sw_dec_jpeg_exten : 1; + } reg67_synthesis_cfg; + + struct { + RK_U32 sw_refbu_top_sum : 16; + RK_U32 sw_refbu_bot_sum : 16; + } reg68_sum_of_partitions; + + struct { + RK_U32 sw_refbu_intra_sum : 16; + RK_U32 sw_refbu_hit_sum : 16; + } reg69_sum_inf; + + struct { + RK_U32 sw_refbu_mv_sum : 22; + RK_U32 sw_reserve : 10; + } reg70_sum_mv; + + RK_U32 reg71_119_reserve[49]; + + struct { + RK_U32 sw_reserve0 : 5; + RK_U32 sw_topfieldfirst_e : 1; + RK_U32 sw_alt_scan_e : 1; + RK_U32 sw_mb_height_off : 4; + RK_U32 sw_pic_mb_hight_p : 8; + RK_U32 sw_mb_width_off : 4; + RK_U32 sw_pic_mb_width : 9; + } reg120; + + struct { + RK_U32 sw_reserve : 5; + RK_U32 sw_vp7_version : 1; + RK_U32 sw_dc_match0 : 3; + RK_U32 sw_dc_match1 : 3; + RK_U32 sw_eable_bilinear : 1; + RK_U32 sw_remain_mv : 1; + RK_U32 sw_reserve1 : 6; + RK_U32 sw_dct2_start_bit : 6; + RK_U32 sw_dct1_start_bit : 6; + } reg121; + + struct { + RK_U32 sw_vop_time_incr : 16; + RK_U32 sw_intradc_vlc_thr : 3; + RK_U32 sw_ch_qp_offset : 5; + RK_U32 sw_quant_type_1_en : 1; + RK_U32 sw_sync_markers_en : 1; + RK_U32 sw_stream_start_word: 6; + } reg122; + + struct { + RK_U32 sw_dc_comp1 : 16; + RK_U32 sw_dc_comp0 : 16; + } reg123; + + struct { + RK_U32 sw_stream1_len : 24; + RK_U32 sw_coeffs_part_am : 4; + RK_U32 sw_reserve : 4; + } reg124; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_5_3 : 10; + RK_U32 sw_pred_bc_tap_5_2 : 10; + RK_U32 sw_pred_bc_tap_5_1 : 10; + } reg125; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_6_2 : 10; + RK_U32 sw_pred_bc_tap_6_1 : 10; + RK_U32 sw_pred_bc_tap_6_0 : 10; + } reg126; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_7_1 : 10; + RK_U32 sw_pred_bc_tap_7_0 : 10; + RK_U32 sw_pred_bc_tap_6_3 : 10; + } reg127; + + struct { + RK_U32 sw_pred_tap_6_4 : 2; + RK_U32 sw_pred_tap_6_M1 : 2; + RK_U32 sw_pred_tap_4_4 : 2; + RK_U32 sw_pred_tap_4_M1 : 2; + RK_U32 sw_pred_tap_2_4 : 2; + RK_U32 sw_pred_tap_2_M1 : 2; + RK_U32 sw_pred_bc_tap_7_3 : 10; + RK_U32 sw_pred_bc_tap_7_2 : 10; + } reg128; + + struct { + RK_U32 sw_filt_level_3 : 6; + RK_U32 sw_filt_level_2 : 6; + RK_U32 sw_filt_level_1 : 6; + RK_U32 sw_filt_level_0 : 6; + RK_U32 reserve : 8; + } reg129; + + struct { + RK_U32 sw_quant_1 : 11; + RK_U32 sw_quant_0 : 11; + RK_U32 sw_quant_delta_1 : 5; + RK_U32 sw_quant_delta_0 : 5; + } reg130; + + + RK_U32 reg131_ref0_base; + + struct { + RK_U32 sw_filt_mb_adj_3 : 7; + RK_U32 sw_filt_mb_adj_2 : 7; + RK_U32 sw_filt_mb_adj_1 : 7; + RK_U32 sw_filt_mb_adj_0 : 7; + RK_U32 sw_filt_sharpness : 3; + RK_U32 sw_filt_type : 1; + } reg132; + + + struct { + RK_U32 sw_filt_ref_adj_3 : 7; + RK_U32 sw_filt_ref_adj_2 : 7; + RK_U32 sw_filt_ref_adj_1 : 7; + RK_U32 sw_filt_ref_adj_0 : 7; + RK_U32 sw_reserve : 4; + } reg133; + + RK_U32 reg134_ref2_base; + RK_U32 reg135_ref3_base; + + struct { + RK_U32 sw_prev_pic_type : 1; + RK_U32 sw_rounding : 1; + RK_U32 sw_fwd_mv_y_resolution : 1; + RK_U32 sw_vrz_bit_of_bwd_mv : 4; + RK_U32 sw_hrz_bit_of_bwd_mv : 4; + RK_U32 sw_vrz_bit_of_fwd_mv : 4; + RK_U32 sw_hrz_bit_of_fwd_mv : 4; + RK_U32 sw_alt_scan : 1; + RK_U32 sw_reserve : 12; + } reg136; + + struct { + RK_U32 sw_trb_per_trd_d0 : 27; + RK_U32 sw_reserve : 5; + } reg137; + + struct { + RK_U32 sw_trb_per_trd_dm1 : 27; + RK_U32 sw_reserve : 5; + } reg138; + + struct { + RK_U32 sw_trb_per_trd_d1 : 27; + RK_U32 sw_reserve : 5; + } reg139; + + RK_U32 reg_dct_strm_base[5]; + RK_U32 reg145_bitpl_ctrl_base; + RK_U32 reg_dct_strm1_base[2]; + + RK_U32 reg148_ref1_base; + + RK_U32 reg149_segment_map_base; + + + struct { + RK_U32 sw_dct_start_bit_7 : 6; + RK_U32 sw_dct_start_bit_6 : 6; + RK_U32 sw_dct_start_bit_5 : 6; + RK_U32 sw_dct_start_bit_4 : 6; + RK_U32 sw_dct_start_bit_3 : 6; + RK_U32 sw_reserve : 2; + } reg150; + + struct { + RK_U32 sw_quant_3 : 11; + RK_U32 sw_quant_2 : 11; + RK_U32 sw_quant_delta_3 : 5; + RK_U32 sw_quant_delta_2 : 5; + } reg151; + + struct { + RK_U32 sw_quant_5 : 11; + RK_U32 sw_quant_4 : 11; + RK_U32 sw_quant_delta_4 : 5; + RK_U32 sw_reserve : 5; + } reg152; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_1_1 : 10; + RK_U32 sw_pred_bc_tap_1_0 : 10; + RK_U32 sw_pred_bc_tap_0_3 : 10; + } reg153; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_2_0 : 10; + RK_U32 sw_pred_bc_tap_1_3 : 10; + RK_U32 sw_pred_bc_tap_1_2 : 10; + } reg154; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_2_3 : 10; + RK_U32 sw_pred_bc_tap_2_2 : 10; + RK_U32 sw_pred_bc_tap_2_1 : 10; + } reg155; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_3_2 : 10; + RK_U32 sw_pred_bc_tap_3_1 : 10; + RK_U32 sw_pred_bc_tap_3_0 : 10; + } reg156; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_4_1 : 10; + RK_U32 sw_pred_bc_tap_4_0 : 10; + RK_U32 sw_pred_bc_tap_3_3 : 10; + } reg157; + + struct { + RK_U32 reserve : 2; + RK_U32 sw_pred_bc_tap_5_0 : 10; + RK_U32 sw_pred_bc_tap_4_3 : 10; + RK_U32 sw_pred_bc_tap_4_2 : 10; + } reg158; +} VpuMpg4dRegSet_t; #endif diff --git a/mpp/legacy/vpu_api_legacy.cpp b/mpp/legacy/vpu_api_legacy.cpp index 5af3cea2..5c10e90d 100644 --- a/mpp/legacy/vpu_api_legacy.cpp +++ b/mpp/legacy/vpu_api_legacy.cpp @@ -354,7 +354,7 @@ RK_S32 VpuApi::control(VpuCodecContext *ctx, VPU_API_CMD cmd, void *param) break; } case VPU_API_USE_PRESENT_TIME_ORDER: { - mpicmd = MPP_DEC_USE_PRESENT_TIME_ORDER; + mpicmd = MPP_DEC_SET_INTERNAL_PTS_ENABLE; break; } case VPU_API_SET_DEFAULT_WIDTH_HEIGH: { diff --git a/mpp/mpp.cpp b/mpp/mpp.cpp index 2734eee8..667a929a 100644 --- a/mpp/mpp.cpp +++ b/mpp/mpp.cpp @@ -300,9 +300,14 @@ MPP_RET Mpp::control(MpiCmd cmd, MppParam param) mpp_dec_control(mDec, cmd, param); break; } - case MPP_DEC_USE_PRESENT_TIME_ORDER: { - RK_U32 flag = *((RK_U32 *)param); - mParserInternalPts = flag; + case MPP_DEC_SET_INTERNAL_PTS_ENABLE: { + if (mType == MPP_CTX_DEC && + (mCoding == MPP_VIDEO_CodingMPEG2 || + mCoding == MPP_VIDEO_CodingMPEG4)) { + mpp_dec_control(mDec, cmd, param); + } else { + mpp_err("type %x coding %x does not support use internal pts control\n"); + } break; } case MPP_DEC_SET_PARSER_SPLIT_MODE: { @@ -328,8 +333,6 @@ MPP_RET Mpp::control(MpiCmd cmd, MppParam param) } break; } - - default : { } break; }