* commit '3a85397e8bb477eb34678d9edc52893f57003226': lavc: add Intel libmfx-based MPEG2 encoder Conflicts: Changelog configure libavcodec/allcodecs.c Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n2.8
| @@ -14,6 +14,7 @@ version <next>: | |||||
| - Go2Meeting decoding support | - Go2Meeting decoding support | ||||
| - adrawgraph audio and drawgraph video filter | - adrawgraph audio and drawgraph video filter | ||||
| - removegrain video filter | - removegrain video filter | ||||
| - Intel QSV-accelerated MPEG-2 video encoding | |||||
| version 2.7: | version 2.7: | ||||
| @@ -2253,6 +2253,7 @@ mpeg1video_decoder_select="error_resilience mpeg_er mpegvideo" | |||||
| mpeg1video_encoder_select="aandcttables mpegvideoenc h263dsp" | mpeg1video_encoder_select="aandcttables mpegvideoenc h263dsp" | ||||
| mpeg2video_decoder_select="error_resilience mpeg_er mpegvideo" | mpeg2video_decoder_select="error_resilience mpeg_er mpegvideo" | ||||
| mpeg2video_encoder_select="aandcttables mpegvideoenc h263dsp" | mpeg2video_encoder_select="aandcttables mpegvideoenc h263dsp" | ||||
| mpeg2_qsv_encoder_select="qsvenc" | |||||
| mpeg4_decoder_select="h263_decoder mpeg4video_parser" | mpeg4_decoder_select="h263_decoder mpeg4video_parser" | ||||
| mpeg4_encoder_select="h263_encoder" | mpeg4_encoder_select="h263_encoder" | ||||
| msmpeg4v1_decoder_select="h263_decoder" | msmpeg4v1_decoder_select="h263_decoder" | ||||
| @@ -352,6 +352,7 @@ OBJS-$(CONFIG_MPEG1VIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o | |||||
| OBJS-$(CONFIG_MPEG1VIDEO_ENCODER) += mpeg12enc.o mpeg12.o | OBJS-$(CONFIG_MPEG1VIDEO_ENCODER) += mpeg12enc.o mpeg12.o | ||||
| OBJS-$(CONFIG_MPEG2VIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o | OBJS-$(CONFIG_MPEG2VIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o | ||||
| OBJS-$(CONFIG_MPEG2VIDEO_ENCODER) += mpeg12enc.o mpeg12.o | OBJS-$(CONFIG_MPEG2VIDEO_ENCODER) += mpeg12enc.o mpeg12.o | ||||
| OBJS-$(CONFIG_MPEG2_QSV_ENCODER) += qsvenc_mpeg2.o | |||||
| OBJS-$(CONFIG_MPEG4_DECODER) += xvididct.o | OBJS-$(CONFIG_MPEG4_DECODER) += xvididct.o | ||||
| OBJS-$(CONFIG_MPL2_DECODER) += mpl2dec.o ass.o | OBJS-$(CONFIG_MPL2_DECODER) += mpl2dec.o ass.o | ||||
| OBJS-$(CONFIG_MSMPEG4V1_DECODER) += msmpeg4dec.o msmpeg4.o msmpeg4data.o | OBJS-$(CONFIG_MSMPEG4V1_DECODER) += msmpeg4dec.o msmpeg4.o msmpeg4data.o | ||||
| @@ -569,6 +569,7 @@ void avcodec_register_all(void) | |||||
| REGISTER_ENCODER(NVENC, nvenc); | REGISTER_ENCODER(NVENC, nvenc); | ||||
| REGISTER_ENCODER(NVENC_H264, nvenc_h264); | REGISTER_ENCODER(NVENC_H264, nvenc_h264); | ||||
| REGISTER_ENCODER(NVENC_HEVC, nvenc_hevc); | REGISTER_ENCODER(NVENC_HEVC, nvenc_hevc); | ||||
| REGISTER_ENCODER(MPEG2_QSV, mpeg2_qsv); | |||||
| /* parsers */ | /* parsers */ | ||||
| REGISTER_PARSER(AAC, aac); | REGISTER_PARSER(AAC, aac); | ||||
| @@ -164,6 +164,7 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q) | |||||
| (mfxExtBuffer*)&extradata, | (mfxExtBuffer*)&extradata, | ||||
| }; | }; | ||||
| int need_pps = avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO; | |||||
| int ret; | int ret; | ||||
| q->param.ExtParam = ext_buffers; | q->param.ExtParam = ext_buffers; | ||||
| @@ -175,19 +176,20 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q) | |||||
| q->packet_size = q->param.mfx.BufferSizeInKB * 1000; | q->packet_size = q->param.mfx.BufferSizeInKB * 1000; | ||||
| if (!extradata.SPSBufSize || !extradata.PPSBufSize) { | |||||
| if (!extradata.SPSBufSize || (need_pps && !extradata.PPSBufSize)) { | |||||
| av_log(avctx, AV_LOG_ERROR, "No extradata returned from libmfx.\n"); | av_log(avctx, AV_LOG_ERROR, "No extradata returned from libmfx.\n"); | ||||
| return AVERROR_UNKNOWN; | return AVERROR_UNKNOWN; | ||||
| } | } | ||||
| avctx->extradata = av_malloc(extradata.SPSBufSize + extradata.PPSBufSize + | |||||
| avctx->extradata = av_malloc(extradata.SPSBufSize + need_pps * extradata.PPSBufSize + | |||||
| FF_INPUT_BUFFER_PADDING_SIZE); | FF_INPUT_BUFFER_PADDING_SIZE); | ||||
| if (!avctx->extradata) | if (!avctx->extradata) | ||||
| return AVERROR(ENOMEM); | return AVERROR(ENOMEM); | ||||
| memcpy(avctx->extradata, sps_buf, extradata.SPSBufSize); | memcpy(avctx->extradata, sps_buf, extradata.SPSBufSize); | ||||
| memcpy(avctx->extradata + extradata.SPSBufSize, pps_buf, extradata.PPSBufSize); | |||||
| avctx->extradata_size = extradata.SPSBufSize + extradata.PPSBufSize; | |||||
| if (need_pps) | |||||
| memcpy(avctx->extradata + extradata.SPSBufSize, pps_buf, extradata.PPSBufSize); | |||||
| avctx->extradata_size = extradata.SPSBufSize + need_pps * extradata.PPSBufSize; | |||||
| memset(avctx->extradata + avctx->extradata_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); | memset(avctx->extradata + avctx->extradata_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); | ||||
| return 0; | return 0; | ||||
| @@ -0,0 +1,117 @@ | |||||
| /* | |||||
| * Intel MediaSDK QSV based MPEG-2 encoder | |||||
| * | |||||
| * This file is part of FFmpeg. | |||||
| * | |||||
| * FFmpeg is free software; you can redistribute it and/or | |||||
| * modify it under the terms of the GNU Lesser General Public | |||||
| * License as published by the Free Software Foundation; either | |||||
| * version 2.1 of the License, or (at your option) any later version. | |||||
| * | |||||
| * FFmpeg is distributed in the hope that it will be useful, | |||||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||||
| * Lesser General Public License for more details. | |||||
| * | |||||
| * You should have received a copy of the GNU Lesser General Public | |||||
| * License along with FFmpeg; if not, write to the Free Software | |||||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||||
| */ | |||||
| #include <stdint.h> | |||||
| #include <sys/types.h> | |||||
| #include <mfx/mfxvideo.h> | |||||
| #include "libavutil/common.h" | |||||
| #include "libavutil/opt.h" | |||||
| #include "avcodec.h" | |||||
| #include "internal.h" | |||||
| #include "qsv.h" | |||||
| #include "qsv_internal.h" | |||||
| #include "qsvenc.h" | |||||
| typedef struct QSVMpeg2EncContext { | |||||
| AVClass *class; | |||||
| QSVEncContext qsv; | |||||
| } QSVMpeg2EncContext; | |||||
| static av_cold int qsv_enc_init(AVCodecContext *avctx) | |||||
| { | |||||
| QSVMpeg2EncContext *q = avctx->priv_data; | |||||
| return ff_qsv_enc_init(avctx, &q->qsv); | |||||
| } | |||||
| static int qsv_enc_frame(AVCodecContext *avctx, AVPacket *pkt, | |||||
| const AVFrame *frame, int *got_packet) | |||||
| { | |||||
| QSVMpeg2EncContext *q = avctx->priv_data; | |||||
| return ff_qsv_encode(avctx, &q->qsv, pkt, frame, got_packet); | |||||
| } | |||||
| static av_cold int qsv_enc_close(AVCodecContext *avctx) | |||||
| { | |||||
| QSVMpeg2EncContext *q = avctx->priv_data; | |||||
| return ff_qsv_enc_close(avctx, &q->qsv); | |||||
| } | |||||
| #define OFFSET(x) offsetof(QSVMpeg2EncContext, x) | |||||
| #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM | |||||
| static const AVOption options[] = { | |||||
| { "async_depth", "Maximum processing parallelism", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VE }, | |||||
| { "avbr_accuracy", "Accuracy of the AVBR ratecontrol", OFFSET(qsv.avbr_accuracy), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, | |||||
| { "avbr_convergence", "Convergence of the AVBR ratecontrol", OFFSET(qsv.avbr_convergence), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, | |||||
| { "profile", NULL, OFFSET(qsv.profile), AV_OPT_TYPE_INT, { .i64 = MFX_PROFILE_UNKNOWN }, 0, INT_MAX, VE, "profile" }, | |||||
| { "unknown", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, VE, "profile" }, | |||||
| { "simple", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_MPEG2_SIMPLE }, INT_MIN, INT_MAX, VE, "profile" }, | |||||
| { "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_MPEG2_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, | |||||
| { "high", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_MPEG2_HIGH }, INT_MIN, INT_MAX, VE, "profile" }, | |||||
| { "preset", NULL, OFFSET(qsv.preset), AV_OPT_TYPE_INT, { .i64 = MFX_TARGETUSAGE_BALANCED }, 0, 7, VE, "preset" }, | |||||
| { "fast", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BEST_SPEED }, INT_MIN, INT_MAX, VE, "preset" }, | |||||
| { "medium", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BALANCED }, INT_MIN, INT_MAX, VE, "preset" }, | |||||
| { "slow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BEST_QUALITY }, INT_MIN, INT_MAX, VE, "preset" }, | |||||
| { NULL }, | |||||
| }; | |||||
| static const AVClass class = { | |||||
| .class_name = "mpeg2_qsv encoder", | |||||
| .item_name = av_default_item_name, | |||||
| .option = options, | |||||
| .version = LIBAVUTIL_VERSION_INT, | |||||
| }; | |||||
| static const AVCodecDefault qsv_enc_defaults[] = { | |||||
| { "b", "1M" }, | |||||
| { "refs", "0" }, | |||||
| // same as the x264 default | |||||
| { "g", "250" }, | |||||
| { "bf", "3" }, | |||||
| { "flags", "+cgop" }, | |||||
| { NULL }, | |||||
| }; | |||||
| AVCodec ff_mpeg2_qsv_encoder = { | |||||
| .name = "mpeg2_qsv", | |||||
| .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video (Intel Quick Sync Video acceleration)"), | |||||
| .priv_data_size = sizeof(QSVMpeg2EncContext), | |||||
| .type = AVMEDIA_TYPE_VIDEO, | |||||
| .id = AV_CODEC_ID_MPEG2VIDEO, | |||||
| .init = qsv_enc_init, | |||||
| .encode2 = qsv_enc_frame, | |||||
| .close = qsv_enc_close, | |||||
| .capabilities = CODEC_CAP_DELAY, | |||||
| .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, | |||||
| AV_PIX_FMT_QSV, | |||||
| AV_PIX_FMT_NONE }, | |||||
| .priv_class = &class, | |||||
| .defaults = qsv_enc_defaults, | |||||
| }; | |||||