/*
|
*
|
* 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 <string.h>
|
|
#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,
|
};
|