2 * Copyright (C) 2010 David Schleef <ds@schleef.org>
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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 * SECTION:element-gstdiracparse
22 * The gstdiracparse element does FIXME stuff.
25 * <title>Example launch line</title>
27 * gst-launch -v fakesrc ! gstdiracparse ! FIXME ! fakesink
29 * FIXME Describe what the pipeline does.
38 #include <gst/base/gstbytereader.h>
40 #include "gstdiracparse.h"
41 #include "dirac_parse.h"
46 static void gst_dirac_parse_set_property (GObject * object,
47 guint property_id, const GValue * value, GParamSpec * pspec);
48 static void gst_dirac_parse_get_property (GObject * object,
49 guint property_id, GValue * value, GParamSpec * pspec);
50 static void gst_dirac_parse_dispose (GObject * object);
51 static void gst_dirac_parse_finalize (GObject * object);
53 static gboolean gst_dirac_parse_start (GstBaseParse * parse);
54 static gboolean gst_dirac_parse_stop (GstBaseParse * parse);
55 static gboolean gst_dirac_parse_set_sink_caps (GstBaseParse * parse,
57 static GstCaps *gst_dirac_parse_get_sink_caps (GstBaseParse * parse);
58 static gboolean gst_dirac_parse_check_valid_frame (GstBaseParse * parse,
59 GstBaseParseFrame * frame, guint * framesize, gint * skipsize);
60 static GstFlowReturn gst_dirac_parse_parse_frame (GstBaseParse * parse,
61 GstBaseParseFrame * frame);
62 static gboolean gst_dirac_parse_convert (GstBaseParse * parse,
63 GstFormat src_format, gint64 src_value, GstFormat dest_format,
65 static gboolean gst_dirac_parse_event (GstBaseParse * parse, GstEvent * event);
66 static gboolean gst_dirac_parse_src_event (GstBaseParse * parse,
68 static GstFlowReturn gst_dirac_parse_pre_push_frame (GstBaseParse * parse,
69 GstBaseParseFrame * frame);
78 static GstStaticPadTemplate gst_dirac_parse_sink_template =
79 GST_STATIC_PAD_TEMPLATE ("sink",
82 GST_STATIC_CAPS ("video/x-dirac")
85 static GstStaticPadTemplate gst_dirac_parse_src_template =
86 GST_STATIC_PAD_TEMPLATE ("src",
89 GST_STATIC_CAPS ("video/x-dirac, parsed=(boolean)TRUE, "
90 "width=(int)[1,MAX], height=(int)[1,MAX], "
91 "framerate=(fraction)[0/1,MAX], "
92 "pixel-aspect-ratio=(fraction)[0/1,MAX], "
93 "interlaced=(boolean){TRUE,FALSE}, "
94 "profile=(int)[0,MAX], level=(int)[0,MAX]")
97 /* class initialization */
99 GST_BOILERPLATE (GstDiracParse, gst_dirac_parse, GstBaseParse,
100 GST_TYPE_BASE_PARSE);
103 gst_dirac_parse_base_init (gpointer g_class)
105 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
107 gst_element_class_add_static_pad_template (element_class,
108 &gst_dirac_parse_src_template);
109 gst_element_class_add_static_pad_template (element_class,
110 &gst_dirac_parse_sink_template);
112 gst_element_class_set_details_simple (element_class, "Dirac parser",
113 "Codec/Parser/Video", "Parses Dirac streams",
114 "David Schleef <ds@schleef.org>");
118 gst_dirac_parse_class_init (GstDiracParseClass * klass)
120 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
121 GstBaseParseClass *base_parse_class = GST_BASE_PARSE_CLASS (klass);
123 gobject_class->set_property = gst_dirac_parse_set_property;
124 gobject_class->get_property = gst_dirac_parse_get_property;
125 gobject_class->dispose = gst_dirac_parse_dispose;
126 gobject_class->finalize = gst_dirac_parse_finalize;
127 base_parse_class->start = GST_DEBUG_FUNCPTR (gst_dirac_parse_start);
128 base_parse_class->stop = GST_DEBUG_FUNCPTR (gst_dirac_parse_stop);
129 base_parse_class->set_sink_caps =
130 GST_DEBUG_FUNCPTR (gst_dirac_parse_set_sink_caps);
131 base_parse_class->get_sink_caps =
132 GST_DEBUG_FUNCPTR (gst_dirac_parse_get_sink_caps);
133 base_parse_class->check_valid_frame =
134 GST_DEBUG_FUNCPTR (gst_dirac_parse_check_valid_frame);
135 base_parse_class->parse_frame =
136 GST_DEBUG_FUNCPTR (gst_dirac_parse_parse_frame);
137 base_parse_class->convert = GST_DEBUG_FUNCPTR (gst_dirac_parse_convert);
138 base_parse_class->event = GST_DEBUG_FUNCPTR (gst_dirac_parse_event);
139 base_parse_class->src_event = GST_DEBUG_FUNCPTR (gst_dirac_parse_src_event);
140 base_parse_class->pre_push_frame =
141 GST_DEBUG_FUNCPTR (gst_dirac_parse_pre_push_frame);
146 gst_dirac_parse_init (GstDiracParse * diracparse,
147 GstDiracParseClass * diracparse_class)
149 gst_base_parse_set_min_frame_size (GST_BASE_PARSE (diracparse), 13);
154 gst_dirac_parse_set_property (GObject * object, guint property_id,
155 const GValue * value, GParamSpec * pspec)
157 g_return_if_fail (GST_IS_DIRAC_PARSE (object));
159 switch (property_id) {
161 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
167 gst_dirac_parse_get_property (GObject * object, guint property_id,
168 GValue * value, GParamSpec * pspec)
170 g_return_if_fail (GST_IS_DIRAC_PARSE (object));
172 switch (property_id) {
174 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
180 gst_dirac_parse_dispose (GObject * object)
182 g_return_if_fail (GST_IS_DIRAC_PARSE (object));
184 /* clean up as possible. may be called multiple times */
186 G_OBJECT_CLASS (parent_class)->dispose (object);
190 gst_dirac_parse_finalize (GObject * object)
192 g_return_if_fail (GST_IS_DIRAC_PARSE (object));
194 /* clean up object here */
196 G_OBJECT_CLASS (parent_class)->finalize (object);
201 gst_dirac_parse_start (GstBaseParse * parse)
203 gst_base_parse_set_min_frame_size (parse, 13);
209 gst_dirac_parse_stop (GstBaseParse * parse)
215 gst_dirac_parse_set_sink_caps (GstBaseParse * parse, GstCaps * caps)
217 /* Called when sink caps are set */
222 gst_dirac_parse_check_valid_frame (GstBaseParse * parse,
223 GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
225 GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (frame->buffer);
230 gboolean have_picture = FALSE;
233 data = GST_BUFFER_DATA (frame->buffer);
234 size = GST_BUFFER_SIZE (frame->buffer);
236 if (G_UNLIKELY (size < 13))
239 GST_DEBUG ("%d: %02x %02x %02x %02x", size, data[0], data[1], data[2],
242 if (GST_READ_UINT32_BE (data) != 0x42424344) {
243 off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff,
244 0x42424344, 0, GST_BUFFER_SIZE (frame->buffer));
247 *skipsize = GST_BUFFER_SIZE (frame->buffer) - 3;
251 GST_LOG_OBJECT (parse, "possible sync at buffer offset %d", off);
253 GST_DEBUG ("skipping %d", off);
258 /* have sync, parse chunks */
261 while (!have_picture) {
262 GST_DEBUG ("offset %d:", offset);
264 if (offset + 13 >= size) {
265 *framesize = offset + 13;
269 GST_DEBUG ("chunk type %02x", data[offset + 4]);
271 if (GST_READ_UINT32_BE (data + offset) != 0x42424344) {
272 GST_DEBUG ("bad header");
277 next_header = GST_READ_UINT32_BE (data + offset + 5);
278 GST_DEBUG ("next_header %d", next_header);
279 if (next_header == 0)
282 if (SCHRO_PARSE_CODE_IS_PICTURE (data[offset + 4])) {
286 offset += next_header;
287 if (offset >= size) {
294 GST_DEBUG ("framesize %d", *framesize);
300 gst_dirac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
302 GstDiracParse *diracparse = GST_DIRAC_PARSE (parse);
306 /* Called when processing incoming buffers. Function should parse
310 data = GST_BUFFER_DATA (frame->buffer);
311 size = GST_BUFFER_SIZE (frame->buffer);
313 //GST_ERROR("got here %d", size);
315 if (data[4] == SCHRO_PARSE_CODE_SEQUENCE_HEADER) {
317 DiracSequenceHeader sequence_header;
320 ret = dirac_sequence_header_parse (&sequence_header, data + 13, size - 13);
322 memcpy (&diracparse->sequence_header, &sequence_header,
323 sizeof (sequence_header));
324 caps = gst_caps_new_simple ("video/x-dirac",
325 "width", G_TYPE_INT, sequence_header.width,
326 "height", G_TYPE_INT, sequence_header.height,
327 "framerate", GST_TYPE_FRACTION,
328 sequence_header.frame_rate_numerator,
329 sequence_header.frame_rate_denominator,
330 "pixel-aspect-ratio", GST_TYPE_FRACTION,
331 sequence_header.aspect_ratio_numerator,
332 sequence_header.aspect_ratio_denominator,
333 "interlaced", G_TYPE_BOOLEAN, sequence_header.interlaced,
334 "profile", G_TYPE_INT, sequence_header.profile,
335 "level", G_TYPE_INT, sequence_header.level, NULL);
336 gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
337 gst_caps_unref (caps);
339 gst_base_parse_set_frame_rate (parse,
340 sequence_header.frame_rate_numerator,
341 sequence_header.frame_rate_denominator, 0, 0);
345 gst_buffer_set_caps (frame->buffer,
346 GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (parse)));
348 gst_base_parse_set_min_frame_size (parse, 13);
354 gst_dirac_parse_convert (GstBaseParse * parse, GstFormat src_format,
355 gint64 src_value, GstFormat dest_format, gint64 * dest_value)
357 /* Convert between formats */
363 gst_dirac_parse_event (GstBaseParse * parse, GstEvent * event)
365 /* Sink pad event handler */
371 gst_dirac_parse_src_event (GstBaseParse * parse, GstEvent * event)
373 /* Src pad event handler */
379 gst_dirac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
386 gst_dirac_parse_get_sink_caps (GstBaseParse * parse)
391 peercaps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (parse));
395 /* Remove the parsed field */
396 peercaps = gst_caps_make_writable (peercaps);
397 n = gst_caps_get_size (peercaps);
398 for (i = 0; i < n; i++) {
399 GstStructure *s = gst_caps_get_structure (peercaps, i);
400 gst_structure_remove_field (s, "parsed");
404 gst_caps_intersect_full (peercaps,
405 gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse)),
406 GST_CAPS_INTERSECT_FIRST);
407 gst_caps_unref (peercaps);
410 gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD