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