Files
mpp/mpp/codec/dec/mpg4/mpg4d_parser.c
2016-07-01 09:54:42 +00:00

1488 lines
51 KiB
C

/*
*
* Copyright 2010 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.
*/
#include <string.h>
#include "mpp_env.h"
#include "mpp_log.h"
#include "mpp_mem.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 {
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
// 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);
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->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;
}
MPP_RET mpp_mpg4_parser_deinit(Mpg4dParser ctx)
{
Mpg4dParserImpl *p = (Mpg4dParserImpl *)ctx;
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;
}
MPP_RET mpp_mpg4_parser_flush(Mpg4dParser ctx)
{
(void)ctx;
return MPP_OK;
}
MPP_RET mpp_mpg4_parser_reset(Mpg4dParser ctx)
{
(void)ctx;
return MPP_OK;
}
MPP_RET mpp_mpg4_parser_split(Mpg4dParser ctx, MppPacket dst, MppPacket src)
{
MPP_RET ret = MPP_NOK;
Mpg4dParserImpl *p = (Mpg4dParserImpl *)ctx;
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);
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;
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 == MPG4_VOP_STARTCODE) {
src_pos++;
pos_frm_start = src_pos - 4;
break;
}
}
}
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 & 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);
// update dst buffer length
mpp_packet_set_length(dst, dst_len + src_len);
// set src buffer pos to end to src buffer
mpp_packet_set_pos(src, src_buf + src_len);
} else {
// 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;
pos_frm_end = -1;
}
p->pos_frm_start = pos_frm_start;
p->pos_frm_end = pos_frm_end;
return ret;
}
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;
// 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->eos = mpp_packet_get_eos(pkt);
return ret;
}
MPP_RET mpp_mpg4_parser_setup_syntax(Mpg4dParser ctx, MppSyntax *syntax)
{
Mpg4dParserImpl *p = (Mpg4dParserImpl *)ctx;
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;
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;
}
p->output = index;
*output = index;
return MPP_OK;
}
MPP_RET mpp_mpg4_parser_setup_refer(Mpg4dParser ctx, RK_S32 *refer, RK_S32 max_ref)
{
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_update_dpb(Mpg4dParser ctx)
{
Mpg4dParserImpl *p = (Mpg4dParserImpl *)ctx;
MppBufSlots slots = p->frame_slots;
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);
}
/*
* NOTE: here fallback to N vop - do nothing
*/
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;
}