/* * * Copyright 2015 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. */ #define MODULE_TAG "dummy_dec_api" #include #include "mpp_mem.h" #include "mpp_debug.h" #include "mpp_common.h" #include "dummy_dec_api.h" #define DUMMY_DEC_FRAME_WIDTH 1280 #define DUMMY_DEC_FRAME_HEIGHT 720 #define DUMMY_DEC_FRAME_NEW_WIDTH 1920 #define DUMMY_DEC_FRAME_NEW_HEIGHT 1088 #define DUMMY_DEC_FRAME_SIZE SZ_1M #define DUMMY_DEC_FRAME_COUNT 16 #define DUMMY_DEC_REF_COUNT 2 typedef struct DummyDec_t { MppBufSlots frame_slots; MppBufSlots packet_slots; RK_S32 task_count; void *stream; size_t stream_size; MppPacket task_pkt; RK_S64 task_pts; RK_U32 task_eos; RK_U32 slots_inited; RK_U32 frame_count; RK_S32 prev_index; RK_S32 slot_index[DUMMY_DEC_REF_COUNT]; } DummyDec; MPP_RET dummy_dec_init(void *dec, ParserCfg *cfg) { DummyDec *p; RK_S32 i; void *stream; size_t stream_size = SZ_512K; MppPacket task_pkt; if (NULL == dec) { mpp_err_f("found NULL intput dec %p cfg %p\n", dec, cfg); return MPP_ERR_NULL_PTR; } stream = mpp_malloc_size(void, stream_size); if (NULL == stream) { mpp_err_f("failed to malloc stream buffer size %d\n", stream_size); return MPP_ERR_MALLOC; } mpp_packet_init(&task_pkt, stream, stream_size); if (NULL == task_pkt) { mpp_err_f("failed to create mpp_packet for task\n"); return MPP_ERR_UNKNOW; } p = (DummyDec *)dec; p->frame_slots = cfg->frame_slots; p->packet_slots = cfg->packet_slots; p->task_count = 2; p->stream = stream; p->stream_size = stream_size; p->task_pkt = task_pkt; for (i = 0; i < DUMMY_DEC_REF_COUNT; i++) { p->slot_index[i] = -1; } return MPP_OK; } MPP_RET dummy_dec_deinit(void *dec) { DummyDec *p; if (NULL == dec) { mpp_err_f("found NULL intput\n"); return MPP_ERR_NULL_PTR; } p = (DummyDec *)dec; if (p->task_pkt) mpp_packet_deinit(&p->task_pkt); if (p->stream) mpp_free(p->stream); return MPP_OK; } MPP_RET dummy_dec_reset(void *dec) { if (NULL == dec) { mpp_err_f("found NULL intput\n"); return MPP_ERR_NULL_PTR; } return MPP_OK; } MPP_RET dummy_dec_flush(void *dec) { if (NULL == dec) { mpp_err_f("found NULL intput\n"); return MPP_ERR_NULL_PTR; } return MPP_OK; } MPP_RET dummy_dec_control(void *dec, MpiCmd cmd_type, void *param) { if (NULL == dec) { mpp_err_f("found NULL intput\n"); return MPP_ERR_NULL_PTR; } (void)cmd_type; (void)param; return MPP_OK; } MPP_RET dummy_dec_prepare(void *dec, MppPacket pkt, HalDecTask *task) { DummyDec *p; RK_U8 *data; size_t length; if (NULL == dec) { mpp_err_f("found NULL intput\n"); return MPP_ERR_NULL_PTR; } p = (DummyDec *)dec; /********************************************************************* * do packet prepare here * including connet nals into a big buffer, setup packet for task copy * pts/eos record *********************************************************************/ p->task_pts = mpp_packet_get_pts(pkt); p->task_eos = mpp_packet_get_eos(pkt); // set pos to indicate that buffer is done data = mpp_packet_get_data(pkt); length = mpp_packet_get_length(pkt); if (length > p->stream_size) { p->stream = mpp_realloc(p->stream, RK_U8, length); mpp_packet_set_data(p->task_pkt, p->stream); p->stream_size = length; } if (p->stream) { memcpy(p->stream, data, length); mpp_packet_set_length(p->task_pkt, length); } else { mpp_err("failed to found task buffer for hardware\n"); return MPP_ERR_UNKNOW; } mpp_packet_set_pos(pkt, data + length); /* * this step will enable the task and goto parse stage */ task->input_packet = p->task_pkt; task->flags.eos = p->task_eos; task->valid = 1; return MPP_OK; } MPP_RET dummy_dec_parse(void *dec, HalDecTask *task) { DummyDec *p; RK_S32 output; MppFrame frame = NULL; RK_U32 frame_count; MppBufSlots slots; RK_S32 i; RK_U32 width, height; if (NULL == dec) { mpp_err_f("found NULL intput\n"); return MPP_ERR_NULL_PTR; } p = (DummyDec *)dec; slots = p->frame_slots; frame_count = p->frame_count; width = DUMMY_DEC_FRAME_WIDTH; height = DUMMY_DEC_FRAME_HEIGHT; mpp_frame_init(&frame); if (!p->slots_inited) { mpp_buf_slot_setup(slots, DUMMY_DEC_FRAME_COUNT); p->slots_inited = 1; } else if (frame_count >= 2) { // do info change test width = DUMMY_DEC_FRAME_NEW_WIDTH; height = DUMMY_DEC_FRAME_NEW_HEIGHT; } mpp_frame_set_width(frame, width); mpp_frame_set_height(frame, height); mpp_frame_set_hor_stride(frame, MPP_ALIGN(width, 16)); mpp_frame_set_ver_stride(frame, MPP_ALIGN(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, &output); mpp_buf_slot_set_flag(slots, output, SLOT_HAL_OUTPUT); task->output = output; mpp_frame_set_pts(frame, p->task_pts); mpp_buf_slot_set_prop(slots, output, SLOT_FRAME, frame); mpp_frame_deinit(&frame); mpp_assert(NULL == frame); /* * 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 */ memset(&task->refer, -1, sizeof(task->refer)); for (i = 0; i < DUMMY_DEC_REF_COUNT; i++) { RK_S32 index = p->slot_index[i]; if (index >= 0) { task->refer[i] = index; mpp_buf_slot_set_flag(slots, index, SLOT_HAL_INPUT); mpp_buf_slot_set_flag(slots, index, SLOT_CODEC_USE); } } /* * update dpb status assuming that hw has decoded the frame */ mpp_buf_slot_set_flag(slots, output, SLOT_QUEUE_USE); mpp_buf_slot_enqueue(slots, output, QUEUE_DISPLAY); // add new reference buffer if (p->task_eos) { for (i = 0; i < DUMMY_DEC_REF_COUNT; i++) { mpp_buf_slot_clr_flag(slots, p->slot_index[i], SLOT_CODEC_USE); p->slot_index[i] = -1; } } else { // clear unreference buffer RK_U32 replace_index = frame_count & 1; if (p->slot_index[replace_index] >= 0) mpp_buf_slot_clr_flag(slots, p->slot_index[replace_index], SLOT_CODEC_USE); p->slot_index[replace_index] = output; mpp_buf_slot_set_flag(slots, output, SLOT_CODEC_USE); } p->frame_count = ++frame_count; return MPP_OK; } MPP_RET dummy_dec_callback(void *dec, void *err_info) { (void)dec; (void)err_info; return MPP_OK; } const ParserApi dummy_dec_parser = { .name = "dummy_dec_parser", .coding = MPP_VIDEO_CodingUnused, .ctx_size = sizeof(DummyDec), .flag = 0, .init = dummy_dec_init, .deinit = dummy_dec_deinit, .prepare = dummy_dec_prepare, .parse = dummy_dec_parse, .reset = dummy_dec_reset, .flush = dummy_dec_flush, .control = dummy_dec_control, .callback = dummy_dec_callback, };