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