• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <va/va.h>
20 #include <va/va_enc_jpeg.h>
21 
22 #include "libavutil/avassert.h"
23 #include "libavutil/common.h"
24 #include "libavutil/internal.h"
25 #include "libavutil/opt.h"
26 #include "libavutil/pixdesc.h"
27 
28 #include "avcodec.h"
29 #include "bytestream.h"
30 #include "cbs.h"
31 #include "cbs_jpeg.h"
32 #include "internal.h"
33 #include "jpegtables.h"
34 #include "mjpeg.h"
35 #include "put_bits.h"
36 #include "vaapi_encode.h"
37 
38 
39 // Standard JPEG quantisation tables, in zigzag order.
40 static const unsigned char vaapi_encode_mjpeg_quant_luminance[64] = {
41     16,  11,  12,  14,  12,  10,  16,  14,
42     13,  14,  18,  17,  16,  19,  24,  40,
43     26,  24,  22,  22,  24,  49,  35,  37,
44     29,  40,  58,  51,  61,  60,  57,  51,
45     56,  55,  64,  72,  92,  78,  64,  68,
46     87,  69,  55,  56,  80, 109,  81,  87,
47     95,  98, 103, 104, 103,  62,  77, 113,
48    121, 112, 100, 120,  92, 101, 103,  99,
49 };
50 static const unsigned char vaapi_encode_mjpeg_quant_chrominance[64] = {
51     17,  18,  18,  24,  21,  24,  47,  26,
52     26,  47,  99,  66,  56,  66,  99,  99,
53     99,  99,  99,  99,  99,  99,  99,  99,
54     99,  99,  99,  99,  99,  99,  99,  99,
55     99,  99,  99,  99,  99,  99,  99,  99,
56     99,  99,  99,  99,  99,  99,  99,  99,
57     99,  99,  99,  99,  99,  99,  99,  99,
58     99,  99,  99,  99,  99,  99,  99,  99,
59 };
60 
61 typedef struct VAAPIEncodeMJPEGContext {
62     VAAPIEncodeContext common;
63 
64     // User options.
65     int jfif;
66     int huffman;
67 
68     // Derived settings.
69     int quality;
70     uint8_t jfif_data[14];
71 
72     // Writer structures.
73     JPEGRawFrameHeader     frame_header;
74     JPEGRawScan            scan;
75     JPEGRawApplicationData jfif_header;
76     JPEGRawQuantisationTableSpecification quant_tables;
77     JPEGRawHuffmanTableSpecification      huffman_tables;
78 
79     CodedBitstreamContext *cbc;
80     CodedBitstreamFragment current_fragment;
81 } VAAPIEncodeMJPEGContext;
82 
vaapi_encode_mjpeg_write_image_header(AVCodecContext * avctx,VAAPIEncodePicture * pic,VAAPIEncodeSlice * slice,char * data,size_t * data_len)83 static int vaapi_encode_mjpeg_write_image_header(AVCodecContext *avctx,
84                                                  VAAPIEncodePicture *pic,
85                                                  VAAPIEncodeSlice *slice,
86                                                  char *data, size_t *data_len)
87 {
88     VAAPIEncodeMJPEGContext *priv = avctx->priv_data;
89     CodedBitstreamFragment  *frag = &priv->current_fragment;
90     int err;
91 
92     if (priv->jfif) {
93         err = ff_cbs_insert_unit_content(frag, -1,
94                                          JPEG_MARKER_APPN + 0,
95                                          &priv->jfif_header, NULL);
96         if (err < 0)
97             goto fail;
98     }
99 
100     err = ff_cbs_insert_unit_content(frag, -1,
101                                      JPEG_MARKER_DQT,
102                                      &priv->quant_tables, NULL);
103     if (err < 0)
104         goto fail;
105 
106     err = ff_cbs_insert_unit_content(frag, -1,
107                                      JPEG_MARKER_SOF0,
108                                      &priv->frame_header, NULL);
109     if (err < 0)
110         goto fail;
111 
112     if (priv->huffman) {
113         err = ff_cbs_insert_unit_content(frag, -1,
114                                          JPEG_MARKER_DHT,
115                                          &priv->huffman_tables, NULL);
116         if (err < 0)
117             goto fail;
118     }
119 
120     err = ff_cbs_insert_unit_content(frag, -1,
121                                      JPEG_MARKER_SOS,
122                                      &priv->scan, NULL);
123     if (err < 0)
124         goto fail;
125 
126     err = ff_cbs_write_fragment_data(priv->cbc, frag);
127     if (err < 0) {
128         av_log(avctx, AV_LOG_ERROR, "Failed to write image header.\n");
129         goto fail;
130     }
131 
132     if (*data_len < 8 * frag->data_size) {
133         av_log(avctx, AV_LOG_ERROR, "Image header too large: "
134                "%zu < %zu.\n", *data_len, 8 * frag->data_size);
135         err = AVERROR(ENOSPC);
136         goto fail;
137     }
138 
139     // Remove the EOI at the end of the fragment.
140     memcpy(data, frag->data, frag->data_size - 2);
141     *data_len = 8 * (frag->data_size - 2);
142 
143     err = 0;
144 fail:
145     ff_cbs_fragment_reset(frag);
146     return err;
147 }
148 
vaapi_encode_mjpeg_write_extra_buffer(AVCodecContext * avctx,VAAPIEncodePicture * pic,int index,int * type,char * data,size_t * data_len)149 static int vaapi_encode_mjpeg_write_extra_buffer(AVCodecContext *avctx,
150                                                  VAAPIEncodePicture *pic,
151                                                  int index, int *type,
152                                                  char *data, size_t *data_len)
153 {
154     VAAPIEncodeMJPEGContext *priv = avctx->priv_data;
155     int t, i, k;
156 
157     if (index == 0) {
158         // Write quantisation tables.
159         JPEGRawFrameHeader                     *fh = &priv->frame_header;
160         JPEGRawQuantisationTableSpecification *dqt = &priv->quant_tables;
161         VAQMatrixBufferJPEG *quant;
162 
163         if (*data_len < sizeof(*quant))
164             return AVERROR(ENOSPC);
165         *type     = VAQMatrixBufferType;
166         *data_len = sizeof(*quant);
167 
168         quant = (VAQMatrixBufferJPEG*)data;
169         memset(quant, 0, sizeof(*quant));
170 
171         quant->load_lum_quantiser_matrix = 1;
172         for (i = 0; i < 64; i++)
173             quant->lum_quantiser_matrix[i] = dqt->table[fh->Tq[0]].Q[i];
174 
175         if (fh->Nf > 1) {
176             quant->load_chroma_quantiser_matrix = 1;
177             for (i = 0; i < 64; i++)
178                 quant->chroma_quantiser_matrix[i] =
179                     dqt->table[fh->Tq[1]].Q[i];
180         }
181 
182     } else if (index == 1) {
183         // Write huffman tables.
184         JPEGRawScanHeader                 *sh = &priv->scan.header;
185         JPEGRawHuffmanTableSpecification *dht = &priv->huffman_tables;
186         VAHuffmanTableBufferJPEGBaseline *huff;
187 
188         if (*data_len < sizeof(*huff))
189             return AVERROR(ENOSPC);
190         *type     = VAHuffmanTableBufferType;
191         *data_len = sizeof(*huff);
192 
193         huff = (VAHuffmanTableBufferJPEGBaseline*)data;
194         memset(huff, 0, sizeof(*huff));
195 
196         for (t = 0; t < 1 + (sh->Ns > 1); t++) {
197             const JPEGRawHuffmanTable *ht;
198 
199             huff->load_huffman_table[t] = 1;
200 
201             ht = &dht->table[2 * t];
202             for (i = k = 0; i < 16; i++)
203                 k += (huff->huffman_table[t].num_dc_codes[i] = ht->L[i]);
204             av_assert0(k <= sizeof(huff->huffman_table[t].dc_values));
205             for (i = 0; i < k; i++)
206                 huff->huffman_table[t].dc_values[i] = ht->V[i];
207 
208             ht = &dht->table[2 * t + 1];
209             for (i = k = 0; i < 16; i++)
210                 k += (huff->huffman_table[t].num_ac_codes[i] = ht->L[i]);
211             av_assert0(k <= sizeof(huff->huffman_table[t].ac_values));
212             for (i = 0; i < k; i++)
213                 huff->huffman_table[t].ac_values[i] = ht->V[i];
214         }
215 
216     } else {
217         return AVERROR_EOF;
218     }
219     return 0;
220 }
221 
vaapi_encode_mjpeg_init_picture_params(AVCodecContext * avctx,VAAPIEncodePicture * pic)222 static int vaapi_encode_mjpeg_init_picture_params(AVCodecContext *avctx,
223                                                   VAAPIEncodePicture *pic)
224 {
225     VAAPIEncodeMJPEGContext         *priv = avctx->priv_data;
226     JPEGRawFrameHeader                *fh = &priv->frame_header;
227     JPEGRawScanHeader                 *sh = &priv->scan.header;
228     VAEncPictureParameterBufferJPEG *vpic = pic->codec_picture_params;
229     const AVPixFmtDescriptor *desc;
230     const uint8_t components_rgb[3] = { 'R', 'G', 'B' };
231     const uint8_t components_yuv[3] = {  1,   2,   3  };
232     const uint8_t *components;
233     int t, i, quant_scale, len;
234 
235     av_assert0(pic->type == PICTURE_TYPE_IDR);
236 
237     desc = av_pix_fmt_desc_get(priv->common.input_frames->sw_format);
238     av_assert0(desc);
239     if (desc->flags & AV_PIX_FMT_FLAG_RGB)
240         components = components_rgb;
241     else
242         components = components_yuv;
243 
244     // Frame header.
245 
246     fh->P  = 8;
247     fh->Y  = avctx->height;
248     fh->X  = avctx->width;
249     fh->Nf = desc->nb_components;
250 
251     for (i = 0; i < fh->Nf; i++) {
252         fh->C[i] = components[i];
253         fh->H[i] = 1 + (i == 0 ? desc->log2_chroma_w : 0);
254         fh->V[i] = 1 + (i == 0 ? desc->log2_chroma_h : 0);
255 
256         fh->Tq[i] = !!i;
257     }
258 
259     fh->Lf = 8 + 3 * fh->Nf;
260 
261     // JFIF header.
262     if (priv->jfif) {
263         JPEGRawApplicationData *app = &priv->jfif_header;
264         AVRational sar = pic->input_image->sample_aspect_ratio;
265         int sar_w, sar_h;
266         PutByteContext pbc;
267 
268         bytestream2_init_writer(&pbc, priv->jfif_data,
269                                 sizeof(priv->jfif_data));
270 
271         bytestream2_put_buffer(&pbc, "JFIF", 5);
272         bytestream2_put_be16(&pbc, 0x0102);
273         bytestream2_put_byte(&pbc, 0);
274 
275         av_reduce(&sar_w, &sar_h, sar.num, sar.den, 65535);
276         if (sar_w && sar_h) {
277             bytestream2_put_be16(&pbc, sar_w);
278             bytestream2_put_be16(&pbc, sar_h);
279         } else {
280             bytestream2_put_be16(&pbc, 1);
281             bytestream2_put_be16(&pbc, 1);
282         }
283 
284         bytestream2_put_byte(&pbc, 0);
285         bytestream2_put_byte(&pbc, 0);
286 
287         av_assert0(bytestream2_get_bytes_left_p(&pbc) == 0);
288 
289         app->Lp     = 2 + sizeof(priv->jfif_data);
290         app->Ap     = priv->jfif_data;
291         app->Ap_ref = NULL;
292     }
293 
294     // Quantisation tables.
295 
296     if (priv->quality < 50)
297         quant_scale = 5000 / priv->quality;
298     else
299         quant_scale = 200 - 2 * priv->quality;
300 
301     len = 2;
302 
303     for (t = 0; t < 1 + (fh->Nf > 1); t++) {
304         JPEGRawQuantisationTable *quant = &priv->quant_tables.table[t];
305         const uint8_t *data = t == 0 ?
306             vaapi_encode_mjpeg_quant_luminance :
307             vaapi_encode_mjpeg_quant_chrominance;
308 
309         quant->Pq = 0;
310         quant->Tq = t;
311         for (i = 0; i < 64; i++)
312             quant->Q[i] = av_clip(data[i] * quant_scale / 100, 1, 255);
313 
314         len += 65;
315     }
316 
317     priv->quant_tables.Lq = len;
318 
319     // Huffman tables.
320 
321     len = 2;
322 
323     for (t = 0; t < 2 + 2 * (fh->Nf > 1); t++) {
324         JPEGRawHuffmanTable *huff = &priv->huffman_tables.table[t];
325         const uint8_t *lengths, *values;
326         int k;
327 
328         switch (t) {
329         case 0:
330             lengths = avpriv_mjpeg_bits_dc_luminance + 1;
331             values  = avpriv_mjpeg_val_dc;
332             break;
333         case 1:
334             lengths = avpriv_mjpeg_bits_ac_luminance + 1;
335             values  = avpriv_mjpeg_val_ac_luminance;
336             break;
337         case 2:
338             lengths = avpriv_mjpeg_bits_dc_chrominance + 1;
339             values  = avpriv_mjpeg_val_dc;
340             break;
341         case 3:
342             lengths = avpriv_mjpeg_bits_ac_chrominance + 1;
343             values  = avpriv_mjpeg_val_ac_chrominance;
344             break;
345         }
346 
347         huff->Tc = t % 2;
348         huff->Th = t / 2;
349 
350         for (i = k = 0; i < 16; i++)
351             k += (huff->L[i] = lengths[i]);
352 
353         for (i = 0; i < k; i++)
354             huff->V[i] = values[i];
355 
356         len += 17 + k;
357     }
358 
359     priv->huffman_tables.Lh = len;
360 
361     // Scan header.
362 
363     sh->Ns = fh->Nf;
364 
365     for (i = 0; i < fh->Nf; i++) {
366         sh->Cs[i] = fh->C[i];
367         sh->Td[i] = i > 0;
368         sh->Ta[i] = i > 0;
369     }
370 
371     sh->Ss = 0;
372     sh->Se = 63;
373     sh->Ah = 0;
374     sh->Al = 0;
375 
376     sh->Ls = 6 + 2 * sh->Ns;
377 
378 
379     *vpic = (VAEncPictureParameterBufferJPEG) {
380         .reconstructed_picture = pic->recon_surface,
381         .coded_buf             = pic->output_buffer,
382 
383         .picture_width  = fh->X,
384         .picture_height = fh->Y,
385 
386         .pic_flags.bits = {
387             .profile      = 0,
388             .progressive  = 0,
389             .huffman      = 1,
390             .interleaved  = 0,
391             .differential = 0,
392         },
393 
394         .sample_bit_depth = fh->P,
395         .num_scan         = 1,
396         .num_components   = fh->Nf,
397 
398         // The driver modifies the provided quantisation tables according
399         // to this quality value; the middle value of 50 makes that the
400         // identity so that they are used unchanged.
401         .quality = 50,
402     };
403 
404     for (i = 0; i < fh->Nf; i++) {
405         vpic->component_id[i]             = fh->C[i];
406         vpic->quantiser_table_selector[i] = fh->Tq[i];
407     }
408 
409     pic->nb_slices = 1;
410 
411     return 0;
412 }
413 
vaapi_encode_mjpeg_init_slice_params(AVCodecContext * avctx,VAAPIEncodePicture * pic,VAAPIEncodeSlice * slice)414 static int vaapi_encode_mjpeg_init_slice_params(AVCodecContext *avctx,
415                                                 VAAPIEncodePicture *pic,
416                                                 VAAPIEncodeSlice *slice)
417 {
418     VAAPIEncodeMJPEGContext         *priv = avctx->priv_data;
419     JPEGRawScanHeader                 *sh = &priv->scan.header;
420     VAEncSliceParameterBufferJPEG *vslice = slice->codec_slice_params;
421     int i;
422 
423     *vslice = (VAEncSliceParameterBufferJPEG) {
424         .restart_interval = 0,
425         .num_components   = sh->Ns,
426     };
427 
428     for (i = 0; i < sh->Ns; i++) {
429         vslice->components[i].component_selector = sh->Cs[i];
430         vslice->components[i].dc_table_selector  = sh->Td[i];
431         vslice->components[i].ac_table_selector  = sh->Ta[i];
432     }
433 
434     return 0;
435 }
436 
vaapi_encode_mjpeg_configure(AVCodecContext * avctx)437 static av_cold int vaapi_encode_mjpeg_configure(AVCodecContext *avctx)
438 {
439     VAAPIEncodeContext       *ctx = avctx->priv_data;
440     VAAPIEncodeMJPEGContext *priv = avctx->priv_data;
441     int err;
442 
443     priv->quality = ctx->rc_quality;
444     if (priv->quality < 1 || priv->quality > 100) {
445         av_log(avctx, AV_LOG_ERROR, "Invalid quality value %d "
446                "(must be 1-100).\n", priv->quality);
447         return AVERROR(EINVAL);
448     }
449 
450     // Hack: the implementation calls the JPEG image header (which we
451     // will use in the same way as a slice header) generic "raw data".
452     // Therefore, if after the packed header capability check we have
453     // PACKED_HEADER_RAW_DATA available, rewrite it as
454     // PACKED_HEADER_SLICE so that the header-writing code can do the
455     // right thing.
456     if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_RAW_DATA) {
457         ctx->va_packed_headers &= ~VA_ENC_PACKED_HEADER_RAW_DATA;
458         ctx->va_packed_headers |=  VA_ENC_PACKED_HEADER_SLICE;
459     }
460 
461     err = ff_cbs_init(&priv->cbc, AV_CODEC_ID_MJPEG, avctx);
462     if (err < 0)
463         return err;
464 
465     return 0;
466 }
467 
468 static const VAAPIEncodeProfile vaapi_encode_mjpeg_profiles[] = {
469     { FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT,
470             8, 1, 0, 0, VAProfileJPEGBaseline },
471     { FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT,
472             8, 3, 1, 1, VAProfileJPEGBaseline },
473     { FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT,
474             8, 3, 1, 0, VAProfileJPEGBaseline },
475     { FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT,
476             8, 3, 0, 0, VAProfileJPEGBaseline },
477     { FF_PROFILE_UNKNOWN }
478 };
479 
480 static const VAAPIEncodeType vaapi_encode_type_mjpeg = {
481     .profiles              = vaapi_encode_mjpeg_profiles,
482 
483     .flags                 = FLAG_CONSTANT_QUALITY_ONLY |
484                              FLAG_INTRA_ONLY,
485 
486     .configure             = &vaapi_encode_mjpeg_configure,
487 
488     .default_quality       = 80,
489 
490     .picture_params_size   = sizeof(VAEncPictureParameterBufferJPEG),
491     .init_picture_params   = &vaapi_encode_mjpeg_init_picture_params,
492 
493     .slice_params_size     = sizeof(VAEncSliceParameterBufferJPEG),
494     .init_slice_params     = &vaapi_encode_mjpeg_init_slice_params,
495 
496     .slice_header_type     = VAEncPackedHeaderRawData,
497     .write_slice_header    = &vaapi_encode_mjpeg_write_image_header,
498 
499     .write_extra_buffer    = &vaapi_encode_mjpeg_write_extra_buffer,
500 };
501 
vaapi_encode_mjpeg_init(AVCodecContext * avctx)502 static av_cold int vaapi_encode_mjpeg_init(AVCodecContext *avctx)
503 {
504     VAAPIEncodeContext *ctx = avctx->priv_data;
505 
506     ctx->codec = &vaapi_encode_type_mjpeg;
507 
508     // The JPEG image header - see note above.
509     ctx->desired_packed_headers =
510         VA_ENC_PACKED_HEADER_RAW_DATA;
511 
512     ctx->surface_width  = FFALIGN(avctx->width,  8);
513     ctx->surface_height = FFALIGN(avctx->height, 8);
514 
515     return ff_vaapi_encode_init(avctx);
516 }
517 
vaapi_encode_mjpeg_close(AVCodecContext * avctx)518 static av_cold int vaapi_encode_mjpeg_close(AVCodecContext *avctx)
519 {
520     VAAPIEncodeMJPEGContext *priv = avctx->priv_data;
521 
522     ff_cbs_fragment_free(&priv->current_fragment);
523     ff_cbs_close(&priv->cbc);
524 
525     return ff_vaapi_encode_close(avctx);
526 }
527 
528 #define OFFSET(x) offsetof(VAAPIEncodeMJPEGContext, x)
529 #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
530 static const AVOption vaapi_encode_mjpeg_options[] = {
531     VAAPI_ENCODE_COMMON_OPTIONS,
532 
533     { "jfif", "Include JFIF header",
534       OFFSET(jfif), AV_OPT_TYPE_BOOL,
535       { .i64 = 0 }, 0, 1, FLAGS },
536     { "huffman", "Include huffman tables",
537       OFFSET(huffman), AV_OPT_TYPE_BOOL,
538       { .i64 = 1 }, 0, 1, FLAGS },
539 
540     { NULL },
541 };
542 
543 static const AVCodecDefault vaapi_encode_mjpeg_defaults[] = {
544     { "b",              "0"  },
545     { NULL },
546 };
547 
548 static const AVClass vaapi_encode_mjpeg_class = {
549     .class_name = "mjpeg_vaapi",
550     .item_name  = av_default_item_name,
551     .option     = vaapi_encode_mjpeg_options,
552     .version    = LIBAVUTIL_VERSION_INT,
553 };
554 
555 AVCodec ff_mjpeg_vaapi_encoder = {
556     .name           = "mjpeg_vaapi",
557     .long_name      = NULL_IF_CONFIG_SMALL("MJPEG (VAAPI)"),
558     .type           = AVMEDIA_TYPE_VIDEO,
559     .id             = AV_CODEC_ID_MJPEG,
560     .priv_data_size = sizeof(VAAPIEncodeMJPEGContext),
561     .init           = &vaapi_encode_mjpeg_init,
562     .receive_packet = &ff_vaapi_encode_receive_packet,
563     .close          = &vaapi_encode_mjpeg_close,
564     .priv_class     = &vaapi_encode_mjpeg_class,
565     .capabilities   = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DR1,
566     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
567     .defaults       = vaapi_encode_mjpeg_defaults,
568     .pix_fmts = (const enum AVPixelFormat[]) {
569         AV_PIX_FMT_VAAPI,
570         AV_PIX_FMT_NONE,
571     },
572     .hw_configs     = ff_vaapi_encode_hw_configs,
573     .wrapper_name   = "vaapi",
574 };
575