Browse code

Merge commit '83f230c2445a94fdd94c66504482217fcece5909'

* commit '83f230c2445a94fdd94c66504482217fcece5909':
lavc: VAAPI MJPEG encoder

Merged-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>

Derek Buitenhuis authored on 2016/05/09 06:46:52
Showing 5 changed files
... ...
@@ -30,7 +30,7 @@ version <next>:
30 30
 - libnpp/CUDA-accelerated format conversion and scaling
31 31
 - Duck TrueMotion 2.0 Real Time decoder
32 32
 - Wideband Single-bit Data (WSD) demuxer
33
-- VAAPI-accelerated H.264/HEVC encoding
33
+- VAAPI-accelerated H.264/HEVC/MJPEG encoding
34 34
 
35 35
 version 3.0:
36 36
 - Common Encryption (CENC) MP4 encoding and decoding support
... ...
@@ -2395,6 +2395,8 @@ mimic_decoder_select="blockdsp bswapdsp hpeldsp idctdsp"
2395 2395
 mjpeg_decoder_select="blockdsp hpeldsp exif idctdsp jpegtables"
2396 2396
 mjpeg_encoder_select="aandcttables jpegtables mpegvideoenc"
2397 2397
 mjpegb_decoder_select="mjpeg_decoder"
2398
+mjpeg_vaapi_encoder_deps="VAEncPictureParameterBufferJPEG"
2399
+mjpeg_vaapi_encoder_select="vaapi_encode jpegtables"
2398 2400
 mlp_decoder_select="mlp_parser"
2399 2401
 motionpixels_decoder_select="bswapdsp"
2400 2402
 mp1_decoder_select="mpegaudio"
... ...
@@ -5477,6 +5479,7 @@ check_type "va/va.h" "VADecPictureParameterBufferVP9"
5477 5477
 check_type "va/va.h va/va_vpp.h" "VAProcPipelineParameterBuffer"
5478 5478
 check_type "va/va.h va/va_enc_h264.h" "VAEncPictureParameterBufferH264"
5479 5479
 check_type "va/va.h va/va_enc_hevc.h" "VAEncPictureParameterBufferHEVC"
5480
+check_type "va/va.h va/va_enc_jpeg.h" "VAEncPictureParameterBufferJPEG"
5480 5481
 
5481 5482
 check_type "vdpau/vdpau.h" "VdpPictureInfoHEVC"
5482 5483
 
... ...
@@ -367,6 +367,7 @@ OBJS-$(CONFIG_MIMIC_DECODER)           += mimic.o
367 367
 OBJS-$(CONFIG_MJPEG_DECODER)           += mjpegdec.o
368 368
 OBJS-$(CONFIG_MJPEG_ENCODER)           += mjpegenc.o mjpegenc_common.o
369 369
 OBJS-$(CONFIG_MJPEGB_DECODER)          += mjpegbdec.o
370
+OBJS-$(CONFIG_MJPEG_VAAPI_ENCODER)     += vaapi_encode_mjpeg.o
370 371
 OBJS-$(CONFIG_MLP_DECODER)             += mlpdec.o mlpdsp.o
371 372
 OBJS-$(CONFIG_MMVIDEO_DECODER)         += mmvideo.o
372 373
 OBJS-$(CONFIG_MOTIONPIXELS_DECODER)    += motionpixels.o
... ...
@@ -225,6 +225,7 @@ void avcodec_register_all(void)
225 225
     REGISTER_DECODER(MIMIC,             mimic);
226 226
     REGISTER_ENCDEC (MJPEG,             mjpeg);
227 227
     REGISTER_DECODER(MJPEGB,            mjpegb);
228
+    REGISTER_ENCODER(MJPEG_VAAPI,       mjpeg_vaapi);
228 229
     REGISTER_DECODER(MMVIDEO,           mmvideo);
229 230
     REGISTER_DECODER(MOTIONPIXELS,      motionpixels);
230 231
 #if FF_API_XVMC
