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