diff --git a/subprojects/gst-plugins-bad/tests/check/libs/jpegbitwriter.c b/subprojects/gst-plugins-bad/tests/check/libs/jpegbitwriter.c new file mode 100644 index 0000000000..b7b132b429 --- /dev/null +++ b/subprojects/gst-plugins-bad/tests/check/libs/jpegbitwriter.c @@ -0,0 +1,263 @@ +/* GStreamer + * Copyright (C) 2024 Intel Corporation + * Author: He Junyan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the0 + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include + +GST_START_TEST (test_jpeg_bitwriter_segments) +{ + GstJpegBitWriterResult writer_res; + gboolean parser_res; + guint8 data[2048] = { 0, }; + guint8 app_data[14] = + { 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x02, 0, 0, 0x01, 0, 0x01, 0, 0 }; + GstJpegQuantTables quant_tables = { 0, }; + GstJpegQuantTables quant_tables2 = { 0, }; + GstJpegHuffmanTables huf_tables = { 0, }; + GstJpegHuffmanTables huf_tables2 = { 0, }; + GstJpegFrameHdr frame_hdr; + GstJpegFrameHdr frame_hdr2 = { 0, }; + GstJpegScanHdr scan_hdr; + GstJpegScanHdr scan_hdr2 = { 0, }; + GstJpegSegment seg; + guint size, offset; + guint i, j; + + offset = 0; + size = sizeof (data); + writer_res = gst_jpeg_bit_writer_segment_with_data (GST_JPEG_MARKER_SOI, + NULL, 0, data, &size); + fail_if (writer_res != GST_JPEG_BIT_WRITER_OK); + + offset += size; + size = sizeof (data) - offset; + writer_res = gst_jpeg_bit_writer_segment_with_data (GST_JPEG_MARKER_APP_MIN, + app_data, sizeof (app_data), data + offset, &size); + fail_if (writer_res != GST_JPEG_BIT_WRITER_OK); + + gst_jpeg_get_default_quantization_tables (&quant_tables); + for (i = 0; i < GST_JPEG_MAX_QUANT_ELEMENTS; i++) { + if (i % 2) + quant_tables.quant_tables[0].quant_table[i] += 10; + + if (i % 3) + quant_tables.quant_tables[1].quant_table[i] += 5; + + if (i % 4) + quant_tables.quant_tables[2].quant_table[i] /= 2; + } + + offset += size; + size = sizeof (data) - offset; + writer_res = gst_jpeg_bit_writer_quantization_table (&quant_tables, + data + offset, &size); + fail_if (writer_res != GST_JPEG_BIT_WRITER_OK); + + /* *INDENT-OFF* */ + frame_hdr = (GstJpegFrameHdr) { + .sample_precision = 8, + .width = 1920, + .height = 1080, + .num_components = 3, + .components[0] = { + .identifier = 1, + .horizontal_factor= 3, + .vertical_factor = 2, + .quant_table_selector = 1, + }, + .components[1] = { + .identifier = 2, + .horizontal_factor= 1, + .vertical_factor = 4, + .quant_table_selector = 2, + }, + .components[2] = { + .identifier = 0, + .horizontal_factor = 2, + .vertical_factor = 1, + .quant_table_selector = 3, + }, + }; + /* *INDENT-ON* */ + + offset += size; + size = sizeof (data) - offset; + writer_res = gst_jpeg_bit_writer_frame_header (&frame_hdr, + GST_JPEG_MARKER_SOF_MIN, data + offset, &size); + fail_if (writer_res != GST_JPEG_BIT_WRITER_OK); + + gst_jpeg_get_default_huffman_tables (&huf_tables); + offset += size; + size = sizeof (data) - offset; + writer_res = gst_jpeg_bit_writer_huffman_table (&huf_tables, + data + offset, &size); + fail_if (writer_res != GST_JPEG_BIT_WRITER_OK); + + /* *INDENT-OFF* */ + scan_hdr = (GstJpegScanHdr) { + .num_components = 3, + .components[0] = { + .component_selector = 85, + .dc_selector = 2, + .ac_selector = 1, + }, + .components[1] = { + .component_selector = 16, + .dc_selector = 1, + .ac_selector = 0, + }, + .components[2] = { + .component_selector = 25, + .dc_selector = 2, + .ac_selector = 1, + }, + }; + /* *INDENT-ON* */ + offset += size; + size = sizeof (data) - offset; + writer_res = gst_jpeg_bit_writer_scan_header (&scan_hdr, + data + offset, &size); + fail_if (writer_res != GST_JPEG_BIT_WRITER_OK); + + offset += size; + fail_if (offset + 2 >= sizeof (data)); + + offset = sizeof (data) - 2; + size = 2; + writer_res = gst_jpeg_bit_writer_segment_with_data (GST_JPEG_MARKER_EOI, + NULL, 0, data + offset, &size); + fail_if (writer_res != GST_JPEG_BIT_WRITER_OK); + + /* Parse it back and check. */ + /* SOI */ + offset = 0; + parser_res = gst_jpeg_parse (&seg, data, sizeof (data), offset); + fail_if (parser_res != TRUE); + fail_if (seg.marker != GST_JPEG_MARKER_SOI); + + /* APP0 */ + offset += 2 + seg.size; + parser_res = gst_jpeg_parse (&seg, data, sizeof (data), offset); + fail_if (parser_res != TRUE); + fail_if (seg.marker != GST_JPEG_MARKER_APP_MIN); + fail_if (*(seg.data + seg.offset) * 256 + *(seg.data + seg.offset + 1) != + seg.size); + for (i = 0; i < sizeof (app_data); i++) { + const guint8 *d = seg.data + seg.offset + 2; + fail_if (d[i] != app_data[i]); + } + + /* Quantization tables */ + offset += 2 + seg.size; + parser_res = gst_jpeg_parse (&seg, data, sizeof (data), offset); + fail_if (parser_res != TRUE); + fail_if (seg.marker != GST_JPEG_MARKER_DQT); + fail_if (*(seg.data + seg.offset) * 256 + *(seg.data + seg.offset + 1) != + seg.size); + parser_res = gst_jpeg_segment_parse_quantization_table (&seg, &quant_tables2); + fail_if (parser_res != TRUE); + + for (i = 0; i < GST_JPEG_MAX_SCAN_COMPONENTS; i++) { + GstJpegQuantTable *quant_table = &quant_tables.quant_tables[i]; + GstJpegQuantTable *quant_table2 = &quant_tables2.quant_tables[i]; + + fail_if (quant_table->quant_precision != quant_table2->quant_precision); + fail_if (quant_table->valid != quant_table2->valid); + + for (j = 0; j < GST_JPEG_MAX_QUANT_ELEMENTS; j++) + fail_if (quant_table->quant_table[j] != quant_table2->quant_table[j]); + } + + /* SOF */ + offset += 2 + seg.size; + parser_res = gst_jpeg_parse (&seg, data, sizeof (data), offset); + fail_if (parser_res != TRUE); + fail_if (seg.marker != GST_JPEG_MARKER_SOF_MIN); + fail_if (*(seg.data + seg.offset) * 256 + *(seg.data + seg.offset + 1) != + seg.size); + parser_res = gst_jpeg_segment_parse_frame_header (&seg, &frame_hdr2); + fail_if (parser_res != TRUE); + + fail_if (frame_hdr.sample_precision != frame_hdr2.sample_precision); + fail_if (frame_hdr.width != frame_hdr2.width); + fail_if (frame_hdr.height != frame_hdr2.height); + fail_if (frame_hdr.num_components != frame_hdr2.num_components); + for (i = 0; i < frame_hdr.num_components; i++) { + fail_if (frame_hdr.components[i].identifier != + frame_hdr2.components[i].identifier); + fail_if (frame_hdr.components[i].horizontal_factor != + frame_hdr2.components[i].horizontal_factor); + fail_if (frame_hdr.components[i].vertical_factor != + frame_hdr2.components[i].vertical_factor); + fail_if (frame_hdr.components[i].quant_table_selector != + frame_hdr2.components[i].quant_table_selector); + } + + /* huffman tables */ + offset += 2 + seg.size; + parser_res = gst_jpeg_parse (&seg, data, sizeof (data), offset); + fail_if (parser_res != TRUE); + fail_if (seg.marker != GST_JPEG_MARKER_DHT); + fail_if (*(seg.data + seg.offset) * 256 + *(seg.data + seg.offset + 1) != + seg.size); + parser_res = gst_jpeg_segment_parse_huffman_table (&seg, &huf_tables2); + fail_if (parser_res != TRUE); + fail_if (memcmp (&huf_tables, &huf_tables2, sizeof (huf_tables)) != 0); + + /* Scan header */ + offset += 2 + seg.size; + parser_res = gst_jpeg_parse (&seg, data, sizeof (data), offset); + fail_if (parser_res != TRUE); + fail_if (seg.marker != GST_JPEG_MARKER_SOS); + parser_res = gst_jpeg_segment_parse_scan_header (&seg, &scan_hdr2); + fail_if (parser_res != TRUE); + + fail_if (scan_hdr.num_components != scan_hdr2.num_components); + for (i = 0; i < scan_hdr.num_components; i++) { + fail_if (scan_hdr.components[i].component_selector != + scan_hdr2.components[i].component_selector); + fail_if (scan_hdr.components[i].dc_selector != + scan_hdr2.components[i].dc_selector); + fail_if (scan_hdr.components[i].ac_selector != + scan_hdr2.components[i].ac_selector); + } + + offset += 2 + seg.size; + parser_res = gst_jpeg_parse (&seg, data, sizeof (data), offset); + fail_if (parser_res != TRUE); + fail_if (seg.marker != GST_JPEG_MARKER_EOI); +} + +GST_END_TEST; + +static Suite * +jpegbitwriter_suite (void) +{ + Suite *s = suite_create ("jpeg bitwriter library"); + + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_jpeg_bitwriter_segments); + + return s; +} + +GST_CHECK_MAIN (jpegbitwriter); diff --git a/subprojects/gst-plugins-bad/tests/check/meson.build b/subprojects/gst-plugins-bad/tests/check/meson.build index bf6f6d0ac2..ce392fcb82 100644 --- a/subprojects/gst-plugins-bad/tests/check/meson.build +++ b/subprojects/gst-plugins-bad/tests/check/meson.build @@ -99,6 +99,7 @@ base_tests = [ [['libs/vkformat.c'], not gstvulkan_dep.found(), [gstvulkan_dep]], [['libs/av1bitwriter.c'], false, [gstcodecparsers_dep]], [['libs/vp9bitwriter.c'], false, [gstcodecparsers_dep]], + [['libs/jpegbitwriter.c'], false, [gstcodecparsers_dep]], [['libs/vkmemory.c'], not gstvulkan_dep.found(), [gstvulkan_dep]], [['libs/analyticsmeta.c'], false, [gstanalytics_dep]], [['elements/vkcolorconvert.c'], not gstvulkan_dep.found(), [gstvulkan_dep]],