231 232
new file mode 100644
... ...
@@ -0,0 +1,420 @@
0
+/*
1
+ * This file is part of FFmpeg.
2
+ *
3
+ * FFmpeg is free software; you can redistribute it and/or
4
+ * modify it under the terms of the GNU Lesser General Public
5
+ * License as published by the Free Software Foundation; either
6
+ * version 2.1 of the License, or (at your option) any later version.
7
+ *
8
+ * FFmpeg is distributed in the hope that it will be useful,
9
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
+ * Lesser General Public License for more details.
12
+ *
13
+ * You should have received a copy of the GNU Lesser General Public
14
+ * License along with FFmpeg; if not, write to the Free Software
15
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+ */
17
+
18
+#include <va/va.h>
19
+#include <va/va_enc_jpeg.h>
20
+
21
+#include "libavutil/avassert.h"
22
+#include "libavutil/common.h"
23
+#include "libavutil/internal.h"
24
+#include "libavutil/opt.h"
25
+#include "libavutil/pixfmt.h"
26
+
27
+#include "avcodec.h"
28
+#include "internal.h"
29
+#include "jpegtables.h"
30
+#include "mjpeg.h"
31
+#include "put_bits.h"
32
+#include "vaapi_encode.h"
33
+
34
+
35
+// Standard JPEG quantisation tables, in zigzag order.
36
+static const unsigned char vaapi_encode_mjpeg_quant_luminance[64] = {
37
+    16,  11,  12,  14,  12,  10,  16,  14,
38
+    13,  14,  18,  17,  16,  19,  24,  40,
39
+    26,  24,  22,  22,  24,  49,  35,  37,
40
+    29,  40,  58,  51,  61,  60,  57,  51,
41
+    56,  55,  64,  72,  92,  78,  64,  68,
42
+    87,  69,  55,  56,  80, 109,  81,  87,
43
+    95,  98, 103, 104, 103,  62,  77, 113,
44
+   121, 112, 100, 120,  92, 101, 103,  99,
45
+};
46
+static const unsigned char vaapi_encode_mjpeg_quant_chrominance[64] = {
47
+    17,  18,  18,  24,  21,  24,  47,  26,
48
+    26,  47,  99,  66,  56,  66,  99,  99,
49
+    99,  99,  99,  99,  99,  99,  99,  99,
50
+    99,  99,  99,  99,  99,  99,  99,  99,
51
+    99,  99,  99,  99,  99,  99,  99,  99,
52
+    99,  99,  99,  99,  99,  99,  99,  99,
53
+    99,  99,  99,  99,  99,  99,  99,  99,
54
+    99,  99,  99,  99,  99,  99,  99,  99,
55
+};
56
+
57
+typedef struct VAAPIEncodeMJPEGContext {
58
+    int quality;
59
+    int component_subsample_h[3];
60
+    int component_subsample_v[3];
61
+
62
+    VAQMatrixBufferJPEG quant_tables;
63
+    VAHuffmanTableBufferJPEGBaseline huffman_tables;
64
+} VAAPIEncodeMJPEGContext;
65
+
66
+static av_cold void vaapi_encode_mjpeg_copy_huffman(unsigned char *dst_lengths,
67
+                                                    unsigned char *dst_values,
68
+                                                    const unsigned char *src_lengths,
69
+                                                    const unsigned char *src_values)
70
+{
71
+    int i, mt;
72
+
73
+    ++src_lengths;
74
+
75
+    mt = 0;
76
+    for (i = 0; i < 16; i++)
77
+        mt += (dst_lengths[i] = src_lengths[i]);
78
+
79
+    for (i = 0; i < mt; i++)
80
+        dst_values[i] = src_values[i];
81
+}
82
+
83
+static av_cold void vaapi_encode_mjpeg_init_tables(AVCodecContext *avctx)
84
+{
85
+    VAAPIEncodeContext                *ctx = avctx->priv_data;
86
+    VAAPIEncodeMJPEGContext          *priv = ctx->priv_data;
87
+    VAQMatrixBufferJPEG             *quant = &priv->quant_tables;
88
+    VAHuffmanTableBufferJPEGBaseline *huff = &priv->huffman_tables;
89
+    int i;
90
+
91
+    quant->load_lum_quantiser_matrix = 1;
92
+    quant->load_chroma_quantiser_matrix = 1;
93
+
94
+    for (i = 0; i < 64; i++) {
95
+        quant->lum_quantiser_matrix[i] =
96
+            vaapi_encode_mjpeg_quant_luminance[i];
97
+        quant->chroma_quantiser_matrix[i] =
98
+            vaapi_encode_mjpeg_quant_chrominance[i];
99
+    }
100
+
101
+    huff->load_huffman_table[0] = 1;
102
+    vaapi_encode_mjpeg_copy_huffman(huff->huffman_table[0].num_dc_codes,
103
+                                    huff->huffman_table[0].dc_values,
104
+                                    avpriv_mjpeg_bits_dc_luminance,
105
+                                    avpriv_mjpeg_val_dc);
106
+    vaapi_encode_mjpeg_copy_huffman(huff->huffman_table[0].num_ac_codes,
107
+                                    huff->huffman_table[0].ac_values,
108
+                                    avpriv_mjpeg_bits_ac_luminance,
109
+                                    avpriv_mjpeg_val_ac_luminance);
110
+    memset(huff->huffman_table[0].pad, 0, sizeof(huff->huffman_table[0].pad));
111
+
112
+    huff->load_huffman_table[1] = 1;
113
+    vaapi_encode_mjpeg_copy_huffman(huff->huffman_table[1].num_dc_codes,
114
+                                    huff->huffman_table[1].dc_values,
115
+                                    avpriv_mjpeg_bits_dc_chrominance,
116
+                                    avpriv_mjpeg_val_dc);
117
+    vaapi_encode_mjpeg_copy_huffman(huff->huffman_table[1].num_ac_codes,
118
+                                    huff->huffman_table[1].ac_values,
119
+                                    avpriv_mjpeg_bits_ac_chrominance,
120
+                                    avpriv_mjpeg_val_ac_chrominance);
121
+    memset(huff->huffman_table[1].pad, 0, sizeof(huff->huffman_table[1].pad));
122
+}
123
+
124
+static void vaapi_encode_mjpeg_write_marker(PutBitContext *pbc, int marker)
125
+{
126
+    put_bits(pbc, 8, 0xff);
127
+    put_bits(pbc, 8, marker);
128
+}
129
+
130
+static int vaapi_encode_mjpeg_write_image_header(AVCodecContext *avctx,
131
+                                                 VAAPIEncodePicture *pic,
132
+                                                 VAAPIEncodeSlice *slice,
133
+                                                 char *data, size_t *data_len)
134
+{
135
+    VAAPIEncodeContext               *ctx = avctx->priv_data;
136
+    VAEncPictureParameterBufferJPEG *vpic = pic->codec_picture_params;
137
+    VAEncSliceParameterBufferJPEG *vslice = slice->codec_slice_params;
138
+    VAAPIEncodeMJPEGContext         *priv = ctx->priv_data;
139
+    PutBitContext pbc;
140
+    int t, i, quant_scale;
141
+
142
+    init_put_bits(&pbc, data, *data_len);
143
+
144
+    vaapi_encode_mjpeg_write_marker(&pbc, SOI);
145
+
146
+    // Quantisation table coefficients are scaled for quality by the driver,
147
+    // so we also need to do it ourselves here so that headers match.
148
+    if (priv->quality < 50)
149
+        quant_scale = 5000 / priv->quality;
150
+    else
151
+        quant_scale = 200 - 2 * priv->quality;
152
+
153
+    for (t = 0; t < 2; t++) {
154
+        int q;
155
+
156
+        vaapi_encode_mjpeg_write_marker(&pbc, DQT);
157
+
158
+        put_bits(&pbc, 16, 3 + 64); // Lq
159
+        put_bits(&pbc, 4, 0); // Pq
160
+        put_bits(&pbc, 4, t); // Tq
161
+
162
+        for (i = 0; i < 64; i++) {
163
+            q = i[t ? priv->quant_tables.chroma_quantiser_matrix
164
+                    : priv->quant_tables.lum_quantiser_matrix];
165
+            q = (q * quant_scale) / 100;
166
+            if (q < 1)   q = 1;
167
+            if (q > 255) q = 255;
168
+            put_bits(&pbc, 8, q);
169
+        }
170
+    }
171
+
172
+    vaapi_encode_mjpeg_write_marker(&pbc, SOF0);
173
+
174
+    put_bits(&pbc, 16, 8 + 3 * vpic->num_components); // Lf
175
+    put_bits(&pbc, 8,  vpic->sample_bit_depth); // P
176
+    put_bits(&pbc, 16, vpic->picture_height);   // Y
177
+    put_bits(&pbc, 16, vpic->picture_width);    // X
178
+    put_bits(&pbc, 8,  vpic->num_components);   // Nf
179
+
180
+    for (i = 0; i < vpic->num_components; i++) {
181
+        put_bits(&pbc, 8, vpic->component_id[i]); // Ci
182
+        put_bits(&pbc, 4, priv->component_subsample_h[i]); // Hi
183
+        put_bits(&pbc, 4, priv->component_subsample_v[i]); // Vi
184
+        put_bits(&pbc, 8, vpic->quantiser_table_selector[i]); // Tqi
185
+    }
186
+
187
+    for (t = 0; t < 4; t++) {
188
+        int mt;
189
+        unsigned char *lengths, *values;
190
+
191
+        vaapi_encode_mjpeg_write_marker(&pbc, DHT);
192
+
193
+        if ((t & 1) == 0) {
194
+            lengths = priv->huffman_tables.huffman_table[t / 2].num_dc_codes;
195
+            values  = priv->huffman_tables.huffman_table[t / 2].dc_values;
196
+        } else {
197
+            lengths = priv->huffman_tables.huffman_table[t / 2].num_ac_codes;
198
+            values  = priv->huffman_tables.huffman_table[t / 2].ac_values;
199
+        }
200
+
201
+        mt = 0;
202
+        for (i = 0; i < 16; i++)
203
+            mt += lengths[i];
204
+
205
+        put_bits(&pbc, 16, 2 + 17 + mt); // Lh
206
+        put_bits(&pbc, 4, t & 1); // Tc
207
+        put_bits(&pbc, 4, t / 2); // Th
208
+
209
+        for (i = 0; i < 16; i++)
210
+            put_bits(&pbc, 8, lengths[i]);
211
+        for (i = 0; i < mt; i++)
212
+            put_bits(&pbc, 8, values[i]);
213
+    }
214
+
215
+    vaapi_encode_mjpeg_write_marker(&pbc, SOS);
216
+
217
+    av_assert0(vpic->num_components == vslice->num_components);
218
+
219
+    put_bits(&pbc, 16, 6 + 2 * vslice->num_components); // Ls
220
+    put_bits(&pbc, 8,  vslice->num_components); // Ns
221
+
222
+    for (i = 0; i < vslice->num_components; i++) {
223
+        put_bits(&pbc, 8, vslice->components[i].component_selector); // Csj
224
+        put_bits(&pbc, 4, vslice->components[i].dc_table_selector);  // Tdj
225
+        put_bits(&pbc, 4, vslice->components[i].ac_table_selector);  // Taj
226
+    }
227
+
228
+    put_bits(&pbc, 8, 0); // Ss
229
+    put_bits(&pbc, 8, 63); // Se
230
+    put_bits(&pbc, 4, 0); // Ah
231
+    put_bits(&pbc, 4, 0); // Al
232
+
233
+    *data_len = put_bits_count(&pbc);
234
+    flush_put_bits(&pbc);
235
+
236
+    return 0;
237
+}
238
+
239
+static int vaapi_encode_mjpeg_write_extra_buffer(AVCodecContext *avctx,
240
+                                                 VAAPIEncodePicture *pic,
241
+                                                 int index, int *type,
242
+                                                 char *data, size_t *data_len)
243
+{
244
+    VAAPIEncodeContext       *ctx = avctx->priv_data;
245
+    VAAPIEncodeMJPEGContext *priv = ctx->priv_data;
246
+
247
+    if (index == 0) {
248
+        // Write quantisation tables.
249
+        if (*data_len < sizeof(priv->quant_tables))
250
+            return AVERROR(EINVAL);
251
+        *type = VAQMatrixBufferType;
252
+        memcpy(data, &priv->quant_tables,
253
+               *data_len = sizeof(priv->quant_tables));
254
+
255
+    } else if (index == 1) {
256
+        // Write huffman tables.
257
+        if (*data_len < sizeof(priv->huffman_tables))
258
+            return AVERROR(EINVAL);
259
+        *type = VAHuffmanTableBufferType;
260
+        memcpy(data, &priv->huffman_tables,
261
+               *data_len = sizeof(priv->huffman_tables));
262
+
263
+    } else {
264
+        return AVERROR_EOF;
265
+    }
266
+    return 0;
267
+}
268
+
269
+static int vaapi_encode_mjpeg_init_picture_params(AVCodecContext *avctx,
270
+                                                  VAAPIEncodePicture *pic)
271
+{
272
+    VAAPIEncodeContext               *ctx = avctx->priv_data;
273
+    VAEncPictureParameterBufferJPEG *vpic = pic->codec_picture_params;
274
+    VAAPIEncodeMJPEGContext         *priv = ctx->priv_data;
275
+
276
+    vpic->reconstructed_picture = pic->recon_surface;
277
+    vpic->coded_buf = pic->output_buffer;
278
+
279
+    vpic->picture_width  = ctx->input_width;
280
+    vpic->picture_height = ctx->input_height;
281
+
282
+    vpic->pic_flags.bits.profile      = 0;
283
+    vpic->pic_flags.bits.progressive  = 0;
284
+    vpic->pic_flags.bits.huffman      = 1;
285
+    vpic->pic_flags.bits.interleaved  = 0;
286
+    vpic->pic_flags.bits.differential = 0;
287
+
288
+    vpic->sample_bit_depth = 8;
289
+    vpic->num_scan = 1;
290
+
291
+    vpic->num_components = 3;
292
+
293
+    vpic->component_id[0] = 1;
294
+    vpic->component_id[1] = 2;
295
+    vpic->component_id[2] = 3;
296
+
297
+    priv->component_subsample_h[0] = 2;
298
+    priv->component_subsample_v[0] = 2;
299
+    priv->component_subsample_h[1] = 1;
300
+    priv->component_subsample_v[1] = 1;
301
+    priv->component_subsample_h[2] = 1;
302
+    priv->component_subsample_v[2] = 1;
303
+
304
+    vpic->quantiser_table_selector[0] = 0;
305
+    vpic->quantiser_table_selector[1] = 1;
306
+    vpic->quantiser_table_selector[2] = 1;
307
+
308
+    vpic->quality = priv->quality;
309
+
310
+    pic->nb_slices = 1;
311
+
312
+    return 0;
313
+}
314
+
315
+static int vaapi_encode_mjpeg_init_slice_params(AVCodecContext *avctx,
316
+                                                VAAPIEncodePicture *pic,
317
+                                                VAAPIEncodeSlice *slice)
318
+{
319
+    VAEncPictureParameterBufferJPEG *vpic = pic->codec_picture_params;
320
+    VAEncSliceParameterBufferJPEG *vslice = slice->codec_slice_params;
321
+    int i;
322
+
323
+    vslice->restart_interval = 0;
324
+
325
+    vslice->num_components = vpic->num_components;
326
+    for (i = 0; i < vslice->num_components; i++) {
327
+        vslice->components[i].component_selector = i + 1;
328
+        vslice->components[i].dc_table_selector = (i > 0);
329
+        vslice->components[i].ac_table_selector = (i > 0);
330
+    }
331
+
332
+    return 0;
333
+}
334
+
335
+static VAConfigAttrib vaapi_encode_mjpeg_config_attributes[] = {
336
+    { .type  = VAConfigAttribRTFormat,
337
+      .value = VA_RT_FORMAT_YUV420 },
338
+    { .type  = VAConfigAttribEncPackedHeaders,
339
+      .value = VA_ENC_PACKED_HEADER_SEQUENCE },
340
+};
341
+
342
+static av_cold int vaapi_encode_mjpeg_init_internal(AVCodecContext *avctx)
343
+{
344
+    VAAPIEncodeContext       *ctx = avctx->priv_data;
345
+    VAAPIEncodeMJPEGContext *priv = ctx->priv_data;
346
+
347
+    ctx->va_profile    = VAProfileJPEGBaseline;
348
+    ctx->va_entrypoint = VAEntrypointEncPicture;
349
+
350
+    ctx->input_width    = avctx->width;
351
+    ctx->input_height   = avctx->height;
352
+    ctx->aligned_width  = FFALIGN(ctx->input_width,  8);
353
+    ctx->aligned_height = FFALIGN(ctx->input_height, 8);
354
+
355
+    ctx->config_attributes    = vaapi_encode_mjpeg_config_attributes;
356
+    ctx->nb_config_attributes =
357
+        FF_ARRAY_ELEMS(vaapi_encode_mjpeg_config_attributes);
358
+
359
+    priv->quality = avctx->global_quality;
360
+    if (priv->quality < 1 || priv->quality > 100) {
361
+        av_log(avctx, AV_LOG_ERROR, "Invalid quality value %d "
362
+               "(must be 1-100).\n", priv->quality);
363
+        return AVERROR(EINVAL);
364
+    }
365
+
366
+    vaapi_encode_mjpeg_init_tables(avctx);
367
+
368
+    return 0;
369
+}
370
+
371
+static VAAPIEncodeType vaapi_encode_type_mjpeg = {
372
+    .priv_data_size        = sizeof(VAAPIEncodeMJPEGContext),
373
+
374
+    .init                  = &vaapi_encode_mjpeg_init_internal,
375
+
376
+    .picture_params_size   = sizeof(VAEncPictureParameterBufferJPEG),
377
+    .init_picture_params   = &vaapi_encode_mjpeg_init_picture_params,
378
+
379
+    .slice_params_size     = sizeof(VAEncSliceParameterBufferJPEG),
380
+    .init_slice_params     = &vaapi_encode_mjpeg_init_slice_params,
381
+
382
+    .slice_header_type     = VAEncPackedHeaderRawData,
383
+    .write_slice_header    = &vaapi_encode_mjpeg_write_image_header,
384
+
385
+    .write_extra_buffer    = &vaapi_encode_mjpeg_write_extra_buffer,
386
+};
387
+
388
+static av_cold int vaapi_encode_mjpeg_init(AVCodecContext *avctx)
389
+{
390
+    return ff_vaapi_encode_init(avctx, &vaapi_encode_type_mjpeg);
391
+}
392
+
393
+static const AVCodecDefault vaapi_encode_mjpeg_defaults[] = {
394
+    { "global_quality", "80" },
395
+    { NULL },
396
+};
397
+
398
+static const AVClass vaapi_encode_mjpeg_class = {
399
+    .class_name = "mjpeg_vaapi",
400
+    .item_name  = av_default_item_name,
401
+    .version    = LIBAVUTIL_VERSION_INT,
402
+};
403
+
404
+AVCodec ff_mjpeg_vaapi_encoder = {
405
+    .name           = "mjpeg_vaapi",
406
+    .long_name      = NULL_IF_CONFIG_SMALL("MJPEG (VAAPI)"),
407
+    .type           = AVMEDIA_TYPE_VIDEO,
408
+    .id             = AV_CODEC_ID_MJPEG,
409
+    .priv_data_size = sizeof(VAAPIEncodeContext),
410
+    .init           = &vaapi_encode_mjpeg_init,
411
+    .encode2        = &ff_vaapi_encode2,
412
+    .close          = &ff_vaapi_encode_close,
413
+    .priv_class     = &vaapi_encode_mjpeg_class,
414
+    .defaults       = vaapi_encode_mjpeg_defaults,
415
+    .pix_fmts = (const enum AVPixelFormat[]) {
416
+        AV_PIX_FMT_VAAPI,
417
+        AV_PIX_FMT_NONE,
418
+    },
419
+};