FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/hw_base_encode.c
Date: 2024-10-04 17:46:48
Exec Total Coverage
Lines: 0 454 0.0%
Functions: 0 15 0.0%
Branches: 0 354 0.0%

Line Branch Exec Source
1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include "libavutil/avassert.h"
20 #include "libavutil/common.h"
21 #include "libavutil/internal.h"
22 #include "libavutil/log.h"
23 #include "libavutil/mem.h"
24 #include "libavutil/pixdesc.h"
25
26 #include "encode.h"
27 #include "avcodec.h"
28 #include "hw_base_encode.h"
29
30 static int base_encode_pic_free(FFHWBaseEncodePicture *pic)
31 {
32 av_frame_free(&pic->input_image);
33 av_frame_free(&pic->recon_image);
34
35 av_buffer_unref(&pic->opaque_ref);
36 av_freep(&pic->codec_priv);
37 av_freep(&pic->priv);
38 av_free(pic);
39
40 return 0;
41 }
42
43 static void hw_base_encode_add_ref(FFHWBaseEncodePicture *pic,
44 FFHWBaseEncodePicture *target,
45 int is_ref, int in_dpb, int prev)
46 {
47 int refs = 0;
48
49 if (is_ref) {
50 av_assert0(pic != target);
51 av_assert0(pic->nb_refs[0] < MAX_PICTURE_REFERENCES &&
52 pic->nb_refs[1] < MAX_PICTURE_REFERENCES);
53 if (target->display_order < pic->display_order)
54 pic->refs[0][pic->nb_refs[0]++] = target;
55 else
56 pic->refs[1][pic->nb_refs[1]++] = target;
57 ++refs;
58 }
59
60 if (in_dpb) {
61 av_assert0(pic->nb_dpb_pics < MAX_DPB_SIZE);
62 pic->dpb[pic->nb_dpb_pics++] = target;
63 ++refs;
64 }
65
66 if (prev) {
67 av_assert0(!pic->prev);
68 pic->prev = target;
69 ++refs;
70 }
71
72 target->ref_count[0] += refs;
73 target->ref_count[1] += refs;
74 }
75
76 static void hw_base_encode_remove_refs(FFHWBaseEncodePicture *pic, int level)
77 {
78 int i;
79
80 if (pic->ref_removed[level])
81 return;
82
83 for (i = 0; i < pic->nb_refs[0]; i++) {
84 av_assert0(pic->refs[0][i]);
85 --pic->refs[0][i]->ref_count[level];
86 av_assert0(pic->refs[0][i]->ref_count[level] >= 0);
87 }
88
89 for (i = 0; i < pic->nb_refs[1]; i++) {
90 av_assert0(pic->refs[1][i]);
91 --pic->refs[1][i]->ref_count[level];
92 av_assert0(pic->refs[1][i]->ref_count[level] >= 0);
93 }
94
95 for (i = 0; i < pic->nb_dpb_pics; i++) {
96 av_assert0(pic->dpb[i]);
97 --pic->dpb[i]->ref_count[level];
98 av_assert0(pic->dpb[i]->ref_count[level] >= 0);
99 }
100
101 av_assert0(pic->prev || pic->type == FF_HW_PICTURE_TYPE_IDR);
102 if (pic->prev) {
103 --pic->prev->ref_count[level];
104 av_assert0(pic->prev->ref_count[level] >= 0);
105 }
106
107 pic->ref_removed[level] = 1;
108 }
109
110 static void hw_base_encode_set_b_pictures(FFHWBaseEncodeContext *ctx,
111 FFHWBaseEncodePicture *start,
112 FFHWBaseEncodePicture *end,
113 FFHWBaseEncodePicture *prev,
114 int current_depth,
115 FFHWBaseEncodePicture **last)
116 {
117 FFHWBaseEncodePicture *pic, *next, *ref;
118 int i, len;
119
120 av_assert0(start && end && start != end && start->next != end);
121
122 // If we are at the maximum depth then encode all pictures as
123 // non-referenced B-pictures. Also do this if there is exactly one
124 // picture left, since there will be nothing to reference it.
125 if (current_depth == ctx->max_b_depth || start->next->next == end) {
126 for (pic = start->next; pic; pic = pic->next) {
127 if (pic == end)
128 break;
129 pic->type = FF_HW_PICTURE_TYPE_B;
130 pic->b_depth = current_depth;
131
132 hw_base_encode_add_ref(pic, start, 1, 1, 0);
133 hw_base_encode_add_ref(pic, end, 1, 1, 0);
134 hw_base_encode_add_ref(pic, prev, 0, 0, 1);
135
136 for (ref = end->refs[1][0]; ref; ref = ref->refs[1][0])
137 hw_base_encode_add_ref(pic, ref, 0, 1, 0);
138 }
139 *last = prev;
140
141 } else {
142 // Split the current list at the midpoint with a referenced
143 // B-picture, then descend into each side separately.
144 len = 0;
145 for (pic = start->next; pic != end; pic = pic->next)
146 ++len;
147 for (pic = start->next, i = 1; 2 * i < len; pic = pic->next, i++);
148
149 pic->type = FF_HW_PICTURE_TYPE_B;
150 pic->b_depth = current_depth;
151
152 pic->is_reference = 1;
153
154 hw_base_encode_add_ref(pic, pic, 0, 1, 0);
155 hw_base_encode_add_ref(pic, start, 1, 1, 0);
156 hw_base_encode_add_ref(pic, end, 1, 1, 0);
157 hw_base_encode_add_ref(pic, prev, 0, 0, 1);
158
159 for (ref = end->refs[1][0]; ref; ref = ref->refs[1][0])
160 hw_base_encode_add_ref(pic, ref, 0, 1, 0);
161
162 if (i > 1)
163 hw_base_encode_set_b_pictures(ctx, start, pic, pic,
164 current_depth + 1, &next);
165 else
166 next = pic;
167
168 hw_base_encode_set_b_pictures(ctx, pic, end, next,
169 current_depth + 1, last);
170 }
171 }
172
173 static void hw_base_encode_add_next_prev(FFHWBaseEncodeContext *ctx,
174 FFHWBaseEncodePicture *pic)
175 {
176 int i;
177
178 if (!pic)
179 return;
180
181 if (pic->type == FF_HW_PICTURE_TYPE_IDR) {
182 for (i = 0; i < ctx->nb_next_prev; i++) {
183 --ctx->next_prev[i]->ref_count[0];
184 ctx->next_prev[i] = NULL;
185 }
186 ctx->next_prev[0] = pic;
187 ++pic->ref_count[0];
188 ctx->nb_next_prev = 1;
189
190 return;
191 }
192
193 if (ctx->nb_next_prev < MAX_PICTURE_REFERENCES) {
194 ctx->next_prev[ctx->nb_next_prev++] = pic;
195 ++pic->ref_count[0];
196 } else {
197 --ctx->next_prev[0]->ref_count[0];
198 for (i = 0; i < MAX_PICTURE_REFERENCES - 1; i++)
199 ctx->next_prev[i] = ctx->next_prev[i + 1];
200 ctx->next_prev[i] = pic;
201 ++pic->ref_count[0];
202 }
203 }
204
205 static int hw_base_encode_pick_next(AVCodecContext *avctx,
206 FFHWBaseEncodeContext *ctx,
207 FFHWBaseEncodePicture **pic_out)
208 {
209 FFHWBaseEncodePicture *pic = NULL, *prev = NULL, *next, *start;
210 int i, b_counter, closed_gop_end;
211
212 // If there are any B-frames already queued, the next one to encode
213 // is the earliest not-yet-issued frame for which all references are
214 // available.
215 for (pic = ctx->pic_start; pic; pic = pic->next) {
216 if (pic->encode_issued)
217 continue;
218 if (pic->type != FF_HW_PICTURE_TYPE_B)
219 continue;
220 for (i = 0; i < pic->nb_refs[0]; i++) {
221 if (!pic->refs[0][i]->encode_issued)
222 break;
223 }
224 if (i != pic->nb_refs[0])
225 continue;
226
227 for (i = 0; i < pic->nb_refs[1]; i++) {
228 if (!pic->refs[1][i]->encode_issued)
229 break;
230 }
231 if (i == pic->nb_refs[1])
232 break;
233 }
234
235 if (pic) {
236 av_log(avctx, AV_LOG_DEBUG, "Pick B-picture at depth %d to "
237 "encode next.\n", pic->b_depth);
238 *pic_out = pic;
239 return 0;
240 }
241
242 // Find the B-per-Pth available picture to become the next picture
243 // on the top layer.
244 start = NULL;
245 b_counter = 0;
246 closed_gop_end = ctx->closed_gop ||
247 ctx->idr_counter == ctx->gop_per_idr;
248 for (pic = ctx->pic_start; pic; pic = next) {
249 next = pic->next;
250 if (pic->encode_issued) {
251 start = pic;
252 continue;
253 }
254 // If the next available picture is force-IDR, encode it to start
255 // a new GOP immediately.
256 if (pic->force_idr)
257 break;
258 if (b_counter == ctx->b_per_p)
259 break;
260 // If this picture ends a closed GOP or starts a new GOP then it
261 // needs to be in the top layer.
262 if (ctx->gop_counter + b_counter + closed_gop_end >= ctx->gop_size)
263 break;
264 // If the picture after this one is force-IDR, we need to encode
265 // this one in the top layer.
266 if (next && next->force_idr)
267 break;
268 ++b_counter;
269 }
270
271 // At the end of the stream the last picture must be in the top layer.
272 if (!pic && ctx->end_of_stream) {
273 --b_counter;
274 pic = ctx->pic_end;
275 if (pic->encode_complete)
276 return AVERROR_EOF;
277 else if (pic->encode_issued)
278 return AVERROR(EAGAIN);
279 }
280
281 if (!pic) {
282 av_log(avctx, AV_LOG_DEBUG, "Pick nothing to encode next - "
283 "need more input for reference pictures.\n");
284 return AVERROR(EAGAIN);
285 }
286 if (ctx->input_order <= ctx->decode_delay && !ctx->end_of_stream) {
287 av_log(avctx, AV_LOG_DEBUG, "Pick nothing to encode next - "
288 "need more input for timestamps.\n");
289 return AVERROR(EAGAIN);
290 }
291
292 if (pic->force_idr) {
293 av_log(avctx, AV_LOG_DEBUG, "Pick forced IDR-picture to "
294 "encode next.\n");
295 pic->type = FF_HW_PICTURE_TYPE_IDR;
296 ctx->idr_counter = 1;
297 ctx->gop_counter = 1;
298
299 } else if (ctx->gop_counter + b_counter >= ctx->gop_size) {
300 if (ctx->idr_counter == ctx->gop_per_idr) {
301 av_log(avctx, AV_LOG_DEBUG, "Pick new-GOP IDR-picture to "
302 "encode next.\n");
303 pic->type = FF_HW_PICTURE_TYPE_IDR;
304 ctx->idr_counter = 1;
305 } else {
306 av_log(avctx, AV_LOG_DEBUG, "Pick new-GOP I-picture to "
307 "encode next.\n");
308 pic->type = FF_HW_PICTURE_TYPE_I;
309 ++ctx->idr_counter;
310 }
311 ctx->gop_counter = 1;
312
313 } else {
314 if (ctx->gop_counter + b_counter + closed_gop_end == ctx->gop_size) {
315 av_log(avctx, AV_LOG_DEBUG, "Pick group-end P-picture to "
316 "encode next.\n");
317 } else {
318 av_log(avctx, AV_LOG_DEBUG, "Pick normal P-picture to "
319 "encode next.\n");
320 }
321 pic->type = FF_HW_PICTURE_TYPE_P;
322 av_assert0(start);
323 ctx->gop_counter += 1 + b_counter;
324 }
325 pic->is_reference = 1;
326 *pic_out = pic;
327
328 hw_base_encode_add_ref(pic, pic, 0, 1, 0);
329 if (pic->type != FF_HW_PICTURE_TYPE_IDR) {
330 // TODO: apply both previous and forward multi reference for all vaapi encoders.
331 // And L0/L1 reference frame number can be set dynamically through query
332 // VAConfigAttribEncMaxRefFrames attribute.
333 if (avctx->codec_id == AV_CODEC_ID_AV1) {
334 for (i = 0; i < ctx->nb_next_prev; i++)
335 hw_base_encode_add_ref(pic, ctx->next_prev[i],
336 pic->type == FF_HW_PICTURE_TYPE_P,
337 b_counter > 0, 0);
338 } else
339 hw_base_encode_add_ref(pic, start,
340 pic->type == FF_HW_PICTURE_TYPE_P,
341 b_counter > 0, 0);
342
343 hw_base_encode_add_ref(pic, ctx->next_prev[ctx->nb_next_prev - 1], 0, 0, 1);
344 }
345
346 if (b_counter > 0) {
347 hw_base_encode_set_b_pictures(ctx, start, pic, pic, 1,
348 &prev);
349 } else {
350 prev = pic;
351 }
352 hw_base_encode_add_next_prev(ctx, prev);
353
354 return 0;
355 }
356
357 static int hw_base_encode_clear_old(AVCodecContext *avctx, FFHWBaseEncodeContext *ctx)
358 {
359 FFHWBaseEncodePicture *pic, *prev, *next;
360
361 av_assert0(ctx->pic_start);
362
363 // Remove direct references once each picture is complete.
364 for (pic = ctx->pic_start; pic; pic = pic->next) {
365 if (pic->encode_complete && pic->next)
366 hw_base_encode_remove_refs(pic, 0);
367 }
368
369 // Remove indirect references once a picture has no direct references.
370 for (pic = ctx->pic_start; pic; pic = pic->next) {
371 if (pic->encode_complete && pic->ref_count[0] == 0)
372 hw_base_encode_remove_refs(pic, 1);
373 }
374
375 // Clear out all complete pictures with no remaining references.
376 prev = NULL;
377 for (pic = ctx->pic_start; pic; pic = next) {
378 next = pic->next;
379 if (pic->encode_complete && pic->ref_count[1] == 0) {
380 av_assert0(pic->ref_removed[0] && pic->ref_removed[1]);
381 if (prev)
382 prev->next = next;
383 else
384 ctx->pic_start = next;
385 ctx->op->free(avctx, pic);
386 base_encode_pic_free(pic);
387 } else {
388 prev = pic;
389 }
390 }
391
392 return 0;
393 }
394
395 static int hw_base_encode_check_frame(FFHWBaseEncodeContext *ctx,
396 const AVFrame *frame)
397 {
398 if ((frame->crop_top || frame->crop_bottom ||
399 frame->crop_left || frame->crop_right) && !ctx->crop_warned) {
400 av_log(ctx->log_ctx, AV_LOG_WARNING, "Cropping information on input "
401 "frames ignored due to lack of API support.\n");
402 ctx->crop_warned = 1;
403 }
404
405 if (!ctx->roi_allowed) {
406 AVFrameSideData *sd =
407 av_frame_get_side_data(frame, AV_FRAME_DATA_REGIONS_OF_INTEREST);
408
409 if (sd && !ctx->roi_warned) {
410 av_log(ctx->log_ctx, AV_LOG_WARNING, "ROI side data on input "
411 "frames ignored due to lack of driver support.\n");
412 ctx->roi_warned = 1;
413 }
414 }
415
416 return 0;
417 }
418
419 static int hw_base_encode_send_frame(AVCodecContext *avctx, FFHWBaseEncodeContext *ctx,
420 AVFrame *frame)
421 {
422 FFHWBaseEncodePicture *pic;
423 int err;
424
425 if (frame) {
426 av_log(avctx, AV_LOG_DEBUG, "Input frame: %ux%u (%"PRId64").\n",
427 frame->width, frame->height, frame->pts);
428
429 err = hw_base_encode_check_frame(ctx, frame);
430 if (err < 0)
431 return err;
432
433 pic = av_mallocz(sizeof(*pic));
434 if (!pic)
435 return AVERROR(ENOMEM);
436
437 pic->input_image = av_frame_alloc();
438 if (!pic->input_image) {
439 err = AVERROR(ENOMEM);
440 goto fail;
441 }
442
443 if (ctx->recon_frames_ref) {
444 pic->recon_image = av_frame_alloc();
445 if (!pic->recon_image) {
446 err = AVERROR(ENOMEM);
447 goto fail;
448 }
449
450 err = av_hwframe_get_buffer(ctx->recon_frames_ref, pic->recon_image, 0);
451 if (err < 0) {
452 err = AVERROR(ENOMEM);
453 goto fail;
454 }
455 }
456
457 pic->priv = av_mallocz(ctx->op->priv_size);
458 if (!pic->priv) {
459 err = AVERROR(ENOMEM);
460 goto fail;
461 }
462
463 if (ctx->input_order == 0 || frame->pict_type == AV_PICTURE_TYPE_I)
464 pic->force_idr = 1;
465
466 pic->pts = frame->pts;
467 pic->duration = frame->duration;
468
469 if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
470 err = av_buffer_replace(&pic->opaque_ref, frame->opaque_ref);
471 if (err < 0)
472 goto fail;
473
474 pic->opaque = frame->opaque;
475 }
476
477 av_frame_move_ref(pic->input_image, frame);
478
479 if (ctx->input_order == 0)
480 ctx->first_pts = pic->pts;
481 if (ctx->input_order == ctx->decode_delay)
482 ctx->dts_pts_diff = pic->pts - ctx->first_pts;
483 if (ctx->output_delay > 0)
484 ctx->ts_ring[ctx->input_order %
485 (3 * ctx->output_delay + ctx->async_depth)] = pic->pts;
486
487 pic->display_order = ctx->input_order;
488 ++ctx->input_order;
489
490 if (ctx->pic_start) {
491 ctx->pic_end->next = pic;
492 ctx->pic_end = pic;
493 } else {
494 ctx->pic_start = pic;
495 ctx->pic_end = pic;
496 }
497
498 err = ctx->op->init(avctx, pic);
499 if (err < 0)
500 goto fail;
501 } else {
502 ctx->end_of_stream = 1;
503
504 // Fix timestamps if we hit end-of-stream before the initial decode
505 // delay has elapsed.
506 if (ctx->input_order <= ctx->decode_delay)
507 ctx->dts_pts_diff = ctx->pic_end->pts - ctx->first_pts;
508 }
509
510 return 0;
511
512 fail:
513 ctx->op->free(avctx, pic);
514 base_encode_pic_free(pic);
515 return err;
516 }
517
518 int ff_hw_base_encode_set_output_property(FFHWBaseEncodeContext *ctx,
519 AVCodecContext *avctx,
520 FFHWBaseEncodePicture *pic,
521 AVPacket *pkt, int flag_no_delay)
522 {
523 if (pic->type == FF_HW_PICTURE_TYPE_IDR)
524 pkt->flags |= AV_PKT_FLAG_KEY;
525
526 pkt->pts = pic->pts;
527 pkt->duration = pic->duration;
528
529 // for no-delay encoders this is handled in generic codec
530 if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY &&
531 avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
532 pkt->opaque = pic->opaque;
533 pkt->opaque_ref = pic->opaque_ref;
534 pic->opaque_ref = NULL;
535 }
536
537 if (flag_no_delay) {
538 pkt->dts = pkt->pts;
539 return 0;
540 }
541
542 if (ctx->output_delay == 0) {
543 pkt->dts = pkt->pts;
544 } else if (pic->encode_order < ctx->decode_delay) {
545 if (ctx->ts_ring[pic->encode_order] < INT64_MIN + ctx->dts_pts_diff)
546 pkt->dts = INT64_MIN;
547 else
548 pkt->dts = ctx->ts_ring[pic->encode_order] - ctx->dts_pts_diff;
549 } else {
550 pkt->dts = ctx->ts_ring[(pic->encode_order - ctx->decode_delay) %
551 (3 * ctx->output_delay + ctx->async_depth)];
552 }
553
554 return 0;
555 }
556
557 int ff_hw_base_encode_receive_packet(FFHWBaseEncodeContext *ctx,
558 AVCodecContext *avctx, AVPacket *pkt)
559 {
560 FFHWBaseEncodePicture *pic = NULL;
561 AVFrame *frame = ctx->frame;
562 int err;
563
564 av_assert0(ctx->op && ctx->op->init && ctx->op->issue &&
565 ctx->op->output && ctx->op->free);
566
567 start:
568 /** if no B frame before repeat P frame, sent repeat P frame out. */
569 if (ctx->tail_pkt->size) {
570 for (FFHWBaseEncodePicture *tmp = ctx->pic_start; tmp; tmp = tmp->next) {
571 if (tmp->type == FF_HW_PICTURE_TYPE_B && tmp->pts < ctx->tail_pkt->pts)
572 break;
573 else if (!tmp->next) {
574 av_packet_move_ref(pkt, ctx->tail_pkt);
575 goto end;
576 }
577 }
578 }
579
580 err = ff_encode_get_frame(avctx, frame);
581 if (err == AVERROR_EOF) {
582 frame = NULL;
583 } else if (err < 0)
584 return err;
585
586 err = hw_base_encode_send_frame(avctx, ctx, frame);
587 if (err < 0)
588 return err;
589
590 if (!ctx->pic_start) {
591 if (ctx->end_of_stream)
592 return AVERROR_EOF;
593 else
594 return AVERROR(EAGAIN);
595 }
596
597 if (ctx->async_encode) {
598 if (av_fifo_can_write(ctx->encode_fifo)) {
599 err = hw_base_encode_pick_next(avctx, ctx, &pic);
600 if (!err) {
601 av_assert0(pic);
602 pic->encode_order = ctx->encode_order +
603 av_fifo_can_read(ctx->encode_fifo);
604 err = ctx->op->issue(avctx, pic);
605 if (err < 0) {
606 av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err);
607 return err;
608 }
609 pic->encode_issued = 1;
610 av_fifo_write(ctx->encode_fifo, &pic, 1);
611 }
612 }
613
614 if (!av_fifo_can_read(ctx->encode_fifo))
615 return err;
616
617 // More frames can be buffered
618 if (av_fifo_can_write(ctx->encode_fifo) && !ctx->end_of_stream)
619 return AVERROR(EAGAIN);
620
621 av_fifo_read(ctx->encode_fifo, &pic, 1);
622 ctx->encode_order = pic->encode_order + 1;
623 } else {
624 err = hw_base_encode_pick_next(avctx, ctx, &pic);
625 if (err < 0)
626 return err;
627 av_assert0(pic);
628
629 pic->encode_order = ctx->encode_order++;
630
631 err = ctx->op->issue(avctx, pic);
632 if (err < 0) {
633 av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err);
634 return err;
635 }
636
637 pic->encode_issued = 1;
638 }
639
640 err = ctx->op->output(avctx, pic, pkt);
641 if (err < 0) {
642 av_log(avctx, AV_LOG_ERROR, "Output failed: %d.\n", err);
643 return err;
644 }
645
646 ctx->output_order = pic->encode_order;
647 hw_base_encode_clear_old(avctx, ctx);
648
649 /** loop to get an available pkt in encoder flushing. */
650 if (ctx->end_of_stream && !pkt->size)
651 goto start;
652
653 end:
654 if (pkt->size)
655 av_log(avctx, AV_LOG_DEBUG, "Output packet: pts %"PRId64", dts %"PRId64", "
656 "size %d bytes.\n", pkt->pts, pkt->dts, pkt->size);
657
658 return 0;
659 }
660
661 int ff_hw_base_init_gop_structure(FFHWBaseEncodeContext *ctx, AVCodecContext *avctx,
662 uint32_t ref_l0, uint32_t ref_l1,
663 int flags, int prediction_pre_only)
664 {
665 if (flags & FF_HW_FLAG_INTRA_ONLY || avctx->gop_size <= 1) {
666 av_log(avctx, AV_LOG_VERBOSE, "Using intra frames only.\n");
667 ctx->gop_size = 1;
668 } else if (ref_l0 < 1) {
669 av_log(avctx, AV_LOG_ERROR, "Driver does not support any "
670 "reference frames.\n");
671 return AVERROR(EINVAL);
672 } else if (!(flags & FF_HW_FLAG_B_PICTURES) || ref_l1 < 1 ||
673 avctx->max_b_frames < 1 || prediction_pre_only) {
674 if (ctx->p_to_gpb)
675 av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames "
676 "(supported references: %d / %d).\n",
677 ref_l0, ref_l1);
678 else
679 av_log(avctx, AV_LOG_VERBOSE, "Using intra and P-frames "
680 "(supported references: %d / %d).\n", ref_l0, ref_l1);
681 ctx->gop_size = avctx->gop_size;
682 ctx->p_per_i = INT_MAX;
683 ctx->b_per_p = 0;
684 } else {
685 if (ctx->p_to_gpb)
686 av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames "
687 "(supported references: %d / %d).\n",
688 ref_l0, ref_l1);
689 else
690 av_log(avctx, AV_LOG_VERBOSE, "Using intra, P- and B-frames "
691 "(supported references: %d / %d).\n", ref_l0, ref_l1);
692 ctx->gop_size = avctx->gop_size;
693 ctx->p_per_i = INT_MAX;
694 ctx->b_per_p = avctx->max_b_frames;
695 if (flags & FF_HW_FLAG_B_PICTURE_REFERENCES) {
696 ctx->max_b_depth = FFMIN(ctx->desired_b_depth,
697 av_log2(ctx->b_per_p) + 1);
698 } else {
699 ctx->max_b_depth = 1;
700 }
701 }
702
703 if (flags & FF_HW_FLAG_NON_IDR_KEY_PICTURES) {
704 ctx->closed_gop = !!(avctx->flags & AV_CODEC_FLAG_CLOSED_GOP);
705 ctx->gop_per_idr = ctx->idr_interval + 1;
706 } else {
707 ctx->closed_gop = 1;
708 ctx->gop_per_idr = 1;
709 }
710
711 return 0;
712 }
713
714 int ff_hw_base_get_recon_format(FFHWBaseEncodeContext *ctx, const void *hwconfig,
715 enum AVPixelFormat *fmt)
716 {
717 AVHWFramesConstraints *constraints = NULL;
718 enum AVPixelFormat recon_format;
719 int err, i;
720
721 constraints = av_hwdevice_get_hwframe_constraints(ctx->device_ref,
722 hwconfig);
723 if (!constraints) {
724 err = AVERROR(ENOMEM);
725 goto fail;
726 }
727
728 // Probably we can use the input surface format as the surface format
729 // of the reconstructed frames. If not, we just pick the first (only?)
730 // format in the valid list and hope that it all works.
731 recon_format = AV_PIX_FMT_NONE;
732 if (constraints->valid_sw_formats) {
733 for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) {
734 if (ctx->input_frames->sw_format ==
735 constraints->valid_sw_formats[i]) {
736 recon_format = ctx->input_frames->sw_format;
737 break;
738 }
739 }
740 if (recon_format == AV_PIX_FMT_NONE) {
741 // No match. Just use the first in the supported list and
742 // hope for the best.
743 recon_format = constraints->valid_sw_formats[0];
744 }
745 } else {
746 // No idea what to use; copy input format.
747 recon_format = ctx->input_frames->sw_format;
748 }
749 av_log(ctx->log_ctx, AV_LOG_DEBUG, "Using %s as format of "
750 "reconstructed frames.\n", av_get_pix_fmt_name(recon_format));
751
752 if (ctx->surface_width < constraints->min_width ||
753 ctx->surface_height < constraints->min_height ||
754 ctx->surface_width > constraints->max_width ||
755 ctx->surface_height > constraints->max_height) {
756 av_log(ctx->log_ctx, AV_LOG_ERROR, "Hardware does not support encoding at "
757 "size %dx%d (constraints: width %d-%d height %d-%d).\n",
758 ctx->surface_width, ctx->surface_height,
759 constraints->min_width, constraints->max_width,
760 constraints->min_height, constraints->max_height);
761 err = AVERROR(EINVAL);
762 goto fail;
763 }
764
765 *fmt = recon_format;
766 err = 0;
767 fail:
768 av_hwframe_constraints_free(&constraints);
769 return err;
770 }
771
772 int ff_hw_base_encode_init(AVCodecContext *avctx, FFHWBaseEncodeContext *ctx)
773 {
774 ctx->log_ctx = (void *)avctx;
775
776 ctx->frame = av_frame_alloc();
777 if (!ctx->frame)
778 return AVERROR(ENOMEM);
779
780 if (!avctx->hw_frames_ctx) {
781 av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is "
782 "required to associate the encoding device.\n");
783 return AVERROR(EINVAL);
784 }
785
786 ctx->input_frames_ref = av_buffer_ref(avctx->hw_frames_ctx);
787 if (!ctx->input_frames_ref)
788 return AVERROR(ENOMEM);
789
790 ctx->input_frames = (AVHWFramesContext *)ctx->input_frames_ref->data;
791
792 ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref);
793 if (!ctx->device_ref)
794 return AVERROR(ENOMEM);
795
796 ctx->device = (AVHWDeviceContext *)ctx->device_ref->data;
797
798 ctx->tail_pkt = av_packet_alloc();
799 if (!ctx->tail_pkt)
800 return AVERROR(ENOMEM);
801
802 return 0;
803 }
804
805 int ff_hw_base_encode_close(FFHWBaseEncodeContext *ctx)
806 {
807 av_fifo_freep2(&ctx->encode_fifo);
808
809 av_frame_free(&ctx->frame);
810 av_packet_free(&ctx->tail_pkt);
811
812 av_buffer_unref(&ctx->device_ref);
813 av_buffer_unref(&ctx->input_frames_ref);
814 av_buffer_unref(&ctx->recon_frames_ref);
815
816 return 0;
817 }
818