va: Handle input caps change.
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-bad / sys / va / gstjpegdecoder.c
1 /* GStreamer
2  * Copyright (C) 2022 Víctor Jáquez <vjaquez@igalia.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <gst/base/base.h>
25 #include "gstjpegdecoder.h"
26
27 #define MAX_SAMPLE_FACTOR 4     /* JPEG limit on sampling factors */
28 #define DCT_SIZE          8     /* The basic DCT block is 8x8 samples */
29
30 typedef enum
31 {
32   GST_JPEG_DECODER_STATE_GOT_SOI = 1 << 0,
33   GST_JPEG_DECODER_STATE_GOT_SOF = 1 << 1,
34   GST_JPEG_DECODER_STATE_GOT_SOS = 1 << 2,
35   GST_JPEG_DECODER_STATE_GOT_HUF_TABLE = 1 << 3,
36   GST_JPEG_DECODER_STATE_GOT_IQ_TABLE = 1 << 4,
37
38   GST_JPEG_DECODER_STATE_VALID_PICTURE = (GST_JPEG_DECODER_STATE_GOT_SOI |
39       GST_JPEG_DECODER_STATE_GOT_SOF | GST_JPEG_DECODER_STATE_GOT_SOS),
40 } GstJpegDecoderState;
41
42 struct _GstJpegDecoderPrivate
43 {
44   guint state;
45   guint restart_interval;
46   GstJpegHuffmanTables huf_tables;
47   GstJpegQuantTables quant_tables;
48   GstJpegFrameHdr frame_hdr;
49
50   guint8 max_h, max_v;
51   gboolean lossless;
52 };
53
54 GST_DEBUG_CATEGORY (gst_jpeg_decoder_debug);
55 #define GST_CAT_DEFAULT gst_jpeg_decoder_debug
56
57 /**
58  * GstJpegDecoder:
59  *
60  * Base class to implement statelesss JPEG decoders
61  *
62  * Since: 1.22
63  */
64 #define parent_class gst_jpeg_decoder_parent_clas
65 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstJpegDecoder, gst_jpeg_decoder,
66     GST_TYPE_VIDEO_DECODER, G_ADD_PRIVATE (GstJpegDecoder);
67     GST_DEBUG_CATEGORY_INIT (gst_jpeg_decoder_debug, "jpegdecoder", 0,
68         "JPEG Image Decoder"));
69
70 static gboolean gst_jpeg_decoder_set_format (GstVideoDecoder * decoder,
71     GstVideoCodecState * state);
72 static GstFlowReturn gst_jpeg_decoder_handle_frame (GstVideoDecoder * decoder,
73     GstVideoCodecFrame * frame);
74 static gboolean gst_jpeg_decoder_stop (GstVideoDecoder * decoder);
75
76 static void
77 gst_jpeg_decoder_class_init (GstJpegDecoderClass * klass)
78 {
79   GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (klass);
80
81   decoder_class->stop = GST_DEBUG_FUNCPTR (gst_jpeg_decoder_stop);
82   decoder_class->set_format = GST_DEBUG_FUNCPTR (gst_jpeg_decoder_set_format);
83   decoder_class->handle_frame =
84       GST_DEBUG_FUNCPTR (gst_jpeg_decoder_handle_frame);
85
86   gst_type_mark_as_plugin_api (GST_TYPE_JPEG_DECODER, 0);
87 }
88
89 static void
90 gst_jpeg_decoder_init (GstJpegDecoder * self)
91 {
92   gst_video_decoder_set_packetized (GST_VIDEO_DECODER (self), TRUE);
93   self->priv = gst_jpeg_decoder_get_instance_private (self);
94 }
95
96 static gboolean
97 gst_jpeg_decoder_stop (GstVideoDecoder * decoder)
98 {
99   GstJpegDecoder *self = GST_JPEG_DECODER (decoder);
100
101   g_clear_pointer (&self->input_state, gst_video_codec_state_unref);
102
103   return TRUE;
104 }
105
106 static gboolean
107 gst_jpeg_decoder_set_format (GstVideoDecoder * decoder,
108     GstVideoCodecState * state)
109 {
110   GstJpegDecoder *self = GST_JPEG_DECODER (decoder);
111
112   GST_DEBUG_OBJECT (decoder, "Set format");
113
114   if (self->input_state)
115     gst_video_codec_state_unref (self->input_state);
116
117   self->input_state = gst_video_codec_state_ref (state);
118
119   return TRUE;
120 }
121
122 static inline gboolean
123 valid_state (guint state, guint ref_state)
124 {
125   return (state & ref_state) == ref_state;
126 }
127
128 static gboolean
129 decode_huffman_table (GstJpegDecoder * self, GstJpegSegment * seg)
130 {
131   GstJpegDecoderPrivate *priv = self->priv;
132
133   if (!gst_jpeg_segment_parse_huffman_table (seg, &priv->huf_tables)) {
134     GST_ERROR_OBJECT (self, "failed to parse Huffman table");
135     return FALSE;
136   }
137
138   priv->state |= GST_JPEG_DECODER_STATE_GOT_HUF_TABLE;
139   return TRUE;
140 }
141
142 static gboolean
143 decode_quant_table (GstJpegDecoder * self, GstJpegSegment * seg)
144 {
145   GstJpegDecoderPrivate *priv = self->priv;
146
147   if (!gst_jpeg_segment_parse_quantization_table (seg, &priv->quant_tables)) {
148     GST_ERROR_OBJECT (self, "failed to parse quantization table");
149     return FALSE;
150   }
151
152   priv->state |= GST_JPEG_DECODER_STATE_GOT_IQ_TABLE;
153   return TRUE;
154 }
155
156 static gboolean
157 decode_restart_interval (GstJpegDecoder * self, GstJpegSegment * seg)
158 {
159   GstJpegDecoderPrivate *priv = self->priv;
160
161   if (!gst_jpeg_segment_parse_restart_interval (seg, &priv->restart_interval)) {
162     GST_ERROR_OBJECT (self, "failed to parse restart interval");
163     return FALSE;
164   }
165   return TRUE;
166 }
167
168 static GstFlowReturn
169 decode_frame (GstJpegDecoder * self, GstJpegSegment * seg,
170     GstVideoCodecFrame * frame)
171 {
172   GstJpegDecoderPrivate *priv = self->priv;
173   GstJpegDecoderClass *klass = GST_JPEG_DECODER_GET_CLASS (self);
174   GstJpegFrameHdr *frame_hdr = &self->priv->frame_hdr;
175   GstFlowReturn ret = GST_FLOW_OK;
176   guint i;
177
178   if (!gst_jpeg_segment_parse_frame_header (seg, frame_hdr)) {
179     GST_ERROR_OBJECT (self, "failed to parse frame header");
180     return GST_FLOW_ERROR;
181   }
182
183   /* A.1.1 Dimensions and sampling factors */
184   priv->max_h = priv->max_v = 0;
185   for (i = 0; i < frame_hdr->num_components; i++) {
186     if (frame_hdr->components[i].horizontal_factor >= MAX_SAMPLE_FACTOR
187         || frame_hdr->components[i].vertical_factor >= MAX_SAMPLE_FACTOR) {
188       ret = GST_FLOW_ERROR;
189       GST_ERROR_OBJECT (self, "frame header with bad sampling factor");
190       goto beach;
191     }
192
193     priv->max_h = MAX (priv->max_h, frame_hdr->components[i].horizontal_factor);
194     priv->max_v = MAX (priv->max_v, frame_hdr->components[i].vertical_factor);
195   }
196
197   if (priv->max_h == 0 || priv->max_v == 0) {
198     ret = GST_FLOW_ERROR;
199     GST_ERROR_OBJECT (self, "frame header with bad sampling factor");
200     goto beach;
201   }
202
203   priv->lossless = seg->marker == GST_JPEG_MARKER_SOF3;
204
205   g_assert (klass->new_picture);
206   ret = klass->new_picture (self, frame, seg->marker, &priv->frame_hdr);
207   if (ret != GST_FLOW_OK) {
208     GST_WARNING_OBJECT (self, "subclass failed to handle new picture");
209     goto beach;
210   }
211
212   priv->state |= GST_JPEG_DECODER_STATE_GOT_SOF;
213
214 beach:
215   return ret;
216 }
217
218
219 static const GstJpegFrameComponent *
220 get_component (const GstJpegFrameHdr * frame_hdr, guint selector)
221 {
222   guint i;
223
224   for (i = 0; i < frame_hdr->num_components; i++) {
225     const GstJpegFrameComponent *fcp = &frame_hdr->components[i];
226     if (fcp->identifier == selector)
227       return fcp;
228   }
229   return NULL;
230 }
231
232 static GstFlowReturn
233 decode_scan (GstJpegDecoder * self, GstJpegSegment * seg)
234 {
235   GstJpegDecoderPrivate *priv = self->priv;
236   GstJpegDecoderClass *klass = GST_JPEG_DECODER_GET_CLASS (self);
237   GstJpegDecoderScan scan;
238   GstJpegScanHdr scan_hdr;
239   GstFlowReturn ret;
240   const guint8 *data;
241   guint size, scan_hdr_size;
242   guint64 mcus_per_row, mcu_rows_in_scan;
243   guint blocksize = priv->lossless ? 1 : DCT_SIZE;
244
245   /* E.2.3 Control procedure for decoding a scan */
246   if (!valid_state (priv->state, GST_JPEG_DECODER_STATE_GOT_SOF))
247     return GST_FLOW_OK;         /* ignore segment */
248
249   if (!gst_jpeg_segment_parse_scan_header (seg, &scan_hdr)) {
250     GST_ERROR_OBJECT (self, "failed to parse scan header");
251     return GST_FLOW_ERROR;
252   }
253
254   if (!valid_state (priv->state, GST_JPEG_DECODER_STATE_GOT_HUF_TABLE))
255     gst_jpeg_get_default_huffman_tables (&priv->huf_tables);
256
257   if (!valid_state (priv->state, GST_JPEG_DECODER_STATE_GOT_IQ_TABLE))
258     gst_jpeg_get_default_quantization_tables (&priv->quant_tables);
259
260   /* Non-interleaved */
261   if (scan_hdr.num_components == 1) {
262     const guint cs = scan_hdr.components[0].component_selector;
263     const GstJpegFrameComponent *fc = get_component (&priv->frame_hdr, cs);
264
265     if (!fc || fc->horizontal_factor == 0 || fc->vertical_factor == 0) {
266       GST_ERROR_OBJECT (self, "failed to validate frame component %u", cs);
267       return GST_FLOW_ERROR;
268     }
269
270     mcus_per_row = gst_util_uint64_scale_int_ceil (priv->frame_hdr.width,
271         fc->horizontal_factor, priv->max_h * blocksize);
272     mcu_rows_in_scan = gst_util_uint64_scale_int_ceil (priv->frame_hdr.height,
273         fc->vertical_factor, priv->max_v * blocksize);
274   } else {
275     mcus_per_row = gst_util_uint64_scale_int_ceil (priv->frame_hdr.width, 1,
276         priv->max_h * blocksize);
277     mcu_rows_in_scan =
278         gst_util_uint64_scale_int_ceil (priv->frame_hdr.height, 1,
279         priv->max_v * blocksize);
280   }
281
282   scan_hdr_size = (seg->data[seg->offset] << 8) | seg->data[seg->offset + 1];
283   size = seg->size - scan_hdr_size;
284   data = seg->data + seg->offset + scan_hdr_size;
285
286   if (size <= 0)
287     return GST_FLOW_ERROR;
288
289   /* *INDENT-OFF* */
290   scan = (GstJpegDecoderScan) {
291     .scan_hdr = &scan_hdr,
292     .huffman_tables = &priv->huf_tables,
293     .quantization_tables = &priv->quant_tables,
294     .restart_interval = priv->restart_interval,
295     .mcus_per_row = mcus_per_row,
296     .mcu_rows_in_scan = mcu_rows_in_scan,
297   };
298   /* *INDENT-ON* */
299
300   g_assert (klass->decode_scan);
301   ret = klass->decode_scan (self, &scan, data, size);
302
303   if (ret == GST_FLOW_OK)
304     priv->state |= GST_JPEG_DECODER_STATE_GOT_SOS;
305
306   return ret;
307 }
308
309 #ifndef GST_DISABLE_GST_DEBUG
310 static const char *
311 _get_marker_name (guint marker)
312 {
313 #define MARKERS(V)                              \
314   V (SOF0)                                      \
315     V (SOF1)                                    \
316     V (SOF2)                                    \
317     V (SOF3)                                    \
318     V (SOF5)                                    \
319     V (SOF6)                                    \
320     V (SOF7)                                    \
321     V (SOF9)                                    \
322     V (SOF10)                                   \
323     V (SOF11)                                   \
324     V (SOF13)                                   \
325     V (SOF14)                                   \
326     V (SOF15)                                   \
327     V (DHT)                                     \
328     V (DAC)                                     \
329     V (RST0)                                    \
330     V (RST1)                                    \
331     V (RST2)                                    \
332     V (RST3)                                    \
333     V (RST4)                                    \
334     V (RST5)                                    \
335     V (RST6)                                    \
336     V (RST7)                                    \
337     V (SOI)                                     \
338     V (EOI)                                     \
339     V (SOS)                                     \
340     V (DQT)                                     \
341     V (DNL)                                     \
342     V (DRI)                                     \
343     V (APP0)                                    \
344     V (APP1)                                    \
345     V (APP2)                                    \
346     V (APP3)                                    \
347     V (APP4)                                    \
348     V (APP5)                                    \
349     V (APP6)                                    \
350     V (APP7)                                    \
351     V (APP8)                                    \
352     V (APP9)                                    \
353     V (APP10)                                   \
354     V (APP11)                                   \
355     V (APP12)                                   \
356     V (APP13)                                   \
357     V (APP14)                                   \
358     V (APP15)                                   \
359     V (COM)
360 #define CASE(marker) case G_PASTE(GST_JPEG_MARKER_, marker): return G_STRINGIFY (marker);
361   switch (marker) {
362       MARKERS (CASE)
363     default:
364       return "Unknown";
365   }
366 #undef CASE
367 #undef MARKERS
368 }
369 #endif
370
371 static GstFlowReturn
372 gst_jpeg_decoder_handle_frame (GstVideoDecoder * decoder,
373     GstVideoCodecFrame * frame)
374 {
375   GstJpegDecoder *self = GST_JPEG_DECODER (decoder);
376   GstJpegDecoderPrivate *priv = self->priv;
377   GstJpegDecoderClass *klass = GST_JPEG_DECODER_GET_CLASS (self);
378   GstBuffer *in_buf = frame->input_buffer;
379   GstFlowReturn ret = GST_FLOW_OK;
380   GstMapInfo map;
381   GstJpegMarker marker;
382   GstJpegSegment seg;
383   guint offset = 0;
384
385   GST_LOG_OBJECT (self, "handle frame %" GST_PTR_FORMAT, in_buf);
386
387   if (!gst_buffer_map (in_buf, &map, GST_MAP_READ)) {
388     GST_ERROR_OBJECT (self, "Cannot map input buffer");
389     ret = GST_FLOW_ERROR;
390     goto error;
391   }
392
393   priv->state = 0;
394
395   /* E.2.1 Control procedure for decoding compressed image data */
396   while (offset < map.size) {
397     if (!gst_jpeg_parse (&seg, map.data, map.size, offset))
398       goto unmap_and_error;
399
400     offset = seg.offset + seg.size;
401     marker = seg.marker;
402
403     if (!valid_state (priv->state, GST_JPEG_DECODER_STATE_GOT_SOI)
404         && marker != GST_JPEG_MARKER_SOI)
405       goto unmap_and_error;
406
407     GST_LOG_OBJECT (self, "marker %s: %" G_GSIZE_FORMAT,
408         _get_marker_name (marker), seg.size);
409
410     switch (marker) {
411
412         /* Start of Image */
413       case GST_JPEG_MARKER_SOI:
414         priv->state |= GST_JPEG_DECODER_STATE_GOT_SOI;
415         priv->restart_interval = 0;
416         break;
417
418         /* End of Image */
419       case GST_JPEG_MARKER_EOI:
420         if (!valid_state (priv->state, GST_JPEG_DECODER_STATE_VALID_PICTURE))
421           goto unmap_and_error;
422
423         g_assert (klass->end_picture);
424         ret = klass->end_picture (self);
425         if (ret != GST_FLOW_OK)
426           goto unmap_and_error;
427
428         priv->state = 0;
429
430         gst_buffer_unmap (in_buf, &map);
431
432         GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
433
434         g_assert (klass->output_picture);
435         return klass->output_picture (self, frame);
436
437         /* Start of Scan */
438       case GST_JPEG_MARKER_SOS:{
439         /* get whole scan + ECSs, with RSTi */
440         GstJpegSegment seg_scan;
441
442         for (;;) {
443           if (!gst_jpeg_parse (&seg_scan, map.data, map.size, offset))
444             goto unmap_and_error;
445
446           if (seg_scan.marker < GST_JPEG_MARKER_RST_MIN
447               || seg_scan.marker > GST_JPEG_MARKER_RST_MAX)
448             break;
449
450           offset = seg_scan.offset + seg_scan.size;
451         }
452
453         offset = seg_scan.offset - 2;
454         seg.size = offset - seg.offset;
455
456         ret = decode_scan (self, &seg);
457         if (ret != GST_FLOW_OK)
458           goto unmap_and_error;
459
460         break;
461       }
462
463         /* Interpret markers */
464       case GST_JPEG_MARKER_DAC:
465         /* FIXME: Annex D - Arithmetic coding */
466         GST_FIXME_OBJECT (self, "Arithmetic coding mode unsupported");
467         goto unmap_and_error;
468       case GST_JPEG_MARKER_DHT:
469         if (!decode_huffman_table (self, &seg)) {
470           ret = GST_FLOW_ERROR;
471           goto unmap_and_error;
472         }
473         break;
474       case GST_JPEG_MARKER_DQT:
475         if (!decode_quant_table (self, &seg)) {
476           ret = GST_FLOW_ERROR;
477           goto unmap_and_error;
478         }
479         break;
480
481       case GST_JPEG_MARKER_DRI:
482         if (!(valid_state (priv->state, GST_JPEG_DECODER_STATE_GOT_SOS)
483                 && decode_restart_interval (self, &seg)))
484           goto unmap_and_error;
485         break;
486       case GST_JPEG_MARKER_DNL:
487         break;
488       default:
489         /* SOFn (Start Of Frame) */
490         if (marker >= GST_JPEG_MARKER_SOF_MIN &&
491             marker <= GST_JPEG_MARKER_SOF_MAX) {
492           ret = decode_frame (self, &seg, frame);
493           if (ret != GST_FLOW_OK)
494             goto unmap_and_error;
495         }
496         break;
497     }
498   }
499
500   ret = GST_FLOW_ERROR;
501
502 unmap_and_error:
503   {
504     gst_buffer_unmap (in_buf, &map);
505     goto error;
506   }
507
508 error:
509   {
510     if (ret == GST_FLOW_ERROR) {
511       GST_VIDEO_DECODER_ERROR (self, 1, STREAM, DECODE,
512           ("Failed to decode data"), (NULL), ret);
513     }
514
515     gst_video_decoder_drop_frame (decoder, frame);
516
517     return ret;
518   }
519 }