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 gst_video_decoder_set_needs_format (GST_VIDEO_DECODER (self), TRUE);
95 self->priv = gst_jpeg_decoder_get_instance_private (self);
99 gst_jpeg_decoder_stop (GstVideoDecoder * decoder)
101 GstJpegDecoder *self = GST_JPEG_DECODER (decoder);
103 g_clear_pointer (&self->input_state, gst_video_codec_state_unref);
109 gst_jpeg_decoder_set_format (GstVideoDecoder * decoder,
110 GstVideoCodecState * state)
112 GstJpegDecoder *self = GST_JPEG_DECODER (decoder);
114 GST_DEBUG_OBJECT (decoder, "Set format");
116 if (self->input_state)
117 gst_video_codec_state_unref (self->input_state);
119 self->input_state = gst_video_codec_state_ref (state);
124 static inline gboolean
125 valid_state (guint state, guint ref_state)
127 return (state & ref_state) == ref_state;
131 decode_huffman_table (GstJpegDecoder * self, GstJpegSegment * seg)
133 GstJpegDecoderPrivate *priv = self->priv;
135 if (!gst_jpeg_segment_parse_huffman_table (seg, &priv->huf_tables)) {
136 GST_ERROR_OBJECT (self, "failed to parse Huffman table");
140 priv->state |= GST_JPEG_DECODER_STATE_GOT_HUF_TABLE;
145 decode_quant_table (GstJpegDecoder * self, GstJpegSegment * seg)
147 GstJpegDecoderPrivate *priv = self->priv;
149 if (!gst_jpeg_segment_parse_quantization_table (seg, &priv->quant_tables)) {
150 GST_ERROR_OBJECT (self, "failed to parse quantization table");
154 priv->state |= GST_JPEG_DECODER_STATE_GOT_IQ_TABLE;
159 decode_restart_interval (GstJpegDecoder * self, GstJpegSegment * seg)
161 GstJpegDecoderPrivate *priv = self->priv;
163 if (!gst_jpeg_segment_parse_restart_interval (seg, &priv->restart_interval)) {
164 GST_ERROR_OBJECT (self, "failed to parse restart interval");
171 decode_frame (GstJpegDecoder * self, GstJpegSegment * seg,
172 GstVideoCodecFrame * frame)
174 GstJpegDecoderPrivate *priv = self->priv;
175 GstJpegDecoderClass *klass = GST_JPEG_DECODER_GET_CLASS (self);
176 GstJpegFrameHdr *frame_hdr = &self->priv->frame_hdr;
177 GstFlowReturn ret = GST_FLOW_OK;
180 if (!gst_jpeg_segment_parse_frame_header (seg, frame_hdr)) {
181 GST_ERROR_OBJECT (self, "failed to parse frame header");
182 return GST_FLOW_ERROR;
185 /* A.1.1 Dimensions and sampling factors */
186 priv->max_h = priv->max_v = 0;
187 for (i = 0; i < frame_hdr->num_components; i++) {
188 if (frame_hdr->components[i].horizontal_factor >= MAX_SAMPLE_FACTOR
189 || frame_hdr->components[i].vertical_factor >= MAX_SAMPLE_FACTOR) {
190 ret = GST_FLOW_ERROR;
191 GST_ERROR_OBJECT (self, "frame header with bad sampling factor");
195 priv->max_h = MAX (priv->max_h, frame_hdr->components[i].horizontal_factor);
196 priv->max_v = MAX (priv->max_v, frame_hdr->components[i].vertical_factor);
199 if (priv->max_h == 0 || priv->max_v == 0) {
200 ret = GST_FLOW_ERROR;
201 GST_ERROR_OBJECT (self, "frame header with bad sampling factor");
205 priv->lossless = seg->marker == GST_JPEG_MARKER_SOF3;
207 g_assert (klass->new_picture);
208 ret = klass->new_picture (self, frame, seg->marker, &priv->frame_hdr);
209 if (ret != GST_FLOW_OK) {
210 GST_WARNING_OBJECT (self, "subclass failed to handle new picture");
214 priv->state |= GST_JPEG_DECODER_STATE_GOT_SOF;
221 static const GstJpegFrameComponent *
222 get_component (const GstJpegFrameHdr * frame_hdr, guint selector)
226 for (i = 0; i < frame_hdr->num_components; i++) {
227 const GstJpegFrameComponent *fcp = &frame_hdr->components[i];
228 if (fcp->identifier == selector)
235 decode_scan (GstJpegDecoder * self, GstJpegSegment * seg)
237 GstJpegDecoderPrivate *priv = self->priv;
238 GstJpegDecoderClass *klass = GST_JPEG_DECODER_GET_CLASS (self);
239 GstJpegDecoderScan scan;
240 GstJpegScanHdr scan_hdr;
243 guint size, scan_hdr_size;
244 guint64 mcus_per_row, mcu_rows_in_scan;
245 guint blocksize = priv->lossless ? 1 : DCT_SIZE;
247 /* E.2.3 Control procedure for decoding a scan */
248 if (!valid_state (priv->state, GST_JPEG_DECODER_STATE_GOT_SOF))
249 return GST_FLOW_OK; /* ignore segment */
251 if (!gst_jpeg_segment_parse_scan_header (seg, &scan_hdr)) {
252 GST_ERROR_OBJECT (self, "failed to parse scan header");
253 return GST_FLOW_ERROR;
256 if (!valid_state (priv->state, GST_JPEG_DECODER_STATE_GOT_HUF_TABLE))
257 gst_jpeg_get_default_huffman_tables (&priv->huf_tables);
259 if (!valid_state (priv->state, GST_JPEG_DECODER_STATE_GOT_IQ_TABLE))
260 gst_jpeg_get_default_quantization_tables (&priv->quant_tables);
262 /* Non-interleaved */
263 if (scan_hdr.num_components == 1) {
264 const guint cs = scan_hdr.components[0].component_selector;
265 const GstJpegFrameComponent *fc = get_component (&priv->frame_hdr, cs);
267 if (!fc || fc->horizontal_factor == 0 || fc->vertical_factor == 0) {
268 GST_ERROR_OBJECT (self, "failed to validate frame component %u", cs);
269 return GST_FLOW_ERROR;
272 mcus_per_row = gst_util_uint64_scale_int_ceil (priv->frame_hdr.width,
273 fc->horizontal_factor, priv->max_h * blocksize);
274 mcu_rows_in_scan = gst_util_uint64_scale_int_ceil (priv->frame_hdr.height,
275 fc->vertical_factor, priv->max_v * blocksize);
277 mcus_per_row = gst_util_uint64_scale_int_ceil (priv->frame_hdr.width, 1,
278 priv->max_h * blocksize);
280 gst_util_uint64_scale_int_ceil (priv->frame_hdr.height, 1,
281 priv->max_v * blocksize);
284 scan_hdr_size = (seg->data[seg->offset] << 8) | seg->data[seg->offset + 1];
285 size = seg->size - scan_hdr_size;
286 data = seg->data + seg->offset + scan_hdr_size;
289 return GST_FLOW_ERROR;
292 scan = (GstJpegDecoderScan) {
293 .scan_hdr = &scan_hdr,
294 .huffman_tables = &priv->huf_tables,
295 .quantization_tables = &priv->quant_tables,
296 .restart_interval = priv->restart_interval,
297 .mcus_per_row = mcus_per_row,
298 .mcu_rows_in_scan = mcu_rows_in_scan,
302 g_assert (klass->decode_scan);
303 ret = klass->decode_scan (self, &scan, data, size);
305 if (ret == GST_FLOW_OK)
306 priv->state |= GST_JPEG_DECODER_STATE_GOT_SOS;
311 #ifndef GST_DISABLE_GST_DEBUG
313 _get_marker_name (guint marker)
362 #define CASE(marker) case G_PASTE(GST_JPEG_MARKER_, marker): return G_STRINGIFY (marker);
374 gst_jpeg_decoder_handle_frame (GstVideoDecoder * decoder,
375 GstVideoCodecFrame * frame)
377 GstJpegDecoder *self = GST_JPEG_DECODER (decoder);
378 GstJpegDecoderPrivate *priv = self->priv;
379 GstJpegDecoderClass *klass = GST_JPEG_DECODER_GET_CLASS (self);
380 GstBuffer *in_buf = frame->input_buffer;
381 GstFlowReturn ret = GST_FLOW_OK;
383 GstJpegMarker marker;
387 GST_LOG_OBJECT (self, "handle frame %" GST_PTR_FORMAT, in_buf);
389 if (!gst_buffer_map (in_buf, &map, GST_MAP_READ)) {
390 GST_ERROR_OBJECT (self, "Cannot map input buffer");
391 ret = GST_FLOW_ERROR;
397 /* E.2.1 Control procedure for decoding compressed image data */
398 while (offset < map.size) {
399 if (!gst_jpeg_parse (&seg, map.data, map.size, offset))
400 goto unmap_and_error;
402 offset = seg.offset + seg.size;
405 if (!valid_state (priv->state, GST_JPEG_DECODER_STATE_GOT_SOI)
406 && marker != GST_JPEG_MARKER_SOI)
407 goto unmap_and_error;
409 GST_LOG_OBJECT (self, "marker %s: %" G_GSIZE_FORMAT,
410 _get_marker_name (marker), seg.size);
415 case GST_JPEG_MARKER_SOI:
416 priv->state |= GST_JPEG_DECODER_STATE_GOT_SOI;
417 priv->restart_interval = 0;
421 case GST_JPEG_MARKER_EOI:
422 if (!valid_state (priv->state, GST_JPEG_DECODER_STATE_VALID_PICTURE))
423 goto unmap_and_error;
425 g_assert (klass->end_picture);
426 ret = klass->end_picture (self);
427 if (ret != GST_FLOW_OK)
428 goto unmap_and_error;
432 gst_buffer_unmap (in_buf, &map);
434 GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
436 g_assert (klass->output_picture);
437 return klass->output_picture (self, frame);
440 case GST_JPEG_MARKER_SOS:{
441 /* get whole scan + ECSs, with RSTi */
442 GstJpegSegment seg_scan;
445 if (!gst_jpeg_parse (&seg_scan, map.data, map.size, offset))
446 goto unmap_and_error;
448 if (seg_scan.marker < GST_JPEG_MARKER_RST_MIN
449 || seg_scan.marker > GST_JPEG_MARKER_RST_MAX)
452 offset = seg_scan.offset + seg_scan.size;
455 offset = seg_scan.offset - 2;
456 seg.size = offset - seg.offset;
458 ret = decode_scan (self, &seg);
459 if (ret != GST_FLOW_OK)
460 goto unmap_and_error;
465 /* Interpret markers */
466 case GST_JPEG_MARKER_DAC:
467 /* FIXME: Annex D - Arithmetic coding */
468 GST_FIXME_OBJECT (self, "Arithmetic coding mode unsupported");
469 goto unmap_and_error;
470 case GST_JPEG_MARKER_DHT:
471 if (!decode_huffman_table (self, &seg)) {
472 ret = GST_FLOW_ERROR;
473 goto unmap_and_error;
476 case GST_JPEG_MARKER_DQT:
477 if (!decode_quant_table (self, &seg)) {
478 ret = GST_FLOW_ERROR;
479 goto unmap_and_error;
483 case GST_JPEG_MARKER_DRI:
484 if (!decode_restart_interval (self, &seg)) {
485 GST_WARNING_OBJECT (self, "Fail to decode restart interval");
486 goto unmap_and_error;
489 case GST_JPEG_MARKER_DNL:
492 /* SOFn (Start Of Frame) */
493 if (marker >= GST_JPEG_MARKER_SOF_MIN &&
494 marker <= GST_JPEG_MARKER_SOF_MAX) {
495 ret = decode_frame (self, &seg, frame);
496 if (ret != GST_FLOW_OK)
497 goto unmap_and_error;
503 ret = GST_FLOW_ERROR;
507 gst_buffer_unmap (in_buf, &map);
513 if (ret == GST_FLOW_ERROR) {
514 GST_VIDEO_DECODER_ERROR (self, 1, STREAM, DECODE,
515 ("Failed to decode data"), (NULL), ret);
518 gst_video_decoder_drop_frame (decoder, frame);