2 * Intel MediaSDK QSV encoder utility functions
4 * copyright (c) 2013 Yukinori Yamazoe
5 * copyright (c) 2015 Anton Khirnov
7 * This file is part of Libav.
9 * Libav 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.
14 * Libav 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.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with Libav; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <sys/types.h>
26 #include <mfx/mfxvideo.h>
28 #include "libavutil/common.h"
29 #include "libavutil/mem.h"
30 #include "libavutil/log.h"
31 #include "libavutil/time.h"
32 #include "libavutil/imgutils.h"
37 #include "qsv_internal.h"
40 static int init_video_param(AVCodecContext
*avctx
, QSVEncContext
*q
)
42 const char *ratecontrol_desc
;
47 ret
= ff_qsv_codec_id_to_mfx(avctx
->codec_id
);
50 q
->param
.mfx
.CodecId
= ret
;
52 q
->width_align
= avctx
->codec_id
== AV_CODEC_ID_HEVC ?
32 : 16;
55 q
->param
.mfx
.CodecLevel
= avctx
->level
;
57 q
->param
.mfx
.CodecProfile
= q
->profile
;
58 q
->param
.mfx
.TargetUsage
= q
->preset
;
59 q
->param
.mfx
.GopPicSize
= FFMAX(0, avctx
->gop_size
);
60 q
->param
.mfx
.GopRefDist
= FFMAX(-1, avctx
->max_b_frames
) + 1;
61 q
->param
.mfx
.GopOptFlag
= avctx
->flags
& AV_CODEC_FLAG_CLOSED_GOP ?
63 q
->param
.mfx
.IdrInterval
= q
->idr_interval
;
64 q
->param
.mfx
.NumSlice
= avctx
->slices
;
65 q
->param
.mfx
.NumRefFrame
= FFMAX(0, avctx
->refs
);
66 q
->param
.mfx
.EncodedOrder
= 0;
67 q
->param
.mfx
.BufferSizeInKB
= 0;
69 q
->param
.mfx
.FrameInfo
.FourCC
= MFX_FOURCC_NV12
;
70 q
->param
.mfx
.FrameInfo
.Width
= FFALIGN(avctx
->width
, q
->width_align
);
71 q
->param
.mfx
.FrameInfo
.Height
= FFALIGN(avctx
->height
, 32);
72 q
->param
.mfx
.FrameInfo
.CropX
= 0;
73 q
->param
.mfx
.FrameInfo
.CropY
= 0;
74 q
->param
.mfx
.FrameInfo
.CropW
= avctx
->width
;
75 q
->param
.mfx
.FrameInfo
.CropH
= avctx
->height
;
76 q
->param
.mfx
.FrameInfo
.AspectRatioW
= avctx
->sample_aspect_ratio
.num
;
77 q
->param
.mfx
.FrameInfo
.AspectRatioH
= avctx
->sample_aspect_ratio
.den
;
78 q
->param
.mfx
.FrameInfo
.PicStruct
= MFX_PICSTRUCT_PROGRESSIVE
;
79 q
->param
.mfx
.FrameInfo
.ChromaFormat
= MFX_CHROMAFORMAT_YUV420
;
80 q
->param
.mfx
.FrameInfo
.BitDepthLuma
= 8;
81 q
->param
.mfx
.FrameInfo
.BitDepthChroma
= 8;
83 if (avctx
->framerate
.den
> 0 && avctx
->framerate
.num
> 0) {
84 q
->param
.mfx
.FrameInfo
.FrameRateExtN
= avctx
->framerate
.num
;
85 q
->param
.mfx
.FrameInfo
.FrameRateExtD
= avctx
->framerate
.den
;
87 q
->param
.mfx
.FrameInfo
.FrameRateExtN
= avctx
->time_base
.den
;
88 q
->param
.mfx
.FrameInfo
.FrameRateExtD
= avctx
->time_base
.num
;
91 if (avctx
->flags
& AV_CODEC_FLAG_QSCALE
) {
92 q
->param
.mfx
.RateControlMethod
= MFX_RATECONTROL_CQP
;
93 ratecontrol_desc
= "constant quantization parameter (CQP)";
94 } else if (avctx
->rc_max_rate
== avctx
->bit_rate
) {
95 q
->param
.mfx
.RateControlMethod
= MFX_RATECONTROL_CBR
;
96 ratecontrol_desc
= "constant bitrate (CBR)";
97 } else if (!avctx
->rc_max_rate
) {
98 q
->param
.mfx
.RateControlMethod
= MFX_RATECONTROL_AVBR
;
99 ratecontrol_desc
= "average variable bitrate (AVBR)";
101 q
->param
.mfx
.RateControlMethod
= MFX_RATECONTROL_VBR
;
102 ratecontrol_desc
= "variable bitrate (VBR)";
105 av_log(avctx
, AV_LOG_VERBOSE
, "Using the %s ratecontrol method\n", ratecontrol_desc
);
107 switch (q
->param
.mfx
.RateControlMethod
) {
108 case MFX_RATECONTROL_CBR
:
109 case MFX_RATECONTROL_VBR
:
110 q
->param
.mfx
.InitialDelayInKB
= avctx
->rc_initial_buffer_occupancy
/ 1000;
111 q
->param
.mfx
.TargetKbps
= avctx
->bit_rate
/ 1000;
112 q
->param
.mfx
.MaxKbps
= avctx
->bit_rate
/ 1000;
114 case MFX_RATECONTROL_CQP
:
115 quant
= avctx
->global_quality
/ FF_QP2LAMBDA
;
117 q
->param
.mfx
.QPI
= av_clip(quant
* fabs(avctx
->i_quant_factor
) + avctx
->i_quant_offset
, 0, 51);
118 q
->param
.mfx
.QPP
= av_clip(quant
, 0, 51);
119 q
->param
.mfx
.QPB
= av_clip(quant
* fabs(avctx
->b_quant_factor
) + avctx
->b_quant_offset
, 0, 51);
122 case MFX_RATECONTROL_AVBR
:
123 q
->param
.mfx
.TargetKbps
= avctx
->bit_rate
/ 1000;
124 q
->param
.mfx
.Convergence
= q
->avbr_convergence
;
125 q
->param
.mfx
.Accuracy
= q
->avbr_accuracy
;
129 // the HEVC encoder plugin currently fails if coding options
131 if (avctx
->codec_id
!= AV_CODEC_ID_HEVC
) {
132 q
->extco
.Header
.BufferId
= MFX_EXTBUFF_CODING_OPTION
;
133 q
->extco
.Header
.BufferSz
= sizeof(q
->extco
);
134 q
->extco
.CAVLC
= avctx
->coder_type
== FF_CODER_TYPE_VLC ?
135 MFX_CODINGOPTION_ON
: MFX_CODINGOPTION_UNKNOWN
;
137 q
->extparam
[0] = (mfxExtBuffer
*)&q
->extco
;
139 q
->param
.ExtParam
= q
->extparam
;
140 q
->param
.NumExtParam
= FF_ARRAY_ELEMS(q
->extparam
);
146 static int qsv_retrieve_enc_params(AVCodecContext
*avctx
, QSVEncContext
*q
)
148 uint8_t sps_buf
[128];
149 uint8_t pps_buf
[128];
151 mfxExtCodingOptionSPSPPS extradata
= {
152 .Header
.BufferId
= MFX_EXTBUFF_CODING_OPTION_SPSPPS
,
153 .Header
.BufferSz
= sizeof(extradata
),
154 .SPSBuffer
= sps_buf
, .SPSBufSize
= sizeof(sps_buf
),
155 .PPSBuffer
= pps_buf
, .PPSBufSize
= sizeof(pps_buf
)
158 mfxExtBuffer
*ext_buffers
[] = {
159 (mfxExtBuffer
*)&extradata
,
162 int need_pps
= avctx
->codec_id
!= AV_CODEC_ID_MPEG2VIDEO
;
165 q
->param
.ExtParam
= ext_buffers
;
166 q
->param
.NumExtParam
= FF_ARRAY_ELEMS(ext_buffers
);
168 ret
= MFXVideoENCODE_GetVideoParam(q
->session
, &q
->param
);
170 return ff_qsv_error(ret
);
172 q
->packet_size
= q
->param
.mfx
.BufferSizeInKB
* 1000;
174 if (!extradata
.SPSBufSize
|| (need_pps
&& !extradata
.PPSBufSize
)) {
175 av_log(avctx
, AV_LOG_ERROR
, "No extradata returned from libmfx.\n");
176 return AVERROR_UNKNOWN
;
179 avctx
->extradata
= av_malloc(extradata
.SPSBufSize
+ need_pps
* extradata
.PPSBufSize
+
180 AV_INPUT_BUFFER_PADDING_SIZE
);
181 if (!avctx
->extradata
)
182 return AVERROR(ENOMEM
);
184 memcpy(avctx
->extradata
, sps_buf
, extradata
.SPSBufSize
);
186 memcpy(avctx
->extradata
+ extradata
.SPSBufSize
, pps_buf
, extradata
.PPSBufSize
);
187 avctx
->extradata_size
= extradata
.SPSBufSize
+ need_pps
* extradata
.PPSBufSize
;
188 memset(avctx
->extradata
+ avctx
->extradata_size
, 0, AV_INPUT_BUFFER_PADDING_SIZE
);
193 int ff_qsv_enc_init(AVCodecContext
*avctx
, QSVEncContext
*q
)
197 q
->param
.IOPattern
= MFX_IOPATTERN_IN_SYSTEM_MEMORY
;
198 q
->param
.AsyncDepth
= q
->async_depth
;
200 q
->async_fifo
= av_fifo_alloc((1 + q
->async_depth
) *
201 (sizeof(AVPacket
) + sizeof(mfxSyncPoint
) + sizeof(mfxBitstream
*)));
203 return AVERROR(ENOMEM
);
205 if (avctx
->hwaccel_context
) {
206 AVQSVContext
*qsv
= avctx
->hwaccel_context
;
208 q
->session
= qsv
->session
;
209 q
->param
.IOPattern
= qsv
->iopattern
;
213 ret
= ff_qsv_init_internal_session(avctx
, &q
->internal_session
,
218 q
->session
= q
->internal_session
;
221 ret
= init_video_param(avctx
, q
);
225 ret
= MFXVideoENCODE_QueryIOSurf(q
->session
, &q
->param
, &q
->req
);
227 av_log(avctx
, AV_LOG_ERROR
, "Error querying the encoding parameters\n");
228 return ff_qsv_error(ret
);
231 ret
= MFXVideoENCODE_Init(q
->session
, &q
->param
);
233 av_log(avctx
, AV_LOG_ERROR
, "Error initializing the encoder\n");
234 return ff_qsv_error(ret
);
237 ret
= qsv_retrieve_enc_params(avctx
, q
);
239 av_log(avctx
, AV_LOG_ERROR
, "Error retrieving encoding parameters.\n");
248 static void clear_unused_frames(QSVEncContext
*q
)
250 QSVFrame
*cur
= q
->work_frames
;
252 if (cur
->surface
&& !cur
->surface
->Data
.Locked
) {
254 av_frame_unref(cur
->frame
);
260 static int get_free_frame(QSVEncContext
*q
, QSVFrame
**f
)
262 QSVFrame
*frame
, **last
;
264 clear_unused_frames(q
);
266 frame
= q
->work_frames
;
267 last
= &q
->work_frames
;
269 if (!frame
->surface
) {
278 frame
= av_mallocz(sizeof(*frame
));
280 return AVERROR(ENOMEM
);
281 frame
->frame
= av_frame_alloc();
284 return AVERROR(ENOMEM
);
293 static int submit_frame(QSVEncContext
*q
, const AVFrame
*frame
,
294 mfxFrameSurface1
**surface
)
299 ret
= get_free_frame(q
, &qf
);
303 if (frame
->format
== AV_PIX_FMT_QSV
) {
304 ret
= av_frame_ref(qf
->frame
, frame
);
308 qf
->surface
= (mfxFrameSurface1
*)qf
->frame
->data
[3];
309 *surface
= qf
->surface
;
313 /* make a copy if the input is not padded as libmfx requires */
314 if (frame
->height
& 31 || frame
->linesize
[0] & (q
->width_align
- 1)) {
315 qf
->frame
->height
= FFALIGN(frame
->height
, 32);
316 qf
->frame
->width
= FFALIGN(frame
->width
, q
->width_align
);
318 ret
= ff_get_buffer(q
->avctx
, qf
->frame
, AV_GET_BUFFER_FLAG_REF
);
322 qf
->frame
->height
= frame
->height
;
323 qf
->frame
->width
= frame
->width
;
324 ret
= av_frame_copy(qf
->frame
, frame
);
326 av_frame_unref(qf
->frame
);
330 ret
= av_frame_ref(qf
->frame
, frame
);
335 qf
->surface_internal
.Info
= q
->param
.mfx
.FrameInfo
;
337 qf
->surface_internal
.Info
.PicStruct
=
338 !frame
->interlaced_frame ? MFX_PICSTRUCT_PROGRESSIVE
:
339 frame
->top_field_first ? MFX_PICSTRUCT_FIELD_TFF
:
340 MFX_PICSTRUCT_FIELD_BFF
;
341 if (frame
->repeat_pict
== 1)
342 qf
->surface_internal
.Info
.PicStruct
|= MFX_PICSTRUCT_FIELD_REPEATED
;
343 else if (frame
->repeat_pict
== 2)
344 qf
->surface_internal
.Info
.PicStruct
|= MFX_PICSTRUCT_FRAME_DOUBLING
;
345 else if (frame
->repeat_pict
== 4)
346 qf
->surface_internal
.Info
.PicStruct
|= MFX_PICSTRUCT_FRAME_TRIPLING
;
348 qf
->surface_internal
.Data
.PitchLow
= qf
->frame
->linesize
[0];
349 qf
->surface_internal
.Data
.Y
= qf
->frame
->data
[0];
350 qf
->surface_internal
.Data
.UV
= qf
->frame
->data
[1];
351 qf
->surface_internal
.Data
.TimeStamp
= av_rescale_q(frame
->pts
, q
->avctx
->time_base
, (AVRational
){1, 90000});
353 qf
->surface
= &qf
->surface_internal
;
355 *surface
= qf
->surface
;
360 static void print_interlace_msg(AVCodecContext
*avctx
, QSVEncContext
*q
)
362 if (q
->param
.mfx
.CodecId
== MFX_CODEC_AVC
) {
363 if (q
->param
.mfx
.CodecProfile
== MFX_PROFILE_AVC_BASELINE
||
364 q
->param
.mfx
.CodecLevel
< MFX_LEVEL_AVC_21
||
365 q
->param
.mfx
.CodecLevel
> MFX_LEVEL_AVC_41
)
366 av_log(avctx
, AV_LOG_WARNING
,
367 "Interlaced coding is supported"
368 " at Main/High Profile Level 2.1-4.1\n");
372 int ff_qsv_encode(AVCodecContext
*avctx
, QSVEncContext
*q
,
373 AVPacket
*pkt
, const AVFrame
*frame
, int *got_packet
)
375 AVPacket new_pkt
= { 0 };
378 mfxFrameSurface1
*surf
= NULL
;
379 mfxSyncPoint sync
= NULL
;
383 ret
= submit_frame(q
, frame
, &surf
);
385 av_log(avctx
, AV_LOG_ERROR
, "Error submitting the frame for encoding.\n");
390 ret
= av_new_packet(&new_pkt
, q
->packet_size
);
392 av_log(avctx
, AV_LOG_ERROR
, "Error allocating the output packet\n");
396 bs
= av_mallocz(sizeof(*bs
));
398 av_packet_unref(&new_pkt
);
399 return AVERROR(ENOMEM
);
401 bs
->Data
= new_pkt
.data
;
402 bs
->MaxLength
= new_pkt
.size
;
405 ret
= MFXVideoENCODE_EncodeFrameAsync(q
->session
, NULL
, surf
, bs
, &sync
);
406 if (ret
== MFX_WRN_DEVICE_BUSY
)
411 av_packet_unref(&new_pkt
);
413 return (ret
== MFX_ERR_MORE_DATA
) ?
0 : ff_qsv_error(ret
);
416 if (ret
== MFX_WRN_INCOMPATIBLE_VIDEO_PARAM
&& frame
->interlaced_frame
)
417 print_interlace_msg(avctx
, q
);
420 av_fifo_generic_write(q
->async_fifo
, &new_pkt
, sizeof(new_pkt
), NULL
);
421 av_fifo_generic_write(q
->async_fifo
, &sync
, sizeof(sync
), NULL
);
422 av_fifo_generic_write(q
->async_fifo
, &bs
, sizeof(bs
), NULL
);
424 av_packet_unref(&new_pkt
);
428 if (!av_fifo_space(q
->async_fifo
) ||
429 (!frame
&& av_fifo_size(q
->async_fifo
))) {
430 av_fifo_generic_read(q
->async_fifo
, &new_pkt
, sizeof(new_pkt
), NULL
);
431 av_fifo_generic_read(q
->async_fifo
, &sync
, sizeof(sync
), NULL
);
432 av_fifo_generic_read(q
->async_fifo
, &bs
, sizeof(bs
), NULL
);
434 MFXVideoCORE_SyncOperation(q
->session
, sync
, 60000);
436 new_pkt
.dts
= av_rescale_q(bs
->DecodeTimeStamp
, (AVRational
){1, 90000}, avctx
->time_base
);
437 new_pkt
.pts
= av_rescale_q(bs
->TimeStamp
, (AVRational
){1, 90000}, avctx
->time_base
);
438 new_pkt
.size
= bs
->DataLength
;
440 if (bs
->FrameType
& MFX_FRAMETYPE_IDR
||
441 bs
->FrameType
& MFX_FRAMETYPE_xIDR
)
442 new_pkt
.flags
|= AV_PKT_FLAG_KEY
;
444 #if FF_API_CODED_FRAME
445 FF_DISABLE_DEPRECATION_WARNINGS
446 if (bs
->FrameType
& MFX_FRAMETYPE_I
|| bs
->FrameType
& MFX_FRAMETYPE_xI
)
447 avctx
->coded_frame
->pict_type
= AV_PICTURE_TYPE_I
;
448 else if (bs
->FrameType
& MFX_FRAMETYPE_P
|| bs
->FrameType
& MFX_FRAMETYPE_xP
)
449 avctx
->coded_frame
->pict_type
= AV_PICTURE_TYPE_P
;
450 else if (bs
->FrameType
& MFX_FRAMETYPE_B
|| bs
->FrameType
& MFX_FRAMETYPE_xB
)
451 avctx
->coded_frame
->pict_type
= AV_PICTURE_TYPE_B
;
452 FF_ENABLE_DEPRECATION_WARNINGS
458 if (pkt
->size
< new_pkt
.size
) {
459 av_log(avctx
, AV_LOG_ERROR
, "Submitted buffer not large enough: %d < %d\n",
460 pkt
->size
, new_pkt
.size
);
461 av_packet_unref(&new_pkt
);
462 return AVERROR(EINVAL
);
465 memcpy(pkt
->data
, new_pkt
.data
, new_pkt
.size
);
466 pkt
->size
= new_pkt
.size
;
468 ret
= av_packet_copy_props(pkt
, &new_pkt
);
469 av_packet_unref(&new_pkt
);
481 int ff_qsv_enc_close(AVCodecContext
*avctx
, QSVEncContext
*q
)
485 MFXVideoENCODE_Close(q
->session
);
486 if (q
->internal_session
)
487 MFXClose(q
->internal_session
);
489 q
->internal_session
= NULL
;
491 cur
= q
->work_frames
;
493 q
->work_frames
= cur
->next
;
494 av_frame_free(&cur
->frame
);
496 cur
= q
->work_frames
;
499 while (q
->async_fifo
&& av_fifo_size(q
->async_fifo
)) {
504 av_fifo_generic_read(q
->async_fifo
, &pkt
, sizeof(pkt
), NULL
);
505 av_fifo_generic_read(q
->async_fifo
, &sync
, sizeof(sync
), NULL
);
506 av_fifo_generic_read(q
->async_fifo
, &bs
, sizeof(bs
), NULL
);
509 av_packet_unref(&pkt
);
511 av_fifo_free(q
->async_fifo
);
512 q
->async_fifo
= NULL
;