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 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");
257 avctx->coded_frame = av_frame_alloc();
258 if (!avctx->coded_frame)
259 return AVERROR(ENOMEM);
266 static void clear_unused_frames(QSVEncContext *q)
268 QSVFrame *cur = q->work_frames;
270 if (cur->surface && !cur->surface->Data.Locked) {
272 av_frame_unref(cur->frame);
278 static int get_free_frame(QSVEncContext *q, QSVFrame **f)
280 QSVFrame *frame, **last;
282 clear_unused_frames(q);
284 frame = q->work_frames;
285 last = &q->work_frames;
287 if (!frame->surface) {
296 frame = av_mallocz(sizeof(*frame));
298 return AVERROR(ENOMEM);
299 frame->frame = av_frame_alloc();
302 return AVERROR(ENOMEM);
311 static int submit_frame(QSVEncContext *q, const AVFrame *frame,
312 mfxFrameSurface1 **surface)
317 ret = get_free_frame(q, &qf);
321 if (frame->format == AV_PIX_FMT_QSV) {
322 ret = av_frame_ref(qf->frame, frame);
326 qf->surface = (mfxFrameSurface1*)qf->frame->data[3];
327 *surface = qf->surface;
331 /* make a copy if the input is not padded as libmfx requires */
332 if ( frame->height & (q->height_align - 1) ||
333 frame->linesize[0] & (q->width_align - 1)) {
334 qf->frame->height = FFALIGN(frame->height, q->height_align);
335 qf->frame->width = FFALIGN(frame->width, q->width_align);
337 ret = ff_get_buffer(q->avctx, qf->frame, AV_GET_BUFFER_FLAG_REF);
341 qf->frame->height = frame->height;
342 qf->frame->width = frame->width;
343 ret = av_frame_copy(qf->frame, frame);
345 av_frame_unref(qf->frame);
349 ret = av_frame_ref(qf->frame, frame);
354 qf->surface_internal.Info = q->param.mfx.FrameInfo;
356 qf->surface_internal.Info.PicStruct =
357 !frame->interlaced_frame ? MFX_PICSTRUCT_PROGRESSIVE :
358 frame->top_field_first ? MFX_PICSTRUCT_FIELD_TFF :
359 MFX_PICSTRUCT_FIELD_BFF;
360 if (frame->repeat_pict == 1)
361 qf->surface_internal.Info.PicStruct |= MFX_PICSTRUCT_FIELD_REPEATED;
362 else if (frame->repeat_pict == 2)
363 qf->surface_internal.Info.PicStruct |= MFX_PICSTRUCT_FRAME_DOUBLING;
364 else if (frame->repeat_pict == 4)
365 qf->surface_internal.Info.PicStruct |= MFX_PICSTRUCT_FRAME_TRIPLING;
367 qf->surface_internal.Data.PitchLow = qf->frame->linesize[0];
368 qf->surface_internal.Data.Y = qf->frame->data[0];
369 qf->surface_internal.Data.UV = qf->frame->data[1];
370 qf->surface_internal.Data.TimeStamp = av_rescale_q(frame->pts, q->avctx->time_base, (AVRational){1, 90000});
372 qf->surface = &qf->surface_internal;
374 *surface = qf->surface;
379 static void print_interlace_msg(AVCodecContext *avctx, QSVEncContext *q)
381 if (q->param.mfx.CodecId == MFX_CODEC_AVC) {
382 if (q->param.mfx.CodecProfile == MFX_PROFILE_AVC_BASELINE ||
383 q->param.mfx.CodecLevel < MFX_LEVEL_AVC_21 ||
384 q->param.mfx.CodecLevel > MFX_LEVEL_AVC_41)
385 av_log(avctx, AV_LOG_WARNING,
386 "Interlaced coding is supported"
387 " at Main/High Profile Level 2.1-4.1\n");
391 int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q,
392 AVPacket *pkt, const AVFrame *frame, int *got_packet)
394 AVPacket new_pkt = { 0 };
397 mfxFrameSurface1 *surf = NULL;
398 mfxSyncPoint sync = NULL;
402 ret = submit_frame(q, frame, &surf);
404 av_log(avctx, AV_LOG_ERROR, "Error submitting the frame for encoding.\n");
409 ret = av_new_packet(&new_pkt, q->packet_size);
411 av_log(avctx, AV_LOG_ERROR, "Error allocating the output packet\n");
415 bs = av_mallocz(sizeof(*bs));
417 av_packet_unref(&new_pkt);
418 return AVERROR(ENOMEM);
420 bs->Data = new_pkt.data;
421 bs->MaxLength = new_pkt.size;
424 ret = MFXVideoENCODE_EncodeFrameAsync(q->session, NULL, surf, bs, &sync);
425 if (ret == MFX_WRN_DEVICE_BUSY) {
433 av_packet_unref(&new_pkt);
435 if (ret == MFX_ERR_MORE_DATA)
437 av_log(avctx, AV_LOG_ERROR, "EncodeFrameAsync returned %d\n", ret);
438 return ff_qsv_error(ret);
441 if (ret == MFX_WRN_INCOMPATIBLE_VIDEO_PARAM) {
442 if (frame->interlaced_frame)
443 print_interlace_msg(avctx, q);
445 av_log(avctx, AV_LOG_WARNING,
446 "EncodeFrameAsync returned 'incompatible param' code\n");
449 av_fifo_generic_write(q->async_fifo, &new_pkt, sizeof(new_pkt), NULL);
450 av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL);
451 av_fifo_generic_write(q->async_fifo, &bs, sizeof(bs), NULL);
453 av_packet_unref(&new_pkt);
457 if (!av_fifo_space(q->async_fifo) ||
458 (!frame && av_fifo_size(q->async_fifo))) {
459 av_fifo_generic_read(q->async_fifo, &new_pkt, sizeof(new_pkt), NULL);
460 av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL);
461 av_fifo_generic_read(q->async_fifo, &bs, sizeof(bs), NULL);
463 MFXVideoCORE_SyncOperation(q->session, sync, 60000);
465 new_pkt.dts = av_rescale_q(bs->DecodeTimeStamp, (AVRational){1, 90000}, avctx->time_base);
466 new_pkt.pts = av_rescale_q(bs->TimeStamp, (AVRational){1, 90000}, avctx->time_base);
467 new_pkt.size = bs->DataLength;
469 if (bs->FrameType & MFX_FRAMETYPE_IDR ||
470 bs->FrameType & MFX_FRAMETYPE_xIDR)
471 new_pkt.flags |= AV_PKT_FLAG_KEY;
473 if (bs->FrameType & MFX_FRAMETYPE_I || bs->FrameType & MFX_FRAMETYPE_xI)
474 avctx->coded_frame->pict_type = AV_PICTURE_TYPE_I;
475 else if (bs->FrameType & MFX_FRAMETYPE_P || bs->FrameType & MFX_FRAMETYPE_xP)
476 avctx->coded_frame->pict_type = AV_PICTURE_TYPE_P;
477 else if (bs->FrameType & MFX_FRAMETYPE_B || bs->FrameType & MFX_FRAMETYPE_xB)
478 avctx->coded_frame->pict_type = AV_PICTURE_TYPE_B;
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;
538 av_frame_free(&avctx->coded_frame);