1*437bfbebSnyanmisaka /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2*437bfbebSnyanmisaka /*
3*437bfbebSnyanmisaka * Copyright (c) 2015 Rockchip Electronics Co., Ltd.
4*437bfbebSnyanmisaka */
5*437bfbebSnyanmisaka
6*437bfbebSnyanmisaka #if defined(_WIN32)
7*437bfbebSnyanmisaka #include "vld.h"
8*437bfbebSnyanmisaka #endif
9*437bfbebSnyanmisaka
10*437bfbebSnyanmisaka #define MODULE_TAG "mpi_dec_test"
11*437bfbebSnyanmisaka
12*437bfbebSnyanmisaka #include <string.h>
13*437bfbebSnyanmisaka #include "rk_mpi.h"
14*437bfbebSnyanmisaka
15*437bfbebSnyanmisaka #include "mpp_mem.h"
16*437bfbebSnyanmisaka #include "mpp_env.h"
17*437bfbebSnyanmisaka #include "mpp_time.h"
18*437bfbebSnyanmisaka #include "mpp_common.h"
19*437bfbebSnyanmisaka #include "mpi_dec_utils.h"
20*437bfbebSnyanmisaka
21*437bfbebSnyanmisaka typedef struct {
22*437bfbebSnyanmisaka MpiDecTestCmd *cmd;
23*437bfbebSnyanmisaka MppCtx ctx;
24*437bfbebSnyanmisaka MppApi *mpi;
25*437bfbebSnyanmisaka RK_U32 quiet;
26*437bfbebSnyanmisaka
27*437bfbebSnyanmisaka /* end of stream flag when set quit the loop */
28*437bfbebSnyanmisaka RK_U32 loop_end;
29*437bfbebSnyanmisaka
30*437bfbebSnyanmisaka /* input and output */
31*437bfbebSnyanmisaka DecBufMgr buf_mgr;
32*437bfbebSnyanmisaka MppBufferGroup frm_grp;
33*437bfbebSnyanmisaka MppPacket packet;
34*437bfbebSnyanmisaka MppFrame frame;
35*437bfbebSnyanmisaka
36*437bfbebSnyanmisaka FILE *fp_output;
37*437bfbebSnyanmisaka RK_S32 frame_count;
38*437bfbebSnyanmisaka RK_S32 frame_num;
39*437bfbebSnyanmisaka
40*437bfbebSnyanmisaka RK_S64 first_pkt;
41*437bfbebSnyanmisaka RK_S64 first_frm;
42*437bfbebSnyanmisaka
43*437bfbebSnyanmisaka size_t max_usage;
44*437bfbebSnyanmisaka float frame_rate;
45*437bfbebSnyanmisaka RK_S64 elapsed_time;
46*437bfbebSnyanmisaka RK_S64 delay;
47*437bfbebSnyanmisaka FILE *fp_verify;
48*437bfbebSnyanmisaka FrmCrc checkcrc;
49*437bfbebSnyanmisaka } MpiDecLoopData;
50*437bfbebSnyanmisaka
dec_simple(MpiDecLoopData * data)51*437bfbebSnyanmisaka static int dec_simple(MpiDecLoopData *data)
52*437bfbebSnyanmisaka {
53*437bfbebSnyanmisaka RK_U32 pkt_done = 0;
54*437bfbebSnyanmisaka RK_U32 pkt_eos = 0;
55*437bfbebSnyanmisaka MPP_RET ret = MPP_OK;
56*437bfbebSnyanmisaka MpiDecTestCmd *cmd = data->cmd;
57*437bfbebSnyanmisaka MppCtx ctx = data->ctx;
58*437bfbebSnyanmisaka MppApi *mpi = data->mpi;
59*437bfbebSnyanmisaka MppPacket packet = data->packet;
60*437bfbebSnyanmisaka FileBufSlot *slot = NULL;
61*437bfbebSnyanmisaka RK_U32 quiet = data->quiet;
62*437bfbebSnyanmisaka FrmCrc *checkcrc = &data->checkcrc;
63*437bfbebSnyanmisaka
64*437bfbebSnyanmisaka // when packet size is valid read the input binary file
65*437bfbebSnyanmisaka ret = reader_read(cmd->reader, &slot);
66*437bfbebSnyanmisaka
67*437bfbebSnyanmisaka mpp_assert(ret == MPP_OK);
68*437bfbebSnyanmisaka mpp_assert(slot);
69*437bfbebSnyanmisaka
70*437bfbebSnyanmisaka pkt_eos = slot->eos;
71*437bfbebSnyanmisaka
72*437bfbebSnyanmisaka if (pkt_eos) {
73*437bfbebSnyanmisaka if (data->frame_num < 0 || data->frame_num > data->frame_count) {
74*437bfbebSnyanmisaka mpp_log_q(quiet, "%p loop again\n", ctx);
75*437bfbebSnyanmisaka reader_rewind(cmd->reader);
76*437bfbebSnyanmisaka pkt_eos = 0;
77*437bfbebSnyanmisaka } else {
78*437bfbebSnyanmisaka mpp_log_q(quiet, "%p found last packet\n", ctx);
79*437bfbebSnyanmisaka data->loop_end = 1;
80*437bfbebSnyanmisaka }
81*437bfbebSnyanmisaka }
82*437bfbebSnyanmisaka
83*437bfbebSnyanmisaka mpp_packet_set_data(packet, slot->data);
84*437bfbebSnyanmisaka mpp_packet_set_size(packet, slot->size);
85*437bfbebSnyanmisaka mpp_packet_set_pos(packet, slot->data);
86*437bfbebSnyanmisaka mpp_packet_set_length(packet, slot->size);
87*437bfbebSnyanmisaka // setup eos flag
88*437bfbebSnyanmisaka if (pkt_eos)
89*437bfbebSnyanmisaka mpp_packet_set_eos(packet);
90*437bfbebSnyanmisaka
91*437bfbebSnyanmisaka do {
92*437bfbebSnyanmisaka RK_U32 frm_eos = 0;
93*437bfbebSnyanmisaka RK_S32 times = 30;
94*437bfbebSnyanmisaka
95*437bfbebSnyanmisaka // send the packet first if packet is not done
96*437bfbebSnyanmisaka if (!pkt_done) {
97*437bfbebSnyanmisaka ret = mpi->decode_put_packet(ctx, packet);
98*437bfbebSnyanmisaka if (MPP_OK == ret) {
99*437bfbebSnyanmisaka pkt_done = 1;
100*437bfbebSnyanmisaka if (!data->first_pkt)
101*437bfbebSnyanmisaka data->first_pkt = mpp_time();
102*437bfbebSnyanmisaka }
103*437bfbebSnyanmisaka }
104*437bfbebSnyanmisaka
105*437bfbebSnyanmisaka // then get all available frame and release
106*437bfbebSnyanmisaka do {
107*437bfbebSnyanmisaka RK_S32 get_frm = 0;
108*437bfbebSnyanmisaka MppFrame frame = NULL;
109*437bfbebSnyanmisaka
110*437bfbebSnyanmisaka try_again:
111*437bfbebSnyanmisaka ret = mpi->decode_get_frame(ctx, &frame);
112*437bfbebSnyanmisaka if (MPP_ERR_TIMEOUT == ret) {
113*437bfbebSnyanmisaka if (times > 0) {
114*437bfbebSnyanmisaka times--;
115*437bfbebSnyanmisaka msleep(1);
116*437bfbebSnyanmisaka goto try_again;
117*437bfbebSnyanmisaka }
118*437bfbebSnyanmisaka mpp_err("%p decode_get_frame failed too much time\n", ctx);
119*437bfbebSnyanmisaka }
120*437bfbebSnyanmisaka if (ret) {
121*437bfbebSnyanmisaka mpp_err("%p decode_get_frame failed ret %d\n", ret, ctx);
122*437bfbebSnyanmisaka break;
123*437bfbebSnyanmisaka }
124*437bfbebSnyanmisaka
125*437bfbebSnyanmisaka if (frame) {
126*437bfbebSnyanmisaka if (mpp_frame_get_info_change(frame)) {
127*437bfbebSnyanmisaka RK_U32 width = mpp_frame_get_width(frame);
128*437bfbebSnyanmisaka RK_U32 height = mpp_frame_get_height(frame);
129*437bfbebSnyanmisaka RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);
130*437bfbebSnyanmisaka RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);
131*437bfbebSnyanmisaka RK_U32 buf_size = mpp_frame_get_buf_size(frame);
132*437bfbebSnyanmisaka MppBufferGroup grp = NULL;
133*437bfbebSnyanmisaka
134*437bfbebSnyanmisaka mpp_log_q(quiet, "%p decode_get_frame get info changed found\n", ctx);
135*437bfbebSnyanmisaka mpp_log_q(quiet, "%p decoder require buffer w:h [%d:%d] stride [%d:%d] buf_size %d",
136*437bfbebSnyanmisaka ctx, width, height, hor_stride, ver_stride, buf_size);
137*437bfbebSnyanmisaka
138*437bfbebSnyanmisaka if (MPP_FRAME_FMT_IS_FBC(cmd->format)) {
139*437bfbebSnyanmisaka MppFrame frm = NULL;
140*437bfbebSnyanmisaka
141*437bfbebSnyanmisaka mpp_frame_init(&frm);
142*437bfbebSnyanmisaka mpp_frame_set_width(frm, width);
143*437bfbebSnyanmisaka mpp_frame_set_height(frm, height);
144*437bfbebSnyanmisaka mpp_frame_set_fmt(frm, cmd->format);
145*437bfbebSnyanmisaka
146*437bfbebSnyanmisaka ret = mpi->control(ctx, MPP_DEC_SET_FRAME_INFO, frm);
147*437bfbebSnyanmisaka mpp_frame_deinit(&frm);
148*437bfbebSnyanmisaka
149*437bfbebSnyanmisaka if (ret) {
150*437bfbebSnyanmisaka mpp_err("set fbc frame info failed\n");
151*437bfbebSnyanmisaka break;
152*437bfbebSnyanmisaka }
153*437bfbebSnyanmisaka }
154*437bfbebSnyanmisaka
155*437bfbebSnyanmisaka grp = dec_buf_mgr_setup(data->buf_mgr, buf_size, 24, cmd->buf_mode);
156*437bfbebSnyanmisaka /* Set buffer to mpp decoder */
157*437bfbebSnyanmisaka ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, grp);
158*437bfbebSnyanmisaka if (ret) {
159*437bfbebSnyanmisaka mpp_err("%p set buffer group failed ret %d\n", ctx, ret);
160*437bfbebSnyanmisaka break;
161*437bfbebSnyanmisaka }
162*437bfbebSnyanmisaka data->frm_grp = grp;
163*437bfbebSnyanmisaka
164*437bfbebSnyanmisaka /*
165*437bfbebSnyanmisaka * All buffer group config done. Set info change ready to let
166*437bfbebSnyanmisaka * decoder continue decoding
167*437bfbebSnyanmisaka */
168*437bfbebSnyanmisaka ret = mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
169*437bfbebSnyanmisaka if (ret) {
170*437bfbebSnyanmisaka mpp_err("%p info change ready failed ret %d\n", ctx, ret);
171*437bfbebSnyanmisaka break;
172*437bfbebSnyanmisaka }
173*437bfbebSnyanmisaka } else {
174*437bfbebSnyanmisaka char log_buf[256];
175*437bfbebSnyanmisaka RK_S32 log_size = sizeof(log_buf) - 1;
176*437bfbebSnyanmisaka RK_S32 log_len = 0;
177*437bfbebSnyanmisaka RK_U32 err_info = mpp_frame_get_errinfo(frame);
178*437bfbebSnyanmisaka RK_U32 discard = mpp_frame_get_discard(frame);
179*437bfbebSnyanmisaka
180*437bfbebSnyanmisaka if (!data->first_frm)
181*437bfbebSnyanmisaka data->first_frm = mpp_time();
182*437bfbebSnyanmisaka
183*437bfbebSnyanmisaka log_len += snprintf(log_buf + log_len, log_size - log_len,
184*437bfbebSnyanmisaka "decode get frame %d", data->frame_count);
185*437bfbebSnyanmisaka
186*437bfbebSnyanmisaka if (mpp_frame_has_meta(frame)) {
187*437bfbebSnyanmisaka MppMeta meta = mpp_frame_get_meta(frame);
188*437bfbebSnyanmisaka RK_S32 temporal_id = 0;
189*437bfbebSnyanmisaka
190*437bfbebSnyanmisaka mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &temporal_id);
191*437bfbebSnyanmisaka
192*437bfbebSnyanmisaka log_len += snprintf(log_buf + log_len, log_size - log_len,
193*437bfbebSnyanmisaka " tid %d", temporal_id);
194*437bfbebSnyanmisaka }
195*437bfbebSnyanmisaka
196*437bfbebSnyanmisaka if (err_info || discard) {
197*437bfbebSnyanmisaka log_len += snprintf(log_buf + log_len, log_size - log_len,
198*437bfbebSnyanmisaka " err %x discard %x", err_info, discard);
199*437bfbebSnyanmisaka }
200*437bfbebSnyanmisaka mpp_log_q(quiet, "%p %s\n", ctx, log_buf);
201*437bfbebSnyanmisaka
202*437bfbebSnyanmisaka data->frame_count++;
203*437bfbebSnyanmisaka if (data->fp_output && !err_info)
204*437bfbebSnyanmisaka dump_mpp_frame_to_file(frame, data->fp_output);
205*437bfbebSnyanmisaka
206*437bfbebSnyanmisaka if (data->fp_verify) {
207*437bfbebSnyanmisaka calc_frm_crc(frame, checkcrc);
208*437bfbebSnyanmisaka write_frm_crc(data->fp_verify, checkcrc);
209*437bfbebSnyanmisaka }
210*437bfbebSnyanmisaka
211*437bfbebSnyanmisaka fps_calc_inc(cmd->fps);
212*437bfbebSnyanmisaka }
213*437bfbebSnyanmisaka frm_eos = mpp_frame_get_eos(frame);
214*437bfbebSnyanmisaka mpp_frame_deinit(&frame);
215*437bfbebSnyanmisaka get_frm = 1;
216*437bfbebSnyanmisaka }
217*437bfbebSnyanmisaka
218*437bfbebSnyanmisaka // try get runtime frame memory usage
219*437bfbebSnyanmisaka if (data->frm_grp) {
220*437bfbebSnyanmisaka size_t usage = mpp_buffer_group_usage(data->frm_grp);
221*437bfbebSnyanmisaka if (usage > data->max_usage)
222*437bfbebSnyanmisaka data->max_usage = usage;
223*437bfbebSnyanmisaka }
224*437bfbebSnyanmisaka
225*437bfbebSnyanmisaka // if last packet is send but last frame is not found continue
226*437bfbebSnyanmisaka if (pkt_eos && pkt_done && !frm_eos) {
227*437bfbebSnyanmisaka msleep(1);
228*437bfbebSnyanmisaka continue;
229*437bfbebSnyanmisaka }
230*437bfbebSnyanmisaka
231*437bfbebSnyanmisaka if (frm_eos) {
232*437bfbebSnyanmisaka mpp_log_q(quiet, "%p found last packet\n", ctx);
233*437bfbebSnyanmisaka break;
234*437bfbebSnyanmisaka }
235*437bfbebSnyanmisaka
236*437bfbebSnyanmisaka if ((data->frame_num > 0 && (data->frame_count >= data->frame_num)) ||
237*437bfbebSnyanmisaka ((data->frame_num == 0) && frm_eos))
238*437bfbebSnyanmisaka break;
239*437bfbebSnyanmisaka
240*437bfbebSnyanmisaka if (get_frm)
241*437bfbebSnyanmisaka continue;
242*437bfbebSnyanmisaka break;
243*437bfbebSnyanmisaka } while (1);
244*437bfbebSnyanmisaka
245*437bfbebSnyanmisaka if ((data->frame_num > 0 && (data->frame_count >= data->frame_num)) ||
246*437bfbebSnyanmisaka ((data->frame_num == 0) && frm_eos)) {
247*437bfbebSnyanmisaka data->loop_end = 1;
248*437bfbebSnyanmisaka break;
249*437bfbebSnyanmisaka }
250*437bfbebSnyanmisaka
251*437bfbebSnyanmisaka if (pkt_done)
252*437bfbebSnyanmisaka break;
253*437bfbebSnyanmisaka
254*437bfbebSnyanmisaka /*
255*437bfbebSnyanmisaka * why sleep here:
256*437bfbebSnyanmisaka * mpi->decode_put_packet will failed when packet in internal queue is
257*437bfbebSnyanmisaka * full,waiting the package is consumed .Usually hardware decode one
258*437bfbebSnyanmisaka * frame which resolution is 1080p needs 2 ms,so here we sleep 1ms
259*437bfbebSnyanmisaka * * is enough.
260*437bfbebSnyanmisaka */
261*437bfbebSnyanmisaka msleep(1);
262*437bfbebSnyanmisaka } while (1);
263*437bfbebSnyanmisaka
264*437bfbebSnyanmisaka return ret;
265*437bfbebSnyanmisaka }
266*437bfbebSnyanmisaka
dec_advanced(MpiDecLoopData * data)267*437bfbebSnyanmisaka static int dec_advanced(MpiDecLoopData *data)
268*437bfbebSnyanmisaka {
269*437bfbebSnyanmisaka MPP_RET ret = MPP_OK;
270*437bfbebSnyanmisaka MpiDecTestCmd *cmd = data->cmd;
271*437bfbebSnyanmisaka MppCtx ctx = data->ctx;
272*437bfbebSnyanmisaka MppApi *mpi = data->mpi;
273*437bfbebSnyanmisaka MppPacket packet = NULL;
274*437bfbebSnyanmisaka MppPacket packet_ret = NULL;
275*437bfbebSnyanmisaka MppFrame frame = data->frame;
276*437bfbebSnyanmisaka MppFrame frame_ret = NULL;
277*437bfbebSnyanmisaka MppMeta meta = NULL;
278*437bfbebSnyanmisaka RK_U32 quiet = data->quiet;
279*437bfbebSnyanmisaka FileBufSlot *slot = NULL;
280*437bfbebSnyanmisaka FrmCrc *checkcrc = &data->checkcrc;
281*437bfbebSnyanmisaka
282*437bfbebSnyanmisaka ret = reader_index_read(cmd->reader, 0, &slot);
283*437bfbebSnyanmisaka mpp_assert(ret == MPP_OK);
284*437bfbebSnyanmisaka mpp_assert(slot);
285*437bfbebSnyanmisaka
286*437bfbebSnyanmisaka mpp_packet_init_with_buffer(&packet, slot->buf);
287*437bfbebSnyanmisaka
288*437bfbebSnyanmisaka // setup eos flag
289*437bfbebSnyanmisaka if (slot->eos)
290*437bfbebSnyanmisaka mpp_packet_set_eos(packet);
291*437bfbebSnyanmisaka
292*437bfbebSnyanmisaka /* use the MppFrame with prealloced buffer and do not release */
293*437bfbebSnyanmisaka meta = mpp_packet_get_meta(packet);
294*437bfbebSnyanmisaka if (meta)
295*437bfbebSnyanmisaka mpp_meta_set_frame(meta, KEY_OUTPUT_FRAME, frame);
296*437bfbebSnyanmisaka
297*437bfbebSnyanmisaka ret = mpi->decode_put_packet(ctx, packet);
298*437bfbebSnyanmisaka if (ret) {
299*437bfbebSnyanmisaka mpp_err("%p mpp decode put packet failed ret %d\n", ctx, ret);
300*437bfbebSnyanmisaka data->loop_end = 1;
301*437bfbebSnyanmisaka goto DONE;
302*437bfbebSnyanmisaka }
303*437bfbebSnyanmisaka
304*437bfbebSnyanmisaka if (!data->first_pkt)
305*437bfbebSnyanmisaka data->first_pkt = mpp_time();
306*437bfbebSnyanmisaka
307*437bfbebSnyanmisaka ret = mpi->decode_get_frame(ctx, &frame_ret);
308*437bfbebSnyanmisaka if (ret || !frame_ret) {
309*437bfbebSnyanmisaka mpp_err("%p mpp decode get frame failed ret %d frame %p\n", ctx, ret, frame_ret);
310*437bfbebSnyanmisaka data->loop_end = 1;
311*437bfbebSnyanmisaka goto DONE;
312*437bfbebSnyanmisaka }
313*437bfbebSnyanmisaka
314*437bfbebSnyanmisaka if (!data->first_frm)
315*437bfbebSnyanmisaka data->first_frm = mpp_time();
316*437bfbebSnyanmisaka
317*437bfbebSnyanmisaka if (frame_ret != frame)
318*437bfbebSnyanmisaka mpp_err_f("mismatch frame %p -> %p\n", frame_ret, frame);
319*437bfbebSnyanmisaka
320*437bfbebSnyanmisaka /* write frame to file here */
321*437bfbebSnyanmisaka if (data->fp_output)
322*437bfbebSnyanmisaka dump_mpp_frame_to_file(frame_ret, data->fp_output);
323*437bfbebSnyanmisaka
324*437bfbebSnyanmisaka if (data->fp_verify) {
325*437bfbebSnyanmisaka calc_frm_crc(frame_ret, checkcrc);
326*437bfbebSnyanmisaka write_frm_crc(data->fp_verify, checkcrc);
327*437bfbebSnyanmisaka }
328*437bfbebSnyanmisaka
329*437bfbebSnyanmisaka mpp_log_q(quiet, "%p decoded frame %d\n", ctx, data->frame_count);
330*437bfbebSnyanmisaka data->frame_count++;
331*437bfbebSnyanmisaka
332*437bfbebSnyanmisaka if (mpp_frame_get_eos(frame_ret))
333*437bfbebSnyanmisaka mpp_log_q(quiet, "%p found eos frame\n", ctx);
334*437bfbebSnyanmisaka
335*437bfbebSnyanmisaka fps_calc_inc(cmd->fps);
336*437bfbebSnyanmisaka
337*437bfbebSnyanmisaka meta = mpp_frame_get_meta(frame);
338*437bfbebSnyanmisaka if (meta) {
339*437bfbebSnyanmisaka ret = mpp_meta_get_packet(meta, KEY_INPUT_PACKET, &packet_ret);
340*437bfbebSnyanmisaka if (ret || !packet_ret) {
341*437bfbebSnyanmisaka mpp_err("%p mpp meta get packet failed ret %d\n", ctx, ret);
342*437bfbebSnyanmisaka goto DONE;
343*437bfbebSnyanmisaka }
344*437bfbebSnyanmisaka
345*437bfbebSnyanmisaka if (packet_ret != packet)
346*437bfbebSnyanmisaka mpp_err_f("mismatch packet %p -> %p\n", packet, packet_ret);
347*437bfbebSnyanmisaka }
348*437bfbebSnyanmisaka
349*437bfbebSnyanmisaka if (data->frame_num > 0) {
350*437bfbebSnyanmisaka if (data->frame_count >= data->frame_num)
351*437bfbebSnyanmisaka data->loop_end = 1;
352*437bfbebSnyanmisaka } else if (data->frame_num == 0) {
353*437bfbebSnyanmisaka if (slot->eos)
354*437bfbebSnyanmisaka data->loop_end = 1;
355*437bfbebSnyanmisaka }
356*437bfbebSnyanmisaka
357*437bfbebSnyanmisaka DONE:
358*437bfbebSnyanmisaka mpp_packet_deinit(&packet);
359*437bfbebSnyanmisaka
360*437bfbebSnyanmisaka return ret;
361*437bfbebSnyanmisaka }
362*437bfbebSnyanmisaka
thread_decode(void * arg)363*437bfbebSnyanmisaka void *thread_decode(void *arg)
364*437bfbebSnyanmisaka {
365*437bfbebSnyanmisaka MpiDecLoopData *data = (MpiDecLoopData *)arg;
366*437bfbebSnyanmisaka MpiDecTestCmd *cmd = data->cmd;
367*437bfbebSnyanmisaka MppCtx ctx = data->ctx;
368*437bfbebSnyanmisaka MppApi *mpi = data->mpi;
369*437bfbebSnyanmisaka RK_S64 t_s, t_e;
370*437bfbebSnyanmisaka
371*437bfbebSnyanmisaka memset(&data->checkcrc, 0, sizeof(data->checkcrc));
372*437bfbebSnyanmisaka data->checkcrc.luma.sum = mpp_malloc(RK_ULONG, 512);
373*437bfbebSnyanmisaka data->checkcrc.chroma.sum = mpp_malloc(RK_ULONG, 512);
374*437bfbebSnyanmisaka
375*437bfbebSnyanmisaka t_s = mpp_time();
376*437bfbebSnyanmisaka
377*437bfbebSnyanmisaka if (cmd->simple) {
378*437bfbebSnyanmisaka while (!data->loop_end)
379*437bfbebSnyanmisaka dec_simple(data);
380*437bfbebSnyanmisaka } else {
381*437bfbebSnyanmisaka /* NOTE: change output format before jpeg decoding */
382*437bfbebSnyanmisaka if (MPP_FRAME_FMT_IS_YUV(cmd->format) || MPP_FRAME_FMT_IS_RGB(cmd->format)) {
383*437bfbebSnyanmisaka MPP_RET ret = mpi->control(ctx, MPP_DEC_SET_OUTPUT_FORMAT, &cmd->format);
384*437bfbebSnyanmisaka if (ret) {
385*437bfbebSnyanmisaka mpp_err("Failed to set output format 0x%x\n", cmd->format);
386*437bfbebSnyanmisaka return NULL;
387*437bfbebSnyanmisaka }
388*437bfbebSnyanmisaka }
389*437bfbebSnyanmisaka
390*437bfbebSnyanmisaka while (!data->loop_end)
391*437bfbebSnyanmisaka dec_advanced(data);
392*437bfbebSnyanmisaka }
393*437bfbebSnyanmisaka
394*437bfbebSnyanmisaka t_e = mpp_time();
395*437bfbebSnyanmisaka data->elapsed_time = t_e - t_s;
396*437bfbebSnyanmisaka data->frame_rate = (float)data->frame_count * 1000000 / data->elapsed_time;
397*437bfbebSnyanmisaka data->delay = data->first_frm - data->first_pkt;
398*437bfbebSnyanmisaka
399*437bfbebSnyanmisaka mpp_log("decode %d frames time %lld ms delay %3d ms fps %3.2f\n",
400*437bfbebSnyanmisaka data->frame_count, (RK_S64)(data->elapsed_time / 1000),
401*437bfbebSnyanmisaka (RK_S32)(data->delay / 1000), data->frame_rate);
402*437bfbebSnyanmisaka
403*437bfbebSnyanmisaka MPP_FREE(data->checkcrc.luma.sum);
404*437bfbebSnyanmisaka MPP_FREE(data->checkcrc.chroma.sum);
405*437bfbebSnyanmisaka
406*437bfbebSnyanmisaka return NULL;
407*437bfbebSnyanmisaka }
408*437bfbebSnyanmisaka
dec_decode(MpiDecTestCmd * cmd)409*437bfbebSnyanmisaka int dec_decode(MpiDecTestCmd *cmd)
410*437bfbebSnyanmisaka {
411*437bfbebSnyanmisaka // base flow context
412*437bfbebSnyanmisaka MppCtx ctx = NULL;
413*437bfbebSnyanmisaka MppApi *mpi = NULL;
414*437bfbebSnyanmisaka
415*437bfbebSnyanmisaka // input / output
416*437bfbebSnyanmisaka MppPacket packet = NULL;
417*437bfbebSnyanmisaka MppFrame frame = NULL;
418*437bfbebSnyanmisaka
419*437bfbebSnyanmisaka // paramter for resource malloc
420*437bfbebSnyanmisaka RK_U32 width = cmd->width;
421*437bfbebSnyanmisaka RK_U32 height = cmd->height;
422*437bfbebSnyanmisaka MppCodingType type = cmd->type;
423*437bfbebSnyanmisaka
424*437bfbebSnyanmisaka // config for runtime mode
425*437bfbebSnyanmisaka MppDecCfg cfg = NULL;
426*437bfbebSnyanmisaka RK_U32 need_split = 1;
427*437bfbebSnyanmisaka
428*437bfbebSnyanmisaka // resources
429*437bfbebSnyanmisaka MppBuffer frm_buf = NULL;
430*437bfbebSnyanmisaka pthread_t thd;
431*437bfbebSnyanmisaka pthread_attr_t attr;
432*437bfbebSnyanmisaka MpiDecLoopData data;
433*437bfbebSnyanmisaka MPP_RET ret = MPP_OK;
434*437bfbebSnyanmisaka
435*437bfbebSnyanmisaka mpp_log("mpi_dec_test start\n");
436*437bfbebSnyanmisaka memset(&data, 0, sizeof(data));
437*437bfbebSnyanmisaka pthread_attr_init(&attr);
438*437bfbebSnyanmisaka
439*437bfbebSnyanmisaka cmd->simple = (cmd->type != MPP_VIDEO_CodingMJPEG) ? (1) : (0);
440*437bfbebSnyanmisaka
441*437bfbebSnyanmisaka if (cmd->have_output) {
442*437bfbebSnyanmisaka data.fp_output = fopen(cmd->file_output, "w+b");
443*437bfbebSnyanmisaka if (NULL == data.fp_output) {
444*437bfbebSnyanmisaka mpp_err("failed to open output file %s\n", cmd->file_output);
445*437bfbebSnyanmisaka goto MPP_TEST_OUT;
446*437bfbebSnyanmisaka }
447*437bfbebSnyanmisaka }
448*437bfbebSnyanmisaka
449*437bfbebSnyanmisaka if (cmd->file_slt) {
450*437bfbebSnyanmisaka data.fp_verify = fopen(cmd->file_slt, "wt");
451*437bfbebSnyanmisaka if (!data.fp_verify)
452*437bfbebSnyanmisaka mpp_err("failed to open verify file %s\n", cmd->file_slt);
453*437bfbebSnyanmisaka }
454*437bfbebSnyanmisaka
455*437bfbebSnyanmisaka ret = dec_buf_mgr_init(&data.buf_mgr);
456*437bfbebSnyanmisaka if (ret) {
457*437bfbebSnyanmisaka mpp_err("dec_buf_mgr_init failed\n");
458*437bfbebSnyanmisaka goto MPP_TEST_OUT;
459*437bfbebSnyanmisaka }
460*437bfbebSnyanmisaka
461*437bfbebSnyanmisaka if (cmd->simple) {
462*437bfbebSnyanmisaka ret = mpp_packet_init(&packet, NULL, 0);
463*437bfbebSnyanmisaka if (ret) {
464*437bfbebSnyanmisaka mpp_err("mpp_packet_init failed\n");
465*437bfbebSnyanmisaka goto MPP_TEST_OUT;
466*437bfbebSnyanmisaka }
467*437bfbebSnyanmisaka } else {
468*437bfbebSnyanmisaka RK_U32 hor_stride = MPP_ALIGN(width, 16);
469*437bfbebSnyanmisaka RK_U32 ver_stride = MPP_ALIGN(height, 16);
470*437bfbebSnyanmisaka
471*437bfbebSnyanmisaka ret = mpp_frame_init(&frame); /* output frame */
472*437bfbebSnyanmisaka if (ret) {
473*437bfbebSnyanmisaka mpp_err("mpp_frame_init failed\n");
474*437bfbebSnyanmisaka goto MPP_TEST_OUT;
475*437bfbebSnyanmisaka }
476*437bfbebSnyanmisaka
477*437bfbebSnyanmisaka data.frm_grp = dec_buf_mgr_setup(data.buf_mgr, hor_stride * ver_stride * 4, 4, cmd->buf_mode);
478*437bfbebSnyanmisaka if (!data.frm_grp) {
479*437bfbebSnyanmisaka mpp_err("failed to get buffer group for input frame ret %d\n", ret);
480*437bfbebSnyanmisaka ret = MPP_NOK;
481*437bfbebSnyanmisaka goto MPP_TEST_OUT;
482*437bfbebSnyanmisaka }
483*437bfbebSnyanmisaka
484*437bfbebSnyanmisaka /*
485*437bfbebSnyanmisaka * NOTE: For jpeg could have YUV420 and YUV422 the buffer should be
486*437bfbebSnyanmisaka * larger for output. And the buffer dimension should align to 16.
487*437bfbebSnyanmisaka * YUV420 buffer is 3/2 times of w*h.
488*437bfbebSnyanmisaka * YUV422 buffer is 2 times of w*h.
489*437bfbebSnyanmisaka * So create larger buffer with 2 times w*h.
490*437bfbebSnyanmisaka */
491*437bfbebSnyanmisaka ret = mpp_buffer_get(data.frm_grp, &frm_buf, hor_stride * ver_stride * 4);
492*437bfbebSnyanmisaka if (ret) {
493*437bfbebSnyanmisaka mpp_err("failed to get buffer for input frame ret %d\n", ret);
494*437bfbebSnyanmisaka goto MPP_TEST_OUT;
495*437bfbebSnyanmisaka }
496*437bfbebSnyanmisaka
497*437bfbebSnyanmisaka mpp_frame_set_buffer(frame, frm_buf);
498*437bfbebSnyanmisaka }
499*437bfbebSnyanmisaka
500*437bfbebSnyanmisaka // decoder demo
501*437bfbebSnyanmisaka ret = mpp_create(&ctx, &mpi);
502*437bfbebSnyanmisaka if (ret) {
503*437bfbebSnyanmisaka mpp_err("mpp_create failed\n");
504*437bfbebSnyanmisaka goto MPP_TEST_OUT;
505*437bfbebSnyanmisaka }
506*437bfbebSnyanmisaka
507*437bfbebSnyanmisaka mpp_log("%p mpi_dec_test decoder test start w %d h %d type %d\n",
508*437bfbebSnyanmisaka ctx, width, height, type);
509*437bfbebSnyanmisaka
510*437bfbebSnyanmisaka ret = mpp_init(ctx, MPP_CTX_DEC, type);
511*437bfbebSnyanmisaka if (ret) {
512*437bfbebSnyanmisaka mpp_err("%p mpp_init failed\n", ctx);
513*437bfbebSnyanmisaka goto MPP_TEST_OUT;
514*437bfbebSnyanmisaka }
515*437bfbebSnyanmisaka
516*437bfbebSnyanmisaka mpp_dec_cfg_init(&cfg);
517*437bfbebSnyanmisaka
518*437bfbebSnyanmisaka /* get default config from decoder context */
519*437bfbebSnyanmisaka ret = mpi->control(ctx, MPP_DEC_GET_CFG, cfg);
520*437bfbebSnyanmisaka if (ret) {
521*437bfbebSnyanmisaka mpp_err("%p failed to get decoder cfg ret %d\n", ctx, ret);
522*437bfbebSnyanmisaka goto MPP_TEST_OUT;
523*437bfbebSnyanmisaka }
524*437bfbebSnyanmisaka
525*437bfbebSnyanmisaka /*
526*437bfbebSnyanmisaka * split_parse is to enable mpp internal frame spliter when the input
527*437bfbebSnyanmisaka * packet is not aplited into frames.
528*437bfbebSnyanmisaka */
529*437bfbebSnyanmisaka ret = mpp_dec_cfg_set_u32(cfg, "base:split_parse", need_split);
530*437bfbebSnyanmisaka if (ret) {
531*437bfbebSnyanmisaka mpp_err("%p failed to set split_parse ret %d\n", ctx, ret);
532*437bfbebSnyanmisaka goto MPP_TEST_OUT;
533*437bfbebSnyanmisaka }
534*437bfbebSnyanmisaka
535*437bfbebSnyanmisaka ret = mpi->control(ctx, MPP_DEC_SET_CFG, cfg);
536*437bfbebSnyanmisaka if (ret) {
537*437bfbebSnyanmisaka mpp_err("%p failed to set cfg %p ret %d\n", ctx, cfg, ret);
538*437bfbebSnyanmisaka goto MPP_TEST_OUT;
539*437bfbebSnyanmisaka }
540*437bfbebSnyanmisaka
541*437bfbebSnyanmisaka data.cmd = cmd;
542*437bfbebSnyanmisaka data.ctx = ctx;
543*437bfbebSnyanmisaka data.mpi = mpi;
544*437bfbebSnyanmisaka data.loop_end = 0;
545*437bfbebSnyanmisaka data.packet = packet;
546*437bfbebSnyanmisaka data.frame = frame;
547*437bfbebSnyanmisaka data.frame_count = 0;
548*437bfbebSnyanmisaka data.frame_num = cmd->frame_num;
549*437bfbebSnyanmisaka data.quiet = cmd->quiet;
550*437bfbebSnyanmisaka
551*437bfbebSnyanmisaka pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
552*437bfbebSnyanmisaka
553*437bfbebSnyanmisaka ret = pthread_create(&thd, &attr, thread_decode, &data);
554*437bfbebSnyanmisaka if (ret) {
555*437bfbebSnyanmisaka mpp_err("failed to create thread for input ret %d\n", ret);
556*437bfbebSnyanmisaka goto MPP_TEST_OUT;
557*437bfbebSnyanmisaka }
558*437bfbebSnyanmisaka
559*437bfbebSnyanmisaka if (cmd->frame_num < 0) {
560*437bfbebSnyanmisaka // wait for input then quit decoding
561*437bfbebSnyanmisaka mpp_log("*******************************************\n");
562*437bfbebSnyanmisaka mpp_log("**** Press Enter to stop loop decoding ****\n");
563*437bfbebSnyanmisaka mpp_log("*******************************************\n");
564*437bfbebSnyanmisaka
565*437bfbebSnyanmisaka getc(stdin);
566*437bfbebSnyanmisaka data.loop_end = 1;
567*437bfbebSnyanmisaka }
568*437bfbebSnyanmisaka
569*437bfbebSnyanmisaka pthread_join(thd, NULL);
570*437bfbebSnyanmisaka
571*437bfbebSnyanmisaka cmd->max_usage = data.max_usage;
572*437bfbebSnyanmisaka
573*437bfbebSnyanmisaka ret = mpi->reset(ctx);
574*437bfbebSnyanmisaka if (ret) {
575*437bfbebSnyanmisaka mpp_err("%p mpi->reset failed\n", ctx);
576*437bfbebSnyanmisaka goto MPP_TEST_OUT;
577*437bfbebSnyanmisaka }
578*437bfbebSnyanmisaka
579*437bfbebSnyanmisaka MPP_TEST_OUT:
580*437bfbebSnyanmisaka if (data.packet) {
581*437bfbebSnyanmisaka mpp_packet_deinit(&data.packet);
582*437bfbebSnyanmisaka data.packet = NULL;
583*437bfbebSnyanmisaka }
584*437bfbebSnyanmisaka
585*437bfbebSnyanmisaka if (frame) {
586*437bfbebSnyanmisaka mpp_frame_deinit(&frame);
587*437bfbebSnyanmisaka frame = NULL;
588*437bfbebSnyanmisaka }
589*437bfbebSnyanmisaka
590*437bfbebSnyanmisaka if (ctx) {
591*437bfbebSnyanmisaka mpp_destroy(ctx);
592*437bfbebSnyanmisaka ctx = NULL;
593*437bfbebSnyanmisaka }
594*437bfbebSnyanmisaka
595*437bfbebSnyanmisaka if (!cmd->simple) {
596*437bfbebSnyanmisaka if (frm_buf) {
597*437bfbebSnyanmisaka mpp_buffer_put(frm_buf);
598*437bfbebSnyanmisaka frm_buf = NULL;
599*437bfbebSnyanmisaka }
600*437bfbebSnyanmisaka }
601*437bfbebSnyanmisaka
602*437bfbebSnyanmisaka data.frm_grp = NULL;
603*437bfbebSnyanmisaka if (data.buf_mgr) {
604*437bfbebSnyanmisaka dec_buf_mgr_deinit(data.buf_mgr);
605*437bfbebSnyanmisaka data.buf_mgr = NULL;
606*437bfbebSnyanmisaka }
607*437bfbebSnyanmisaka
608*437bfbebSnyanmisaka if (data.fp_output) {
609*437bfbebSnyanmisaka fclose(data.fp_output);
610*437bfbebSnyanmisaka data.fp_output = NULL;
611*437bfbebSnyanmisaka }
612*437bfbebSnyanmisaka
613*437bfbebSnyanmisaka if (data.fp_verify) {
614*437bfbebSnyanmisaka fclose(data.fp_verify);
615*437bfbebSnyanmisaka data.fp_verify = NULL;
616*437bfbebSnyanmisaka }
617*437bfbebSnyanmisaka
618*437bfbebSnyanmisaka if (cfg) {
619*437bfbebSnyanmisaka mpp_dec_cfg_deinit(cfg);
620*437bfbebSnyanmisaka cfg = NULL;
621*437bfbebSnyanmisaka }
622*437bfbebSnyanmisaka
623*437bfbebSnyanmisaka pthread_attr_destroy(&attr);
624*437bfbebSnyanmisaka
625*437bfbebSnyanmisaka return ret;
626*437bfbebSnyanmisaka }
627*437bfbebSnyanmisaka
main(int argc,char ** argv)628*437bfbebSnyanmisaka int main(int argc, char **argv)
629*437bfbebSnyanmisaka {
630*437bfbebSnyanmisaka RK_S32 ret = 0;
631*437bfbebSnyanmisaka MpiDecTestCmd cmd_ctx;
632*437bfbebSnyanmisaka MpiDecTestCmd* cmd = &cmd_ctx;
633*437bfbebSnyanmisaka
634*437bfbebSnyanmisaka memset((void*)cmd, 0, sizeof(*cmd));
635*437bfbebSnyanmisaka cmd->format = MPP_FMT_BUTT;
636*437bfbebSnyanmisaka cmd->pkt_size = MPI_DEC_STREAM_SIZE;
637*437bfbebSnyanmisaka
638*437bfbebSnyanmisaka // parse the cmd option
639*437bfbebSnyanmisaka ret = mpi_dec_test_cmd_init(cmd, argc, argv);
640*437bfbebSnyanmisaka if (ret)
641*437bfbebSnyanmisaka goto RET;
642*437bfbebSnyanmisaka
643*437bfbebSnyanmisaka mpi_dec_test_cmd_options(cmd);
644*437bfbebSnyanmisaka
645*437bfbebSnyanmisaka ret = dec_decode(cmd);
646*437bfbebSnyanmisaka if (MPP_OK == ret)
647*437bfbebSnyanmisaka mpp_log("test success max memory %.2f MB\n", cmd->max_usage / (float)(1 << 20));
648*437bfbebSnyanmisaka else
649*437bfbebSnyanmisaka mpp_err("test failed ret %d\n", ret);
650*437bfbebSnyanmisaka
651*437bfbebSnyanmisaka RET:
652*437bfbebSnyanmisaka mpi_dec_test_cmd_deinit(cmd);
653*437bfbebSnyanmisaka
654*437bfbebSnyanmisaka return ret;
655*437bfbebSnyanmisaka }
656*437bfbebSnyanmisaka
657