1 /* GStreamer RealAudio demuxer
2 * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
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., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 * SECTION:element-rademux
24 * Demuxes/parses a RealAudio (.ra) file or stream into compressed audio.
26 * ## Example launch line
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.
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.
48 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
51 GST_STATIC_CAPS ("application/x-pn-realaudio")
54 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
59 GST_DEBUG_CATEGORY_STATIC (real_audio_demux_debug);
60 #define GST_CAT_DEFAULT real_audio_demux_debug
62 #define gst_real_audio_demux_parent_class parent_class
63 G_DEFINE_TYPE (GstRealAudioDemux, gst_real_audio_demux, GST_TYPE_ELEMENT);
64 GST_ELEMENT_REGISTER_DEFINE (rademux, "rademux",
65 GST_RANK_SECONDARY, GST_TYPE_REAL_AUDIO_DEMUX);
67 static GstStateChangeReturn gst_real_audio_demux_change_state (GstElement * e,
68 GstStateChange transition);
69 static GstFlowReturn gst_real_audio_demux_chain (GstPad * pad,
70 GstObject * parent, GstBuffer * buf);
71 static gboolean gst_real_audio_demux_sink_event (GstPad * pad,
72 GstObject * parent, GstEvent * ev);
73 static gboolean gst_real_audio_demux_src_event (GstPad * pad,
74 GstObject * parent, GstEvent * ev);
75 static gboolean gst_real_audio_demux_src_query (GstPad * pad,
76 GstObject * parent, GstQuery * query);
77 static void gst_real_audio_demux_loop (GstRealAudioDemux * demux);
78 static gboolean gst_real_audio_demux_sink_activate (GstPad * sinkpad,
80 static gboolean gst_real_audio_demux_sink_activate_mode (GstPad * sinkpad,
81 GstObject * parent, GstPadMode mode, gboolean active);
84 gst_real_audio_demux_finalize (GObject * obj)
86 GstRealAudioDemux *demux = GST_REAL_AUDIO_DEMUX (obj);
88 g_object_unref (demux->adapter);
90 G_OBJECT_CLASS (parent_class)->finalize (obj);
94 gst_real_audio_demux_class_init (GstRealAudioDemuxClass * klass)
96 GObjectClass *gobject_class = (GObjectClass *) klass;
97 GstElementClass *gstelement_class = (GstElementClass *) klass;
99 gobject_class->finalize = gst_real_audio_demux_finalize;
101 gst_element_class_add_static_pad_template (gstelement_class, &sink_template);
102 gst_element_class_add_static_pad_template (gstelement_class, &src_template);
104 gst_element_class_set_static_metadata (gstelement_class, "RealAudio Demuxer",
106 "Demultiplex a RealAudio file",
107 "Tim-Philipp Müller <tim centricular net>");
109 gstelement_class->change_state =
110 GST_DEBUG_FUNCPTR (gst_real_audio_demux_change_state);
112 GST_DEBUG_CATEGORY_INIT (real_audio_demux_debug, "rademux",
113 0, "Demuxer for RealAudio streams");
117 gst_real_audio_demux_reset (GstRealAudioDemux * demux)
119 gst_adapter_clear (demux->adapter);
122 GST_DEBUG_OBJECT (demux, "Removing source pad");
123 gst_element_remove_pad (GST_ELEMENT (demux), demux->srcpad);
124 demux->srcpad = NULL;
127 if (demux->pending_tags) {
128 gst_tag_list_unref (demux->pending_tags);
129 demux->pending_tags = NULL;
132 demux->state = REAL_AUDIO_DEMUX_STATE_MARKER;
133 demux->ra_version = 0;
134 demux->data_offset = 0;
135 demux->packet_size = 0;
137 demux->sample_rate = 0;
138 demux->sample_width = 0;
142 demux->need_newsegment = TRUE;
144 demux->segment_running = FALSE;
146 demux->byterate_num = 0;
147 demux->byterate_denom = 0;
150 demux->upstream_size = 0;
154 demux->have_group_id = FALSE;
155 demux->group_id = G_MAXUINT;
157 gst_adapter_clear (demux->adapter);
161 gst_real_audio_demux_init (GstRealAudioDemux * demux)
163 demux->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
165 gst_pad_set_chain_function (demux->sinkpad,
166 GST_DEBUG_FUNCPTR (gst_real_audio_demux_chain));
167 gst_pad_set_event_function (demux->sinkpad,
168 GST_DEBUG_FUNCPTR (gst_real_audio_demux_sink_event));
169 gst_pad_set_activate_function (demux->sinkpad,
170 GST_DEBUG_FUNCPTR (gst_real_audio_demux_sink_activate));
171 gst_pad_set_activatemode_function (demux->sinkpad,
172 GST_DEBUG_FUNCPTR (gst_real_audio_demux_sink_activate_mode));
174 gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
176 demux->adapter = gst_adapter_new ();
177 gst_real_audio_demux_reset (demux);
181 gst_real_audio_demux_sink_activate (GstPad * sinkpad, GstObject * parent)
186 query = gst_query_new_scheduling ();
188 if (!gst_pad_peer_query (sinkpad, query)) {
189 gst_query_unref (query);
193 pull_mode = gst_query_has_scheduling_mode_with_flags (query,
194 GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
195 gst_query_unref (query);
200 GST_DEBUG_OBJECT (sinkpad, "activating pull");
201 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
205 GST_DEBUG_OBJECT (sinkpad, "activating push");
206 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
211 gst_real_audio_demux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
212 GstPadMode mode, gboolean active)
215 GstRealAudioDemux *demux;
217 demux = GST_REAL_AUDIO_DEMUX (parent);
220 case GST_PAD_MODE_PUSH:
221 demux->seekable = FALSE;
224 case GST_PAD_MODE_PULL:
226 demux->seekable = TRUE;
228 res = gst_pad_start_task (sinkpad,
229 (GstTaskFunction) gst_real_audio_demux_loop, demux, NULL);
231 demux->seekable = FALSE;
232 res = gst_pad_stop_task (sinkpad);
243 gst_real_audio_demux_parse_marker (GstRealAudioDemux * demux)
247 if (gst_adapter_available (demux->adapter) < 6) {
248 GST_LOG_OBJECT (demux, "need at least 6 bytes, waiting for more data");
252 gst_adapter_copy (demux->adapter, data, 0, 6);
253 if (memcmp (data, ".ra\375", 4) != 0)
256 demux->ra_version = GST_READ_UINT16_BE (data + 4);
257 GST_DEBUG_OBJECT (demux, "ra_version = %u", demux->ra_version);
258 if (demux->ra_version != 4 && demux->ra_version != 3)
259 goto unsupported_ra_version;
261 gst_adapter_flush (demux->adapter, 6);
262 demux->state = REAL_AUDIO_DEMUX_STATE_HEADER;
268 GST_ELEMENT_ERROR (GST_ELEMENT (demux), STREAM, WRONG_TYPE, (NULL), (NULL));
269 return GST_FLOW_ERROR;
272 unsupported_ra_version:
274 GST_ELEMENT_ERROR (GST_ELEMENT (demux), STREAM, DECODE,
275 ("Cannot decode this RealAudio file, please file a bug"),
276 ("ra_version = %u", demux->ra_version));
277 return GST_FLOW_ERROR;
282 gst_real_demux_get_timestamp_from_offset (GstRealAudioDemux * demux,
285 if (offset >= demux->data_offset && demux->byterate_num > 0 &&
286 demux->byterate_denom > 0) {
287 return gst_util_uint64_scale (offset - demux->data_offset,
288 demux->byterate_denom * GST_SECOND, demux->byterate_num);
289 } else if (offset == demux->data_offset) {
290 return (GstClockTime) 0;
292 return GST_CLOCK_TIME_NONE;
297 gst_real_audio_demux_get_data_offset_from_header (GstRealAudioDemux * demux)
301 gst_adapter_copy (demux->adapter, data, 0, 16);
303 switch (demux->ra_version) {
305 demux->data_offset = GST_READ_UINT16_BE (data) + 8;
308 demux->data_offset = GST_READ_UINT32_BE (data + 12) + 16;
311 demux->data_offset = 0;
312 g_return_val_if_reached (FALSE);
319 gst_real_audio_demux_parse_header (GstRealAudioDemux * demux)
322 gchar *codec_name = NULL;
323 GstCaps *caps = NULL;
328 g_assert (demux->ra_version == 4 || demux->ra_version == 3);
330 avail = gst_adapter_available (demux->adapter);
334 if (!gst_real_audio_demux_get_data_offset_from_header (demux))
335 return GST_FLOW_ERROR; /* shouldn't happen */
337 GST_DEBUG_OBJECT (demux, "data_offset = %u", demux->data_offset);
339 if (avail + 6 < demux->data_offset) {
340 GST_DEBUG_OBJECT (demux, "Need %u bytes, but only %u available now",
341 demux->data_offset - 6, avail);
345 data = gst_adapter_map (demux->adapter, demux->data_offset - 6);
348 switch (demux->ra_version) {
350 demux->fourcc = GST_RM_AUD_14_4;
351 demux->packet_size = 20;
352 demux->sample_rate = 8000;
354 demux->sample_width = 16;
356 demux->leaf_size = 0;
360 demux->flavour = GST_READ_UINT16_BE (data + 16);
361 /* demux->frame_size = GST_READ_UINT32_BE (data + 36); */
362 demux->leaf_size = GST_READ_UINT16_BE (data + 38);
363 demux->height = GST_READ_UINT16_BE (data + 34);
364 demux->packet_size = GST_READ_UINT32_BE (data + 18);
365 demux->sample_rate = GST_READ_UINT16_BE (data + 42);
366 demux->sample_width = GST_READ_UINT16_BE (data + 46);
367 demux->channels = GST_READ_UINT16_BE (data + 48);
368 demux->fourcc = GST_READ_UINT32_LE (data + 56);
369 demux->pending_tags = gst_rm_utils_read_tags (data + 63,
370 demux->data_offset - 63, gst_rm_utils_read_string8);
371 if (demux->pending_tags)
372 gst_tag_list_set_scope (demux->pending_tags, GST_TAG_SCOPE_GLOBAL);
375 g_assert_not_reached ();
378 demux->flavour = GST_READ_UINT16_BE (data + 16);
379 /* demux->frame_size = GST_READ_UINT32_BE (data + 36); */
380 demux->leaf_size = GST_READ_UINT16_BE (data + 38);
381 demux->height = GST_READ_UINT16_BE (data + 34);
383 demux->sample_rate = GST_READ_UINT16_BE (data + 48);
384 demux->sample_width = GST_READ_UINT16_BE (data + 52);
385 demux->n_channels = GST_READ_UINT16_BE (data + 54);
386 demux->fourcc = RMDEMUX_FOURCC_GET (data + 60);
391 GST_INFO_OBJECT (demux, "packet_size = %u", demux->packet_size);
392 GST_INFO_OBJECT (demux, "sample_rate = %u", demux->sample_rate);
393 GST_INFO_OBJECT (demux, "sample_width = %u", demux->sample_width);
394 GST_INFO_OBJECT (demux, "channels = %u", demux->channels);
395 GST_INFO_OBJECT (demux, "fourcc = '%" GST_FOURCC_FORMAT "' (%08X)",
396 GST_FOURCC_ARGS (demux->fourcc), demux->fourcc);
398 switch (demux->fourcc) {
399 case GST_RM_AUD_14_4:
400 caps = gst_caps_new_simple ("audio/x-pn-realaudio", "raversion",
401 G_TYPE_INT, 1, NULL);
402 demux->byterate_num = 1000;
403 demux->byterate_denom = 1;
406 case GST_RM_AUD_28_8:
407 /* FIXME: needs descrambling */
408 caps = gst_caps_new_simple ("audio/x-pn-realaudio", "raversion",
409 G_TYPE_INT, 2, NULL);
412 case GST_RM_AUD_DNET:
413 caps = gst_caps_new_simple ("audio/x-ac3", "rate", G_TYPE_INT,
414 demux->sample_rate, NULL);
415 if (demux->packet_size == 0 || demux->sample_rate == 0)
417 demux->byterate_num = demux->packet_size * demux->sample_rate;
418 demux->byterate_denom = 1536;
421 /* Sipro/ACELP.NET Voice Codec (MIME unknown) */
422 case GST_RM_AUD_SIPR:
423 caps = gst_caps_new_empty_simple ("audio/x-sipro");
427 GST_WARNING_OBJECT (demux, "unknown fourcc %08X", demux->fourcc);
434 gst_caps_set_simple (caps,
435 "flavor", G_TYPE_INT, demux->flavour,
436 "rate", G_TYPE_INT, demux->sample_rate,
437 "channels", G_TYPE_INT, demux->channels,
438 "width", G_TYPE_INT, demux->sample_width,
439 "leaf_size", G_TYPE_INT, demux->leaf_size,
440 "packet_size", G_TYPE_INT, demux->packet_size,
441 "height", G_TYPE_INT, demux->height, NULL);
443 GST_INFO_OBJECT (demux, "Adding source pad, caps %" GST_PTR_FORMAT, caps);
444 demux->srcpad = gst_pad_new_from_static_template (&src_template, "src");
445 gst_pad_set_event_function (demux->srcpad,
446 GST_DEBUG_FUNCPTR (gst_real_audio_demux_src_event));
447 gst_pad_set_query_function (demux->srcpad,
448 GST_DEBUG_FUNCPTR (gst_real_audio_demux_src_query));
449 gst_pad_set_active (demux->srcpad, TRUE);
450 gst_pad_use_fixed_caps (demux->srcpad);
453 gst_pad_create_stream_id (demux->srcpad, GST_ELEMENT_CAST (demux), NULL);
455 event = gst_pad_get_sticky_event (demux->sinkpad, GST_EVENT_STREAM_START, 0);
457 if (gst_event_parse_group_id (event, &demux->group_id))
458 demux->have_group_id = TRUE;
460 demux->have_group_id = FALSE;
461 gst_event_unref (event);
462 } else if (!demux->have_group_id) {
463 demux->have_group_id = TRUE;
464 demux->group_id = gst_util_group_id_next ();
467 event = gst_event_new_stream_start (stream_id);
468 if (demux->have_group_id)
469 gst_event_set_group_id (event, demux->group_id);
471 gst_pad_push_event (demux->srcpad, event);
474 gst_pad_set_caps (demux->srcpad, caps);
475 codec_name = gst_pb_utils_get_codec_description (caps);
476 gst_caps_unref (caps);
478 gst_element_add_pad (GST_ELEMENT (demux), demux->srcpad);
480 if (demux->byterate_num > 0 && demux->byterate_denom > 0) {
481 GstFormat bformat = GST_FORMAT_BYTES;
482 gint64 size_bytes = 0;
484 GST_INFO_OBJECT (demux, "byte rate = %u/%u = %u bytes/sec",
485 demux->byterate_num, demux->byterate_denom,
486 demux->byterate_num / demux->byterate_denom);
488 if (gst_pad_peer_query_duration (demux->sinkpad, bformat, &size_bytes)) {
490 gst_real_demux_get_timestamp_from_offset (demux, size_bytes);
491 demux->upstream_size = size_bytes;
492 GST_INFO_OBJECT (demux, "upstream_size = %" G_GUINT64_FORMAT,
493 demux->upstream_size);
494 GST_INFO_OBJECT (demux, "duration = %" GST_TIME_FORMAT,
495 GST_TIME_ARGS (demux->duration));
499 demux->need_newsegment = TRUE;
502 if (demux->pending_tags == NULL) {
503 demux->pending_tags = gst_tag_list_new_empty ();
504 gst_tag_list_set_scope (demux->pending_tags, GST_TAG_SCOPE_GLOBAL);
507 gst_tag_list_add (demux->pending_tags, GST_TAG_MERGE_REPLACE,
508 GST_TAG_AUDIO_CODEC, codec_name, NULL);
512 gst_adapter_unmap (demux->adapter);
513 gst_adapter_flush (demux->adapter, demux->data_offset - 6);
515 demux->state = REAL_AUDIO_DEMUX_STATE_DATA;
516 demux->need_newsegment = TRUE;
523 GST_ELEMENT_ERROR (GST_ELEMENT (demux), STREAM, DECODE, (NULL),
524 ("Unknown fourcc '0x%" G_GINT32_MODIFIER "x'", demux->fourcc));
525 return GST_FLOW_ERROR;
529 GST_ELEMENT_ERROR (GST_ELEMENT (demux), STREAM, DECODE, (NULL),
530 ("Broken file - invalid sample_rate or other header value"));
531 return GST_FLOW_ERROR;
537 gst_real_audio_demux_parse_data (GstRealAudioDemux * demux)
539 GstFlowReturn ret = GST_FLOW_OK;
540 guint avail, unit_size;
542 avail = gst_adapter_available (demux->adapter);
544 if (demux->packet_size > 0)
545 unit_size = demux->packet_size;
547 unit_size = avail & 0xfffffff0; /* round down to next multiple of 16 */
549 GST_LOG_OBJECT (demux, "available = %u, unit_size = %u", avail, unit_size);
551 while (ret == GST_FLOW_OK && unit_size > 0 && avail >= unit_size) {
555 buf = gst_adapter_take_buffer (demux->adapter, unit_size);
558 if (demux->need_newsegment) {
559 gst_pad_push_event (demux->srcpad,
560 gst_event_new_segment (&demux->segment));
561 demux->need_newsegment = FALSE;
564 if (demux->pending_tags) {
565 gst_pad_push_event (demux->srcpad,
566 gst_event_new_tag (demux->pending_tags));
567 demux->pending_tags = NULL;
570 if (demux->fourcc == GST_RM_AUD_DNET) {
571 buf = gst_rm_utils_descramble_dnet_buffer (buf);
574 ts = gst_real_demux_get_timestamp_from_offset (demux, demux->offset);
575 GST_BUFFER_TIMESTAMP (buf) = ts;
577 demux->segment.position = ts;
579 ret = gst_pad_push (demux->srcpad, buf);
586 gst_real_audio_demux_handle_buffer (GstRealAudioDemux * demux, GstBuffer * buf)
590 gst_adapter_push (demux->adapter, buf);
593 switch (demux->state) {
594 case REAL_AUDIO_DEMUX_STATE_MARKER:{
595 ret = gst_real_audio_demux_parse_marker (demux);
596 if (ret != GST_FLOW_OK || demux->state != REAL_AUDIO_DEMUX_STATE_HEADER)
598 /* otherwise fall through */
600 case REAL_AUDIO_DEMUX_STATE_HEADER:{
601 ret = gst_real_audio_demux_parse_header (demux);
602 if (ret != GST_FLOW_OK || demux->state != REAL_AUDIO_DEMUX_STATE_DATA)
604 /* otherwise fall through */
606 case REAL_AUDIO_DEMUX_STATE_DATA:{
607 ret = gst_real_audio_demux_parse_data (demux);
611 g_return_val_if_reached (GST_FLOW_ERROR);
618 gst_real_audio_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
620 GstRealAudioDemux *demux;
622 demux = GST_REAL_AUDIO_DEMUX (parent);
624 return gst_real_audio_demux_handle_buffer (demux, buf);
628 gst_real_audio_demux_loop (GstRealAudioDemux * demux)
634 /* check how much data we need */
635 switch (demux->state) {
636 case REAL_AUDIO_DEMUX_STATE_MARKER:
637 bytes_needed = 6 + 16; /* 16 are beginning of header */
639 case REAL_AUDIO_DEMUX_STATE_HEADER:
640 if (!gst_real_audio_demux_get_data_offset_from_header (demux))
641 goto parse_header_error;
642 bytes_needed = demux->data_offset - (6 + 16);
644 case REAL_AUDIO_DEMUX_STATE_DATA:
645 if (demux->packet_size > 0) {
646 /* TODO: should probably take into account width/height as well? */
647 bytes_needed = demux->packet_size;
653 g_return_if_reached ();
656 /* now get the data */
657 GST_LOG_OBJECT (demux, "getting data: %5u bytes @ %8" G_GINT64_MODIFIER "u",
658 bytes_needed, demux->offset);
660 if (demux->upstream_size > 0 && demux->offset >= demux->upstream_size)
664 ret = gst_pad_pull_range (demux->sinkpad, demux->offset, bytes_needed, &buf);
666 if (ret != GST_FLOW_OK)
667 goto pull_range_error;
669 if (gst_buffer_get_size (buf) != bytes_needed)
670 goto pull_range_short_read;
672 ret = gst_real_audio_demux_handle_buffer (demux, buf);
673 if (ret != GST_FLOW_OK)
674 goto handle_flow_error;
676 /* TODO: increase this in chain function too (for timestamps)? */
677 demux->offset += bytes_needed;
679 /* check for the end of the segment */
680 if (demux->segment.stop != -1 && demux->segment.position != -1 &&
681 demux->segment.position > demux->segment.stop) {
682 GST_DEBUG_OBJECT (demux, "reached end of segment");
691 GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL), (NULL));
696 GST_WARNING_OBJECT (demux, "handle_buf flow: %s", gst_flow_get_name (ret));
701 GST_WARNING_OBJECT (demux, "pull range flow: %s", gst_flow_get_name (ret));
704 pull_range_short_read:
706 GST_WARNING_OBJECT (demux, "pull range short read: wanted %u bytes, but "
707 "got only %" G_GSIZE_FORMAT " bytes", bytes_needed,
708 gst_buffer_get_size (buf));
709 gst_buffer_unref (buf);
714 if (demux->state != REAL_AUDIO_DEMUX_STATE_DATA) {
715 GST_WARNING_OBJECT (demux, "reached EOS before finished parsing header");
716 goto parse_header_error;
718 GST_INFO_OBJECT (demux, "EOS");
719 if ((demux->segment.flags & GST_SEEK_FLAG_SEGMENT) != 0) {
722 /* for segment playback we need to post when (in stream time)
723 * we stopped, this is either stop (when set) or the duration. */
724 if ((stop = demux->segment.stop) == -1)
725 stop = demux->segment.duration;
727 GST_DEBUG_OBJECT (demux, "sending segment done, at end of segment");
728 gst_element_post_message (GST_ELEMENT (demux),
729 gst_message_new_segment_done (GST_OBJECT (demux), GST_FORMAT_TIME,
731 gst_pad_push_event (demux->srcpad,
732 gst_event_new_segment_done (GST_FORMAT_TIME, stop));
734 /* normal playback, send EOS event downstream */
735 GST_DEBUG_OBJECT (demux, "sending EOS event, at end of stream");
736 gst_pad_push_event (demux->srcpad, gst_event_new_eos ());
742 demux->segment_running = FALSE;
743 gst_pad_pause_task (demux->sinkpad);
744 GST_DEBUG_OBJECT (demux, "pausing task");
750 gst_real_audio_demux_sink_event (GstPad * pad, GstObject * parent,
753 GstRealAudioDemux *demux;
756 demux = GST_REAL_AUDIO_DEMUX (parent);
758 switch (GST_EVENT_TYPE (event)) {
759 case GST_EVENT_SEGMENT:{
761 gst_event_unref (event);
762 demux->need_newsegment = TRUE;
767 ret = gst_pad_event_default (pad, parent, event);
774 gst_real_audio_demux_handle_seek (GstRealAudioDemux * demux, GstEvent * event)
778 GstSeekType cur_type, stop_type;
779 gboolean flush, update;
784 if (!demux->seekable)
787 if (demux->byterate_num == 0 || demux->byterate_denom == 0)
790 gst_event_parse_seek (event, &rate, &format, &flags,
791 &cur_type, &cur, &stop_type, &stop);
793 if (format != GST_FORMAT_TIME)
794 goto only_time_format_supported;
797 goto cannot_do_backwards_playback;
799 flush = ((flags & GST_SEEK_FLAG_FLUSH) != 0);
801 GST_DEBUG_OBJECT (demux, "flush=%d, rate=%g", flush, rate);
803 /* unlock streaming thread and make streaming stop */
805 gst_pad_push_event (demux->sinkpad, gst_event_new_flush_start ());
806 gst_pad_push_event (demux->srcpad, gst_event_new_flush_start ());
808 gst_pad_pause_task (demux->sinkpad);
811 GST_PAD_STREAM_LOCK (demux->sinkpad);
813 gst_segment_do_seek (&demux->segment, rate, format, flags,
814 cur_type, cur, stop_type, stop, &update);
816 GST_DEBUG_OBJECT (demux, "segment: %" GST_SEGMENT_FORMAT, &demux->segment);
818 seek_pos = gst_util_uint64_scale (demux->segment.start,
819 demux->byterate_num, demux->byterate_denom * GST_SECOND);
820 if (demux->packet_size > 0) {
821 seek_pos -= seek_pos % demux->packet_size;
823 seek_pos += demux->data_offset;
825 GST_DEBUG_OBJECT (demux, "seek_pos = %" G_GUINT64_FORMAT, seek_pos);
828 gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop (TRUE));
829 gst_pad_push_event (demux->srcpad, gst_event_new_flush_stop (TRUE));
831 demux->offset = seek_pos;
832 demux->need_newsegment = TRUE;
834 /* notify start of new segment */
835 if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
836 gst_element_post_message (GST_ELEMENT (demux),
837 gst_message_new_segment_start (GST_OBJECT (demux),
838 GST_FORMAT_TIME, demux->segment.position));
841 demux->segment_running = TRUE;
842 /* restart our task since it might have been stopped when we did the flush */
843 gst_pad_start_task (demux->sinkpad,
844 (GstTaskFunction) gst_real_audio_demux_loop, demux, NULL);
846 /* streaming can continue now */
847 GST_PAD_STREAM_UNLOCK (demux->sinkpad);
854 GST_DEBUG_OBJECT (demux, "seek failed: cannot seek in streaming mode");
859 GST_DEBUG_OBJECT (demux, "seek failed: bitrate unknown");
862 only_time_format_supported:
864 GST_DEBUG_OBJECT (demux, "can only seek in TIME format");
867 cannot_do_backwards_playback:
869 GST_DEBUG_OBJECT (demux, "can only seek with positive rate, not %lf", rate);
875 gst_real_audio_demux_src_event (GstPad * pad, GstObject * parent,
878 GstRealAudioDemux *demux;
879 gboolean ret = FALSE;
881 demux = GST_REAL_AUDIO_DEMUX (parent);
883 switch (GST_EVENT_TYPE (event)) {
885 gst_event_unref (event);
888 ret = gst_real_audio_demux_handle_seek (demux, event);
889 gst_event_unref (event);
892 ret = gst_pad_event_default (pad, parent, event);
900 gst_real_audio_demux_src_query (GstPad * pad, GstObject * parent,
903 GstRealAudioDemux *demux;
904 gboolean ret = FALSE;
906 demux = GST_REAL_AUDIO_DEMUX (parent);
908 switch (GST_QUERY_TYPE (query)) {
909 case GST_QUERY_DURATION:{
912 gst_query_parse_duration (query, &format, NULL);
913 if (format == GST_FORMAT_TIME && demux->duration > 0) {
914 gst_query_set_duration (query, GST_FORMAT_TIME, demux->duration);
916 } else if (format == GST_FORMAT_BYTES && demux->upstream_size > 0) {
917 gst_query_set_duration (query, GST_FORMAT_BYTES,
918 demux->upstream_size - demux->data_offset);
923 case GST_QUERY_SEEKING:{
927 gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
928 seekable = (format == GST_FORMAT_TIME && demux->seekable);
929 gst_query_set_seeking (query, format, seekable, 0,
930 (format == GST_FORMAT_TIME) ? demux->duration : -1);
934 case GST_QUERY_SEGMENT:
939 format = demux->segment.format;
942 gst_segment_to_stream_time (&demux->segment, format,
943 demux->segment.start);
944 if ((stop = demux->segment.stop) == -1)
945 stop = demux->segment.duration;
947 stop = gst_segment_to_stream_time (&demux->segment, format, stop);
949 gst_query_set_segment (query, demux->segment.rate, format, start, stop);
954 ret = gst_pad_query_default (pad, parent, query);
961 static GstStateChangeReturn
962 gst_real_audio_demux_change_state (GstElement * element,
963 GstStateChange transition)
965 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
966 GstRealAudioDemux *demux = GST_REAL_AUDIO_DEMUX (element);
968 switch (transition) {
969 case GST_STATE_CHANGE_NULL_TO_READY:
971 case GST_STATE_CHANGE_READY_TO_PAUSED:
972 demux->state = REAL_AUDIO_DEMUX_STATE_MARKER;
973 demux->segment_running = FALSE;
974 gst_segment_init (&demux->segment, GST_FORMAT_TIME);
975 gst_adapter_clear (demux->adapter);
977 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
983 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
985 switch (transition) {
986 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
988 case GST_STATE_CHANGE_PAUSED_TO_READY:{
989 gst_real_audio_demux_reset (demux);
990 gst_segment_init (&demux->segment, GST_FORMAT_UNDEFINED);
993 case GST_STATE_CHANGE_READY_TO_NULL: