FFmpeg coverage


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