diff --git a/mpp/codec/dec/mpg4/mpg4d_api.c b/mpp/codec/dec/mpg4/mpg4d_api.c index 59f5c122..ca032171 100644 --- a/mpp/codec/dec/mpg4/mpg4d_api.c +++ b/mpp/codec/dec/mpg4/mpg4d_api.c @@ -37,6 +37,7 @@ typedef struct { RK_S32 task_count; RK_U8 *stream; size_t stream_size; + size_t left_length; MppPacket task_pkt; RK_S64 task_pts; RK_U32 task_eos; @@ -99,7 +100,7 @@ MPP_RET mpg4d_init(void *dec, ParserCfg *cfg) p->stream_size = stream_size; p->task_pkt = task_pkt; p->parser = parser; - + p->left_length = 0; return MPP_OK; ERR_RET: if (task_pkt) { @@ -145,6 +146,7 @@ MPP_RET mpg4d_reset(void *dec) } Mpg4dCtx *p = (Mpg4dCtx *)dec; + p->left_length = 0; return mpp_mpg4_parser_reset(p->parser); } @@ -209,6 +211,33 @@ MPP_RET mpg4d_prepare(void *dec, MppPacket pkt, HalDecTask *task) mpp_err("failed to malloc task buffer for hardware with size %d\n", length); return MPP_ERR_UNKNOW; } + mpp_packet_set_length(p->task_pkt, p->left_length); + + /* + * Check have enough buffer to store stream + * NOTE: total length is the left size plus the new incoming + * packet length. + */ + size_t total_length = MPP_ALIGN(p->left_length + length, 16) + 64; // add extra 64 bytes in tails + + if (total_length > p->stream_size) { + RK_U8 *dst; + + do { + p->stream_size <<= 1; + } while (length > p->stream_size); + + dst = mpp_malloc_size(RK_U8, p->stream_size); + mpp_assert(dst); + // NOTE: copy remaining stream to new buffer + if (p->left_length > 0) { + memcpy(dst, p->stream, p->left_length); + } + mpp_free(p->stream); + p->stream = dst; + mpp_packet_set_data(p->task_pkt, p->stream); + mpp_packet_set_size(p->task_pkt, p->stream_size); + } if (!p->need_split) { /* @@ -216,19 +245,6 @@ MPP_RET mpg4d_prepare(void *dec, MppPacket pkt, HalDecTask *task) * Decoder's user will insure each packet is one frame for process * Parser will just copy packet to the beginning of stream buffer */ - if (length > p->stream_size) { - // NOTE: here we double the buffer length to reduce frequency of realloc - do { - p->stream_size <<= 1; - } while (length > p->stream_size); - - mpp_free(p->stream); - p->stream = mpp_malloc_size(RK_U8, p->stream_size); - mpp_assert(p->stream); - mpp_packet_set_data(p->task_pkt, p->stream); - mpp_packet_set_size(p->task_pkt, p->stream_size); - } - memcpy(p->stream, pos, length); mpp_packet_set_pos(p->task_pkt, p->stream); mpp_packet_set_length(p->task_pkt, length); @@ -246,32 +262,12 @@ MPP_RET mpg4d_prepare(void *dec, MppPacket pkt, HalDecTask *task) * Input packet can be any length and no need to be bound of on frame * Parser will do split frame operation to find the beginning and end of one frame */ - /* - * NOTE: on split mode total length is the left size plus the new incoming - * packet length. - */ - size_t remain_length = mpp_packet_get_length(p->task_pkt); - size_t total_length = remain_length + length; - if (total_length > p->stream_size) { - RK_U8 *dst; - do { - p->stream_size <<= 1; - } while (length > p->stream_size); - - // NOTE; split mode need to copy remaining stream to new buffer - dst = mpp_malloc_size(RK_U8, p->stream_size); - mpp_assert(dst); - - memcpy(dst, p->stream, remain_length); - mpp_free(p->stream); - p->stream = dst; - mpp_packet_set_data(p->task_pkt, p->stream); - mpp_packet_set_size(p->task_pkt, p->stream_size); - } - - // start parser split if (MPP_OK == mpp_mpg4_parser_split(p->parser, p->task_pkt, pkt)) { + p->left_length = 0; task->valid = 1; + } else { + task->valid = 0; + p->left_length = mpp_packet_get_length(p->task_pkt); } p->task_pts = mpp_packet_get_pts(p->task_pkt); p->task_eos = mpp_packet_get_eos(p->task_pkt); @@ -300,6 +296,7 @@ MPP_RET mpg4d_parse(void *dec, HalDecTask *task) task->valid = 0; task->output = -1; mpp_packet_set_length(task->input_packet, 0); + return MPP_NOK; } diff --git a/mpp/codec/dec/mpg4/mpg4d_parser.c b/mpp/codec/dec/mpg4/mpg4d_parser.c index 33668046..5bc2a03b 100644 --- a/mpp/codec/dec/mpg4/mpg4d_parser.c +++ b/mpp/codec/dec/mpg4/mpg4d_parser.c @@ -23,6 +23,7 @@ #include "mpp_log.h" #include "mpp_mem.h" #include "mpp_packet.h" +#include "mpp_common.h" #include "mpp_bitread.h" #include "mpg4d_parser.h" @@ -171,8 +172,8 @@ typedef struct { 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_U32 state; + RK_U32 vop_header_found; // flag: visual object plane header found // bit read context BitReadCtx_t *bit_ctx; @@ -180,7 +181,6 @@ typedef struct { 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 @@ -1074,8 +1074,8 @@ MPP_RET mpp_mpg4_parser_init(Mpg4dParser *ctx, MppBufSlots frame_slots) 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->state = -1; + p->vop_header_found = 0; p->bit_ctx = bit_ctx; init_mpg4_header(&p->hdr_curr); init_mpg4_header(&p->hdr_ref0); @@ -1160,8 +1160,10 @@ MPP_RET mpp_mpg4_parser_reset(Mpg4dParser ctx) hdr_ref1->slot_idx = -1; } - p->found_i_vop = 0; - p->found_vop = 0; + p->found_i_vop = 0; + p->found_vop = 0; + p->state = -1; + p->vop_header_found = 0; mpg4d_dbg_func("out\n"); @@ -1172,84 +1174,54 @@ 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_U8 *src_buf = (RK_U8 *)mpp_packet_get_pos(src); + RK_U32 src_len = (RK_U32)mpp_packet_get_length(src); RK_U32 src_eos = mpp_packet_get_eos(src); - RK_S32 src_pos = 0; - RK_U32 state = (RK_U32) - 1; + RK_U8 *dst_buf = (RK_U8 *)mpp_packet_get_data(dst); + RK_U32 dst_len = (RK_U32)mpp_packet_get_length(dst); + RK_U32 src_pos = 0; mpg4d_dbg_func("in\n"); - 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; + // find the began of the vop + if (!p->vop_header_found) { + // add last startcode to the new frame data + if ((dst_len < sizeof(p->state)) + && ((p->state & 0x00FFFFFF) == 0x000001)) { + dst_buf[0] = 0; + dst_buf[1] = 0; + dst_buf[2] = 1; + dst_len = 3; + } + while (src_pos < src_len) { + p->state = (p->state << 8) | src_buf[src_pos]; + dst_buf[dst_len++] = src_buf[src_pos++]; + if (p->state == MPG4_VOP_STARTCODE) { + p->vop_header_found = 1; 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; + // find the end of the vop + if (p->vop_header_found) { + while (src_pos < src_len) { + p->state = (p->state << 8) | src_buf[src_pos]; + dst_buf[dst_len++] = src_buf[src_pos++]; + if ((p->state & 0x00FFFFFF) == 0x000001) { + dst_len -= 3; + p->vop_header_found = 0; + ret = MPP_OK; // split complete 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; + // the last packet + if (src_eos && src_pos >= src_len) { + mpp_packet_set_eos(dst); } - - p->pos_frm_start = pos_frm_start; - p->pos_frm_end = pos_frm_end; + // reset the src and dst + mpp_packet_set_length(dst, dst_len); + mpp_packet_set_pos(src, src_buf + src_pos); mpg4d_dbg_func("out\n"); diff --git a/mpp/hal/vpu/mpg4d/hal_mpg4d_reg.c b/mpp/hal/vpu/mpg4d/hal_mpg4d_reg.c index 8d070ecd..f692c840 100644 --- a/mpp/hal/vpu/mpg4d/hal_mpg4d_reg.c +++ b/mpp/hal/vpu/mpg4d/hal_mpg4d_reg.c @@ -25,6 +25,7 @@ #include "mpp_mem.h" #include "mpp_env.h" #include "mpp_buffer.h" +#include "mpp_common.h" #include "mpp_device.h" #include "mpp_dec.h" @@ -45,7 +46,7 @@ typedef struct mpeg4d_reg_context { RK_S32 fd_curr; RK_S32 fd_ref0; RK_S32 fd_ref1; - + RK_U32 bitstrm_len; // mv info buffer // NOTE: mv buffer fix to 1080p size for convenience MppBuffer mv_buf; @@ -109,6 +110,7 @@ static void vpu_mpg4d_setup_regs_by_syntax(hal_mpg4_ctx *ctx, MppSyntax syntax) case DXVA2_BitStreamDateBufferType : { stream_length = desc->DataSize; stream_used = desc->DataOffset; + ctx->bitstrm_len = stream_length; } break; default : { mpp_err_f("found invalid buffer descriptor type %d\n", desc->CompressedBufferType); @@ -442,6 +444,12 @@ MPP_RET hal_vpu_mpg4d_gen_regs(void *hal, HalTaskInfo *syn) /* setup other registers, here will update packet address */ vpu_mpg4d_setup_regs_by_syntax(ctx, task->syntax); + /* memset tails to zero for stream buffer */ + { + RK_U8 *ptr = (RK_U8 *)mpp_buffer_get_ptr(buf_pkt); + RK_U32 strm_len = MPP_ALIGN(ctx->bitstrm_len, 16) + 64; + memset(ptr + ctx->bitstrm_len, 0, strm_len - ctx->bitstrm_len); + } return ret; }