1 /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2 /*
3 * Copyright (c) 2015 Rockchip Electronics Co., Ltd.
4 */
5
6 #define MODULE_TAG "mpp"
7
8 #include <errno.h>
9 #include <string.h>
10
11 #include "rk_mpi.h"
12
13 #include "mpp_mem.h"
14 #include "mpp_env.h"
15 #include "mpp_time.h"
16 #include "mpp_impl.h"
17 #include "mpp_2str.h"
18 #include "mpp_debug.h"
19
20 #include "mpp.h"
21 #include "mpp_hal.h"
22
23 #include "mpp_task_impl.h"
24 #include "mpp_buffer_impl.h"
25 #include "mpp_frame_impl.h"
26 #include "mpp_packet_impl.h"
27
28 #include "kmpp.h"
29
30 #define MPP_TEST_FRAME_SIZE SZ_1M
31 #define MPP_TEST_PACKET_SIZE SZ_512K
32
mpp_notify_by_buffer_group(void * arg,void * group)33 static void mpp_notify_by_buffer_group(void *arg, void *group)
34 {
35 Mpp *mpp = (Mpp *)arg;
36 mpp_notify_group(mpp, (MppBufferGroup)group);
37 }
38
list_wraper_packet(void * arg)39 static void *list_wraper_packet(void *arg)
40 {
41 MppPacket packet = *(MppPacket*)arg;
42
43 if (mpp_packet_has_meta(packet)) {
44 MppMeta meta = mpp_packet_get_meta(packet);
45 MppFrame frm = NULL;
46
47 if (MPP_OK == mpp_meta_get_frame(meta, KEY_INPUT_FRAME, &frm)) {
48 mpp_assert(frm);
49 mpp_frame_deinit(&frm);
50 }
51 }
52
53 mpp_packet_deinit((MppPacket *)arg);
54 return NULL;
55 }
56
list_wraper_frame(void * arg)57 static void *list_wraper_frame(void *arg)
58 {
59 mpp_frame_deinit((MppFrame *)arg);
60 return NULL;
61 }
62
check_frm_task_cnt_cap(MppCodingType coding)63 static RK_S32 check_frm_task_cnt_cap(MppCodingType coding)
64 {
65 RockchipSocType soc_type = mpp_get_soc_type();
66
67 if (soc_type == ROCKCHIP_SOC_RK3588 || soc_type == ROCKCHIP_SOC_RK3576) {
68 if (coding == MPP_VIDEO_CodingAVC || coding == MPP_VIDEO_CodingHEVC)
69 return 2;
70 if (coding == MPP_VIDEO_CodingMJPEG && soc_type == ROCKCHIP_SOC_RK3588)
71 return 4;
72 }
73
74 mpp_log("Only rk3588's h264/265/jpeg and rk3576's h264/265 encoder can use frame parallel\n");
75
76 return 1;
77 }
78
mpp_ctx_create(Mpp ** mpp,MppCtx ctx)79 MPP_RET mpp_ctx_create(Mpp **mpp, MppCtx ctx)
80 {
81 if (!mpp) {
82 mpp_err_f("invalid input mpp pointer\n");
83 return MPP_ERR_NULL_PTR;
84 }
85
86 Mpp *p = mpp_calloc(Mpp, 1);
87 if (!p) {
88 mpp_err_f("failed to allocate mpp context\n");
89 return MPP_ERR_MALLOC;
90 }
91
92 /* Initialize all members to default values */
93 p->mPktIn = NULL;
94 p->mPktOut = NULL;
95 p->mFrmIn = NULL;
96 p->mFrmOut = NULL;
97 p->mPacketPutCount = 0;
98 p->mPacketGetCount = 0;
99 p->mFramePutCount = 0;
100 p->mFrameGetCount = 0;
101 p->mTaskPutCount = 0;
102 p->mTaskGetCount = 0;
103 p->mPacketGroup = NULL;
104 p->mFrameGroup = NULL;
105 p->mExternalBufferMode = 0;
106 p->mUsrInPort = NULL;
107 p->mUsrOutPort = NULL;
108 p->mMppInPort = NULL;
109 p->mMppOutPort = NULL;
110 p->mInputTaskQueue = NULL;
111 p->mOutputTaskQueue = NULL;
112 p->mInputTaskCount = 1;
113 p->mOutputTaskCount = 1;
114 p->mInputTimeout = MPP_POLL_BUTT;
115 p->mOutputTimeout = MPP_POLL_BUTT;
116 p->mInputTask = NULL;
117 p->mEosTask = NULL;
118 p->mCtx = ctx;
119 p->mDec = NULL;
120 p->mEnc = NULL;
121 p->mEncAyncIo = 0;
122 p->mEncAyncProc = 0;
123 p->mIoMode = MPP_IO_MODE_DEFAULT;
124 p->mDisableThread = 0;
125 p->mDump = NULL;
126 p->mKmpp = NULL;
127 p->mVencInitKcfg = NULL;
128 p->mType = MPP_CTX_BUTT;
129 p->mCoding = MPP_VIDEO_CodingUnused;
130 p->mInitDone = 0;
131 p->mStatus = 0;
132 p->mDecCfg = NULL;
133 p->mParserFastMode = 0;
134 p->mParserNeedSplit = 0;
135 p->mParserInternalPts = 0;
136 p->mImmediateOut = 0;
137 p->mExtraPacket = NULL;
138
139 mpp_env_get_u32("mpp_debug", &mpp_debug, 0);
140
141 mpp_dec_cfg_init(&p->mDecCfg);
142 mpp_dec_cfg_set_u32(p->mDecCfg, "base:enable_vproc", MPP_VPROC_MODE_DEINTELACE);
143
144 mpp_dump_init(&p->mDump);
145
146 *mpp = p;
147 return MPP_OK;
148 }
149
mpp_ctx_init(Mpp * mpp,MppCtxType type,MppCodingType coding)150 MPP_RET mpp_ctx_init(Mpp *mpp, MppCtxType type, MppCodingType coding)
151 {
152 MPP_RET ret = MPP_NOK;
153
154 if (!mpp) {
155 mpp_err_f("invalid input mpp pointer\n");
156 return MPP_ERR_NULL_PTR;
157 }
158
159 if (!mpp_check_soc_cap(type, coding)) {
160 mpp_err("unable to create %s %s for soc %s unsupported\n",
161 strof_ctx_type(type), strof_coding_type(coding),
162 mpp_get_soc_info()->compatible);
163 return MPP_NOK;
164 }
165
166 if (mpp_check_support_format(type, coding)) {
167 mpp_err("unable to create %s %s for mpp unsupported\n",
168 strof_ctx_type(type), strof_coding_type(coding));
169 return MPP_NOK;
170 }
171
172 mpp_ops_init(mpp->mDump, type, coding);
173
174 mpp->mType = type;
175 mpp->mCoding = coding;
176
177 /* init kmpp venc */
178 if (mpp->mVencInitKcfg) {
179 mpp->mKmpp = mpp_calloc(Kmpp, 1);
180 if (!mpp->mKmpp) {
181 mpp_err("failed to alloc kmpp context\n");
182 return MPP_NOK;
183 }
184 mpp->mKmpp->mClientFd = -1;
185 mpp_get_api(mpp->mKmpp);
186 mpp->mKmpp->mVencInitKcfg = mpp->mVencInitKcfg;
187 ret = mpp->mKmpp->mApi->init(mpp->mKmpp, type, coding);
188 if (ret) {
189 mpp_err("failed to init kmpp ret %d\n", ret);
190 return ret;
191 }
192 mpp->mInitDone = 1;
193 return ret;
194 }
195
196 mpp_task_queue_init(&mpp->mInputTaskQueue, mpp, "input");
197 mpp_task_queue_init(&mpp->mOutputTaskQueue, mpp, "output");
198
199 switch (mpp->mType) {
200 case MPP_CTX_DEC : {
201 mpp->mPktIn = mpp_list_create(list_wraper_packet);
202 mpp->mFrmOut = mpp_list_create(list_wraper_frame);
203
204 if (mpp->mInputTimeout == MPP_POLL_BUTT)
205 mpp->mInputTimeout = MPP_POLL_NON_BLOCK;
206
207 if (mpp->mOutputTimeout == MPP_POLL_BUTT)
208 mpp->mOutputTimeout = MPP_POLL_NON_BLOCK;
209
210 if (mpp->mCoding != MPP_VIDEO_CodingMJPEG) {
211 mpp_buffer_group_get_internal(&mpp->mPacketGroup, MPP_BUFFER_TYPE_ION | MPP_BUFFER_FLAGS_CACHABLE);
212 mpp_buffer_group_limit_config(mpp->mPacketGroup, 0, 3);
213
214 mpp->mInputTaskCount = 4;
215 mpp->mOutputTaskCount = 4;
216 }
217
218 mpp_task_queue_setup(mpp->mInputTaskQueue, mpp->mInputTaskCount);
219 mpp_task_queue_setup(mpp->mOutputTaskQueue, mpp->mOutputTaskCount);
220
221 mpp->mUsrInPort = mpp_task_queue_get_port(mpp->mInputTaskQueue, MPP_PORT_INPUT);
222 mpp->mUsrOutPort = mpp_task_queue_get_port(mpp->mOutputTaskQueue, MPP_PORT_OUTPUT);
223 mpp->mMppInPort = mpp_task_queue_get_port(mpp->mInputTaskQueue, MPP_PORT_OUTPUT);
224 mpp->mMppOutPort = mpp_task_queue_get_port(mpp->mOutputTaskQueue, MPP_PORT_INPUT);
225
226 mpp_dec_cfg_set_u32(mpp->mDecCfg, "base:disable_thread", mpp->mDisableThread);
227
228 MppDecInitCfg cfg = {
229 coding,
230 mpp,
231 mpp->mDecCfg,
232 };
233
234 ret = mpp_dec_init(&mpp->mDec, &cfg);
235 if (ret)
236 break;
237 ret = mpp_dec_start(mpp->mDec);
238 if (ret)
239 break;
240 mpp->mInitDone = 1;
241 } break;
242 case MPP_CTX_ENC : {
243 mpp->mPktOut = mpp_list_create(list_wraper_packet);
244 mpp->mFrmIn = mpp_list_create(list_wraper_frame);
245
246 if (mpp->mInputTimeout == MPP_POLL_BUTT)
247 mpp->mInputTimeout = MPP_POLL_BLOCK;
248
249 if (mpp->mOutputTimeout == MPP_POLL_BUTT)
250 mpp->mOutputTimeout = MPP_POLL_NON_BLOCK;
251
252 mpp_buffer_group_get_internal(&mpp->mPacketGroup, MPP_BUFFER_TYPE_ION);
253 mpp_buffer_group_get_internal(&mpp->mFrameGroup, MPP_BUFFER_TYPE_ION);
254
255 if (mpp->mInputTimeout == MPP_POLL_NON_BLOCK) {
256 mpp->mEncAyncIo = 1;
257
258 mpp->mInputTaskCount = check_frm_task_cnt_cap(coding);
259 if (mpp->mInputTaskCount == 1)
260 mpp->mInputTimeout = MPP_POLL_BLOCK;
261 }
262 mpp->mOutputTaskCount = 8;
263
264 mpp_task_queue_setup(mpp->mInputTaskQueue, mpp->mInputTaskCount);
265 mpp_task_queue_setup(mpp->mOutputTaskQueue, mpp->mOutputTaskCount);
266
267 mpp->mUsrInPort = mpp_task_queue_get_port(mpp->mInputTaskQueue, MPP_PORT_INPUT);
268 mpp->mUsrOutPort = mpp_task_queue_get_port(mpp->mOutputTaskQueue, MPP_PORT_OUTPUT);
269 mpp->mMppInPort = mpp_task_queue_get_port(mpp->mInputTaskQueue, MPP_PORT_OUTPUT);
270 mpp->mMppOutPort = mpp_task_queue_get_port(mpp->mOutputTaskQueue, MPP_PORT_INPUT);
271
272 MppEncInitCfg cfg = {
273 coding,
274 mpp->mInputTaskCount,
275 mpp,
276 };
277
278 ret = mpp_enc_init_v2(&mpp->mEnc, &cfg);
279 if (ret)
280 break;
281
282 if (mpp->mInputTimeout == MPP_POLL_NON_BLOCK) {
283 mpp->mEncAyncProc = 1;
284 ret = mpp_enc_start_async(mpp->mEnc);
285 } else {
286 ret = mpp_enc_start_v2(mpp->mEnc);
287 }
288
289 if (ret)
290 break;
291 mpp->mInitDone = 1;
292 } break;
293 default : {
294 mpp_err("Mpp error type %d\n", mpp->mType);
295 } break;
296 }
297
298 if (!mpp->mInitDone) {
299 mpp_err("error found on mpp initialization\n");
300 mpp_clear(mpp);
301 }
302
303 return ret;
304 }
305
mpp_clear(Mpp * mpp)306 void mpp_clear(Mpp *mpp)
307 {
308 if (!mpp)
309 return;
310
311 /* MUST: release listener here */
312 if (mpp->mFrameGroup)
313 mpp_buffer_group_set_callback((MppBufferGroupImpl *)mpp->mFrameGroup,
314 NULL, NULL);
315
316 if (mpp->mType == MPP_CTX_DEC) {
317 if (mpp->mDec) {
318 mpp_dec_stop(mpp->mDec);
319 mpp_dec_deinit(mpp->mDec);
320 mpp->mDec = NULL;
321 }
322 } else {
323 if (mpp->mEnc) {
324 mpp_enc_stop_v2(mpp->mEnc);
325 mpp_enc_deinit_v2(mpp->mEnc);
326 mpp->mEnc = NULL;
327 }
328 }
329
330 if (mpp->mInputTaskQueue) {
331 mpp_task_queue_deinit(mpp->mInputTaskQueue);
332 mpp->mInputTaskQueue = NULL;
333 }
334 if (mpp->mOutputTaskQueue) {
335 mpp_task_queue_deinit(mpp->mOutputTaskQueue);
336 mpp->mOutputTaskQueue = NULL;
337 }
338
339 mpp->mUsrInPort = NULL;
340 mpp->mUsrOutPort = NULL;
341 mpp->mMppInPort = NULL;
342 mpp->mMppOutPort = NULL;
343
344 if (mpp->mExtraPacket) {
345 mpp_packet_deinit(&mpp->mExtraPacket);
346 mpp->mExtraPacket = NULL;
347 }
348
349 if (mpp->mPktIn) {
350 mpp_list_destroy(mpp->mPktIn);
351 mpp->mPktIn = NULL;
352 }
353 if (mpp->mPktOut) {
354 mpp_list_destroy(mpp->mPktOut);
355 mpp->mPktOut = NULL;
356 }
357 if (mpp->mFrmIn) {
358 mpp_list_destroy(mpp->mFrmIn);
359 mpp->mFrmIn = NULL;
360 }
361 if (mpp->mFrmOut) {
362 mpp_list_destroy(mpp->mFrmOut);
363 mpp->mFrmOut = NULL;
364 }
365
366 if (mpp->mPacketGroup) {
367 mpp_buffer_group_put(mpp->mPacketGroup);
368 mpp->mPacketGroup = NULL;
369 }
370
371 if (mpp->mFrameGroup && !mpp->mExternalBufferMode) {
372 mpp_buffer_group_put(mpp->mFrameGroup);
373 mpp->mFrameGroup = NULL;
374 }
375
376 if (mpp->mKmpp) {
377 if (mpp->mKmpp->mApi && mpp->mKmpp->mApi->clear)
378 mpp->mKmpp->mApi->clear(mpp->mKmpp);
379
380 MPP_FREE(mpp->mKmpp);
381 }
382
383 if (mpp->mDecCfg) {
384 mpp_dec_cfg_deinit(mpp->mDecCfg);
385 mpp->mDecCfg = NULL;
386 }
387
388 mpp_dump_deinit(&mpp->mDump);
389 }
390
mpp_ctx_destroy(Mpp * mpp)391 MPP_RET mpp_ctx_destroy(Mpp *mpp)
392 {
393 if (!mpp)
394 return MPP_OK;
395
396 mpp_clear(mpp);
397 mpp_free(mpp);
398
399 return MPP_OK;
400 }
401
mpp_start(Mpp * mpp)402 MPP_RET mpp_start(Mpp *mpp)
403 {
404 if (!mpp) {
405 mpp_err_f("invalid input mpp pointer\n");
406 return MPP_ERR_NULL_PTR;
407 }
408 return MPP_OK;
409 }
410
mpp_stop(Mpp * mpp)411 MPP_RET mpp_stop(Mpp *mpp)
412 {
413 if (!mpp) {
414 mpp_err_f("invalid input mpp pointer\n");
415 return MPP_ERR_NULL_PTR;
416 }
417 return MPP_OK;
418 }
419
mpp_pause(Mpp * mpp)420 MPP_RET mpp_pause(Mpp *mpp)
421 {
422 if (!mpp) {
423 mpp_err_f("invalid input mpp pointer\n");
424 return MPP_ERR_NULL_PTR;
425 }
426 return MPP_OK;
427 }
428
mpp_resume(Mpp * mpp)429 MPP_RET mpp_resume(Mpp *mpp)
430 {
431 if (!mpp) {
432 mpp_err_f("invalid input mpp pointer\n");
433 return MPP_ERR_NULL_PTR;
434 }
435 return MPP_OK;
436 }
437
mpp_put_packet(Mpp * mpp,MppPacket packet)438 MPP_RET mpp_put_packet(Mpp *mpp, MppPacket packet)
439 {
440 if (!mpp) {
441 mpp_err_f("invalid input mpp pointer\n");
442 return MPP_ERR_NULL_PTR;
443 }
444
445 if (!mpp->mInitDone)
446 return MPP_ERR_INIT;
447
448 MPP_RET ret = MPP_NOK;
449 MppPollType timeout = mpp->mInputTimeout;
450 MppTask task_dequeue = NULL;
451 RK_U32 pkt_copy = 0;
452
453 if (mpp->mDisableThread) {
454 mpp_err_f("no thread decoding case MUST use mpi_decode interface\n");
455 return ret;
456 }
457
458 if (mpp->mExtraPacket) {
459 MppPacket extra = mpp->mExtraPacket;
460
461 mpp->mExtraPacket = NULL;
462 mpp_put_packet(mpp, extra);
463 }
464
465 /* non-jpeg mode - reserve extra task for incoming eos packet */
466 if (mpp->mInputTaskCount > 1) {
467 if (!mpp->mEosTask) {
468 /* handle eos packet on block mode */
469 ret = mpp_poll(mpp, MPP_PORT_INPUT, MPP_POLL_BLOCK);
470 if (ret < 0)
471 goto RET;
472
473 mpp_dequeue(mpp, MPP_PORT_INPUT, &mpp->mEosTask);
474 if (NULL == mpp->mEosTask) {
475 mpp_err_f("fail to reserve eos task\n");
476 ret = MPP_NOK;
477 goto RET;
478 }
479 }
480
481 if (mpp_packet_get_eos(packet)) {
482 mpp_assert(mpp->mEosTask);
483 task_dequeue = mpp->mEosTask;
484 mpp->mEosTask = NULL;
485 }
486 }
487
488 /* Use reserved task to send eos packet */
489 if (mpp->mInputTask && !task_dequeue) {
490 task_dequeue = mpp->mInputTask;
491 mpp->mInputTask = NULL;
492 }
493
494 if (NULL == task_dequeue) {
495 ret = mpp_poll(mpp, MPP_PORT_INPUT, timeout);
496 if (ret < 0) {
497 ret = MPP_ERR_BUFFER_FULL;
498 goto RET;
499 }
500
501 /* do not pull here to avoid block wait */
502 mpp_dequeue(mpp, MPP_PORT_INPUT, &task_dequeue);
503 if (NULL == task_dequeue) {
504 mpp_err_f("fail to get task on poll ret %d\n", ret);
505 ret = MPP_NOK;
506 goto RET;
507 }
508 }
509
510 if (NULL == mpp_packet_get_buffer(packet)) {
511 /* packet copy path */
512 MppPacket pkt_in = NULL;
513
514 mpp_packet_copy_init(&pkt_in, packet);
515 mpp_packet_set_length(packet, 0);
516 pkt_copy = 1;
517 packet = pkt_in;
518 ret = MPP_OK;
519 } else {
520 /* packet zero copy path */
521 timeout = MPP_POLL_BLOCK;
522 ret = MPP_OK;
523 }
524
525 /* setup task */
526 ret = mpp_task_meta_set_packet(task_dequeue, KEY_INPUT_PACKET, packet);
527 if (ret) {
528 mpp_err_f("set input frame to task ret %d\n", ret);
529 /* keep current task for next */
530 mpp->mInputTask = task_dequeue;
531 goto RET;
532 }
533
534 mpp_ops_dec_put_pkt(mpp->mDump, packet);
535
536 /* enqueue valid task to decoder */
537 ret = mpp_enqueue(mpp, MPP_PORT_INPUT, task_dequeue);
538 if (ret) {
539 mpp_err_f("enqueue ret %d\n", ret);
540 goto RET;
541 }
542
543 mpp->mPacketPutCount++;
544
545 if (timeout && !pkt_copy)
546 mpp_poll(mpp, MPP_PORT_INPUT, timeout);
547
548 RET:
549 /* wait enqueued task finished */
550 if (NULL == mpp->mInputTask) {
551 MPP_RET cnt = mpp_poll(mpp, MPP_PORT_INPUT, MPP_POLL_NON_BLOCK);
552 /* reserve one task for eos block mode */
553 if (cnt >= 0) {
554 mpp_dequeue(mpp, MPP_PORT_INPUT, &mpp->mInputTask);
555 mpp_assert(mpp->mInputTask);
556 }
557 }
558
559 return ret;
560 }
561
mpp_get_frame(Mpp * mpp,MppFrame * frame)562 MPP_RET mpp_get_frame(Mpp *mpp, MppFrame *frame)
563 {
564 MppFrame frm = NULL;
565
566 if (!mpp) {
567 mpp_err_f("invalid input mpp pointer\n");
568 return MPP_ERR_NULL_PTR;
569 }
570
571 if (!mpp->mInitDone)
572 return MPP_ERR_INIT;
573
574 mpp_mutex_cond_lock(&mpp->mFrmOut->cond_lock);
575
576 if (0 == mpp_list_size(mpp->mFrmOut)) {
577 if (mpp->mOutputTimeout) {
578 if (mpp->mOutputTimeout < 0) {
579 /* block wait */
580 mpp_list_wait(mpp->mFrmOut);
581 } else {
582 RK_S32 ret = mpp_list_wait_timed(mpp->mFrmOut, mpp->mOutputTimeout);
583 if (ret) {
584 if (ret == ETIMEDOUT) {
585 mpp_mutex_cond_unlock(&mpp->mFrmOut->cond_lock);
586 return MPP_ERR_TIMEOUT;
587 } else {
588 mpp_mutex_cond_unlock(&mpp->mFrmOut->cond_lock);
589 return MPP_NOK;
590 }
591 }
592 }
593 }
594 }
595
596 if (mpp_list_size(mpp->mFrmOut)) {
597 MppBuffer buffer;
598
599 mpp_list_del_at_head(mpp->mFrmOut, &frm, sizeof(frm));
600 mpp->mFrameGetCount++;
601 mpp_notify_flag(mpp, MPP_OUTPUT_DEQUEUE);
602
603 buffer = mpp_frame_get_buffer(frm);
604 if (buffer)
605 mpp_buffer_sync_ro_begin(buffer);
606 } else {
607 // NOTE: Add signal here is not efficient
608 // This is for fix bug of stucking on decoder parser thread
609 // When decoder parser thread is block by info change and enter waiting.
610 // There is no way to wake up parser thread to continue decoding.
611 // The put_packet only signal sem on may be it better to use sem on info
612 // change too.
613 mpp_mutex_cond_lock(&mpp->mPktIn->cond_lock);
614 if (mpp_list_size(mpp->mPktIn))
615 mpp_notify_flag(mpp, MPP_INPUT_ENQUEUE);
616 mpp_mutex_cond_unlock(&mpp->mPktIn->cond_lock);
617 }
618
619 *frame = frm;
620
621 // dump output
622 mpp_ops_dec_get_frm(mpp->mDump, frm);
623 mpp_mutex_cond_unlock(&mpp->mFrmOut->cond_lock);
624
625 return MPP_OK;
626 }
627
mpp_get_frame_noblock(Mpp * mpp,MppFrame * frame)628 MPP_RET mpp_get_frame_noblock(Mpp *mpp, MppFrame *frame)
629 {
630 MppFrame first = NULL;
631
632 if (!mpp) {
633 mpp_err_f("invalid input mpp pointer\n");
634 return MPP_ERR_NULL_PTR;
635 }
636
637 if (!mpp->mInitDone)
638 return MPP_ERR_INIT;
639
640 mpp_mutex_cond_lock(&mpp->mFrmOut->cond_lock);
641 if (mpp_list_size(mpp->mFrmOut)) {
642 mpp_list_del_at_head(mpp->mFrmOut, &first, sizeof(first));
643 mpp_buffer_sync_ro_begin(mpp_frame_get_buffer(first));
644 mpp->mFrameGetCount++;
645 }
646 mpp_mutex_cond_unlock(&mpp->mFrmOut->cond_lock);
647 *frame = first;
648
649 return MPP_OK;
650 }
651
mpp_decode(Mpp * mpp,MppPacket packet,MppFrame * frame)652 MPP_RET mpp_decode(Mpp *mpp, MppPacket packet, MppFrame *frame)
653 {
654 RK_U32 pkt_done = 0;
655 RK_S32 frm_rdy = 0;
656 MPP_RET ret = MPP_OK;
657
658 if (!mpp) {
659 mpp_err_f("invalid input mpp pointer\n");
660 return MPP_ERR_NULL_PTR;
661 }
662
663 if (!mpp->mDec)
664 return MPP_NOK;
665
666 if (!mpp->mInitDone)
667 return MPP_ERR_INIT;
668
669 /*
670 * If there is frame to return get the frame first
671 * But if the output mode is block then we need to send packet first
672 */
673 if (!mpp->mOutputTimeout) {
674 mpp_mutex_cond_lock(&mpp->mFrmOut->cond_lock);
675 if (mpp_list_size(mpp->mFrmOut)) {
676 MppBuffer buffer;
677
678 mpp_list_del_at_head(mpp->mFrmOut, frame, sizeof(*frame));
679 buffer = mpp_frame_get_buffer(*frame);
680 if (buffer)
681 mpp_buffer_sync_ro_begin(buffer);
682 mpp->mFrameGetCount++;
683 mpp_mutex_cond_unlock(&mpp->mFrmOut->cond_lock);
684 return MPP_OK;
685 }
686 mpp_mutex_cond_unlock(&mpp->mFrmOut->cond_lock);
687 }
688
689 do {
690 if (!pkt_done)
691 ret = mpp_dec_decode(mpp->mDec, packet);
692
693 /* check input packet finished or not */
694 if (!packet || !mpp_packet_get_length(packet))
695 pkt_done = 1;
696
697 /* always try getting frame */
698 mpp_mutex_cond_lock(&mpp->mFrmOut->cond_lock);
699 if (mpp_list_size(mpp->mFrmOut)) {
700 MppBuffer buffer;
701
702 mpp_list_del_at_head(mpp->mFrmOut, frame, sizeof(*frame));
703 buffer = mpp_frame_get_buffer(*frame);
704 if (buffer)
705 mpp_buffer_sync_ro_begin(buffer);
706 mpp->mFrameGetCount++;
707 frm_rdy = 1;
708 }
709 mpp_mutex_cond_unlock(&mpp->mFrmOut->cond_lock);
710
711 /* return on flow error */
712 if (ret < 0)
713 break;
714
715 /* return on output frame is ready */
716 if (frm_rdy) {
717 mpp_assert(ret > 0);
718 ret = MPP_OK;
719 break;
720 }
721
722 /* return when packet is send and it is a non-block call */
723 if (pkt_done) {
724 ret = MPP_OK;
725 break;
726 }
727
728 /* otherwise continue decoding and getting frame */
729 } while (1);
730
731 return ret;
732 }
733
mpp_put_frame(Mpp * mpp,MppFrame frame)734 MPP_RET mpp_put_frame(Mpp *mpp, MppFrame frame)
735 {
736 if (!mpp) {
737 mpp_err_f("invalid input mpp pointer\n");
738 return MPP_ERR_NULL_PTR;
739 }
740
741 if (!mpp->mInitDone)
742 return MPP_ERR_INIT;
743
744 mpp_dbg_pts("%p input frame pts %lld\n", mpp, mpp_frame_get_pts(frame));
745
746 if (mpp->mKmpp && mpp->mKmpp->mApi && mpp->mKmpp->mApi->put_frame)
747 return mpp->mKmpp->mApi->put_frame(mpp->mKmpp, frame);
748
749 if (mpp->mInputTimeout == MPP_POLL_NON_BLOCK) {
750 mpp_set_io_mode(mpp, MPP_IO_MODE_NORMAL);
751 return mpp_put_frame_async(mpp, frame);
752 }
753
754 MPP_RET ret = MPP_NOK;
755 MppStopwatch stopwatch = NULL;
756
757 if (mpp_debug & MPP_DBG_TIMING) {
758 mpp_frame_set_stopwatch_enable(frame, 1);
759 stopwatch = mpp_frame_get_stopwatch(frame);
760 }
761
762 mpp_stopwatch_record(stopwatch, NULL);
763 mpp_stopwatch_record(stopwatch, "put frame start");
764
765 if (mpp->mInputTask == NULL) {
766 mpp_stopwatch_record(stopwatch, "input port user poll");
767 /* poll input port for valid task */
768 ret = mpp_poll(mpp, MPP_PORT_INPUT, mpp->mInputTimeout);
769 if (ret < 0) {
770 if (mpp->mInputTimeout)
771 mpp_log_f("poll on set timeout %d ret %d\n", mpp->mInputTimeout, ret);
772 goto RET;
773 }
774
775 /* dequeue task for setup */
776 mpp_stopwatch_record(stopwatch, "input port user dequeue");
777 ret = mpp_dequeue(mpp, MPP_PORT_INPUT, &mpp->mInputTask);
778 if (ret || NULL == mpp->mInputTask) {
779 mpp_log_f("dequeue on set ret %d task %p\n", ret, mpp->mInputTask);
780 goto RET;
781 }
782 }
783
784 mpp_assert(mpp->mInputTask);
785
786 /* setup task */
787 ret = mpp_task_meta_set_frame(mpp->mInputTask, KEY_INPUT_FRAME, frame);
788 if (ret) {
789 mpp_log_f("set input frame to task ret %d\n", ret);
790 goto RET;
791 }
792
793 if (mpp_frame_has_meta(frame)) {
794 MppMeta meta = mpp_frame_get_meta(frame);
795 MppPacket packet = NULL;
796 MppBuffer md_info_buf = NULL;
797
798 mpp_meta_get_packet(meta, KEY_OUTPUT_PACKET, &packet);
799 if (packet) {
800 ret = mpp_task_meta_set_packet(mpp->mInputTask, KEY_OUTPUT_PACKET, packet);
801 if (ret) {
802 mpp_log_f("set output packet to task ret %d\n", ret);
803 goto RET;
804 }
805 }
806
807 mpp_meta_get_buffer(meta, KEY_MOTION_INFO, &md_info_buf);
808 if (md_info_buf) {
809 ret = mpp_task_meta_set_buffer(mpp->mInputTask, KEY_MOTION_INFO, md_info_buf);
810 if (ret) {
811 mpp_log_f("set output motion dection info ret %d\n", ret);
812 goto RET;
813 }
814 }
815 }
816
817 // dump input
818 mpp_ops_enc_put_frm(mpp->mDump, frame);
819
820 /* enqueue valid task to encoder */
821 mpp_stopwatch_record(stopwatch, "input port user enqueue");
822 ret = mpp_enqueue(mpp, MPP_PORT_INPUT, mpp->mInputTask);
823 if (ret) {
824 mpp_log_f("enqueue ret %d\n", ret);
825 goto RET;
826 }
827
828 mpp->mInputTask = NULL;
829 /* wait enqueued task finished */
830 mpp_stopwatch_record(stopwatch, "input port user poll");
831 ret = mpp_poll(mpp, MPP_PORT_INPUT, mpp->mInputTimeout);
832 if (ret < 0) {
833 if (mpp->mInputTimeout)
834 mpp_log_f("poll on get timeout %d ret %d\n", mpp->mInputTimeout, ret);
835 goto RET;
836 }
837
838 /* get previous enqueued task back */
839 mpp_stopwatch_record(stopwatch, "input port user dequeue");
840 ret = mpp_dequeue(mpp, MPP_PORT_INPUT, &mpp->mInputTask);
841 if (ret) {
842 mpp_log_f("dequeue on get ret %d\n", ret);
843 goto RET;
844 }
845
846 mpp_assert(mpp->mInputTask);
847 if (mpp->mInputTask) {
848 MppFrame frm_out = NULL;
849
850 mpp_task_meta_get_frame(mpp->mInputTask, KEY_INPUT_FRAME, &frm_out);
851 mpp_assert(frm_out == frame);
852 }
853
854 RET:
855 mpp_stopwatch_record(stopwatch, "put_frame finish");
856 mpp_frame_set_stopwatch_enable(frame, 0);
857 return ret;
858 }
859
mpp_get_packet(Mpp * mpp,MppPacket * packet)860 MPP_RET mpp_get_packet(Mpp *mpp, MppPacket *packet)
861 {
862 MppPacket pkt = NULL;
863
864 if (!mpp) {
865 mpp_err_f("invalid input mpp pointer\n");
866 return MPP_ERR_NULL_PTR;
867 }
868
869 if (!mpp->mInitDone)
870 return MPP_ERR_INIT;
871
872 if (mpp->mKmpp && mpp->mKmpp->mApi && mpp->mKmpp->mApi->get_packet)
873 return mpp->mKmpp->mApi->get_packet(mpp->mKmpp, packet);
874
875 if (mpp->mInputTimeout == MPP_POLL_NON_BLOCK) {
876 mpp_set_io_mode(mpp, MPP_IO_MODE_NORMAL);
877 return mpp_get_packet_async(mpp, packet);
878 }
879
880 MPP_RET ret = MPP_OK;
881 MppTask task = NULL;
882
883 ret = mpp_poll(mpp, MPP_PORT_OUTPUT, mpp->mOutputTimeout);
884 if (ret < 0) {
885 // NOTE: Do not treat poll failure as error. Just clear output
886 ret = MPP_OK;
887 *packet = NULL;
888 goto RET;
889 }
890
891 ret = mpp_dequeue(mpp, MPP_PORT_OUTPUT, &task);
892 if (ret || NULL == task) {
893 mpp_log_f("dequeue on get ret %d task %p\n", ret, task);
894 goto RET;
895 }
896
897 mpp_assert(task);
898
899 ret = mpp_task_meta_get_packet(task, KEY_OUTPUT_PACKET, packet);
900 if (ret) {
901 mpp_log_f("get output packet from task ret %d\n", ret);
902 goto RET;
903 }
904
905 pkt = *packet;
906 if (!pkt) {
907 mpp_log_f("get invalid task without output packet\n");
908 } else {
909 MppPacketImpl *impl = (MppPacketImpl *)pkt;
910 MppBuffer buf = impl->buffer;
911
912 if (buf) {
913 RK_U32 offset = (RK_U32)((char *)impl->pos - (char *)impl->data);
914
915 mpp_buffer_sync_ro_partial_begin(buf, offset, impl->length);
916 }
917
918 mpp_dbg_pts("%p output packet pts %lld\n", mpp, impl->pts);
919 }
920
921 // dump output
922 mpp_ops_enc_get_pkt(mpp->mDump, pkt);
923
924 ret = mpp_enqueue(mpp, MPP_PORT_OUTPUT, task);
925 if (ret)
926 mpp_log_f("enqueue on set ret %d\n", ret);
927 RET:
928
929 return ret;
930 }
931
mpp_put_frame_async(Mpp * mpp,MppFrame frame)932 MPP_RET mpp_put_frame_async(Mpp *mpp, MppFrame frame)
933 {
934 if (!mpp) {
935 mpp_err_f("invalid input mpp pointer\n");
936 return MPP_ERR_NULL_PTR;
937 }
938
939 if (NULL == mpp->mFrmIn)
940 return MPP_NOK;
941
942 if (mpp_mutex_cond_trylock(&mpp->mFrmIn->cond_lock))
943 return MPP_NOK;
944
945 /* NOTE: the max input queue length is 2 */
946 if (mpp_list_wait_le(mpp->mFrmIn, 10, 1)) {
947 mpp_mutex_cond_unlock(&mpp->mFrmIn->cond_lock);
948 return MPP_NOK;
949 }
950
951 mpp_list_add_at_tail(mpp->mFrmIn, &frame, sizeof(frame));
952 mpp->mFramePutCount++;
953
954 mpp_notify_flag(mpp, MPP_INPUT_ENQUEUE);
955 mpp_mutex_cond_unlock(&mpp->mFrmIn->cond_lock);
956
957 return MPP_OK;
958 }
959
mpp_get_packet_async(Mpp * mpp,MppPacket * packet)960 MPP_RET mpp_get_packet_async(Mpp *mpp, MppPacket *packet)
961 {
962 if (!mpp) {
963 mpp_err_f("invalid input mpp pointer\n");
964 return MPP_ERR_NULL_PTR;
965 }
966
967 mpp_mutex_cond_lock(&mpp->mPktOut->cond_lock);
968 *packet = NULL;
969 if (0 == mpp_list_size(mpp->mPktOut)) {
970 if (mpp->mOutputTimeout) {
971 if (mpp->mOutputTimeout < 0) {
972 /* block wait */
973 mpp_list_wait(mpp->mPktOut);
974 } else {
975 RK_S32 ret = mpp_list_wait_timed(mpp->mPktOut, mpp->mOutputTimeout);
976
977 if (ret) {
978 if (ret == ETIMEDOUT) {
979 mpp_mutex_cond_unlock(&mpp->mPktOut->cond_lock);
980 return MPP_ERR_TIMEOUT;
981 } else {
982 mpp_mutex_cond_unlock(&mpp->mPktOut->cond_lock);
983 return MPP_NOK;
984 }
985 }
986 }
987 } else {
988 /* NOTE: in non-block mode the sleep is to avoid user's dead loop */
989 msleep(1);
990 }
991 }
992
993 if (mpp_list_size(mpp->mPktOut)) {
994 MppPacket pkt = NULL;
995 MppPacketImpl *impl = NULL;
996 RK_U32 offset;
997
998 mpp_list_del_at_head(mpp->mPktOut, &pkt, sizeof(pkt));
999 mpp->mPacketGetCount++;
1000 mpp_notify_flag(mpp, MPP_OUTPUT_DEQUEUE);
1001
1002 *packet = pkt;
1003
1004 impl = (MppPacketImpl *)pkt;
1005 if (impl->buffer) {
1006 offset = (RK_U32)((char *)impl->pos - (char *)impl->data);
1007 mpp_buffer_sync_ro_partial_begin(impl->buffer, offset, impl->length);
1008 }
1009 } else {
1010 mpp_mutex_cond_lock(&mpp->mFrmIn->cond_lock);
1011 if (mpp_list_size(mpp->mFrmIn))
1012 mpp_notify_flag(mpp, MPP_INPUT_ENQUEUE);
1013 mpp_mutex_cond_unlock(&mpp->mFrmIn->cond_lock);
1014 mpp_mutex_cond_unlock(&mpp->mPktOut->cond_lock);
1015
1016 return MPP_NOK;
1017 }
1018 mpp_mutex_cond_unlock(&mpp->mPktOut->cond_lock);
1019
1020 return MPP_OK;
1021 }
1022
mpp_poll(Mpp * mpp,MppPortType type,MppPollType timeout)1023 MPP_RET mpp_poll(Mpp *mpp, MppPortType type, MppPollType timeout)
1024 {
1025 MppTaskQueue port = NULL;
1026 MPP_RET ret = MPP_NOK;
1027
1028 if (!mpp) {
1029 mpp_err_f("invalid input mpp pointer\n");
1030 return MPP_ERR_NULL_PTR;
1031 }
1032
1033 if (!mpp->mInitDone)
1034 return MPP_ERR_INIT;
1035
1036 mpp_set_io_mode(mpp, MPP_IO_MODE_TASK);
1037
1038 switch (type) {
1039 case MPP_PORT_INPUT : {
1040 port = mpp->mUsrInPort;
1041 } break;
1042 case MPP_PORT_OUTPUT : {
1043 port = mpp->mUsrOutPort;
1044 } break;
1045 default : {
1046 } break;
1047 }
1048
1049 if (port)
1050 ret = mpp_port_poll(port, timeout);
1051
1052 return ret;
1053 }
1054
mpp_dequeue(Mpp * mpp,MppPortType type,MppTask * task)1055 MPP_RET mpp_dequeue(Mpp *mpp, MppPortType type, MppTask *task)
1056 {
1057 MppTaskQueue port = NULL;
1058 RK_U32 notify_flag = 0;
1059 MPP_RET ret = MPP_NOK;
1060
1061 if (!mpp) {
1062 mpp_err_f("invalid input mpp pointer\n");
1063 return MPP_ERR_NULL_PTR;
1064 }
1065
1066 if (!mpp->mInitDone)
1067 return MPP_ERR_INIT;
1068
1069 mpp_set_io_mode(mpp, MPP_IO_MODE_TASK);
1070
1071 switch (type) {
1072 case MPP_PORT_INPUT : {
1073 port = mpp->mUsrInPort;
1074 notify_flag = MPP_INPUT_DEQUEUE;
1075 } break;
1076 case MPP_PORT_OUTPUT : {
1077 port = mpp->mUsrOutPort;
1078 notify_flag = MPP_OUTPUT_DEQUEUE;
1079 } break;
1080 default : {
1081 } break;
1082 }
1083
1084 if (port) {
1085 ret = mpp_port_dequeue(port, task);
1086 if (MPP_OK == ret)
1087 mpp_notify_flag(mpp, notify_flag);
1088 }
1089
1090 return ret;
1091 }
1092
mpp_enqueue(Mpp * mpp,MppPortType type,MppTask task)1093 MPP_RET mpp_enqueue(Mpp *mpp, MppPortType type, MppTask task)
1094 {
1095 MppTaskQueue port = NULL;
1096 RK_U32 notify_flag = 0;
1097 MPP_RET ret = MPP_NOK;
1098
1099 if (!mpp) {
1100 mpp_err_f("invalid input mpp pointer\n");
1101 return MPP_ERR_NULL_PTR;
1102 }
1103
1104 if (!mpp->mInitDone)
1105 return MPP_ERR_INIT;
1106
1107 mpp_set_io_mode(mpp, MPP_IO_MODE_TASK);
1108
1109 switch (type) {
1110 case MPP_PORT_INPUT : {
1111 port = mpp->mUsrInPort;
1112 notify_flag = MPP_INPUT_ENQUEUE;
1113 } break;
1114 case MPP_PORT_OUTPUT : {
1115 port = mpp->mUsrOutPort;
1116 notify_flag = MPP_OUTPUT_ENQUEUE;
1117 } break;
1118 default : {
1119 } break;
1120 }
1121
1122 if (port) {
1123 ret = mpp_port_enqueue(port, task);
1124 // if enqueue success wait up thread
1125 if (MPP_OK == ret)
1126 mpp_notify_flag(mpp, notify_flag);
1127 }
1128
1129 return ret;
1130 }
1131
mpp_set_io_mode(Mpp * mpp,MppIoMode mode)1132 void mpp_set_io_mode(Mpp *mpp, MppIoMode mode)
1133 {
1134 if (!mpp) {
1135 mpp_err_f("invalid input mpp pointer\n");
1136 return;
1137 }
1138
1139 mpp_assert(mode == MPP_IO_MODE_NORMAL || mode == MPP_IO_MODE_TASK);
1140
1141 if (mpp->mIoMode == MPP_IO_MODE_DEFAULT)
1142 mpp->mIoMode = mode;
1143 else if (mpp->mIoMode != mode) {
1144 static const char *iomode_2str[] = {
1145 "normal",
1146 "task queue",
1147 };
1148
1149 mpp_assert(mpp->mIoMode < MPP_IO_MODE_BUTT);
1150 mpp_assert(mode < MPP_IO_MODE_BUTT);
1151 mpp_err("can not reset io mode from %s to %s\n",
1152 iomode_2str[!!mpp->mIoMode], iomode_2str[!!mode]);
1153 }
1154 }
1155
mpp_control(Mpp * mpp,MpiCmd cmd,MppParam param)1156 MPP_RET mpp_control(Mpp *mpp, MpiCmd cmd, MppParam param)
1157 {
1158 MPP_RET ret = MPP_NOK;
1159
1160 if (!mpp) {
1161 mpp_err_f("invalid input mpp pointer\n");
1162 return MPP_ERR_NULL_PTR;
1163 }
1164
1165 mpp_ops_ctrl(mpp->mDump, cmd);
1166
1167 if (mpp->mKmpp && mpp->mKmpp->mApi && mpp->mKmpp->mApi->control)
1168 return mpp->mKmpp->mApi->control(mpp->mKmpp, cmd, param);
1169
1170 switch (cmd & CMD_MODULE_ID_MASK) {
1171 case CMD_MODULE_OSAL : {
1172 ret = mpp_control_osal(mpp, cmd, param);
1173 } break;
1174 case CMD_MODULE_MPP : {
1175 mpp_assert(cmd > MPP_CMD_BASE);
1176 mpp_assert(cmd < MPP_CMD_END);
1177
1178 ret = mpp_control_mpp(mpp, cmd, param);
1179 } break;
1180 case CMD_MODULE_CODEC : {
1181 switch (cmd & CMD_CTX_ID_MASK) {
1182 case CMD_CTX_ID_DEC : {
1183 mpp_assert(mpp->mType == MPP_CTX_DEC || mpp->mType == MPP_CTX_BUTT);
1184 mpp_assert(cmd > MPP_DEC_CMD_BASE);
1185 mpp_assert(cmd < MPP_DEC_CMD_END);
1186
1187 ret = mpp_control_dec(mpp, cmd, param);
1188 } break;
1189 case CMD_CTX_ID_ENC : {
1190 mpp_assert(mpp->mType == MPP_CTX_ENC);
1191 mpp_assert(cmd > MPP_ENC_CMD_BASE);
1192 mpp_assert(cmd < MPP_ENC_CMD_END);
1193
1194 ret = mpp_control_enc(mpp, cmd, param);
1195 } break;
1196 case CMD_CTX_ID_ISP : {
1197 mpp_assert(mpp->mType == MPP_CTX_ISP);
1198 ret = mpp_control_isp(mpp, cmd, param);
1199 } break;
1200 default : {
1201 mpp_assert(cmd > MPP_CODEC_CMD_BASE);
1202 mpp_assert(cmd < MPP_CODEC_CMD_END);
1203
1204 ret = mpp_control_codec(mpp, cmd, param);
1205 } break;
1206 }
1207 } break;
1208 default : {
1209 } break;
1210 }
1211
1212 if (ret)
1213 mpp_err("command %x param %p ret %d\n", cmd, param, ret);
1214
1215 return ret;
1216 }
1217
mpp_reset(Mpp * mpp)1218 MPP_RET mpp_reset(Mpp *mpp)
1219 {
1220 if (!mpp) {
1221 mpp_err_f("invalid input mpp pointer\n");
1222 return MPP_ERR_NULL_PTR;
1223 }
1224
1225 if (!mpp->mInitDone)
1226 return MPP_ERR_INIT;
1227
1228 if (mpp->mKmpp && mpp->mKmpp->mApi && mpp->mKmpp->mApi->reset)
1229 return mpp->mKmpp->mApi->reset(mpp->mKmpp);
1230
1231 mpp_ops_reset(mpp->mDump);
1232
1233 if (mpp->mType == MPP_CTX_DEC) {
1234 /*
1235 * On mp4 case extra data of sps/pps will be put at the beginning
1236 * If these packet was reset before they are send to decoder then
1237 * decoder can not get these important information to continue decoding
1238 * To avoid this case happen we need to save it on reset beginning
1239 * then restore it on reset end.
1240 */
1241 mpp_mutex_cond_lock(&mpp->mPktIn->cond_lock);
1242 while (mpp_list_size(mpp->mPktIn)) {
1243 MppPacket pkt = NULL;
1244
1245 mpp_list_del_at_head(mpp->mPktIn, &pkt, sizeof(pkt));
1246 mpp->mPacketGetCount++;
1247
1248 RK_U32 flags = mpp_packet_get_flag(pkt);
1249 if (flags & MPP_PACKET_FLAG_EXTRA_DATA) {
1250 if (mpp->mExtraPacket) {
1251 mpp_packet_deinit(&mpp->mExtraPacket);
1252 }
1253 mpp->mExtraPacket = pkt;
1254 } else {
1255 mpp_packet_deinit(&pkt);
1256 }
1257 }
1258 mpp_list_flush(mpp->mPktIn);
1259 mpp_mutex_cond_unlock(&mpp->mPktIn->cond_lock);
1260
1261 mpp_dec_reset(mpp->mDec);
1262
1263 mpp_mutex_cond_lock(&mpp->mFrmOut->cond_lock);
1264 mpp_list_flush(mpp->mFrmOut);
1265 mpp_mutex_cond_unlock(&mpp->mFrmOut->cond_lock);
1266
1267 mpp_port_awake(mpp->mUsrInPort);
1268 mpp_port_awake(mpp->mUsrOutPort);
1269 } else {
1270 mpp_enc_reset_v2(mpp->mEnc);
1271 }
1272
1273 return MPP_OK;
1274 }
1275
mpp_control_mpp(Mpp * mpp,MpiCmd cmd,MppParam param)1276 MPP_RET mpp_control_mpp(Mpp *mpp, MpiCmd cmd, MppParam param)
1277 {
1278 MPP_RET ret = MPP_OK;
1279
1280 if (!mpp) {
1281 mpp_err_f("invalid input mpp pointer\n");
1282 return MPP_ERR_NULL_PTR;
1283 }
1284
1285 switch (cmd) {
1286 case MPP_SET_INPUT_BLOCK :
1287 case MPP_SET_OUTPUT_BLOCK :
1288 case MPP_SET_INTPUT_BLOCK_TIMEOUT :
1289 case MPP_SET_OUTPUT_BLOCK_TIMEOUT : {
1290 MppPollType block = (param) ? *((MppPollType *)param) : MPP_POLL_NON_BLOCK;
1291
1292 if (block <= MPP_POLL_BUTT || block > MPP_POLL_MAX) {
1293 mpp_err("invalid output timeout type %d should be in range [%d, %d]\n",
1294 block, MPP_POLL_BUTT, MPP_POLL_MAX);
1295 ret = MPP_ERR_VALUE;
1296 break;
1297 }
1298 if (cmd == MPP_SET_INPUT_BLOCK || cmd == MPP_SET_INTPUT_BLOCK_TIMEOUT)
1299 mpp->mInputTimeout = block;
1300 else
1301 mpp->mOutputTimeout = block;
1302
1303 mpp_log("deprecated block control, use timeout control instead\n");
1304 } break;
1305
1306 case MPP_SET_DISABLE_THREAD: {
1307 mpp->mDisableThread = 1;
1308 } break;
1309
1310 case MPP_SET_INPUT_TIMEOUT:
1311 case MPP_SET_OUTPUT_TIMEOUT: {
1312 MppPollType timeout = (param) ? *((MppPollType *)param) : MPP_POLL_NON_BLOCK;
1313
1314 if (timeout <= MPP_POLL_BUTT || timeout > MPP_POLL_MAX) {
1315 mpp_err("invalid output timeout type %d should be in range [%d, %d]\n",
1316 timeout, MPP_POLL_BUTT, MPP_POLL_MAX);
1317 ret = MPP_ERR_VALUE;
1318 break;
1319 }
1320
1321 if (cmd == MPP_SET_INPUT_TIMEOUT)
1322 mpp->mInputTimeout = timeout;
1323 else
1324 mpp->mOutputTimeout = timeout;
1325 } break;
1326 case MPP_SET_VENC_INIT_KCFG: {
1327 KmppObj obj = param;
1328
1329 if (!obj) {
1330 mpp_err_f("ctrl %d invalid param %p\n", cmd, param);
1331 return MPP_ERR_VALUE;
1332 }
1333 mpp->mVencInitKcfg = obj;
1334 } break;
1335 case MPP_START : {
1336 mpp_start(mpp);
1337 } break;
1338 case MPP_STOP : {
1339 mpp_stop(mpp);
1340 } break;
1341
1342 case MPP_PAUSE : {
1343 mpp_pause(mpp);
1344 } break;
1345 case MPP_RESUME : {
1346 mpp_resume(mpp);
1347 } break;
1348
1349 default : {
1350 ret = MPP_NOK;
1351 } break;
1352 }
1353 return ret;
1354 }
1355
mpp_control_osal(Mpp * mpp,MpiCmd cmd,MppParam param)1356 MPP_RET mpp_control_osal(Mpp *mpp, MpiCmd cmd, MppParam param)
1357 {
1358 MPP_RET ret = MPP_NOK;
1359
1360 if (!mpp) {
1361 mpp_err_f("invalid input mpp pointer\n");
1362 return MPP_ERR_NULL_PTR;
1363 }
1364
1365 mpp_assert(cmd > MPP_OSAL_CMD_BASE);
1366 mpp_assert(cmd < MPP_OSAL_CMD_END);
1367
1368 (void)cmd;
1369 (void)param;
1370 return ret;
1371 }
1372
mpp_control_codec(Mpp * mpp,MpiCmd cmd,MppParam param)1373 MPP_RET mpp_control_codec(Mpp *mpp, MpiCmd cmd, MppParam param)
1374 {
1375 MPP_RET ret = MPP_NOK;
1376
1377 if (!mpp) {
1378 mpp_err_f("invalid input mpp pointer\n");
1379 return MPP_ERR_NULL_PTR;
1380 }
1381
1382 (void)cmd;
1383 (void)param;
1384 return ret;
1385 }
1386
mpp_control_dec(Mpp * mpp,MpiCmd cmd,MppParam param)1387 MPP_RET mpp_control_dec(Mpp *mpp, MpiCmd cmd, MppParam param)
1388 {
1389 MPP_RET ret = MPP_NOK;
1390
1391 if (!mpp) {
1392 mpp_err_f("invalid input mpp pointer\n");
1393 return MPP_ERR_NULL_PTR;
1394 }
1395
1396 switch (cmd) {
1397 case MPP_DEC_GET_THUMBNAIL_FRAME_INFO:
1398 case MPP_DEC_SET_FRAME_INFO: {
1399 ret = mpp_dec_control(mpp->mDec, cmd, param);
1400 } break;
1401 case MPP_DEC_SET_EXT_BUF_GROUP: {
1402 /*
1403 * NOTE: If frame buffer group is configured before decoder init
1404 * then the buffer limitation maybe not be correctly setup
1405 * without infomation from InfoChange frame.
1406 * And the thread signal connection may not be setup here. It
1407 * may have a bad effect on MPP efficiency.
1408 */
1409 if (!mpp->mInitDone) {
1410 mpp_err("WARNING: setup buffer group before decoder init\n");
1411 break;
1412 }
1413
1414 ret = MPP_OK;
1415 if (!param) {
1416 /* set to internal mode */
1417 if (mpp->mExternalBufferMode) {
1418 /* switch from external mode to internal mode */
1419 mpp_assert(mpp->mFrameGroup);
1420 mpp_buffer_group_set_callback((MppBufferGroupImpl *)mpp->mFrameGroup,
1421 NULL, NULL);
1422 mpp->mFrameGroup = NULL;
1423 } else {
1424 /* keep internal buffer mode cleanup old buffers */
1425 if (mpp->mFrameGroup)
1426 mpp_buffer_group_clear(mpp->mFrameGroup);
1427 }
1428
1429 mpp_dbg_info("using internal buffer group %p\n", mpp->mFrameGroup);
1430 mpp->mExternalBufferMode = 0;
1431 } else {
1432 /* set to external mode */
1433 if (mpp->mExternalBufferMode) {
1434 /* keep external buffer mode */
1435 if (mpp->mFrameGroup != param) {
1436 /* switch to new buffer group */
1437 mpp_assert(mpp->mFrameGroup);
1438 mpp_buffer_group_set_callback((MppBufferGroupImpl *)mpp->mFrameGroup,
1439 NULL, NULL);
1440 } else {
1441 /* keep old group the external group user should cleanup its old buffers */
1442 }
1443 } else {
1444 /* switch from intenal mode to external mode */
1445 if (mpp->mFrameGroup)
1446 mpp_buffer_group_put(mpp->mFrameGroup);
1447 }
1448
1449 mpp_dbg_info("using external buffer group %p\n", mpp->mFrameGroup);
1450
1451 mpp->mFrameGroup = (MppBufferGroup)param;
1452 mpp_buffer_group_set_callback((MppBufferGroupImpl *)mpp->mFrameGroup,
1453 mpp_notify_by_buffer_group, (void *)mpp);
1454 mpp->mExternalBufferMode = 1;
1455 mpp_notify_flag(mpp, MPP_DEC_NOTIFY_EXT_BUF_GRP_READY);
1456 }
1457 } break;
1458 case MPP_DEC_SET_INFO_CHANGE_READY: {
1459 mpp_dbg_info("set info change ready\n");
1460
1461 ret = mpp_dec_control(mpp->mDec, cmd, param);
1462 mpp_notify_flag(mpp, MPP_DEC_NOTIFY_INFO_CHG_DONE | MPP_DEC_NOTIFY_BUFFER_MATCH);
1463 } break;
1464 case MPP_DEC_SET_PRESENT_TIME_ORDER :
1465 case MPP_DEC_SET_PARSER_SPLIT_MODE :
1466 case MPP_DEC_SET_PARSER_FAST_MODE :
1467 case MPP_DEC_SET_IMMEDIATE_OUT :
1468 case MPP_DEC_SET_DISABLE_ERROR :
1469 case MPP_DEC_SET_DIS_ERR_CLR_MARK :
1470 case MPP_DEC_SET_ENABLE_DEINTERLACE :
1471 case MPP_DEC_SET_ENABLE_FAST_PLAY :
1472 case MPP_DEC_SET_ENABLE_MVC :
1473 case MPP_DEC_SET_DISABLE_DPB_CHECK :
1474 case MPP_DEC_SET_CODEC_MODE : {
1475 /*
1476 * These control may be set before mpp_init
1477 * When this case happen record the config and wait for decoder init
1478 */
1479 if (mpp->mDec) {
1480 ret = mpp_dec_control(mpp->mDec, cmd, param);
1481 return ret;
1482 }
1483
1484 ret = mpp_dec_set_cfg_by_cmd(mpp->mDecCfg, cmd, param);
1485 } break;
1486 case MPP_DEC_GET_STREAM_COUNT: {
1487 mpp_mutex_cond_lock(&mpp->mPktIn->cond_lock);
1488 *((RK_S32 *)param) = mpp_list_size(mpp->mPktIn);
1489 ret = MPP_OK;
1490 mpp_mutex_cond_unlock(&mpp->mPktIn->cond_lock);
1491 } break;
1492 case MPP_DEC_GET_VPUMEM_USED_COUNT :
1493 case MPP_DEC_SET_OUTPUT_FORMAT :
1494 case MPP_DEC_QUERY :
1495 case MPP_DEC_SET_MAX_USE_BUFFER_SIZE: {
1496 ret = mpp_dec_control(mpp->mDec, cmd, param);
1497 } break;
1498 case MPP_DEC_SET_CFG : {
1499 if (mpp->mDec)
1500 ret = mpp_dec_control(mpp->mDec, cmd, param);
1501 else if (param) {
1502 ret = (MPP_RET)kmpp_obj_update(mpp->mDecCfg, param);
1503 }
1504 } break;
1505 case MPP_DEC_GET_CFG : {
1506 if (mpp->mDec)
1507 ret = mpp_dec_control(mpp->mDec, cmd, param);
1508 else if (param) {
1509 ret = (MPP_RET)kmpp_obj_copy_entry(param, mpp->mDecCfg);
1510 }
1511 } break;
1512 default : {
1513 } break;
1514 }
1515 return ret;
1516 }
1517
mpp_control_enc(Mpp * mpp,MpiCmd cmd,MppParam param)1518 MPP_RET mpp_control_enc(Mpp *mpp, MpiCmd cmd, MppParam param)
1519 {
1520 if (!mpp) {
1521 mpp_err_f("invalid input mpp pointer\n");
1522 return MPP_ERR_NULL_PTR;
1523 }
1524
1525 mpp_assert(mpp->mEnc);
1526 return mpp_enc_control_v2(mpp->mEnc, cmd, param);
1527 }
1528
mpp_control_isp(Mpp * mpp,MpiCmd cmd,MppParam param)1529 MPP_RET mpp_control_isp(Mpp *mpp, MpiCmd cmd, MppParam param)
1530 {
1531 MPP_RET ret = MPP_NOK;
1532
1533 if (!mpp) {
1534 mpp_err_f("invalid input mpp pointer\n");
1535 return MPP_ERR_NULL_PTR;
1536 }
1537
1538 mpp_assert(cmd > MPP_ISP_CMD_BASE);
1539 mpp_assert(cmd < MPP_ISP_CMD_END);
1540
1541 (void)cmd;
1542 (void)param;
1543 return ret;
1544 }
1545
mpp_notify_flag(Mpp * mpp,RK_U32 flag)1546 MPP_RET mpp_notify_flag(Mpp *mpp, RK_U32 flag)
1547 {
1548 if (!mpp) {
1549 mpp_err_f("invalid input mpp pointer\n");
1550 return MPP_ERR_NULL_PTR;
1551 }
1552
1553 switch (mpp->mType) {
1554 case MPP_CTX_DEC : {
1555 return mpp_dec_notify(mpp->mDec, flag);
1556 } break;
1557 case MPP_CTX_ENC : {
1558 return mpp_enc_notify_v2(mpp->mEnc, flag);
1559 } break;
1560 default : {
1561 mpp_err("unsupport context type %d\n", mpp->mType);
1562 } break;
1563 }
1564 return MPP_NOK;
1565 }
1566
mpp_notify_group(Mpp * mpp,MppBufferGroup group)1567 MPP_RET mpp_notify_group(Mpp *mpp, MppBufferGroup group)
1568 {
1569 MPP_RET ret = MPP_NOK;
1570
1571 if (!mpp) {
1572 mpp_err_f("invalid input mpp pointer\n");
1573 return MPP_ERR_NULL_PTR;
1574 }
1575
1576 switch (mpp->mType) {
1577 case MPP_CTX_DEC : {
1578 if (group == mpp->mFrameGroup)
1579 ret = mpp_notify_flag(mpp, MPP_DEC_NOTIFY_BUFFER_VALID | MPP_DEC_NOTIFY_BUFFER_MATCH);
1580 } break;
1581 default : {
1582 } break;
1583 }
1584
1585 return ret;
1586 }
1587