// SPDX-License-Identifier: GPL-2.0-only /* * V4L2 JPEG header parser helpers. * * Copyright (C) 2019 Pengutronix, Philipp Zabel <[email protected]> * * For reference, see JPEG ITU-T.81 (ISO/IEC 10918-1) [1] * * [1] https://www.w3.org/Graphics/JPEG/itu-t81.pdf */ #include <asm/unaligned.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/types.h> #include <media/v4l2-jpeg.h> MODULE_DESCRIPTION(…) …; MODULE_AUTHOR(…) …; MODULE_LICENSE(…) …; /* Table B.1 - Marker code assignments */ #define SOF0 … #define SOF1 … #define SOF2 … #define SOF3 … #define SOF5 … #define SOF7 … #define JPG … #define SOF9 … #define SOF11 … #define SOF13 … #define SOF15 … #define DHT … #define DAC … #define RST0 … #define RST7 … #define SOI … #define EOI … #define SOS … #define DQT … #define DNL … #define DRI … #define DHP … #define EXP … #define APP0 … #define APP14 … #define APP15 … #define JPG0 … #define JPG13 … #define COM … #define TEM … /* Luma and chroma qp tables to achieve 50% compression quality * This is as per example in Annex K.1 of ITU-T.81 */ const u8 v4l2_jpeg_ref_table_luma_qt[V4L2_JPEG_PIXELS_IN_BLOCK] = …; EXPORT_SYMBOL_GPL(…); const u8 v4l2_jpeg_ref_table_chroma_qt[V4L2_JPEG_PIXELS_IN_BLOCK] = …; EXPORT_SYMBOL_GPL(…); /* Zigzag scan pattern indexes */ const u8 v4l2_jpeg_zigzag_scan_index[V4L2_JPEG_PIXELS_IN_BLOCK] = …; EXPORT_SYMBOL_GPL(…); /* * Contains the data that needs to be sent in the marker segment of an * interchange format JPEG stream or an abbreviated format table specification * data stream. Specifies the huffman table used for encoding the luminance DC * coefficient differences. The table represents Table K.3 of ITU-T.81 */ const u8 v4l2_jpeg_ref_table_luma_dc_ht[V4L2_JPEG_REF_HT_DC_LEN] = …; EXPORT_SYMBOL_GPL(…); /* * Contains the data that needs to be sent in the marker segment of an * interchange format JPEG stream or an abbreviated format table specification * data stream. Specifies the huffman table used for encoding the luminance AC * coefficients. The table represents Table K.5 of ITU-T.81 */ const u8 v4l2_jpeg_ref_table_luma_ac_ht[V4L2_JPEG_REF_HT_AC_LEN] = …; EXPORT_SYMBOL_GPL(…); /* * Contains the data that needs to be sent in the marker segment of an interchange format JPEG * stream or an abbreviated format table specification data stream. * Specifies the huffman table used for encoding the chrominance DC coefficient differences. * The table represents Table K.4 of ITU-T.81 */ const u8 v4l2_jpeg_ref_table_chroma_dc_ht[V4L2_JPEG_REF_HT_DC_LEN] = …; EXPORT_SYMBOL_GPL(…); /* * Contains the data that needs to be sent in the marker segment of an * interchange format JPEG stream or an abbreviated format table specification * data stream. Specifies the huffman table used for encoding the chrominance * AC coefficients. The table represents Table K.6 of ITU-T.81 */ const u8 v4l2_jpeg_ref_table_chroma_ac_ht[V4L2_JPEG_REF_HT_AC_LEN] = …; EXPORT_SYMBOL_GPL(…); /** * struct jpeg_stream - JPEG byte stream * @curr: current position in stream * @end: end position, after last byte */ struct jpeg_stream { … }; /* returns a value that fits into u8, or negative error */ static int jpeg_get_byte(struct jpeg_stream *stream) { … } /* returns a value that fits into u16, or negative error */ static int jpeg_get_word_be(struct jpeg_stream *stream) { … } static int jpeg_skip(struct jpeg_stream *stream, size_t len) { … } static int jpeg_next_marker(struct jpeg_stream *stream) { … } /* this does not advance the current position in the stream */ static int jpeg_reference_segment(struct jpeg_stream *stream, struct v4l2_jpeg_reference *segment) { … } static int v4l2_jpeg_decode_subsampling(u8 nf, u8 h_v) { … } static int jpeg_parse_frame_header(struct jpeg_stream *stream, u16 sof_marker, struct v4l2_jpeg_frame_header *frame_header) { … } static int jpeg_parse_scan_header(struct jpeg_stream *stream, struct v4l2_jpeg_scan_header *scan_header) { … } /* B.2.4.1 Quantization table-specification syntax */ static int jpeg_parse_quantization_tables(struct jpeg_stream *stream, u8 precision, struct v4l2_jpeg_reference *tables) { … } /* B.2.4.2 Huffman table-specification syntax */ static int jpeg_parse_huffman_tables(struct jpeg_stream *stream, struct v4l2_jpeg_reference *tables) { … } /* B.2.4.4 Restart interval definition syntax */ static int jpeg_parse_restart_interval(struct jpeg_stream *stream, u16 *restart_interval) { … } static int jpeg_skip_segment(struct jpeg_stream *stream) { … } /* Rec. ITU-T T.872 (06/2012) 6.5.3 */ static int jpeg_parse_app14_data(struct jpeg_stream *stream, enum v4l2_jpeg_app14_tf *tf) { … } /** * v4l2_jpeg_parse_header - locate marker segments and optionally parse headers * @buf: address of the JPEG buffer, should start with a SOI marker * @len: length of the JPEG buffer * @out: returns marker segment positions and optionally parsed headers * * The out->scan_header pointer must be initialized to NULL or point to a valid * v4l2_jpeg_scan_header structure. The out->huffman_tables and * out->quantization_tables pointers must be initialized to NULL or point to a * valid array of 4 v4l2_jpeg_reference structures each. * * Returns 0 or negative error if parsing failed. */ int v4l2_jpeg_parse_header(void *buf, size_t len, struct v4l2_jpeg_header *out) { … } EXPORT_SYMBOL_GPL(…); /** * v4l2_jpeg_parse_frame_header - parse frame header * @buf: address of the frame header, after the SOF0 marker * @len: length of the frame header * @frame_header: returns the parsed frame header * * Returns 0 or negative error if parsing failed. */ int v4l2_jpeg_parse_frame_header(void *buf, size_t len, struct v4l2_jpeg_frame_header *frame_header) { … } EXPORT_SYMBOL_GPL(…); /** * v4l2_jpeg_parse_scan_header - parse scan header * @buf: address of the scan header, after the SOS marker * @len: length of the scan header * @scan_header: returns the parsed scan header * * Returns 0 or negative error if parsing failed. */ int v4l2_jpeg_parse_scan_header(void *buf, size_t len, struct v4l2_jpeg_scan_header *scan_header) { … } EXPORT_SYMBOL_GPL(…); /** * v4l2_jpeg_parse_quantization_tables - parse quantization tables segment * @buf: address of the quantization table segment, after the DQT marker * @len: length of the quantization table segment * @precision: sample precision (P) in bits per component * @q_tables: returns four references into the buffer for the * four possible quantization table destinations * * Returns 0 or negative error if parsing failed. */ int v4l2_jpeg_parse_quantization_tables(void *buf, size_t len, u8 precision, struct v4l2_jpeg_reference *q_tables) { … } EXPORT_SYMBOL_GPL(…); /** * v4l2_jpeg_parse_huffman_tables - parse huffman tables segment * @buf: address of the Huffman table segment, after the DHT marker * @len: length of the Huffman table segment * @huffman_tables: returns four references into the buffer for the * four possible Huffman table destinations, in * the order DC0, DC1, AC0, AC1 * * Returns 0 or negative error if parsing failed. */ int v4l2_jpeg_parse_huffman_tables(void *buf, size_t len, struct v4l2_jpeg_reference *huffman_tables) { … } EXPORT_SYMBOL_GPL(…);