xref: /rockchip-linux_mpp/mpp/mpp.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
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