Merging gst-plugins-ugly
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-ugly / gst / realmedia / rademux.c
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  * @title: rademux
23  *
24  * Demuxes/parses a RealAudio (.ra) file or stream into compressed audio.
25  *
26  * ## Example launch line
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  *
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 GST_ELEMENT_REGISTER_DEFINE (rademux, "rademux",
65     GST_RANK_SECONDARY, GST_TYPE_REAL_AUDIO_DEMUX);
66
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,
79     GstObject * parent);
80 static gboolean gst_real_audio_demux_sink_activate_mode (GstPad * sinkpad,
81     GstObject * parent, GstPadMode mode, gboolean active);
82
83 static void
84 gst_real_audio_demux_finalize (GObject * obj)
85 {
86   GstRealAudioDemux *demux = GST_REAL_AUDIO_DEMUX (obj);
87
88   g_object_unref (demux->adapter);
89
90   G_OBJECT_CLASS (parent_class)->finalize (obj);
91 }
92
93 static void
94 gst_real_audio_demux_class_init (GstRealAudioDemuxClass * klass)
95 {
96   GObjectClass *gobject_class = (GObjectClass *) klass;
97   GstElementClass *gstelement_class = (GstElementClass *) klass;
98
99   gobject_class->finalize = gst_real_audio_demux_finalize;
100
101   gst_element_class_add_static_pad_template (gstelement_class, &sink_template);
102   gst_element_class_add_static_pad_template (gstelement_class, &src_template);
103
104   gst_element_class_set_static_metadata (gstelement_class, "RealAudio Demuxer",
105       "Codec/Demuxer",
106       "Demultiplex a RealAudio file",
107       "Tim-Philipp Müller <tim centricular net>");
108
109   gstelement_class->change_state =
110       GST_DEBUG_FUNCPTR (gst_real_audio_demux_change_state);
111
112   GST_DEBUG_CATEGORY_INIT (real_audio_demux_debug, "rademux",
113       0, "Demuxer for RealAudio streams");
114 }
115
116 static void
117 gst_real_audio_demux_reset (GstRealAudioDemux * demux)
118 {
119   gst_adapter_clear (demux->adapter);
120
121   if (demux->srcpad) {
122     GST_DEBUG_OBJECT (demux, "Removing source pad");
123     gst_element_remove_pad (GST_ELEMENT (demux), demux->srcpad);
124     demux->srcpad = NULL;
125   }
126
127   if (demux->pending_tags) {
128     gst_tag_list_unref (demux->pending_tags);
129     demux->pending_tags = NULL;
130   }
131
132   demux->state = REAL_AUDIO_DEMUX_STATE_MARKER;
133   demux->ra_version = 0;
134   demux->data_offset = 0;
135   demux->packet_size = 0;
136
137   demux->sample_rate = 0;
138   demux->sample_width = 0;
139   demux->channels = 0;
140   demux->fourcc = 0;
141
142   demux->need_newsegment = TRUE;
143
144   demux->segment_running = FALSE;
145
146   demux->byterate_num = 0;
147   demux->byterate_denom = 0;
148
149   demux->duration = 0;
150   demux->upstream_size = 0;
151
152   demux->offset = 0;
153
154   demux->have_group_id = FALSE;
155   demux->group_id = G_MAXUINT;
156
157   gst_adapter_clear (demux->adapter);
158 }
159
160 static void
161 gst_real_audio_demux_init (GstRealAudioDemux * demux)
162 {
163   demux->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
164
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));
173
174   gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
175
176   demux->adapter = gst_adapter_new ();
177   gst_real_audio_demux_reset (demux);
178 }
179
180 static gboolean
181 gst_real_audio_demux_sink_activate (GstPad * sinkpad, GstObject * parent)
182 {
183   GstQuery *query;
184   gboolean pull_mode;
185
186   query = gst_query_new_scheduling ();
187
188   if (!gst_pad_peer_query (sinkpad, query)) {
189     gst_query_unref (query);
190     goto activate_push;
191   }
192
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);
196
197   if (!pull_mode)
198     goto activate_push;
199
200   GST_DEBUG_OBJECT (sinkpad, "activating pull");
201   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
202
203 activate_push:
204   {
205     GST_DEBUG_OBJECT (sinkpad, "activating push");
206     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
207   }
208 }
209
210 static gboolean
211 gst_real_audio_demux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
212     GstPadMode mode, gboolean active)
213 {
214   gboolean res;
215   GstRealAudioDemux *demux;
216
217   demux = GST_REAL_AUDIO_DEMUX (parent);
218
219   switch (mode) {
220     case GST_PAD_MODE_PUSH:
221       demux->seekable = FALSE;
222       res = TRUE;
223       break;
224     case GST_PAD_MODE_PULL:
225       if (active) {
226         demux->seekable = TRUE;
227
228         res = gst_pad_start_task (sinkpad,
229             (GstTaskFunction) gst_real_audio_demux_loop, demux, NULL);
230       } else {
231         demux->seekable = FALSE;
232         res = gst_pad_stop_task (sinkpad);
233       }
234       break;
235     default:
236       res = FALSE;
237       break;
238   }
239   return res;
240 }
241
242 static GstFlowReturn
243 gst_real_audio_demux_parse_marker (GstRealAudioDemux * demux)
244 {
245   guint8 data[6];
246
247   if (gst_adapter_available (demux->adapter) < 6) {
248     GST_LOG_OBJECT (demux, "need at least 6 bytes, waiting for more data");
249     return GST_FLOW_OK;
250   }
251
252   gst_adapter_copy (demux->adapter, data, 0, 6);
253   if (memcmp (data, ".ra\375", 4) != 0)
254     goto wrong_format;
255
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;
260
261   gst_adapter_flush (demux->adapter, 6);
262   demux->state = REAL_AUDIO_DEMUX_STATE_HEADER;
263   return GST_FLOW_OK;
264
265 /* ERRORS */
266 wrong_format:
267   {
268     GST_ELEMENT_ERROR (GST_ELEMENT (demux), STREAM, WRONG_TYPE, (NULL), (NULL));
269     return GST_FLOW_ERROR;
270   }
271
272 unsupported_ra_version:
273   {
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;
278   }
279 }
280
281 static GstClockTime
282 gst_real_demux_get_timestamp_from_offset (GstRealAudioDemux * demux,
283     guint64 offset)
284 {
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;
291   } else {
292     return GST_CLOCK_TIME_NONE;
293   }
294 }
295
296 static gboolean
297 gst_real_audio_demux_get_data_offset_from_header (GstRealAudioDemux * demux)
298 {
299   guint8 data[16];
300
301   gst_adapter_copy (demux->adapter, data, 0, 16);
302
303   switch (demux->ra_version) {
304     case 3:
305       demux->data_offset = GST_READ_UINT16_BE (data) + 8;
306       break;
307     case 4:
308       demux->data_offset = GST_READ_UINT32_BE (data + 12) + 16;
309       break;
310     default:
311       demux->data_offset = 0;
312       g_return_val_if_reached (FALSE);
313   }
314
315   return TRUE;
316 }
317
318 static GstFlowReturn
319 gst_real_audio_demux_parse_header (GstRealAudioDemux * demux)
320 {
321   const guint8 *data;
322   gchar *codec_name = NULL;
323   GstCaps *caps = NULL;
324   GstEvent *event;
325   gchar *stream_id;
326   guint avail;
327
328   g_assert (demux->ra_version == 4 || demux->ra_version == 3);
329
330   avail = gst_adapter_available (demux->adapter);
331   if (avail < 16)
332     return GST_FLOW_OK;
333
334   if (!gst_real_audio_demux_get_data_offset_from_header (demux))
335     return GST_FLOW_ERROR;      /* shouldn't happen */
336
337   GST_DEBUG_OBJECT (demux, "data_offset  = %u", demux->data_offset);
338
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);
342     return GST_FLOW_OK;
343   }
344
345   data = gst_adapter_map (demux->adapter, demux->data_offset - 6);
346   g_assert (data);
347
348   switch (demux->ra_version) {
349     case 3:
350       demux->fourcc = GST_RM_AUD_14_4;
351       demux->packet_size = 20;
352       demux->sample_rate = 8000;
353       demux->channels = 1;
354       demux->sample_width = 16;
355       demux->flavour = 1;
356       demux->leaf_size = 0;
357       demux->height = 0;
358       break;
359     case 4:
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);
373       break;
374     default:
375       g_assert_not_reached ();
376 #if 0
377     case 5:
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);
382
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);
387       break;
388 #endif
389   }
390
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);
397
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;
404       break;
405
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);
410       break;
411
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)
416         goto broken_file;
417       demux->byterate_num = demux->packet_size * demux->sample_rate;
418       demux->byterate_denom = 1536;
419       break;
420
421       /* Sipro/ACELP.NET Voice Codec (MIME unknown) */
422     case GST_RM_AUD_SIPR:
423       caps = gst_caps_new_empty_simple ("audio/x-sipro");
424       break;
425
426     default:
427       GST_WARNING_OBJECT (demux, "unknown fourcc %08X", demux->fourcc);
428       break;
429   }
430
431   if (caps == NULL)
432     goto unknown_fourcc;
433
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);
442
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);
451
452   stream_id =
453       gst_pad_create_stream_id (demux->srcpad, GST_ELEMENT_CAST (demux), NULL);
454
455   event = gst_pad_get_sticky_event (demux->sinkpad, GST_EVENT_STREAM_START, 0);
456   if (event) {
457     if (gst_event_parse_group_id (event, &demux->group_id))
458       demux->have_group_id = TRUE;
459     else
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 ();
465   }
466
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);
470
471   gst_pad_push_event (demux->srcpad, event);
472   g_free (stream_id);
473
474   gst_pad_set_caps (demux->srcpad, caps);
475   codec_name = gst_pb_utils_get_codec_description (caps);
476   gst_caps_unref (caps);
477
478   gst_element_add_pad (GST_ELEMENT (demux), demux->srcpad);
479
480   if (demux->byterate_num > 0 && demux->byterate_denom > 0) {
481     GstFormat bformat = GST_FORMAT_BYTES;
482     gint64 size_bytes = 0;
483
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);
487
488     if (gst_pad_peer_query_duration (demux->sinkpad, bformat, &size_bytes)) {
489       demux->duration =
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));
496     }
497   }
498
499   demux->need_newsegment = TRUE;
500
501   if (codec_name) {
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);
505     }
506
507     gst_tag_list_add (demux->pending_tags, GST_TAG_MERGE_REPLACE,
508         GST_TAG_AUDIO_CODEC, codec_name, NULL);
509     g_free (codec_name);
510   }
511
512   gst_adapter_unmap (demux->adapter);
513   gst_adapter_flush (demux->adapter, demux->data_offset - 6);
514
515   demux->state = REAL_AUDIO_DEMUX_STATE_DATA;
516   demux->need_newsegment = TRUE;
517
518   return GST_FLOW_OK;
519
520 /* ERRORS */
521 unknown_fourcc:
522   {
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;
526   }
527 broken_file:
528   {
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;
532   }
533
534 }
535
536 static GstFlowReturn
537 gst_real_audio_demux_parse_data (GstRealAudioDemux * demux)
538 {
539   GstFlowReturn ret = GST_FLOW_OK;
540   guint avail, unit_size;
541
542   avail = gst_adapter_available (demux->adapter);
543
544   if (demux->packet_size > 0)
545     unit_size = demux->packet_size;
546   else
547     unit_size = avail & 0xfffffff0;     /* round down to next multiple of 16 */
548
549   GST_LOG_OBJECT (demux, "available = %u, unit_size = %u", avail, unit_size);
550
551   while (ret == GST_FLOW_OK && unit_size > 0 && avail >= unit_size) {
552     GstClockTime ts;
553     GstBuffer *buf;
554
555     buf = gst_adapter_take_buffer (demux->adapter, unit_size);
556     avail -= unit_size;
557
558     if (demux->need_newsegment) {
559       gst_pad_push_event (demux->srcpad,
560           gst_event_new_segment (&demux->segment));
561       demux->need_newsegment = FALSE;
562     }
563
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;
568     }
569
570     if (demux->fourcc == GST_RM_AUD_DNET) {
571       buf = gst_rm_utils_descramble_dnet_buffer (buf);
572     }
573
574     ts = gst_real_demux_get_timestamp_from_offset (demux, demux->offset);
575     GST_BUFFER_TIMESTAMP (buf) = ts;
576
577     demux->segment.position = ts;
578
579     ret = gst_pad_push (demux->srcpad, buf);
580   }
581
582   return ret;
583 }
584
585 static GstFlowReturn
586 gst_real_audio_demux_handle_buffer (GstRealAudioDemux * demux, GstBuffer * buf)
587 {
588   GstFlowReturn ret;
589
590   gst_adapter_push (demux->adapter, buf);
591   buf = NULL;
592
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)
597         break;
598       /* otherwise fall through */
599     }
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)
603         break;
604       /* otherwise fall through */
605     }
606     case REAL_AUDIO_DEMUX_STATE_DATA:{
607       ret = gst_real_audio_demux_parse_data (demux);
608       break;
609     }
610     default:
611       g_return_val_if_reached (GST_FLOW_ERROR);
612   }
613
614   return ret;
615 }
616
617 static GstFlowReturn
618 gst_real_audio_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
619 {
620   GstRealAudioDemux *demux;
621
622   demux = GST_REAL_AUDIO_DEMUX (parent);
623
624   return gst_real_audio_demux_handle_buffer (demux, buf);
625 }
626
627 static void
628 gst_real_audio_demux_loop (GstRealAudioDemux * demux)
629 {
630   GstFlowReturn ret;
631   GstBuffer *buf;
632   guint bytes_needed;
633
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 */
638       break;
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);
643       break;
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;
648       } else {
649         bytes_needed = 1024;
650       }
651       break;
652     default:
653       g_return_if_reached ();
654   }
655
656   /* now get the data */
657   GST_LOG_OBJECT (demux, "getting data: %5u bytes @ %8" G_GINT64_MODIFIER "u",
658       bytes_needed, demux->offset);
659
660   if (demux->upstream_size > 0 && demux->offset >= demux->upstream_size)
661     goto eos;
662
663   buf = NULL;
664   ret = gst_pad_pull_range (demux->sinkpad, demux->offset, bytes_needed, &buf);
665
666   if (ret != GST_FLOW_OK)
667     goto pull_range_error;
668
669   if (gst_buffer_get_size (buf) != bytes_needed)
670     goto pull_range_short_read;
671
672   ret = gst_real_audio_demux_handle_buffer (demux, buf);
673   if (ret != GST_FLOW_OK)
674     goto handle_flow_error;
675
676   /* TODO: increase this in chain function too (for timestamps)? */
677   demux->offset += bytes_needed;
678
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");
683     goto eos;
684   }
685
686   return;
687
688 /* ERRORS */
689 parse_header_error:
690   {
691     GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL), (NULL));
692     goto pause_task;
693   }
694 handle_flow_error:
695   {
696     GST_WARNING_OBJECT (demux, "handle_buf flow: %s", gst_flow_get_name (ret));
697     goto pause_task;
698   }
699 pull_range_error:
700   {
701     GST_WARNING_OBJECT (demux, "pull range flow: %s", gst_flow_get_name (ret));
702     goto pause_task;
703   }
704 pull_range_short_read:
705   {
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);
710     goto eos;
711   }
712 eos:
713   {
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;
717     }
718     GST_INFO_OBJECT (demux, "EOS");
719     if ((demux->segment.flags & GST_SEEK_FLAG_SEGMENT) != 0) {
720       gint64 stop;
721
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;
726
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,
730               stop));
731       gst_pad_push_event (demux->srcpad,
732           gst_event_new_segment_done (GST_FORMAT_TIME, stop));
733     } else {
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 ());
737     }
738     goto pause_task;
739   }
740 pause_task:
741   {
742     demux->segment_running = FALSE;
743     gst_pad_pause_task (demux->sinkpad);
744     GST_DEBUG_OBJECT (demux, "pausing task");
745     return;
746   }
747 }
748
749 static gboolean
750 gst_real_audio_demux_sink_event (GstPad * pad, GstObject * parent,
751     GstEvent * event)
752 {
753   GstRealAudioDemux *demux;
754   gboolean ret;
755
756   demux = GST_REAL_AUDIO_DEMUX (parent);
757
758   switch (GST_EVENT_TYPE (event)) {
759     case GST_EVENT_SEGMENT:{
760       /* FIXME */
761       gst_event_unref (event);
762       demux->need_newsegment = TRUE;
763       ret = TRUE;
764       break;
765     }
766     default:
767       ret = gst_pad_event_default (pad, parent, event);
768       break;
769   }
770   return ret;
771 }
772
773 static gboolean
774 gst_real_audio_demux_handle_seek (GstRealAudioDemux * demux, GstEvent * event)
775 {
776   GstFormat format;
777   GstSeekFlags flags;
778   GstSeekType cur_type, stop_type;
779   gboolean flush, update;
780   gdouble rate;
781   guint64 seek_pos;
782   gint64 cur, stop;
783
784   if (!demux->seekable)
785     goto not_seekable;
786
787   if (demux->byterate_num == 0 || demux->byterate_denom == 0)
788     goto no_bitrate;
789
790   gst_event_parse_seek (event, &rate, &format, &flags,
791       &cur_type, &cur, &stop_type, &stop);
792
793   if (format != GST_FORMAT_TIME)
794     goto only_time_format_supported;
795
796   if (rate <= 0.0)
797     goto cannot_do_backwards_playback;
798
799   flush = ((flags & GST_SEEK_FLAG_FLUSH) != 0);
800
801   GST_DEBUG_OBJECT (demux, "flush=%d, rate=%g", flush, rate);
802
803   /* unlock streaming thread and make streaming stop */
804   if (flush) {
805     gst_pad_push_event (demux->sinkpad, gst_event_new_flush_start ());
806     gst_pad_push_event (demux->srcpad, gst_event_new_flush_start ());
807   } else {
808     gst_pad_pause_task (demux->sinkpad);
809   }
810
811   GST_PAD_STREAM_LOCK (demux->sinkpad);
812
813   gst_segment_do_seek (&demux->segment, rate, format, flags,
814       cur_type, cur, stop_type, stop, &update);
815
816   GST_DEBUG_OBJECT (demux, "segment: %" GST_SEGMENT_FORMAT, &demux->segment);
817
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;
822   }
823   seek_pos += demux->data_offset;
824
825   GST_DEBUG_OBJECT (demux, "seek_pos = %" G_GUINT64_FORMAT, seek_pos);
826
827   /* stop flushing */
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));
830
831   demux->offset = seek_pos;
832   demux->need_newsegment = TRUE;
833
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));
839   }
840
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);
845
846   /* streaming can continue now */
847   GST_PAD_STREAM_UNLOCK (demux->sinkpad);
848
849   return TRUE;
850
851 /* ERRORS */
852 not_seekable:
853   {
854     GST_DEBUG_OBJECT (demux, "seek failed: cannot seek in streaming mode");
855     return FALSE;
856   }
857 no_bitrate:
858   {
859     GST_DEBUG_OBJECT (demux, "seek failed: bitrate unknown");
860     return FALSE;
861   }
862 only_time_format_supported:
863   {
864     GST_DEBUG_OBJECT (demux, "can only seek in TIME format");
865     return FALSE;
866   }
867 cannot_do_backwards_playback:
868   {
869     GST_DEBUG_OBJECT (demux, "can only seek with positive rate, not %lf", rate);
870     return FALSE;
871   }
872 }
873
874 static gboolean
875 gst_real_audio_demux_src_event (GstPad * pad, GstObject * parent,
876     GstEvent * event)
877 {
878   GstRealAudioDemux *demux;
879   gboolean ret = FALSE;
880
881   demux = GST_REAL_AUDIO_DEMUX (parent);
882
883   switch (GST_EVENT_TYPE (event)) {
884     case GST_EVENT_QOS:
885       gst_event_unref (event);
886       break;
887     case GST_EVENT_SEEK:
888       ret = gst_real_audio_demux_handle_seek (demux, event);
889       gst_event_unref (event);
890       break;
891     default:
892       ret = gst_pad_event_default (pad, parent, event);
893       break;
894   }
895
896   return ret;
897 }
898
899 static gboolean
900 gst_real_audio_demux_src_query (GstPad * pad, GstObject * parent,
901     GstQuery * query)
902 {
903   GstRealAudioDemux *demux;
904   gboolean ret = FALSE;
905
906   demux = GST_REAL_AUDIO_DEMUX (parent);
907
908   switch (GST_QUERY_TYPE (query)) {
909     case GST_QUERY_DURATION:{
910       GstFormat format;
911
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);
915         ret = TRUE;
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);
919         ret = TRUE;
920       }
921       break;
922     }
923     case GST_QUERY_SEEKING:{
924       GstFormat format;
925       gboolean seekable;
926
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);
931       ret = TRUE;
932       break;
933     }
934     case GST_QUERY_SEGMENT:
935     {
936       GstFormat format;
937       gint64 start, stop;
938
939       format = demux->segment.format;
940
941       start =
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;
946       else
947         stop = gst_segment_to_stream_time (&demux->segment, format, stop);
948
949       gst_query_set_segment (query, demux->segment.rate, format, start, stop);
950       ret = TRUE;
951       break;
952     }
953     default:
954       ret = gst_pad_query_default (pad, parent, query);
955       break;
956   }
957
958   return ret;
959 }
960
961 static GstStateChangeReturn
962 gst_real_audio_demux_change_state (GstElement * element,
963     GstStateChange transition)
964 {
965   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
966   GstRealAudioDemux *demux = GST_REAL_AUDIO_DEMUX (element);
967
968   switch (transition) {
969     case GST_STATE_CHANGE_NULL_TO_READY:
970       break;
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);
976       break;
977     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
978       break;
979     default:
980       break;
981   }
982
983   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
984
985   switch (transition) {
986     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
987       break;
988     case GST_STATE_CHANGE_PAUSED_TO_READY:{
989       gst_real_audio_demux_reset (demux);
990       gst_segment_init (&demux->segment, GST_FORMAT_UNDEFINED);
991       break;
992     }
993     case GST_STATE_CHANGE_READY_TO_NULL:
994       break;
995     default:
996       break;
997   }
998
999   return ret;
1000 }