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
30
31 #if CONFIG_D3D11VA
33 #endif
34 #if CONFIG_DXVA2
35 #define COBJMACROS
37 #endif
38
39 #ifdef _WIN32
41 #else
42 #include <dlfcn.h>
43 #endif
44 //will be in public headers soon
45 #define AMF_VIDEO_DECODER_OUTPUT_FORMAT L"OutputDecodeFormat"
46
53 };
54
62 },
64 },
66 };
67
69 {
70 AMFSurface *surface = (AMFSurface*)(
data);
71 surface->pVtbl->Release(surface);
72 }
73
75 {
76 if( AMF_GET_MAJOR_VERSION(amf_device_ctx->
version) <= 1 &&
77 AMF_GET_MINOR_VERSION(amf_device_ctx->
version) <= 4 &&
78 AMF_GET_SUBMINOR_VERSION(amf_device_ctx->
version) < 36)
79 return 1;
80 return 0;
81 }
82
84 {
89 AMF_RESULT res;
91 amf_int64 color_profile;
92 int pool_size = 36;
93 // way-around for older drivers that don't support dynamic bitness detection -
94 // define HEVC and VP9 10-bit based on container info
96
98 ctx->resolution_changed = 0;
99
102 codec_id = AMFVideoDecoderUVD_H264_AVC;
103 break;
105 codec_id = AMFVideoDecoderHW_H265_HEVC;
106 if(no_bitness_detect){
108 codec_id = AMFVideoDecoderHW_H265_MAIN10;
109 }
110 } break;
113 if(no_bitness_detect){
115 codec_id = AMFVideoDecoderHW_VP9_10BIT;
116 }
117 } break;
120 break;
121 default:
122 break;
123 }
125
126 res = amf_device_ctx->factory->pVtbl->CreateComponent(amf_device_ctx->factory, amf_device_ctx->context,
codec_id, &
ctx->decoder);
128
129 // Color Metadata
130 /// Color Range (Support for older Drivers)
132 AMF_ASSIGN_PROPERTY_BOOL(res,
ctx->decoder, AMF_VIDEO_DECODER_FULL_RANGE_COLOR, 1);
134 AMF_ASSIGN_PROPERTY_BOOL(res,
ctx->decoder, AMF_VIDEO_DECODER_FULL_RANGE_COLOR, 0);
135 }
136 color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN;
140 color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_601;
141 } else {
142 color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_601;
143 }
144 break;
147 color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_709;
148 } else {
149 color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_709;
150 }
151 break;
155 color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_2020;
156 } else {
157 color_profile = AMF_VIDEO_CONVERTER_COLOR_PROFILE_2020;
158 }
159 break;
160 }
161 if (color_profile != AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN)
162 AMF_ASSIGN_PROPERTY_INT64(res,
ctx->decoder, AMF_VIDEO_DECODER_COLOR_PROFILE, color_profile);
164 AMF_ASSIGN_PROPERTY_INT64(res,
ctx->decoder, AMF_VIDEO_DECODER_COLOR_TRANSFER_CHARACTERISTIC, (amf_int64)avctx->
color_trc);
165
167 AMF_ASSIGN_PROPERTY_INT64(res,
ctx->decoder, AMF_VIDEO_DECODER_COLOR_PRIMARIES, (amf_int64)avctx->
color_primaries);
168
169 if (
ctx->timestamp_mode != -1)
170 AMF_ASSIGN_PROPERTY_INT64(res,
ctx->decoder, AMF_TIMESTAMP_MODE,
ctx->timestamp_mode);
171 if (
ctx->decoder_mode != -1)
172 AMF_ASSIGN_PROPERTY_INT64(res,
ctx->decoder, AMF_VIDEO_DECODER_REORDER_MODE,
ctx->decoder_mode);
173 if (
ctx->dpb_size != -1)
174 AMF_ASSIGN_PROPERTY_INT64(res,
ctx->decoder, AMF_VIDEO_DECODER_DPB_SIZE,
ctx->dpb_size);
175 if (
ctx->lowlatency != -1)
176 AMF_ASSIGN_PROPERTY_INT64(res,
ctx->decoder, AMF_VIDEO_DECODER_LOW_LATENCY,
ctx->lowlatency);
177 if (
ctx->smart_access_video != -1) {
178 AMF_ASSIGN_PROPERTY_INT64(res,
ctx->decoder, AMF_VIDEO_DECODER_ENABLE_SMART_ACCESS_VIDEO,
ctx->smart_access_video != 0);
179 if (res != AMF_OK) {
180 av_log(avctx,
AV_LOG_ERROR,
"The Smart Access Video is not supported by AMF decoder.\n");
182 } else {
184 // Set low latency mode if Smart Access Video is enabled
185 if (
ctx->smart_access_video != 0) {
186 AMF_ASSIGN_PROPERTY_INT64(res,
ctx->decoder, AMF_VIDEO_DECODER_LOW_LATENCY,
true);
187 av_log(avctx,
AV_LOG_INFO,
"The Smart Access Video set low latency mode for decoder.\n");
188 }
189 }
190 }
191 if (
ctx->skip_transfer_sav != -1)
192 AMF_ASSIGN_PROPERTY_INT64(res,
ctx->decoder, AMF_VIDEO_DECODER_SKIP_TRANSFER_SMART_ACCESS_VIDEO,
ctx->skip_transfer_sav);
193
194 if (
ctx->copy_output != -1)
195 AMF_ASSIGN_PROPERTY_INT64(res,
ctx->decoder, AMF_VIDEO_DECODER_SURFACE_COPY,
ctx->copy_output);
196
198 const uint8_t *extradata;
199 int extradata_size;
201 res = amf_device_ctx->context->pVtbl->AllocBuffer(amf_device_ctx->context, AMF_MEMORY_HOST, extradata_size, &
buffer);
202 if (res == AMF_OK) {
203 memcpy(
buffer->pVtbl->GetNative(
buffer), extradata, extradata_size);
204 AMF_ASSIGN_PROPERTY_INTERFACE(res,
ctx->decoder, AMF_VIDEO_DECODER_EXTRADATA,
buffer);
207 }
208 }
209 if (
ctx->surface_pool_size == -1) {
210 ctx->surface_pool_size = pool_size;
215 }
216
217 //at the moment, there is such a restriction in AMF.
218 //when it is possible, I will remove this code
219 if (
ctx->surface_pool_size > 100)
220 ctx->surface_pool_size = 100;
221
222 AMF_ASSIGN_PROPERTY_INT64(res,
ctx->decoder, AMF_VIDEO_DECODER_SURFACE_POOL_SIZE,
ctx->surface_pool_size);
223 res =
ctx->decoder->pVtbl->Init(
ctx->decoder, AMF_SURFACE_UNKNOWN, avctx->
width, avctx->
height);
224 if (res != AMF_OK) {
227 }
228 return 0;
229 }
230
232 {
234
236 ctx->decoder->pVtbl->Terminate(
ctx->decoder);
237 ctx->decoder->pVtbl->Release(
ctx->decoder);
239 }
240
243
244 return 0;
245 }
246
248 {
254 return 0;
258
260 return 0;
261
262 hwframes_ctx->
width = new_width;
263 hwframes_ctx->
height = new_height;
267
273 }
274 return 0;
275 }
276
278 {
284
289 {
292
294 } else {
297 }
298 } else {
301 }
306
308 // if bitness detection is not supported in legacy driver use format from container
315 }
316 }else{
317 AMFVariantStruct format_var = {0};
318
321
323 }
325 {
326 // this values should be set for avcodec_open2
327 // will be updated after header decoded if not true.
336 }
337 else
339
340 return 0;
341 }
345 }
346
348 {
349 AMF_RESULT res;
350 AMFVariantStruct var;
351 res = AMFVariantInit(&var);
352 if (res == AMF_OK) {
353 res =
object->pVtbl->GetProperty(
object,
name, &var);
354 if (res == AMF_OK) {
355 if (var.type == AMF_VARIANT_INTERFACE) {
356 AMFGuid guid_AMFBuffer = IID_AMFBuffer();
357 AMFInterface *amf_interface = AMFVariantInterface(&var);
358 res = amf_interface->pVtbl->QueryInterface(amf_interface, &guid_AMFBuffer, (
void**)
val);
359 } else {
360 res = AMF_INVALID_DATA_TYPE;
361 }
362 }
363 AMFVariantClear(&var);
364 }
365 return res;
366 }
367
369 {
370 AMFVariantStruct var = {0};
371 AMFPlane *plane;
374 int format_amf;
375
377 // prepare frame similar to ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF);
378
382
384
390
391 ////
396
397 frame->data[0] = (uint8_t *)surface;
399 format_amf = surface->pVtbl->GetFormat(surface);
402 } else {
403 ret = surface->pVtbl->Convert(surface, AMF_MEMORY_HOST);
405
406 for (
i = 0;
i < surface->pVtbl->GetPlanesCount(surface);
i++) {
407 plane = surface->pVtbl->GetPlaneAt(surface,
i);
408 frame->data[
i] = plane->pVtbl->GetNative(plane);
409 frame->linesize[
i] = plane->pVtbl->GetHPitch(plane);
410 }
411
416
417 format_amf = surface->pVtbl->GetFormat(surface);
419 }
420
423
424 frame->pts = surface->pVtbl->GetPts(surface);
425
426 surface->pVtbl->GetProperty(surface,
L "FFMPEG:dts", &var);
427 frame->pkt_dts = var.int64Value;
428
429 frame->duration = surface->pVtbl->GetDuration(surface);
430 if (
frame->duration < 0)
432
437
439 AMFBuffer * hdrmeta_buffer =
NULL;
441 if (hdrmeta_buffer !=
NULL) {
442 AMFHDRMetadata * hdrmeta = (AMFHDRMetadata*)hdrmeta_buffer->pVtbl->GetNative(hdrmeta_buffer);
445 if (hdrmeta !=
NULL) {
447 const int chroma_den = 50000;
448 const int luma_den = 10000;
449
450 if (!mastering)
452
455
458
461
464
467
470 if (hdrmeta->maxContentLightLevel) {
472
473 if (!light)
475
476 light->
MaxCLL = hdrmeta->maxContentLightLevel;
477 light->
MaxFALL = hdrmeta->maxFrameAverageLightLevel;
478 }
479 }
480 }
481 }
482 return 0;
483 }
484
486 {
488 AMF_RESULT
ret = AMF_OK;
489 AMFSurface *surface =
NULL;
490 AMFData *data_out =
NULL;
491
492 ret =
ctx->decoder->pVtbl->QueryOutput(
ctx->decoder, &data_out);
493 if (
ret != AMF_OK &&
ret != AMF_REPEAT) {
495 }
496 if (data_out ==
NULL) {
497 return AMF_REPEAT;
498 }
499
500 if (data_out) {
501 AMFGuid guid = IID_AMFSurface();
502 data_out->pVtbl->QueryInterface(data_out, &guid, (void**)&surface); // query for buffer interface
503 data_out->pVtbl->Release(data_out);
505 }
506
509 return AMF_OK;
511
512 if (surface) {
513 surface->pVtbl->Release(surface);
515 }
517 }
518
520 {
521 AMF_RESULT res;
522
527 AMF_ASSIGN_PROPERTY_INT64(res,
buffer,
L "FFMPEG:dts",
pkt->
dts);
528 if (res != AMF_OK)
530 return AMF_OK;
531 }
532
534 {
538 AMFContext *ctxt = amf_device_ctx->context;
539 void *mem;
540 AMF_RESULT err;
541 AMFBuffer *buf =
NULL;
542
545
549 err = buf->pVtbl->SetSize(buf,
pkt->
size);
550 AMF_RETURN_IF_FALSE(ctxt, err == AMF_OK, err,
"amf_buffer_from_packet() - SetSize failed");
551 // get the memory location and check the buffer was indeed allocated
552 mem = buf->pVtbl->GetNative(buf);
554
555 // copy the packet memory and clear data padding
558
560 }
561
563 {
565 AMFBuffer *buf;
566 AMF_RESULT res;
567 int got_frame = 0;
569
572
573 // get packet if needed
575 if(
ctx->resolution_changed)
576 ctx->resolution_changed = 0;
577 else{
584 //nothing to consume, start external drain
585 ctx->decoder->pVtbl->Drain(
ctx->decoder);
587 }
588 }
589 }
590
592 // submit frame
595 do{
596 res =
ctx->decoder->pVtbl->SubmitInput(
ctx->decoder, (AMFData*) buf);
597 if(res == AMF_DECODER_NO_FREE_SURFACES)
598 {
600 }
601 } while (res == AMF_DECODER_NO_FREE_SURFACES);
602
603 buf->pVtbl->Release(buf);
604
605 if(res == AMF_DECODER_NO_FREE_SURFACES) {
606 // input is not consumed, need to QueryOutput and submit again
607 av_log(avctx,
AV_LOG_VERBOSE,
"SubmitInput() returned NO_FREE_SURFACES and came out of loop - should never happen\n");
608 res = AMF_OK;
609 } else if (res == AMF_RESOLUTION_CHANGED) {
610 //input is not consumed, start internal drain
611 ctx->decoder->pVtbl->Drain(
ctx->decoder);
613 // process resolution_changed when internal drain is complete
614 ctx->resolution_changed = 1;
615 res = AMF_OK;
616 } else if (res != AMF_OK && res != AMF_NEED_MORE_INPUT && res != AMF_REPEAT) {
619 }
620 }
621
623 if (res == AMF_OK)
624 got_frame = 1;
625 else if (res == AMF_REPEAT)
626 // decoder has no output yet
627 res = AMF_OK;
628 else if (res == AMF_EOF) {
629 // drain is complete
631 if(
ctx->resolution_changed){
632 // re-initialze decoder
633 AMFVariantStruct size_var = {0};
634 AMFVariantStruct format_var = {0};
635 res =
ctx->decoder->pVtbl->GetProperty(
ctx->decoder, AMF_VIDEO_DECODER_CURRENT_SIZE, &size_var);
636 if (res != AMF_OK) {
638 }
639
640 avctx->
width = size_var.sizeValue.width;
641 avctx->
height = size_var.sizeValue.height;
645 if (res != AMF_OK) {
648 }
650 if (res == AMF_OK) {
652 }
653
654 if (res < 0)
656 }else
658 } else {
660 }
661 return got_frame ? 0 :
AVERROR(EAGAIN);
662 }
663
665 {
667 ctx->decoder->pVtbl->Flush(
ctx->decoder);
668 }
669
670 #define OFFSET(x) offsetof(AMFDecoderContext, x)
671 #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
672
674 // Decoder mode
675 {
"decoder_mode",
"Decoder mode",
OFFSET(decoder_mode),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, AMF_VIDEO_DECODER_MODE_LOW_LATENCY,
VD,
"decoder_mode" },
676 {
"regular",
"DPB delay is based on number of reference frames + 1", 0,
AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_DECODER_MODE_REGULAR }, 0, 0,
VD,
"decoder_mode" },
677 {
"compliant",
"DPB delay is based on profile - up to 16", 0,
AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_DECODER_MODE_COMPLIANT }, 0, 0,
VD,
"decoder_mode" },
678 {
"low_latency",
"DPB delay is 0", 0,
AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_DECODER_MODE_LOW_LATENCY }, 0, 0,
VD,
"decoder_mode" },
679
680 // Timestamp mode
681 {
"timestamp_mode",
"Timestamp mode",
OFFSET(timestamp_mode),
AV_OPT_TYPE_INT, { .i64 = AMF_TS_SORT }, -1, AMF_TS_DECODE,
VD,
"timestamp_mode" },
682 {
"presentation",
"Preserve timestamps from input to output", 0,
AV_OPT_TYPE_CONST, { .i64 = AMF_TS_PRESENTATION }, 0, 0,
VD,
"timestamp_mode" },
683 {
"sort",
"Resort PTS list", 0,
AV_OPT_TYPE_CONST, { .i64 = AMF_TS_SORT }, 0, 0,
VD,
"timestamp_mode" },
684 {
"decode",
"Decode order", 0,
AV_OPT_TYPE_CONST, { .i64 = AMF_TS_DECODE }, 0, 0,
VD,
"timestamp_mode" },
685
686 // Reference frame management
687 {
"surface_pool_size",
"Number of surfaces in the decode pool",
OFFSET(surface_pool_size),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX,
VD,
NULL },
689
692 {
"skip_transfer_sav",
"Skip transfer on another GPU when SAV enabled",
OFFSET(skip_transfer_sav),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1,
VD,
NULL },
694
696 };
697
703 };
704
705 #define DEFINE_AMF_DECODER(x, X, bsf_name) \
706 const FFCodec ff_##x##_amf_decoder = { \
707 .p.name = #x "_amf", \
708 CODEC_LONG_NAME(#X " AMD AMF video decoder"), \
709 .priv_data_size = sizeof(AMFDecoderContext), \
710 .p.type = AVMEDIA_TYPE_VIDEO, \
711 .p.id = AV_CODEC_ID_##X, \
712 .init = amf_decode_init, \
713 FF_CODEC_RECEIVE_FRAME_CB(amf_decode_frame), \
714 .flush = amf_decode_flush, \
715 .close = amf_decode_close, \
716 .bsfs = bsf_name, \
717 .p.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \
718 .p.priv_class = &amf_decode_class, \
719 CODEC_PIXFMTS_ARRAY(amf_dec_pix_fmts), \
720 .hw_configs = amf_hw_configs, \
721 .p.wrapper_name = "amf", \
722 .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE, \
723 }; \
724