xref: /rockchip-linux_mpp/mpp/codec/mpp_dec_normal.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_dec"
7 
8 #include <string.h>
9 
10 #include "mpp_buffer_impl.h"
11 
12 #include "mpp_dec_debug.h"
13 #include "mpp_dec_vproc.h"
14 #include "mpp_dec_normal.h"
15 #include "rk_hdr_meta_com.h"
16 
ts_cmp(void * priv,const struct list_head * a,const struct list_head * b)17 static RK_S32 ts_cmp(void *priv, const struct list_head *a, const struct list_head *b)
18 {
19     MppPktTs *ts1, *ts2;
20     (void)priv;
21 
22     ts1 = container_of(a, MppPktTs, link);
23     ts2 = container_of(b, MppPktTs, link);
24 
25     return ts1->pts - ts2->pts;
26 }
27 
28 /*
29  * return MPP_OK for not wait
30  * return MPP_NOK for wait
31  */
check_task_wait(MppDecImpl * dec,DecTask * task)32 static MPP_RET check_task_wait(MppDecImpl *dec, DecTask *task)
33 {
34     MPP_RET ret = MPP_OK;
35     RK_U32 notify = dec->parser_notify_flag;
36     RK_U32 last_wait = dec->parser_wait_flag;
37     RK_U32 curr_wait = task->wait.val;
38     RK_U32 wait_chg  = last_wait & (~curr_wait);
39     RK_U32 keep_notify = 0;
40 
41     do {
42         if (dec->reset_flag)
43             break;
44 
45         // NOTE: User control should always be processed
46         if (notify & MPP_DEC_CONTROL) {
47             keep_notify = notify & (~MPP_DEC_CONTROL);
48             break;
49         }
50 
51         // NOTE: When condition is not fulfilled check nofify flag again
52         if (!curr_wait || (curr_wait & notify))
53             break;
54 
55         // wait for condition
56         ret = MPP_NOK;
57     } while (0);
58 
59     dec_dbg_status("%p %08x -> %08x [%08x] notify %08x -> %s\n", dec,
60                    last_wait, curr_wait, wait_chg, notify, (ret) ? ("wait") : ("work"));
61 
62     dec->parser_status_flag = task->status.val;
63     dec->parser_wait_flag = task->wait.val;
64     dec->parser_notify_flag = keep_notify;
65 
66     if (ret) {
67         dec->parser_wait_count++;
68     } else {
69         dec->parser_work_count++;
70     }
71 
72     return ret;
73 }
74 
dec_release_task_in_port(MppPort port)75 static MPP_RET dec_release_task_in_port(MppPort port)
76 {
77     MPP_RET ret = MPP_OK;
78     MppPacket packet = NULL;
79     MppFrame frame = NULL;
80     MppTask mpp_task;
81 
82     do {
83         ret = mpp_port_poll(port, MPP_POLL_NON_BLOCK);
84         if (ret < 0)
85             break;
86 
87         ret = mpp_port_dequeue(port, &mpp_task);
88         if (ret || mpp_task == NULL)
89             break;
90 
91         packet = NULL;
92         frame = NULL;
93         ret = mpp_task_meta_get_frame(mpp_task, KEY_OUTPUT_FRAME,  &frame);
94         if (frame) {
95             mpp_frame_deinit(&frame);
96             frame = NULL;
97         }
98         ret = mpp_task_meta_get_packet(mpp_task, KEY_INPUT_PACKET, &packet);
99         if (packet && NULL == mpp_packet_get_buffer(packet)) {
100             mpp_packet_deinit(&packet);
101             packet = NULL;
102         }
103 
104         mpp_port_enqueue(port, mpp_task);
105         mpp_task = NULL;
106     } while (1);
107 
108     return ret;
109 }
110 
dec_release_input_packet(MppDecImpl * dec,RK_S32 force)111 static void dec_release_input_packet(MppDecImpl *dec, RK_S32 force)
112 {
113     if (dec->mpp_pkt_in) {
114         if (force || 0 == mpp_packet_get_length(dec->mpp_pkt_in)) {
115             mpp_packet_deinit(&dec->mpp_pkt_in);
116 
117             mpp_dec_callback(dec, MPP_DEC_EVENT_ON_PKT_RELEASE, dec->mpp_pkt_in);
118             dec->mpp_pkt_in = NULL;
119         }
120     }
121 }
122 
reset_parser_thread(Mpp * mpp,DecTask * task)123 static RK_U32 reset_parser_thread(Mpp *mpp, DecTask *task)
124 {
125     MppDecImpl *dec = (MppDecImpl *)mpp->mDec;
126     MppThread *hal = dec->thread_hal;
127     HalTaskGroup tasks  = dec->tasks;
128     MppBufSlots frame_slots  = dec->frame_slots;
129     MppBufSlots packet_slots = dec->packet_slots;
130     HalDecTask *task_dec = &task->info.dec;
131 
132     dec_dbg_reset("reset: parser reset start\n");
133     dec_dbg_reset("reset: parser wait hal proc reset start\n");
134 
135     dec_release_task_in_port(mpp->mMppInPort);
136 
137     mpp_assert(hal);
138 
139     mpp_thread_lock(hal, THREAD_WORK);
140     dec->hal_reset_post++;
141     mpp_thread_signal(hal, THREAD_WORK);
142     mpp_thread_unlock(hal, THREAD_WORK);
143 
144     sem_wait(&dec->hal_reset);
145 
146     dec_dbg_reset("reset: parser check hal proc task empty start\n");
147 
148     if (hal_task_check_empty(tasks, TASK_PROCESSING)) {
149         mpp_err_f("found task not processed put %d get %d\n",
150                   mpp->mTaskPutCount, mpp->mTaskGetCount);
151         mpp_abort();
152     }
153 
154     dec_dbg_reset("reset: parser check hal proc task empty done\n");
155 
156     // do parser reset process
157     {
158         RK_S32 index;
159         RK_U32 i;
160 
161         task->status.curr_task_rdy = 0;
162         task->status.prev_task_rdy = 1;
163         task_dec->valid = 0;
164         mpp_parser_reset(dec->parser);
165         mpp_hal_reset(dec->hal);
166         if (dec->vproc) {
167             dec_dbg_reset("reset: vproc reset start\n");
168             dec_vproc_reset(dec->vproc);
169             dec_dbg_reset("reset: vproc reset done\n");
170         }
171 
172         if (task->status.task_parsed_rdy) {
173             mpp_log("task no send to hal que must clr current frame hal status\n");
174             if (task_dec->output >= 0)
175                 mpp_buf_slot_clr_flag(frame_slots, task_dec->output, SLOT_HAL_OUTPUT);
176 
177             for (i = 0; i < MPP_ARRAY_ELEMS(task_dec->refer); i++) {
178                 index = task_dec->refer[i];
179                 if (index >= 0)
180                     mpp_buf_slot_clr_flag(frame_slots, index, SLOT_HAL_INPUT);
181             }
182             task->status.task_parsed_rdy = 0;
183         }
184 
185         dec_release_input_packet(dec, 1);
186 
187         while (MPP_OK == mpp_buf_slot_dequeue(frame_slots, &index, QUEUE_DISPLAY)) {
188             /* release extra ref in slot's MppBuffer */
189             MppBuffer buffer = NULL;
190             mpp_buf_slot_get_prop(frame_slots, index, SLOT_BUFFER, &buffer);
191             if (buffer)
192                 mpp_buffer_put(buffer);
193             mpp_buf_slot_clr_flag(frame_slots, index, SLOT_QUEUE_USE);
194         }
195 
196         if (dec->cfg->base.sort_pts) {
197             // flush
198             MppPktTs *ts, *pos;
199 
200             mpp_spinlock_lock(&dec->ts_lock);
201             list_for_each_entry_safe(ts, pos, &dec->ts_link, MppPktTs, link) {
202                 list_del_init(&ts->link);
203                 mpp_mem_pool_put_f(dec->ts_pool, ts);
204             }
205             mpp_spinlock_unlock(&dec->ts_lock);
206         }
207 
208         if (task->status.dec_pkt_copy_rdy) {
209             mpp_buf_slot_clr_flag(packet_slots, task_dec->input,  SLOT_HAL_INPUT);
210             task->status.dec_pkt_copy_rdy = 0;
211             task_dec->input = -1;
212         }
213 
214         // wait hal thread reset ready
215         if (task->wait.info_change)
216             mpp_log("reset at info change\n");
217 
218         task->status.task_parsed_rdy = 0;
219         // IMPORTANT: clear flag in MppDec context
220         dec->parser_status_flag = 0;
221         dec->parser_wait_flag = 0;
222     }
223 
224     dec_task_init(task);
225 
226     dec_dbg_reset("reset: parser reset all done\n");
227 
228     return MPP_OK;
229 }
230 
mpp_dec_put_task(Mpp * mpp,DecTask * task)231 static void mpp_dec_put_task(Mpp *mpp, DecTask *task)
232 {
233     MppDecImpl *dec = (MppDecImpl *)mpp->mDec;
234 
235     hal_task_hnd_set_info(task->hnd, &task->info);
236     mpp_thread_lock(dec->thread_hal, THREAD_WORK);
237     hal_task_hnd_set_status(task->hnd, TASK_PROCESSING);
238     mpp->mTaskPutCount++;
239     mpp_thread_signal(dec->thread_hal, THREAD_WORK);
240     mpp_thread_unlock(dec->thread_hal, THREAD_WORK);
241     task->hnd = NULL;
242 }
243 
reset_hal_thread(Mpp * mpp)244 static void reset_hal_thread(Mpp *mpp)
245 {
246     MppDecImpl *dec = (MppDecImpl *)mpp->mDec;
247     HalTaskGroup tasks = dec->tasks;
248     MppBufSlots frame_slots = dec->frame_slots;
249     HalDecTaskFlag flag;
250     RK_S32 index = -1;
251     HalTaskHnd  task = NULL;
252 
253     /* when hal thread reset output all frames */
254     flag.val = 0;
255     mpp_dec_flush(dec);
256 
257     mpp_thread_lock(dec->thread_hal, THREAD_OUTPUT);
258     while (MPP_OK == mpp_buf_slot_dequeue(frame_slots, &index, QUEUE_DISPLAY)) {
259         mpp_dec_put_frame(mpp, index, flag);
260         mpp_buf_slot_clr_flag(frame_slots, index, SLOT_QUEUE_USE);
261     }
262 
263     // Need to set processed task to idle status
264     while (MPP_OK == hal_task_get_hnd(tasks, TASK_PROC_DONE, &task)) {
265         if (task) {
266             hal_task_hnd_set_status(task, TASK_IDLE);
267             task = NULL;
268         }
269     }
270 
271     mpp_thread_unlock(dec->thread_hal, THREAD_OUTPUT);
272 }
273 
try_get_input_packet(Mpp * mpp,DecTask * task)274 static MPP_RET try_get_input_packet(Mpp *mpp, DecTask *task)
275 {
276     MppDecImpl *dec = (MppDecImpl *)mpp->mDec;
277     MppPort input = mpp->mMppInPort;
278     MppTask mpp_task = NULL;
279     MppPacket packet = NULL;
280     MPP_RET ret = MPP_OK;
281 
282     ret = mpp_port_poll(input, MPP_POLL_NON_BLOCK);
283     if (ret < 0) {
284         task->wait.dec_pkt_in = 1;
285         return MPP_NOK;
286     }
287 
288     ret = mpp_port_dequeue(input, &mpp_task);
289     mpp_assert(ret == MPP_OK && mpp_task);
290     mpp_task_meta_get_packet(mpp_task, KEY_INPUT_PACKET, &packet);
291     mpp_assert(packet);
292 
293     /* when it is copy buffer return packet right here */
294     if (NULL == mpp_packet_get_buffer(packet))
295         mpp_port_enqueue(input, mpp_task);
296 
297     dec->mpp_pkt_in = packet;
298     mpp->mPacketGetCount++;
299     dec->dec_in_pkt_count++;
300 
301     task->status.mpp_pkt_in_rdy = 1;
302     task->wait.dec_pkt_in = 0;
303 
304     return MPP_OK;
305 }
306 
try_proc_dec_task(Mpp * mpp,DecTask * task)307 static MPP_RET try_proc_dec_task(Mpp *mpp, DecTask *task)
308 {
309     MppDecImpl *dec = (MppDecImpl *)mpp->mDec;
310     HalTaskGroup tasks  = dec->tasks;
311     MppBufSlots frame_slots = dec->frame_slots;
312     MppBufSlots packet_slots = dec->packet_slots;
313     HalDecTask  *task_dec = &task->info.dec;
314     MppBuffer hal_buf_in = NULL;
315     MppBuffer hal_buf_out = NULL;
316     size_t stream_size = 0;
317     RK_S32 output = 0;
318 
319     /*
320      * 1. get task handle from hal for parsing one frame
321      */
322     if (!task->hnd) {
323         hal_task_get_hnd(tasks, TASK_IDLE, &task->hnd);
324         if (task->hnd) {
325             task->wait.task_hnd = 0;
326         } else {
327             task->wait.task_hnd = 1;
328             return MPP_NOK;
329         }
330     }
331 
332     /*
333      * 2. get packet for parser preparing
334      */
335     if (!dec->mpp_pkt_in && !task->status.curr_task_rdy) {
336         if (try_get_input_packet(mpp, task))
337             return MPP_NOK;
338 
339         mpp_assert(dec->mpp_pkt_in);
340 
341         dec_dbg_detail("detail: %p get pkt pts %llu len %d\n", dec,
342                        mpp_packet_get_pts(dec->mpp_pkt_in),
343                        mpp_packet_get_length(dec->mpp_pkt_in));
344     }
345 
346     /*
347      * 3. send packet data to parser for prepare
348      *
349      *    mpp_parser_prepare functioin input / output
350      *    input:    input MppPacket data from user
351      *    output:   one packet which contains one frame for hardware processing
352      *              output information will be stored in task_dec->input_packet
353      *              output data can be stored inside of parser.
354      *
355      *    NOTE:
356      *    1. Prepare process is controlled by need_split flag
357      *       If need_split flag is zero prepare function is just copy the input
358      *       packet to task_dec->input_packet
359      *       If need_split flag is non-zero prepare function will call split function
360      *       of different coding type and find the start and end of one frame. Then
361      *       copy data to task_dec->input_packet
362      *    2. On need_split mode if one input MppPacket contain multiple frame for
363      *       decoding one mpp_parser_prepare call will only frame for task. Then input
364      *       MppPacket->pos/length will be updated. The input MppPacket will not be
365      *       released until it is totally consumed.
366      *    3. On spliting frame if one frame contain multiple slices and these multiple
367      *       slices have different pts/dts the output frame will use the last pts/dts
368      *       as the output frame's pts/dts.
369      *
370      */
371     if (!task->status.curr_task_rdy) {
372         mpp_dbg_pts("input packet pts %lld\n", mpp_packet_get_pts(dec->mpp_pkt_in));
373 
374         mpp_clock_start(dec->clocks[DEC_PRS_PREPARE]);
375         mpp_parser_prepare(dec->parser, dec->mpp_pkt_in, task_dec);
376         mpp_clock_pause(dec->clocks[DEC_PRS_PREPARE]);
377         if (dec->cfg->base.sort_pts && task_dec->valid) {
378             task->ts_cur.pts = mpp_packet_get_pts(dec->mpp_pkt_in);
379             task->ts_cur.dts = mpp_packet_get_dts(dec->mpp_pkt_in);
380         }
381         dec_release_input_packet(dec, 0);
382     }
383 
384     task->status.curr_task_rdy = task_dec->valid;
385     /*
386     * We may find eos in prepare step and there will be no anymore vaild task generated.
387     * So here we try push eos task to hal, hal will push all frame to display then
388     * push a eos frame to tell all frame decoded
389     */
390     if (task_dec->flags.eos && !task_dec->valid)
391         mpp_dec_put_task(mpp, task);
392 
393     if (!task->status.curr_task_rdy)
394         return MPP_NOK;
395 
396     // NOTE: packet in task should be ready now
397     mpp_assert(task_dec->input_packet);
398 
399     /*
400      * 4. look for a unused packet slot index
401      */
402     if (task_dec->input < 0) {
403         mpp_buf_slot_get_unused(packet_slots, &task_dec->input);
404     }
405 
406     task->wait.dec_pkt_idx = (task_dec->input < 0);
407     if (task->wait.dec_pkt_idx)
408         return MPP_NOK;
409 
410     /*
411      * 5. malloc hardware buffer for the packet slot index
412      */
413     stream_size = mpp_packet_get_size(task_dec->input_packet);
414 
415     mpp_buf_slot_get_prop(packet_slots, task_dec->input, SLOT_BUFFER, &hal_buf_in);
416     if (NULL == hal_buf_in) {
417         mpp_buffer_get(mpp->mPacketGroup, &hal_buf_in, stream_size);
418         if (hal_buf_in) {
419             mpp_buf_slot_set_prop(packet_slots, task_dec->input, SLOT_BUFFER, hal_buf_in);
420             mpp_buffer_attach_dev(hal_buf_in, dec->dev);
421             mpp_buffer_put(hal_buf_in);
422         }
423     } else {
424         MppBufferImpl *buf = (MppBufferImpl *)hal_buf_in;
425         mpp_assert(buf->info.size >= stream_size);
426     }
427 
428     task->wait.dec_pkt_buf = (NULL == hal_buf_in);
429     if (task->wait.dec_pkt_buf)
430         return MPP_NOK;
431 
432     /*
433      * 6. copy prepared stream to hardware buffer
434      */
435     if (!task->status.dec_pkt_copy_rdy) {
436         void *src = mpp_packet_get_data(task_dec->input_packet);
437         size_t length = mpp_packet_get_length(task_dec->input_packet);
438 
439         mpp_buffer_write(hal_buf_in, 0, src, length);
440         mpp_buffer_sync_partial_end(hal_buf_in, 0, length);
441         mpp_buf_slot_set_flag(packet_slots, task_dec->input, SLOT_CODEC_READY);
442         mpp_buf_slot_set_flag(packet_slots, task_dec->input, SLOT_HAL_INPUT);
443         task->status.dec_pkt_copy_rdy = 1;
444     }
445 
446     /* 7.1 if not fast mode wait previous task done here */
447     if (!dec->parser_fast_mode) {
448         // wait previous task done
449         if (!task->status.prev_task_rdy) {
450             HalTaskHnd task_prev = NULL;
451             hal_task_get_hnd(tasks, TASK_PROC_DONE, &task_prev);
452             if (task_prev) {
453                 task->status.prev_task_rdy  = 1;
454                 task->wait.prev_task = 0;
455                 hal_task_hnd_set_status(task_prev, TASK_IDLE);
456                 task_prev = NULL;
457             } else {
458                 task->wait.prev_task = 1;
459                 return MPP_NOK;
460             }
461         }
462     }
463 
464     // for vp9 only wait all task is processed
465     if (task->wait.dec_all_done) {
466         if (!hal_task_check_empty(dec->tasks, TASK_PROCESSING))
467             task->wait.dec_all_done = 0;
468         else
469             return MPP_NOK;
470     }
471 
472     dec_dbg_detail("detail: %p check prev task pass\n", dec);
473 
474     /* too many frame delay in dispaly queue */
475     if (mpp->mFrmOut) {
476         task->wait.dis_que_full = (mpp_list_size(mpp->mFrmOut) > 4) ? 1 : 0;
477         if (task->wait.dis_que_full)
478             return MPP_ERR_DISPLAY_FULL;
479     }
480     dec_dbg_detail("detail: %p check mframes pass\n", dec);
481 
482     /* 7.3 wait for a unused slot index for decoder parse operation */
483     task->wait.dec_slot_idx = (mpp_slots_get_unused_count(frame_slots)) ? (0) : (1);
484     if (task->wait.dec_slot_idx)
485         return MPP_ERR_BUFFER_FULL;
486 
487     /*
488      * 8. send packet data to parser
489      *
490      *    parser prepare functioin input / output
491      *    input:    packet data
492      *    output:   dec task output information (with dxva output slot)
493      *              buffer slot usage informatioin
494      *
495      *    NOTE:
496      *    1. dpb slot will be set internally in parser process.
497      *    2. parse function need to set valid flag when one frame is ready.
498      *    3. if packet size is zero then next packet is needed.
499      *    4. detect whether output index has MppBuffer and task valid
500      */
501     if (!task->status.task_parsed_rdy) {
502         mpp_clock_start(dec->clocks[DEC_PRS_PARSE]);
503         mpp_parser_parse(dec->parser, task_dec);
504         mpp_clock_pause(dec->clocks[DEC_PRS_PARSE]);
505         task->status.task_parsed_rdy = 1;
506     }
507 
508     if (task_dec->output < 0 || !task_dec->valid) {
509         /*
510          * We may meet an eos in parser step and there will be no anymore vaild
511          * task generated. So here we try push eos task to hal, hal will push
512          * all frame(s) to display, a frame of them with a eos flag will be
513          * used to inform that all frame have decoded
514          */
515         if (task_dec->flags.eos) {
516             mpp_dec_put_task(mpp, task);
517         } else {
518             hal_task_hnd_set_status(task->hnd, TASK_IDLE);
519             task->hnd = NULL;
520         }
521 
522         if (task->status.dec_pkt_copy_rdy) {
523             mpp_buf_slot_clr_flag(packet_slots, task_dec->input,  SLOT_HAL_INPUT);
524             task->status.dec_pkt_copy_rdy = 0;
525         }
526         task->status.curr_task_rdy  = 0;
527         task->status.task_parsed_rdy = 0;
528         dec_task_info_init(&task->info);
529         return MPP_NOK;
530     }
531     dec_dbg_detail("detail: %p check output index pass\n", dec);
532 
533     /*
534      * 9. parse local task and slot to check whether new buffer or info change is needed.
535      *
536      * detect info change from frame slot
537      */
538     if (mpp_buf_slot_is_changed(frame_slots)) {
539         if (!task->status.info_task_gen_rdy) {
540             RK_U32 eos = task_dec->flags.eos;
541 
542             // NOTE: info change should not go with eos flag
543             task_dec->flags.info_change = 1;
544             task_dec->flags.eos = 0;
545             mpp_dec_put_task(mpp, task);
546             task_dec->flags.eos = eos;
547 
548             task->status.info_task_gen_rdy = 1;
549             return MPP_ERR_STREAM;
550         }
551         dec->info_updated = 0;
552     }
553 
554     task->wait.info_change = mpp_buf_slot_is_changed(frame_slots);
555     if (task->wait.info_change) {
556         return MPP_ERR_STREAM;
557     } else {
558         task->status.info_task_gen_rdy = 0;
559         task_dec->flags.info_change = 0;
560         // NOTE: check the task must be ready
561         mpp_assert(task->hnd);
562     }
563 
564     /* 10. whether the frame buffer group is internal or external */
565     if (NULL == mpp->mFrameGroup) {
566         mpp_log("mpp_dec use internal frame buffer group\n");
567         mpp_buffer_group_get_internal(&mpp->mFrameGroup, MPP_BUFFER_TYPE_ION | MPP_BUFFER_FLAGS_CACHABLE);
568     }
569 
570     /* 10.1 look for a unused hardware buffer for output */
571     if (mpp->mFrameGroup) {
572         RK_S32 unused = mpp_buffer_group_unused(mpp->mFrameGroup);
573 
574         // NOTE: When dec post-process is enabled reserve 2 buffer for it.
575         task->wait.dec_pic_unusd = (dec->vproc) ? (unused < 3) : (unused < 1);
576         if (task->wait.dec_pic_unusd)
577             return MPP_ERR_BUFFER_FULL;
578     }
579     dec_dbg_detail("detail: %p check frame group count pass\n", dec);
580 
581     /*
582      * 11. do buffer operation according to usage information
583      *
584      *    possible case:
585      *    a. normal case
586      *       - wait and alloc(or fetch) a normal frame buffer
587      *    b. field mode case
588      *       - two field may reuse a same buffer, no need to alloc
589      *    c. info change case
590      *       - need buffer in different side, need to send a info change
591      *         frame to hal loop.
592      */
593     output = task_dec->output;
594     mpp_buf_slot_get_prop(frame_slots, output, SLOT_BUFFER, &hal_buf_out);
595     if (NULL == hal_buf_out) {
596         MppFrame mframe = NULL;
597         mpp_buf_slot_get_prop(frame_slots, output,
598                               SLOT_FRAME_PTR, &mframe);
599         size_t size = mpp_buf_slot_get_size(frame_slots);
600 
601         if (mframe && mpp_frame_get_thumbnail_en(mframe) == MPP_FRAME_THUMBNAIL_ONLY) {
602             // only for 8K thumbnail downscale to 4K 8bit mode
603             RK_U32 downscale_width = mpp_frame_get_width(mframe) / 2;
604             RK_U32 downscale_height = mpp_frame_get_height(mframe) / 2;
605 
606             size = downscale_width * downscale_height * 3 / 2;
607         }
608         mpp_buffer_get(mpp->mFrameGroup, &hal_buf_out, size);
609         if (hal_buf_out)
610             mpp_buf_slot_set_prop(frame_slots, output, SLOT_BUFFER,
611                                   hal_buf_out);
612     }
613 
614     dec_dbg_detail("detail: %p check output buffer %p\n", dec, hal_buf_out);
615 
616     {
617         MppFrame mframe = NULL;
618 
619         mpp_buf_slot_get_prop(frame_slots, output, SLOT_FRAME_PTR, &mframe);
620 
621         if (MPP_FRAME_FMT_IS_HDR(mpp_frame_get_fmt(mframe)) &&
622             dec->cfg->base.enable_hdr_meta) {
623             fill_hdr_meta_to_frame(mframe, dec->coding);
624         }
625     }
626 
627     // update codec info
628     if (!dec->info_updated && dec->dev) {
629         MppFrame frame = NULL;
630 
631         mpp_buf_slot_get_prop(frame_slots, output, SLOT_FRAME_PTR, &frame);
632         update_dec_hal_info(dec, frame);
633         dec->info_updated = 1;
634     }
635 
636     task->wait.dec_pic_match = (NULL == hal_buf_out);
637     if (task->wait.dec_pic_match)
638         return MPP_NOK;
639 
640     if (dec->cfg->base.sort_pts) {
641         MppFrame frame = NULL;
642         MppPktTs *pkt_ts = (MppPktTs *)mpp_mem_pool_get_f(dec->ts_pool);
643 
644         mpp_assert(pkt_ts);
645         mpp_buf_slot_get_prop(frame_slots, output, SLOT_FRAME_PTR, &frame);
646         pkt_ts->pts = task->ts_cur.pts;
647         pkt_ts->dts = task->ts_cur.dts;
648         INIT_LIST_HEAD(&pkt_ts->link);
649         if (frame && mpp_frame_get_pts(frame) == pkt_ts->pts) {
650             mpp_spinlock_lock(&dec->ts_lock);
651             list_add_tail(&pkt_ts->link, &dec->ts_link);
652             list_sort(NULL, &dec->ts_link, ts_cmp);
653             mpp_spinlock_unlock(&dec->ts_lock);
654         }
655     }
656 
657     /* generating registers table */
658     mpp_clock_start(dec->clocks[DEC_HAL_GEN_REG]);
659     mpp_hal_reg_gen(dec->hal, &task->info);
660     mpp_clock_pause(dec->clocks[DEC_HAL_GEN_REG]);
661 
662     /* send current register set to hardware */
663     mpp_clock_start(dec->clocks[DEC_HW_START]);
664     mpp_hal_hw_start(dec->hal, &task->info);
665     mpp_clock_pause(dec->clocks[DEC_HW_START]);
666 
667     /*
668      * 12. send dxva output information and buffer information to hal thread
669      *    combinate video codec dxva output and buffer information
670      */
671     mpp_dec_put_task(mpp, task);
672 
673     task->wait.dec_all_done = (dec->parser_fast_mode &&
674                                task_dec->flags.wait_done) ? 1 : 0;
675 
676     task->status.dec_pkt_copy_rdy  = 0;
677     task->status.curr_task_rdy  = 0;
678     task->status.task_parsed_rdy = 0;
679     task->status.prev_task_rdy   = 0;
680     dec_task_info_init(&task->info);
681 
682     dec_dbg_detail("detail: %p one task ready\n", dec);
683 
684     return MPP_OK;
685 }
686 
mpp_dec_parser_thread(void * data)687 void *mpp_dec_parser_thread(void *data)
688 {
689     Mpp *mpp = (Mpp*)data;
690     MppDecImpl *dec = (MppDecImpl *)mpp->mDec;
691     MppThread *parser = dec->thread_parser;
692     MppBufSlots packet_slots = dec->packet_slots;
693 
694     DecTask task;
695     HalDecTask  *task_dec = &task.info.dec;
696 
697     dec_task_init(&task);
698 
699     mpp_clock_start(dec->clocks[DEC_PRS_TOTAL]);
700 
701     while (1) {
702         mpp_thread_lock(parser, THREAD_WORK);
703         if (MPP_THREAD_RUNNING != mpp_thread_get_status(parser, THREAD_WORK)) {
704             mpp_thread_unlock(parser, THREAD_WORK);
705             break;
706         }
707 
708         /*
709          * parser thread need to wait at cases below:
710          * 1. no task slot for output
711          * 2. no packet for parsing
712          * 3. info change on progress
713          * 3. no buffer on analyzing output task
714          */
715         if (check_task_wait(dec, &task)) {
716             mpp_clock_start(dec->clocks[DEC_PRS_WAIT]);
717             mpp_thread_wait(parser, THREAD_WORK);
718             mpp_clock_pause(dec->clocks[DEC_PRS_WAIT]);
719         }
720         mpp_thread_unlock(parser, THREAD_WORK);
721 
722         // process user control
723         if (dec->cmd_send != dec->cmd_recv) {
724             dec_dbg_detail("ctrl proc %d cmd %08x\n", dec->cmd_recv, dec->cmd);
725             sem_wait(&dec->cmd_start);
726             *dec->cmd_ret = mpp_dec_proc_cfg(dec, dec->cmd, dec->param);
727             dec->cmd_recv++;
728             dec_dbg_detail("ctrl proc %d done send %d\n", dec->cmd_recv,
729                            dec->cmd_send);
730             mpp_assert(dec->cmd_send == dec->cmd_send);
731             dec->param = NULL;
732             dec->cmd = (MpiCmd)0;
733             dec->cmd_ret = NULL;
734             sem_post(&dec->cmd_done);
735             continue;
736         }
737 
738         if (dec->reset_flag) {
739             reset_parser_thread(mpp, &task);
740 
741             mpp_thread_lock(parser, THREAD_CONTROL);
742             dec->reset_flag = 0;
743             sem_post(&dec->parser_reset);
744             mpp_thread_unlock(parser, THREAD_CONTROL);
745             continue;
746         }
747 
748         // NOTE: ignore return value here is to fast response to reset.
749         // Otherwise we can loop all dec task until it is failed.
750         mpp_clock_start(dec->clocks[DEC_PRS_PROC]);
751         try_proc_dec_task(mpp, &task);
752         mpp_clock_pause(dec->clocks[DEC_PRS_PROC]);
753     }
754 
755     mpp_clock_pause(dec->clocks[DEC_PRS_TOTAL]);
756 
757     mpp_dbg_info("mpp_dec_parser_thread is going to exit\n");
758     if (task.hnd && task_dec->valid) {
759         mpp_buf_slot_set_flag(packet_slots, task_dec->input, SLOT_CODEC_READY);
760         mpp_buf_slot_set_flag(packet_slots, task_dec->input, SLOT_HAL_INPUT);
761         mpp_buf_slot_clr_flag(packet_slots, task_dec->input, SLOT_HAL_INPUT);
762     }
763     mpp_buffer_group_clear(mpp->mPacketGroup);
764     dec_release_task_in_port(mpp->mMppInPort);
765     mpp_dbg_info("mpp_dec_parser_thread exited\n");
766     return NULL;
767 }
768 
mpp_dec_hal_thread(void * data)769 void *mpp_dec_hal_thread(void *data)
770 {
771     Mpp *mpp = (Mpp*)data;
772     MppDecImpl *dec = (MppDecImpl *)mpp->mDec;
773     MppThread *hal = dec->thread_hal;
774     HalTaskGroup tasks = dec->tasks;
775     MppBufSlots frame_slots = dec->frame_slots;
776     MppBufSlots packet_slots = dec->packet_slots;
777 
778     HalTaskHnd  task = NULL;
779     HalTaskInfo task_info;
780     HalDecTask  *task_dec = &task_info.dec;
781     RK_U32 i;
782 
783     mpp_clock_start(dec->clocks[DEC_HAL_TOTAL]);
784 
785     while (1) {
786         /* hal thread wait for dxva interface intput first */
787         mpp_thread_lock(hal, THREAD_WORK);
788         if (MPP_THREAD_RUNNING != mpp_thread_get_status(hal, THREAD_WORK)) {
789             mpp_thread_unlock(hal, THREAD_WORK);
790             break;
791         }
792 
793         if (hal_task_get_hnd(tasks, TASK_PROCESSING, &task)) {
794             // process all task then do reset process
795             if (dec->hal_reset_post != dec->hal_reset_done) {
796                 dec_dbg_reset("reset: hal reset start\n");
797                 reset_hal_thread(mpp);
798                 dec_dbg_reset("reset: hal reset done\n");
799                 dec->hal_reset_done++;
800                 sem_post(&dec->hal_reset);
801                 mpp_thread_unlock(hal, THREAD_WORK);
802                 continue;
803             }
804 
805             mpp_dec_notify(dec, MPP_DEC_NOTIFY_TASK_ALL_DONE);
806             mpp_clock_start(dec->clocks[DEC_HAL_WAIT]);
807             mpp_thread_wait(hal, THREAD_WORK);
808             mpp_clock_pause(dec->clocks[DEC_HAL_WAIT]);
809             mpp_thread_unlock(hal, THREAD_WORK);
810             continue;
811         }
812         mpp_thread_unlock(hal, THREAD_WORK);
813 
814         if (task) {
815             RK_U32 notify_flag = MPP_DEC_NOTIFY_TASK_HND_VALID;
816 
817             mpp_clock_start(dec->clocks[DEC_HAL_PROC]);
818             mpp->mTaskGetCount++;
819 
820             hal_task_hnd_get_info(task, &task_info);
821 
822             /*
823              * check info change flag
824              * if this is a frame with that flag, only output an empty
825              * MppFrame without any image data for info change.
826              */
827             if (task_dec->flags.info_change) {
828                 mpp_dec_flush(dec);
829                 mpp_dec_push_display(mpp, task_dec->flags);
830                 mpp_dec_put_frame(mpp, task_dec->output, task_dec->flags);
831 
832                 hal_task_hnd_set_status(task, TASK_IDLE);
833                 task = NULL;
834                 mpp_dec_notify(dec, notify_flag);
835                 mpp_clock_pause(dec->clocks[DEC_HAL_PROC]);
836                 continue;
837             }
838             /*
839              * check eos task
840              * if this task is invalid while eos flag is set, we will
841              * flush display queue then push the eos frame to info that
842              * all frames have decoded.
843              */
844             if (task_dec->flags.eos &&
845                 (!task_dec->valid || task_dec->output < 0)) {
846                 mpp_dec_push_display(mpp, task_dec->flags);
847                 /*
848                  * Use -1 as invalid buffer slot index.
849                  * Reason: the last task maybe is a empty task with eos flag
850                  * only but this task may go through vproc process also. We need
851                  * create a buffer slot index for it.
852                  */
853                 mpp_dec_put_frame(mpp, -1, task_dec->flags);
854 
855                 hal_task_hnd_set_status(task, TASK_IDLE);
856                 task = NULL;
857                 mpp_dec_notify(dec, notify_flag);
858                 mpp_clock_pause(dec->clocks[DEC_HAL_PROC]);
859                 continue;
860             }
861 
862             mpp_clock_start(dec->clocks[DEC_HW_WAIT]);
863             mpp_hal_hw_wait(dec->hal, &task_info);
864             mpp_clock_pause(dec->clocks[DEC_HW_WAIT]);
865             dec->dec_hw_run_count++;
866 
867             /*
868              * when hardware decoding is done:
869              * 1. clear decoding flag (mark buffer is ready)
870              * 2. use get_display to get a new frame with buffer
871              * 3. add frame to output list
872              * repeat 2 and 3 until not frame can be output
873              */
874             mpp_buf_slot_clr_flag(packet_slots, task_dec->input,
875                                   SLOT_HAL_INPUT);
876 
877             hal_task_hnd_set_status(task, (dec->parser_fast_mode) ?
878                                     (TASK_IDLE) : (TASK_PROC_DONE));
879 
880             if (dec->parser_fast_mode)
881                 notify_flag |= MPP_DEC_NOTIFY_TASK_HND_VALID;
882             else
883                 notify_flag |= MPP_DEC_NOTIFY_TASK_PREV_DONE;
884 
885             task = NULL;
886 
887             if (task_dec->output >= 0)
888                 mpp_buf_slot_clr_flag(frame_slots, task_dec->output, SLOT_HAL_OUTPUT);
889 
890             for (i = 0; i < MPP_ARRAY_ELEMS(task_dec->refer); i++) {
891                 RK_S32 index = task_dec->refer[i];
892                 if (index >= 0)
893                     mpp_buf_slot_clr_flag(frame_slots, index, SLOT_HAL_INPUT);
894             }
895             if (task_dec->flags.eos)
896                 mpp_dec_flush(dec);
897             mpp_dec_push_display(mpp, task_dec->flags);
898 
899             mpp_dec_notify(dec, notify_flag);
900             mpp_clock_pause(dec->clocks[DEC_HAL_PROC]);
901         }
902     }
903 
904     mpp_clock_pause(dec->clocks[DEC_HAL_TOTAL]);
905 
906     mpp_assert(mpp->mTaskPutCount == mpp->mTaskGetCount);
907     mpp_dbg_info("mpp_dec_hal_thread exited\n");
908     return NULL;
909 }
910 
mpp_dec_advanced_thread(void * data)911 void *mpp_dec_advanced_thread(void *data)
912 {
913     Mpp *mpp = (Mpp*)data;
914     MppDecImpl *dec = (MppDecImpl *)mpp->mDec;
915     MppBufSlots frame_slots = dec->frame_slots;
916     MppBufSlots packet_slots = dec->packet_slots;
917     MppThread *thd_dec  = dec->thread_parser;
918     DecTask task;   /* decoder task */
919     DecTask *pTask = &task;
920     dec_task_init(pTask);
921     HalDecTask  *task_dec = &pTask->info.dec;
922     MppPort input  = mpp->mMppInPort;
923     MppPort output = mpp->mMppOutPort;
924     MppTask mpp_task = NULL;
925     MPP_RET ret = MPP_OK;
926     MppFrame frame = NULL;
927     MppPacket packet = NULL;
928 
929     while (1) {
930         mpp_thread_lock(thd_dec, THREAD_WORK);
931         if (MPP_THREAD_RUNNING != mpp_thread_get_status(thd_dec, THREAD_WORK)) {
932             mpp_thread_unlock(thd_dec, THREAD_WORK);
933             break;
934         }
935 
936         if (check_task_wait(dec, &task))
937             mpp_thread_wait(thd_dec, THREAD_WORK);
938         mpp_thread_unlock(thd_dec, THREAD_WORK);
939 
940         // process user control
941         if (dec->cmd_send != dec->cmd_recv) {
942             dec_dbg_detail("ctrl proc %d cmd %08x\n", dec->cmd_recv, dec->cmd);
943             sem_wait(&dec->cmd_start);
944             *dec->cmd_ret = mpp_dec_proc_cfg(dec, dec->cmd, dec->param);
945             dec->cmd_recv++;
946             dec_dbg_detail("ctrl proc %d done send %d\n", dec->cmd_recv,
947                            dec->cmd_send);
948             mpp_assert(dec->cmd_send == dec->cmd_send);
949             dec->param = NULL;
950             dec->cmd = (MpiCmd)0;
951             dec->cmd_ret = NULL;
952             sem_post(&dec->cmd_done);
953             continue;
954         }
955 
956         // 1. check task in
957         dec_dbg_detail("mpp_pkt_in_rdy %d\n", task.status.mpp_pkt_in_rdy);
958         if (!task.status.mpp_pkt_in_rdy) {
959             ret = mpp_port_poll(input, MPP_POLL_NON_BLOCK);
960             if (ret < 0) {
961                 task.wait.dec_pkt_in = 1;
962                 continue;
963             }
964 
965             dec_dbg_detail("poll ready\n");
966 
967             task.status.mpp_pkt_in_rdy = 1;
968             task.wait.dec_pkt_in = 0;
969 
970             ret = mpp_port_dequeue(input, &mpp_task);
971             mpp_assert(ret == MPP_OK);
972         }
973         dec_dbg_detail("task in ready\n");
974 
975         mpp_assert(mpp_task);
976 
977         mpp_task_meta_get_packet(mpp_task, KEY_INPUT_PACKET, &packet);
978         mpp_task_meta_get_frame (mpp_task, KEY_OUTPUT_FRAME,  &frame);
979 
980         if (!frame && packet) {
981             MppMeta meta = mpp_packet_get_meta(packet);
982 
983             if (meta) {
984                 mpp_meta_get_frame(meta, KEY_OUTPUT_FRAME, &frame);
985                 if (frame)
986                     task.status.mpp_in_frm_at_pkt = 1;
987             }
988         }
989 
990         if (NULL == packet || NULL == frame) {
991             mpp_port_enqueue(input, mpp_task);
992             task.status.mpp_pkt_in_rdy = 0;
993             continue;
994         }
995 
996         if (mpp_packet_get_buffer(packet)) {
997             /*
998              * if there is available buffer in the input packet do decoding
999              */
1000             MppBuffer input_buffer = mpp_packet_get_buffer(packet);
1001             MppBuffer output_buffer = mpp_frame_get_buffer(frame);
1002 
1003             mpp_parser_prepare(dec->parser, packet, task_dec);
1004 
1005             /*
1006              * We may find eos in prepare step and there will be no anymore vaild task generated.
1007              * So here we try push eos task to hal, hal will push all frame to display then
1008              * push a eos frame to tell all frame decoded
1009              */
1010             if (task_dec->flags.eos && !task_dec->valid) {
1011                 mpp_frame_set_eos(frame, 1);
1012                 goto DEC_OUT;
1013             }
1014 
1015             /*
1016              *  look for a unused packet slot index
1017              */
1018             if (task_dec->input < 0) {
1019                 mpp_buf_slot_get_unused(packet_slots, &task_dec->input);
1020             }
1021             mpp_buf_slot_set_prop(packet_slots, task_dec->input, SLOT_BUFFER, input_buffer);
1022             mpp_buf_slot_set_flag(packet_slots, task_dec->input, SLOT_CODEC_READY);
1023             mpp_buf_slot_set_flag(packet_slots, task_dec->input, SLOT_HAL_INPUT);
1024 
1025             ret = mpp_parser_parse(dec->parser, task_dec);
1026             if (ret != MPP_OK) {
1027                 mpp_err_f("something wrong with mpp_parser_parse!\n");
1028                 mpp_frame_set_errinfo(frame, 1); /* 0 - OK; 1 - error */
1029                 mpp_buf_slot_clr_flag(packet_slots, task_dec->input,  SLOT_HAL_INPUT);
1030                 goto DEC_OUT;
1031             }
1032 
1033             dec_dbg_detail("slot change %d\n", mpp_buf_slot_is_changed(frame_slots));
1034             if (mpp_buf_slot_is_changed(frame_slots)) {
1035                 size_t slot_size = mpp_buf_slot_get_size(frame_slots);
1036                 size_t buffer_size = mpp_buffer_get_size(output_buffer);
1037 
1038                 dec_dbg_detail("change size required %d vs input %d\n", slot_size, buffer_size);
1039                 if (slot_size == buffer_size) {
1040                     mpp_buf_slot_ready(frame_slots);
1041                 }
1042 
1043                 mpp_assert(slot_size <= buffer_size);
1044 
1045                 if (slot_size > buffer_size) {
1046                     mpp_err_f("required buffer size %d is larger than input buffer size %d\n",
1047                               slot_size, buffer_size);
1048                 }
1049             }
1050 
1051             mpp_buf_slot_set_prop(frame_slots, task_dec->output, SLOT_BUFFER, output_buffer);
1052             // update codec info
1053             if (!dec->info_updated && dec->dev) {
1054                 MppFrame tmp = NULL;
1055 
1056                 mpp_buf_slot_get_prop(frame_slots, task_dec->output, SLOT_FRAME_PTR, &tmp);
1057                 update_dec_hal_info(dec, tmp);
1058                 dec->info_updated = 1;
1059             }
1060             // register genertation
1061             mpp_hal_reg_gen(dec->hal, &pTask->info);
1062             mpp_hal_hw_start(dec->hal, &pTask->info);
1063             mpp_hal_hw_wait(dec->hal, &pTask->info);
1064 
1065             MppFrame tmp = NULL;
1066             mpp_buf_slot_get_prop(frame_slots, task_dec->output, SLOT_FRAME_PTR, &tmp);
1067             mpp_frame_set_width(frame, mpp_frame_get_width(tmp));
1068             mpp_frame_set_height(frame, mpp_frame_get_height(tmp));
1069             mpp_frame_set_hor_stride(frame, mpp_frame_get_hor_stride(tmp));
1070             mpp_frame_set_ver_stride(frame, mpp_frame_get_ver_stride(tmp));
1071             mpp_frame_set_hor_stride_pixel(frame, mpp_frame_get_hor_stride_pixel(tmp));
1072             mpp_frame_set_pts(frame, mpp_frame_get_pts(tmp));
1073             mpp_frame_set_fmt(frame, mpp_frame_get_fmt(tmp));
1074             mpp_frame_set_errinfo(frame, mpp_frame_get_errinfo(tmp));
1075             mpp_frame_set_buf_size(frame, mpp_frame_get_buf_size(tmp));
1076 
1077             mpp_buf_slot_clr_flag(packet_slots, task_dec->input,  SLOT_HAL_INPUT);
1078             mpp_buf_slot_clr_flag(frame_slots, task_dec->output, SLOT_HAL_OUTPUT);
1079         } else {
1080             /*
1081              * else init a empty frame for output
1082              */
1083             mpp_log_f("line(%d): Error! Get no buffer from input packet\n", __LINE__);
1084             mpp_frame_init(&frame);
1085             mpp_frame_set_errinfo(frame, 1);
1086         }
1087 
1088         /*
1089          * first clear output packet
1090          * then enqueue task back to input port
1091          * final user will release the mpp_frame they had input
1092          */
1093     DEC_OUT:
1094         if (task.status.mpp_in_frm_at_pkt) {
1095             MppList *list = mpp->mFrmOut;
1096             MppMeta meta = mpp_frame_get_meta(frame);
1097 
1098             if (meta)
1099                 mpp_meta_set_packet(meta, KEY_INPUT_PACKET, packet);
1100 
1101             mpp_dbg_pts("output frame pts %lld\n", mpp_frame_get_pts(frame));
1102 
1103             mpp_mutex_cond_lock(&list->cond_lock);
1104             mpp_list_add_at_tail(list, &frame, sizeof(frame));
1105             mpp->mFramePutCount++;
1106             mpp_list_signal(list);
1107             mpp_mutex_cond_unlock(&list->cond_lock);
1108 
1109             mpp_port_enqueue(input, mpp_task);
1110             mpp_task = NULL;
1111 
1112             task.status.mpp_in_frm_at_pkt = 0;
1113         } else {
1114             mpp_task_meta_set_packet(mpp_task, KEY_INPUT_PACKET, packet);
1115             mpp_port_enqueue(input, mpp_task);
1116             mpp_task = NULL;
1117 
1118             // send finished task to output port
1119             mpp_port_poll(output, MPP_POLL_BLOCK);
1120             mpp_port_dequeue(output, &mpp_task);
1121             mpp_task_meta_set_frame(mpp_task, KEY_OUTPUT_FRAME, frame);
1122             mpp_buffer_sync_ro_begin(mpp_frame_get_buffer(frame));
1123 
1124             // setup output task here
1125             mpp_port_enqueue(output, mpp_task);
1126             mpp_task = NULL;
1127         }
1128 
1129         packet = NULL;
1130         frame = NULL;
1131 
1132         dec_task_info_init(&pTask->info);
1133 
1134         task.status.mpp_pkt_in_rdy = 0;
1135     }
1136 
1137     // clear remain task in output port
1138     dec_release_task_in_port(input);
1139     dec_release_task_in_port(mpp->mUsrInPort);
1140     dec_release_task_in_port(mpp->mUsrOutPort);
1141 
1142     return NULL;
1143 }
1144 
mpp_dec_start_normal(MppDecImpl * dec)1145 MPP_RET mpp_dec_start_normal(MppDecImpl *dec)
1146 {
1147     if (dec->coding != MPP_VIDEO_CodingMJPEG) {
1148         dec->thread_parser = mpp_thread_create(mpp_dec_parser_thread,
1149                                                dec->mpp, "mpp_dec_parser");
1150         mpp_thread_start(dec->thread_parser);
1151         dec->thread_hal = mpp_thread_create(mpp_dec_hal_thread,
1152                                             dec->mpp, "mpp_dec_hal");
1153 
1154         mpp_thread_start(dec->thread_hal);
1155     } else {
1156         dec->thread_parser = mpp_thread_create(mpp_dec_advanced_thread,
1157                                                dec->mpp, "mpp_dec_parser");
1158         mpp_thread_start(dec->thread_parser);
1159     }
1160 
1161     return MPP_OK;
1162 }
1163 
mpp_dec_reset_normal(MppDecImpl * dec)1164 MPP_RET mpp_dec_reset_normal(MppDecImpl *dec)
1165 {
1166     MppThread *parser = dec->thread_parser;
1167 
1168     if (dec->coding != MPP_VIDEO_CodingMJPEG) {
1169         // set reset flag
1170         mpp_thread_lock(parser, THREAD_CONTROL);
1171         dec->reset_flag = 1;
1172         // signal parser thread to reset
1173         mpp_dec_notify(dec, MPP_DEC_RESET);
1174         mpp_thread_unlock(parser, THREAD_CONTROL);
1175         sem_wait(&dec->parser_reset);
1176     }
1177 
1178     dec->dec_in_pkt_count = 0;
1179     dec->dec_hw_run_count = 0;
1180     dec->dec_out_frame_count = 0;
1181     dec->info_updated = 0;
1182 
1183     return MPP_OK;
1184 }
1185 
mpp_dec_notify_normal(MppDecImpl * dec,RK_U32 flag)1186 MPP_RET mpp_dec_notify_normal(MppDecImpl *dec, RK_U32 flag)
1187 {
1188     MppThread *thd_dec  = dec->thread_parser;
1189     RK_U32 notify = 0;
1190 
1191     if (!thd_dec)
1192         return MPP_NOK;
1193 
1194     mpp_thread_lock(thd_dec, THREAD_WORK);
1195     if (flag == MPP_DEC_CONTROL) {
1196         dec->parser_notify_flag |= flag;
1197         notify = 1;
1198     } else {
1199         RK_U32 old_flag = dec->parser_notify_flag;
1200 
1201         dec->parser_notify_flag |= flag;
1202         if ((old_flag != dec->parser_notify_flag) &&
1203             (dec->parser_notify_flag & dec->parser_wait_flag))
1204             notify = 1;
1205     }
1206 
1207     if (notify) {
1208         dec_dbg_notify("%p status %08x notify control signal\n", dec,
1209                        dec->parser_wait_flag, dec->parser_notify_flag);
1210         mpp_thread_signal(thd_dec, THREAD_WORK);
1211     }
1212     mpp_thread_unlock(thd_dec, THREAD_WORK);
1213 
1214     return MPP_OK;
1215 }
1216 
mpp_dec_control_normal(MppDecImpl * dec,MpiCmd cmd,void * param)1217 MPP_RET mpp_dec_control_normal(MppDecImpl *dec, MpiCmd cmd, void *param)
1218 {
1219     MPP_RET ret = MPP_OK;
1220     mpp_mutex_cond_lock(&dec->cmd_lock);
1221 
1222     dec->cmd = cmd;
1223     dec->param = param;
1224     dec->cmd_ret = &ret;
1225     dec->cmd_send++;
1226 
1227     dec_dbg_detail("detail: %p control cmd %08x param %p start disable_thread %d \n",
1228                    dec, cmd, param, dec->cfg->base.disable_thread);
1229 
1230     mpp_dec_notify_normal(dec, MPP_DEC_CONTROL);
1231     sem_post(&dec->cmd_start);
1232     sem_wait(&dec->cmd_done);
1233     mpp_mutex_cond_unlock(&dec->cmd_lock);
1234 
1235     return ret;
1236 }
1237 
1238 MppDecModeApi dec_api_normal = {
1239     mpp_dec_start_normal,
1240     NULL,
1241     mpp_dec_reset_normal,
1242     mpp_dec_notify_normal,
1243     mpp_dec_control_normal,
1244 };
1245