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