* commit '2fd6e7d077f590e4d7195356f9baeb271f8b9ae2':
libavcodec/mjpeg_qsv: Add QSV MJPEG encoder
Merged-by: James Almer <jamrial@gmail.com>
... | ... |
@@ -2821,6 +2821,8 @@ hevc_vaapi_encoder_select="cbs_h265 vaapi_encode" |
2821 | 2821 |
hevc_v4l2m2m_decoder_deps="v4l2_m2m hevc_v4l2_m2m" |
2822 | 2822 |
hevc_v4l2m2m_encoder_deps="v4l2_m2m hevc_v4l2_m2m" |
2823 | 2823 |
mjpeg_cuvid_decoder_deps="cuda cuvid" |
2824 |
+mjpeg_qsv_encoder_deps="libmfx" |
|
2825 |
+mjpeg_qsv_encoder_select="qsvenc" |
|
2824 | 2826 |
mjpeg_vaapi_encoder_deps="VAEncPictureParameterBufferJPEG" |
2825 | 2827 |
mjpeg_vaapi_encoder_select="vaapi_encode jpegtables" |
2826 | 2828 |
mpeg1_cuvid_decoder_deps="cuda cuvid" |
... | ... |
@@ -410,6 +410,7 @@ OBJS-$(CONFIG_MJPEG_DECODER) += mjpegdec.o |
410 | 410 |
OBJS-$(CONFIG_MJPEG_ENCODER) += mjpegenc.o mjpegenc_common.o \ |
411 | 411 |
mjpegenc_huffman.o |
412 | 412 |
OBJS-$(CONFIG_MJPEGB_DECODER) += mjpegbdec.o |
413 |
+OBJS-$(CONFIG_MJPEG_QSV_ENCODER) += qsvenc_jpeg.o |
|
413 | 414 |
OBJS-$(CONFIG_MJPEG_VAAPI_ENCODER) += vaapi_encode_mjpeg.o |
414 | 415 |
OBJS-$(CONFIG_MLP_DECODER) += mlpdec.o mlpdsp.o |
415 | 416 |
OBJS-$(CONFIG_MLP_ENCODER) += mlpenc.o mlp.o |
... | ... |
@@ -669,6 +669,7 @@ static void register_all(void) |
669 | 669 |
REGISTER_ENCODER(HEVC_VAAPI, hevc_vaapi); |
670 | 670 |
REGISTER_ENCODER(LIBKVAZAAR, libkvazaar); |
671 | 671 |
REGISTER_DECODER(MJPEG_CUVID, mjpeg_cuvid); |
672 |
+ REGISTER_ENCODER(MJPEG_QSV, mjpeg_qsv); |
|
672 | 673 |
REGISTER_ENCODER(MJPEG_VAAPI, mjpeg_vaapi); |
673 | 674 |
REGISTER_DECODER(MPEG1_CUVID, mpeg1_cuvid); |
674 | 675 |
REGISTER_DECODER(MPEG2_CUVID, mpeg2_cuvid); |
... | ... |
@@ -20,6 +20,7 @@ |
20 | 20 |
|
21 | 21 |
#include <mfx/mfxvideo.h> |
22 | 22 |
#include <mfx/mfxplugin.h> |
23 |
+#include <mfx/mfxjpeg.h> |
|
23 | 24 |
|
24 | 25 |
#include <stdio.h> |
25 | 26 |
#include <string.h> |
... | ... |
@@ -56,6 +57,8 @@ int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id) |
56 | 56 |
case AV_CODEC_ID_VP8: |
57 | 57 |
return MFX_CODEC_VP8; |
58 | 58 |
#endif |
59 |
+ case AV_CODEC_ID_MJPEG: |
|
60 |
+ return MFX_CODEC_JPEG; |
|
59 | 61 |
default: |
60 | 62 |
break; |
61 | 63 |
} |
... | ... |
@@ -345,6 +345,64 @@ static int rc_supported(QSVEncContext *q) |
345 | 345 |
return 1; |
346 | 346 |
} |
347 | 347 |
|
348 |
+static int init_video_param_jpeg(AVCodecContext *avctx, QSVEncContext *q) |
|
349 |
+{ |
|
350 |
+ enum AVPixelFormat sw_format = avctx->pix_fmt == AV_PIX_FMT_QSV ? |
|
351 |
+ avctx->sw_pix_fmt : avctx->pix_fmt; |
|
352 |
+ const AVPixFmtDescriptor *desc; |
|
353 |
+ int ret; |
|
354 |
+ |
|
355 |
+ ret = ff_qsv_codec_id_to_mfx(avctx->codec_id); |
|
356 |
+ if (ret < 0) |
|
357 |
+ return AVERROR_BUG; |
|
358 |
+ q->param.mfx.CodecId = ret; |
|
359 |
+ |
|
360 |
+ if (avctx->level > 0) |
|
361 |
+ q->param.mfx.CodecLevel = avctx->level; |
|
362 |
+ q->param.mfx.CodecProfile = q->profile; |
|
363 |
+ |
|
364 |
+ desc = av_pix_fmt_desc_get(sw_format); |
|
365 |
+ if (!desc) |
|
366 |
+ return AVERROR_BUG; |
|
367 |
+ |
|
368 |
+ ff_qsv_map_pixfmt(sw_format, &q->param.mfx.FrameInfo.FourCC); |
|
369 |
+ |
|
370 |
+ q->param.mfx.FrameInfo.CropX = 0; |
|
371 |
+ q->param.mfx.FrameInfo.CropY = 0; |
|
372 |
+ q->param.mfx.FrameInfo.CropW = avctx->width; |
|
373 |
+ q->param.mfx.FrameInfo.CropH = avctx->height; |
|
374 |
+ q->param.mfx.FrameInfo.AspectRatioW = avctx->sample_aspect_ratio.num; |
|
375 |
+ q->param.mfx.FrameInfo.AspectRatioH = avctx->sample_aspect_ratio.den; |
|
376 |
+ q->param.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420; |
|
377 |
+ q->param.mfx.FrameInfo.BitDepthLuma = desc->comp[0].depth; |
|
378 |
+ q->param.mfx.FrameInfo.BitDepthChroma = desc->comp[0].depth; |
|
379 |
+ q->param.mfx.FrameInfo.Shift = desc->comp[0].depth > 8; |
|
380 |
+ |
|
381 |
+ q->param.mfx.FrameInfo.Width = FFALIGN(avctx->width, 16); |
|
382 |
+ q->param.mfx.FrameInfo.Height = FFALIGN(avctx->height, 16); |
|
383 |
+ |
|
384 |
+ if (avctx->hw_frames_ctx) { |
|
385 |
+ AVHWFramesContext *frames_ctx = (AVHWFramesContext *)avctx->hw_frames_ctx->data; |
|
386 |
+ AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx; |
|
387 |
+ q->param.mfx.FrameInfo.Width = frames_hwctx->surfaces[0].Info.Width; |
|
388 |
+ q->param.mfx.FrameInfo.Height = frames_hwctx->surfaces[0].Info.Height; |
|
389 |
+ } |
|
390 |
+ |
|
391 |
+ if (avctx->framerate.den > 0 && avctx->framerate.num > 0) { |
|
392 |
+ q->param.mfx.FrameInfo.FrameRateExtN = avctx->framerate.num; |
|
393 |
+ q->param.mfx.FrameInfo.FrameRateExtD = avctx->framerate.den; |
|
394 |
+ } else { |
|
395 |
+ q->param.mfx.FrameInfo.FrameRateExtN = avctx->time_base.den; |
|
396 |
+ q->param.mfx.FrameInfo.FrameRateExtD = avctx->time_base.num; |
|
397 |
+ } |
|
398 |
+ |
|
399 |
+ q->param.mfx.Interleaved = 1; |
|
400 |
+ q->param.mfx.Quality = av_clip(avctx->global_quality, 1, 100); |
|
401 |
+ q->param.mfx.RestartInterval = 0; |
|
402 |
+ |
|
403 |
+ return 0; |
|
404 |
+} |
|
405 |
+ |
|
348 | 406 |
static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) |
349 | 407 |
{ |
350 | 408 |
enum AVPixelFormat sw_format = avctx->pix_fmt == AV_PIX_FMT_QSV ? |
... | ... |
@@ -567,6 +625,24 @@ FF_ENABLE_DEPRECATION_WARNINGS |
567 | 567 |
return 0; |
568 | 568 |
} |
569 | 569 |
|
570 |
+static int qsv_retrieve_enc_jpeg_params(AVCodecContext *avctx, QSVEncContext *q) |
|
571 |
+{ |
|
572 |
+ int ret = 0; |
|
573 |
+ |
|
574 |
+ ret = MFXVideoENCODE_GetVideoParam(q->session, &q->param); |
|
575 |
+ if (ret < 0) |
|
576 |
+ return ff_qsv_print_error(avctx, ret, |
|
577 |
+ "Error calling GetVideoParam"); |
|
578 |
+ |
|
579 |
+ q->packet_size = q->param.mfx.BufferSizeInKB * 1000; |
|
580 |
+ |
|
581 |
+ // for qsv mjpeg the return value maybe 0 so alloc the buffer |
|
582 |
+ if (q->packet_size == 0) |
|
583 |
+ q->packet_size = q->param.mfx.FrameInfo.Height * q->param.mfx.FrameInfo.Width * 4; |
|
584 |
+ |
|
585 |
+ return 0; |
|
586 |
+} |
|
587 |
+ |
|
570 | 588 |
static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q) |
571 | 589 |
{ |
572 | 590 |
AVCPBProperties *cpb_props; |
... | ... |
@@ -760,7 +836,15 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q) |
760 | 760 |
if (ret < 0) |
761 | 761 |
return ret; |
762 | 762 |
|
763 |
- ret = init_video_param(avctx, q); |
|
763 |
+ // in the mfxInfoMFX struct, JPEG is different from other codecs |
|
764 |
+ switch (avctx->codec_id) { |
|
765 |
+ case AV_CODEC_ID_MJPEG: |
|
766 |
+ ret = init_video_param_jpeg(avctx, q); |
|
767 |
+ break; |
|
768 |
+ default: |
|
769 |
+ ret = init_video_param(avctx, q); |
|
770 |
+ break; |
|
771 |
+ } |
|
764 | 772 |
if (ret < 0) |
765 | 773 |
return ret; |
766 | 774 |
|
... | ... |
@@ -820,7 +904,14 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q) |
820 | 820 |
ff_qsv_print_warning(avctx, ret, |
821 | 821 |
"Warning in encoder initialization"); |
822 | 822 |
|
823 |
- ret = qsv_retrieve_enc_params(avctx, q); |
|
823 |
+ switch (avctx->codec_id) { |
|
824 |
+ case AV_CODEC_ID_MJPEG: |
|
825 |
+ ret = qsv_retrieve_enc_jpeg_params(avctx, q); |
|
826 |
+ break; |
|
827 |
+ default: |
|
828 |
+ ret = qsv_retrieve_enc_params(avctx, q); |
|
829 |
+ break; |
|
830 |
+ } |
|
824 | 831 |
if (ret < 0) { |
825 | 832 |
av_log(avctx, AV_LOG_ERROR, "Error retrieving encoding parameters.\n"); |
826 | 833 |
return ret; |
827 | 834 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,91 @@ |
0 |
+/* |
|
1 |
+ * Intel MediaSDK QSV based MJPEG encoder |
|
2 |
+ * |
|
3 |
+ * This file is part of Libav. |
|
4 |
+ * |
|
5 |
+ * Libav is free software; you can redistribute it and/or |
|
6 |
+ * modify it under the terms of the GNU Lesser General Public |
|
7 |
+ * License as published by the Free Software Foundation; either |
|
8 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
9 |
+ * |
|
10 |
+ * Libav is distributed in the hope that it will be useful, |
|
11 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 |
+ * Lesser General Public License for more details. |
|
14 |
+ * |
|
15 |
+ * You should have received a copy of the GNU Lesser General Public |
|
16 |
+ * License along with Libav; if not, write to the Free Software |
|
17 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
18 |
+ */ |
|
19 |
+ |
|
20 |
+ |
|
21 |
+#include <stdint.h> |
|
22 |
+#include <sys/types.h> |
|
23 |
+ |
|
24 |
+#include <mfx/mfxvideo.h> |
|
25 |
+ |
|
26 |
+#include "libavutil/common.h" |
|
27 |
+#include "libavutil/opt.h" |
|
28 |
+ |
|
29 |
+#include "avcodec.h" |
|
30 |
+#include "internal.h" |
|
31 |
+#include "h264.h" |
|
32 |
+#include "qsv.h" |
|
33 |
+#include "qsv_internal.h" |
|
34 |
+#include "qsvenc.h" |
|
35 |
+ |
|
36 |
+typedef struct QSVMJPEGEncContext { |
|
37 |
+ AVClass *class; |
|
38 |
+ QSVEncContext qsv; |
|
39 |
+} QSVMJPEGEncContext; |
|
40 |
+ |
|
41 |
+static av_cold int qsv_enc_init(AVCodecContext *avctx) |
|
42 |
+{ |
|
43 |
+ QSVMJPEGEncContext *q = avctx->priv_data; |
|
44 |
+ |
|
45 |
+ return ff_qsv_enc_init(avctx, &q->qsv); |
|
46 |
+} |
|
47 |
+ |
|
48 |
+static int qsv_enc_frame(AVCodecContext *avctx, AVPacket *pkt, |
|
49 |
+ const AVFrame *frame, int *got_packet) |
|
50 |
+{ |
|
51 |
+ QSVMJPEGEncContext *q = avctx->priv_data; |
|
52 |
+ |
|
53 |
+ return ff_qsv_encode(avctx, &q->qsv, pkt, frame, got_packet); |
|
54 |
+} |
|
55 |
+ |
|
56 |
+static av_cold int qsv_enc_close(AVCodecContext *avctx) |
|
57 |
+{ |
|
58 |
+ QSVMJPEGEncContext *q = avctx->priv_data; |
|
59 |
+ |
|
60 |
+ return ff_qsv_enc_close(avctx, &q->qsv); |
|
61 |
+} |
|
62 |
+ |
|
63 |
+#define OFFSET(x) offsetof(QSVMJPEGEncContext, x) |
|
64 |
+#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM |
|
65 |
+static const AVOption options[] = { |
|
66 |
+ { NULL }, |
|
67 |
+}; |
|
68 |
+ |
|
69 |
+static const AVClass class = { |
|
70 |
+ .class_name = "mjpeg_qsv encoder", |
|
71 |
+ .item_name = av_default_item_name, |
|
72 |
+ .option = options, |
|
73 |
+ .version = LIBAVUTIL_VERSION_INT, |
|
74 |
+}; |
|
75 |
+ |
|
76 |
+AVCodec ff_mjpeg_qsv_encoder = { |
|
77 |
+ .name = "mjpeg_qsv", |
|
78 |
+ .long_name = NULL_IF_CONFIG_SMALL("MJPEG (Intel Quick Sync Video acceleration)"), |
|
79 |
+ .priv_data_size = sizeof(QSVMJPEGEncContext), |
|
80 |
+ .type = AVMEDIA_TYPE_VIDEO, |
|
81 |
+ .id = AV_CODEC_ID_MJPEG, |
|
82 |
+ .init = qsv_enc_init, |
|
83 |
+ .encode2 = qsv_enc_frame, |
|
84 |
+ .close = qsv_enc_close, |
|
85 |
+ .capabilities = AV_CODEC_CAP_DELAY, |
|
86 |
+ .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, |
|
87 |
+ AV_PIX_FMT_QSV, |
|
88 |
+ AV_PIX_FMT_NONE }, |
|
89 |
+ .priv_class = &class, |
|
90 |
+}; |