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