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 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 AV_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, AV_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 q->async_fifo = av_fifo_alloc((1 + q->async_depth) *
213 (sizeof(AVPacket) + sizeof(mfxSyncPoint) + sizeof(mfxBitstream*)));
215 return AVERROR(ENOMEM);
217 if (avctx->hwaccel_context) {
218 AVQSVContext *qsv = avctx->hwaccel_context;
220 q->session = qsv->session;
221 q->param.IOPattern = qsv->iopattern;
225 ret = ff_qsv_init_internal_session(avctx, &q->internal_qs,
230 q->session = q->internal_qs.session;
233 ret = init_video_param(avctx, q);
237 ret = MFXVideoENCODE_QueryIOSurf(q->session, &q->param, &q->req);
239 av_log(avctx, AV_LOG_ERROR, "Error querying the encoding parameters\n");
240 return ff_qsv_error(ret);
243 ret = MFXVideoENCODE_Init(q->session, &q->param);
244 if (MFX_WRN_PARTIAL_ACCELERATION==ret) {
245 av_log(avctx, AV_LOG_WARNING, "Encoder will work with partial HW acceleration\n");
246 } else if (ret < 0) {
247 av_log(avctx, AV_LOG_ERROR, "Error initializing the encoder\n");
248 return ff_qsv_error(ret);
251 ret = qsv_retrieve_enc_params(avctx, q);
253 av_log(avctx, AV_LOG_ERROR, "Error retrieving encoding parameters.\n");
262 static void clear_unused_frames(QSVEncContext *q)
264 QSVFrame *cur = q->work_frames;
266 if (cur->surface && !cur->surface->Data.Locked) {
268 av_frame_unref(cur->frame);
274 static int get_free_frame(QSVEncContext *q, QSVFrame **f)
276 QSVFrame *frame, **last;
278 clear_unused_frames(q);
280 frame = q->work_frames;
281 last = &q->work_frames;
283 if (!frame->surface) {
292 frame = av_mallocz(sizeof(*frame));
294 return AVERROR(ENOMEM);
295 frame->frame = av_frame_alloc();
298 return AVERROR(ENOMEM);
307 static int submit_frame(QSVEncContext *q, const AVFrame *frame,
308 mfxFrameSurface1 **surface)
313 ret = get_free_frame(q, &qf);
317 if (frame->format == AV_PIX_FMT_QSV) {
318 ret = av_frame_ref(qf->frame, frame);
322 qf->surface = (mfxFrameSurface1*)qf->frame->data[3];
323 *surface = qf->surface;
327 /* make a copy if the input is not padded as libmfx requires */
328 if ( frame->height & (q->height_align - 1) ||
329 frame->linesize[0] & (q->width_align - 1)) {
330 qf->frame->height = FFALIGN(frame->height, q->height_align);
331 qf->frame->width = FFALIGN(frame->width, q->width_align);
333 ret = ff_get_buffer(q->avctx, qf->frame, AV_GET_BUFFER_FLAG_REF);
337 qf->frame->height = frame->height;
338 qf->frame->width = frame->width;
339 ret = av_frame_copy(qf->frame, frame);
341 av_frame_unref(qf->frame);
345 ret = av_frame_ref(qf->frame, frame);
350 qf->surface_internal.Info = q->param.mfx.FrameInfo;
352 qf->surface_internal.Info.PicStruct =
353 !frame->interlaced_frame ? MFX_PICSTRUCT_PROGRESSIVE :
354 frame->top_field_first ? MFX_PICSTRUCT_FIELD_TFF :
355 MFX_PICSTRUCT_FIELD_BFF;
356 if (frame->repeat_pict == 1)
357 qf->surface_internal.Info.PicStruct |= MFX_PICSTRUCT_FIELD_REPEATED;
358 else if (frame->repeat_pict == 2)
359 qf->surface_internal.Info.PicStruct |= MFX_PICSTRUCT_FRAME_DOUBLING;
360 else if (frame->repeat_pict == 4)
361 qf->surface_internal.Info.PicStruct |= MFX_PICSTRUCT_FRAME_TRIPLING;
363 qf->surface_internal.Data.PitchLow = qf->frame->linesize[0];
364 qf->surface_internal.Data.Y = qf->frame->data[0];
365 qf->surface_internal.Data.UV = qf->frame->data[1];
366 qf->surface_internal.Data.TimeStamp = av_rescale_q(frame->pts, q->avctx->time_base, (AVRational){1, 90000});
368 qf->surface = &qf->surface_internal;
370 *surface = qf->surface;
375 static void print_interlace_msg(AVCodecContext *avctx, QSVEncContext *q)
377 if (q->param.mfx.CodecId == MFX_CODEC_AVC) {
378 if (q->param.mfx.CodecProfile == MFX_PROFILE_AVC_BASELINE ||
379 q->param.mfx.CodecLevel < MFX_LEVEL_AVC_21 ||
380 q->param.mfx.CodecLevel > MFX_LEVEL_AVC_41)
381 av_log(avctx, AV_LOG_WARNING,
382 "Interlaced coding is supported"
383 " at Main/High Profile Level 2.1-4.1\n");
387 int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q,
388 AVPacket *pkt, const AVFrame *frame, int *got_packet)
390 AVPacket new_pkt = { 0 };
393 mfxFrameSurface1 *surf = NULL;
394 mfxSyncPoint sync = NULL;
398 ret = submit_frame(q, frame, &surf);
400 av_log(avctx, AV_LOG_ERROR, "Error submitting the frame for encoding.\n");
405 ret = av_new_packet(&new_pkt, q->packet_size);
407 av_log(avctx, AV_LOG_ERROR, "Error allocating the output packet\n");
411 bs = av_mallocz(sizeof(*bs));
413 av_packet_unref(&new_pkt);
414 return AVERROR(ENOMEM);
416 bs->Data = new_pkt.data;
417 bs->MaxLength = new_pkt.size;
420 ret = MFXVideoENCODE_EncodeFrameAsync(q->session, NULL, surf, bs, &sync);
421 if (ret == MFX_WRN_DEVICE_BUSY) {
429 av_packet_unref(&new_pkt);
431 if (ret == MFX_ERR_MORE_DATA)
433 av_log(avctx, AV_LOG_ERROR, "EncodeFrameAsync returned %d\n", ret);
434 return ff_qsv_error(ret);
437 if (ret == MFX_WRN_INCOMPATIBLE_VIDEO_PARAM) {
438 if (frame->interlaced_frame)
439 print_interlace_msg(avctx, q);
441 av_log(avctx, AV_LOG_WARNING,
442 "EncodeFrameAsync returned 'incompatible param' code\n");
445 av_fifo_generic_write(q->async_fifo, &new_pkt, sizeof(new_pkt), NULL);
446 av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL);
447 av_fifo_generic_write(q->async_fifo, &bs, sizeof(bs), NULL);
449 av_packet_unref(&new_pkt);
453 if (!av_fifo_space(q->async_fifo) ||
454 (!frame && av_fifo_size(q->async_fifo))) {
455 av_fifo_generic_read(q->async_fifo, &new_pkt, sizeof(new_pkt), NULL);
456 av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL);
457 av_fifo_generic_read(q->async_fifo, &bs, sizeof(bs), NULL);
459 MFXVideoCORE_SyncOperation(q->session, sync, 60000);
461 new_pkt.dts = av_rescale_q(bs->DecodeTimeStamp, (AVRational){1, 90000}, avctx->time_base);
462 new_pkt.pts = av_rescale_q(bs->TimeStamp, (AVRational){1, 90000}, avctx->time_base);
463 new_pkt.size = bs->DataLength;
465 if (bs->FrameType & MFX_FRAMETYPE_IDR ||
466 bs->FrameType & MFX_FRAMETYPE_xIDR)
467 new_pkt.flags |= AV_PKT_FLAG_KEY;
469 #if FF_API_CODED_FRAME
470 FF_DISABLE_DEPRECATION_WARNINGS
471 if (bs->FrameType & MFX_FRAMETYPE_I || bs->FrameType & MFX_FRAMETYPE_xI)
472 avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
473 else if (bs->FrameType & MFX_FRAMETYPE_P || bs->FrameType & MFX_FRAMETYPE_xP)
474 avctx->coded_frame->pict_type = AV_PICTURE_TYPE_P;
475 else if (bs->FrameType & MFX_FRAMETYPE_B || bs->FrameType & MFX_FRAMETYPE_xB)
476 avctx->coded_frame->pict_type = AV_PICTURE_TYPE_B;
477 FF_ENABLE_DEPRECATION_WARNINGS
483 if (pkt->size < new_pkt.size) {
484 av_log(avctx, AV_LOG_ERROR, "Submitted buffer not large enough: %d < %d\n",
485 pkt->size, new_pkt.size);
486 av_packet_unref(&new_pkt);
487 return AVERROR(EINVAL);
490 memcpy(pkt->data, new_pkt.data, new_pkt.size);
491 pkt->size = new_pkt.size;
493 ret = av_packet_copy_props(pkt, &new_pkt);
494 av_packet_unref(&new_pkt);
506 int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q)
510 MFXVideoENCODE_Close(q->session);
513 ff_qsv_close_internal_session(&q->internal_qs);
515 cur = q->work_frames;
517 q->work_frames = cur->next;
518 av_frame_free(&cur->frame);
520 cur = q->work_frames;
523 while (q->async_fifo && av_fifo_size(q->async_fifo)) {
528 av_fifo_generic_read(q->async_fifo, &pkt, sizeof(pkt), NULL);
529 av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL);
530 av_fifo_generic_read(q->async_fifo, &bs, sizeof(bs), NULL);
533 av_packet_unref(&pkt);
535 av_fifo_free(q->async_fifo);
536 q->async_fifo = NULL;