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_enc"
18
19 #include <string.h>
20 #include <stdarg.h>
21 #include <limits.h>
22
23 #include "mpp_time.h"
24 #include "mpp_common.h"
25
26 #include "mpp_frame_impl.h"
27 #include "mpp_packet_impl.h"
28
29 #include "mpp.h"
30 #include "mpp_enc_debug.h"
31 #include "mpp_enc_cfg_impl.h"
32 #include "mpp_enc_impl.h"
33 #include "mpp_enc_cb_param.h"
34
35 typedef union EncAsyncWait_u {
36 RK_U32 val;
37 struct {
38 RK_U32 enc_frm_in : 1; // 0x0001 MPP_ENC_NOTIFY_FRAME_ENQUEUE
39 RK_U32 reserv0002 : 1; // 0x0002
40 RK_U32 reserv0004 : 1; // 0x0004
41 RK_U32 enc_pkt_out : 1; // 0x0008 MPP_ENC_NOTIFY_PACKET_ENQUEUE
42
43 RK_U32 task_hnd : 1; // 0x0010
44 RK_U32 reserv0020 : 1; // 0x0020
45 RK_U32 reserv0040 : 1; // 0x0040
46 RK_U32 reserv0080 : 1; // 0x0080
47
48 RK_U32 reserv0100 : 1; // 0x0100
49 RK_U32 reserv0200 : 1; // 0x0200
50 RK_U32 reserv0400 : 1; // 0x0400
51 RK_U32 reserv0800 : 1; // 0x0800
52
53 RK_U32 reserv1000 : 1; // 0x1000
54 RK_U32 reserv2000 : 1; // 0x2000
55 RK_U32 reserv4000 : 1; // 0x4000
56 RK_U32 reserv8000 : 1; // 0x8000
57 };
58 } EncAsyncWait;
59
60 static RK_U8 uuid_version[16] = {
61 0x3d, 0x07, 0x6d, 0x45, 0x73, 0x0f, 0x41, 0xa8,
62 0xb1, 0xc4, 0x25, 0xd7, 0x97, 0x6b, 0xf1, 0xac,
63 };
64
65 static RK_U8 uuid_rc_cfg[16] = {
66 0xd7, 0xdc, 0x03, 0xc3, 0xc5, 0x6f, 0x40, 0xe0,
67 0x8e, 0xa9, 0x17, 0x1a, 0xd2, 0xef, 0x5e, 0x23,
68 };
69
70 static RK_U8 uuid_usr_data[16] = {
71 0xfe, 0x39, 0xac, 0x4c, 0x4a, 0x8e, 0x4b, 0x4b,
72 0x85, 0xd9, 0xb2, 0xa2, 0x4f, 0xa1, 0x19, 0x5b,
73 };
74
75 static RK_U8 uuid_debug_info[16] = {
76 0x57, 0x68, 0x97, 0x80, 0xe7, 0x0c, 0x4b, 0x65,
77 0xa9, 0x06, 0xae, 0x29, 0x94, 0x11, 0xcd, 0x9a
78 };
79
80 RK_U8 uuid_refresh_cfg[16] = {
81 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79,
82 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x00, 0x00
83 };
84
reset_hal_enc_task(HalEncTask * task)85 static void reset_hal_enc_task(HalEncTask *task)
86 {
87 memset(task, 0, sizeof(*task));
88 }
89
reset_enc_rc_task(EncRcTask * task)90 static void reset_enc_rc_task(EncRcTask *task)
91 {
92 memset(task, 0, sizeof(*task));
93 }
94
reset_enc_task(MppEncImpl * enc)95 static void reset_enc_task(MppEncImpl *enc)
96 {
97 enc->task_in = NULL;
98 enc->task_out = NULL;
99 enc->packet = NULL;
100 enc->frame = NULL;
101
102 enc->frm_buf = NULL;
103 enc->pkt_buf = NULL;
104
105 /* NOTE: clear add_by flags */
106 enc->hdr_status.val = enc->hdr_status.ready;
107 }
108
update_enc_hal_info(MppEncImpl * enc)109 static void update_enc_hal_info(MppEncImpl *enc)
110 {
111 MppDevInfoCfg data[32];
112 RK_S32 size = sizeof(data);
113 RK_S32 i;
114
115 if (NULL == enc->hal_info || NULL == enc->dev)
116 return ;
117
118 hal_info_from_enc_cfg(enc->hal_info, &enc->cfg);
119 hal_info_get(enc->hal_info, data, &size);
120
121 if (size) {
122 size /= sizeof(data[0]);
123 for (i = 0; i < size; i++)
124 mpp_dev_ioctl(enc->dev, MPP_DEV_SET_INFO, &data[i]);
125 }
126 }
127
update_hal_info_fps(MppEncImpl * enc)128 static void update_hal_info_fps(MppEncImpl *enc)
129 {
130 MppDevInfoCfg cfg;
131
132 RK_S32 time_diff = ((RK_S32)(enc->time_end - enc->time_base) / 1000);
133 RK_U64 fps = hal_info_to_float(enc->frame_count * 1000, time_diff);
134
135 cfg.type = ENC_INFO_FPS_CALC;
136 cfg.flag = CODEC_INFO_FLAG_STRING;
137 cfg.data = fps;
138
139 mpp_dev_ioctl(enc->dev, MPP_DEV_SET_INFO, &cfg);
140
141 enc->time_base = enc->time_end;
142 enc->frame_count = 0;
143 }
144
release_task_in_port(MppPort port)145 static MPP_RET release_task_in_port(MppPort port)
146 {
147 MPP_RET ret = MPP_OK;
148 MppPacket packet = NULL;
149 MppFrame frame = NULL;
150 MppTask mpp_task;
151
152 do {
153 ret = mpp_port_poll(port, MPP_POLL_NON_BLOCK);
154 if (ret < 0)
155 break;
156
157 mpp_port_dequeue(port, &mpp_task);
158 mpp_assert(mpp_task);
159 if (mpp_task) {
160 packet = NULL;
161 frame = NULL;
162 ret = mpp_task_meta_get_frame(mpp_task, KEY_INPUT_FRAME, &frame);
163 if (frame) {
164 mpp_frame_deinit(&frame);
165 frame = NULL;
166 }
167 ret = mpp_task_meta_get_packet(mpp_task, KEY_OUTPUT_PACKET, &packet);
168 if (packet) {
169 mpp_packet_deinit(&packet);
170 packet = NULL;
171 }
172
173 mpp_port_enqueue(port, mpp_task);
174 mpp_task = NULL;
175 } else
176 break;
177 } while (1);
178
179 return ret;
180 }
181
check_hal_task_pkt_len(HalEncTask * task,const char * reason)182 static void check_hal_task_pkt_len(HalEncTask *task, const char *reason)
183 {
184 RK_U32 task_length = task->length;
185 RK_U32 packet_length = mpp_packet_get_length(task->packet);
186
187 if (task_length != packet_length) {
188 mpp_err_f("%s check failed: task length is not match to packet length %d vs %d\n",
189 reason, task_length, packet_length);
190 }
191 }
192
check_enc_task_wait(MppEncImpl * enc,EncAsyncWait * wait)193 static MPP_RET check_enc_task_wait(MppEncImpl *enc, EncAsyncWait *wait)
194 {
195 MPP_RET ret = MPP_OK;
196 RK_U32 notify = enc->notify_flag;
197 RK_U32 last_wait = enc->status_flag;
198 RK_U32 curr_wait = wait->val;
199 RK_U32 wait_chg = last_wait & (~curr_wait);
200 RK_U32 keep_notify = 0;
201
202 do {
203 if (enc->reset_flag)
204 break;
205
206 // NOTE: User control should always be processed
207 if (notify & MPP_ENC_CONTROL) {
208 keep_notify = notify & (~MPP_ENC_CONTROL);
209 break;
210 }
211
212 // NOTE: When condition is not fulfilled check nofify flag again
213 if (!curr_wait || (curr_wait & notify))
214 break;
215
216 ret = MPP_NOK;
217 } while (0);
218
219 enc_dbg_status("%p %08x -> %08x [%08x] notify %08x -> %s\n", enc,
220 last_wait, curr_wait, wait_chg, notify, (ret) ? ("wait") : ("work"));
221
222 enc->status_flag = wait->val;
223 enc->notify_flag = keep_notify;
224
225 if (ret) {
226 enc->wait_count++;
227 } else {
228 enc->work_count++;
229 }
230
231 return ret;
232 }
233
check_codec_to_resend_hdr(MppEncCodecCfg * codec)234 static RK_S32 check_codec_to_resend_hdr(MppEncCodecCfg *codec)
235 {
236 switch (codec->coding) {
237 case MPP_VIDEO_CodingAVC : {
238 if (codec->h264.change)
239 return 1;
240 } break;
241 case MPP_VIDEO_CodingHEVC : {
242 if (codec->h265.change)
243 return 1;
244 } break;
245 case MPP_VIDEO_CodingVP8 :
246 case MPP_VIDEO_CodingMJPEG :
247 default : {
248 } break;
249 }
250 return 0;
251 }
252
check_resend_hdr(MpiCmd cmd,void * param,MppEncCfgSet * cfg)253 static RK_S32 check_resend_hdr(MpiCmd cmd, void *param, MppEncCfgSet *cfg)
254 {
255 RK_S32 resend = 0;
256 static const char *resend_reason[] = {
257 "unchanged",
258 "codec/prep cfg change",
259 "rc cfg change rc_mode/fps/gop",
260 "set cfg change input/format/color",
261 "set cfg change rc_mode/fps/gop",
262 "set cfg change codec",
263 };
264
265 if (cfg->codec.coding == MPP_VIDEO_CodingMJPEG ||
266 cfg->codec.coding == MPP_VIDEO_CodingVP8)
267 return 0;
268
269 do {
270 if (cmd == MPP_ENC_SET_IDR_FRAME)
271 return 1;
272
273 if (cmd == MPP_ENC_SET_CODEC_CFG ||
274 cmd == MPP_ENC_SET_PREP_CFG) {
275 resend = 1;
276 break;
277 }
278
279 if (cmd == MPP_ENC_SET_RC_CFG) {
280 RK_U32 change = *(RK_U32 *)param;
281 RK_U32 check_flag = MPP_ENC_RC_CFG_CHANGE_RC_MODE |
282 MPP_ENC_RC_CFG_CHANGE_FPS_IN |
283 MPP_ENC_RC_CFG_CHANGE_FPS_OUT |
284 MPP_ENC_RC_CFG_CHANGE_GOP;
285
286 if (change & check_flag) {
287 resend = 2;
288 break;
289 }
290 }
291
292 if (cmd == MPP_ENC_SET_CFG) {
293 RK_U32 change = cfg->prep.change;
294 RK_U32 check_flag = MPP_ENC_PREP_CFG_CHANGE_INPUT |
295 MPP_ENC_PREP_CFG_CHANGE_FORMAT |
296 MPP_ENC_PREP_CFG_CHANGE_ROTATION |
297 MPP_ENC_PREP_CFG_CHANGE_COLOR_RANGE |
298 MPP_ENC_PREP_CFG_CHANGE_COLOR_SPACE |
299 MPP_ENC_PREP_CFG_CHANGE_COLOR_PRIME |
300 MPP_ENC_PREP_CFG_CHANGE_COLOR_TRC;
301
302 if (change & check_flag) {
303 resend = 3;
304 break;
305 }
306
307 change = cfg->rc.change;
308 check_flag = MPP_ENC_RC_CFG_CHANGE_RC_MODE |
309 MPP_ENC_RC_CFG_CHANGE_FPS_IN |
310 MPP_ENC_RC_CFG_CHANGE_FPS_OUT |
311 MPP_ENC_RC_CFG_CHANGE_GOP;
312
313 if (change & check_flag) {
314 resend = 4;
315 break;
316 }
317 if (check_codec_to_resend_hdr(&cfg->codec)) {
318 resend = 5;
319 break;
320 }
321 }
322 } while (0);
323
324 if (resend)
325 enc_dbg_detail("send header for %s\n", resend_reason[resend]);
326
327 return resend;
328 }
329
check_rc_cfg_update(MpiCmd cmd,MppEncCfgSet * cfg)330 static RK_S32 check_rc_cfg_update(MpiCmd cmd, MppEncCfgSet *cfg)
331 {
332 if (cmd == MPP_ENC_SET_RC_CFG ||
333 cmd == MPP_ENC_SET_PREP_CFG ||
334 cmd == MPP_ENC_SET_REF_CFG) {
335 return 1;
336 }
337
338 if (cmd == MPP_ENC_SET_CFG) {
339 RK_U32 change = cfg->prep.change;
340 RK_U32 check_flag = MPP_ENC_PREP_CFG_CHANGE_INPUT |
341 MPP_ENC_PREP_CFG_CHANGE_FORMAT;
342
343 if (change & check_flag)
344 return 1;
345
346 change = cfg->rc.change;
347 check_flag = MPP_ENC_RC_CFG_CHANGE_ALL &
348 (~MPP_ENC_RC_CFG_CHANGE_QUALITY);
349
350 if (change & check_flag)
351 return 1;
352 }
353
354 return 0;
355 }
356
check_rc_gop_update(MpiCmd cmd,MppEncCfgSet * cfg)357 static RK_S32 check_rc_gop_update(MpiCmd cmd, MppEncCfgSet *cfg)
358 {
359 if (((cmd == MPP_ENC_SET_RC_CFG) || (cmd == MPP_ENC_SET_CFG)) &&
360 (cfg->rc.change & MPP_ENC_RC_CFG_CHANGE_GOP))
361 return 1;
362
363 return 0;
364 }
365
check_hal_info_update(MpiCmd cmd)366 static RK_S32 check_hal_info_update(MpiCmd cmd)
367 {
368 if (cmd == MPP_ENC_SET_CFG ||
369 cmd == MPP_ENC_SET_RC_CFG ||
370 cmd == MPP_ENC_SET_CODEC_CFG ||
371 cmd == MPP_ENC_SET_PREP_CFG ||
372 cmd == MPP_ENC_SET_REF_CFG) {
373 return 1;
374 }
375
376 return 0;
377 }
378
check_low_delay_part_mode(MppEncImpl * enc)379 static void check_low_delay_part_mode(MppEncImpl *enc)
380 {
381 MppEncCfgSet *cfg = &enc->cfg;
382
383 enc->low_delay_part_mode = 0;
384
385 if (!(cfg->base.low_delay))
386 return;
387
388 if (!cfg->split.split_mode)
389 return;
390
391 if (mpp_enc_hal_check_part_mode(enc->enc_hal))
392 return;
393
394 enc->low_delay_part_mode = 1;
395 }
396
check_low_delay_output(MppEncImpl * enc)397 static void check_low_delay_output(MppEncImpl *enc)
398 {
399 MppEncCfgSet *cfg = &enc->cfg;
400
401 enc->low_delay_output = 0;
402
403 if (!cfg->split.split_mode || !(cfg->split.split_out & MPP_ENC_SPLIT_OUT_LOWDELAY))
404 return;
405
406 if (cfg->rc.max_reenc_times) {
407 mpp_log_f("can not enable lowdelay output with reencode enabled\n");
408 cfg->rc.max_reenc_times = 0;
409 }
410
411 if (cfg->rc.drop_mode) {
412 mpp_log_f("can not enable lowdelay output with drop mode enabled\n");
413 cfg->rc.drop_mode = MPP_ENC_RC_DROP_FRM_DISABLED;
414 }
415
416 if (cfg->rc.super_mode) {
417 mpp_log_f("can not enable lowdelay output with super frame mode enabled\n");
418 cfg->rc.super_mode = MPP_ENC_RC_SUPER_FRM_NONE;
419 }
420
421 enc->low_delay_output = 1;
422 }
423
mpp_enc_callback(const char * caller,void * ctx,RK_S32 cmd,void * param)424 MPP_RET mpp_enc_callback(const char *caller, void *ctx, RK_S32 cmd, void *param)
425 {
426 MppEncImpl *enc = (MppEncImpl *)ctx;
427 EncOutParam *out = (EncOutParam *)param;
428 HalEncTask *task = NULL;
429 MppPacket packet = NULL;
430 MppPacketImpl *impl = NULL;
431 RK_U8 *last_pos = NULL;
432 RK_S32 slice_length = 0;
433 RK_U32 part_first = 0;
434 MPP_RET ret = MPP_OK;
435 Mpp *mpp = (Mpp*)enc->mpp;
436 (void) caller;
437
438 if (!enc->low_delay_output)
439 return ret;
440
441 task = (HalEncTask *)out->task;
442 mpp_assert(task);
443 part_first = task->part_first;
444 packet = task->packet;
445
446 if (part_first) {
447 task->part_pos = (RK_U8 *)mpp_packet_get_pos(packet);
448 task->part_length = mpp_packet_get_length(packet);
449
450 enc_dbg_slice("first slice previous length %d\n", task->part_length);
451 mpp_assert(task->part_pos);
452 task->part_first = 0;
453 slice_length = task->part_length;
454 }
455
456 last_pos = (RK_U8 *)task->part_pos;
457 slice_length += out->length;
458
459 enc_dbg_slice("last_pos %p len %d:%d\n", last_pos, out->length, slice_length);
460
461 switch (cmd) {
462 case ENC_OUTPUT_FINISH : {
463 enc_dbg_slice("slice pos %p len %5d last\n", last_pos, slice_length);
464
465 impl = (MppPacketImpl *)packet;
466
467 impl->pos = last_pos;
468 impl->length = slice_length;
469 impl->status.val = 0;
470 impl->status.partition = 1;
471 impl->status.soi = part_first;
472 impl->status.eoi = 1;
473
474 task->part_pos += slice_length;
475 task->part_length += slice_length;
476 task->part_count++;
477 task->part_last = 1;
478 } break;
479 case ENC_OUTPUT_SLICE : {
480 enc_dbg_slice("slice pos %p len %5d\n", last_pos, slice_length);
481
482 mpp_packet_new((MppPacket *)&impl);
483 mpp_assert(impl);
484
485 /* copy the source data */
486 memcpy(impl, packet, sizeof(*impl));
487
488 impl->pos = last_pos;
489 impl->length = slice_length;
490 impl->status.val = 0;
491 impl->status.partition = 1;
492 impl->status.soi = part_first;
493 impl->status.eoi = 0;
494
495 if (impl->buffer)
496 mpp_buffer_inc_ref(impl->buffer);
497
498 mpp_meta_get(&impl->meta);
499 if (impl->meta) {
500 EncFrmStatus *frm = &task->rc_task->frm;
501
502 mpp_meta_set_s32(impl->meta, KEY_OUTPUT_INTRA, frm->is_intra);
503 }
504
505 mpp_packet_copy_segment_info(impl, packet);
506 mpp_packet_reset_segment(packet);
507
508 enc_dbg_detail("pkt %d new pos %p len %d\n", task->part_count,
509 last_pos, slice_length);
510
511 task->part_pos += slice_length;
512 task->part_length += slice_length;
513 task->part_count++;
514 if (!mpp->mEncAyncProc) {
515 mpp_task_meta_set_packet(enc->task_out, KEY_OUTPUT_PACKET, impl);
516 mpp_port_enqueue(enc->output, enc->task_out);
517
518 ret = mpp_port_poll(enc->output, MPP_POLL_BLOCK);
519 mpp_assert(ret > 0);
520 ret = mpp_port_dequeue(enc->output, &enc->task_out);
521 mpp_assert(enc->task_out);
522 } else {
523 if (mpp->mPktOut) {
524 mpp_list *pkt_out = mpp->mPktOut;
525
526 AutoMutex autoLock(pkt_out->mutex());
527
528 pkt_out->add_at_tail(&impl, sizeof(impl));
529 mpp->mPacketPutCount++;
530 pkt_out->signal();
531 }
532 }
533 } break;
534 default : {
535 } break;
536 }
537
538 return ret;
539 }
540
mpp_enc_proc_rc_cfg(MppCodingType coding,MppEncRcCfg * dst,MppEncRcCfg * src)541 MPP_RET mpp_enc_proc_rc_cfg(MppCodingType coding, MppEncRcCfg *dst, MppEncRcCfg *src)
542 {
543 MPP_RET ret = MPP_OK;
544 RK_U32 change = src->change;
545
546 if (change) {
547 MppEncRcCfg bak = *dst;
548
549 if (change & MPP_ENC_RC_CFG_CHANGE_RC_MODE)
550 dst->rc_mode = src->rc_mode;
551
552 if (change & MPP_ENC_RC_CFG_CHANGE_QUALITY)
553 dst->quality = src->quality;
554
555 if (change & MPP_ENC_RC_CFG_CHANGE_BPS) {
556 dst->bps_target = src->bps_target;
557 dst->bps_max = src->bps_max;
558 dst->bps_min = src->bps_min;
559 }
560
561 if (change & MPP_ENC_RC_CFG_CHANGE_FPS_IN) {
562 dst->fps_in_flex = src->fps_in_flex;
563 dst->fps_in_num = src->fps_in_num;
564 dst->fps_in_denorm = src->fps_in_denorm;
565 }
566
567 if (change & MPP_ENC_RC_CFG_CHANGE_FPS_OUT) {
568 dst->fps_out_flex = src->fps_out_flex;
569 dst->fps_out_num = src->fps_out_num;
570 dst->fps_out_denorm = src->fps_out_denorm;
571 }
572
573 if (change & MPP_ENC_RC_CFG_CHANGE_GOP) {
574 /*
575 * If GOP is changed smaller, disable Intra-Refresh
576 * and User level should reconfig Intra-Refresh
577 */
578 if (dst->gop < src->gop && dst->refresh_en) {
579 dst->refresh_en = 0;
580 }
581 dst->gop = src->gop;
582 }
583
584 if (change & MPP_ENC_RC_CFG_CHANGE_GOP_REF_CFG)
585 dst->ref_cfg = src->ref_cfg;
586
587 if (change & MPP_ENC_RC_CFG_CHANGE_MAX_REENC)
588 dst->max_reenc_times = src->max_reenc_times;
589
590 if (change & MPP_ENC_RC_CFG_CHANGE_DROP_FRM) {
591 dst->drop_mode = src->drop_mode;
592 dst->drop_threshold = src->drop_threshold;
593 dst->drop_gap = src->drop_gap;
594 }
595
596 if (change & MPP_ENC_RC_CFG_CHANGE_PRIORITY) {
597 if (src->rc_priority >= MPP_ENC_RC_PRIORITY_BUTT) {
598 mpp_err("invalid rc_priority %d should be[%d, %d] \n",
599 src->rc_priority, MPP_ENC_RC_BY_BITRATE_FIRST, MPP_ENC_RC_PRIORITY_BUTT);
600 ret = MPP_ERR_VALUE;
601 }
602 dst->rc_priority = src->rc_priority;
603 }
604
605 if (change & MPP_ENC_RC_CFG_CHANGE_SUPER_FRM) {
606 if (src->super_mode >= MPP_ENC_RC_SUPER_FRM_BUTT) {
607 mpp_err("invalid super_mode %d should be[%d, %d] \n",
608 src->super_mode, MPP_ENC_RC_SUPER_FRM_NONE, MPP_ENC_RC_SUPER_FRM_BUTT);
609 ret = MPP_ERR_VALUE;
610 }
611 dst->super_mode = src->super_mode;
612 dst->super_i_thd = src->super_i_thd;
613 dst->super_p_thd = src->super_p_thd;
614 }
615
616 if (change & MPP_ENC_RC_CFG_CHANGE_DEBREATH) {
617 dst->debreath_en = src->debreath_en;
618 dst->debre_strength = src->debre_strength;
619 if (dst->debreath_en && dst->debre_strength > 35) {
620 mpp_err("invalid debre_strength should be[%d, %d] \n", 0, 35);
621 ret = MPP_ERR_VALUE;
622 }
623 }
624
625 if (change & MPP_ENC_RC_CFG_CHANGE_MAX_I_PROP)
626 dst->max_i_prop = src->max_i_prop;
627
628 if (change & MPP_ENC_RC_CFG_CHANGE_MIN_I_PROP)
629 dst->min_i_prop = src->min_i_prop;
630
631 if (change & MPP_ENC_RC_CFG_CHANGE_INIT_IP_RATIO)
632 dst->init_ip_ratio = src->init_ip_ratio;
633
634 if (change & MPP_ENC_RC_CFG_CHANGE_QP_INIT)
635 dst->qp_init = src->qp_init;
636
637 if (change & MPP_ENC_RC_CFG_CHANGE_QP_RANGE) {
638 dst->qp_min = src->qp_min;
639 dst->qp_max = src->qp_max;
640 }
641
642 if (change & MPP_ENC_RC_CFG_CHANGE_QP_RANGE_I) {
643 dst->qp_min_i = src->qp_min_i;
644 dst->qp_max_i = src->qp_max_i;
645 }
646
647 if (change & MPP_ENC_RC_CFG_CHANGE_QP_MAX_STEP)
648 dst->qp_max_step = src->qp_max_step;
649
650 if (change & MPP_ENC_RC_CFG_CHANGE_QP_IP)
651 dst->qp_delta_ip = src->qp_delta_ip;
652
653 if (change & MPP_ENC_RC_CFG_CHANGE_QP_VI)
654 dst->qp_delta_vi = src->qp_delta_vi;
655
656 if (change & MPP_ENC_RC_CFG_CHANGE_HIER_QP) {
657 dst->hier_qp_en = src->hier_qp_en;
658 memcpy(dst->hier_qp_delta, src->hier_qp_delta, sizeof(src->hier_qp_delta));
659 memcpy(dst->hier_frame_num, src->hier_frame_num, sizeof(src->hier_frame_num));
660 }
661
662 if (change & MPP_ENC_RC_CFG_CHANGE_ST_TIME)
663 dst->stats_time = src->stats_time;
664
665 if (change & MPP_ENC_RC_CFG_CHANGE_REFRESH) {
666 if (dst->debreath_en) {
667 mpp_err_f("Turn off Debreath first.");
668 ret = MPP_ERR_VALUE;
669 }
670 dst->refresh_en = src->refresh_en;
671 dst->refresh_mode = src->refresh_mode;
672 // Make sure refresh_num is legal
673 dst->refresh_num = src->refresh_num;
674 }
675
676 // parameter checking
677 if (dst->rc_mode >= MPP_ENC_RC_MODE_BUTT) {
678 mpp_err("invalid rc mode %d should be RC_MODE_VBR or RC_MODE_CBR\n",
679 src->rc_mode);
680 ret = MPP_ERR_VALUE;
681 }
682 if (dst->quality >= MPP_ENC_RC_QUALITY_BUTT) {
683 mpp_err("invalid quality %d should be from QUALITY_WORST to QUALITY_BEST\n",
684 dst->quality);
685 ret = MPP_ERR_VALUE;
686 }
687
688 if (dst->rc_mode != MPP_ENC_RC_MODE_FIXQP) {
689 RK_S32 bps_min = MPP_ENC_MIN_BPS;
690 RK_S32 bps_max = MPP_ENC_MAX_BPS;
691
692 if (coding == MPP_VIDEO_CodingMJPEG) {
693 bps_min *= 4;
694 bps_max *= 4;
695 if (bps_max < 0)
696 bps_max = INT_MAX;
697 }
698
699 if ((dst->bps_target >= bps_max || dst->bps_target <= bps_min) ||
700 (dst->bps_max >= bps_max || dst->bps_max <= bps_min) ||
701 (dst->bps_min >= bps_max || dst->bps_min <= bps_min)) {
702 mpp_err("invalid bit per second %x:%u min %x:%u max %x:%u out of range %dK~%dM\n",
703 dst->bps_target, dst->bps_target, dst->bps_min,
704 dst->bps_min, dst->bps_max, dst->bps_max,
705 bps_min / SZ_1K, bps_max / SZ_1M);
706 ret = MPP_ERR_VALUE;
707 }
708 }
709
710 if (dst->fps_in_num < 0 || dst->fps_in_denorm < 0 ||
711 dst->fps_out_num < 0 || dst->fps_out_denorm < 0) {
712 mpp_err("invalid fps cfg [number:denorm:flex]: in [%d:%d:%d] out [%d:%d:%d]\n",
713 dst->fps_in_num, dst->fps_in_denorm, dst->fps_in_flex,
714 dst->fps_out_num, dst->fps_out_denorm, dst->fps_out_flex);
715 ret = MPP_ERR_VALUE;
716 }
717
718 // if I frame min/max is not set use normal case
719 if (dst->qp_min_i <= 0)
720 dst->qp_min_i = dst->qp_min;
721 if (dst->qp_max_i <= 0)
722 dst->qp_max_i = dst->qp_max;
723 if (dst->qp_min < 0 || dst->qp_max < 0 || dst->qp_min > dst->qp_max ||
724 dst->qp_min_i < 0 || dst->qp_max_i < 0 ||
725 dst->qp_min_i > dst->qp_max_i ||
726 (dst->qp_init > 0 &&
727 (dst->qp_init > dst->qp_max_i || dst->qp_init < dst->qp_min_i))) {
728 mpp_err("invalid qp range: init %d i [%d:%d] p [%d:%d]\n",
729 dst->qp_init, dst->qp_min_i, dst->qp_max_i,
730 dst->qp_min, dst->qp_max);
731
732 dst->qp_init = bak.qp_init;
733 dst->qp_min_i = bak.qp_min_i;
734 dst->qp_max_i = bak.qp_max_i;
735 dst->qp_min = bak.qp_min;
736 dst->qp_max = bak.qp_max;
737
738 mpp_err("restore qp range: init %d i [%d:%d] p [%d:%d]\n",
739 dst->qp_init, dst->qp_min_i, dst->qp_max_i,
740 dst->qp_min, dst->qp_max);
741 }
742 if (MPP_ABS(dst->qp_delta_ip) > 8) {
743 mpp_err("invalid qp delta ip %d restore to %d\n",
744 dst->qp_delta_ip, bak.qp_delta_ip);
745 dst->qp_delta_ip = bak.qp_delta_ip;
746 }
747 if (MPP_ABS(dst->qp_delta_vi) > 6) {
748 mpp_err("invalid qp delta vi %d restore to %d\n",
749 dst->qp_delta_vi, bak.qp_delta_vi);
750 dst->qp_delta_vi = bak.qp_delta_vi;
751 }
752 if (dst->qp_max_step < 0) {
753 mpp_err("invalid qp max step %d restore to %d\n",
754 dst->qp_max_step, bak.qp_max_step);
755 dst->qp_max_step = bak.qp_max_step;
756 }
757 if (dst->stats_time && dst->stats_time > 60) {
758 mpp_err("warning: bitrate statistic time %d is larger than 60s\n",
759 dst->stats_time);
760 }
761
762 dst->change |= change;
763
764 if (ret) {
765 mpp_err_f("failed to accept new rc config\n");
766 *dst = bak;
767 } else {
768 mpp_log("MPP_ENC_SET_RC_CFG bps %d [%d : %d] fps [%d:%d] gop %d\n",
769 dst->bps_target, dst->bps_min, dst->bps_max,
770 dst->fps_in_num, dst->fps_out_num, dst->gop);
771 }
772 }
773
774 return ret;
775 }
776
mpp_enc_proc_hw_cfg(MppEncHwCfg * dst,MppEncHwCfg * src)777 MPP_RET mpp_enc_proc_hw_cfg(MppEncHwCfg *dst, MppEncHwCfg *src)
778 {
779 MPP_RET ret = MPP_OK;
780 RK_U32 change = src->change;
781
782 if (change) {
783 MppEncHwCfg bak = *dst;
784
785 if (change & MPP_ENC_HW_CFG_CHANGE_QP_ROW)
786 dst->qp_delta_row = src->qp_delta_row;
787
788 if (change & MPP_ENC_HW_CFG_CHANGE_QP_ROW_I)
789 dst->qp_delta_row_i = src->qp_delta_row_i;
790
791 if (change & MPP_ENC_HW_CFG_CHANGE_AQ_THRD_I)
792 memcpy(dst->aq_thrd_i, src->aq_thrd_i, sizeof(dst->aq_thrd_i));
793
794 if (change & MPP_ENC_HW_CFG_CHANGE_AQ_THRD_P)
795 memcpy(dst->aq_thrd_p, src->aq_thrd_p, sizeof(dst->aq_thrd_p));
796
797 if (change & MPP_ENC_HW_CFG_CHANGE_AQ_STEP_I)
798 memcpy(dst->aq_step_i, src->aq_step_i, sizeof(dst->aq_step_i));
799
800 if (change & MPP_ENC_HW_CFG_CHANGE_AQ_STEP_P)
801 memcpy(dst->aq_step_p, src->aq_step_p, sizeof(dst->aq_step_p));
802
803 if (change & MPP_ENC_HW_CFG_CHANGE_MB_RC)
804 dst->mb_rc_disable = src->mb_rc_disable;
805
806 if (change & MPP_ENC_HW_CFG_CHANGE_CU_MODE_BIAS)
807 memcpy(dst->mode_bias, src->mode_bias, sizeof(dst->mode_bias));
808
809 if (change & MPP_ENC_HW_CFG_CHANGE_CU_SKIP_BIAS) {
810 dst->skip_bias_en = src->skip_bias_en;
811 dst->skip_sad = src->skip_sad;
812 dst->skip_bias = src->skip_bias;
813 }
814
815 if (dst->qp_delta_row < 0 || dst->qp_delta_row_i < 0) {
816 mpp_err("invalid hw qp delta row [%d:%d]\n",
817 dst->qp_delta_row_i, dst->qp_delta_row);
818 ret = MPP_ERR_VALUE;
819 }
820
821 dst->change |= change;
822
823 if (ret) {
824 mpp_err_f("failed to accept new hw config\n");
825 *dst = bak;
826 }
827 }
828
829 return ret;
830 }
831
mpp_enc_proc_tune_cfg(MppEncFineTuneCfg * dst,MppEncFineTuneCfg * src)832 MPP_RET mpp_enc_proc_tune_cfg(MppEncFineTuneCfg *dst, MppEncFineTuneCfg *src)
833 {
834 MPP_RET ret = MPP_OK;
835 RK_U32 change = src->change;
836
837 if (change) {
838 MppEncFineTuneCfg bak = *dst;
839
840 if (change & MPP_ENC_TUNE_CFG_CHANGE_SCENE_MODE)
841 dst->scene_mode = src->scene_mode;
842
843 if (dst->scene_mode < MPP_ENC_SCENE_MODE_DEFAULT ||
844 dst->scene_mode >= MPP_ENC_SCENE_MODE_BUTT) {
845 mpp_err("invalid scene mode %d not in range [%d:%d]\n", dst->scene_mode,
846 MPP_ENC_SCENE_MODE_DEFAULT, MPP_ENC_SCENE_MODE_BUTT - 1);
847 ret = MPP_ERR_VALUE;
848 }
849
850 dst->change |= change;
851
852 if (ret) {
853 mpp_err_f("failed to accept new tuning config\n");
854 *dst = bak;
855 }
856 }
857
858 return ret;
859 }
860
mpp_enc_control_set_ref_cfg(MppEncImpl * enc,void * param)861 static MPP_RET mpp_enc_control_set_ref_cfg(MppEncImpl *enc, void *param)
862 {
863 MPP_RET ret = MPP_OK;
864 MppEncRefCfg src = (MppEncRefCfg)param;
865 MppEncRefCfg dst = enc->cfg.ref_cfg;
866
867 if (NULL == src)
868 src = mpp_enc_ref_default();
869
870 if (NULL == dst) {
871 mpp_enc_ref_cfg_init(&dst);
872 enc->cfg.ref_cfg = dst;
873 }
874
875 ret = mpp_enc_ref_cfg_copy(dst, src);
876 if (ret) {
877 mpp_err_f("failed to copy ref cfg ret %d\n", ret);
878 }
879
880 ret = mpp_enc_refs_set_cfg(enc->refs, dst);
881 if (ret) {
882 mpp_err_f("failed to set ref cfg ret %d\n", ret);
883 }
884
885 if (mpp_enc_refs_update_hdr(enc->refs))
886 enc->hdr_status.val = 0;
887
888 return ret;
889 }
890
mpp_enc_proc_cfg(MppEncImpl * enc,MpiCmd cmd,void * param)891 MPP_RET mpp_enc_proc_cfg(MppEncImpl *enc, MpiCmd cmd, void *param)
892 {
893 MPP_RET ret = MPP_OK;
894
895 switch (cmd) {
896 case MPP_ENC_SET_CFG : {
897 MppEncCfgImpl *impl = (MppEncCfgImpl *)param;
898 MppEncCfgSet *src = &impl->cfg;
899 RK_U32 change = src->base.change;
900
901 /* get base cfg here */
902 if (change) {
903 MppEncCfgSet *dst = &enc->cfg;
904
905 if (change & MPP_ENC_BASE_CFG_CHANGE_LOW_DELAY)
906 dst->base.low_delay = src->base.low_delay;
907
908 src->base.change = 0;
909 }
910
911 /* process rc cfg at mpp_enc module */
912 if (src->rc.change) {
913 ret = mpp_enc_proc_rc_cfg(enc->coding, &enc->cfg.rc, &src->rc);
914
915 // update ref cfg
916 if ((enc->cfg.rc.change & MPP_ENC_RC_CFG_CHANGE_GOP_REF_CFG) &&
917 (enc->cfg.rc.gop > 0))
918 mpp_enc_control_set_ref_cfg(enc, enc->cfg.rc.ref_cfg);
919
920 src->rc.change = 0;
921 }
922
923 /* process hardware cfg at mpp_enc module */
924 if (src->hw.change) {
925 ret = mpp_enc_proc_hw_cfg(&enc->cfg.hw, &src->hw);
926 src->hw.change = 0;
927 }
928
929 /* process hardware cfg at mpp_enc module */
930 if (src->tune.change) {
931 ret = mpp_enc_proc_tune_cfg(&enc->cfg.tune, &src->tune);
932 src->tune.change = 0;
933 }
934
935 /* Then process the rest config */
936 ret = enc_impl_proc_cfg(enc->impl, cmd, param);
937 } break;
938 case MPP_ENC_SET_RC_CFG : {
939 MppEncRcCfg *src = (MppEncRcCfg *)param;
940 if (src) {
941 ret = mpp_enc_proc_rc_cfg(enc->coding, &enc->cfg.rc, src);
942
943 // update ref cfg
944 if ((enc->cfg.rc.change & MPP_ENC_RC_CFG_CHANGE_GOP_REF_CFG) &&
945 (enc->cfg.rc.gop > 0))
946 mpp_enc_control_set_ref_cfg(enc, enc->cfg.rc.ref_cfg);
947 }
948 } break;
949 case MPP_ENC_SET_IDR_FRAME : {
950 enc->frm_cfg.force_idr++;
951 } break;
952 case MPP_ENC_GET_HDR_SYNC :
953 case MPP_ENC_GET_EXTRA_INFO : {
954 /*
955 * NOTE: get stream header should use user's MppPacket
956 * If we provide internal MppPacket to external user
957 * we do not known when the buffer usage is finished.
958 * So encoder always write its header to external buffer
959 * which is provided by user.
960 */
961 if (!enc->hdr_status.ready) {
962 enc_impl_gen_hdr(enc->impl, enc->hdr_pkt);
963 enc->hdr_len = mpp_packet_get_length(enc->hdr_pkt);
964 enc->hdr_status.ready = 1;
965 }
966
967 if (cmd == MPP_ENC_GET_EXTRA_INFO) {
968 mpp_err("Please use MPP_ENC_GET_HDR_SYNC instead of unsafe MPP_ENC_GET_EXTRA_INFO\n");
969 mpp_err("NOTE: MPP_ENC_GET_HDR_SYNC needs MppPacket input\n");
970
971 *(MppPacket *)param = enc->hdr_pkt;
972 } else {
973 mpp_packet_copy((MppPacket)param, enc->hdr_pkt);
974 }
975
976 if (enc->hdr_pkt) {
977 Mpp *mpp = (Mpp *)enc->mpp;
978 // dump output
979 mpp_ops_enc_get_pkt(mpp->mDump, enc->hdr_pkt);
980 }
981
982 enc->hdr_status.added_by_ctrl = 1;
983 } break;
984 case MPP_ENC_PRE_ALLOC_BUFF : {
985 /* deprecated control */
986 mpp_log("deprecated MPP_ENC_PRE_ALLOC_BUFF control\n");
987 } break;
988 case MPP_ENC_GET_RC_API_ALL : {
989 RcApiQueryAll *query = (RcApiQueryAll *)param;
990
991 rc_brief_get_all(query);
992 } break;
993 case MPP_ENC_GET_RC_API_BY_TYPE : {
994 RcApiQueryType *query = (RcApiQueryType *)param;
995
996 rc_brief_get_by_type(query);
997 } break;
998 case MPP_ENC_SET_RC_API_CFG : {
999 const RcImplApi *api = (const RcImplApi *)param;
1000
1001 rc_api_add(api);
1002 } break;
1003 case MPP_ENC_GET_RC_API_CURRENT : {
1004 RcApiBrief *dst = (RcApiBrief *)param;
1005
1006 *dst = enc->rc_brief;
1007 } break;
1008 case MPP_ENC_SET_RC_API_CURRENT : {
1009 RcApiBrief *src = (RcApiBrief *)param;
1010
1011 mpp_assert(src->type == enc->coding);
1012 enc->rc_brief = *src;
1013 enc->rc_status.rc_api_user_cfg = 1;
1014 enc->rc_status.rc_api_updated = 1;
1015 } break;
1016 case MPP_ENC_SET_HEADER_MODE : {
1017 if (param) {
1018 MppEncHeaderMode mode = *((MppEncHeaderMode *)param);
1019
1020 if (mode < MPP_ENC_HEADER_MODE_BUTT) {
1021 enc->hdr_mode = mode;
1022 enc_dbg_ctrl("header mode set to %d\n", mode);
1023 } else {
1024 mpp_err_f("invalid header mode %d\n", mode);
1025 ret = MPP_NOK;
1026 }
1027 } else {
1028 mpp_err_f("invalid NULL ptr on setting header mode\n");
1029 ret = MPP_NOK;
1030 }
1031 } break;
1032 case MPP_ENC_SET_SEI_CFG : {
1033 if (param) {
1034 MppEncSeiMode mode = *((MppEncSeiMode *)param);
1035
1036 if (mode <= MPP_ENC_SEI_MODE_ONE_FRAME) {
1037 enc->sei_mode = mode;
1038 enc_dbg_ctrl("sei mode set to %d\n", mode);
1039 } else {
1040 mpp_err_f("invalid sei mode %d\n", mode);
1041 ret = MPP_NOK;
1042 }
1043 } else {
1044 mpp_err_f("invalid NULL ptr on setting header mode\n");
1045 ret = MPP_NOK;
1046 }
1047 } break;
1048 case MPP_ENC_SET_REF_CFG : {
1049 ret = mpp_enc_control_set_ref_cfg(enc, param);
1050 } break;
1051 case MPP_ENC_SET_OSD_PLT_CFG : {
1052 MppEncOSDPltCfg *src = (MppEncOSDPltCfg *)param;
1053 MppEncOSDPltCfg *dst = &enc->cfg.plt_cfg;
1054 RK_U32 change = src->change;
1055
1056 if (change) {
1057 RK_S32 cfg_err = 0;
1058
1059 if (change & MPP_ENC_OSD_PLT_CFG_CHANGE_MODE) {
1060 if (src->type >= MPP_ENC_OSD_PLT_TYPE_BUTT) {
1061 mpp_err_f("invalid osd plt type %d\n", src->type);
1062 cfg_err |= MPP_ENC_OSD_PLT_CFG_CHANGE_MODE;
1063 } else
1064 dst->type = src->type;
1065 }
1066
1067 if (change & MPP_ENC_OSD_PLT_CFG_CHANGE_PLT_VAL) {
1068 if (src->plt == NULL) {
1069 mpp_err_f("invalid osd plt NULL pointer\n");
1070 cfg_err |= MPP_ENC_OSD_PLT_CFG_CHANGE_PLT_VAL;
1071 } else {
1072 memcpy(dst->plt, src->plt, sizeof(MppEncOSDPlt));
1073 }
1074 }
1075
1076 dst->change = cfg_err ? 0 : change;
1077 enc_dbg_ctrl("plt type %d data %p\n", dst->type, src->plt);
1078 }
1079 } break;
1080 default : {
1081 ret = enc_impl_proc_cfg(enc->impl, cmd, param);
1082 } break;
1083 }
1084
1085 if (check_resend_hdr(cmd, param, &enc->cfg)) {
1086 enc->frm_cfg.force_flag |= ENC_FORCE_IDR;
1087 enc->hdr_status.val = 0;
1088 }
1089 if (check_rc_cfg_update(cmd, &enc->cfg))
1090 enc->rc_status.rc_api_user_cfg = 1;
1091 if (check_rc_gop_update(cmd, &enc->cfg))
1092 mpp_enc_refs_set_rc_igop(enc->refs, enc->cfg.rc.gop);
1093
1094 if (enc->cfg.rc.refresh_en)
1095 mpp_enc_refs_set_refresh_length(enc->refs, enc->cfg.rc.refresh_length);
1096
1097 if (check_hal_info_update(cmd))
1098 enc->hal_info_updated = 0;
1099
1100 check_low_delay_part_mode(enc);
1101 check_low_delay_output(enc);
1102
1103 return ret;
1104 }
1105
1106 static const char *name_of_rc_mode[] = {
1107 "vbr",
1108 "cbr",
1109 "fixqp",
1110 "avbr",
1111 };
1112
update_rc_cfg_log(MppEncImpl * impl,const char * fmt,...)1113 static void update_rc_cfg_log(MppEncImpl *impl, const char* fmt, ...)
1114 {
1115 va_list args;
1116 va_start(args, fmt);
1117
1118 RK_S32 size = impl->rc_cfg_size;
1119 RK_S32 length = impl->rc_cfg_length;
1120 char *base = impl->rc_cfg_info + length;
1121
1122 length += vsnprintf(base, size - length, fmt, args);
1123 if (length >= size)
1124 mpp_log_f("rc cfg log is full\n");
1125
1126 impl->rc_cfg_length = length;
1127
1128 va_end(args);
1129 }
1130
update_user_datas(EncImpl impl,MppPacket packet,MppFrame frame,HalEncTask * hal_task)1131 static void update_user_datas(EncImpl impl, MppPacket packet, MppFrame frame, HalEncTask *hal_task)
1132 {
1133 MppMeta frm_meta = mpp_frame_get_meta(frame);
1134 MppEncUserData *user_data = NULL;
1135 MppEncUserDataSet *user_datas = NULL;
1136 RK_S32 length = 0;
1137
1138 mpp_meta_get_ptr(frm_meta, KEY_USER_DATA, (void**)&user_data);
1139 if (user_data) {
1140 if (user_data->pdata && user_data->len) {
1141 enc_impl_add_prefix(impl, packet, &length, uuid_usr_data,
1142 user_data->pdata, user_data->len);
1143
1144 hal_task->sei_length += length;
1145 hal_task->length += length;
1146 } else
1147 mpp_err_f("failed to insert user data %p len %d\n",
1148 user_data->pdata, user_data->len);
1149 }
1150
1151 mpp_meta_get_ptr(frm_meta, KEY_USER_DATAS, (void**)&user_datas);
1152 if (user_datas && user_datas->count) {
1153 RK_U32 i = 0;
1154
1155 for (i = 0; i < user_datas->count; i++) {
1156 MppEncUserDataFull *user_data_v2 = &user_datas->datas[i];
1157 if (user_data_v2->pdata && user_data_v2->len) {
1158 if (user_data_v2->uuid)
1159 enc_impl_add_prefix(impl, packet, &length, user_data_v2->uuid,
1160 user_data_v2->pdata, user_data_v2->len);
1161 else
1162 enc_impl_add_prefix(impl, packet, &length, uuid_debug_info,
1163 user_data_v2->pdata, user_data_v2->len);
1164
1165 hal_task->sei_length += length;
1166 hal_task->length += length;
1167 }
1168 }
1169 }
1170 }
1171
set_rc_cfg(RcCfg * cfg,MppEncCfgSet * cfg_set)1172 static void set_rc_cfg(RcCfg *cfg, MppEncCfgSet *cfg_set)
1173 {
1174 MppEncRcCfg *rc = &cfg_set->rc;
1175 MppEncPrepCfg *prep = &cfg_set->prep;
1176 MppEncCodecCfg *codec = &cfg_set->codec;
1177 MppEncRefCfgImpl *ref = (MppEncRefCfgImpl *)cfg_set->ref_cfg;
1178 MppEncCpbInfo *info = &ref->cpb_info;
1179
1180 cfg->width = prep->width;
1181 cfg->height = prep->height;
1182
1183 switch (rc->rc_mode) {
1184 case MPP_ENC_RC_MODE_CBR : {
1185 cfg->mode = RC_CBR;
1186 } break;
1187 case MPP_ENC_RC_MODE_VBR : {
1188 cfg->mode = RC_VBR;
1189 } break;
1190 case MPP_ENC_RC_MODE_AVBR : {
1191 cfg->mode = RC_AVBR;
1192 } break;
1193 case MPP_ENC_RC_MODE_FIXQP: {
1194 cfg->mode = RC_FIXQP;
1195 } break;
1196 default : {
1197 cfg->mode = RC_AVBR;
1198 } break;
1199 }
1200
1201 cfg->fps.fps_in_flex = rc->fps_in_flex;
1202 cfg->fps.fps_in_num = rc->fps_in_num;
1203 cfg->fps.fps_in_denorm = rc->fps_in_denorm;
1204 cfg->fps.fps_out_flex = rc->fps_out_flex;
1205 cfg->fps.fps_out_num = rc->fps_out_num;
1206 cfg->fps.fps_out_denorm = rc->fps_out_denorm;
1207 cfg->igop = rc->gop;
1208 cfg->max_i_bit_prop = rc->max_i_prop;
1209 cfg->min_i_bit_prop = rc->min_i_prop;
1210 cfg->init_ip_ratio = rc->init_ip_ratio;
1211
1212 cfg->bps_target = rc->bps_target;
1213 cfg->bps_max = rc->bps_max;
1214 cfg->bps_min = rc->bps_min;
1215
1216 cfg->hier_qp_cfg.hier_qp_en = rc->hier_qp_en;
1217 memcpy(cfg->hier_qp_cfg.hier_frame_num, rc->hier_frame_num, sizeof(rc->hier_frame_num));
1218 memcpy(cfg->hier_qp_cfg.hier_qp_delta, rc->hier_qp_delta, sizeof(rc->hier_qp_delta));
1219
1220 mpp_assert(rc->fps_out_num);
1221 cfg->stats_time = rc->stats_time ? rc->stats_time : 3;
1222 cfg->stats_time = mpp_clip(cfg->stats_time, 1, 60);
1223
1224 /* quality configure */
1225 switch (codec->coding) {
1226 case MPP_VIDEO_CodingAVC :
1227 case MPP_VIDEO_CodingHEVC :
1228 case MPP_VIDEO_CodingVP8 : {
1229 cfg->init_quality = rc->qp_init;
1230 cfg->max_quality = rc->qp_max;
1231 cfg->min_quality = rc->qp_min;
1232 cfg->max_i_quality = rc->qp_max_i ? rc->qp_max_i : rc->qp_max;
1233 cfg->min_i_quality = rc->qp_min_i ? rc->qp_min_i : rc->qp_min;
1234 cfg->i_quality_delta = rc->qp_delta_ip;
1235 cfg->vi_quality_delta = rc->qp_delta_vi;
1236 } break;
1237 case MPP_VIDEO_CodingMJPEG : {
1238 MppEncJpegCfg *jpeg = &codec->jpeg;
1239
1240 cfg->init_quality = jpeg->q_factor;
1241 cfg->max_quality = jpeg->qf_max;
1242 cfg->min_quality = jpeg->qf_min;
1243 cfg->max_i_quality = jpeg->qf_max;
1244 cfg->min_i_quality = jpeg->qf_min;
1245 } break;
1246 default : {
1247 mpp_err_f("unsupport coding type %d\n", codec->coding);
1248 } break;
1249 }
1250
1251 cfg->layer_bit_prop[0] = 256;
1252 cfg->layer_bit_prop[1] = 0;
1253 cfg->layer_bit_prop[2] = 0;
1254 cfg->layer_bit_prop[3] = 0;
1255
1256 cfg->max_reencode_times = rc->max_reenc_times;
1257 cfg->drop_mode = rc->drop_mode;
1258 cfg->drop_thd = rc->drop_threshold;
1259 cfg->drop_gap = rc->drop_gap;
1260
1261 cfg->super_cfg.rc_priority = rc->rc_priority;
1262 cfg->super_cfg.super_mode = rc->super_mode;
1263 cfg->super_cfg.super_i_thd = rc->super_i_thd;
1264 cfg->super_cfg.super_p_thd = rc->super_p_thd;
1265
1266 cfg->debreath_cfg.enable = rc->debreath_en;
1267 cfg->debreath_cfg.strength = rc->debre_strength;
1268
1269 cfg->refresh_len = rc->refresh_length;
1270
1271 if (info->st_gop) {
1272 cfg->vgop = info->st_gop;
1273 if (cfg->vgop >= rc->fps_out_num / rc->fps_out_denorm &&
1274 cfg->vgop < cfg->igop ) {
1275 cfg->gop_mode = SMART_P;
1276 if (!cfg->vi_quality_delta)
1277 cfg->vi_quality_delta = 2;
1278 }
1279 }
1280
1281 if (codec->coding == MPP_VIDEO_CodingAVC ||
1282 codec->coding == MPP_VIDEO_CodingHEVC) {
1283 mpp_log("mode %s bps [%d:%d:%d] fps %s [%d/%d] -> %s [%d/%d] gop i [%d] v [%d]\n",
1284 name_of_rc_mode[cfg->mode],
1285 rc->bps_min, rc->bps_target, rc->bps_max,
1286 cfg->fps.fps_in_flex ? "flex" : "fix",
1287 cfg->fps.fps_in_num, cfg->fps.fps_in_denorm,
1288 cfg->fps.fps_out_flex ? "flex" : "fix",
1289 cfg->fps.fps_out_num, cfg->fps.fps_out_denorm,
1290 cfg->igop, cfg->vgop);
1291 }
1292 }
1293
mpp_enc_proc_rc_update(MppEncImpl * enc)1294 MPP_RET mpp_enc_proc_rc_update(MppEncImpl *enc)
1295 {
1296 MPP_RET ret = MPP_OK;
1297
1298 // check and update rate control api
1299 if (!enc->rc_status.rc_api_inited || enc->rc_status.rc_api_updated) {
1300 RcApiBrief *brief = &enc->rc_brief;
1301
1302 if (enc->rc_ctx) {
1303 enc_dbg_detail("rc deinit %p\n", enc->rc_ctx);
1304 rc_deinit(enc->rc_ctx);
1305 enc->rc_ctx = NULL;
1306 }
1307
1308 /* NOTE: default name is NULL */
1309 ret = rc_init(&enc->rc_ctx, enc->coding, &brief->name);
1310 if (ret)
1311 mpp_err("enc %p fail to init rc %s\n", enc, brief->name);
1312 else
1313 enc->rc_status.rc_api_inited = 1;
1314
1315 enc_dbg_detail("rc init %p name %s ret %d\n", enc->rc_ctx, brief->name, ret);
1316 enc->rc_status.rc_api_updated = 0;
1317
1318 enc->rc_cfg_length = 0;
1319 update_rc_cfg_log(enc, "%s:", brief->name);
1320 enc->rc_cfg_pos = enc->rc_cfg_length;
1321 }
1322
1323 // check and update rate control config
1324 if (enc->rc_status.rc_api_user_cfg) {
1325 MppEncCfgSet *cfg = &enc->cfg;
1326 MppEncRcCfg *rc_cfg = &cfg->rc;
1327 MppEncPrepCfg *prep_cfg = &cfg->prep;
1328 RcCfg usr_cfg;
1329
1330 enc_dbg_detail("rc update cfg start\n");
1331
1332 memset(&usr_cfg, 0 , sizeof(usr_cfg));
1333 set_rc_cfg(&usr_cfg, cfg);
1334 ret = rc_update_usr_cfg(enc->rc_ctx, &usr_cfg);
1335 rc_cfg->change = 0;
1336 prep_cfg->change = 0;
1337
1338 enc_dbg_detail("rc update cfg done\n");
1339 enc->rc_status.rc_api_user_cfg = 0;
1340
1341 enc->rc_cfg_length = enc->rc_cfg_pos;
1342 update_rc_cfg_log(enc, "%s-b:%d[%d:%d]-g:%d-q:%d:[%d:%d]:[%d:%d]:%d\n",
1343 name_of_rc_mode[usr_cfg.mode],
1344 usr_cfg.bps_target,
1345 usr_cfg.bps_min, usr_cfg.bps_max, usr_cfg.igop,
1346 usr_cfg.init_quality,
1347 usr_cfg.min_quality, usr_cfg.max_quality,
1348 usr_cfg.min_i_quality, usr_cfg.max_i_quality,
1349 usr_cfg.i_quality_delta);
1350 }
1351
1352 return ret;
1353 }
1354
1355 #define ENC_RUN_FUNC2(func, ctx, task, mpp, ret) \
1356 ret = func(ctx, task); \
1357 if (ret) { \
1358 mpp_err("mpp %p "#func":%-4d failed return %d", \
1359 mpp, __LINE__, ret); \
1360 goto TASK_DONE; \
1361 }
1362
mpp_enc_check_frm_pkt(MppEncImpl * enc)1363 static MPP_RET mpp_enc_check_frm_pkt(MppEncImpl *enc)
1364 {
1365 enc->frm_buf = NULL;
1366 enc->pkt_buf = NULL;
1367
1368 if (enc->packet)
1369 enc->pkt_buf = mpp_packet_get_buffer(enc->packet);
1370 else
1371 mpp_packet_new(&enc->packet);
1372
1373 if (enc->frame) {
1374 RK_S64 pts = mpp_frame_get_pts(enc->frame);
1375 MppBuffer frm_buf = mpp_frame_get_buffer(enc->frame);
1376
1377 enc->task_pts = pts;
1378 enc->frm_buf = frm_buf;
1379
1380 mpp_packet_set_pts(enc->packet, pts);
1381 mpp_packet_set_dts(enc->packet, mpp_frame_get_dts(enc->frame));
1382
1383 if (mpp_frame_get_eos(enc->frame))
1384 mpp_packet_set_eos(enc->packet);
1385 else
1386 mpp_packet_clr_eos(enc->packet);
1387 }
1388
1389 return (NULL == enc->frame || NULL == enc->frm_buf) ? MPP_NOK : MPP_OK;
1390 }
1391
mpp_enc_check_pkt_buf(MppEncImpl * enc)1392 static MPP_RET mpp_enc_check_pkt_buf(MppEncImpl *enc)
1393 {
1394 if (NULL == enc->pkt_buf) {
1395 /* NOTE: set buffer w * h * 1.5 to avoid buffer overflow */
1396 Mpp *mpp = (Mpp *)enc->mpp;
1397 MppEncPrepCfg *prep = &enc->cfg.prep;
1398 RK_U32 width = MPP_ALIGN(prep->width, 16);
1399 RK_U32 height = MPP_ALIGN(prep->height, 16);
1400 RK_U32 size = (enc->coding == MPP_VIDEO_CodingMJPEG) ?
1401 (width * height * 3 / 2) : (width * height);
1402 MppPacketImpl *pkt = (MppPacketImpl *)enc->packet;
1403 MppBuffer buffer = NULL;
1404
1405 mpp_assert(size);
1406 mpp_buffer_get(mpp->mPacketGroup, &buffer, size);
1407 mpp_assert(buffer);
1408 enc->pkt_buf = buffer;
1409 pkt->data = mpp_buffer_get_ptr(buffer);
1410 pkt->pos = pkt->data;
1411 pkt->size = mpp_buffer_get_size(buffer);
1412 pkt->length = 0;
1413 pkt->buffer = buffer;
1414
1415 enc_dbg_detail("create output pkt %p buf %p\n", enc->packet, buffer);
1416 } else {
1417 enc_dbg_detail("output to pkt %p buf %p pos %p length %d\n",
1418 enc->packet, enc->pkt_buf,
1419 mpp_packet_get_pos(enc->packet),
1420 mpp_packet_get_length(enc->packet));
1421 }
1422
1423 return MPP_OK;
1424 }
1425
mpp_enc_proc_two_pass(Mpp * mpp,EncAsyncTaskInfo * task)1426 static MPP_RET mpp_enc_proc_two_pass(Mpp *mpp, EncAsyncTaskInfo *task)
1427 {
1428 MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
1429 MPP_RET ret = MPP_OK;
1430
1431 if (mpp_enc_refs_next_frm_is_intra(enc->refs)) {
1432 EncRcTask *rc_task = &task->rc;
1433 EncFrmStatus frm_bak = rc_task->frm;
1434 EncRcTaskInfo rc_info = rc_task->info;
1435 EncCpbStatus *cpb = &rc_task->cpb;
1436 EncFrmStatus *frm = &rc_task->frm;
1437 HalEncTask *hal_task = &task->task;
1438 EncImpl impl = enc->impl;
1439 MppEncHal hal = enc->enc_hal;
1440 MppPacket packet = hal_task->packet;
1441 RK_S32 task_len = hal_task->length;
1442 RK_S32 hw_len = hal_task->hw_length;
1443 RK_S32 pkt_len = mpp_packet_get_length(packet);
1444
1445 enc_dbg_detail("task %d two pass mode enter\n", frm->seq_idx);
1446 rc_task->info = enc->rc_info_prev;
1447 hal_task->segment_nb = mpp_packet_get_segment_nb(hal_task->packet);
1448
1449 enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx);
1450 mpp_enc_refs_get_cpb_pass1(enc->refs, cpb);
1451
1452 enc_dbg_frm_status("frm %d start ***********************************\n", cpb->curr.seq_idx);
1453 ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret);
1454
1455 enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx);
1456 ENC_RUN_FUNC2(enc_impl_proc_hal, impl, hal_task, mpp, ret);
1457
1458 enc_dbg_detail("task %d hal get task\n", frm->seq_idx);
1459 ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret);
1460
1461 enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx);
1462 ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret);
1463
1464 enc_dbg_detail("task %d hal start\n", frm->seq_idx);
1465 ENC_RUN_FUNC2(mpp_enc_hal_start, hal, hal_task, mpp, ret);
1466
1467 enc_dbg_detail("task %d hal wait\n", frm->seq_idx);
1468 ENC_RUN_FUNC2(mpp_enc_hal_wait, hal, hal_task, mpp, ret);
1469
1470 enc_dbg_detail("task %d hal ret task\n", frm->seq_idx);
1471 ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret);
1472
1473 //recover status & packet
1474 mpp_packet_set_length(packet, pkt_len);
1475 mpp_packet_set_segment_nb(packet, hal_task->segment_nb);
1476 hal_task->hw_length = hw_len;
1477 hal_task->length = task_len;
1478
1479 *frm = frm_bak;
1480 rc_task->info = rc_info;
1481
1482 enc_dbg_detail("task %d two pass mode leave\n", frm->seq_idx);
1483 }
1484 TASK_DONE:
1485 return ret;
1486 }
1487
mpp_enc_rc_info_backup(MppEncImpl * enc,EncAsyncTaskInfo * task)1488 static void mpp_enc_rc_info_backup(MppEncImpl *enc, EncAsyncTaskInfo *task)
1489 {
1490 if (!enc->support_hw_deflicker || !enc->cfg.rc.debreath_en)
1491 return;
1492
1493 enc->rc_info_prev = task->rc.info;
1494 }
1495
mpp_enc_add_sw_header(MppEncImpl * enc,HalEncTask * hal_task)1496 static void mpp_enc_add_sw_header(MppEncImpl *enc, HalEncTask *hal_task)
1497 {
1498 EncImpl impl = enc->impl;
1499 MppEncHeaderStatus *hdr_status = &enc->hdr_status;
1500 EncRcTask *rc_task = hal_task->rc_task;
1501 EncFrmStatus *frm = &rc_task->frm;
1502 MppPacket packet = hal_task->packet;
1503 MppFrame frame = hal_task->frame;
1504
1505 if (!(hdr_status->val & HDR_ADDED_MASK)) {
1506 RK_U32 add_header = 0;
1507
1508 if (enc->hdr_mode == MPP_ENC_HEADER_MODE_EACH_IDR && frm->is_intra)
1509 add_header |= 1;
1510
1511 if (enc->cfg.rc.refresh_en && frm->is_i_recovery && !frm->is_idr)
1512 add_header |= 2;
1513
1514 if (add_header) {
1515 enc_dbg_detail("task %d IDR header length %d\n",
1516 frm->seq_idx, enc->hdr_len);
1517
1518 mpp_packet_append(packet, enc->hdr_pkt);
1519
1520 hal_task->header_length = enc->hdr_len;
1521 hal_task->length += enc->hdr_len;
1522 hdr_status->added_by_mode = 1;
1523 }
1524
1525 if ((add_header & 2) && enc->sei_mode >= MPP_ENC_SEI_MODE_ONE_SEQ) {
1526 RK_S32 length = 0;
1527
1528 enc_impl_add_prefix(impl, packet, &length, uuid_refresh_cfg,
1529 &enc->cfg.rc.refresh_length, 0);
1530
1531 if (length) {
1532 enc_dbg_detail("task %d refresh header length %d\n",
1533 frm->seq_idx, enc->hdr_len);
1534
1535 hal_task->sei_length += length;
1536 hal_task->length += length;
1537 }
1538 }
1539 }
1540
1541 // check for header adding
1542 check_hal_task_pkt_len(hal_task, "header adding");
1543
1544 /* 17. Add all prefix info before encoding */
1545 if (frm->is_idr && enc->sei_mode >= MPP_ENC_SEI_MODE_ONE_SEQ) {
1546 RK_S32 length = 0;
1547
1548 enc_impl_add_prefix(impl, packet, &length, uuid_version,
1549 enc->version_info, enc->version_length);
1550
1551 hal_task->sei_length += length;
1552 hal_task->length += length;
1553
1554 length = 0;
1555 enc_impl_add_prefix(impl, packet, &length, uuid_rc_cfg,
1556 enc->rc_cfg_info, enc->rc_cfg_length);
1557
1558 hal_task->sei_length += length;
1559 hal_task->length += length;
1560 }
1561
1562 if (mpp_frame_has_meta(frame)) {
1563 update_user_datas(impl, packet, frame, hal_task);
1564 }
1565
1566 // check for user data adding
1567 check_hal_task_pkt_len(hal_task, "user data adding");
1568 }
1569
mpp_enc_normal(Mpp * mpp,EncAsyncTaskInfo * task)1570 static MPP_RET mpp_enc_normal(Mpp *mpp, EncAsyncTaskInfo *task)
1571 {
1572 MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
1573 EncImpl impl = enc->impl;
1574 MppEncHal hal = enc->enc_hal;
1575 EncRcTask *rc_task = &task->rc;
1576 EncCpbStatus *cpb = &rc_task->cpb;
1577 EncFrmStatus *frm = &rc_task->frm;
1578 HalEncTask *hal_task = &task->task;
1579 MPP_RET ret = MPP_OK;
1580
1581 if (enc->support_hw_deflicker && enc->cfg.rc.debreath_en) {
1582 ret = mpp_enc_proc_two_pass(mpp, task);
1583 if (ret)
1584 return ret;
1585 }
1586
1587 enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx);
1588 mpp_enc_refs_get_cpb(enc->refs, cpb);
1589
1590 enc_dbg_frm_status("frm %d start ***********************************\n", cpb->curr.seq_idx);
1591 ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret);
1592
1593 enc_dbg_frm_status("frm %d compare\n", cpb->curr.seq_idx);
1594 enc_dbg_frm_status("seq_idx %d vs %d\n", frm->seq_idx, cpb->curr.seq_idx);
1595 enc_dbg_frm_status("is_idr %d vs %d\n", frm->is_idr, cpb->curr.is_idr);
1596 enc_dbg_frm_status("is_intra %d vs %d\n", frm->is_intra, cpb->curr.is_intra);
1597 enc_dbg_frm_status("is_non_ref %d vs %d\n", frm->is_non_ref, cpb->curr.is_non_ref);
1598 enc_dbg_frm_status("is_lt_ref %d vs %d\n", frm->is_lt_ref, cpb->curr.is_lt_ref);
1599 enc_dbg_frm_status("lt_idx %d vs %d\n", frm->lt_idx, cpb->curr.lt_idx);
1600 enc_dbg_frm_status("temporal_id %d vs %d\n", frm->temporal_id, cpb->curr.temporal_id);
1601 enc_dbg_frm_status("frm %d done ***********************************\n", cpb->curr.seq_idx);
1602
1603 enc_dbg_detail("task %d rc frame start\n", frm->seq_idx);
1604 ENC_RUN_FUNC2(rc_frm_start, enc->rc_ctx, rc_task, mpp, ret);
1605
1606 // 16. generate header before hardware stream
1607 mpp_enc_add_sw_header(enc, hal_task);
1608
1609 enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx);
1610 ENC_RUN_FUNC2(enc_impl_proc_hal, impl, hal_task, mpp, ret);
1611
1612 enc_dbg_detail("task %d hal get task\n", frm->seq_idx);
1613 ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret);
1614
1615 enc_dbg_detail("task %d rc hal start\n", frm->seq_idx);
1616 ENC_RUN_FUNC2(rc_hal_start, enc->rc_ctx, rc_task, mpp, ret);
1617
1618 enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx);
1619 ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret);
1620
1621 hal_task->segment_nb = mpp_packet_get_segment_nb(hal_task->packet);
1622 mpp_stopwatch_record(hal_task->stopwatch, "encode hal start");
1623 enc_dbg_detail("task %d hal start\n", frm->seq_idx);
1624 ENC_RUN_FUNC2(mpp_enc_hal_start, hal, hal_task, mpp, ret);
1625
1626 enc_dbg_detail("task %d hal wait\n", frm->seq_idx);
1627 ENC_RUN_FUNC2(mpp_enc_hal_wait, hal, hal_task, mpp, ret);
1628
1629 mpp_stopwatch_record(hal_task->stopwatch, "encode hal finish");
1630
1631 enc_dbg_detail("task %d rc hal end\n", frm->seq_idx);
1632 ENC_RUN_FUNC2(rc_hal_end, enc->rc_ctx, rc_task, mpp, ret);
1633
1634 enc_dbg_detail("task %d hal ret task\n", frm->seq_idx);
1635 ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret);
1636
1637 enc_dbg_detail("task %d rc frame check reenc\n", frm->seq_idx);
1638 ENC_RUN_FUNC2(rc_frm_check_reenc, enc->rc_ctx, rc_task, mpp, ret);
1639
1640 TASK_DONE:
1641 return ret;
1642 }
1643
mpp_enc_clr_rc_cb_info(EncRcTask * rc_task)1644 static void mpp_enc_clr_rc_cb_info(EncRcTask *rc_task)
1645 {
1646 EncRcTaskInfo *hal_rc = (EncRcTaskInfo *) &rc_task->info;
1647 EncRcTaskInfo bak = rc_task->info;
1648
1649 memset(hal_rc, 0, sizeof(rc_task->info));
1650
1651 hal_rc->frame_type = bak.frame_type;
1652 hal_rc->bit_target = bak.bit_target;
1653 hal_rc->bit_max = bak.bit_max;
1654 hal_rc->bit_min = bak.bit_min;
1655 hal_rc->quality_target = bak.quality_target;
1656 hal_rc->quality_max = bak.quality_max;
1657 hal_rc->quality_min = bak.quality_min;
1658 }
1659
mpp_enc_reenc_simple(Mpp * mpp,EncAsyncTaskInfo * task)1660 static MPP_RET mpp_enc_reenc_simple(Mpp *mpp, EncAsyncTaskInfo *task)
1661 {
1662 MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
1663 MppEncHal hal = enc->enc_hal;
1664 EncRcTask *rc_task = &task->rc;
1665 EncFrmStatus *frm = &rc_task->frm;
1666 HalEncTask *hal_task = &task->task;
1667 MPP_RET ret = MPP_OK;
1668
1669 enc_dbg_func("enter\n");
1670
1671 mpp_enc_clr_rc_cb_info(rc_task);
1672
1673 enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx);
1674 ENC_RUN_FUNC2(enc_impl_proc_hal, enc->impl, hal_task, mpp, ret);
1675
1676 enc_dbg_detail("task %d hal get task\n", frm->seq_idx);
1677 ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret);
1678
1679 enc_dbg_detail("task %d rc hal start\n", frm->seq_idx);
1680 ENC_RUN_FUNC2(rc_hal_start, enc->rc_ctx, rc_task, mpp, ret);
1681
1682 enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx);
1683 ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret);
1684
1685 enc_dbg_detail("task %d hal start\n", frm->seq_idx);
1686 ENC_RUN_FUNC2(mpp_enc_hal_start, hal, hal_task, mpp, ret);
1687
1688 enc_dbg_detail("task %d hal wait\n", frm->seq_idx);
1689 ENC_RUN_FUNC2(mpp_enc_hal_wait, hal, hal_task, mpp, ret);
1690
1691 enc_dbg_detail("task %d rc hal end\n", frm->seq_idx);
1692 ENC_RUN_FUNC2(rc_hal_end, enc->rc_ctx, rc_task, mpp, ret);
1693
1694 enc_dbg_detail("task %d hal ret task\n", frm->seq_idx);
1695 ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret);
1696
1697 enc_dbg_detail("task %d rc frame check reenc\n", frm->seq_idx);
1698 ENC_RUN_FUNC2(rc_frm_check_reenc, enc->rc_ctx, rc_task, mpp, ret);
1699
1700 enc_dbg_detail("task %d reenc %d times %d\n", frm->seq_idx, frm->reencode, frm->reencode_times);
1701 enc_dbg_func("leave\n");
1702
1703 TASK_DONE:
1704 return ret;
1705 }
1706
mpp_enc_reenc_drop(Mpp * mpp,EncAsyncTaskInfo * task)1707 static MPP_RET mpp_enc_reenc_drop(Mpp *mpp, EncAsyncTaskInfo *task)
1708 {
1709 MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
1710 EncRcTask *rc_task = &task->rc;
1711 EncRcTaskInfo *info = &rc_task->info;
1712 EncFrmStatus *frm = &rc_task->frm;
1713 HalEncTask *hal_task = &task->task;
1714 MPP_RET ret = MPP_OK;
1715
1716 enc_dbg_func("enter\n");
1717 mpp_enc_refs_rollback(enc->refs);
1718
1719 info->bit_real = hal_task->length;
1720 info->quality_real = info->quality_target;
1721
1722 enc_dbg_detail("task %d rc frame end\n", frm->seq_idx);
1723 ENC_RUN_FUNC2(rc_frm_end, enc->rc_ctx, rc_task, mpp, ret);
1724
1725 TASK_DONE:
1726 enc_dbg_func("leave\n");
1727 return ret;
1728 }
1729
mpp_enc_reenc_force_pskip(Mpp * mpp,EncAsyncTaskInfo * task)1730 static MPP_RET mpp_enc_reenc_force_pskip(Mpp *mpp, EncAsyncTaskInfo *task)
1731 {
1732 MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
1733 EncImpl impl = enc->impl;
1734 MppEncRefFrmUsrCfg *frm_cfg = &task->usr;
1735 EncRcTask *rc_task = &task->rc;
1736 EncCpbStatus *cpb = &rc_task->cpb;
1737 EncFrmStatus *frm = &rc_task->frm;
1738 HalEncTask *hal_task = &task->task;
1739 MPP_RET ret = MPP_OK;
1740
1741 enc_dbg_func("enter\n");
1742
1743 frm_cfg->force_pskip++;
1744 frm_cfg->force_flag |= ENC_FORCE_PSKIP;
1745
1746 /* NOTE: in some condition the pskip should not happen */
1747
1748 mpp_enc_refs_rollback(enc->refs);
1749 mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg);
1750
1751 enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx);
1752 mpp_enc_refs_get_cpb(enc->refs, cpb);
1753
1754 enc_dbg_frm_status("frm %d start ***********************************\n", cpb->curr.seq_idx);
1755 ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret);
1756
1757 enc_dbg_detail("task %d enc sw enc start\n", frm->seq_idx);
1758 ENC_RUN_FUNC2(enc_impl_sw_enc, impl, hal_task, mpp, ret);
1759
1760 enc_dbg_detail("task %d rc frame end\n", frm->seq_idx);
1761 ENC_RUN_FUNC2(rc_frm_end, enc->rc_ctx, rc_task, mpp, ret);
1762
1763 TASK_DONE:
1764 enc_dbg_func("leave\n");
1765 return ret;
1766 }
1767
mpp_enc_terminate_task(MppEncImpl * enc,EncAsyncTaskInfo * task)1768 static void mpp_enc_terminate_task(MppEncImpl *enc, EncAsyncTaskInfo *task)
1769 {
1770 HalEncTask *hal_task = &task->task;
1771 EncFrmStatus *frm = &task->rc.frm;
1772
1773 mpp_stopwatch_record(hal_task->stopwatch, "encode task done");
1774
1775 if (enc->packet) {
1776 /* setup output packet and meta data */
1777 mpp_packet_set_length(enc->packet, hal_task->length);
1778
1779 /*
1780 * First return output packet.
1781 * Then enqueue task back to input port.
1782 * Final user will release the mpp_frame they had input.
1783 */
1784 enc_dbg_detail("task %d enqueue packet pts %lld\n", frm->seq_idx, enc->task_pts);
1785
1786 mpp_task_meta_set_packet(enc->task_out, KEY_OUTPUT_PACKET, enc->packet);
1787 mpp_port_enqueue(enc->output, enc->task_out);
1788 }
1789
1790 if (enc->task_in) {
1791 enc_dbg_detail("task %d enqueue frame pts %lld\n", frm->seq_idx, enc->task_pts);
1792
1793 mpp_task_meta_set_frame(enc->task_in, KEY_INPUT_FRAME, enc->frame);
1794 mpp_port_enqueue(enc->input, enc->task_in);
1795 }
1796
1797 reset_enc_task(enc);
1798 task->status.val = 0;
1799 }
1800
try_get_enc_task(MppEncImpl * enc,EncAsyncTaskInfo * task,EncAsyncWait * wait)1801 static MPP_RET try_get_enc_task(MppEncImpl *enc, EncAsyncTaskInfo *task, EncAsyncWait *wait)
1802 {
1803 EncRcTask *rc_task = &task->rc;
1804 EncFrmStatus *frm = &rc_task->frm;
1805 MppEncRefFrmUsrCfg *frm_cfg = &task->usr;
1806 MppEncHeaderStatus *hdr_status = &enc->hdr_status;
1807 EncAsyncStatus *status = &task->status;
1808 HalEncTask *hal_task = &task->task;
1809 MppStopwatch stopwatch = NULL;
1810 MPP_RET ret = MPP_OK;
1811
1812 if (!status->task_in_rdy) {
1813 ret = mpp_port_poll(enc->input, MPP_POLL_NON_BLOCK);
1814 if (ret < 0) {
1815 wait->enc_frm_in = 1;
1816 return ret;
1817 }
1818
1819 status->task_in_rdy = 1;
1820 wait->enc_frm_in = 0;
1821 enc_dbg_detail("task in ready\n");
1822 }
1823
1824 // 5. check output task
1825 if (!status->task_out_rdy) {
1826 ret = mpp_port_poll(enc->output, MPP_POLL_NON_BLOCK);
1827 if (ret < 0) {
1828 wait->enc_pkt_out = 1;
1829 return ret;
1830 }
1831
1832 status->task_out_rdy = 1;
1833 wait->enc_pkt_out = 0;
1834 enc_dbg_detail("task out ready\n");
1835 }
1836
1837 /*
1838 * 6. get frame and packet for one task
1839 * If there is no input frame just return empty packet task
1840 */
1841 if (!status->frm_pkt_rdy) {
1842 // get tasks from both input and output
1843 ret = mpp_port_dequeue(enc->input, &enc->task_in);
1844 mpp_assert(enc->task_in);
1845
1846 ret = mpp_port_dequeue(enc->output, &enc->task_out);
1847 mpp_assert(enc->task_out);
1848
1849 /*
1850 * frame will be return to input.
1851 * packet will be sent to output.
1852 */
1853 mpp_task_meta_get_frame (enc->task_in, KEY_INPUT_FRAME, &enc->frame);
1854 mpp_task_meta_get_packet(enc->task_in, KEY_OUTPUT_PACKET, &enc->packet);
1855 mpp_task_meta_get_buffer(enc->task_in, KEY_MOTION_INFO, &enc->md_info);
1856
1857 enc_dbg_detail("task dequeue done frm %p pkt %p\n", enc->frame, enc->packet);
1858
1859 stopwatch = mpp_frame_get_stopwatch(enc->frame);
1860 mpp_stopwatch_record(stopwatch, "encode task start");
1861
1862 if (mpp_enc_check_frm_pkt(enc)) {
1863 mpp_stopwatch_record(stopwatch, "invalid on check frm pkt");
1864 reset_hal_enc_task(hal_task);
1865 ret = MPP_NOK;
1866 goto TASK_DONE;
1867 }
1868
1869 status->frm_pkt_rdy = 1;
1870 enc_dbg_detail("task frame packet ready\n");
1871 }
1872
1873 // 8. all task ready start encoding one frame
1874 if (!status->hal_task_reset_rdy) {
1875 reset_hal_enc_task(hal_task);
1876 reset_enc_rc_task(rc_task);
1877 task->usr = enc->frm_cfg;
1878 enc->frm_cfg.force_flag = 0;
1879
1880 hal_task->rc_task = rc_task;
1881 hal_task->frm_cfg = frm_cfg;
1882 hal_task->frame = enc->frame;
1883 hal_task->input = enc->frm_buf;
1884 hal_task->packet = enc->packet;
1885 hal_task->output = enc->pkt_buf;
1886 hal_task->md_info = enc->md_info;
1887 hal_task->stopwatch = stopwatch;
1888
1889 frm->seq_idx = task->seq_idx++;
1890 rc_task->frame = enc->frame;
1891 enc_dbg_detail("task seq idx %d start\n", frm->seq_idx);
1892 }
1893
1894 // 9. check frame drop by frame rate conversion
1895 if (!status->rc_check_frm_drop) {
1896 ENC_RUN_FUNC2(rc_frm_check_drop, enc->rc_ctx, rc_task, enc->mpp, ret);
1897 status->rc_check_frm_drop = 1;
1898 enc_dbg_detail("task %d drop %d\n", frm->seq_idx, frm->drop);
1899
1900 hal_task->valid = 1;
1901 // when the frame should be dropped just return empty packet
1902 if (frm->drop) {
1903 mpp_stopwatch_record(stopwatch, "invalid on frame rate drop");
1904 hal_task->length = 0;
1905 hal_task->flags.drop_by_fps = 1;
1906 status->enc_start = 1;
1907 if (!status->refs_force_update) {
1908 if (frm_cfg->force_flag)
1909 mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg);
1910
1911 status->refs_force_update = 1;
1912 }
1913 ret = MPP_OK;
1914 goto TASK_DONE;
1915 }
1916 }
1917
1918 // start encoder task process here
1919 mpp_assert(hal_task->valid);
1920
1921 // 10. check and create packet for output
1922 if (!status->pkt_buf_rdy) {
1923 mpp_enc_check_pkt_buf(enc);
1924 status->pkt_buf_rdy = 1;
1925
1926 hal_task->output = enc->pkt_buf;
1927 }
1928 mpp_assert(enc->packet);
1929 mpp_assert(enc->pkt_buf);
1930
1931 // 11. check hal info update
1932 if (!enc->hal_info_updated) {
1933 update_enc_hal_info(enc);
1934 enc->hal_info_updated = 1;
1935 }
1936
1937 // 12. generate header before hardware stream
1938 if (!hdr_status->ready) {
1939 /* config cpb before generating header */
1940 enc_impl_gen_hdr(enc->impl, enc->hdr_pkt);
1941 enc->hdr_len = mpp_packet_get_length(enc->hdr_pkt);
1942 hdr_status->ready = 1;
1943
1944 enc_dbg_detail("task %d update header length %d\n",
1945 frm->seq_idx, enc->hdr_len);
1946
1947 mpp_packet_append(enc->packet, enc->hdr_pkt);
1948 hal_task->header_length = enc->hdr_len;
1949 hal_task->length += enc->hdr_len;
1950 hdr_status->added_by_change = 1;
1951 }
1952
1953 check_hal_task_pkt_len(hal_task, "gen_hdr and adding");
1954
1955 // 13. check frm_meta data force key in input frame and start one frame
1956 if (!status->enc_start) {
1957 enc_dbg_detail("task %d enc start\n", frm->seq_idx);
1958 ENC_RUN_FUNC2(enc_impl_start, enc->impl, hal_task, enc->mpp, ret);
1959 status->enc_start = 1;
1960 }
1961
1962 // 14. setup user_cfg to dpb
1963 if (!status->refs_force_update) {
1964 if (frm_cfg->force_flag)
1965 mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg);
1966
1967 status->refs_force_update = 1;
1968 }
1969
1970 // 15. backup dpb
1971 if (!status->enc_backup) {
1972 mpp_enc_refs_stash(enc->refs);
1973 status->enc_backup = 1;
1974 }
1975
1976 TASK_DONE:
1977 if (ret)
1978 mpp_enc_terminate_task(enc, task);
1979 return ret;
1980 }
1981
try_proc_low_deley_task(Mpp * mpp,EncAsyncTaskInfo * task,EncAsyncWait * wait)1982 static MPP_RET try_proc_low_deley_task(Mpp *mpp, EncAsyncTaskInfo *task, EncAsyncWait *wait)
1983 {
1984 MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
1985 EncImpl impl = enc->impl;
1986 MppEncHal hal = enc->enc_hal;
1987 EncRcTask *rc_task = &task->rc;
1988 EncCpbStatus *cpb = &rc_task->cpb;
1989 EncFrmStatus *frm = &rc_task->frm;
1990 EncAsyncStatus *status = &task->status;
1991 HalEncTask *hal_task = &task->task;
1992 MppPacket packet = hal_task->packet;
1993 MPP_RET ret = MPP_OK;
1994
1995 if (hal_task->flags.drop_by_fps)
1996 goto TASK_DONE;
1997
1998 if (status->low_delay_again)
1999 goto GET_OUTPUT_TASK;
2000
2001 enc_dbg_detail("task %d enc proc dpb\n", frm->seq_idx);
2002 mpp_enc_refs_get_cpb(enc->refs, cpb);
2003
2004 enc_dbg_frm_status("frm %d start ***********************************\n", cpb->curr.seq_idx);
2005 ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret);
2006
2007 enc_dbg_detail("task %d rc frame start\n", frm->seq_idx);
2008 ENC_RUN_FUNC2(rc_frm_start, enc->rc_ctx, rc_task, mpp, ret);
2009
2010 // 16. generate header before hardware stream
2011 mpp_enc_add_sw_header(enc, hal_task);
2012
2013 enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx);
2014 ENC_RUN_FUNC2(enc_impl_proc_hal, impl, hal_task, mpp, ret);
2015
2016 enc_dbg_detail("task %d hal get task\n", frm->seq_idx);
2017 ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret);
2018
2019 enc_dbg_detail("task %d rc hal start\n", frm->seq_idx);
2020 ENC_RUN_FUNC2(rc_hal_start, enc->rc_ctx, rc_task, mpp, ret);
2021
2022 enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx);
2023 ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret);
2024
2025 hal_task->part_first = 0;
2026 hal_task->part_last = 0;
2027
2028 do {
2029 enc_dbg_detail("task %d hal start\n", frm->seq_idx);
2030 ENC_RUN_FUNC2(mpp_enc_hal_part_start, hal, hal_task, mpp, ret);
2031
2032 enc_dbg_detail("task %d hal wait\n", frm->seq_idx);
2033 ENC_RUN_FUNC2(mpp_enc_hal_part_wait, hal, hal_task, mpp, ret);
2034
2035 enc_dbg_detail("task %d hal ret task\n", frm->seq_idx);
2036 ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret);
2037
2038 if (hal_task->part_first) {
2039 hal_task->part_pos = (RK_U8 *)mpp_packet_get_pos(packet);
2040 hal_task->part_length = 0;
2041 }
2042
2043 mpp_packet_set_length(packet, hal_task->length);
2044
2045 enc_dbg_detail("task %d task_out %p\n", frm->seq_idx, enc->task_out);
2046
2047 GET_OUTPUT_TASK:
2048 /* output task as soon as */
2049 if (NULL == enc->task_out) {
2050 enc_dbg_detail("task %d poll new task for part output\n", frm->seq_idx);
2051 ret = mpp_port_poll(enc->output, MPP_POLL_NON_BLOCK);
2052 if (ret < 0) {
2053 wait->enc_pkt_out = 1;
2054 status->low_delay_again = 1;
2055 return MPP_NOK;
2056 }
2057
2058 status->task_out_rdy = 1;
2059 wait->enc_pkt_out = 0;
2060 enc_dbg_detail("task out ready\n");
2061
2062 ret = mpp_port_dequeue(enc->output, &enc->task_out);
2063 }
2064
2065 mpp_assert(enc->task_out);
2066
2067 /* copy new packet for multiple packet output */
2068 if (!hal_task->part_last) {
2069 RK_U8 *part_pos = (RK_U8 *)mpp_packet_get_pos(packet);
2070 RK_U32 part_length = hal_task->length;
2071 RK_U8 *last_pos = (RK_U8 *)hal_task->part_pos;
2072 RK_U32 pkt_len = 0;
2073 MppPacketImpl *part_pkt = NULL;
2074
2075 enc_dbg_detail("pkt %d last %p part %p len %d\n", hal_task->part_count,
2076 last_pos, part_pos, part_length);
2077
2078 part_pos += part_length;
2079 pkt_len = (RK_U32)(part_pos - last_pos);
2080
2081 mpp_packet_copy_init((MppPacket *)&part_pkt, packet);
2082 part_pkt->pos = last_pos;
2083 part_pkt->length = pkt_len;
2084 part_pkt->status.val = 0;
2085 part_pkt->status.partition = 1;
2086 part_pkt->status.soi = hal_task->part_first;
2087 part_pkt->status.eoi = hal_task->part_last;
2088
2089 enc_dbg_detail("pkt %d new pos %p len %d\n", hal_task->part_count,
2090 last_pos, pkt_len);
2091
2092 hal_task->part_pos = part_pos;
2093
2094 enc_dbg_detail("task %d enqueue packet pts %lld part %d\n",
2095 frm->seq_idx, enc->task_pts, hal_task->part_count);
2096 mpp_task_meta_set_packet(enc->task_out, KEY_OUTPUT_PACKET, part_pkt);
2097 mpp_port_enqueue(enc->output, enc->task_out);
2098 enc->task_out = NULL;
2099 hal_task->part_count++;
2100 }
2101 } while (!hal_task->part_last);
2102
2103 TASK_DONE:
2104 /* output last task */
2105 {
2106 RK_U8 *part_pos = (RK_U8 *)mpp_packet_get_pos(packet);
2107 size_t part_length = hal_task->length;
2108 RK_U8 *last_pos = (RK_U8 *)hal_task->part_pos;
2109 RK_U32 pkt_len = 0;
2110 MppPacketImpl *pkt = (MppPacketImpl *)packet;
2111
2112 enc_dbg_detail("pkt %d last %p part %p len %d\n", hal_task->part_count,
2113 last_pos, part_pos, part_length);
2114
2115 part_pos += part_length;
2116 pkt_len = part_pos - last_pos;
2117
2118 enc_dbg_detail("pkt %d new pos %p len %d\n", hal_task->part_count,
2119 last_pos, pkt_len);
2120
2121 pkt->length = pkt_len;
2122 pkt->pos = last_pos;
2123 pkt->status.val = 0;
2124 pkt->status.partition = 1;
2125 pkt->status.soi = hal_task->part_first;
2126 pkt->status.eoi = hal_task->part_last;
2127
2128 enc_dbg_detail("pkt %d new pos %p len %d\n", hal_task->part_count,
2129 last_pos, pkt_len);
2130
2131 hal_task->part_pos = part_pos;
2132
2133 enc_dbg_detail("task %d enqueue packet pts %lld part %d\n",
2134 frm->seq_idx, enc->task_pts, hal_task->part_count);
2135 mpp_task_meta_set_packet(enc->task_out, KEY_OUTPUT_PACKET, packet);
2136 mpp_port_enqueue(enc->output, enc->task_out);
2137 enc->task_out = NULL;
2138 hal_task->part_count = 0;
2139 }
2140 status->low_delay_again = 0;
2141
2142 enc->time_end = mpp_time();
2143 enc->frame_count++;
2144
2145 if (enc->dev && enc->time_base && enc->time_end &&
2146 ((enc->time_end - enc->time_base) >= (RK_S64)(1000 * 1000)))
2147 update_hal_info_fps(enc);
2148
2149 enc_dbg_detail("task %d rc hal end\n", frm->seq_idx);
2150 ENC_RUN_FUNC2(rc_hal_end, enc->rc_ctx, rc_task, mpp, ret);
2151
2152 enc_dbg_detail("task %d enqueue frame pts %lld\n", frm->seq_idx, enc->task_pts);
2153
2154 mpp_task_meta_set_frame(enc->task_in, KEY_INPUT_FRAME, enc->frame);
2155 mpp_port_enqueue(enc->input, enc->task_in);
2156
2157 reset_enc_task(enc);
2158 status->val = 0;
2159 task->usr.force_flag = 0;
2160
2161 return ret;
2162 }
2163
try_proc_normal_task(MppEncImpl * enc,EncAsyncTaskInfo * task)2164 static MPP_RET try_proc_normal_task(MppEncImpl *enc, EncAsyncTaskInfo *task)
2165 {
2166 Mpp *mpp = (Mpp*)enc->mpp;
2167 EncRcTask *rc_task = &task->rc;
2168 EncFrmStatus *frm = &rc_task->frm;
2169 MppEncRefFrmUsrCfg *frm_cfg = &task->usr;
2170 HalEncTask *hal_task = &task->task;
2171 MppPacket packet = hal_task->packet;
2172 MPP_RET ret = MPP_OK;
2173
2174 if (hal_task->flags.drop_by_fps)
2175 goto TASK_DONE;
2176
2177 // 17. normal encode
2178 ENC_RUN_FUNC2(mpp_enc_normal, mpp, task, mpp, ret);
2179
2180 // 18. drop, force pskip and reencode process
2181 while (frm->reencode && frm->reencode_times < enc->cfg.rc.max_reenc_times) {
2182 hal_task->length -= hal_task->hw_length;
2183 hal_task->hw_length = 0;
2184
2185 mpp_packet_set_segment_nb(hal_task->packet, hal_task->segment_nb);
2186
2187 enc_dbg_detail("task %d reenc %d times %d\n", frm->seq_idx, frm->reencode, frm->reencode_times);
2188
2189 if (frm->drop) {
2190 mpp_enc_reenc_drop(mpp, task);
2191 break;
2192 }
2193
2194 if (frm->force_pskip && !frm->is_idr && !frm->is_lt_ref) {
2195 mpp_enc_reenc_force_pskip(mpp, task);
2196 break;
2197 }
2198
2199 mpp_enc_reenc_simple(mpp, task);
2200 }
2201 enc_dbg_detail("task %d rc frame end\n", frm->seq_idx);
2202 ENC_RUN_FUNC2(rc_frm_end, enc->rc_ctx, rc_task, mpp, ret);
2203
2204 enc->time_end = mpp_time();
2205 enc->frame_count++;
2206
2207 if (enc->dev && enc->time_base && enc->time_end &&
2208 ((enc->time_end - enc->time_base) >= (RK_S64)(1000 * 1000)))
2209 update_hal_info_fps(enc);
2210
2211 frm->reencode = 0;
2212 frm->reencode_times = 0;
2213 frm_cfg->force_flag = 0;
2214
2215 TASK_DONE:
2216 mpp_stopwatch_record(hal_task->stopwatch, "encode task done");
2217
2218 if (!mpp_packet_is_partition(packet)) {
2219 /* setup output packet and meta data */
2220 mpp_packet_set_length(packet, hal_task->length);
2221 }
2222
2223 {
2224 MppMeta meta = mpp_packet_get_meta(packet);
2225
2226 if (hal_task->md_info)
2227 mpp_meta_set_buffer(meta, KEY_MOTION_INFO, hal_task->md_info);
2228
2229 mpp_meta_set_s32(meta, KEY_OUTPUT_INTRA, frm->is_intra);
2230 if (rc_task->info.quality_real)
2231 mpp_meta_set_s32(meta, KEY_ENC_AVERAGE_QP, rc_task->info.quality_real);
2232
2233 if (mpp->mEncAyncIo)
2234 mpp_meta_set_frame(meta, KEY_INPUT_FRAME, enc->frame);
2235 }
2236
2237 /* enc failed force idr */
2238 if (ret) {
2239 enc->frm_cfg.force_flag |= ENC_FORCE_IDR;
2240 enc->hdr_status.val = 0;
2241 mpp_packet_set_length(packet, 0);
2242 mpp_err_f("enc failed force idr!\n");
2243 }
2244 /*
2245 * First return output packet.
2246 * Then enqueue task back to input port.
2247 * Final user will release the mpp_frame they had input.
2248 */
2249 enc_dbg_detail("task %d enqueue packet pts %lld\n", frm->seq_idx, enc->task_pts);
2250
2251 mpp_task_meta_set_packet(enc->task_out, KEY_OUTPUT_PACKET, packet);
2252 mpp_port_enqueue(enc->output, enc->task_out);
2253
2254 enc_dbg_detail("task %d enqueue frame pts %lld\n", frm->seq_idx, enc->task_pts);
2255
2256 mpp_task_meta_set_frame(enc->task_in, KEY_INPUT_FRAME, enc->frame);
2257 mpp_port_enqueue(enc->input, enc->task_in);
2258
2259 mpp_enc_rc_info_backup(enc, task);
2260 reset_enc_task(enc);
2261 task->status.val = 0;
2262
2263 return ret;
2264 }
2265
mpp_enc_thread(void * data)2266 void *mpp_enc_thread(void *data)
2267 {
2268 Mpp *mpp = (Mpp*)data;
2269 MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
2270 MppThread *thd_enc = enc->thread_enc;
2271 EncAsyncTaskInfo task;
2272 EncAsyncWait wait;
2273 EncAsyncStatus *status = &task.status;
2274 MPP_RET ret = MPP_OK;
2275
2276 memset(&task, 0, sizeof(task));
2277 wait.val = 0;
2278
2279 enc->time_base = mpp_time();
2280
2281 while (1) {
2282 {
2283 AutoMutex autolock(thd_enc->mutex());
2284 if (MPP_THREAD_RUNNING != thd_enc->get_status())
2285 break;
2286
2287 if (check_enc_task_wait(enc, &wait))
2288 thd_enc->wait();
2289 }
2290
2291 // When encoder is not on encoding process external config and reset
2292 if (!status->enc_start) {
2293 // 1. process user control
2294 if (enc->cmd_send != enc->cmd_recv) {
2295 enc_dbg_detail("ctrl proc %d cmd %08x\n", enc->cmd_recv, enc->cmd);
2296 sem_wait(&enc->cmd_start);
2297 ret = mpp_enc_proc_cfg(enc, enc->cmd, enc->param);
2298 if (ret)
2299 *enc->cmd_ret = ret;
2300 enc->cmd_recv++;
2301 enc_dbg_detail("ctrl proc %d done send %d\n", enc->cmd_recv,
2302 enc->cmd_send);
2303 mpp_assert(enc->cmd_send == enc->cmd_send);
2304 enc->param = NULL;
2305 enc->cmd = (MpiCmd)0;
2306 sem_post(&enc->cmd_done);
2307
2308 // async cfg update process for hal
2309 // mainly for buffer prepare
2310 mpp_enc_hal_prepare(enc->enc_hal);
2311
2312 /* NOTE: here will clear change flag of rc and prep cfg */
2313 mpp_enc_proc_rc_update(enc);
2314 wait.val = 0;
2315 continue;
2316 }
2317
2318 // 2. process reset
2319 if (enc->reset_flag) {
2320 enc_dbg_detail("thread reset start\n");
2321 {
2322 AutoMutex autolock(thd_enc->mutex());
2323 enc->status_flag = 0;
2324 }
2325
2326 enc->frm_cfg.force_flag |= ENC_FORCE_IDR;
2327 enc->frm_cfg.force_idr++;
2328
2329 AutoMutex autolock(thd_enc->mutex(THREAD_CONTROL));
2330 enc->reset_flag = 0;
2331 sem_post(&enc->enc_reset);
2332 enc_dbg_detail("thread reset done\n");
2333 wait.val = 0;
2334 continue;
2335 }
2336
2337 // 3. try get a task to encode
2338 ret = try_get_enc_task(enc, &task, &wait);
2339 if (ret)
2340 continue;
2341 }
2342
2343 mpp_assert(status->enc_start);
2344 if (!status->enc_start)
2345 continue;
2346
2347 // check partition low delay encoding
2348 /*
2349 * NOTE: Only when both split encoding and low delay mode are set then
2350 * use special low delay path
2351 */
2352 if (enc->low_delay_part_mode)
2353 try_proc_low_deley_task(mpp, &task, &wait);
2354 else
2355 try_proc_normal_task(enc, &task);
2356 }
2357
2358 // clear remain task in enc->output port
2359 release_task_in_port(enc->input);
2360 release_task_in_port(mpp->mUsrOutPort);
2361
2362 return NULL;
2363 }
2364
async_task_reset(EncAsyncTaskInfo * task)2365 static void async_task_reset(EncAsyncTaskInfo *task)
2366 {
2367 memset(task, 0, sizeof(*task));
2368 task->task.rc_task = &task->rc;
2369 task->task.frm_cfg = &task->usr;
2370 task->usr.force_flag = 0;
2371 }
2372
async_task_terminate(MppEncImpl * enc,EncAsyncTaskInfo * async)2373 static void async_task_terminate(MppEncImpl *enc, EncAsyncTaskInfo *async)
2374 {
2375 HalEncTask *hal_task = &async->task;
2376 EncFrmStatus *frm = &async->rc.frm;
2377 Mpp *mpp = (Mpp *)enc->mpp;
2378
2379 mpp_stopwatch_record(hal_task->stopwatch, "encode task done");
2380
2381 if (hal_task->packet) {
2382 MppPacket pkt = hal_task->packet;
2383
2384 /* setup output packet and meta data */
2385 mpp_packet_set_length(pkt, hal_task->length);
2386
2387 /*
2388 * First return output packet.
2389 * Then enqueue task back to input port.
2390 * Final user will release the mpp_frame they had input.
2391 */
2392 enc_dbg_detail("task %d enqueue packet pts %lld\n", frm->seq_idx, enc->task_pts);
2393
2394 if (mpp->mPktOut) {
2395 mpp_list *pkt_out = mpp->mPktOut;
2396
2397 if (enc->frame) {
2398 MppMeta meta = mpp_packet_get_meta(pkt);
2399 MppStopwatch stopwatch = mpp_frame_get_stopwatch(enc->frame);
2400
2401 mpp_stopwatch_record(stopwatch, "encode task terminate");
2402
2403 mpp_meta_set_frame(meta, KEY_INPUT_FRAME, enc->frame);
2404 enc->frame = NULL;
2405 }
2406
2407 AutoMutex autolock(pkt_out->mutex());
2408
2409 pkt_out->add_at_tail(&pkt, sizeof(pkt));
2410 mpp->mPacketPutCount++;
2411 pkt_out->signal();
2412 mpp_assert(pkt);
2413
2414 enc_dbg_detail("packet out ready\n");
2415 }
2416 }
2417
2418 async_task_reset(async);
2419 }
2420
async_task_skip(MppEncImpl * enc)2421 static void async_task_skip(MppEncImpl *enc)
2422 {
2423 Mpp *mpp = (Mpp*)enc->mpp;
2424 MppStopwatch stopwatch = NULL;
2425 MppMeta meta = NULL;
2426 MppFrame frm = NULL;
2427 MppPacket pkt = NULL;
2428
2429 mpp->mFrmIn->del_at_head(&frm, sizeof(frm));
2430 mpp->mFrameGetCount++;
2431
2432 mpp_assert(frm);
2433
2434 enc_dbg_detail("skip input frame start\n");
2435
2436 stopwatch = mpp_frame_get_stopwatch(frm);
2437 mpp_stopwatch_record(stopwatch, "skip task start");
2438
2439 if (mpp_frame_has_meta(frm)) {
2440 meta = mpp_frame_get_meta(frm);
2441 if (meta)
2442 mpp_meta_get_packet(meta, KEY_OUTPUT_PACKET, &pkt);
2443 }
2444
2445 if (NULL == pkt)
2446 mpp_packet_new(&pkt);
2447
2448 mpp_assert(pkt);
2449
2450 mpp_packet_set_length(pkt, 0);
2451 mpp_packet_set_pts(pkt, mpp_frame_get_pts(frm));
2452 mpp_packet_set_dts(pkt, mpp_frame_get_dts(frm));
2453
2454 if (mpp_frame_get_eos(frm))
2455 mpp_packet_set_eos(pkt);
2456 else
2457 mpp_packet_clr_eos(pkt);
2458
2459 meta = mpp_packet_get_meta(pkt);
2460 mpp_assert(meta);
2461
2462 mpp_meta_set_frame(meta, KEY_INPUT_FRAME, frm);
2463
2464 if (mpp->mPktOut) {
2465 mpp_list *pkt_out = mpp->mPktOut;
2466
2467 pkt_out->lock();
2468 mpp_stopwatch_record(stopwatch, "skip task output");
2469 pkt_out->add_at_tail(&pkt, sizeof(pkt));
2470 mpp->mPacketPutCount++;
2471 pkt_out->signal();
2472 pkt_out->unlock();
2473 }
2474
2475 enc_dbg_detail("packet skip ready\n");
2476 }
2477
check_async_frm_pkt(EncAsyncTaskInfo * async)2478 static MPP_RET check_async_frm_pkt(EncAsyncTaskInfo *async)
2479 {
2480 HalEncTask *hal_task = &async->task;
2481 MppPacket packet = hal_task->packet;
2482 MppFrame frame = hal_task->frame;
2483
2484 hal_task->input = NULL;
2485 hal_task->output = NULL;
2486
2487 if (packet)
2488 hal_task->output = mpp_packet_get_buffer(packet);
2489 else {
2490 mpp_packet_new(&packet);
2491 hal_task->packet = packet;
2492 }
2493
2494 if (frame) {
2495 RK_S64 pts = mpp_frame_get_pts(frame);
2496 MppBuffer frm_buf = mpp_frame_get_buffer(frame);
2497
2498 hal_task->input = frm_buf;
2499
2500 mpp_packet_set_pts(packet, pts);
2501 mpp_packet_set_dts(packet, mpp_frame_get_dts(frame));
2502
2503 if (mpp_frame_get_eos(frame))
2504 mpp_packet_set_eos(packet);
2505 else
2506 mpp_packet_clr_eos(packet);
2507 }
2508
2509 return (NULL == frame || NULL == hal_task->input) ? MPP_NOK : MPP_OK;
2510 }
2511
check_async_pkt_buf(MppEncImpl * enc,EncAsyncTaskInfo * async)2512 static MPP_RET check_async_pkt_buf(MppEncImpl *enc, EncAsyncTaskInfo *async)
2513 {
2514 HalEncTask *hal_task = &async->task;
2515
2516 if (NULL == hal_task->output) {
2517 /* NOTE: set buffer w * h * 1.5 to avoid buffer overflow */
2518 Mpp *mpp = (Mpp *)enc->mpp;
2519 MppEncPrepCfg *prep = &enc->cfg.prep;
2520 RK_U32 width = MPP_ALIGN(prep->width, 16);
2521 RK_U32 height = MPP_ALIGN(prep->height, 16);
2522 RK_U32 size = (enc->coding == MPP_VIDEO_CodingMJPEG) ?
2523 (width * height * 3 / 2) : (width * height);
2524 MppPacketImpl *pkt = (MppPacketImpl *)hal_task->packet;
2525 MppBuffer buffer = NULL;
2526
2527 mpp_assert(size);
2528 mpp_buffer_get(mpp->mPacketGroup, &buffer, size);
2529 mpp_assert(buffer);
2530 enc->pkt_buf = buffer;
2531 pkt->data = mpp_buffer_get_ptr(buffer);
2532 pkt->pos = pkt->data;
2533 pkt->size = mpp_buffer_get_size(buffer);
2534 pkt->length = 0;
2535 pkt->buffer = buffer;
2536 hal_task->output = buffer;
2537
2538 enc_dbg_detail("create output pkt %p buf %p\n", hal_task->packet, buffer);
2539 } else {
2540 enc_dbg_detail("output to pkt %p buf %p pos %p length %d\n",
2541 hal_task->packet, hal_task->output,
2542 mpp_packet_get_pos(hal_task->packet),
2543 mpp_packet_get_length(hal_task->packet));
2544 }
2545
2546 return MPP_OK;
2547 }
2548
try_get_async_task(MppEncImpl * enc,EncAsyncWait * wait)2549 static MPP_RET try_get_async_task(MppEncImpl *enc, EncAsyncWait *wait)
2550 {
2551 Mpp *mpp = (Mpp *)enc->mpp;
2552 EncAsyncTaskInfo *async = enc->async;
2553 EncRcTask *rc_task = NULL;
2554 MppEncHeaderStatus *hdr_status = &enc->hdr_status;
2555 HalEncTask *hal_task = NULL;
2556 EncAsyncStatus *status = NULL;
2557 MppStopwatch stopwatch = NULL;
2558 MppPacket packet = NULL;
2559 MppFrame frame = NULL;
2560 RK_U32 seq_idx = 0;
2561 MPP_RET ret = MPP_OK;
2562
2563 if (NULL == enc->hnd) {
2564 hal_task_get_hnd(enc->tasks, TASK_IDLE, &enc->hnd);
2565 if (enc->hnd) {
2566 wait->task_hnd = 0;
2567 enc_dbg_detail("get hnd success\n");
2568
2569 mpp_assert(enc->async == NULL);
2570 async = (EncAsyncTaskInfo *)hal_task_hnd_get_data(enc->hnd);
2571 async_task_reset(async);
2572 enc->async = async;
2573 } else {
2574 wait->task_hnd = 1;
2575 enc_dbg_detail("get hnd failed\n");
2576 return MPP_NOK;
2577 }
2578 }
2579
2580 mpp_assert(enc->hnd);
2581 mpp_assert(enc->async);
2582
2583 hal_task = &async->task;
2584 rc_task = &async->rc;
2585 status = &async->status;
2586 packet = hal_task->packet;
2587 frame = hal_task->frame;
2588
2589 if (NULL == frame) {
2590 if (mpp->mFrmIn) {
2591 mpp_list *frm_in = mpp->mFrmIn;
2592 AutoMutex autolock(frm_in->mutex());
2593
2594 if (frm_in->list_size()) {
2595 frm_in->del_at_head(&frame, sizeof(frame));
2596 frm_in->signal();
2597 mpp->mFrameGetCount++;
2598
2599 mpp_assert(frame);
2600
2601 status->task_in_rdy = 1;
2602 wait->enc_frm_in = 0;
2603
2604 enc_dbg_detail("get input frame success\n");
2605
2606 stopwatch = mpp_frame_get_stopwatch(frame);
2607 mpp_stopwatch_record(stopwatch, "encode task start");
2608
2609 hal_task->frame = frame;
2610 }
2611 }
2612
2613 if (NULL == frame) {
2614 enc_dbg_detail("get input frame failed\n");
2615 wait->enc_frm_in = 1;
2616 return MPP_NOK;
2617 }
2618 }
2619
2620 if (NULL == packet) {
2621 if (mpp_frame_has_meta(frame)) {
2622 MppMeta meta = mpp_frame_get_meta(frame);
2623
2624 mpp_meta_get_packet(meta, KEY_OUTPUT_PACKET, &packet);
2625 }
2626
2627 if (packet) {
2628 status->task_out_rdy = 1;
2629 wait->enc_pkt_out = 0;
2630
2631 enc_dbg_detail("get output packet success\n");
2632
2633 hal_task->packet = packet;
2634 }
2635 }
2636
2637 mpp_assert(frame);
2638
2639 stopwatch = mpp_frame_get_stopwatch(frame);
2640
2641 /*
2642 * 6. get frame and packet for one task
2643 * If there is no input frame just return empty packet task
2644 */
2645 if (!status->frm_pkt_rdy) {
2646 async->seq_idx = enc->task_idx++;
2647 async->pts = mpp_frame_get_pts(hal_task->frame);
2648
2649 hal_task->stopwatch = stopwatch;
2650 rc_task->frame = async->task.frame;
2651
2652 enc_dbg_detail("task seq idx %d start\n", seq_idx);
2653
2654 if (check_async_frm_pkt(async)) {
2655 mpp_stopwatch_record(stopwatch, "empty frame on check frm pkt");
2656 hal_task->valid = 1;
2657 hal_task->length = 0;
2658 hal_task->flags.drop_by_fps = 1;
2659 ret = MPP_OK;
2660 goto TASK_DONE;
2661 }
2662
2663 status->frm_pkt_rdy = 1;
2664 enc_dbg_detail("task frame packet ready\n");
2665 }
2666
2667 seq_idx = async->seq_idx;
2668
2669 // 9. check frame drop by frame rate conversion
2670 if (!status->rc_check_frm_drop) {
2671 EncFrmStatus *frm = &rc_task->frm;
2672
2673 ENC_RUN_FUNC2(rc_frm_check_drop, enc->rc_ctx, rc_task, enc->mpp, ret);
2674 status->rc_check_frm_drop = 1;
2675 enc_dbg_detail("task %d drop %d\n", seq_idx, frm->drop);
2676
2677 // when the frame should be dropped just return empty packet
2678 hal_task->valid = 1;
2679 if (frm->drop) {
2680 mpp_stopwatch_record(stopwatch, "invalid on frame rate drop");
2681 hal_task->length = 0;
2682 hal_task->flags.drop_by_fps = 1;
2683 ret = MPP_OK;
2684 goto TASK_DONE;
2685 }
2686
2687 *hal_task->frm_cfg = enc->frm_cfg;
2688 enc->frm_cfg.force_flag = 0;
2689 }
2690
2691 // start encoder task process here
2692 mpp_assert(hal_task->valid);
2693
2694 // 10. check and create packet for output
2695 if (!status->pkt_buf_rdy) {
2696 check_async_pkt_buf(enc, async);
2697 status->pkt_buf_rdy = 1;
2698
2699 enc_dbg_detail("task %d check pkt buffer success\n", seq_idx);
2700 }
2701 mpp_assert(hal_task->packet);
2702 mpp_assert(hal_task->output);
2703
2704 // 11. check hal info update
2705 if (!enc->hal_info_updated) {
2706 update_enc_hal_info(enc);
2707 enc->hal_info_updated = 1;
2708
2709 enc_dbg_detail("task %d update enc hal info success\n", seq_idx);
2710 }
2711
2712 // 12. generate header before hardware stream
2713 if (!hdr_status->ready) {
2714 /* config cpb before generating header */
2715 enc_impl_gen_hdr(enc->impl, enc->hdr_pkt);
2716 enc->hdr_len = mpp_packet_get_length(enc->hdr_pkt);
2717 hdr_status->ready = 1;
2718
2719 enc_dbg_detail("task %d update header length %d\n",
2720 seq_idx, enc->hdr_len);
2721
2722 mpp_packet_append(hal_task->packet, enc->hdr_pkt);
2723 hal_task->header_length = enc->hdr_len;
2724 hal_task->length += enc->hdr_len;
2725 hdr_status->added_by_change = 1;
2726 }
2727
2728 check_hal_task_pkt_len(hal_task, "gen_hdr and adding");
2729
2730 // 13. check frm_meta data force key in input frame and start one frame
2731 if (!status->enc_start) {
2732 enc_dbg_detail("task %d enc start\n", seq_idx);
2733 ENC_RUN_FUNC2(enc_impl_start, enc->impl, hal_task, enc->mpp, ret);
2734 status->enc_start = 1;
2735 }
2736
2737 // 14. setup user_cfg to dpb
2738 if (!status->refs_force_update) {
2739 MppEncRefFrmUsrCfg *frm_cfg = &async->usr;
2740
2741 if (frm_cfg->force_flag) {
2742 mpp_enc_refs_set_usr_cfg(enc->refs, frm_cfg);
2743 frm_cfg->force_flag = 0;
2744 }
2745
2746 enc_dbg_detail("task %d refs force update success\n", seq_idx);
2747 status->refs_force_update = 1;
2748 }
2749
2750 // 15. backup dpb
2751 if (!status->enc_backup) {
2752 mpp_enc_refs_stash(enc->refs);
2753 enc_dbg_detail("task %d refs stash success\n", seq_idx);
2754 status->enc_backup = 1;
2755 }
2756
2757 TASK_DONE:
2758 if (ret) {
2759 enc_dbg_detail("task %d terminate\n", seq_idx);
2760 async_task_terminate(enc, async);
2761 }
2762
2763 return ret;
2764 }
2765
proc_async_task(MppEncImpl * enc)2766 static MPP_RET proc_async_task(MppEncImpl *enc)
2767 {
2768 Mpp *mpp = (Mpp*)enc->mpp;
2769 EncImpl impl = enc->impl;
2770 MppEncHal hal = enc->enc_hal;
2771 EncAsyncTaskInfo *async = enc->async;
2772 EncAsyncStatus *status = &async->status;
2773 HalEncTask *hal_task = &async->task;
2774 EncRcTask *rc_task = hal_task->rc_task;
2775 EncCpbStatus *cpb = &rc_task->cpb;
2776 EncFrmStatus *frm = &rc_task->frm;
2777 RK_U32 seq_idx = async->seq_idx;
2778 MPP_RET ret = MPP_OK;
2779
2780 mpp_assert(hal_task->valid);
2781
2782 if (hal_task->flags.drop_by_fps)
2783 goto SEND_TASK_INFO;
2784
2785 enc_dbg_detail("task %d enc proc dpb\n", seq_idx);
2786 mpp_enc_refs_get_cpb(enc->refs, cpb);
2787
2788 enc_dbg_frm_status("frm %d start ***********************************\n", seq_idx);
2789 ENC_RUN_FUNC2(enc_impl_proc_dpb, impl, hal_task, mpp, ret);
2790
2791 enc_dbg_detail("task %d rc frame start\n", frm->seq_idx);
2792 ENC_RUN_FUNC2(rc_frm_start, enc->rc_ctx, rc_task, mpp, ret);
2793
2794 // 16. generate header before hardware stream
2795 mpp_enc_add_sw_header(enc, hal_task);
2796
2797 enc_dbg_detail("task %d enc proc hal\n", frm->seq_idx);
2798 ENC_RUN_FUNC2(enc_impl_proc_hal, impl, hal_task, mpp, ret);
2799
2800 enc_dbg_detail("task %d hal get task\n", frm->seq_idx);
2801 ENC_RUN_FUNC2(mpp_enc_hal_get_task, hal, hal_task, mpp, ret);
2802
2803 enc_dbg_detail("task %d rc hal start\n", frm->seq_idx);
2804 ENC_RUN_FUNC2(rc_hal_start, enc->rc_ctx, rc_task, mpp, ret);
2805
2806 enc_dbg_detail("task %d hal generate reg\n", frm->seq_idx);
2807 ENC_RUN_FUNC2(mpp_enc_hal_gen_regs, hal, hal_task, mpp, ret);
2808
2809 mpp_stopwatch_record(hal_task->stopwatch, "encode hal start");
2810 enc_dbg_detail("task %d hal start\n", frm->seq_idx);
2811 ENC_RUN_FUNC2(mpp_enc_hal_start, hal, hal_task, mpp, ret);
2812
2813 SEND_TASK_INFO:
2814 status->enc_done = 0;
2815 hal_task_hnd_set_status(enc->hnd, TASK_PROCESSING);
2816 enc_dbg_detail("task %d on processing ret %d\n", frm->seq_idx, ret);
2817
2818 enc->hnd = NULL;
2819 enc->async = NULL;
2820
2821 TASK_DONE:
2822
2823 /* NOTE: clear add_by flags */
2824 enc->hdr_status.val = enc->hdr_status.ready;
2825
2826 return ret;
2827 }
2828
check_enc_async_wait(MppEncImpl * enc,EncAsyncWait * wait)2829 static MPP_RET check_enc_async_wait(MppEncImpl *enc, EncAsyncWait *wait)
2830 {
2831 MPP_RET ret = MPP_OK;
2832 RK_U32 notify = enc->notify_flag;
2833 RK_U32 last_wait = enc->status_flag;
2834 RK_U32 curr_wait = wait->val;
2835 RK_U32 wait_chg = last_wait & (~curr_wait);
2836 RK_U32 keep_notify = 0;
2837
2838 do {
2839 if (enc->reset_flag)
2840 break;
2841
2842 // NOTE: User control should always be processed
2843 if (notify & MPP_ENC_CONTROL) {
2844 keep_notify = notify & (~MPP_ENC_CONTROL);
2845 break;
2846 }
2847
2848 // NOTE: When condition is not fulfilled check nofify flag again
2849 if (!curr_wait || (curr_wait & notify))
2850 break;
2851
2852 ret = MPP_NOK;
2853 } while (0);
2854
2855 enc_dbg_status("%p %08x -> %08x [%08x] notify %08x -> %s\n", enc,
2856 last_wait, curr_wait, wait_chg, notify, (ret) ? ("wait") : ("work"));
2857
2858 enc->status_flag = wait->val;
2859 enc->notify_flag = keep_notify;
2860
2861 if (ret) {
2862 enc->wait_count++;
2863 } else {
2864 enc->work_count++;
2865 }
2866
2867 return ret;
2868 }
2869
enc_async_wait_task(MppEncImpl * enc,EncAsyncTaskInfo * info)2870 static MPP_RET enc_async_wait_task(MppEncImpl *enc, EncAsyncTaskInfo *info)
2871 {
2872 Mpp *mpp = (Mpp*)enc->mpp;
2873 MppEncHal hal = enc->enc_hal;
2874 HalEncTask *hal_task = &info->task;
2875 EncRcTask *rc_task = hal_task->rc_task;
2876 EncFrmStatus *frm = &info->rc.frm;
2877 MppPacket pkt = hal_task->packet;
2878 MppMeta meta = mpp_packet_get_meta(pkt);
2879 MPP_RET ret = MPP_OK;
2880
2881 if (hal_task->flags.drop_by_fps)
2882 goto TASK_DONE;
2883
2884 enc_dbg_detail("task %d hal wait\n", frm->seq_idx);
2885 ENC_RUN_FUNC2(mpp_enc_hal_wait, hal, hal_task, mpp, ret);
2886
2887 mpp_stopwatch_record(hal_task->stopwatch, "encode hal finish");
2888
2889 enc_dbg_detail("task %d rc hal end\n", frm->seq_idx);
2890 ENC_RUN_FUNC2(rc_hal_end, enc->rc_ctx, rc_task, mpp, ret);
2891
2892 enc_dbg_detail("task %d hal ret task\n", frm->seq_idx);
2893 ENC_RUN_FUNC2(mpp_enc_hal_ret_task, hal, hal_task, mpp, ret);
2894
2895 enc_dbg_detail("task %d rc frame end\n", frm->seq_idx);
2896 ENC_RUN_FUNC2(rc_frm_end, enc->rc_ctx, rc_task, mpp, ret);
2897
2898 TASK_DONE:
2899 if (!mpp_packet_is_partition(pkt)) {
2900 /* setup output packet and meta data */
2901 mpp_packet_set_length(pkt, hal_task->length);
2902
2903 check_hal_task_pkt_len(hal_task, "hw finish");
2904 }
2905
2906 mpp_meta_set_s32(meta, KEY_OUTPUT_INTRA, frm->is_intra);
2907 if (rc_task->info.quality_real)
2908 mpp_meta_set_s32(meta, KEY_ENC_AVERAGE_QP, rc_task->info.quality_real);
2909
2910 mpp_meta_set_frame(meta, KEY_INPUT_FRAME, hal_task->frame);
2911
2912 enc_dbg_detail("task %d output packet pts %lld\n", info->seq_idx, info->pts);
2913
2914 /*
2915 * async encode process, there may have multiple frames encoding.
2916 * if last frame enc failed, drop non-idr frames and force idr for next frame.
2917 */
2918 if (enc->enc_failed_drop && !hal_task->rc_task->frm.is_idr) {
2919 mpp_packet_set_length(pkt, 0);
2920 mpp_err_f("last frame enc failed, drop this P frame\n");
2921 enc->frm_cfg.force_flag |= ENC_FORCE_IDR;
2922 enc->hdr_status.val = 0;
2923 } else
2924 enc->enc_failed_drop = 0;
2925 /* enc failed, force idr for next frame */
2926 if (ret) {
2927 enc->frm_cfg.force_flag |= ENC_FORCE_IDR;
2928 enc->hdr_status.val = 0;
2929 mpp_packet_set_length(pkt, 0);
2930 enc->enc_failed_drop = 1;
2931
2932 mpp_err_f("enc failed force idr!\n");
2933 }
2934
2935 if (mpp->mPktOut) {
2936 mpp_list *pkt_out = mpp->mPktOut;
2937
2938 AutoMutex autoLock(pkt_out->mutex());
2939
2940 pkt_out->add_at_tail(&pkt, sizeof(pkt));
2941 mpp->mPacketPutCount++;
2942 pkt_out->signal();
2943 }
2944
2945 return ret;
2946 }
2947
mpp_enc_async_thread(void * data)2948 void *mpp_enc_async_thread(void *data)
2949 {
2950 Mpp *mpp = (Mpp*)data;
2951 MppEncImpl *enc = (MppEncImpl *)mpp->mEnc;
2952 MppThread *thd_enc = enc->thread_enc;
2953 EncAsyncWait wait;
2954 MPP_RET ret = MPP_OK;
2955
2956 enc_dbg_func("thread start\n");
2957
2958 wait.val = 0;
2959
2960 while (1) {
2961 {
2962 AutoMutex autolock(thd_enc->mutex());
2963 if (MPP_THREAD_RUNNING != thd_enc->get_status())
2964 break;
2965
2966 if (check_enc_async_wait(enc, &wait)) {
2967 enc_dbg_detail("wait start\n");
2968 thd_enc->wait();
2969 enc_dbg_detail("wait done\n");
2970 }
2971 }
2972
2973 // When encoder is not on encoding process external config and reset
2974 // 1. process user control and reset flag
2975 if (enc->cmd_send != enc->cmd_recv || enc->reset_flag) {
2976 mpp_list *frm_in = mpp->mFrmIn;
2977 HalTaskHnd hnd = NULL;
2978 EncAsyncTaskInfo *info = NULL;
2979
2980 /* when process cmd or reset hold frame input */
2981 frm_in->lock();
2982
2983 enc_dbg_detail("ctrl proc %d cmd %08x\n", enc->cmd_recv, enc->cmd);
2984
2985 // wait all tasks done
2986 while (MPP_OK == hal_task_get_hnd(enc->tasks, TASK_PROCESSING, &hnd)) {
2987 info = (EncAsyncTaskInfo *)hal_task_hnd_get_data(hnd);
2988
2989 mpp_assert(!info->status.enc_done);
2990
2991 enc_async_wait_task(enc, info);
2992 hal_task_hnd_set_status(hnd, TASK_IDLE);
2993 wait.task_hnd = 0;
2994 }
2995
2996 if (enc->cmd_send != enc->cmd_recv) {
2997 sem_wait(&enc->cmd_start);
2998 ret = mpp_enc_proc_cfg(enc, enc->cmd, enc->param);
2999 if (ret)
3000 *enc->cmd_ret = ret;
3001 enc->cmd_recv++;
3002 enc_dbg_detail("ctrl proc %d done send %d\n", enc->cmd_recv,
3003 enc->cmd_send);
3004 mpp_assert(enc->cmd_send == enc->cmd_send);
3005 enc->param = NULL;
3006 enc->cmd = (MpiCmd)0;
3007 sem_post(&enc->cmd_done);
3008
3009 // async cfg update process for hal
3010 // mainly for buffer prepare
3011 mpp_enc_hal_prepare(enc->enc_hal);
3012
3013 /* NOTE: here will clear change flag of rc and prep cfg */
3014 mpp_enc_proc_rc_update(enc);
3015 goto SYNC_DONE;
3016 }
3017
3018 if (enc->reset_flag) {
3019 enc_dbg_detail("thread reset start\n");
3020
3021 /* skip the frames in input queue */
3022 while (frm_in->list_size())
3023 async_task_skip(enc);
3024
3025 {
3026 AutoMutex autolock(thd_enc->mutex());
3027 enc->status_flag = 0;
3028 }
3029
3030 enc->frm_cfg.force_flag |= ENC_FORCE_IDR;
3031 enc->frm_cfg.force_idr++;
3032
3033 AutoMutex autolock(thd_enc->mutex(THREAD_CONTROL));
3034 enc->reset_flag = 0;
3035 sem_post(&enc->enc_reset);
3036 enc_dbg_detail("thread reset done\n");
3037 }
3038 SYNC_DONE:
3039 frm_in->unlock();
3040 wait.val = 0;
3041 continue;
3042 }
3043
3044 // 2. try get a task to encode
3045 ret = try_get_async_task(enc, &wait);
3046 enc_dbg_detail("try_get_async_task ret %d\n", ret);
3047 if (ret) {
3048 HalTaskHnd hnd = NULL;
3049 EncAsyncTaskInfo *info = NULL;
3050
3051 hal_task_get_hnd(enc->tasks, TASK_PROCESSING, &hnd);
3052 if (hnd) {
3053 info = (EncAsyncTaskInfo *)hal_task_hnd_get_data(hnd);
3054
3055 mpp_assert(!info->status.enc_done);
3056
3057 enc_async_wait_task(enc, info);
3058 hal_task_hnd_set_status(hnd, TASK_IDLE);
3059 wait.task_hnd = 0;
3060 }
3061
3062 continue;
3063 }
3064
3065 mpp_assert(enc->async);
3066 mpp_assert(enc->async->task.valid);
3067
3068 proc_async_task(enc);
3069 }
3070
3071 enc_dbg_func("thread finish\n");
3072
3073 return NULL;
3074 }
3075