Browse code

Merge commit '2fd6e7d077f590e4d7195356f9baeb271f8b9ae2'

* commit '2fd6e7d077f590e4d7195356f9baeb271f8b9ae2':
libavcodec/mjpeg_qsv: Add QSV MJPEG encoder

Merged-by: James Almer <jamrial@gmail.com>

James Almer authored on 2017/11/09 01:45:09
Showing 7 changed files
... ...
@@ -9,6 +9,7 @@ version <next>:
9 9
 - MagicYUV encoder
10 10
 - Raw AMR-NB and AMR-WB demuxers
11 11
 - TiVo ty/ty+ demuxer
12
+- Intel QSV-accelerated MJPEG encoding
12 13
 
13 14
 
14 15
 version 3.4:
... ...
@@ -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
+};