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 & 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.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 & AV_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 & AV_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 #if QSV_VERSION_ATLEAST(1,7)
112 q->param.mfx.RateControlMethod = MFX_RATECONTROL_LA;
113 ratecontrol_desc = "lookahead (LA)";
117 q->param.mfx.RateControlMethod = MFX_RATECONTROL_AVBR;
118 ratecontrol_desc = "average variable bitrate (AVBR)";
121 q->param.mfx.RateControlMethod = MFX_RATECONTROL_VBR;
122 ratecontrol_desc = "variable bitrate (VBR)";
125 av_log(avctx, AV_LOG_VERBOSE, "Using the %s ratecontrol method\n", ratecontrol_desc);
127 switch (q->param.mfx.RateControlMethod) {
128 case MFX_RATECONTROL_CBR:
129 case MFX_RATECONTROL_VBR:
130 q->param.mfx.InitialDelayInKB = avctx->rc_initial_buffer_occupancy / 1000;
131 q->param.mfx.TargetKbps = avctx->bit_rate / 1000;
132 q->param.mfx.MaxKbps = avctx->rc_max_rate / 1000;
134 case MFX_RATECONTROL_CQP:
135 quant = avctx->global_quality / FF_QP2LAMBDA;
137 q->param.mfx.QPI = av_clip(quant * fabs(avctx->i_quant_factor) + avctx->i_quant_offset, 0, 51);
138 q->param.mfx.QPP = av_clip(quant, 0, 51);
139 q->param.mfx.QPB = av_clip(quant * fabs(avctx->b_quant_factor) + avctx->b_quant_offset, 0, 51);
142 case MFX_RATECONTROL_AVBR:
143 #if QSV_VERSION_ATLEAST(1,7)
144 case MFX_RATECONTROL_LA:
146 q->param.mfx.TargetKbps = avctx->bit_rate / 1000;
147 q->param.mfx.Convergence = q->avbr_convergence;
148 q->param.mfx.Accuracy = q->avbr_accuracy;
152 // the HEVC encoder plugin currently fails if coding options
154 if (avctx->codec_id != AV_CODEC_ID_HEVC) {
155 q->extco.Header.BufferId = MFX_EXTBUFF_CODING_OPTION;
156 q->extco.Header.BufferSz = sizeof(q->extco);
157 q->extco.CAVLC = avctx->coder_type == FF_CODER_TYPE_VLC ?
158 MFX_CODINGOPTION_ON : MFX_CODINGOPTION_UNKNOWN;
160 q->extco.PicTimingSEI = q->pic_timing_sei ?
161 MFX_CODINGOPTION_ON : MFX_CODINGOPTION_UNKNOWN;
163 q->extparam[0] = (mfxExtBuffer *)&q->extco;
165 #if QSV_VERSION_ATLEAST(1,6)
166 q->extco2.Header.BufferId = MFX_EXTBUFF_CODING_OPTION2;
167 q->extco2.Header.BufferSz = sizeof(q->extco2);
169 #if QSV_VERSION_ATLEAST(1,7)
170 // valid value range is from 10 to 100 inclusive
171 // to instruct the encoder to use the default value this should be set to zero
172 q->extco2.LookAheadDepth = q->look_ahead_depth != 0 ? FFMAX(10, q->look_ahead_depth) : 0;
174 #if QSV_VERSION_ATLEAST(1,8)
175 q->extco2.LookAheadDS = q->look_ahead_downsampling;
178 q->extparam[1] = (mfxExtBuffer *)&q->extco2;
181 q->param.ExtParam = q->extparam;
182 q->param.NumExtParam = FF_ARRAY_ELEMS(q->extparam);
188 static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
190 uint8_t sps_buf[128];
191 uint8_t pps_buf[128];
193 mfxExtCodingOptionSPSPPS extradata = {
194 .Header.BufferId = MFX_EXTBUFF_CODING_OPTION_SPSPPS,
195 .Header.BufferSz = sizeof(extradata),
196 .SPSBuffer = sps_buf, .SPSBufSize = sizeof(sps_buf),
197 .PPSBuffer = pps_buf, .PPSBufSize = sizeof(pps_buf)
200 mfxExtBuffer *ext_buffers[] = {
201 (mfxExtBuffer*)&extradata,
204 int need_pps = avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO;
207 q->param.ExtParam = ext_buffers;
208 q->param.NumExtParam = FF_ARRAY_ELEMS(ext_buffers);
210 ret = MFXVideoENCODE_GetVideoParam(q->session, &q->param);
212 return ff_qsv_error(ret);
214 q->packet_size = q->param.mfx.BufferSizeInKB * 1000;
216 if (!extradata.SPSBufSize || (need_pps && !extradata.PPSBufSize)) {
217 av_log(avctx, AV_LOG_ERROR, "No extradata returned from libmfx.\n");
218 return AVERROR_UNKNOWN;
221 avctx->extradata = av_malloc(extradata.SPSBufSize + need_pps * extradata.PPSBufSize +
222 AV_INPUT_BUFFER_PADDING_SIZE);
223 if (!avctx->extradata)
224 return AVERROR(ENOMEM);
226 memcpy(avctx->extradata, sps_buf, extradata.SPSBufSize);
228 memcpy(avctx->extradata + extradata.SPSBufSize, pps_buf, extradata.PPSBufSize);
229 avctx->extradata_size = extradata.SPSBufSize + need_pps * extradata.PPSBufSize;
230 memset(avctx->extradata + avctx->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
235 int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q)
239 q->param.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY;
240 q->param.AsyncDepth = q->async_depth;
242 q->async_fifo = av_fifo_alloc((1 + q->async_depth) *
243 (sizeof(AVPacket) + sizeof(mfxSyncPoint) + sizeof(mfxBitstream*)));
245 return AVERROR(ENOMEM);
247 if (avctx->hwaccel_context) {
248 AVQSVContext *qsv = avctx->hwaccel_context;
250 q->session = qsv->session;
251 q->param.IOPattern = qsv->iopattern;
255 ret = ff_qsv_init_internal_session(avctx, &q->internal_qs,
260 q->session = q->internal_qs.session;
263 ret = init_video_param(avctx, q);
267 ret = MFXVideoENCODE_Query(q->session, &q->param,&q->param);
268 if (MFX_WRN_PARTIAL_ACCELERATION==ret) {
269 av_log(avctx, AV_LOG_WARNING, "Encoder will work with partial HW acceleration\n");
270 } else if (ret < 0) {
271 av_log(avctx, AV_LOG_ERROR, "Error %d querying encoder params\n", ret);
272 return ff_qsv_error(ret);
275 ret = MFXVideoENCODE_QueryIOSurf(q->session, &q->param, &q->req);
277 av_log(avctx, AV_LOG_ERROR, "Error querying the encoding parameters\n");
278 return ff_qsv_error(ret);
281 ret = MFXVideoENCODE_Init(q->session, &q->param);
282 if (MFX_WRN_PARTIAL_ACCELERATION==ret) {
283 av_log(avctx, AV_LOG_WARNING, "Encoder will work with partial HW acceleration\n");
284 } else if (ret < 0) {
285 av_log(avctx, AV_LOG_ERROR, "Error initializing the encoder\n");
286 return ff_qsv_error(ret);
289 ret = qsv_retrieve_enc_params(avctx, q);
291 av_log(avctx, AV_LOG_ERROR, "Error retrieving encoding parameters.\n");
300 static void clear_unused_frames(QSVEncContext *q)
302 QSVFrame *cur = q->work_frames;
304 if (cur->surface && !cur->surface->Data.Locked) {
306 av_frame_unref(cur->frame);
312 static int get_free_frame(QSVEncContext *q, QSVFrame **f)
314 QSVFrame *frame, **last;
316 clear_unused_frames(q);
318 frame = q->work_frames;
319 last = &q->work_frames;
321 if (!frame->surface) {
330 frame = av_mallocz(sizeof(*frame));
332 return AVERROR(ENOMEM);
333 frame->frame = av_frame_alloc();
336 return AVERROR(ENOMEM);
345 static int submit_frame(QSVEncContext *q, const AVFrame *frame,
346 mfxFrameSurface1 **surface)
351 ret = get_free_frame(q, &qf);
355 if (frame->format == AV_PIX_FMT_QSV) {
356 ret = av_frame_ref(qf->frame, frame);
360 qf->surface = (mfxFrameSurface1*)qf->frame->data[3];
361 *surface = qf->surface;
365 /* make a copy if the input is not padded as libmfx requires */
366 if ( frame->height & (q->height_align - 1) ||
367 frame->linesize[0] & (q->width_align - 1)) {
368 qf->frame->height = FFALIGN(frame->height, q->height_align);
369 qf->frame->width = FFALIGN(frame->width, q->width_align);
371 ret = ff_get_buffer(q->avctx, qf->frame, AV_GET_BUFFER_FLAG_REF);
375 qf->frame->height = frame->height;
376 qf->frame->width = frame->width;
377 ret = av_frame_copy(qf->frame, frame);
379 av_frame_unref(qf->frame);
383 ret = av_frame_ref(qf->frame, frame);
388 qf->surface_internal.Info = q->param.mfx.FrameInfo;
390 qf->surface_internal.Info.PicStruct =
391 !frame->interlaced_frame ? MFX_PICSTRUCT_PROGRESSIVE :
392 frame->top_field_first ? MFX_PICSTRUCT_FIELD_TFF :
393 MFX_PICSTRUCT_FIELD_BFF;
394 if (frame->repeat_pict == 1)
395 qf->surface_internal.Info.PicStruct |= MFX_PICSTRUCT_FIELD_REPEATED;
396 else if (frame->repeat_pict == 2)
397 qf->surface_internal.Info.PicStruct |= MFX_PICSTRUCT_FRAME_DOUBLING;
398 else if (frame->repeat_pict == 4)
399 qf->surface_internal.Info.PicStruct |= MFX_PICSTRUCT_FRAME_TRIPLING;
401 qf->surface_internal.Data.PitchLow = qf->frame->linesize[0];
402 qf->surface_internal.Data.Y = qf->frame->data[0];
403 qf->surface_internal.Data.UV = qf->frame->data[1];
404 qf->surface_internal.Data.TimeStamp = av_rescale_q(frame->pts, q->avctx->time_base, (AVRational){1, 90000});
406 qf->surface = &qf->surface_internal;
408 *surface = qf->surface;
413 static void print_interlace_msg(AVCodecContext *avctx, QSVEncContext *q)
415 if (q->param.mfx.CodecId == MFX_CODEC_AVC) {
416 if (q->param.mfx.CodecProfile == MFX_PROFILE_AVC_BASELINE ||
417 q->param.mfx.CodecLevel < MFX_LEVEL_AVC_21 ||
418 q->param.mfx.CodecLevel > MFX_LEVEL_AVC_41)
419 av_log(avctx, AV_LOG_WARNING,
420 "Interlaced coding is supported"
421 " at Main/High Profile Level 2.1-4.1\n");
425 int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q,
426 AVPacket *pkt, const AVFrame *frame, int *got_packet)
428 AVPacket new_pkt = { 0 };
431 mfxFrameSurface1 *surf = NULL;
432 mfxSyncPoint sync = NULL;
436 ret = submit_frame(q, frame, &surf);
438 av_log(avctx, AV_LOG_ERROR, "Error submitting the frame for encoding.\n");
443 ret = av_new_packet(&new_pkt, q->packet_size);
445 av_log(avctx, AV_LOG_ERROR, "Error allocating the output packet\n");
449 bs = av_mallocz(sizeof(*bs));
451 av_packet_unref(&new_pkt);
452 return AVERROR(ENOMEM);
454 bs->Data = new_pkt.data;
455 bs->MaxLength = new_pkt.size;
458 ret = MFXVideoENCODE_EncodeFrameAsync(q->session, NULL, surf, bs, &sync);
459 if (ret == MFX_WRN_DEVICE_BUSY) {
467 av_packet_unref(&new_pkt);
469 if (ret == MFX_ERR_MORE_DATA)
471 av_log(avctx, AV_LOG_ERROR, "EncodeFrameAsync returned %d\n", ret);
472 return ff_qsv_error(ret);
475 if (ret == MFX_WRN_INCOMPATIBLE_VIDEO_PARAM) {
476 if (frame->interlaced_frame)
477 print_interlace_msg(avctx, q);
479 av_log(avctx, AV_LOG_WARNING,
480 "EncodeFrameAsync returned 'incompatible param' code\n");
483 av_fifo_generic_write(q->async_fifo, &new_pkt, sizeof(new_pkt), NULL);
484 av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL);
485 av_fifo_generic_write(q->async_fifo, &bs, sizeof(bs), NULL);
487 av_packet_unref(&new_pkt);
491 if (!av_fifo_space(q->async_fifo) ||
492 (!frame && av_fifo_size(q->async_fifo))) {
493 av_fifo_generic_read(q->async_fifo, &new_pkt, sizeof(new_pkt), NULL);
494 av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL);
495 av_fifo_generic_read(q->async_fifo, &bs, sizeof(bs), NULL);
497 MFXVideoCORE_SyncOperation(q->session, sync, 60000);
499 new_pkt.dts = av_rescale_q(bs->DecodeTimeStamp, (AVRational){1, 90000}, avctx->time_base);
500 new_pkt.pts = av_rescale_q(bs->TimeStamp, (AVRational){1, 90000}, avctx->time_base);
501 new_pkt.size = bs->DataLength;
503 if (bs->FrameType & MFX_FRAMETYPE_IDR ||
504 bs->FrameType & MFX_FRAMETYPE_xIDR)
505 new_pkt.flags |= AV_PKT_FLAG_KEY;
507 #if FF_API_CODED_FRAME
508 FF_DISABLE_DEPRECATION_WARNINGS
509 if (bs->FrameType & MFX_FRAMETYPE_I || bs->FrameType & MFX_FRAMETYPE_xI)
510 avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
511 else if (bs->FrameType & MFX_FRAMETYPE_P || bs->FrameType & MFX_FRAMETYPE_xP)
512 avctx->coded_frame->pict_type = AV_PICTURE_TYPE_P;
513 else if (bs->FrameType & MFX_FRAMETYPE_B || bs->FrameType & MFX_FRAMETYPE_xB)
514 avctx->coded_frame->pict_type = AV_PICTURE_TYPE_B;
515 FF_ENABLE_DEPRECATION_WARNINGS
521 if (pkt->size < new_pkt.size) {
522 av_log(avctx, AV_LOG_ERROR, "Submitted buffer not large enough: %d < %d\n",
523 pkt->size, new_pkt.size);
524 av_packet_unref(&new_pkt);
525 return AVERROR(EINVAL);
528 memcpy(pkt->data, new_pkt.data, new_pkt.size);
529 pkt->size = new_pkt.size;
531 ret = av_packet_copy_props(pkt, &new_pkt);
532 av_packet_unref(&new_pkt);
544 int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q)
549 MFXVideoENCODE_Close(q->session);
552 ff_qsv_close_internal_session(&q->internal_qs);
554 cur = q->work_frames;
556 q->work_frames = cur->next;
557 av_frame_free(&cur->frame);
559 cur = q->work_frames;
562 while (q->async_fifo && av_fifo_size(q->async_fifo)) {
567 av_fifo_generic_read(q->async_fifo, &pkt, sizeof(pkt), NULL);
568 av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL);
569 av_fifo_generic_read(q->async_fifo, &bs, sizeof(bs), NULL);
572 av_packet_unref(&pkt);
574 av_fifo_free(q->async_fifo);
575 q->async_fifo = NULL;