1 /*
2 * Intel MediaSDK QSV codec-independent code
3 *
4 * copyright (c) 2013 Luca Barbato
5 * copyright (c) 2015 Anton Khirnov <anton@khirnov.net>
6 *
7 * This file is part of FFmpeg.
8 *
9 * FFmpeg is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * FFmpeg is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with FFmpeg; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #include "config_components.h"
25
26 #include <stdint.h>
27 #include <string.h>
28 #include <sys/types.h>
29
30 #include <mfxvideo.h>
31
46
55
56 #if QSV_ONEVPL
57 #include <mfxdispatcher.h>
58 #else
59 #define MFXUnload(a) do { } while(0)
60 #endif
61
63
64 #define PTS_TO_MFX_PTS(pts, pts_tb) ((pts) == AV_NOPTS_VALUE ? \
65 MFX_TIMESTAMP_UNKNOWN : pts_tb.num ? \
66 av_rescale_q(pts, pts_tb, mfx_tb) : pts)
67
68 #define MFX_PTS_TO_PTS(mfx_pts, pts_tb) ((mfx_pts) == MFX_TIMESTAMP_UNKNOWN ? \
69 AV_NOPTS_VALUE : pts_tb.num ? \
70 av_rescale_q(mfx_pts, mfx_tb, pts_tb) : mfx_pts)
71
72 #define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
73
78
80 // the session used for decoding
84
85 // the session we allocated internally, in case the caller did not provide
86 // one
88
90
91 /**
92 * a linked list of frames currently being used by QSV
93 */
95
99
106
107 // options set by the caller
111
113
117
125 },
127 },
129 };
130
133 {
135
139
142
146 break;
151 break;
157 break;
160 break;
161 default:
164 }
165
169
177 }
178
182
183 return 0;
184 }
185
188 {
190 mfxIMPL impl;
191
192 if (q->
gpu_copy == MFX_GPUCOPY_ON &&
193 !(q->
iopattern & MFX_IOPATTERN_OUT_SYSTEM_MEMORY)) {
195 "only works in system memory mode.\n");
197 }
198 if (session) {
200 } else if (hw_frames_ref) {
204 }
206
210
214 q->
iopattern == MFX_IOPATTERN_OUT_OPAQUE_MEMORY,
215 #else
216 0,
217 #endif
222 }
223
225 } else if (hw_device_ref) {
229 }
230
235
237 } else {
243 }
244
246 }
247
248 if (MFXQueryIMPL(q->
session, &impl) == MFX_ERR_NONE) {
250 case MFX_IMPL_VIA_VAAPI:
252 break;
253
254 case MFX_IMPL_VIA_D3D11:
256 break;
257
258 case MFX_IMPL_VIA_D3D9:
260 break;
261
262 default:
264 }
265 } else {
268 }
269
270 if (MFXQueryVersion(q->
session, &q->
ver) != MFX_ERR_NONE) {
273 }
274
275 /* make sure the decoder is uninitialized */
276 MFXVideoDECODE_Close(q->
session);
277
278 return 0;
279
282
286 }
287
291 }
292
294 }
295
297 {
298 mfxSession session =
NULL;
299 int iopattern = 0;
302 AV_PIX_FMT_QSV,
/* opaque format in case of video memory output */
303 pix_fmt,
/* system memory format obtained from bitstream parser */
305
310 }
311
316 }
317
324 }
325
329
331
335 }
336
338 frames_hwctx = hwframes_ctx->
hwctx;
345 else
347 frames_hwctx->
frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
348
350
355 }
356 }
357
361
363 #if QSV_HAVE_OPAQUE
364 if (frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME)
365 iopattern = MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
366 else if (frames_hwctx->frame_type & MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET)
367 iopattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY;
368 #else
369 if (frames_hwctx->frame_type & MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET)
370 iopattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY;
371 #endif
372 }
373 }
374
375 if (!iopattern)
376 iopattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
378
380
385 }
386
391
392 return 0;
393 }
394
396 {
398
399 avctx->
width = param->mfx.FrameInfo.CropW;
400 avctx->
height = param->mfx.FrameInfo.CropH;
403 avctx->
level = param->mfx.CodecLevel;
404 avctx->
profile = param->mfx.CodecProfile;
407
411 "Error initializing the MFX video decoder");
412
414
420 }
421 return 0;
422 }
423
426 mfxVideoParam *param)
427 {
429 mfxExtVideoSignalInfo video_signal_info = { 0 };
430 mfxExtBuffer *header_ext_params[1] = { (mfxExtBuffer *)&video_signal_info };
431 mfxBitstream bs = { 0 };
432
434 bs.Data = avpkt->
data;
435 bs.DataLength = avpkt->
size;
436 bs.MaxLength = bs.DataLength;
439 bs.DataFlag |= MFX_BITSTREAM_COMPLETE_FRAME;
440 } else
442
443
448 }
449
453
454 param->mfx.CodecId =
ret;
455 video_signal_info.Header.BufferId = MFX_EXTBUFF_VIDEO_SIGNAL_INFO;
456 video_signal_info.Header.BufferSz = sizeof(video_signal_info);
457 // The SDK doesn't support other ext buffers when calling MFXVideoDECODE_DecodeHeader,
458 // so do not append this buffer to the existent buffer array
459 param->ExtParam = header_ext_params;
460 param->NumExtParam = 1;
461 ret = MFXVideoDECODE_DecodeHeader(q->
session, &bs, param);
462 if (MFX_ERR_MORE_DATA ==
ret) {
464 }
467 "Error decoding stream header");
468
470
471 if (video_signal_info.ColourDescriptionPresent) {
473 avctx->
color_trc = video_signal_info.TransferCharacteristics;
474 avctx->
colorspace = video_signal_info.MatrixCoefficients;
475 }
476
479
480 if (param->mfx.FrameInfo.FrameRateExtN == 0 || param->mfx.FrameInfo.FrameRateExtD == 0) {
481 param->mfx.FrameInfo.FrameRateExtN = 25;
482 param->mfx.FrameInfo.FrameRateExtD = 1;
483 }
484
485 #if QSV_VERSION_ATLEAST(1, 34)
488 #endif
489
490 return 0;
491 }
492
494 {
496
499 else
501
504
506 frame->surface = *(mfxFrameSurface1*)
frame->frame->data[3];
507 } else {
512 }
513 }
514
516
521
523 }
524
525 frame->surface.Data.ExtParam =
frame->ext_param;
526 frame->surface.Data.NumExtParam = 0;
527 frame->num_ext_params = 0;
528 frame->dec_info.Header.BufferId = MFX_EXTBUFF_DECODED_FRAME_INFO;
529 frame->dec_info.Header.BufferSz =
sizeof(
frame->dec_info);
531 #if QSV_VERSION_ATLEAST(1, 34)
533 frame->av1_film_grain_param.Header.BufferId = MFX_EXTBUFF_AV1_FILM_GRAIN_PARAM;
534 frame->av1_film_grain_param.Header.BufferSz =
sizeof(
frame->av1_film_grain_param);
535 frame->av1_film_grain_param.FilmGrainFlags = 0;
537 }
538 #endif
539
540 #if QSV_VERSION_ATLEAST(1, 35)
543 frame->mdcv.Header.BufferId = MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME;
544 frame->mdcv.Header.BufferSz =
sizeof(
frame->mdcv);
545 // The data in mdcv is valid when this flag is 1
546 frame->mdcv.InsertPayloadToggle = 0;
548
549 frame->clli.Header.BufferId = MFX_EXTBUFF_CONTENT_LIGHT_LEVEL_INFO;
550 frame->clli.Header.BufferSz =
sizeof(
frame->clli);
551 // The data in clli is valid when this flag is 1
552 frame->clli.InsertPayloadToggle = 0;
554 }
555 #endif
556
558
559 return 0;
560 }
561
563 {
565 while (cur) {
569 }
571 }
572 }
573
575 {
578
580
588 *surf = &
frame->surface;
589 return 0;
590 }
591
594 }
595
603 }
605
609
610 *surf = &
frame->surface;
611
612 return 0;
613 }
614
616 {
618 while (cur) {
620 return cur;
622 }
624 }
625
626 #if QSV_VERSION_ATLEAST(1, 34)
628 {
632
633 if (!(ext_param->FilmGrainFlags & MFX_FILM_GRAIN_APPLY))
634 return 0;
635
637
638 if (!fgp)
640
642 fgp->
seed = ext_param->GrainSeed;
644
650 aom->
overlap_flag = !!(ext_param->FilmGrainFlags & MFX_FILM_GRAIN_OVERLAP);
651 aom->
limit_output_range = !!(ext_param->FilmGrainFlags & MFX_FILM_GRAIN_CLIP_TO_RESTRICTED_RANGE);
652
654
656 aom->
y_points[
i][0] = ext_param->PointY[
i].Value;
657 aom->
y_points[
i][1] = ext_param->PointY[
i].Scaling;
658 }
659
661
663 aom->
uv_points[0][
i][0] = ext_param->PointCb[
i].Value;
664 aom->
uv_points[0][
i][1] = ext_param->PointCb[
i].Scaling;
665 }
666
668
670 aom->
uv_points[1][
i][0] = ext_param->PointCr[
i].Value;
671 aom->
uv_points[1][
i][1] = ext_param->PointCr[
i].Scaling;
672 }
673
674 for (
i = 0;
i < 24;
i++)
676
677 for (
i = 0;
i < 25;
i++) {
680 }
681
682 aom->
uv_mult[0] = ext_param->CbMult;
683 aom->
uv_mult[1] = ext_param->CrMult;
688
689 return 0;
690 }
691 #endif
692
693 #if QSV_VERSION_ATLEAST(1, 35)
694 static int qsv_export_hdr_side_data(
AVCodecContext *avctx, mfxExtMasteringDisplayColourVolume *mdcv,
696 {
698
699 // The SDK re-uses this flag for HDR SEI parsing
700 if (mdcv->InsertPayloadToggle) {
702 const int mapping[3] = {2, 0, 1};
703 const int chroma_den = 50000;
704 const int luma_den = 10000;
706
710
711 if (mastering) {
712 for (
i = 0;
i < 3;
i++) {
713 const int j = mapping[
i];
716 }
717
720
723
726 }
727 }
728
729 // The SDK re-uses this flag for HDR SEI parsing
730 if (clli->InsertPayloadToggle) {
732
736
737 if (light) {
738 light->
MaxCLL = clli->MaxContentLightLevel;
739 light->
MaxFALL = clli->MaxPicAverageLightLevel;
740 }
741 }
742
743 return 0;
744 }
745
746 static int qsv_export_hdr_side_data_av1(
AVCodecContext *avctx, mfxExtMasteringDisplayColourVolume *mdcv,
748 {
749 if (mdcv->InsertPayloadToggle) {
751 const int chroma_den = 1 << 16;
752 const int max_luma_den = 1 << 8;
753 const int min_luma_den = 1 << 14;
754
755 if (!mastering)
757
758 for (
int i = 0;
i < 3;
i++) {
761 }
762
765
768
771 }
772
773 if (clli->InsertPayloadToggle) {
775 if (!light)
777
778 light->
MaxCLL = clli->MaxContentLightLevel;
779 light->
MaxFALL = clli->MaxPicAverageLightLevel;
780 }
781
782 return 0;
783 }
784
785 #endif
786
790 {
791 mfxFrameSurface1 *insurf;
792 mfxFrameSurface1 *outsurf;
793 mfxSyncPoint *sync;
794 mfxBitstream bs = { { { 0 } } };
796
798 bs.Data = avpkt->
data;
799 bs.DataLength = avpkt->
size;
800 bs.MaxLength = bs.DataLength;
803 bs.DataFlag |= MFX_BITSTREAM_COMPLETE_FRAME;
804 }
805
807 if (!sync) {
810 }
811
812 do {
817 }
818
820 insurf, &outsurf, sync);
821 if (
ret == MFX_WRN_DEVICE_BUSY)
823
824 }
while (
ret == MFX_WRN_DEVICE_BUSY ||
ret == MFX_ERR_MORE_SURFACE);
825
826 if (
ret == MFX_ERR_INCOMPATIBLE_VIDEO_PARAM) {
830 return 0;
831 }
832
833 if (
ret != MFX_ERR_NONE &&
834 ret != MFX_ERR_MORE_DATA &&
835 ret != MFX_WRN_VIDEO_PARAM_CHANGED &&
836 ret != MFX_ERR_MORE_SURFACE) {
839 "Error during QSV decoding.");
840 }
841
842 /* make sure we do not enter an infinite loop if the SDK
843 * did not consume any data and did not return anything */
844 if (!*sync && !bs.DataOffset) {
845 bs.DataOffset = avpkt->
size;
849 ret != MFX_ERR_MORE_DATA))
851 } else {
853 }
854
855 if (*sync) {
858
859 if (!out_frame) {
861 "The returned surface does not correspond to any frame\n");
864 }
865
867
870 } else {
872 }
873
878
881
883 do {
885 }
while (
ret == MFX_WRN_IN_EXECUTION);
886 }
887
889
891
895
897
899 #if QSV_VERSION_ATLEAST(1, 34)
903 ret = qsv_export_film_grain(avctx, &aframe.
frame->av1_film_grain_param,
frame);
904
907 }
908 #endif
909
910 #if QSV_VERSION_ATLEAST(1, 35)
912 ret = qsv_export_hdr_side_data(avctx, &aframe.
frame->mdcv, &aframe.
frame->clli,
frame);
913
916 }
917
919 ret = qsv_export_hdr_side_data_av1(avctx, &aframe.
frame->mdcv, &aframe.
frame->clli,
frame);
922 }
923 #endif
924
926 outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_TRIPLING ? 4 :
927 outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_DOUBLING ? 2 :
928 outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_REPEATED ? 1 : 0;
930 !!(outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF);
932 !(outsurf->Info.PicStruct & MFX_PICSTRUCT_PROGRESSIVE);
934
940 else
942 } else {
945 else
947 }
948 frame->crop_left = outsurf->Info.CropX;
949 frame->crop_top = outsurf->Info.CropY;
950 frame->crop_right = outsurf->Info.Width - (outsurf->Info.CropX + outsurf->Info.CropW);
951 frame->crop_bottom = outsurf->Info.Height - (outsurf->Info.CropY + outsurf->Info.CropH);
952
953 /* update the surface properties */
955 ((mfxFrameSurface1*)
frame->data[3])->Info = outsurf->Info;
956
957 *got_frame = 1;
958 }
959
960 return bs.DataOffset;
961 }
962
964 {
966
968 MFXVideoDECODE_Close(q->
session);
969
975 }
976
977 while (cur) {
982 }
983
985
989 }
990
993 {
995 mfxVideoParam param = { 0 };
997
1000
1001 /* TODO: flush delayed frames on reinit */
1002
1003 // sw_pix_fmt, coded_width/height should be set for ff_get_format(),
1004 // assume sw_pix_fmt is NV12 and coded_width/height to be 1280x720,
1005 // the assumption may be not corret but will be updated after header decoded if not true.
1012
1013 /* decode zero-size pkt to flush the buffered pkt before reinit */
1017 if (
ret < 0 || *got_frame)
1019 }
1020
1022 mfxFrameAllocRequest request;
1023 memset(&request, 0, sizeof(request));
1024
1030 else
1032 goto reinit_fail;
1033 }
1035
1037
1040
1041 ret = MFXVideoDECODE_QueryIOSurf(q->
session, ¶m, &request);
1044
1046
1049 goto reinit_fail;
1051 }
1052
1056 goto reinit_fail;
1058 }
1059
1061
1062 reinit_fail:
1065 }
1066
1071 };
1072
1076
1078
1080
1083
1085 {
1089
1091 }
1092
1094 {
1096
1098
1100
1102
1103 return 0;
1104 }
1105
1107 {
1111
1113 uid =
"f622394d8d87452f878c51f2fc9b4131";
1115 uid =
"a922394d8d87452f878c51f2fc9b4131";
1116 }
1118 static const char * const uid_hevcdec_sw = "15dd936825ad475ea34e35f3f54217a6";
1119 static const char * const uid_hevcdec_hw = "33a61c0b4c27454ca8d85dde757c6f8e";
1120
1121 if (
s->qsv.load_plugins[0]) {
1123 "load_plugins is not empty, but load_plugin is not set to 'none'."
1124 "The load_plugin value will be ignored.\n");
1125 } else {
1127 uid = uid_hevcdec_sw;
1128 else
1129 uid = uid_hevcdec_hw;
1130 }
1131 }
1135 if (!
s->qsv.load_plugins)
1137 }
1138
1142 if (!
s->packet_fifo) {
1145 }
1146
1149
1150 return 0;
1154 }
1155
1158 {
1161
1162 /* buffer the input packet */
1165
1170 }
1171
1172 /* process buffered data */
1173 while (!*got_frame) {
1174 /* prepare the input data */
1175 if (
s->buffer_pkt.size <= 0) {
1176 /* no more data */
1179 /* in progress of reinit, no read from fifo and keep the buffer_pkt */
1180 if (!
s->qsv.reinit_flag) {
1183 }
1184 }
1185
1190
1191 /* Drop buffer_pkt when failed to decode the packet. Otherwise,
1192 the decoder will keep decoding the failure packet. */
1195 }
1196 if (
s->qsv.reinit_flag)
1197 continue;
1198
1199 s->buffer_pkt.size -=
ret;
1200 s->buffer_pkt.data +=
ret;
1201 }
1202
1204 }
1205
1207 {
1209
1211
1213 s->qsv.initialized = 0;
1214 }
1215
1216 #define OFFSET(x) offsetof(QSVDecContext, x)
1217 #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
1218
1219 #define DEFINE_QSV_DECODER_WITH_OPTION(x, X, bsf_name, opt) \
1220 static const AVClass x##_qsv_class = { \
1221 .class_name = #x "_qsv", \
1222 .item_name = av_default_item_name, \
1223 .option = opt, \
1224 .version = LIBAVUTIL_VERSION_INT, \
1225 }; \
1226 const FFCodec ff_##x##_qsv_decoder = { \
1227 .p.name = #x "_qsv", \
1228 CODEC_LONG_NAME(#X " video (Intel Quick Sync Video acceleration)"), \
1229 .priv_data_size = sizeof(QSVDecContext), \
1230 .p.type = AVMEDIA_TYPE_VIDEO, \
1231 .p.id = AV_CODEC_ID_##X, \
1232 .init = qsv_decode_init, \
1233 FF_CODEC_DECODE_CB(qsv_decode_frame), \
1234 .flush = qsv_decode_flush, \
1235 .close = qsv_decode_close, \
1236 .bsfs = bsf_name, \
1237 .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HYBRID, \
1238 .p.priv_class = &x##_qsv_class, \
1239 .hw_configs = qsv_hw_configs, \
1240 .p.wrapper_name = "qsv", \
1241 .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_EXPORTS_CROPPING, \
1242 }; \
1243
1244 #define DEFINE_QSV_DECODER(x, X, bsf_name) DEFINE_QSV_DECODER_WITH_OPTION(x, X, bsf_name, options)
1245
1246 #if CONFIG_HEVC_QSV_DECODER
1249
1254
1255 { "load_plugins", "A :-separate list of hexadecimal plugin UIDs to load in an internal session",
1257
1258 {
"gpu_copy",
"A GPU-accelerated copy between video and system memory",
OFFSET(qsv.gpu_copy),
AV_OPT_TYPE_INT, { .i64 = MFX_GPUCOPY_DEFAULT }, MFX_GPUCOPY_DEFAULT, MFX_GPUCOPY_OFF,
VD, .unit =
"gpu_copy"},
1263 };
1265 #endif
1266
1269
1270 {
"gpu_copy",
"A GPU-accelerated copy between video and system memory",
OFFSET(qsv.gpu_copy),
AV_OPT_TYPE_INT, { .i64 = MFX_GPUCOPY_DEFAULT }, MFX_GPUCOPY_DEFAULT, MFX_GPUCOPY_OFF,
VD, .unit =
"gpu_copy"},
1275 };
1276
1277 #if CONFIG_H264_QSV_DECODER
1279 #endif
1280
1281 #if CONFIG_MPEG2_QSV_DECODER
1283 #endif
1284
1285 #if CONFIG_VC1_QSV_DECODER
1287 #endif
1288
1289 #if CONFIG_MJPEG_QSV_DECODER
1291 #endif
1292
1293 #if CONFIG_VP8_QSV_DECODER
1295 #endif
1296
1297 #if CONFIG_VP9_QSV_DECODER
1299 #endif
1300
1301 #if CONFIG_AV1_QSV_DECODER
1303 #endif
1304
1305 #if CONFIG_VVC_QSV_DECODER
1307 #endif