1 /* GStreamer RealAudio demuxer
2 * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
3 *
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.
8 *
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.
13 *
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., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 /**
21 * SECTION:element-rademux
22 *
23 * Demuxes/parses a RealAudio (.ra) file or stream into compressed audio.
24 *
25 * <refsect2>
26 * <title>Example launch line</title>
27 * |[
28 * gst-launch-1.0 filesrc location=interview.ra ! rademux ! avdec_real_288 ! audioconvert ! audioresample ! autoaudiosink
29 * ]| Read a RealAudio file and decode it and output it to the soundcard using
30 * the ALSA element. The .ra file is assumed to contain RealAudio version 2.
31 * |[
32 * gst-launch-1.0 souphttpsrc location=http://www.example.org/interview.ra ! rademux ! ac3parse ! a52dec ! audioconvert ! audioresample ! autoaudiosink
33 * ]| Stream RealAudio data containing AC3 (dnet) compressed audio and decode it
34 * and output it to the soundcard.
35 * </refsect2>
36 */
37
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41
42 #include "rademux.h"
43 #include "rmdemux.h"
44 #include "rmutils.h"
45
46 #include <string.h>
47
48 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
49 GST_PAD_SINK,
50 GST_PAD_ALWAYS,
51 GST_STATIC_CAPS ("application/x-pn-realaudio")
52 );
53
54 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
55 GST_PAD_SRC,
56 GST_PAD_SOMETIMES,
57 GST_STATIC_CAPS_ANY);
58
59 GST_DEBUG_CATEGORY_STATIC (real_audio_demux_debug);
60 #define GST_CAT_DEFAULT real_audio_demux_debug
61
62 #define gst_real_audio_demux_parent_class parent_class
63 G_DEFINE_TYPE (GstRealAudioDemux, gst_real_audio_demux, GST_TYPE_ELEMENT);
64
65 static GstStateChangeReturn gst_real_audio_demux_change_state (GstElement * e,
66 GstStateChange transition);
67 static GstFlowReturn gst_real_audio_demux_chain (GstPad * pad,
68 GstObject * parent, GstBuffer * buf);
69 static gboolean gst_real_audio_demux_sink_event (GstPad * pad,
70 GstObject * parent, GstEvent * ev);
71 static gboolean gst_real_audio_demux_src_event (GstPad * pad,
72 GstObject * parent, GstEvent * ev);
73 static gboolean gst_real_audio_demux_src_query (GstPad * pad,
74 GstObject * parent, GstQuery * query);
75 static void gst_real_audio_demux_loop (GstRealAudioDemux * demux);
76 static gboolean gst_real_audio_demux_sink_activate (GstPad * sinkpad,
77 GstObject * parent);
78 static gboolean gst_real_audio_demux_sink_activate_mode (GstPad * sinkpad,
79 GstObject * parent, GstPadMode mode, gboolean active);
80
81 static void
gst_real_audio_demux_finalize(GObject * obj)82 gst_real_audio_demux_finalize (GObject * obj)
83 {
84 GstRealAudioDemux *demux = GST_REAL_AUDIO_DEMUX (obj);
85
86 g_object_unref (demux->adapter);
87
88 G_OBJECT_CLASS (parent_class)->finalize (obj);
89 }
90
91 static void
gst_real_audio_demux_class_init(GstRealAudioDemuxClass * klass)92 gst_real_audio_demux_class_init (GstRealAudioDemuxClass * klass)
93 {
94 GObjectClass *gobject_class = (GObjectClass *) klass;
95 GstElementClass *gstelement_class = (GstElementClass *) klass;
96
97 gobject_class->finalize = gst_real_audio_demux_finalize;
98
99 gst_element_class_add_static_pad_template (gstelement_class, &sink_template);
100 gst_element_class_add_static_pad_template (gstelement_class, &src_template);
101
102 gst_element_class_set_static_metadata (gstelement_class, "RealAudio Demuxer",
103 "Codec/Demuxer",
104 "Demultiplex a RealAudio file",
105 "Tim-Philipp Müller <tim centricular net>");
106
107 gstelement_class->change_state =
108 GST_DEBUG_FUNCPTR (gst_real_audio_demux_change_state);
109
110 GST_DEBUG_CATEGORY_INIT (real_audio_demux_debug, "rademux",
111 0, "Demuxer for RealAudio streams");
112 }
113
114 static void
gst_real_audio_demux_reset(GstRealAudioDemux * demux)115 gst_real_audio_demux_reset (GstRealAudioDemux * demux)
116 {
117 gst_adapter_clear (demux->adapter);
118
119 if (demux->srcpad) {
120 GST_DEBUG_OBJECT (demux, "Removing source pad");
121 gst_element_remove_pad (GST_ELEMENT (demux), demux->srcpad);
122 demux->srcpad = NULL;
123 }
124
125 if (demux->pending_tags) {
126 gst_tag_list_unref (demux->pending_tags);
127 demux->pending_tags = NULL;
128 }
129
130 demux->state = REAL_AUDIO_DEMUX_STATE_MARKER;
131 demux->ra_version = 0;
132 demux->data_offset = 0;
133 demux->packet_size = 0;
134
135 demux->sample_rate = 0;
136 demux->sample_width = 0;
137 demux->channels = 0;
138 demux->fourcc = 0;
139
140 demux->need_newsegment = TRUE;
141
142 demux->segment_running = FALSE;
143
144 demux->byterate_num = 0;
145 demux->byterate_denom = 0;
146
147 demux->duration = 0;
148 demux->upstream_size = 0;
149
150 demux->offset = 0;
151
152 demux->have_group_id = FALSE;
153 demux->group_id = G_MAXUINT;
154
155 gst_adapter_clear (demux->adapter);
156 }
157
158 static void
gst_real_audio_demux_init(GstRealAudioDemux * demux)159 gst_real_audio_demux_init (GstRealAudioDemux * demux)
160 {
161 demux->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
162
163 gst_pad_set_chain_function (demux->sinkpad,
164 GST_DEBUG_FUNCPTR (gst_real_audio_demux_chain));
165 gst_pad_set_event_function (demux->sinkpad,
166 GST_DEBUG_FUNCPTR (gst_real_audio_demux_sink_event));
167 gst_pad_set_activate_function (demux->sinkpad,
168 GST_DEBUG_FUNCPTR (gst_real_audio_demux_sink_activate));
169 gst_pad_set_activatemode_function (demux->sinkpad,
170 GST_DEBUG_FUNCPTR (gst_real_audio_demux_sink_activate_mode));
171
172 gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
173
174 demux->adapter = gst_adapter_new ();
175 gst_real_audio_demux_reset (demux);
176 }
177
178 static gboolean
gst_real_audio_demux_sink_activate(GstPad * sinkpad,GstObject * parent)179 gst_real_audio_demux_sink_activate (GstPad * sinkpad, GstObject * parent)
180 {
181 GstQuery *query;
182 gboolean pull_mode;
183
184 query = gst_query_new_scheduling ();
185
186 if (!gst_pad_peer_query (sinkpad, query)) {
187 gst_query_unref (query);
188 goto activate_push;
189 }
190
191 pull_mode = gst_query_has_scheduling_mode_with_flags (query,
192 GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
193 gst_query_unref (query);
194
195 if (!pull_mode)
196 goto activate_push;
197
198 GST_DEBUG_OBJECT (sinkpad, "activating pull");
199 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
200
201 activate_push:
202 {
203 GST_DEBUG_OBJECT (sinkpad, "activating push");
204 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
205 }
206 }
207
208 static gboolean
gst_real_audio_demux_sink_activate_mode(GstPad * sinkpad,GstObject * parent,GstPadMode mode,gboolean active)209 gst_real_audio_demux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
210 GstPadMode mode, gboolean active)
211 {
212 gboolean res;
213 GstRealAudioDemux *demux;
214
215 demux = GST_REAL_AUDIO_DEMUX (parent);
216
217 switch (mode) {
218 case GST_PAD_MODE_PUSH:
219 demux->seekable = FALSE;
220 res = TRUE;
221 break;
222 case GST_PAD_MODE_PULL:
223 if (active) {
224 demux->seekable = TRUE;
225
226 res = gst_pad_start_task (sinkpad,
227 (GstTaskFunction) gst_real_audio_demux_loop, demux, NULL);
228 } else {
229 demux->seekable = FALSE;
230 res = gst_pad_stop_task (sinkpad);
231 }
232 break;
233 default:
234 res = FALSE;
235 break;
236 }
237 return res;
238 }
239
240 static GstFlowReturn
gst_real_audio_demux_parse_marker(GstRealAudioDemux * demux)241 gst_real_audio_demux_parse_marker (GstRealAudioDemux * demux)
242 {
243 guint8 data[6];
244
245 if (gst_adapter_available (demux->adapter) < 6) {
246 GST_LOG_OBJECT (demux, "need at least 6 bytes, waiting for more data");
247 return GST_FLOW_OK;
248 }
249
250 gst_adapter_copy (demux->adapter, data, 0, 6);
251 if (memcmp (data, ".ra\375", 4) != 0)
252 goto wrong_format;
253
254 demux->ra_version = GST_READ_UINT16_BE (data + 4);
255 GST_DEBUG_OBJECT (demux, "ra_version = %u", demux->ra_version);
256 if (demux->ra_version != 4 && demux->ra_version != 3)
257 goto unsupported_ra_version;
258
259 gst_adapter_flush (demux->adapter, 6);
260 demux->state = REAL_AUDIO_DEMUX_STATE_HEADER;
261 return GST_FLOW_OK;
262
263 /* ERRORS */
264 wrong_format:
265 {
266 GST_ELEMENT_ERROR (GST_ELEMENT (demux), STREAM, WRONG_TYPE, (NULL), (NULL));
267 return GST_FLOW_ERROR;
268 }
269
270 unsupported_ra_version:
271 {
272 GST_ELEMENT_ERROR (GST_ELEMENT (demux), STREAM, DECODE,
273 ("Cannot decode this RealAudio file, please file a bug"),
274 ("ra_version = %u", demux->ra_version));
275 return GST_FLOW_ERROR;
276 }
277 }
278
279 static GstClockTime
gst_real_demux_get_timestamp_from_offset(GstRealAudioDemux * demux,guint64 offset)280 gst_real_demux_get_timestamp_from_offset (GstRealAudioDemux * demux,
281 guint64 offset)
282 {
283 if (offset >= demux->data_offset && demux->byterate_num > 0 &&
284 demux->byterate_denom > 0) {
285 return gst_util_uint64_scale (offset - demux->data_offset,
286 demux->byterate_denom * GST_SECOND, demux->byterate_num);
287 } else if (offset == demux->data_offset) {
288 return (GstClockTime) 0;
289 } else {
290 return GST_CLOCK_TIME_NONE;
291 }
292 }
293
294 static gboolean
gst_real_audio_demux_get_data_offset_from_header(GstRealAudioDemux * demux)295 gst_real_audio_demux_get_data_offset_from_header (GstRealAudioDemux * demux)
296 {
297 guint8 data[16];
298
299 gst_adapter_copy (demux->adapter, data, 0, 16);
300
301 switch (demux->ra_version) {
302 case 3:
303 demux->data_offset = GST_READ_UINT16_BE (data) + 8;
304 break;
305 case 4:
306 demux->data_offset = GST_READ_UINT32_BE (data + 12) + 16;
307 break;
308 default:
309 demux->data_offset = 0;
310 g_return_val_if_reached (FALSE);
311 }
312
313 return TRUE;
314 }
315
316 static GstFlowReturn
gst_real_audio_demux_parse_header(GstRealAudioDemux * demux)317 gst_real_audio_demux_parse_header (GstRealAudioDemux * demux)
318 {
319 const guint8 *data;
320 gchar *codec_name = NULL;
321 GstCaps *caps = NULL;
322 GstEvent *event;
323 gchar *stream_id;
324 guint avail;
325
326 g_assert (demux->ra_version == 4 || demux->ra_version == 3);
327
328 avail = gst_adapter_available (demux->adapter);
329 if (avail < 16)
330 return GST_FLOW_OK;
331
332 if (!gst_real_audio_demux_get_data_offset_from_header (demux))
333 return GST_FLOW_ERROR; /* shouldn't happen */
334
335 GST_DEBUG_OBJECT (demux, "data_offset = %u", demux->data_offset);
336
337 if (avail + 6 < demux->data_offset) {
338 GST_DEBUG_OBJECT (demux, "Need %u bytes, but only %u available now",
339 demux->data_offset - 6, avail);
340 return GST_FLOW_OK;
341 }
342
343 data = gst_adapter_map (demux->adapter, demux->data_offset - 6);
344 g_assert (data);
345
346 switch (demux->ra_version) {
347 case 3:
348 demux->fourcc = GST_RM_AUD_14_4;
349 demux->packet_size = 20;
350 demux->sample_rate = 8000;
351 demux->channels = 1;
352 demux->sample_width = 16;
353 demux->flavour = 1;
354 demux->leaf_size = 0;
355 demux->height = 0;
356 break;
357 case 4:
358 demux->flavour = GST_READ_UINT16_BE (data + 16);
359 /* demux->frame_size = GST_READ_UINT32_BE (data + 36); */
360 demux->leaf_size = GST_READ_UINT16_BE (data + 38);
361 demux->height = GST_READ_UINT16_BE (data + 34);
362 demux->packet_size = GST_READ_UINT32_BE (data + 18);
363 demux->sample_rate = GST_READ_UINT16_BE (data + 42);
364 demux->sample_width = GST_READ_UINT16_BE (data + 46);
365 demux->channels = GST_READ_UINT16_BE (data + 48);
366 demux->fourcc = GST_READ_UINT32_LE (data + 56);
367 demux->pending_tags = gst_rm_utils_read_tags (data + 63,
368 demux->data_offset - 63, gst_rm_utils_read_string8);
369 if (demux->pending_tags)
370 gst_tag_list_set_scope (demux->pending_tags, GST_TAG_SCOPE_GLOBAL);
371 break;
372 default:
373 g_assert_not_reached ();
374 #if 0
375 case 5:
376 demux->flavour = GST_READ_UINT16_BE (data + 16);
377 /* demux->frame_size = GST_READ_UINT32_BE (data + 36); */
378 demux->leaf_size = GST_READ_UINT16_BE (data + 38);
379 demux->height = GST_READ_UINT16_BE (data + 34);
380
381 demux->sample_rate = GST_READ_UINT16_BE (data + 48);
382 demux->sample_width = GST_READ_UINT16_BE (data + 52);
383 demux->n_channels = GST_READ_UINT16_BE (data + 54);
384 demux->fourcc = RMDEMUX_FOURCC_GET (data + 60);
385 break;
386 #endif
387 }
388
389 GST_INFO_OBJECT (demux, "packet_size = %u", demux->packet_size);
390 GST_INFO_OBJECT (demux, "sample_rate = %u", demux->sample_rate);
391 GST_INFO_OBJECT (demux, "sample_width = %u", demux->sample_width);
392 GST_INFO_OBJECT (demux, "channels = %u", demux->channels);
393 GST_INFO_OBJECT (demux, "fourcc = '%" GST_FOURCC_FORMAT "' (%08X)",
394 GST_FOURCC_ARGS (demux->fourcc), demux->fourcc);
395
396 switch (demux->fourcc) {
397 case GST_RM_AUD_14_4:
398 caps = gst_caps_new_simple ("audio/x-pn-realaudio", "raversion",
399 G_TYPE_INT, 1, NULL);
400 demux->byterate_num = 1000;
401 demux->byterate_denom = 1;
402 break;
403
404 case GST_RM_AUD_28_8:
405 /* FIXME: needs descrambling */
406 caps = gst_caps_new_simple ("audio/x-pn-realaudio", "raversion",
407 G_TYPE_INT, 2, NULL);
408 break;
409
410 case GST_RM_AUD_DNET:
411 caps = gst_caps_new_simple ("audio/x-ac3", "rate", G_TYPE_INT,
412 demux->sample_rate, NULL);
413 if (demux->packet_size == 0 || demux->sample_rate == 0)
414 goto broken_file;
415 demux->byterate_num = demux->packet_size * demux->sample_rate;
416 demux->byterate_denom = 1536;
417 break;
418
419 /* Sipro/ACELP.NET Voice Codec (MIME unknown) */
420 case GST_RM_AUD_SIPR:
421 caps = gst_caps_new_empty_simple ("audio/x-sipro");
422 break;
423
424 default:
425 GST_WARNING_OBJECT (demux, "unknown fourcc %08X", demux->fourcc);
426 break;
427 }
428
429 if (caps == NULL)
430 goto unknown_fourcc;
431
432 gst_caps_set_simple (caps,
433 "flavor", G_TYPE_INT, demux->flavour,
434 "rate", G_TYPE_INT, demux->sample_rate,
435 "channels", G_TYPE_INT, demux->channels,
436 "width", G_TYPE_INT, demux->sample_width,
437 "leaf_size", G_TYPE_INT, demux->leaf_size,
438 "packet_size", G_TYPE_INT, demux->packet_size,
439 "height", G_TYPE_INT, demux->height, NULL);
440
441 GST_INFO_OBJECT (demux, "Adding source pad, caps %" GST_PTR_FORMAT, caps);
442 demux->srcpad = gst_pad_new_from_static_template (&src_template, "src");
443 gst_pad_set_event_function (demux->srcpad,
444 GST_DEBUG_FUNCPTR (gst_real_audio_demux_src_event));
445 gst_pad_set_query_function (demux->srcpad,
446 GST_DEBUG_FUNCPTR (gst_real_audio_demux_src_query));
447 gst_pad_set_active (demux->srcpad, TRUE);
448 gst_pad_use_fixed_caps (demux->srcpad);
449
450 stream_id =
451 gst_pad_create_stream_id (demux->srcpad, GST_ELEMENT_CAST (demux), NULL);
452
453 event = gst_pad_get_sticky_event (demux->sinkpad, GST_EVENT_STREAM_START, 0);
454 if (event) {
455 if (gst_event_parse_group_id (event, &demux->group_id))
456 demux->have_group_id = TRUE;
457 else
458 demux->have_group_id = FALSE;
459 gst_event_unref (event);
460 } else if (!demux->have_group_id) {
461 demux->have_group_id = TRUE;
462 demux->group_id = gst_util_group_id_next ();
463 }
464
465 event = gst_event_new_stream_start (stream_id);
466 if (demux->have_group_id)
467 gst_event_set_group_id (event, demux->group_id);
468
469 gst_pad_push_event (demux->srcpad, event);
470 g_free (stream_id);
471
472 gst_pad_set_caps (demux->srcpad, caps);
473 codec_name = gst_pb_utils_get_codec_description (caps);
474 gst_caps_unref (caps);
475
476 gst_element_add_pad (GST_ELEMENT (demux), demux->srcpad);
477
478 if (demux->byterate_num > 0 && demux->byterate_denom > 0) {
479 GstFormat bformat = GST_FORMAT_BYTES;
480 gint64 size_bytes = 0;
481
482 GST_INFO_OBJECT (demux, "byte rate = %u/%u = %u bytes/sec",
483 demux->byterate_num, demux->byterate_denom,
484 demux->byterate_num / demux->byterate_denom);
485
486 if (gst_pad_peer_query_duration (demux->sinkpad, bformat, &size_bytes)) {
487 demux->duration =
488 gst_real_demux_get_timestamp_from_offset (demux, size_bytes);
489 demux->upstream_size = size_bytes;
490 GST_INFO_OBJECT (demux, "upstream_size = %" G_GUINT64_FORMAT,
491 demux->upstream_size);
492 GST_INFO_OBJECT (demux, "duration = %" GST_TIME_FORMAT,
493 GST_TIME_ARGS (demux->duration));
494 }
495 }
496
497 demux->need_newsegment = TRUE;
498
499 if (codec_name) {
500 if (demux->pending_tags == NULL) {
501 demux->pending_tags = gst_tag_list_new_empty ();
502 gst_tag_list_set_scope (demux->pending_tags, GST_TAG_SCOPE_GLOBAL);
503 }
504
505 gst_tag_list_add (demux->pending_tags, GST_TAG_MERGE_REPLACE,
506 GST_TAG_AUDIO_CODEC, codec_name, NULL);
507 g_free (codec_name);
508 }
509
510 gst_adapter_unmap (demux->adapter);
511 gst_adapter_flush (demux->adapter, demux->data_offset - 6);
512
513 demux->state = REAL_AUDIO_DEMUX_STATE_DATA;
514 demux->need_newsegment = TRUE;
515
516 return GST_FLOW_OK;
517
518 /* ERRORS */
519 unknown_fourcc:
520 {
521 GST_ELEMENT_ERROR (GST_ELEMENT (demux), STREAM, DECODE, (NULL),
522 ("Unknown fourcc '0x%" G_GINT32_MODIFIER "x'", demux->fourcc));
523 return GST_FLOW_ERROR;
524 }
525 broken_file:
526 {
527 GST_ELEMENT_ERROR (GST_ELEMENT (demux), STREAM, DECODE, (NULL),
528 ("Broken file - invalid sample_rate or other header value"));
529 return GST_FLOW_ERROR;
530 }
531
532 }
533
534 static GstFlowReturn
gst_real_audio_demux_parse_data(GstRealAudioDemux * demux)535 gst_real_audio_demux_parse_data (GstRealAudioDemux * demux)
536 {
537 GstFlowReturn ret = GST_FLOW_OK;
538 guint avail, unit_size;
539
540 avail = gst_adapter_available (demux->adapter);
541
542 if (demux->packet_size > 0)
543 unit_size = demux->packet_size;
544 else
545 unit_size = avail & 0xfffffff0; /* round down to next multiple of 16 */
546
547 GST_LOG_OBJECT (demux, "available = %u, unit_size = %u", avail, unit_size);
548
549 while (ret == GST_FLOW_OK && unit_size > 0 && avail >= unit_size) {
550 GstClockTime ts;
551 GstBuffer *buf;
552
553 buf = gst_adapter_take_buffer (demux->adapter, unit_size);
554 avail -= unit_size;
555
556 if (demux->need_newsegment) {
557 gst_pad_push_event (demux->srcpad,
558 gst_event_new_segment (&demux->segment));
559 demux->need_newsegment = FALSE;
560 }
561
562 if (demux->pending_tags) {
563 gst_pad_push_event (demux->srcpad,
564 gst_event_new_tag (demux->pending_tags));
565 demux->pending_tags = NULL;
566 }
567
568 if (demux->fourcc == GST_RM_AUD_DNET) {
569 buf = gst_rm_utils_descramble_dnet_buffer (buf);
570 }
571
572 ts = gst_real_demux_get_timestamp_from_offset (demux, demux->offset);
573 GST_BUFFER_TIMESTAMP (buf) = ts;
574
575 demux->segment.position = ts;
576
577 ret = gst_pad_push (demux->srcpad, buf);
578 }
579
580 return ret;
581 }
582
583 static GstFlowReturn
gst_real_audio_demux_handle_buffer(GstRealAudioDemux * demux,GstBuffer * buf)584 gst_real_audio_demux_handle_buffer (GstRealAudioDemux * demux, GstBuffer * buf)
585 {
586 GstFlowReturn ret;
587
588 gst_adapter_push (demux->adapter, buf);
589 buf = NULL;
590
591 switch (demux->state) {
592 case REAL_AUDIO_DEMUX_STATE_MARKER:{
593 ret = gst_real_audio_demux_parse_marker (demux);
594 if (ret != GST_FLOW_OK || demux->state != REAL_AUDIO_DEMUX_STATE_HEADER)
595 break;
596 /* otherwise fall through */
597 }
598 case REAL_AUDIO_DEMUX_STATE_HEADER:{
599 ret = gst_real_audio_demux_parse_header (demux);
600 if (ret != GST_FLOW_OK || demux->state != REAL_AUDIO_DEMUX_STATE_DATA)
601 break;
602 /* otherwise fall through */
603 }
604 case REAL_AUDIO_DEMUX_STATE_DATA:{
605 ret = gst_real_audio_demux_parse_data (demux);
606 break;
607 }
608 default:
609 g_return_val_if_reached (GST_FLOW_ERROR);
610 }
611
612 return ret;
613 }
614
615 static GstFlowReturn
gst_real_audio_demux_chain(GstPad * pad,GstObject * parent,GstBuffer * buf)616 gst_real_audio_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
617 {
618 GstRealAudioDemux *demux;
619
620 demux = GST_REAL_AUDIO_DEMUX (parent);
621
622 return gst_real_audio_demux_handle_buffer (demux, buf);
623 }
624
625 static void
gst_real_audio_demux_loop(GstRealAudioDemux * demux)626 gst_real_audio_demux_loop (GstRealAudioDemux * demux)
627 {
628 GstFlowReturn ret;
629 GstBuffer *buf;
630 guint bytes_needed;
631
632 /* check how much data we need */
633 switch (demux->state) {
634 case REAL_AUDIO_DEMUX_STATE_MARKER:
635 bytes_needed = 6 + 16; /* 16 are beginning of header */
636 break;
637 case REAL_AUDIO_DEMUX_STATE_HEADER:
638 if (!gst_real_audio_demux_get_data_offset_from_header (demux))
639 goto parse_header_error;
640 bytes_needed = demux->data_offset - (6 + 16);
641 break;
642 case REAL_AUDIO_DEMUX_STATE_DATA:
643 if (demux->packet_size > 0) {
644 /* TODO: should probably take into account width/height as well? */
645 bytes_needed = demux->packet_size;
646 } else {
647 bytes_needed = 1024;
648 }
649 break;
650 default:
651 g_return_if_reached ();
652 }
653
654 /* now get the data */
655 GST_LOG_OBJECT (demux, "getting data: %5u bytes @ %8" G_GINT64_MODIFIER "u",
656 bytes_needed, demux->offset);
657
658 if (demux->upstream_size > 0 && demux->offset >= demux->upstream_size)
659 goto eos;
660
661 buf = NULL;
662 ret = gst_pad_pull_range (demux->sinkpad, demux->offset, bytes_needed, &buf);
663
664 if (ret != GST_FLOW_OK)
665 goto pull_range_error;
666
667 if (gst_buffer_get_size (buf) != bytes_needed)
668 goto pull_range_short_read;
669
670 ret = gst_real_audio_demux_handle_buffer (demux, buf);
671 if (ret != GST_FLOW_OK)
672 goto handle_flow_error;
673
674 /* TODO: increase this in chain function too (for timestamps)? */
675 demux->offset += bytes_needed;
676
677 /* check for the end of the segment */
678 if (demux->segment.stop != -1 && demux->segment.position != -1 &&
679 demux->segment.position > demux->segment.stop) {
680 GST_DEBUG_OBJECT (demux, "reached end of segment");
681 goto eos;
682 }
683
684 return;
685
686 /* ERRORS */
687 parse_header_error:
688 {
689 GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL), (NULL));
690 goto pause_task;
691 }
692 handle_flow_error:
693 {
694 GST_WARNING_OBJECT (demux, "handle_buf flow: %s", gst_flow_get_name (ret));
695 goto pause_task;
696 }
697 pull_range_error:
698 {
699 GST_WARNING_OBJECT (demux, "pull range flow: %s", gst_flow_get_name (ret));
700 goto pause_task;
701 }
702 pull_range_short_read:
703 {
704 GST_WARNING_OBJECT (demux, "pull range short read: wanted %u bytes, but "
705 "got only %" G_GSIZE_FORMAT " bytes", bytes_needed,
706 gst_buffer_get_size (buf));
707 gst_buffer_unref (buf);
708 goto eos;
709 }
710 eos:
711 {
712 if (demux->state != REAL_AUDIO_DEMUX_STATE_DATA) {
713 GST_WARNING_OBJECT (demux, "reached EOS before finished parsing header");
714 goto parse_header_error;
715 }
716 GST_INFO_OBJECT (demux, "EOS");
717 if ((demux->segment.flags & GST_SEEK_FLAG_SEGMENT) != 0) {
718 gint64 stop;
719
720 /* for segment playback we need to post when (in stream time)
721 * we stopped, this is either stop (when set) or the duration. */
722 if ((stop = demux->segment.stop) == -1)
723 stop = demux->segment.duration;
724
725 GST_DEBUG_OBJECT (demux, "sending segment done, at end of segment");
726 gst_element_post_message (GST_ELEMENT (demux),
727 gst_message_new_segment_done (GST_OBJECT (demux), GST_FORMAT_TIME,
728 stop));
729 gst_pad_push_event (demux->srcpad,
730 gst_event_new_segment_done (GST_FORMAT_TIME, stop));
731 } else {
732 /* normal playback, send EOS event downstream */
733 GST_DEBUG_OBJECT (demux, "sending EOS event, at end of stream");
734 gst_pad_push_event (demux->srcpad, gst_event_new_eos ());
735 }
736 goto pause_task;
737 }
738 pause_task:
739 {
740 demux->segment_running = FALSE;
741 gst_pad_pause_task (demux->sinkpad);
742 GST_DEBUG_OBJECT (demux, "pausing task");
743 return;
744 }
745 }
746
747 static gboolean
gst_real_audio_demux_sink_event(GstPad * pad,GstObject * parent,GstEvent * event)748 gst_real_audio_demux_sink_event (GstPad * pad, GstObject * parent,
749 GstEvent * event)
750 {
751 GstRealAudioDemux *demux;
752 gboolean ret;
753
754 demux = GST_REAL_AUDIO_DEMUX (parent);
755
756 switch (GST_EVENT_TYPE (event)) {
757 case GST_EVENT_SEGMENT:{
758 /* FIXME */
759 gst_event_unref (event);
760 demux->need_newsegment = TRUE;
761 ret = TRUE;
762 break;
763 }
764 default:
765 ret = gst_pad_event_default (pad, parent, event);
766 break;
767 }
768 return ret;
769 }
770
771 static gboolean
gst_real_audio_demux_handle_seek(GstRealAudioDemux * demux,GstEvent * event)772 gst_real_audio_demux_handle_seek (GstRealAudioDemux * demux, GstEvent * event)
773 {
774 GstFormat format;
775 GstSeekFlags flags;
776 GstSeekType cur_type, stop_type;
777 gboolean flush, update;
778 gdouble rate;
779 guint64 seek_pos;
780 gint64 cur, stop;
781
782 if (!demux->seekable)
783 goto not_seekable;
784
785 if (demux->byterate_num == 0 || demux->byterate_denom == 0)
786 goto no_bitrate;
787
788 gst_event_parse_seek (event, &rate, &format, &flags,
789 &cur_type, &cur, &stop_type, &stop);
790
791 if (format != GST_FORMAT_TIME)
792 goto only_time_format_supported;
793
794 if (rate <= 0.0)
795 goto cannot_do_backwards_playback;
796
797 flush = ((flags & GST_SEEK_FLAG_FLUSH) != 0);
798
799 GST_DEBUG_OBJECT (demux, "flush=%d, rate=%g", flush, rate);
800
801 /* unlock streaming thread and make streaming stop */
802 if (flush) {
803 gst_pad_push_event (demux->sinkpad, gst_event_new_flush_start ());
804 gst_pad_push_event (demux->srcpad, gst_event_new_flush_start ());
805 } else {
806 gst_pad_pause_task (demux->sinkpad);
807 }
808
809 GST_PAD_STREAM_LOCK (demux->sinkpad);
810
811 gst_segment_do_seek (&demux->segment, rate, format, flags,
812 cur_type, cur, stop_type, stop, &update);
813
814 GST_DEBUG_OBJECT (demux, "segment: %" GST_SEGMENT_FORMAT, &demux->segment);
815
816 seek_pos = gst_util_uint64_scale (demux->segment.start,
817 demux->byterate_num, demux->byterate_denom * GST_SECOND);
818 if (demux->packet_size > 0) {
819 seek_pos -= seek_pos % demux->packet_size;
820 }
821 seek_pos += demux->data_offset;
822
823 GST_DEBUG_OBJECT (demux, "seek_pos = %" G_GUINT64_FORMAT, seek_pos);
824
825 /* stop flushing */
826 gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop (TRUE));
827 gst_pad_push_event (demux->srcpad, gst_event_new_flush_stop (TRUE));
828
829 demux->offset = seek_pos;
830 demux->need_newsegment = TRUE;
831
832 /* notify start of new segment */
833 if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
834 gst_element_post_message (GST_ELEMENT (demux),
835 gst_message_new_segment_start (GST_OBJECT (demux),
836 GST_FORMAT_TIME, demux->segment.position));
837 }
838
839 demux->segment_running = TRUE;
840 /* restart our task since it might have been stopped when we did the flush */
841 gst_pad_start_task (demux->sinkpad,
842 (GstTaskFunction) gst_real_audio_demux_loop, demux, NULL);
843
844 /* streaming can continue now */
845 GST_PAD_STREAM_UNLOCK (demux->sinkpad);
846
847 return TRUE;
848
849 /* ERRORS */
850 not_seekable:
851 {
852 GST_DEBUG_OBJECT (demux, "seek failed: cannot seek in streaming mode");
853 return FALSE;
854 }
855 no_bitrate:
856 {
857 GST_DEBUG_OBJECT (demux, "seek failed: bitrate unknown");
858 return FALSE;
859 }
860 only_time_format_supported:
861 {
862 GST_DEBUG_OBJECT (demux, "can only seek in TIME format");
863 return FALSE;
864 }
865 cannot_do_backwards_playback:
866 {
867 GST_DEBUG_OBJECT (demux, "can only seek with positive rate, not %lf", rate);
868 return FALSE;
869 }
870 }
871
872 static gboolean
gst_real_audio_demux_src_event(GstPad * pad,GstObject * parent,GstEvent * event)873 gst_real_audio_demux_src_event (GstPad * pad, GstObject * parent,
874 GstEvent * event)
875 {
876 GstRealAudioDemux *demux;
877 gboolean ret = FALSE;
878
879 demux = GST_REAL_AUDIO_DEMUX (parent);
880
881 switch (GST_EVENT_TYPE (event)) {
882 case GST_EVENT_QOS:
883 gst_event_unref (event);
884 break;
885 case GST_EVENT_SEEK:
886 ret = gst_real_audio_demux_handle_seek (demux, event);
887 gst_event_unref (event);
888 break;
889 default:
890 ret = gst_pad_event_default (pad, parent, event);
891 break;
892 }
893
894 return ret;
895 }
896
897 static gboolean
gst_real_audio_demux_src_query(GstPad * pad,GstObject * parent,GstQuery * query)898 gst_real_audio_demux_src_query (GstPad * pad, GstObject * parent,
899 GstQuery * query)
900 {
901 GstRealAudioDemux *demux;
902 gboolean ret = FALSE;
903
904 demux = GST_REAL_AUDIO_DEMUX (parent);
905
906 switch (GST_QUERY_TYPE (query)) {
907 case GST_QUERY_DURATION:{
908 GstFormat format;
909
910 gst_query_parse_duration (query, &format, NULL);
911 if (format == GST_FORMAT_TIME && demux->duration > 0) {
912 gst_query_set_duration (query, GST_FORMAT_TIME, demux->duration);
913 ret = TRUE;
914 } else if (format == GST_FORMAT_BYTES && demux->upstream_size > 0) {
915 gst_query_set_duration (query, GST_FORMAT_BYTES,
916 demux->upstream_size - demux->data_offset);
917 ret = TRUE;
918 }
919 break;
920 }
921 case GST_QUERY_SEEKING:{
922 GstFormat format;
923 gboolean seekable;
924
925 gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
926 seekable = (format == GST_FORMAT_TIME && demux->seekable);
927 gst_query_set_seeking (query, format, seekable, 0,
928 (format == GST_FORMAT_TIME) ? demux->duration : -1);
929 ret = TRUE;
930 break;
931 }
932 case GST_QUERY_SEGMENT:
933 {
934 GstFormat format;
935 gint64 start, stop;
936
937 format = demux->segment.format;
938
939 start =
940 gst_segment_to_stream_time (&demux->segment, format,
941 demux->segment.start);
942 if ((stop = demux->segment.stop) == -1)
943 stop = demux->segment.duration;
944 else
945 stop = gst_segment_to_stream_time (&demux->segment, format, stop);
946
947 gst_query_set_segment (query, demux->segment.rate, format, start, stop);
948 ret = TRUE;
949 break;
950 }
951 default:
952 ret = gst_pad_query_default (pad, parent, query);
953 break;
954 }
955
956 return ret;
957 }
958
959 static GstStateChangeReturn
gst_real_audio_demux_change_state(GstElement * element,GstStateChange transition)960 gst_real_audio_demux_change_state (GstElement * element,
961 GstStateChange transition)
962 {
963 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
964 GstRealAudioDemux *demux = GST_REAL_AUDIO_DEMUX (element);
965
966 switch (transition) {
967 case GST_STATE_CHANGE_NULL_TO_READY:
968 break;
969 case GST_STATE_CHANGE_READY_TO_PAUSED:
970 demux->state = REAL_AUDIO_DEMUX_STATE_MARKER;
971 demux->segment_running = FALSE;
972 gst_segment_init (&demux->segment, GST_FORMAT_TIME);
973 gst_adapter_clear (demux->adapter);
974 break;
975 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
976 break;
977 default:
978 break;
979 }
980
981 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
982
983 switch (transition) {
984 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
985 break;
986 case GST_STATE_CHANGE_PAUSED_TO_READY:{
987 gst_real_audio_demux_reset (demux);
988 gst_segment_init (&demux->segment, GST_FORMAT_UNDEFINED);
989 break;
990 }
991 case GST_STATE_CHANGE_READY_TO_NULL:
992 break;
993 default:
994 break;
995 }
996
997 return ret;
998 }
999
1000 gboolean
gst_rademux_plugin_init(GstPlugin * plugin)1001 gst_rademux_plugin_init (GstPlugin * plugin)
1002 {
1003 return gst_element_register (plugin, "rademux",
1004 GST_RANK_SECONDARY, GST_TYPE_REAL_AUDIO_DEMUX);
1005 }
1006