1
#include <gst/gst.h>
2
3
#include <string.h>
4
#include <stdbool.h>
5
6
#include "gstdspparse.h"
7
#include "gstdspvdec.h"
8
9
typedef bool (*parse_func)(GstDspBase *base, GstBuffer *buf);
10
11
static char *filename;
12
static char *result;
13
static char *result_crop;
14
15
static GMainLoop *loop;
16
static GstElement *pipeline;
17
static GstElement *src, *demux, *sink;
18
19
static GstDspBase *dec;
20
21
static parse_func gst_dsp_parse;
22
23
static unsigned buffer_count;
24
25
static gboolean bus_cb(GstBus *bus, GstMessage *msg, gpointer data)
26
{
27
	switch (GST_MESSAGE_TYPE(msg)) {
28
	case GST_MESSAGE_EOS:
29
		g_main_loop_quit(loop);
30
		break;
31
	case GST_MESSAGE_ERROR: {
32
		gchar *debug;
33
		GError *err;
34
35
		gst_message_parse_error(msg, &err, &debug);
36
37
		g_printerr("error: %s: %s\n", err->message, debug);
38
		g_error_free(err);
39
		g_free(debug);
40
41
		g_main_loop_quit(loop);
42
		break;
43
	}
44
	default:
45
		break;
46
	}
47
48
	return TRUE;
49
}
50
51
static void on_pad_added(GstElement *element, GstPad *pad, gpointer data)
52
{
53
	GstPad *sinkpad;
54
	GstStructure *struc;
55
	const gchar *name;
56
57
	sinkpad = gst_element_get_static_pad(sink, "sink");
58
	gst_pad_link(pad, sinkpad);
59
	gst_object_unref(sinkpad);
60
61
	struc = gst_caps_get_structure(GST_PAD_CAPS(pad), 0);
62
63
	name = gst_structure_get_name(struc);
64
	if (strncmp(name, "video/", 6) != 0)
65
		return;
66
67
	if (strcmp(name, "video/x-h263") == 0)
68
		gst_dsp_parse = gst_dsp_h263_parse;
69
	else if (strcmp(name, "video/x-h264") == 0)
70
		gst_dsp_parse = gst_dsp_h264_parse;
71
	else
72
		gst_dsp_parse = gst_dsp_mpeg4_parse;
73
}
74
75
static void handoff(GstElement *object,
76
	     GstBuffer *buffer,
77
	     GstPad *pad,
78
	     gpointer user_data)
79
{
80
	GstStructure *struc;
81
	const GValue *codec_data;
82
	bool r;
83
84
	buffer_count++;
85
86
	struc = gst_caps_get_structure(GST_BUFFER_CAPS(buffer), 0);
87
	codec_data = gst_structure_get_value(struc, "codec_data");
88
	if (codec_data) {
89
		GstBuffer *tmp;
90
		tmp = gst_value_get_buffer(codec_data);
91
		r = gst_dsp_parse(dec, tmp);
92
		if (r)
93
			goto ok;
94
		else
95
			g_printerr("bad codec data\n");
96
	}
97
98
	r = gst_dsp_parse(dec, buffer);
99
ok:
100
	if (r) {
101
		GstDspVDec *vdec = GST_DSP_VDEC(dec);
102
		result = g_strdup_printf("fs=%ix%i",
103
				vdec->width, vdec->height);
104
		result_crop = g_strdup_printf("cfs=%ix%i",
105
				vdec->crop_width, vdec->crop_height);
106
	} else {
107
		g_printerr("parse error\n");
108
	}
109
	g_main_loop_quit(loop);
110
}
111
112
static void init(void)
113
{
114
	pipeline = gst_pipeline_new("parse");
115
116
	src = gst_element_factory_make("filesrc", "src");
117
	demux = gst_element_factory_make("qtdemux", "demux");
118
	sink = gst_element_factory_make("fakesink", "sink");
119
120
	gst_bin_add_many(GST_BIN(pipeline), src, demux, sink, NULL);
121
	gst_element_link(src, demux);
122
	g_signal_connect(demux, "pad-added", G_CALLBACK(on_pad_added), NULL);
123
124
	GstBus *bus;
125
	bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
126
	gst_bus_add_watch(bus, bus_cb, NULL);
127
	gst_object_unref(bus);
128
129
	g_object_set(G_OBJECT(src), "location", filename, NULL);
130
131
	g_object_set(G_OBJECT(sink), "signal-handoffs", TRUE, "num-buffers", 1, NULL);
132
	g_signal_connect(sink, "handoff", G_CALLBACK(handoff), NULL);
133
134
	gst_element_set_state(pipeline, GST_STATE_PLAYING);
135
}
136
137
GstDebugCategory *gstdsp_debug;
138
139
int main(int argc, char *argv[])
140
{
141
	int ret;
142
	char *expected;
143
	char *expected_crop = NULL;
144
145
	gst_init(&argc, &argv);
146
147
	loop = g_main_loop_new(NULL, FALSE);
148
149
	if (argc < 3)
150
		return -1;
151
152
	filename = argv[1];
153
	expected = argv[2];
154
155
	if (argc >= 4)
156
		expected_crop = argv[3];
157
158
#ifndef GST_DISABLE_GST_DEBUG
159
	gstdsp_debug = _gst_debug_category_new("dsp", 0, "DSP stuff");
160
#endif
161
162
	dec = g_object_new(GST_DSP_VDEC_TYPE, NULL);
163
164
	init();
165
166
	g_main_loop_run(loop);
167
168
	if (result) {
169
		g_print("%s %s\n", result, result_crop);
170
	} else {
171
		if (buffer_count == 0)
172
			g_printerr("no data\n");
173
		else
174
			g_printerr("no result\n");
175
	}
176
177
	ret = !!g_strcmp0(expected, result);
178
	if (!ret && expected_crop)
179
		ret = !!g_strcmp0(expected_crop, result_crop);
180
181
	g_free(result);
182
	g_free(result_crop);
183
184
	if (pipeline) {
185
		gst_element_set_state(pipeline, GST_STATE_NULL);
186
		gst_object_unref(GST_OBJECT(pipeline));
187
	}
188
189
	g_object_unref(dec);
190
191
	g_main_loop_unref(loop);
192
193
	return -ret;
194
}