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