diff options
author | James Almer <jamrial@gmail.com> | 2017-11-08 13:45:09 -0300 |
---|---|---|
committer | James Almer <jamrial@gmail.com> | 2017-11-08 13:45:09 -0300 |
commit | 1926f13a206bfbd99abf536e7424e2b321f2e2ad (patch) | |
tree | a13838e5728599f13f4152fe0bee18092e6a2b9c /libavcodec | |
parent | 51f977c2c4b39d80ed39107a21b1647abce1acca (diff) | |
parent | 2fd6e7d077f590e4d7195356f9baeb271f8b9ae2 (diff) | |
download | ffmpeg-1926f13a206bfbd99abf536e7424e2b321f2e2ad.tar.gz |
Merge commit '2fd6e7d077f590e4d7195356f9baeb271f8b9ae2'
* commit '2fd6e7d077f590e4d7195356f9baeb271f8b9ae2':
libavcodec/mjpeg_qsv: Add QSV MJPEG encoder
Merged-by: James Almer <jamrial@gmail.com>
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/Makefile | 1 | ||||
-rw-r--r-- | libavcodec/allcodecs.c | 1 | ||||
-rw-r--r-- | libavcodec/qsv.c | 3 | ||||
-rw-r--r-- | libavcodec/qsvenc.c | 95 | ||||
-rw-r--r-- | libavcodec/qsvenc_jpeg.c | 91 |
5 files changed, 189 insertions, 2 deletions
diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3a33361f33..45f4db5939 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -410,6 +410,7 @@ OBJS-$(CONFIG_MJPEG_DECODER) += mjpegdec.o OBJS-$(CONFIG_MJPEG_ENCODER) += mjpegenc.o mjpegenc_common.o \ mjpegenc_huffman.o OBJS-$(CONFIG_MJPEGB_DECODER) += mjpegbdec.o +OBJS-$(CONFIG_MJPEG_QSV_ENCODER) += qsvenc_jpeg.o OBJS-$(CONFIG_MJPEG_VAAPI_ENCODER) += vaapi_encode_mjpeg.o OBJS-$(CONFIG_MLP_DECODER) += mlpdec.o mlpdsp.o OBJS-$(CONFIG_MLP_ENCODER) += mlpenc.o mlp.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 98655ddd7c..d96e499ba7 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -669,6 +669,7 @@ static void register_all(void) REGISTER_ENCODER(HEVC_VAAPI, hevc_vaapi); REGISTER_ENCODER(LIBKVAZAAR, libkvazaar); REGISTER_DECODER(MJPEG_CUVID, mjpeg_cuvid); + REGISTER_ENCODER(MJPEG_QSV, mjpeg_qsv); REGISTER_ENCODER(MJPEG_VAAPI, mjpeg_vaapi); REGISTER_DECODER(MPEG1_CUVID, mpeg1_cuvid); REGISTER_DECODER(MPEG2_CUVID, mpeg2_cuvid); diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c index 56ca9df262..5180eb8771 100644 --- a/libavcodec/qsv.c +++ b/libavcodec/qsv.c @@ -20,6 +20,7 @@ #include <mfx/mfxvideo.h> #include <mfx/mfxplugin.h> +#include <mfx/mfxjpeg.h> #include <stdio.h> #include <string.h> @@ -56,6 +57,8 @@ int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id) case AV_CODEC_ID_VP8: return MFX_CODEC_VP8; #endif + case AV_CODEC_ID_MJPEG: + return MFX_CODEC_JPEG; default: break; } diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 5eb506fb76..2bc19f5241 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -345,6 +345,64 @@ static int rc_supported(QSVEncContext *q) return 1; } +static int init_video_param_jpeg(AVCodecContext *avctx, QSVEncContext *q) +{ + enum AVPixelFormat sw_format = avctx->pix_fmt == AV_PIX_FMT_QSV ? + avctx->sw_pix_fmt : avctx->pix_fmt; + const AVPixFmtDescriptor *desc; + int ret; + + ret = ff_qsv_codec_id_to_mfx(avctx->codec_id); + if (ret < 0) + return AVERROR_BUG; + q->param.mfx.CodecId = ret; + + if (avctx->level > 0) + q->param.mfx.CodecLevel = avctx->level; + q->param.mfx.CodecProfile = q->profile; + + desc = av_pix_fmt_desc_get(sw_format); + if (!desc) + return AVERROR_BUG; + + ff_qsv_map_pixfmt(sw_format, &q->param.mfx.FrameInfo.FourCC); + + q->param.mfx.FrameInfo.CropX = 0; + q->param.mfx.FrameInfo.CropY = 0; + q->param.mfx.FrameInfo.CropW = avctx->width; + q->param.mfx.FrameInfo.CropH = avctx->height; + q->param.mfx.FrameInfo.AspectRatioW = avctx->sample_aspect_ratio.num; + q->param.mfx.FrameInfo.AspectRatioH = avctx->sample_aspect_ratio.den; + q->param.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420; + q->param.mfx.FrameInfo.BitDepthLuma = desc->comp[0].depth; + q->param.mfx.FrameInfo.BitDepthChroma = desc->comp[0].depth; + q->param.mfx.FrameInfo.Shift = desc->comp[0].depth > 8; + + q->param.mfx.FrameInfo.Width = FFALIGN(avctx->width, 16); + q->param.mfx.FrameInfo.Height = FFALIGN(avctx->height, 16); + + if (avctx->hw_frames_ctx) { + AVHWFramesContext *frames_ctx = (AVHWFramesContext *)avctx->hw_frames_ctx->data; + AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx; + q->param.mfx.FrameInfo.Width = frames_hwctx->surfaces[0].Info.Width; + q->param.mfx.FrameInfo.Height = frames_hwctx->surfaces[0].Info.Height; + } + + if (avctx->framerate.den > 0 && avctx->framerate.num > 0) { + q->param.mfx.FrameInfo.FrameRateExtN = avctx->framerate.num; + q->param.mfx.FrameInfo.FrameRateExtD = avctx->framerate.den; + } else { + q->param.mfx.FrameInfo.FrameRateExtN = avctx->time_base.den; + q->param.mfx.FrameInfo.FrameRateExtD = avctx->time_base.num; + } + + q->param.mfx.Interleaved = 1; + q->param.mfx.Quality = av_clip(avctx->global_quality, 1, 100); + q->param.mfx.RestartInterval = 0; + + return 0; +} + static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) { enum AVPixelFormat sw_format = avctx->pix_fmt == AV_PIX_FMT_QSV ? @@ -567,6 +625,24 @@ FF_ENABLE_DEPRECATION_WARNINGS return 0; } +static int qsv_retrieve_enc_jpeg_params(AVCodecContext *avctx, QSVEncContext *q) +{ + int ret = 0; + + ret = MFXVideoENCODE_GetVideoParam(q->session, &q->param); + if (ret < 0) + return ff_qsv_print_error(avctx, ret, + "Error calling GetVideoParam"); + + q->packet_size = q->param.mfx.BufferSizeInKB * 1000; + + // for qsv mjpeg the return value maybe 0 so alloc the buffer + if (q->packet_size == 0) + q->packet_size = q->param.mfx.FrameInfo.Height * q->param.mfx.FrameInfo.Width * 4; + + return 0; +} + static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q) { AVCPBProperties *cpb_props; @@ -760,7 +836,15 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q) if (ret < 0) return ret; - ret = init_video_param(avctx, q); + // in the mfxInfoMFX struct, JPEG is different from other codecs + switch (avctx->codec_id) { + case AV_CODEC_ID_MJPEG: + ret = init_video_param_jpeg(avctx, q); + break; + default: + ret = init_video_param(avctx, q); + break; + } if (ret < 0) return ret; @@ -820,7 +904,14 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q) ff_qsv_print_warning(avctx, ret, "Warning in encoder initialization"); - ret = qsv_retrieve_enc_params(avctx, q); + switch (avctx->codec_id) { + case AV_CODEC_ID_MJPEG: + ret = qsv_retrieve_enc_jpeg_params(avctx, q); + break; + default: + ret = qsv_retrieve_enc_params(avctx, q); + break; + } if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error retrieving encoding parameters.\n"); return ret; diff --git a/libavcodec/qsvenc_jpeg.c b/libavcodec/qsvenc_jpeg.c new file mode 100644 index 0000000000..3fa17f13ab --- /dev/null +++ b/libavcodec/qsvenc_jpeg.c @@ -0,0 +1,91 @@ +/* + * Intel MediaSDK QSV based MJPEG encoder + * + * This file is part of Libav. + * + * Libav 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. + * + * Libav 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 Libav; 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 "h264.h" +#include "qsv.h" +#include "qsv_internal.h" +#include "qsvenc.h" + +typedef struct QSVMJPEGEncContext { + AVClass *class; + QSVEncContext qsv; +} QSVMJPEGEncContext; + +static av_cold int qsv_enc_init(AVCodecContext *avctx) +{ + QSVMJPEGEncContext *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) +{ + QSVMJPEGEncContext *q = avctx->priv_data; + + return ff_qsv_encode(avctx, &q->qsv, pkt, frame, got_packet); +} + +static av_cold int qsv_enc_close(AVCodecContext *avctx) +{ + QSVMJPEGEncContext *q = avctx->priv_data; + + return ff_qsv_enc_close(avctx, &q->qsv); +} + +#define OFFSET(x) offsetof(QSVMJPEGEncContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { NULL }, +}; + +static const AVClass class = { + .class_name = "mjpeg_qsv encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_mjpeg_qsv_encoder = { + .name = "mjpeg_qsv", + .long_name = NULL_IF_CONFIG_SMALL("MJPEG (Intel Quick Sync Video acceleration)"), + .priv_data_size = sizeof(QSVMJPEGEncContext), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MJPEG, + .init = qsv_enc_init, + .encode2 = qsv_enc_frame, + .close = qsv_enc_close, + .capabilities = AV_CODEC_CAP_DELAY, + .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, + AV_PIX_FMT_QSV, + AV_PIX_FMT_NONE }, + .priv_class = &class, +}; |