2 * Copyright (C) 2022 Víctor Jáquez <vjaquez@igalia.com>
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.
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.
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.
24 #include <gst/base/base.h>
25 #include "gstjpegdecoder.h"
27 #define MAX_SAMPLE_FACTOR 4 /* JPEG limit on sampling factors */
28 #define DCT_SIZE 8 /* The basic DCT block is 8x8 samples */
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,
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;
42 struct _GstJpegDecoderPrivate
45 guint restart_interval;
46 GstJpegHuffmanTables huf_tables;
47 GstJpegQuantTables quant_tables;
48 GstJpegFrameHdr frame_hdr;
54 GST_DEBUG_CATEGORY (gst_jpeg_decoder_debug);
55 #define GST_CAT_DEFAULT gst_jpeg_decoder_debug
60 * Base class to implement statelesss JPEG decoders
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"));
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);
77 gst_jpeg_decoder_class_init (GstJpegDecoderClass * klass)
79 GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (klass);
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);
86 gst_type_mark_as_plugin_api (GST_TYPE_JPEG_DECODER, 0);
90 gst_jpeg_decoder_init (GstJpegDecoder * self)
92 gst_video_decoder_set_packetized (GST_VIDEO_DECODER (self), TRUE);
93 self->priv = gst_jpeg_decoder_get_instance_private (self);
97 gst_jpeg_decoder_stop (GstVideoDecoder * decoder)
99 GstJpegDecoder *self = GST_JPEG_DECODER (decoder);
101 g_clear_pointer (&self->input_state, gst_video_codec_state_unref);
107 gst_jpeg_decoder_set_format (GstVideoDecoder * decoder,
108 GstVideoCodecState * state)
110 GstJpegDecoder *self = GST_JPEG_DECODER (decoder);
112 GST_DEBUG_OBJECT (decoder, "Set format");
114 if (self->input_state)
115 gst_video_codec_state_unref (self->input_state);
117 self->input_state = gst_video_codec_state_ref (state);
122 static inline gboolean
123 valid_state (guint state, guint ref_state)
125 return (state & ref_state) == ref_state;
129 decode_huffman_table (GstJpegDecoder * self, GstJpegSegment * seg)
131 GstJpegDecoderPrivate *priv = self->priv;
133 if (!gst_jpeg_segment_parse_huffman_table (seg, &priv->huf_tables)) {
134 GST_ERROR_OBJECT (self, "failed to parse Huffman table");
138 priv->state |= GST_JPEG_DECODER_STATE_GOT_HUF_TABLE;
143 decode_quant_table (GstJpegDecoder * self, GstJpegSegment * seg)
145 GstJpegDecoderPrivate *priv = self->priv;
147 if (!gst_jpeg_segment_parse_quantization_table (seg, &priv->quant_tables)) {
148 GST_ERROR_OBJECT (self, "failed to parse quantization table");
152 priv->state |= GST_JPEG_DECODER_STATE_GOT_IQ_TABLE;
157 decode_restart_interval (GstJpegDecoder * self, GstJpegSegment * seg)
159 GstJpegDecoderPrivate *priv = self->priv;
161 if (!gst_jpeg_segment_parse_restart_interval (seg, &priv->restart_interval)) {
162 GST_ERROR_OBJECT (self, "failed to parse restart interval");
169 decode_frame (GstJpegDecoder * self, GstJpegSegment * seg,
170 GstVideoCodecFrame * frame)
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;
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;
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");
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);
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");
203 priv->lossless = seg->marker == GST_JPEG_MARKER_SOF3;
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");
212 priv->state |= GST_JPEG_DECODER_STATE_GOT_SOF;
219 static const GstJpegFrameComponent *
220 get_component (const GstJpegFrameHdr * frame_hdr, guint selector)
224 for (i = 0; i < frame_hdr->num_components; i++) {
225 const GstJpegFrameComponent *fcp = &frame_hdr->components[i];
226 if (fcp->identifier == selector)
233 decode_scan (GstJpegDecoder * self, GstJpegSegment * seg)
235 GstJpegDecoderPrivate *priv = self->priv;
236 GstJpegDecoderClass *klass = GST_JPEG_DECODER_GET_CLASS (self);
237 GstJpegDecoderScan scan;
238 GstJpegScanHdr scan_hdr;
241 guint size, scan_hdr_size;
242 guint64 mcus_per_row, mcu_rows_in_scan;
243 guint blocksize = priv->lossless ? 1 : DCT_SIZE;
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 */
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;
254 if (!valid_state (priv->state, GST_JPEG_DECODER_STATE_GOT_HUF_TABLE))
255 gst_jpeg_get_default_huffman_tables (&priv->huf_tables);
257 if (!valid_state (priv->state, GST_JPEG_DECODER_STATE_GOT_IQ_TABLE))
258 gst_jpeg_get_default_quantization_tables (&priv->quant_tables);
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);
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;
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);
275 mcus_per_row = gst_util_uint64_scale_int_ceil (priv->frame_hdr.width, 1,
276 priv->max_h * blocksize);
278 gst_util_uint64_scale_int_ceil (priv->frame_hdr.height, 1,
279 priv->max_v * blocksize);
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;
287 return GST_FLOW_ERROR;
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,
300 g_assert (klass->decode_scan);
301 ret = klass->decode_scan (self, &scan, data, size);
303 if (ret == GST_FLOW_OK)
304 priv->state |= GST_JPEG_DECODER_STATE_GOT_SOS;
309 #ifndef GST_DISABLE_GST_DEBUG
311 _get_marker_name (guint marker)
360 #define CASE(marker) case G_PASTE(GST_JPEG_MARKER_, marker): return G_STRINGIFY (marker);
372 gst_jpeg_decoder_handle_frame (GstVideoDecoder * decoder,
373 GstVideoCodecFrame * frame)
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;
381 GstJpegMarker marker;
385 GST_LOG_OBJECT (self, "handle frame %" GST_PTR_FORMAT, in_buf);
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;
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;
400 offset = seg.offset + seg.size;
403 if (!valid_state (priv->state, GST_JPEG_DECODER_STATE_GOT_SOI)
404 && marker != GST_JPEG_MARKER_SOI)
405 goto unmap_and_error;
407 GST_LOG_OBJECT (self, "marker %s: %" G_GSIZE_FORMAT,
408 _get_marker_name (marker), seg.size);
413 case GST_JPEG_MARKER_SOI:
414 priv->state |= GST_JPEG_DECODER_STATE_GOT_SOI;
415 priv->restart_interval = 0;
419 case GST_JPEG_MARKER_EOI:
420 if (!valid_state (priv->state, GST_JPEG_DECODER_STATE_VALID_PICTURE))
421 goto unmap_and_error;
423 g_assert (klass->end_picture);
424 ret = klass->end_picture (self);
425 if (ret != GST_FLOW_OK)
426 goto unmap_and_error;
430 gst_buffer_unmap (in_buf, &map);
432 GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
434 g_assert (klass->output_picture);
435 return klass->output_picture (self, frame);
438 case GST_JPEG_MARKER_SOS:{
439 /* get whole scan + ECSs, with RSTi */
440 GstJpegSegment seg_scan;
443 if (!gst_jpeg_parse (&seg_scan, map.data, map.size, offset))
444 goto unmap_and_error;
446 if (seg_scan.marker < GST_JPEG_MARKER_RST_MIN
447 || seg_scan.marker > GST_JPEG_MARKER_RST_MAX)
450 offset = seg_scan.offset + seg_scan.size;
453 offset = seg_scan.offset - 2;
454 seg.size = offset - seg.offset;
456 ret = decode_scan (self, &seg);
457 if (ret != GST_FLOW_OK)
458 goto unmap_and_error;
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;
474 case GST_JPEG_MARKER_DQT:
475 if (!decode_quant_table (self, &seg)) {
476 ret = GST_FLOW_ERROR;
477 goto unmap_and_error;
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;
486 case GST_JPEG_MARKER_DNL:
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;
500 ret = GST_FLOW_ERROR;
504 gst_buffer_unmap (in_buf, &map);
510 if (ret == GST_FLOW_ERROR) {
511 GST_VIDEO_DECODER_ERROR (self, 1, STREAM, DECODE,
512 ("Failed to decode data"), (NULL), ret);
515 gst_video_decoder_drop_frame (decoder, frame);