summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog1
-rwxr-xr-xconfigure2
-rw-r--r--libavcodec/Makefile1
-rw-r--r--libavcodec/allcodecs.c1
-rw-r--r--libavcodec/qsv.c3
-rw-r--r--libavcodec/qsvenc.c95
-rw-r--r--libavcodec/qsvenc_jpeg.c91
7 files changed, 192 insertions, 2 deletions
diff --git a/Changelog b/Changelog
index 80ada1f5f1..4f937216eb 100644
--- a/Changelog
+++ b/Changelog
@@ -9,6 +9,7 @@ version <next>:
- MagicYUV encoder
- Raw AMR-NB and AMR-WB demuxers
- TiVo ty/ty+ demuxer
+- Intel QSV-accelerated MJPEG encoding
version 3.4:
diff --git a/configure b/configure
index 5b7a745b76..14f10deded 100755
--- a/configure
+++ b/configure
@@ -2821,6 +2821,8 @@ hevc_vaapi_encoder_select="cbs_h265 vaapi_encode"
hevc_v4l2m2m_decoder_deps="v4l2_m2m hevc_v4l2_m2m"
hevc_v4l2m2m_encoder_deps="v4l2_m2m hevc_v4l2_m2m"
mjpeg_cuvid_decoder_deps="cuda cuvid"
+mjpeg_qsv_encoder_deps="libmfx"
+mjpeg_qsv_encoder_select="qsvenc"
mjpeg_vaapi_encoder_deps="VAEncPictureParameterBufferJPEG"
mjpeg_vaapi_encoder_select="vaapi_encode jpegtables"
mpeg1_cuvid_decoder_deps="cuda cuvid"
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,
+};