xref: /OK3568_Linux_fs/external/mpp/test/mpi_dec_mt_test.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright 2015 Rockchip Electronics Co. LTD
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #if defined(_WIN32)
18 #include "vld.h"
19 #endif
20 
21 #define MODULE_TAG "mpi_dec_mt_test"
22 
23 #include <string.h>
24 #include <pthread.h>
25 
26 #include "rk_mpi.h"
27 
28 #include "mpp_mem.h"
29 #include "mpp_env.h"
30 #include "mpp_time.h"
31 #include "mpp_common.h"
32 
33 #include "mpi_dec_utils.h"
34 
35 typedef struct {
36     MpiDecTestCmd   *cmd;
37     MppCtx          ctx;
38     MppApi          *mpi;
39 
40     volatile RK_U32 loop_end;
41 
42     /* buffer for stream data reading */
43     char            *buf;
44 
45     /* input and output */
46     MppBufferGroup  frm_grp;
47     MppPacket       packet;
48     size_t          packet_size;
49     MppFrame        frame;
50 
51     FILE            *fp_output;
52     RK_S32          frame_count;
53     RK_S32          frame_num;
54     FileReader      reader;
55 
56     /* runtime flag */
57     RK_U32          quiet;
58 } MpiDecMtLoopData;
59 
thread_input(void * arg)60 void *thread_input(void *arg)
61 {
62     MpiDecMtLoopData *data = (MpiDecMtLoopData *)arg;
63     MppCtx ctx  = data->ctx;
64     MppApi *mpi = data->mpi;
65     MppPacket packet = data->packet;
66     FileReader reader = data->reader;
67     RK_U32 quiet = data->quiet;
68 
69     mpp_log_q(quiet, "put packet thread start\n");
70 
71     do {
72         RK_U32 pkt_eos = 0;
73         FileBufSlot *slot = NULL;
74         MPP_RET ret = reader_read(reader, &slot);
75         if (ret)
76             break;
77 
78         mpp_packet_set_data(packet, slot->data);
79         mpp_packet_set_size(packet, slot->size);
80         mpp_packet_set_pos(packet, slot->data);
81         mpp_packet_set_length(packet, slot->size);
82 
83         pkt_eos = slot->eos;
84         // setup eos flag
85         if (pkt_eos) {
86             if (data->frame_num < 0 || data->frame_count < data->frame_num) {
87                 mpp_log_q(quiet, "%p loop again\n", ctx);
88                 reader_rewind(reader);
89                 pkt_eos = 0;
90             } else {
91                 mpp_log_q(quiet, "%p found last packet\n", ctx);
92                 mpp_packet_set_eos(packet);
93             }
94         }
95 
96         // send packet until it success
97         do {
98             ret = mpi->decode_put_packet(ctx, packet);
99             if (MPP_OK == ret) {
100                 mpp_assert(0 == mpp_packet_get_length(packet));
101                 break;
102 
103             }
104             // if failed wait a moment and retry
105             msleep(1);
106         } while (!data->loop_end);
107 
108         if (pkt_eos)
109             break;
110     } while (!data->loop_end);
111 
112     mpp_log_q(quiet, "put packet thread end\n");
113 
114     return NULL;
115 }
116 
thread_output(void * arg)117 void *thread_output(void *arg)
118 {
119     MpiDecMtLoopData *data = (MpiDecMtLoopData *)arg;
120     MpiDecTestCmd *cmd = data->cmd;
121     MppCtx ctx  = data->ctx;
122     MppApi *mpi = data->mpi;
123     RK_U32 quiet = data->quiet;
124 
125     mpp_log_q(quiet, "get frame thread start\n");
126 
127     // then get all available frame and release
128     do {
129         RK_U32 frm_eos = 0;
130         MppFrame frame = NULL;
131         MPP_RET ret = mpi->decode_get_frame(ctx, &frame);
132 
133         if (ret) {
134             mpp_err("decode_get_frame failed ret %d\n", ret);
135             continue;
136         }
137 
138         if (NULL == frame) {
139             msleep(1);
140             continue;
141         }
142 
143         if (mpp_frame_get_info_change(frame)) {
144             // found info change and create buffer group for decoding
145             RK_U32 width = mpp_frame_get_width(frame);
146             RK_U32 height = mpp_frame_get_height(frame);
147             RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);
148             RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);
149             RK_U32 buf_size = mpp_frame_get_buf_size(frame);
150 
151             mpp_log_q(quiet, "decode_get_frame get info changed found\n");
152             mpp_log_q(quiet, "decoder require buffer w:h [%d:%d] stride [%d:%d] size %d\n",
153                       width, height, hor_stride, ver_stride, buf_size);
154 
155             if (NULL == data->frm_grp) {
156                 /* If buffer group is not set create one and limit it */
157                 ret = mpp_buffer_group_get_internal(&data->frm_grp, MPP_BUFFER_TYPE_ION);
158                 if (ret) {
159                     mpp_err("get mpp buffer group failed ret %d\n", ret);
160                     break;
161                 }
162 
163                 /* Set buffer to mpp decoder */
164                 ret = mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, data->frm_grp);
165                 if (ret) {
166                     mpp_err("set buffer group failed ret %d\n", ret);
167                     break;
168                 }
169             } else {
170                 /* If old buffer group exist clear it */
171                 ret = mpp_buffer_group_clear(data->frm_grp);
172                 if (ret) {
173                     mpp_err("clear buffer group failed ret %d\n", ret);
174                     break;
175                 }
176             }
177 
178             /* Use limit config to limit buffer count to 24 */
179             ret = mpp_buffer_group_limit_config(data->frm_grp, buf_size, 24);
180             if (ret) {
181                 mpp_err("limit buffer group failed ret %d\n", ret);
182                 break;
183             }
184 
185             ret = mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
186             if (ret) {
187                 mpp_err("info change ready failed ret %d\n", ret);
188                 break;
189             }
190         } else {
191             char log_buf[256];
192             RK_S32 log_size = sizeof(log_buf) - 1;
193             RK_S32 log_len = 0;
194             RK_U32 err_info = mpp_frame_get_errinfo(frame);
195             RK_U32 discard = mpp_frame_get_discard(frame);
196 
197             log_len += snprintf(log_buf + log_len, log_size - log_len,
198                                 "decode get frame %d", data->frame_count);
199 
200             if (mpp_frame_has_meta(frame)) {
201                 MppMeta meta = mpp_frame_get_meta(frame);
202                 RK_S32 temporal_id = 0;
203 
204                 mpp_meta_get_s32(meta, KEY_TEMPORAL_ID, &temporal_id);
205 
206                 log_len += snprintf(log_buf + log_len, log_size - log_len,
207                                     " tid %d", temporal_id);
208             }
209 
210             if (err_info || discard) {
211                 log_len += snprintf(log_buf + log_len, log_size - log_len,
212                                     " err %x discard %x", err_info, discard);
213             }
214             mpp_log_q(quiet, "%p %s\n", ctx, log_buf);
215 
216             data->frame_count++;
217             if (data->fp_output && !err_info)
218                 dump_mpp_frame_to_file(frame, data->fp_output);
219 
220             fps_calc_inc(cmd->fps);
221         }
222 
223         frm_eos = mpp_frame_get_eos(frame);
224         mpp_frame_deinit(&frame);
225 
226         if ((data->frame_num > 0 && (data->frame_count >= data->frame_num)) ||
227             ((data->frame_num == 0) && frm_eos))
228             data->loop_end = 1;
229     } while (!data->loop_end);
230 
231     mpp_log_q(quiet, "get frame thread end\n");
232 
233     return NULL;
234 }
235 
mt_dec_decode(MpiDecTestCmd * cmd)236 int mt_dec_decode(MpiDecTestCmd *cmd)
237 {
238     MPP_RET ret         = MPP_OK;
239     FileReader reader   = cmd->reader;
240 
241     // base flow context
242     MppCtx ctx          = NULL;
243     MppApi *mpi         = NULL;
244 
245     // input / output
246     MppPacket packet    = NULL;
247     MppFrame  frame     = NULL;
248 
249     // config for runtime mode
250     MppDecCfg cfg       = NULL;
251     RK_U32 need_split   = 1;
252 
253     // paramter for resource malloc
254     RK_U32 width        = cmd->width;
255     RK_U32 height       = cmd->height;
256     MppCodingType type  = cmd->type;
257 
258     pthread_t thd_in;
259     pthread_t thd_out = 0;
260     pthread_attr_t attr;
261     MpiDecMtLoopData data;
262 
263     mpp_log("mpi_dec_mt_test start\n");
264     memset(&data, 0, sizeof(data));
265 
266     if (cmd->have_output) {
267         data.fp_output = fopen(cmd->file_output, "w+b");
268         if (NULL == data.fp_output) {
269             mpp_err("failed to open output file %s\n", cmd->file_output);
270             goto MPP_TEST_OUT;
271         }
272     }
273 
274     ret = mpp_packet_init(&packet, NULL, 0);
275     if (ret) {
276         mpp_err("mpp_packet_init failed\n");
277         goto MPP_TEST_OUT;
278     }
279 
280     mpp_log("mpi_dec_mt_test decoder test start w %d h %d type %d\n", width, height, type);
281 
282     // decoder demo
283     ret = mpp_create(&ctx, &mpi);
284     if (ret) {
285         mpp_err("mpp_create failed\n");
286         goto MPP_TEST_OUT;
287     }
288 
289     ret = mpp_init(ctx, MPP_CTX_DEC, type);
290     if (ret) {
291         mpp_err("mpp_init failed\n");
292         goto MPP_TEST_OUT;
293     }
294 
295     // NOTE: timeout value please refer to MppPollType definition
296     //  0   - non-block call (default)
297     // -1   - block call
298     // +val - timeout value in ms
299     {
300         MppPollType timeout = MPP_POLL_BLOCK;
301         MppParam param = &timeout;
302 
303         ret = mpi->control(ctx, MPP_SET_OUTPUT_TIMEOUT, param);
304         if (ret) {
305             mpp_err("Failed to set output timeout %d ret %d\n", timeout, ret);
306             goto MPP_TEST_OUT;
307         }
308     }
309 
310     mpp_dec_cfg_init(&cfg);
311 
312     /* get default config from decoder context */
313     ret = mpi->control(ctx, MPP_DEC_GET_CFG, cfg);
314     if (ret) {
315         mpp_err("%p failed to get decoder cfg ret %d\n", ctx, ret);
316         goto MPP_TEST_OUT;
317     }
318 
319     /*
320      * split_parse is to enable mpp internal frame spliter when the input
321      * packet is not aplited into frames.
322      */
323     ret = mpp_dec_cfg_set_u32(cfg, "base:split_parse", need_split);
324     if (ret) {
325         mpp_err("%p failed to set split_parse ret %d\n", ctx, ret);
326         goto MPP_TEST_OUT;
327     }
328 
329     ret = mpi->control(ctx, MPP_DEC_SET_CFG, cfg);
330     if (ret) {
331         mpp_err("%p failed to set cfg %p ret %d\n", ctx, cfg, ret);
332         goto MPP_TEST_OUT;
333     }
334 
335     data.cmd            = cmd;
336     data.ctx            = ctx;
337     data.mpi            = mpi;
338     data.loop_end       = 0;
339     data.packet         = packet;
340     data.frame          = frame;
341     data.frame_count    = 0;
342     data.frame_num      = cmd->frame_num;
343     data.reader         = reader;
344     data.quiet          = cmd->quiet;
345 
346     pthread_attr_init(&attr);
347     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
348 
349     ret = pthread_create(&thd_in, &attr, thread_input, &data);
350     if (ret) {
351         mpp_err("failed to create thread for input ret %d\n", ret);
352         goto THREAD_END;
353     }
354 
355     ret = pthread_create(&thd_out, &attr, thread_output, &data);
356     if (ret) {
357         mpp_err("failed to create thread for output ret %d\n", ret);
358         goto THREAD_END;
359     }
360 
361     if (cmd->frame_num < 0) {
362         // wait for input then quit decoding
363         mpp_log("*******************************************\n");
364         mpp_log("**** Press Enter to stop loop decoding ****\n");
365         mpp_log("*******************************************\n");
366 
367         getc(stdin);
368         data.loop_end = 1;
369     }
370 
371 THREAD_END:
372     pthread_attr_destroy(&attr);
373 
374     pthread_join(thd_in, NULL);
375     pthread_join(thd_out, NULL);
376 
377     ret = mpi->reset(ctx);
378     if (ret) {
379         mpp_err("mpi->reset failed\n");
380         goto MPP_TEST_OUT;
381     }
382 
383 MPP_TEST_OUT:
384     if (packet) {
385         mpp_packet_deinit(&packet);
386         packet = NULL;
387     }
388 
389     if (frame) {
390         mpp_frame_deinit(&frame);
391         frame = NULL;
392     }
393 
394     if (ctx) {
395         mpp_destroy(ctx);
396         ctx = NULL;
397     }
398 
399     if (data.frm_grp) {
400         mpp_buffer_group_put(data.frm_grp);
401         data.frm_grp = NULL;
402     }
403 
404     if (data.fp_output) {
405         fclose(data.fp_output);
406         data.fp_output = NULL;
407     }
408 
409     if (cfg) {
410         mpp_dec_cfg_deinit(cfg);
411         cfg = NULL;
412     }
413 
414     return ret;
415 }
416 
main(int argc,char ** argv)417 int main(int argc, char **argv)
418 {
419     RK_S32 ret = 0;
420     MpiDecTestCmd  cmd_ctx;
421     MpiDecTestCmd* cmd = &cmd_ctx;
422 
423     memset((void*)cmd, 0, sizeof(*cmd));
424     // default use block mode
425     cmd->timeout = -1;
426 
427     // parse the cmd option
428     ret = mpi_dec_test_cmd_init(cmd, argc, argv);
429     if (ret)
430         goto RET;
431 
432     mpi_dec_test_cmd_options(cmd);
433 
434     ret = mt_dec_decode(cmd);
435     if (MPP_OK == ret)
436         mpp_log("test success\n");
437     else
438         mpp_err("test failed ret %d\n", ret);
439 
440 RET:
441     mpi_dec_test_cmd_deinit(cmd);
442 
443     return ret;
444 }
445 
446