2 * This file is part of Libav.
4 * Libav 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.
9 * Libav 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.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with Libav; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "libavutil/avassert.h"
23 #include "libavutil/common.h"
24 #include "libavutil/log.h"
25 #include "libavutil/pixdesc.h"
27 #include "vaapi_encode.h"
30 static const char *picture_type_name
[] = { "IDR", "I", "P", "B" };
32 static int vaapi_encode_make_packed_header(AVCodecContext
*avctx
,
33 VAAPIEncodePicture
*pic
,
34 int type
, char *data
, size_t bit_len
)
36 VAAPIEncodeContext
*ctx
= avctx
->priv_data
;
38 VABufferID param_buffer
, data_buffer
;
39 VAEncPackedHeaderParameterBuffer params
= {
41 .bit_length
= bit_len
,
42 .has_emulation_bytes
= 1,
45 av_assert0(pic
->nb_param_buffers
+ 2 <= MAX_PARAM_BUFFERS
);
47 vas
= vaCreateBuffer(ctx
->hwctx
->display
, ctx
->va_context
,
48 VAEncPackedHeaderParameterBufferType
,
49 sizeof(params
), 1, ¶ms
, ¶m_buffer
);
50 if (vas
!= VA_STATUS_SUCCESS
) {
51 av_log(avctx
, AV_LOG_ERROR
, "Failed to create parameter buffer "
52 "for packed header (type %d): %d (%s).\n",
53 type
, vas
, vaErrorStr(vas
));
56 pic
->param_buffers
[pic
->nb_param_buffers
++] = param_buffer
;
58 vas
= vaCreateBuffer(ctx
->hwctx
->display
, ctx
->va_context
,
59 VAEncPackedHeaderDataBufferType
,
60 (bit_len
+ 7) / 8, 1, data
, &data_buffer
);
61 if (vas
!= VA_STATUS_SUCCESS
) {
62 av_log(avctx
, AV_LOG_ERROR
, "Failed to create data buffer "
63 "for packed header (type %d): %d (%s).\n",
64 type
, vas
, vaErrorStr(vas
));
67 pic
->param_buffers
[pic
->nb_param_buffers
++] = data_buffer
;
69 av_log(avctx
, AV_LOG_DEBUG
, "Packed header buffer (%d) is %#x/%#x "
70 "(%zu bits).\n", type
, param_buffer
, data_buffer
, bit_len
);
74 static int vaapi_encode_make_param_buffer(AVCodecContext
*avctx
,
75 VAAPIEncodePicture
*pic
,
76 int type
, char *data
, size_t len
)
78 VAAPIEncodeContext
*ctx
= avctx
->priv_data
;
82 av_assert0(pic
->nb_param_buffers
+ 1 <= MAX_PARAM_BUFFERS
);
84 vas
= vaCreateBuffer(ctx
->hwctx
->display
, ctx
->va_context
,
85 type
, len
, 1, data
, &buffer
);
86 if (vas
!= VA_STATUS_SUCCESS
) {
87 av_log(avctx
, AV_LOG_ERROR
, "Failed to create parameter buffer "
88 "(type %d): %d (%s).\n", type
, vas
, vaErrorStr(vas
));
91 pic
->param_buffers
[pic
->nb_param_buffers
++] = buffer
;
93 av_log(avctx
, AV_LOG_DEBUG
, "Param buffer (%d) is %#x.\n",
98 static int vaapi_encode_wait(AVCodecContext
*avctx
,
99 VAAPIEncodePicture
*pic
)
101 VAAPIEncodeContext
*ctx
= avctx
->priv_data
;
104 av_assert0(pic
->encode_issued
);
106 if (pic
->encode_complete
) {
107 // Already waited for this picture.
111 av_log(avctx
, AV_LOG_DEBUG
, "Sync to pic %"PRId64
"/%"PRId64
" "
112 "(recon surface %#x).\n", pic
->display_order
,
113 pic
->encode_order
, pic
->recon_surface
);
115 vas
= vaSyncSurface(ctx
->hwctx
->display
, pic
->recon_surface
);
116 if (vas
!= VA_STATUS_SUCCESS
) {
117 av_log(avctx
, AV_LOG_ERROR
, "Failed to sync to picture completion: "
118 "%d (%s).\n", vas
, vaErrorStr(vas
));
122 // Input is definitely finished with now.
123 av_frame_free(&pic
->input_image
);
125 pic
->encode_complete
= 1;
129 static int vaapi_encode_issue(AVCodecContext
*avctx
,
130 VAAPIEncodePicture
*pic
)
132 VAAPIEncodeContext
*ctx
= avctx
->priv_data
;
133 VAAPIEncodeSlice
*slice
;
136 char data
[MAX_PARAM_BUFFER_SIZE
];
139 av_log(avctx
, AV_LOG_DEBUG
, "Issuing encode for pic %"PRId64
"/%"PRId64
" "
140 "as type %s.\n", pic
->display_order
, pic
->encode_order
,
141 picture_type_name
[pic
->type
]);
142 if (pic
->nb_refs
== 0) {
143 av_log(avctx
, AV_LOG_DEBUG
, "No reference pictures.\n");
145 av_log(avctx
, AV_LOG_DEBUG
, "Refers to:");
146 for (i
= 0; i
< pic
->nb_refs
; i
++) {
147 av_log(avctx
, AV_LOG_DEBUG
, " %"PRId64
"/%"PRId64
,
148 pic
->refs
[i
]->display_order
, pic
->refs
[i
]->encode_order
);
150 av_log(avctx
, AV_LOG_DEBUG
, ".\n");
153 av_assert0(pic
->input_available
&& !pic
->encode_issued
);
154 for (i
= 0; i
< pic
->nb_refs
; i
++) {
155 av_assert0(pic
->refs
[i
]);
156 // If we are serialised then the references must have already
157 // completed. If not, they must have been issued but need not
158 // have completed yet.
159 if (ctx
->issue_mode
== ISSUE_MODE_SERIALISE_EVERYTHING
)
160 av_assert0(pic
->refs
[i
]->encode_complete
);
162 av_assert0(pic
->refs
[i
]->encode_issued
);
165 av_log(avctx
, AV_LOG_DEBUG
, "Input surface is %#x.\n", pic
->input_surface
);
167 pic
->recon_image
= av_frame_alloc();
168 if (!pic
->recon_image
) {
169 err
= AVERROR(ENOMEM
);
173 err
= av_hwframe_get_buffer(ctx
->recon_frames_ref
, pic
->recon_image
, 0);
175 err
= AVERROR(ENOMEM
);
178 pic
->recon_surface
= (VASurfaceID
)(uintptr_t)pic
->recon_image
->data
[3];
179 av_log(avctx
, AV_LOG_DEBUG
, "Recon surface is %#x.\n", pic
->recon_surface
);
181 vas
= vaCreateBuffer(ctx
->hwctx
->display
, ctx
->va_context
,
182 VAEncCodedBufferType
,
183 MAX_OUTPUT_BUFFER_SIZE
, 1, 0,
184 &pic
->output_buffer
);
185 if (vas
!= VA_STATUS_SUCCESS
) {
186 av_log(avctx
, AV_LOG_ERROR
, "Failed to create bitstream "
187 "output buffer: %d (%s).\n", vas
, vaErrorStr(vas
));
188 err
= AVERROR(ENOMEM
);
191 av_log(avctx
, AV_LOG_DEBUG
, "Output buffer is %#x.\n",
194 if (ctx
->codec
->picture_params_size
> 0) {
195 pic
->codec_picture_params
= av_malloc(ctx
->codec
->picture_params_size
);
196 if (!pic
->codec_picture_params
)
198 memcpy(pic
->codec_picture_params
, ctx
->codec_picture_params
,
199 ctx
->codec
->picture_params_size
);
201 av_assert0(!ctx
->codec_picture_params
);
204 pic
->nb_param_buffers
= 0;
206 if (pic
->encode_order
== 0) {
207 // Global parameter buffers are set on the first picture only.
209 for (i
= 0; i
< ctx
->nb_global_params
; i
++) {
210 err
= vaapi_encode_make_param_buffer(avctx
, pic
,
211 VAEncMiscParameterBufferType
,
212 (char*)ctx
->global_params
[i
],
213 ctx
->global_params_size
[i
]);
219 if (pic
->type
== PICTURE_TYPE_IDR
&& ctx
->codec
->init_sequence_params
) {
220 err
= vaapi_encode_make_param_buffer(avctx
, pic
,
221 VAEncSequenceParameterBufferType
,
222 ctx
->codec_sequence_params
,
223 ctx
->codec
->sequence_params_size
);
228 if (ctx
->codec
->init_picture_params
) {
229 err
= ctx
->codec
->init_picture_params(avctx
, pic
);
231 av_log(avctx
, AV_LOG_ERROR
, "Failed to initialise picture "
232 "parameters: %d.\n", err
);
235 err
= vaapi_encode_make_param_buffer(avctx
, pic
,
236 VAEncPictureParameterBufferType
,
237 pic
->codec_picture_params
,
238 ctx
->codec
->picture_params_size
);
243 if (pic
->type
== PICTURE_TYPE_IDR
) {
244 if (ctx
->codec
->write_sequence_header
) {
245 bit_len
= 8 * sizeof(data
);
246 err
= ctx
->codec
->write_sequence_header(avctx
, data
, &bit_len
);
248 av_log(avctx
, AV_LOG_ERROR
, "Failed to write per-sequence "
249 "header: %d.\n", err
);
252 err
= vaapi_encode_make_packed_header(avctx
, pic
,
253 ctx
->codec
->sequence_header_type
,
260 if (ctx
->codec
->write_picture_header
) {
261 bit_len
= 8 * sizeof(data
);
262 err
= ctx
->codec
->write_picture_header(avctx
, pic
, data
, &bit_len
);
264 av_log(avctx
, AV_LOG_ERROR
, "Failed to write per-picture "
265 "header: %d.\n", err
);
268 err
= vaapi_encode_make_packed_header(avctx
, pic
,
269 ctx
->codec
->picture_header_type
,
275 if (ctx
->codec
->write_extra_buffer
) {
277 size_t len
= sizeof(data
);
279 err
= ctx
->codec
->write_extra_buffer(avctx
, pic
, i
, &type
,
281 if (err
== AVERROR_EOF
)
284 av_log(avctx
, AV_LOG_ERROR
, "Failed to write extra "
285 "buffer %d: %d.\n", i
, err
);
289 err
= vaapi_encode_make_param_buffer(avctx
, pic
, type
,
296 if (ctx
->codec
->write_extra_header
) {
299 bit_len
= 8 * sizeof(data
);
300 err
= ctx
->codec
->write_extra_header(avctx
, pic
, i
, &type
,
302 if (err
== AVERROR_EOF
)
305 av_log(avctx
, AV_LOG_ERROR
, "Failed to write extra "
306 "header %d: %d.\n", i
, err
);
310 err
= vaapi_encode_make_packed_header(avctx
, pic
, type
,
317 av_assert0(pic
->nb_slices
<= MAX_PICTURE_SLICES
);
318 for (i
= 0; i
< pic
->nb_slices
; i
++) {
319 slice
= av_mallocz(sizeof(*slice
));
321 err
= AVERROR(ENOMEM
);
324 pic
->slices
[i
] = slice
;
326 if (ctx
->codec
->slice_params_size
> 0) {
327 slice
->codec_slice_params
= av_mallocz(ctx
->codec
->slice_params_size
);
328 if (!slice
->codec_slice_params
) {
329 err
= AVERROR(ENOMEM
);
334 if (ctx
->codec
->init_slice_params
) {
335 err
= ctx
->codec
->init_slice_params(avctx
, pic
, slice
);
337 av_log(avctx
, AV_LOG_ERROR
, "Failed to initalise slice "
338 "parameters: %d.\n", err
);
343 if (ctx
->codec
->write_slice_header
) {
344 bit_len
= 8 * sizeof(data
);
345 err
= ctx
->codec
->write_slice_header(avctx
, pic
, slice
,
348 av_log(avctx
, AV_LOG_ERROR
, "Failed to write per-slice "
349 "header: %d.\n", err
);
352 err
= vaapi_encode_make_packed_header(avctx
, pic
,
353 ctx
->codec
->slice_header_type
,
359 if (ctx
->codec
->init_slice_params
) {
360 err
= vaapi_encode_make_param_buffer(avctx
, pic
,
361 VAEncSliceParameterBufferType
,
362 slice
->codec_slice_params
,
363 ctx
->codec
->slice_params_size
);
369 vas
= vaBeginPicture(ctx
->hwctx
->display
, ctx
->va_context
,
371 if (vas
!= VA_STATUS_SUCCESS
) {
372 av_log(avctx
, AV_LOG_ERROR
, "Failed to begin picture encode issue: "
373 "%d (%s).\n", vas
, vaErrorStr(vas
));
375 goto fail_with_picture
;
378 vas
= vaRenderPicture(ctx
->hwctx
->display
, ctx
->va_context
,
379 pic
->param_buffers
, pic
->nb_param_buffers
);
380 if (vas
!= VA_STATUS_SUCCESS
) {
381 av_log(avctx
, AV_LOG_ERROR
, "Failed to upload encode parameters: "
382 "%d (%s).\n", vas
, vaErrorStr(vas
));
384 goto fail_with_picture
;
387 vas
= vaEndPicture(ctx
->hwctx
->display
, ctx
->va_context
);
388 if (vas
!= VA_STATUS_SUCCESS
) {
389 av_log(avctx
, AV_LOG_ERROR
, "Failed to end picture encode issue: "
390 "%d (%s).\n", vas
, vaErrorStr(vas
));
395 pic
->encode_issued
= 1;
397 if (ctx
->issue_mode
== ISSUE_MODE_SERIALISE_EVERYTHING
)
398 return vaapi_encode_wait(avctx
, pic
);
403 vaEndPicture(ctx
->hwctx
->display
, ctx
->va_context
);
405 for(i
= 0; i
< pic
->nb_param_buffers
; i
++)
406 vaDestroyBuffer(ctx
->hwctx
->display
, pic
->param_buffers
[i
]);
408 av_freep(&pic
->codec_picture_params
);
409 av_frame_free(&pic
->recon_image
);
413 static int vaapi_encode_output(AVCodecContext
*avctx
,
414 VAAPIEncodePicture
*pic
, AVPacket
*pkt
)
416 VAAPIEncodeContext
*ctx
= avctx
->priv_data
;
417 VACodedBufferSegment
*buf_list
, *buf
;
421 err
= vaapi_encode_wait(avctx
, pic
);
426 vas
= vaMapBuffer(ctx
->hwctx
->display
, pic
->output_buffer
,
428 if (vas
!= VA_STATUS_SUCCESS
) {
429 av_log(avctx
, AV_LOG_ERROR
, "Failed to map output buffers: "
430 "%d (%s).\n", vas
, vaErrorStr(vas
));
435 for (buf
= buf_list
; buf
; buf
= buf
->next
) {
436 av_log(avctx
, AV_LOG_DEBUG
, "Output buffer: %u bytes "
437 "(status %08x).\n", buf
->size
, buf
->status
);
439 err
= av_new_packet(pkt
, buf
->size
);
443 memcpy(pkt
->data
, buf
->buf
, buf
->size
);
446 if (pic
->type
== PICTURE_TYPE_IDR
)
447 pkt
->flags
|= AV_PKT_FLAG_KEY
;
451 vas
= vaUnmapBuffer(ctx
->hwctx
->display
, pic
->output_buffer
);
452 if (vas
!= VA_STATUS_SUCCESS
) {
453 av_log(avctx
, AV_LOG_ERROR
, "Failed to unmap output buffers: "
454 "%d (%s).\n", vas
, vaErrorStr(vas
));
459 vaDestroyBuffer(ctx
->hwctx
->display
, pic
->output_buffer
);
460 pic
->output_buffer
= VA_INVALID_ID
;
462 av_log(avctx
, AV_LOG_DEBUG
, "Output read for pic %"PRId64
"/%"PRId64
".\n",
463 pic
->display_order
, pic
->encode_order
);
467 if (pic
->output_buffer
!= VA_INVALID_ID
) {
468 vaUnmapBuffer(ctx
->hwctx
->display
, pic
->output_buffer
);
469 vaDestroyBuffer(ctx
->hwctx
->display
, pic
->output_buffer
);
470 pic
->output_buffer
= VA_INVALID_ID
;
475 static int vaapi_encode_discard(AVCodecContext
*avctx
,
476 VAAPIEncodePicture
*pic
)
478 VAAPIEncodeContext
*ctx
= avctx
->priv_data
;
480 vaapi_encode_wait(avctx
, pic
);
482 if (pic
->output_buffer
!= VA_INVALID_ID
) {
483 av_log(avctx
, AV_LOG_DEBUG
, "Discard output for pic "
484 "%"PRId64
"/%"PRId64
".\n",
485 pic
->display_order
, pic
->encode_order
);
487 vaDestroyBuffer(ctx
->hwctx
->display
, pic
->output_buffer
);
488 pic
->output_buffer
= VA_INVALID_ID
;
494 static VAAPIEncodePicture
*vaapi_encode_alloc(void)
496 VAAPIEncodePicture
*pic
;
498 pic
= av_mallocz(sizeof(*pic
));
502 pic
->input_surface
= VA_INVALID_ID
;
503 pic
->recon_surface
= VA_INVALID_ID
;
504 pic
->output_buffer
= VA_INVALID_ID
;
509 static int vaapi_encode_free(AVCodecContext
*avctx
,
510 VAAPIEncodePicture
*pic
)
514 if (pic
->encode_issued
)
515 vaapi_encode_discard(avctx
, pic
);
517 for (i
= 0; i
< pic
->nb_slices
; i
++) {
518 av_freep(&pic
->slices
[i
]->priv_data
);
519 av_freep(&pic
->slices
[i
]->codec_slice_params
);
520 av_freep(&pic
->slices
[i
]);
522 av_freep(&pic
->codec_picture_params
);
524 av_frame_free(&pic
->input_image
);
525 av_frame_free(&pic
->recon_image
);
527 // Output buffer should already be destroyed.
528 av_assert0(pic
->output_buffer
== VA_INVALID_ID
);
530 av_freep(&pic
->priv_data
);
531 av_freep(&pic
->codec_picture_params
);
538 static int vaapi_encode_step(AVCodecContext
*avctx
,
539 VAAPIEncodePicture
*target
)
541 VAAPIEncodeContext
*ctx
= avctx
->priv_data
;
542 VAAPIEncodePicture
*pic
;
545 if (ctx
->issue_mode
== ISSUE_MODE_SERIALISE_EVERYTHING
||
546 ctx
->issue_mode
== ISSUE_MODE_MINIMISE_LATENCY
) {
547 // These two modes are equivalent, except that we wait for
548 // immediate completion on each operation if serialised.
551 // No target, nothing to do yet.
555 if (target
->encode_complete
) {
561 for (i
= 0; i
< pic
->nb_refs
; i
++) {
562 if (!pic
->refs
[i
]->encode_complete
) {
563 err
= vaapi_encode_step(avctx
, pic
->refs
[i
]);
569 err
= vaapi_encode_issue(avctx
, pic
);
573 } else if (ctx
->issue_mode
== ISSUE_MODE_MAXIMISE_THROUGHPUT
) {
578 for (pic
= ctx
->pic_start
; pic
; pic
= pic
->next
) {
579 if (!pic
->input_available
|| pic
->encode_issued
)
581 for (i
= 0; i
< pic
->nb_refs
; i
++) {
582 if (!pic
->refs
[i
]->encode_issued
)
585 if (i
< pic
->nb_refs
)
587 err
= vaapi_encode_issue(avctx
, pic
);
595 av_assert0(target
->encode_issued
&& "broken dependencies?");
605 static int vaapi_encode_get_next(AVCodecContext
*avctx
,
606 VAAPIEncodePicture
**pic_out
)
608 VAAPIEncodeContext
*ctx
= avctx
->priv_data
;
609 VAAPIEncodePicture
*start
, *end
, *pic
;
612 for (pic
= ctx
->pic_start
; pic
; pic
= pic
->next
) {
614 av_assert0(pic
->display_order
+ 1 == pic
->next
->display_order
);
615 if (pic
->display_order
== ctx
->input_order
) {
621 if (ctx
->input_order
== 0) {
622 // First frame is always an IDR frame.
623 av_assert0(!ctx
->pic_start
&& !ctx
->pic_end
);
625 pic
= vaapi_encode_alloc();
627 return AVERROR(ENOMEM
);
629 pic
->type
= PICTURE_TYPE_IDR
;
630 pic
->display_order
= 0;
631 pic
->encode_order
= 0;
633 ctx
->pic_start
= ctx
->pic_end
= pic
;
639 pic
= vaapi_encode_alloc();
641 return AVERROR(ENOMEM
);
643 if (ctx
->p_per_i
== 0 || ctx
->p_counter
== ctx
->p_per_i
) {
644 if (ctx
->i_per_idr
== 0 || ctx
->i_counter
== ctx
->i_per_idr
) {
645 pic
->type
= PICTURE_TYPE_IDR
;
648 pic
->type
= PICTURE_TYPE_I
;
653 pic
->type
= PICTURE_TYPE_P
;
654 pic
->refs
[0] = ctx
->pic_end
;
660 if (pic
->type
!= PICTURE_TYPE_IDR
) {
661 // If that was not an IDR frame, add B-frames display-before and
664 for (i
= 0; i
< ctx
->b_per_p
; i
++) {
665 pic
= vaapi_encode_alloc();
669 pic
->type
= PICTURE_TYPE_B
;
670 pic
->refs
[0] = ctx
->pic_end
;
675 pic
->display_order
= ctx
->input_order
+ ctx
->b_per_p
- i
- 1;
676 pic
->encode_order
= pic
->display_order
+ 1;
681 for (i
= 0, pic
= start
; pic
; i
++, pic
= pic
->next
) {
682 pic
->display_order
= ctx
->input_order
+ i
;
683 if (end
->type
== PICTURE_TYPE_IDR
)
684 pic
->encode_order
= ctx
->input_order
+ i
;
686 pic
->encode_order
= ctx
->input_order
;
688 pic
->encode_order
= ctx
->input_order
+ i
+ 1;
691 av_assert0(ctx
->pic_end
);
692 ctx
->pic_end
->next
= start
;
697 av_log(avctx
, AV_LOG_DEBUG
, "Pictures:");
698 for (pic
= ctx
->pic_start
; pic
; pic
= pic
->next
) {
699 av_log(avctx
, AV_LOG_DEBUG
, " %s (%"PRId64
"/%"PRId64
")",
700 picture_type_name
[pic
->type
],
701 pic
->display_order
, pic
->encode_order
);
703 av_log(avctx
, AV_LOG_DEBUG
, "\n");
710 vaapi_encode_free(avctx
, start
);
713 return AVERROR(ENOMEM
);
716 static int vaapi_encode_mangle_end(AVCodecContext
*avctx
)
718 VAAPIEncodeContext
*ctx
= avctx
->priv_data
;
719 VAAPIEncodePicture
*pic
, *last_pic
, *next
;
721 // Find the last picture we actually have input for.
722 for (pic
= ctx
->pic_start
; pic
; pic
= pic
->next
) {
723 if (!pic
->input_available
)
729 av_assert0(last_pic
);
731 if (last_pic
->type
== PICTURE_TYPE_B
) {
732 // Some fixing up is required. Change the type of this
733 // picture to P, then modify preceding B references which
734 // point beyond it to point at it instead.
736 last_pic
->type
= PICTURE_TYPE_P
;
737 last_pic
->encode_order
= last_pic
->refs
[1]->encode_order
;
739 for (pic
= ctx
->pic_start
; pic
!= last_pic
; pic
= pic
->next
) {
740 if (pic
->type
== PICTURE_TYPE_B
&&
741 pic
->refs
[1] == last_pic
->refs
[1])
742 pic
->refs
[1] = last_pic
;
745 last_pic
->nb_refs
= 1;
746 last_pic
->refs
[1] = NULL
;
748 // We can use the current structure (no references point
749 // beyond the end), but there are unused pics to discard.
752 // Discard all following pics, they will never be used.
753 for (pic
= last_pic
->next
; pic
; pic
= next
) {
755 vaapi_encode_free(avctx
, pic
);
758 last_pic
->next
= NULL
;
759 ctx
->pic_end
= last_pic
;
762 // Input is available for all pictures, so we don't need to
766 av_log(avctx
, AV_LOG_DEBUG
, "Pictures at end of stream:");
767 for (pic
= ctx
->pic_start
; pic
; pic
= pic
->next
) {
768 av_log(avctx
, AV_LOG_DEBUG
, " %s (%"PRId64
"/%"PRId64
")",
769 picture_type_name
[pic
->type
],
770 pic
->display_order
, pic
->encode_order
);
772 av_log(avctx
, AV_LOG_DEBUG
, "\n");
777 static int vaapi_encode_clear_old(AVCodecContext
*avctx
)
779 VAAPIEncodeContext
*ctx
= avctx
->priv_data
;
780 VAAPIEncodePicture
*pic
, *old
;
783 while (ctx
->pic_start
!= ctx
->pic_end
) {
784 old
= ctx
->pic_start
;
785 if (old
->encode_order
> ctx
->output_order
)
788 for (pic
= old
->next
; pic
; pic
= pic
->next
) {
789 if (pic
->encode_complete
)
791 for (i
= 0; i
< pic
->nb_refs
; i
++) {
792 if (pic
->refs
[i
] == old
) {
793 // We still need this picture because it's referred to
794 // directly by a later one, so it and all following
795 // pictures have to stay.
801 pic
= ctx
->pic_start
;
802 ctx
->pic_start
= pic
->next
;
803 vaapi_encode_free(avctx
, pic
);
809 int ff_vaapi_encode2(AVCodecContext
*avctx
, AVPacket
*pkt
,
810 const AVFrame
*input_image
, int *got_packet
)
812 VAAPIEncodeContext
*ctx
= avctx
->priv_data
;
813 VAAPIEncodePicture
*pic
;
817 av_log(avctx
, AV_LOG_DEBUG
, "Encode frame: %ux%u (%"PRId64
").\n",
818 input_image
->width
, input_image
->height
, input_image
->pts
);
820 err
= vaapi_encode_get_next(avctx
, &pic
);
822 av_log(avctx
, AV_LOG_ERROR
, "Input setup failed: %d.\n", err
);
826 pic
->input_image
= av_frame_alloc();
827 if (!pic
->input_image
) {
828 err
= AVERROR(ENOMEM
);
831 err
= av_frame_ref(pic
->input_image
, input_image
);
834 pic
->input_surface
= (VASurfaceID
)(uintptr_t)input_image
->data
[3];
835 pic
->pts
= input_image
->pts
;
837 if (ctx
->input_order
== 0)
838 ctx
->first_pts
= pic
->pts
;
839 if (ctx
->input_order
== ctx
->decode_delay
)
840 ctx
->dts_pts_diff
= pic
->pts
- ctx
->first_pts
;
841 if (ctx
->output_delay
> 0)
842 ctx
->ts_ring
[ctx
->input_order
% (3 * ctx
->output_delay
)] = pic
->pts
;
844 pic
->input_available
= 1;
847 if (!ctx
->end_of_stream
) {
848 err
= vaapi_encode_mangle_end(avctx
);
851 ctx
->end_of_stream
= 1;
857 av_assert0(ctx
->output_order
+ ctx
->output_delay
+ 1 == ctx
->input_order
);
859 for (pic
= ctx
->pic_start
; pic
; pic
= pic
->next
)
860 if (pic
->encode_order
== ctx
->output_order
)
863 // pic can be null here if we don't have a specific target in this
864 // iteration. We might still issue encodes if things can be overlapped,
865 // even though we don't intend to output anything.
867 err
= vaapi_encode_step(avctx
, pic
);
869 av_log(avctx
, AV_LOG_ERROR
, "Encode failed: %d.\n", err
);
876 err
= vaapi_encode_output(avctx
, pic
, pkt
);
878 av_log(avctx
, AV_LOG_ERROR
, "Output failed: %d.\n", err
);
882 if (ctx
->output_delay
== 0) {
884 } else if (ctx
->output_order
< ctx
->decode_delay
) {
885 if (ctx
->ts_ring
[ctx
->output_order
] < INT64_MIN
+ ctx
->dts_pts_diff
)
886 pkt
->dts
= INT64_MIN
;
888 pkt
->dts
= ctx
->ts_ring
[ctx
->output_order
] - ctx
->dts_pts_diff
;
890 pkt
->dts
= ctx
->ts_ring
[(ctx
->output_order
- ctx
->decode_delay
) %
891 (3 * ctx
->output_delay
)];
897 err
= vaapi_encode_clear_old(avctx
);
899 av_log(avctx
, AV_LOG_ERROR
, "List clearing failed: %d.\n", err
);
906 // Unclear what to clean up on failure. There are probably some things we
907 // could do usefully clean up here, but for now just leave them for uninit()
912 static av_cold
int vaapi_encode_check_config(AVCodecContext
*avctx
)
914 VAAPIEncodeContext
*ctx
= avctx
->priv_data
;
917 VAProfile
*profiles
= NULL
;
918 VAEntrypoint
*entrypoints
= NULL
;
919 VAConfigAttrib attr
[] = {
920 { VAConfigAttribRateControl
},
921 { VAConfigAttribEncMaxRefFrames
},
924 n
= vaMaxNumProfiles(ctx
->hwctx
->display
);
925 profiles
= av_malloc_array(n
, sizeof(VAProfile
));
927 err
= AVERROR(ENOMEM
);
930 vas
= vaQueryConfigProfiles(ctx
->hwctx
->display
, profiles
, &n
);
931 if (vas
!= VA_STATUS_SUCCESS
) {
932 av_log(ctx
, AV_LOG_ERROR
, "Failed to query profiles: %d (%s).\n",
933 vas
, vaErrorStr(vas
));
934 err
= AVERROR(ENOSYS
);
937 for (i
= 0; i
< n
; i
++) {
938 if (profiles
[i
] == ctx
->va_profile
)
942 av_log(ctx
, AV_LOG_ERROR
, "Encoding profile not found (%d).\n",
944 err
= AVERROR(ENOSYS
);
948 n
= vaMaxNumEntrypoints(ctx
->hwctx
->display
);
949 entrypoints
= av_malloc_array(n
, sizeof(VAEntrypoint
));
951 err
= AVERROR(ENOMEM
);
954 vas
= vaQueryConfigEntrypoints(ctx
->hwctx
->display
, ctx
->va_profile
,
956 if (vas
!= VA_STATUS_SUCCESS
) {
957 av_log(ctx
, AV_LOG_ERROR
, "Failed to query entrypoints for "
958 "profile %u: %d (%s).\n", ctx
->va_profile
,
959 vas
, vaErrorStr(vas
));
960 err
= AVERROR(ENOSYS
);
963 for (i
= 0; i
< n
; i
++) {
964 if (entrypoints
[i
] == ctx
->va_entrypoint
)
968 av_log(ctx
, AV_LOG_ERROR
, "Encoding entrypoint not found "
969 "(%d / %d).\n", ctx
->va_profile
, ctx
->va_entrypoint
);
970 err
= AVERROR(ENOSYS
);
974 vas
= vaGetConfigAttributes(ctx
->hwctx
->display
,
975 ctx
->va_profile
, ctx
->va_entrypoint
,
976 attr
, FF_ARRAY_ELEMS(attr
));
977 if (vas
!= VA_STATUS_SUCCESS
) {
978 av_log(avctx
, AV_LOG_ERROR
, "Failed to fetch config "
979 "attributes: %d (%s).\n", vas
, vaErrorStr(vas
));
980 return AVERROR(EINVAL
);
983 for (i
= 0; i
< FF_ARRAY_ELEMS(attr
); i
++) {
984 if (attr
[i
].value
== VA_ATTRIB_NOT_SUPPORTED
) {
985 // Unfortunately we have to treat this as "don't know" and hope
986 // for the best, because the Intel MJPEG encoder returns this
987 // for all the interesting attributes.
990 switch (attr
[i
].type
) {
991 case VAConfigAttribRateControl
:
992 if (!(ctx
->va_rc_mode
& attr
[i
].value
)) {
993 av_log(avctx
, AV_LOG_ERROR
, "Rate control mode is not "
994 "supported: %x\n", attr
[i
].value
);
995 err
= AVERROR(EINVAL
);
999 case VAConfigAttribEncMaxRefFrames
:
1001 unsigned int ref_l0
= attr
[i
].value
& 0xffff;
1002 unsigned int ref_l1
= (attr
[i
].value
>> 16) & 0xffff;
1004 if (avctx
->gop_size
> 1 && ref_l0
< 1) {
1005 av_log(avctx
, AV_LOG_ERROR
, "P frames are not "
1006 "supported (%x).\n", attr
[i
].value
);
1007 err
= AVERROR(EINVAL
);
1010 if (avctx
->max_b_frames
> 0 && ref_l1
< 1) {
1011 av_log(avctx
, AV_LOG_ERROR
, "B frames are not "
1012 "supported (%x).\n", attr
[i
].value
);
1013 err
= AVERROR(EINVAL
);
1023 av_freep(&profiles
);
1024 av_freep(&entrypoints
);
1028 av_cold
int ff_vaapi_encode_init(AVCodecContext
*avctx
,
1029 const VAAPIEncodeType
*type
)
1031 VAAPIEncodeContext
*ctx
= avctx
->priv_data
;
1032 AVVAAPIFramesContext
*recon_hwctx
= NULL
;
1033 AVVAAPIHWConfig
*hwconfig
= NULL
;
1034 AVHWFramesConstraints
*constraints
= NULL
;
1035 enum AVPixelFormat recon_format
;
1039 if (!avctx
->hw_frames_ctx
) {
1040 av_log(avctx
, AV_LOG_ERROR
, "A hardware frames reference is "
1041 "required to associate the encoding device.\n");
1042 return AVERROR(EINVAL
);
1046 ctx
->codec_options
= ctx
->codec_options_data
;
1048 ctx
->va_config
= VA_INVALID_ID
;
1049 ctx
->va_context
= VA_INVALID_ID
;
1051 ctx
->priv_data
= av_mallocz(type
->priv_data_size
);
1052 if (!ctx
->priv_data
) {
1053 err
= AVERROR(ENOMEM
);
1057 ctx
->input_frames_ref
= av_buffer_ref(avctx
->hw_frames_ctx
);
1058 if (!ctx
->input_frames_ref
) {
1059 err
= AVERROR(ENOMEM
);
1062 ctx
->input_frames
= (AVHWFramesContext
*)ctx
->input_frames_ref
->data
;
1064 ctx
->device_ref
= av_buffer_ref(ctx
->input_frames
->device_ref
);
1065 if (!ctx
->device_ref
) {
1066 err
= AVERROR(ENOMEM
);
1069 ctx
->device
= (AVHWDeviceContext
*)ctx
->device_ref
->data
;
1070 ctx
->hwctx
= ctx
->device
->hwctx
;
1072 err
= ctx
->codec
->init(avctx
);
1076 err
= vaapi_encode_check_config(avctx
);
1080 vas
= vaCreateConfig(ctx
->hwctx
->display
,
1081 ctx
->va_profile
, ctx
->va_entrypoint
,
1082 ctx
->config_attributes
, ctx
->nb_config_attributes
,
1084 if (vas
!= VA_STATUS_SUCCESS
) {
1085 av_log(avctx
, AV_LOG_ERROR
, "Failed to create encode pipeline "
1086 "configuration: %d (%s).\n", vas
, vaErrorStr(vas
));
1091 hwconfig
= av_hwdevice_hwconfig_alloc(ctx
->device_ref
);
1093 err
= AVERROR(ENOMEM
);
1096 hwconfig
->config_id
= ctx
->va_config
;
1098 constraints
= av_hwdevice_get_hwframe_constraints(ctx
->device_ref
,
1101 err
= AVERROR(ENOMEM
);
1105 // Probably we can use the input surface format as the surface format
1106 // of the reconstructed frames. If not, we just pick the first (only?)
1107 // format in the valid list and hope that it all works.
1108 recon_format
= AV_PIX_FMT_NONE
;
1109 if (constraints
->valid_sw_formats
) {
1110 for (i
= 0; constraints
->valid_sw_formats
[i
] != AV_PIX_FMT_NONE
; i
++) {
1111 if (ctx
->input_frames
->sw_format
==
1112 constraints
->valid_sw_formats
[i
]) {
1113 recon_format
= ctx
->input_frames
->sw_format
;
1117 if (recon_format
== AV_PIX_FMT_NONE
)
1118 recon_format
= constraints
->valid_sw_formats
[i
];
1120 // No idea what to use; copy input format.
1121 recon_format
= ctx
->input_frames
->sw_format
;
1123 av_log(avctx
, AV_LOG_DEBUG
, "Using %s as format of "
1124 "reconstructed frames.\n", av_get_pix_fmt_name(recon_format
));
1126 if (ctx
->aligned_width
< constraints
->min_width
||
1127 ctx
->aligned_height
< constraints
->min_height
||
1128 ctx
->aligned_width
> constraints
->max_width
||
1129 ctx
->aligned_height
> constraints
->max_height
) {
1130 av_log(avctx
, AV_LOG_ERROR
, "Hardware does not support encoding at "
1131 "size %dx%d (constraints: width %d-%d height %d-%d).\n",
1132 ctx
->aligned_width
, ctx
->aligned_height
,
1133 constraints
->min_width
, constraints
->max_width
,
1134 constraints
->min_height
, constraints
->max_height
);
1135 err
= AVERROR(EINVAL
);
1139 av_freep(&hwconfig
);
1140 av_hwframe_constraints_free(&constraints
);
1142 ctx
->recon_frames_ref
= av_hwframe_ctx_alloc(ctx
->device_ref
);
1143 if (!ctx
->recon_frames_ref
) {
1144 err
= AVERROR(ENOMEM
);
1147 ctx
->recon_frames
= (AVHWFramesContext
*)ctx
->recon_frames_ref
->data
;
1149 ctx
->recon_frames
->format
= AV_PIX_FMT_VAAPI
;
1150 ctx
->recon_frames
->sw_format
= recon_format
;
1151 ctx
->recon_frames
->width
= ctx
->aligned_width
;
1152 ctx
->recon_frames
->height
= ctx
->aligned_height
;
1153 ctx
->recon_frames
->initial_pool_size
= ctx
->nb_recon_frames
;
1155 err
= av_hwframe_ctx_init(ctx
->recon_frames_ref
);
1157 av_log(avctx
, AV_LOG_ERROR
, "Failed to initialise reconstructed "
1158 "frame context: %d.\n", err
);
1161 recon_hwctx
= ctx
->recon_frames
->hwctx
;
1163 vas
= vaCreateContext(ctx
->hwctx
->display
, ctx
->va_config
,
1164 ctx
->aligned_width
, ctx
->aligned_height
,
1166 recon_hwctx
->surface_ids
,
1167 recon_hwctx
->nb_surfaces
,
1169 if (vas
!= VA_STATUS_SUCCESS
) {
1170 av_log(avctx
, AV_LOG_ERROR
, "Failed to create encode pipeline "
1171 "context: %d (%s).\n", vas
, vaErrorStr(vas
));
1176 ctx
->input_order
= 0;
1177 ctx
->output_delay
= avctx
->max_b_frames
;
1178 ctx
->decode_delay
= 1;
1179 ctx
->output_order
= - ctx
->output_delay
- 1;
1181 if (ctx
->codec
->sequence_params_size
> 0) {
1182 ctx
->codec_sequence_params
=
1183 av_mallocz(ctx
->codec
->sequence_params_size
);
1184 if (!ctx
->codec_sequence_params
) {
1185 err
= AVERROR(ENOMEM
);
1189 if (ctx
->codec
->picture_params_size
> 0) {
1190 ctx
->codec_picture_params
=
1191 av_mallocz(ctx
->codec
->picture_params_size
);
1192 if (!ctx
->codec_picture_params
) {
1193 err
= AVERROR(ENOMEM
);
1198 if (ctx
->codec
->init_sequence_params
) {
1199 err
= ctx
->codec
->init_sequence_params(avctx
);
1201 av_log(avctx
, AV_LOG_ERROR
, "Codec sequence initialisation "
1202 "failed: %d.\n", err
);
1207 // All I are IDR for now.
1209 ctx
->p_per_i
= ((avctx
->gop_size
+ avctx
->max_b_frames
) /
1210 (avctx
->max_b_frames
+ 1));
1211 ctx
->b_per_p
= avctx
->max_b_frames
;
1213 // This should be configurable somehow. (Needs testing on a machine
1214 // where it actually overlaps properly, though.)
1215 ctx
->issue_mode
= ISSUE_MODE_MAXIMISE_THROUGHPUT
;
1220 av_freep(&hwconfig
);
1221 av_hwframe_constraints_free(&constraints
);
1222 ff_vaapi_encode_close(avctx
);
1226 av_cold
int ff_vaapi_encode_close(AVCodecContext
*avctx
)
1228 VAAPIEncodeContext
*ctx
= avctx
->priv_data
;
1229 VAAPIEncodePicture
*pic
, *next
;
1231 for (pic
= ctx
->pic_start
; pic
; pic
= next
) {
1233 vaapi_encode_free(avctx
, pic
);
1236 if (ctx
->va_context
!= VA_INVALID_ID
) {
1237 vaDestroyContext(ctx
->hwctx
->display
, ctx
->va_context
);
1238 ctx
->va_context
= VA_INVALID_ID
;
1241 if (ctx
->va_config
!= VA_INVALID_ID
) {
1242 vaDestroyConfig(ctx
->hwctx
->display
, ctx
->va_config
);
1243 ctx
->va_config
= VA_INVALID_ID
;
1246 if (ctx
->codec
->close
)
1247 ctx
->codec
->close(avctx
);
1249 av_freep(&ctx
->codec_sequence_params
);
1250 av_freep(&ctx
->codec_picture_params
);
1252 av_buffer_unref(&ctx
->recon_frames_ref
);
1253 av_buffer_unref(&ctx
->input_frames_ref
);
1254 av_buffer_unref(&ctx
->device_ref
);
1256 av_freep(&ctx
->priv_data
);