mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
examples: add small jpeg codecparser test
https://bugzilla.gnome.org/show_bug.cgi?id=673925
This commit is contained in:
parent
7d8f694501
commit
82be4ad395
5 changed files with 319 additions and 3 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -52,6 +52,7 @@ gst*orc.h
|
|||
/ext/gsettings/org.freedesktop.gstreamer-0.10.default-elements.gschema.xml
|
||||
|
||||
/tests/check/orc
|
||||
/tests/examples/codecparsers/parse-jpeg
|
||||
/tests/examples/shapewipe/shapewipe-example
|
||||
/tests/examples/jack/jack_client
|
||||
/tests/examples/opencv/gstmotioncells_dynamic_test
|
||||
|
|
|
@ -3273,6 +3273,7 @@ tests/files/Makefile
|
|||
tests/examples/Makefile
|
||||
tests/examples/avsamplesink/Makefile
|
||||
tests/examples/camerabin2/Makefile
|
||||
tests/examples/codecparsers/Makefile
|
||||
tests/examples/directfb/Makefile
|
||||
tests/examples/gl/Makefile
|
||||
tests/examples/gl/cocoa/Makefile
|
||||
|
|
|
@ -46,8 +46,8 @@ playout_SOURCES = playout.c
|
|||
playout_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
|
||||
playout_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_API_VERSION) $(GST_LIBS)
|
||||
|
||||
SUBDIRS= mpegts $(DIRECTFB_DIR) $(GTK_EXAMPLES) $(OPENCV_EXAMPLES) $(GL_DIR) \
|
||||
$(GTK3_DIR) $(AVSAMPLE_DIR)
|
||||
DIST_SUBDIRS= mpegts camerabin2 directfb mxf opencv uvch264 gl gtk avsamplesink
|
||||
SUBDIRS= codecparsers mpegts $(DIRECTFB_DIR) $(GTK_EXAMPLES) $(OPENCV_EXAMPLES) \
|
||||
$(GL_DIR) $(GTK3_DIR) $(AVSAMPLE_DIR)
|
||||
DIST_SUBDIRS= codecparsers mpegts camerabin2 directfb mxf opencv uvch264 gl gtk avsamplesink
|
||||
|
||||
include $(top_srcdir)/common/parallel-subdirs.mak
|
||||
|
|
7
tests/examples/codecparsers/Makefile.am
Normal file
7
tests/examples/codecparsers/Makefile.am
Normal file
|
@ -0,0 +1,7 @@
|
|||
noinst_PROGRAMS = parse-jpeg
|
||||
|
||||
parse_jpeg_SOURCES = parse-jpeg.c
|
||||
parse_jpeg_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_CFLAGS)
|
||||
parse_jpeg_LDFLAGS = $(GST_LIBS)
|
||||
parse_jpeg_LDADD = \
|
||||
$(top_builddir)/gst-libs/gst/codecparsers/libgstcodecparsers-$(GST_API_VERSION).la
|
307
tests/examples/codecparsers/parse-jpeg.c
Normal file
307
tests/examples/codecparsers/parse-jpeg.c
Normal file
|
@ -0,0 +1,307 @@
|
|||
/* GStreamer JPEG parser test utility
|
||||
* Copyright (C) 2015 Tim-Philipp Müller <tim@centricular.com>
|
||||
*
|
||||
* 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 the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/codecparsers/gstjpegparser.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static GstBuffer *app_segments[16]; /* NULL */
|
||||
|
||||
static const gchar *
|
||||
get_marker_name (guint8 marker)
|
||||
{
|
||||
switch (marker) {
|
||||
case GST_JPEG_MARKER_SOF0:
|
||||
return "SOF (Baseline)";
|
||||
case GST_JPEG_MARKER_SOF1:
|
||||
return "SOF (Extended Sequential, Huffman)";
|
||||
case GST_JPEG_MARKER_SOF2:
|
||||
return "SOF (Extended Progressive, Huffman)";
|
||||
case GST_JPEG_MARKER_SOF3:
|
||||
return "SOF (Lossless, Huffman)";
|
||||
case GST_JPEG_MARKER_SOF5:
|
||||
return "SOF (Differential Sequential, Huffman)";
|
||||
case GST_JPEG_MARKER_SOF6:
|
||||
return "SOF (Differential Progressive, Huffman)";
|
||||
case GST_JPEG_MARKER_SOF7:
|
||||
return "SOF (Differential Lossless, Huffman)";
|
||||
case GST_JPEG_MARKER_SOF9:
|
||||
return "SOF (Extended Sequential, Arithmetic)";
|
||||
case GST_JPEG_MARKER_SOF10:
|
||||
return "SOF (Progressive, Arithmetic)";
|
||||
case GST_JPEG_MARKER_SOF11:
|
||||
return "SOF (Lossless, Arithmetic)";
|
||||
case GST_JPEG_MARKER_SOF13:
|
||||
return "SOF (Differential Sequential, Arithmetic)";
|
||||
case GST_JPEG_MARKER_SOF14:
|
||||
return "SOF (Differential Progressive, Arithmetic)";
|
||||
case GST_JPEG_MARKER_SOF15:
|
||||
return "SOF (Differential Lossless, Arithmetic)";
|
||||
case GST_JPEG_MARKER_DHT:
|
||||
return "DHT";
|
||||
case GST_JPEG_MARKER_DAC:
|
||||
return "DAC";
|
||||
case GST_JPEG_MARKER_SOI:
|
||||
return "SOI";
|
||||
case GST_JPEG_MARKER_EOI:
|
||||
return "EOI";
|
||||
case GST_JPEG_MARKER_SOS:
|
||||
return "SOS";
|
||||
case GST_JPEG_MARKER_DQT:
|
||||
return "DQT";
|
||||
case GST_JPEG_MARKER_DNL:
|
||||
return "DNL";
|
||||
case GST_JPEG_MARKER_DRI:
|
||||
return "DRI";
|
||||
case GST_JPEG_MARKER_APP0:
|
||||
return "APP0";
|
||||
case GST_JPEG_MARKER_APP1:
|
||||
return "APP1";
|
||||
case GST_JPEG_MARKER_APP2:
|
||||
return "APP2";
|
||||
case GST_JPEG_MARKER_APP3:
|
||||
return "APP3";
|
||||
case GST_JPEG_MARKER_APP4:
|
||||
return "APP4";
|
||||
case GST_JPEG_MARKER_APP5:
|
||||
return "APP5";
|
||||
case GST_JPEG_MARKER_APP6:
|
||||
return "APP6";
|
||||
case GST_JPEG_MARKER_APP7:
|
||||
return "APP7";
|
||||
case GST_JPEG_MARKER_APP8:
|
||||
return "APP8";
|
||||
case GST_JPEG_MARKER_APP9:
|
||||
return "APP9";
|
||||
case GST_JPEG_MARKER_APP10:
|
||||
return "APP10";
|
||||
case GST_JPEG_MARKER_APP11:
|
||||
return "APP11";
|
||||
case GST_JPEG_MARKER_APP12:
|
||||
return "APP12";
|
||||
case GST_JPEG_MARKER_APP13:
|
||||
return "APP13";
|
||||
case GST_JPEG_MARKER_APP14:
|
||||
return "APP14";
|
||||
case GST_JPEG_MARKER_APP15:
|
||||
return "APP15";
|
||||
case GST_JPEG_MARKER_COM:
|
||||
return "COM";
|
||||
default:
|
||||
if (marker > GST_JPEG_MARKER_RST_MIN && marker < GST_JPEG_MARKER_RST_MAX)
|
||||
return "RST";
|
||||
break;
|
||||
}
|
||||
return "???";
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_jpeg_segment (GstJpegSegment * segment)
|
||||
{
|
||||
switch (segment->marker) {
|
||||
case GST_JPEG_MARKER_SOF0:
|
||||
case GST_JPEG_MARKER_SOF1:
|
||||
case GST_JPEG_MARKER_SOF2:
|
||||
case GST_JPEG_MARKER_SOF3:
|
||||
case GST_JPEG_MARKER_SOF9:
|
||||
case GST_JPEG_MARKER_SOF10:
|
||||
case GST_JPEG_MARKER_SOF11:{
|
||||
GstJpegFrameHdr hdr;
|
||||
int i;
|
||||
|
||||
if (!gst_jpeg_segment_parse_frame_header (segment, &hdr)) {
|
||||
g_printerr ("Failed to parse frame header!\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_print ("\t\twidth x height = %u x %u\n", hdr.width, hdr.height);
|
||||
g_print ("\t\tsample precision = %u\n", hdr.sample_precision);
|
||||
g_print ("\t\tnum components = %u\n", hdr.num_components);
|
||||
for (i = 0; i < hdr.num_components; ++i) {
|
||||
g_print ("\t\t%d: id=%d, h=%d, v=%d, qts=%d\n", i,
|
||||
hdr.components[i].identifier, hdr.components[i].horizontal_factor,
|
||||
hdr.components[i].vertical_factor,
|
||||
hdr.components[i].quant_table_selector);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GST_JPEG_MARKER_DHT:{
|
||||
GstJpegHuffmanTables ht;
|
||||
|
||||
if (!gst_jpeg_segment_parse_huffman_table (segment, &ht)) {
|
||||
g_printerr ("Failed to parse huffman table!\n");
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GST_JPEG_MARKER_DQT:{
|
||||
GstJpegQuantTables qt;
|
||||
|
||||
if (!gst_jpeg_segment_parse_quantization_table (segment, &qt)) {
|
||||
g_printerr ("Failed to parse quantization table!\n");
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GST_JPEG_MARKER_SOS:{
|
||||
GstJpegScanHdr hdr;
|
||||
int i;
|
||||
|
||||
if (!gst_jpeg_segment_parse_scan_header (segment, &hdr)) {
|
||||
g_printerr ("Failed to parse scan header!\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_print ("\t\tnum components = %u\n", hdr.num_components);
|
||||
for (i = 0; i < hdr.num_components; ++i) {
|
||||
g_print ("\t\t %d: cs=%d, dcs=%d, acs=%d\n", i,
|
||||
hdr.components[i].component_selector,
|
||||
hdr.components[i].dc_selector, hdr.components[i].ac_selector);
|
||||
}
|
||||
}
|
||||
case GST_JPEG_MARKER_COM:
|
||||
/* gst_util_dump_mem (segment->data + segment->offset, segment->size); */
|
||||
break;
|
||||
default:
|
||||
if (segment->marker >= GST_JPEG_MARKER_APP_MIN
|
||||
&& segment->marker <= GST_JPEG_MARKER_APP_MAX) {
|
||||
guint n = segment->marker - GST_JPEG_MARKER_APP_MIN;
|
||||
|
||||
if (app_segments[n] == NULL)
|
||||
app_segments[n] = gst_buffer_new ();
|
||||
|
||||
gst_buffer_append_memory (app_segments[n],
|
||||
gst_memory_new_wrapped (GST_MEMORY_FLAG_READONLY,
|
||||
(guint8 *) segment->data + segment->offset,
|
||||
segment->size, 0, segment->size, NULL, NULL));
|
||||
}
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_jpeg (const guint8 * data, gsize size)
|
||||
{
|
||||
GstJpegSegment segment;
|
||||
guint offset = 0;
|
||||
|
||||
while (gst_jpeg_parse (&segment, data, size, offset)) {
|
||||
if (segment.offset > offset + 2)
|
||||
g_print (" skipped %u bytes\n", (guint) segment.offset - offset - 2);
|
||||
|
||||
g_print ("%6d bytes at offset %-8u : %s\n", (gint) segment.size,
|
||||
segment.offset, get_marker_name (segment.marker));
|
||||
|
||||
if (segment.marker == GST_JPEG_MARKER_EOI)
|
||||
break;
|
||||
|
||||
if (offset + segment.size < size &&
|
||||
parse_jpeg_segment (&segment) && segment.size >= 0)
|
||||
offset = segment.offset + segment.size;
|
||||
else
|
||||
offset += 2;
|
||||
};
|
||||
}
|
||||
|
||||
static void
|
||||
process_file (const gchar * fn)
|
||||
{
|
||||
GError *err = NULL;
|
||||
gchar *data = NULL;
|
||||
gsize size = 0;
|
||||
guint i;
|
||||
|
||||
g_print ("===============================================================\n");
|
||||
g_print (" %s\n", fn);
|
||||
g_print ("===============================================================\n");
|
||||
|
||||
if (!g_file_get_contents (fn, &data, &size, &err)) {
|
||||
g_error ("%s", err->message);
|
||||
g_error_free (err);
|
||||
return;
|
||||
}
|
||||
|
||||
parse_jpeg ((const guint8 *) data, size);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (app_segments); ++i) {
|
||||
if (app_segments[i] != NULL) {
|
||||
GstMapInfo map = GST_MAP_INFO_INIT;
|
||||
|
||||
/* Could parse/extract tags here */
|
||||
gst_buffer_map (app_segments[i], &map, GST_MAP_READ);
|
||||
g_print ("\tAPP%-2u : %u bytes\n", i, (guint) map.size);
|
||||
gst_util_dump_mem ((guchar *) map.data, MIN (map.size, 16));
|
||||
gst_buffer_unmap (app_segments[i], &map);
|
||||
gst_buffer_unref (app_segments[i]);
|
||||
app_segments[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, gchar ** argv)
|
||||
{
|
||||
gchar **filenames = NULL;
|
||||
GOptionEntry options[] = {
|
||||
{G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL},
|
||||
{NULL}
|
||||
};
|
||||
GOptionContext *ctx;
|
||||
GError *err = NULL;
|
||||
guint i, num;
|
||||
|
||||
gst_init (&argc, &argv);
|
||||
|
||||
if (argc == 1) {
|
||||
g_printerr ("Usage: %s FILE.JPG [FILE2.JPG] [FILE..JPG]\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx = g_option_context_new ("JPEG FILES");
|
||||
g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE);
|
||||
g_option_context_add_group (ctx, gst_init_get_option_group ());
|
||||
if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
|
||||
g_print ("Error initializing: %s\n", GST_STR_NULL (err->message));
|
||||
exit (1);
|
||||
}
|
||||
g_option_context_free (ctx);
|
||||
|
||||
if (filenames == NULL || *filenames == NULL) {
|
||||
g_printerr ("Please provide one or more filenames.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
num = g_strv_length (filenames);
|
||||
|
||||
for (i = 0; i < num; ++i) {
|
||||
process_file (filenames[i]);
|
||||
}
|
||||
|
||||
g_strfreev (filenames);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue