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 FFmpeg.
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.
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.
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
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 & 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.CropX = 0;
71 q->param.mfx.FrameInfo.CropY = 0;
72 q->param.mfx.FrameInfo.CropW = avctx->width;
73 q->param.mfx.FrameInfo.CropH = avctx->height;
74 q->param.mfx.FrameInfo.AspectRatioW = avctx->sample_aspect_ratio.num;
75 q->param.mfx.FrameInfo.AspectRatioH = avctx->sample_aspect_ratio.den;
76 q->param.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
77 q->param.mfx.FrameInfo.BitDepthLuma = 8;
78 q->param.mfx.FrameInfo.BitDepthChroma = 8;
79 q->param.mfx.FrameInfo.Width = FFALIGN(avctx->width, q->width_align);
81 if (avctx->flags & CODEC_FLAG_INTERLACED_DCT) {
82 /* A true field layout (TFF or BFF) is not important here,
83 it will specified later during frame encoding. But it is important
84 to specify is frame progressive or not because allowed heigh alignment
87 q->param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_FIELD_TFF;
90 q->param.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
93 q->param.mfx.FrameInfo.Height = FFALIGN(avctx->height, q->height_align);
95 if (avctx->framerate.den > 0 && avctx->framerate.num > 0) {
96 q->param.mfx.FrameInfo.FrameRateExtN = avctx->framerate.num;
97 q->param.mfx.FrameInfo.FrameRateExtD = avctx->framerate.den;
99 q->param.mfx.FrameInfo.FrameRateExtN = avctx->time_base.den;
100 q->param.mfx.FrameInfo.FrameRateExtD = avctx->time_base.num;
103 if (avctx->flags & CODEC_FLAG_QSCALE) {
104 q->param.mfx.RateControlMethod = MFX_RATECONTROL_CQP;
105 ratecontrol_desc = "constant quantization parameter (CQP)";
106 } else if (avctx->rc_max_rate == avctx->bit_rate) {
107 q->param.mfx.RateControlMethod = MFX_RATECONTROL_CBR;
108 ratecontrol_desc = "constant bitrate (CBR)";
109 } else if (!avctx->rc_max_rate) {
110 q->param.mfx.RateControlMethod = MFX_RATECONTROL_AVBR;
111 ratecontrol_desc = "average variable bitrate (AVBR)";
113 q->param.mfx.RateControlMethod = MFX_RATECONTROL_VBR;
114 ratecontrol_desc = "variable bitrate (VBR)";
117 av_log(avctx, AV_LOG_VERBOSE, "Using the %s ratecontrol method\n", ratecontrol_desc);
119 switch (q->param.mfx.RateControlMethod) {
120 case MFX_RATECONTROL_CBR:
121 case MFX_RATECONTROL_VBR:
122 q->param.mfx.InitialDelayInKB = avctx->rc_initial_buffer_occupancy / 1000;
123 q->param.mfx.TargetKbps = avctx->bit_rate / 1000;
124 q->param.mfx.MaxKbps = avctx->bit_rate / 1000;
126 case MFX_RATECONTROL_CQP:
127 quant = avctx->global_quality / FF_QP2LAMBDA;
129 q->param.mfx.QPI = av_clip(quant * fabs(avctx->i_quant_factor) + avctx->i_quant_offset, 0, 51);
130 q->param.mfx.QPP = av_clip(quant, 0, 51);
131 q->param.mfx.QPB = av_clip(quant * fabs(avctx->b_quant_factor) + avctx->b_quant_offset, 0, 51);
134 case MFX_RATECONTROL_AVBR:
135 q->param.mfx.TargetKbps = avctx->bit_rate / 1000;
136 q->param.mfx.Convergence = q->avbr_convergence;
137 q->param.mfx.Accuracy = q->avbr_accuracy;
141 // the HEVC encoder plugin currently fails if coding options
143 if (avctx->codec_id != AV_CODEC_ID_HEVC) {
144 q->extco.Header.BufferId = MFX_EXTBUFF_CODING_OPTION;
145 q->extco.Header.BufferSz = sizeof(q->extco);
146 q->extco.CAVLC = avctx->coder_type == FF_CODER_TYPE_VLC ?
147 MFX_CODINGOPTION_ON : MFX_CODINGOPTION_UNKNOWN;
149 q->extparam[0] = (mfxExtBuffer *)&q->extco;
151 q->param.ExtParam = q->extparam;
152 q->param.NumExtParam = FF_ARRAY_ELEMS(q->extparam);
158 static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
160 uint8_t sps_buf[128];
161 uint8_t pps_buf[128];
163 mfxExtCodingOptionSPSPPS extradata = {
164 .Header.BufferId = MFX_EXTBUFF_CODING_OPTION_SPSPPS,
165 .Header.BufferSz = sizeof(extradata),
166 .SPSBuffer = sps_buf, .SPSBufSize = sizeof(sps_buf),
167 .PPSBuffer = pps_buf, .PPSBufSize = sizeof(pps_buf)
170 mfxExtBuffer *ext_buffers[] = {
171 (mfxExtBuffer*)&extradata,
174 int need_pps = avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO;
177 q->param.ExtParam = ext_buffers;
178 q->param.NumExtParam = FF_ARRAY_ELEMS(ext_buffers);
180 ret = MFXVideoENCODE_GetVideoParam(q->session, &q->param);
182 return ff_qsv_error(ret);
184 q->packet_size = q->param.mfx.BufferSizeInKB * 1000;
186 if (!extradata.SPSBufSize || (need_pps && !extradata.PPSBufSize)) {
187 av_log(avctx, AV_LOG_ERROR, "No extradata returned from libmfx.\n");
188 return AVERROR_UNKNOWN;
191 avctx->extradata = av_malloc(extradata.SPSBufSize + need_pps * extradata.PPSBufSize +
192 FF_INPUT_BUFFER_PADDING_SIZE);
193 if (!avctx->extradata)
194 return AVERROR(ENOMEM);
196 memcpy(avctx->extradata, sps_buf, extradata.SPSBufSize);
198 memcpy(avctx->extradata + extradata.SPSBufSize, pps_buf, extradata.PPSBufSize);
199 avctx->extradata_size = extradata.SPSBufSize + need_pps * extradata.PPSBufSize;
200 memset(avctx->extradata + avctx->extradata_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
205 int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q)
209 q->param.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY;
210 q->param.AsyncDepth = q->async_depth;
212 if (avctx->hwaccel_context) {
213 AVQSVContext *qsv = avctx->hwaccel_context;
215 q->session = qsv->session;
216 q->param.IOPattern = qsv->iopattern;
220 ret = ff_qsv_init_internal_session(avctx, &q->internal_qs,
225 q->session = q->internal_qs.session;
228 ret = init_video_param(avctx, q);
232 ret = MFXVideoENCODE_QueryIOSurf(q->session, &q->param, &q->req);
234 av_log(avctx, AV_LOG_ERROR, "Error querying the encoding parameters\n");
235 return ff_qsv_error(ret);
238 ret = MFXVideoENCODE_Init(q->session, &q->param);
239 if (MFX_WRN_PARTIAL_ACCELERATION==ret) {
240 av_log(avctx, AV_LOG_WARNING, "Encoder will work with partial HW acceleration\n");
241 } else if (ret < 0) {
242 av_log(avctx, AV_LOG_ERROR, "Error initializing the encoder\n");
243 return ff_qsv_error(ret);
246 ret = qsv_retrieve_enc_params(avctx, q);
248 av_log(avctx, AV_LOG_ERROR, "Error retrieving encoding parameters.\n");
252 avctx->coded_frame = av_frame_alloc();
253 if (!avctx->coded_frame)
254 return AVERROR(ENOMEM);
261 static void clear_unused_frames(QSVEncContext *q)
263 QSVFrame *cur = q->work_frames;
265 if (cur->surface && !cur->surface->Data.Locked) {
267 av_frame_unref(cur->frame);
273 static int get_free_frame(QSVEncContext *q, QSVFrame **f)
275 QSVFrame *frame, **last;
277 clear_unused_frames(q);
279 frame = q->work_frames;
280 last = &q->work_frames;
282 if (!frame->surface) {
291 frame = av_mallocz(sizeof(*frame));
293 return AVERROR(ENOMEM);
294 frame->frame = av_frame_alloc();
297 return AVERROR(ENOMEM);
306 static int submit_frame(QSVEncContext *q, const AVFrame *frame,
307 mfxFrameSurface1 **surface)
312 ret = get_free_frame(q, &qf);
316 if (frame->format == AV_PIX_FMT_QSV) {
317 ret = av_frame_ref(qf->frame, frame);
321 qf->surface = (mfxFrameSurface1*)qf->frame->data[3];
322 *surface = qf->surface;
326 /* make a copy if the input is not padded as libmfx requires */
327 if ( frame->height & (q->height_align - 1) ||
328 frame->linesize[0] & (q->width_align - 1)) {
329 qf->frame->height = FFALIGN(frame->height, q->height_align);
330 qf->frame->width = FFALIGN(frame->width, q->width_align);
332 ret = ff_get_buffer(q->avctx, qf->frame, AV_GET_BUFFER_FLAG_REF);
336 qf->frame->height = frame->height;
337 qf->frame->width = frame->width;
338 ret = av_frame_copy(qf->frame, frame);
340 av_frame_unref(qf->frame);
344 ret = av_frame_ref(qf->frame, frame);
349 qf->surface_internal.Info = q->param.mfx.FrameInfo;
351 qf->surface_internal.Info.PicStruct =
352 !frame->interlaced_frame ? MFX_PICSTRUCT_PROGRESSIVE :
353 frame->top_field_first ? MFX_PICSTRUCT_FIELD_TFF :
354 MFX_PICSTRUCT_FIELD_BFF;
355 if (frame->repeat_pict == 1)
356 qf->surface_internal.Info.PicStruct |= MFX_PICSTRUCT_FIELD_REPEATED;
357 else if (frame->repeat_pict == 2)
358 qf->surface_internal.Info.PicStruct |= MFX_PICSTRUCT_FRAME_DOUBLING;
359 else if (frame->repeat_pict == 4)
360 qf->surface_internal.Info.PicStruct |= MFX_PICSTRUCT_FRAME_TRIPLING;
362 qf->surface_internal.Data.PitchLow = qf->frame->linesize[0];
363 qf->surface_internal.Data.Y = qf->frame->data[0];
364 qf->surface_internal.Data.UV = qf->frame->data[1];
365 qf->surface_internal.Data.TimeStamp = av_rescale_q(frame->pts, q->avctx->time_base, (AVRational){1, 90000});
367 qf->surface = &qf->surface_internal;
369 *surface = qf->surface;
374 static void print_interlace_msg(AVCodecContext *avctx, QSVEncContext *q)
376 if (q->param.mfx.CodecId == MFX_CODEC_AVC) {
377 if (q->param.mfx.CodecProfile == MFX_PROFILE_AVC_BASELINE ||
378 q->param.mfx.CodecLevel < MFX_LEVEL_AVC_21 ||
379 q->param.mfx.CodecLevel > MFX_LEVEL_AVC_41)
380 av_log(avctx, AV_LOG_WARNING,
381 "Interlaced coding is supported"
382 " at Main/High Profile Level 2.1-4.1\n");
386 int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q,
387 AVPacket *pkt, const AVFrame *frame, int *got_packet)
389 mfxBitstream bs = { { { 0 } } };
391 mfxFrameSurface1 *surf = NULL;
392 mfxSyncPoint sync = NULL;
396 ret = submit_frame(q, frame, &surf);
398 av_log(avctx, AV_LOG_ERROR, "Error submitting the frame for encoding.\n");
403 ret = ff_alloc_packet(pkt, q->packet_size);
405 av_log(avctx, AV_LOG_ERROR, "Error allocating the output packet\n");
409 bs.MaxLength = pkt->size;
412 ret = MFXVideoENCODE_EncodeFrameAsync(q->session, NULL, surf, &bs, &sync);
413 if (ret == MFX_WRN_DEVICE_BUSY) {
421 if (ret == MFX_ERR_MORE_DATA)
423 av_log(avctx, AV_LOG_ERROR, "EncodeFrameAsync returned %d\n", ret);
424 return ff_qsv_error(ret);
427 if (ret == MFX_WRN_INCOMPATIBLE_VIDEO_PARAM) {
428 if (frame->interlaced_frame)
429 print_interlace_msg(avctx, q);
431 av_log(avctx, AV_LOG_WARNING,
432 "EncodeFrameAsync returned 'incompatible param' code\n");
435 MFXVideoCORE_SyncOperation(q->session, sync, 60000);
437 if (bs.FrameType & MFX_FRAMETYPE_I || bs.FrameType & MFX_FRAMETYPE_xI)
438 avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
439 else if (bs.FrameType & MFX_FRAMETYPE_P || bs.FrameType & MFX_FRAMETYPE_xP)
440 avctx->coded_frame->pict_type = AV_PICTURE_TYPE_P;
441 else if (bs.FrameType & MFX_FRAMETYPE_B || bs.FrameType & MFX_FRAMETYPE_xB)
442 avctx->coded_frame->pict_type = AV_PICTURE_TYPE_B;
444 pkt->dts = av_rescale_q(bs.DecodeTimeStamp, (AVRational){1, 90000}, avctx->time_base);
445 pkt->pts = av_rescale_q(bs.TimeStamp, (AVRational){1, 90000}, avctx->time_base);
446 pkt->size = bs.DataLength;
448 if (bs.FrameType & MFX_FRAMETYPE_IDR ||
449 bs.FrameType & MFX_FRAMETYPE_xIDR)
450 pkt->flags |= AV_PKT_FLAG_KEY;
458 int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q)
462 MFXVideoENCODE_Close(q->session);
465 ff_qsv_close_internal_session(&q->internal_qs);
467 cur = q->work_frames;
469 q->work_frames = cur->next;
470 av_frame_free(&cur->frame);
472 cur = q->work_frames;
475 av_frame_free(&avctx->coded_frame);