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