1 /* GStreamer Musepack decoder plugin
2 * Copyright (C) 2004 Ronald Bultje <rbultje@ronald.bitfreak.net>
3 * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
4 * Copyright (C) 2008 Sebastian Dröge <slomo@circular-chaos.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "gstmusepackdec.h"
27 #include "gstmusepackreader.h"
28
29 GST_DEBUG_CATEGORY (musepackdec_debug);
30 #define GST_CAT_DEFAULT musepackdec_debug
31
32 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
33 GST_PAD_SINK,
34 GST_PAD_ALWAYS,
35 GST_STATIC_CAPS ("audio/x-musepack, streamversion = (int) { 7, 8 }")
36 );
37
38 #ifdef MPC_FIXED_POINT
39 # if G_BYTE_ORDER == G_LITTLE_ENDIAN
40 # define GST_MPC_FORMAT "S32LE"
41 # else
42 # define GST_MPC_FORMAT "S32BE"
43 # endif
44 #else
45 # if G_BYTE_ORDER == G_LITTLE_ENDIAN
46 # define GST_MPC_FORMAT "F32LE"
47 # else
48 # define GST_MPC_FORMAT "F32BE"
49 # endif
50 #endif
51
52 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
53 GST_PAD_SRC,
54 GST_PAD_ALWAYS,
55 GST_STATIC_CAPS ("audio/x-raw, "
56 "format = (string) " GST_MPC_FORMAT ", "
57 "layout = (string) interleaved, "
58 "rate = (int) [ 8000, 96000 ], " "channels = (int) [ 1, 2 ]")
59 );
60
61 static void gst_musepackdec_dispose (GObject * obj);
62
63 static gboolean gst_musepackdec_src_event (GstPad * pad, GstObject * parent,
64 GstEvent * event);
65 static gboolean gst_musepackdec_src_query (GstPad * pad, GstObject * parent,
66 GstQuery * query);
67 static gboolean gst_musepackdec_sink_activate (GstPad * sinkpad,
68 GstObject * parent);
69 static gboolean gst_musepackdec_sink_activate_mode (GstPad * sinkpad,
70 GstObject * parent, GstPadMode mode, gboolean active);
71
72 static void gst_musepackdec_loop (GstPad * sinkpad);
73 static GstStateChangeReturn
74 gst_musepackdec_change_state (GstElement * element, GstStateChange transition);
75
76 #define parent_class gst_musepackdec_parent_class
77 G_DEFINE_TYPE_WITH_CODE (GstMusepackDec, gst_musepackdec, GST_TYPE_ELEMENT,
78 GST_DEBUG_CATEGORY_INIT (musepackdec_debug, "musepackdec", 0,
79 "mpc decoder");
80 );
81 GST_ELEMENT_REGISTER_DEFINE (musepackdec, "musepackdec",
82 GST_RANK_PRIMARY, GST_TYPE_MUSEPACK_DEC);
83 static void
gst_musepackdec_class_init(GstMusepackDecClass * klass)84 gst_musepackdec_class_init (GstMusepackDecClass * klass)
85 {
86 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
87 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
88
89 gst_element_class_add_static_pad_template (element_class, &src_template);
90 gst_element_class_add_static_pad_template (element_class, &sink_template);
91
92 gst_element_class_set_static_metadata (element_class, "Musepack decoder",
93 "Codec/Decoder/Audio",
94 "Musepack decoder", "Ronald Bultje <rbultje@ronald.bitfreak.net>");
95
96 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_musepackdec_dispose);
97
98 element_class->change_state =
99 GST_DEBUG_FUNCPTR (gst_musepackdec_change_state);
100 }
101
102 static void
gst_musepackdec_init(GstMusepackDec * musepackdec)103 gst_musepackdec_init (GstMusepackDec * musepackdec)
104 {
105 musepackdec->offset = 0;
106 musepackdec->rate = 0;
107 musepackdec->bps = 0;
108
109 musepackdec->r = g_new (mpc_reader, 1);
110
111 musepackdec->sinkpad =
112 gst_pad_new_from_static_template (&sink_template, "sink");
113 gst_pad_set_activate_function (musepackdec->sinkpad,
114 GST_DEBUG_FUNCPTR (gst_musepackdec_sink_activate));
115 gst_pad_set_activatemode_function (musepackdec->sinkpad,
116 GST_DEBUG_FUNCPTR (gst_musepackdec_sink_activate_mode));
117 gst_element_add_pad (GST_ELEMENT (musepackdec), musepackdec->sinkpad);
118
119 musepackdec->srcpad = gst_pad_new_from_static_template (&src_template, "src");
120 gst_pad_set_event_function (musepackdec->srcpad,
121 GST_DEBUG_FUNCPTR (gst_musepackdec_src_event));
122 gst_pad_set_query_function (musepackdec->srcpad,
123 GST_DEBUG_FUNCPTR (gst_musepackdec_src_query));
124 gst_pad_use_fixed_caps (musepackdec->srcpad);
125 gst_element_add_pad (GST_ELEMENT (musepackdec), musepackdec->srcpad);
126 }
127
128 static void
gst_musepackdec_dispose(GObject * obj)129 gst_musepackdec_dispose (GObject * obj)
130 {
131 GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (obj);
132
133 g_free (musepackdec->r);
134 musepackdec->r = NULL;
135
136 if (musepackdec->d) {
137 mpc_demux_exit (musepackdec->d);
138 musepackdec->d = NULL;
139 }
140
141 G_OBJECT_CLASS (parent_class)->dispose (obj);
142 }
143
144 static void
gst_musepackdec_send_newsegment(GstMusepackDec * dec)145 gst_musepackdec_send_newsegment (GstMusepackDec * dec)
146 {
147 GstSegment os = dec->segment;
148
149 os.format = GST_FORMAT_TIME;
150 os.start = gst_util_uint64_scale_int (os.start, GST_SECOND, dec->rate);
151 if (os.stop)
152 os.stop = gst_util_uint64_scale_int (os.stop, GST_SECOND, dec->rate);
153 os.time = gst_util_uint64_scale_int (os.time, GST_SECOND, dec->rate);
154
155 GST_DEBUG_OBJECT (dec, "sending newsegment from %" GST_TIME_FORMAT
156 " to %" GST_TIME_FORMAT ", rate = %.1f", GST_TIME_ARGS (os.start),
157 GST_TIME_ARGS (os.stop), os.rate);
158
159 gst_pad_push_event (dec->srcpad, gst_event_new_segment (&os));
160 }
161
162 static gboolean
gst_musepackdec_handle_seek_event(GstMusepackDec * dec,GstEvent * event)163 gst_musepackdec_handle_seek_event (GstMusepackDec * dec, GstEvent * event)
164 {
165 GstSeekType start_type, stop_type;
166 GstSeekFlags flags;
167 GstSegment segment;
168 GstFormat format;
169 gboolean flush;
170 gdouble rate;
171 gint64 start, stop;
172 gint samplerate;
173
174 gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
175 &stop_type, &stop);
176
177 if (format != GST_FORMAT_TIME && format != GST_FORMAT_DEFAULT) {
178 GST_DEBUG_OBJECT (dec, "seek failed: only TIME or DEFAULT format allowed");
179 return FALSE;
180 }
181
182 samplerate = g_atomic_int_get (&dec->rate);
183
184 if (format == GST_FORMAT_TIME) {
185 if (start_type != GST_SEEK_TYPE_NONE)
186 start = gst_util_uint64_scale_int (start, samplerate, GST_SECOND);
187 if (stop_type != GST_SEEK_TYPE_NONE)
188 stop = gst_util_uint64_scale_int (stop, samplerate, GST_SECOND);
189 }
190
191 flush = ((flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH);
192
193 if (flush)
194 gst_pad_push_event (dec->srcpad, gst_event_new_flush_start ());
195 else
196 gst_pad_pause_task (dec->sinkpad); /* not _stop_task()? */
197
198 GST_PAD_STREAM_LOCK (dec->sinkpad);
199
200 /* operate on segment copy until we know the seek worked */
201 segment = dec->segment;
202
203 gst_segment_do_seek (&segment, rate, GST_FORMAT_DEFAULT,
204 flags, start_type, start, stop_type, stop, NULL);
205
206 gst_pad_push_event (dec->sinkpad, gst_event_new_flush_stop (TRUE));
207
208 GST_DEBUG_OBJECT (dec, "segment: [%" G_GINT64_FORMAT "-%" G_GINT64_FORMAT
209 "] = [%" GST_TIME_FORMAT "-%" GST_TIME_FORMAT "]",
210 segment.start, segment.stop,
211 GST_TIME_ARGS (segment.start * GST_SECOND / dec->rate),
212 GST_TIME_ARGS (segment.stop * GST_SECOND / dec->rate));
213
214 GST_DEBUG_OBJECT (dec, "performing seek to sample %" G_GINT64_FORMAT,
215 segment.start);
216
217 if (segment.start >= segment.duration) {
218 GST_WARNING_OBJECT (dec, "seek out of bounds");
219 goto failed;
220 }
221 if (mpc_demux_seek_sample (dec->d, segment.start) != MPC_STATUS_OK)
222 goto failed;
223
224 if ((flags & GST_SEEK_FLAG_SEGMENT) == GST_SEEK_FLAG_SEGMENT) {
225 GST_DEBUG_OBJECT (dec, "posting SEGMENT_START message");
226
227 gst_element_post_message (GST_ELEMENT (dec),
228 gst_message_new_segment_start (GST_OBJECT (dec), GST_FORMAT_TIME,
229 gst_util_uint64_scale_int (segment.start, GST_SECOND, dec->rate)));
230 }
231
232 if (flush) {
233 gst_pad_push_event (dec->srcpad, gst_event_new_flush_stop (TRUE));
234 }
235
236 segment.position = segment.start;
237 dec->segment = segment;
238 gst_musepackdec_send_newsegment (dec);
239
240 GST_DEBUG_OBJECT (dec, "seek successful");
241
242 gst_pad_start_task (dec->sinkpad,
243 (GstTaskFunction) gst_musepackdec_loop, dec->sinkpad, NULL);
244
245 GST_PAD_STREAM_UNLOCK (dec->sinkpad);
246
247 return TRUE;
248
249 failed:
250 {
251 GST_WARNING_OBJECT (dec, "seek failed");
252 GST_PAD_STREAM_UNLOCK (dec->sinkpad);
253 return FALSE;
254 }
255 }
256
257 static gboolean
gst_musepackdec_src_event(GstPad * pad,GstObject * parent,GstEvent * event)258 gst_musepackdec_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
259 {
260 GstMusepackDec *dec;
261 gboolean res;
262
263 dec = GST_MUSEPACK_DEC (parent);
264
265 GST_DEBUG_OBJECT (dec, "handling %s event", GST_EVENT_TYPE_NAME (event));
266
267 switch (GST_EVENT_TYPE (event)) {
268 case GST_EVENT_SEEK:
269 res = gst_musepackdec_handle_seek_event (dec, event);
270 break;
271 default:
272 res = gst_pad_event_default (pad, parent, event);
273 break;
274 }
275
276 return res;
277 }
278
279 static gboolean
gst_musepackdec_src_query(GstPad * pad,GstObject * parent,GstQuery * query)280 gst_musepackdec_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
281 {
282 GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (parent);
283 GstFormat format;
284 gboolean res = FALSE;
285 gint samplerate;
286
287 samplerate = g_atomic_int_get (&musepackdec->rate);
288
289 switch (GST_QUERY_TYPE (query)) {
290 case GST_QUERY_POSITION:{
291 gint64 cur, cur_off;
292
293 if (samplerate == 0)
294 goto done;
295
296 gst_query_parse_position (query, &format, NULL);
297
298 GST_OBJECT_LOCK (musepackdec);
299 cur_off = musepackdec->segment.position;
300 GST_OBJECT_UNLOCK (musepackdec);
301
302 if (format == GST_FORMAT_TIME) {
303 cur = gst_util_uint64_scale_int (cur_off, GST_SECOND, samplerate);
304 gst_query_set_position (query, GST_FORMAT_TIME, cur);
305 res = TRUE;
306 } else if (format == GST_FORMAT_DEFAULT) {
307 gst_query_set_position (query, GST_FORMAT_DEFAULT, cur_off);
308 res = TRUE;
309 }
310 break;
311 }
312 case GST_QUERY_DURATION:{
313 gint64 len, len_off;
314
315 if (samplerate == 0)
316 goto done;
317
318 gst_query_parse_duration (query, &format, NULL);
319
320 GST_OBJECT_LOCK (musepackdec);
321 len_off = musepackdec->segment.duration;
322 GST_OBJECT_UNLOCK (musepackdec);
323
324 if (format == GST_FORMAT_TIME) {
325 len = gst_util_uint64_scale_int (len_off, GST_SECOND, samplerate);
326 gst_query_set_duration (query, GST_FORMAT_TIME, len);
327 res = TRUE;
328 } else if (format == GST_FORMAT_DEFAULT) {
329 gst_query_set_duration (query, GST_FORMAT_DEFAULT, len_off);
330 res = TRUE;
331 }
332 break;
333 }
334 case GST_QUERY_SEEKING:{
335 GstFormat fmt;
336 gint64 len, len_off;
337
338 res = TRUE;
339 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
340
341 GST_OBJECT_LOCK (musepackdec);
342 len_off = musepackdec->segment.duration;
343 GST_OBJECT_UNLOCK (musepackdec);
344
345 if (fmt == GST_FORMAT_TIME) {
346 len = gst_util_uint64_scale_int (len_off, GST_SECOND, samplerate);
347 gst_query_set_seeking (query, fmt, TRUE, 0, len);
348 } else if (fmt == GST_FORMAT_DEFAULT) {
349 gst_query_set_seeking (query, fmt, TRUE, 0, len_off);
350 } else {
351 gst_query_set_seeking (query, fmt, FALSE, -1, -1);
352 }
353 break;
354 }
355 default:
356 res = gst_pad_query_default (pad, parent, query);
357 break;
358 }
359
360 done:
361 return res;
362 }
363
364 static gboolean
gst_musepack_stream_init(GstMusepackDec * musepackdec)365 gst_musepack_stream_init (GstMusepackDec * musepackdec)
366 {
367 mpc_streaminfo i;
368 GstTagList *tags;
369 GstCaps *caps;
370 gchar *stream_id;
371
372 /* set up reading */
373 gst_musepack_init_reader (musepackdec->r, musepackdec);
374
375 musepackdec->d = mpc_demux_init (musepackdec->r);
376 if (!musepackdec->d) {
377 GST_ELEMENT_ERROR (musepackdec, STREAM, WRONG_TYPE, (NULL), (NULL));
378 return FALSE;
379 }
380
381 mpc_demux_get_info (musepackdec->d, &i);
382
383 stream_id = gst_pad_create_stream_id (musepackdec->srcpad,
384 GST_ELEMENT_CAST (musepackdec), NULL);
385 gst_pad_push_event (musepackdec->srcpad,
386 gst_event_new_stream_start (stream_id));
387 g_free (stream_id);
388
389 /* capsnego */
390 caps = gst_caps_new_simple ("audio/x-raw",
391 "format", G_TYPE_STRING, GST_MPC_FORMAT,
392 "layout", G_TYPE_STRING, "interleaved",
393 "channels", G_TYPE_INT, i.channels,
394 "rate", G_TYPE_INT, i.sample_freq, NULL);
395 gst_pad_use_fixed_caps (musepackdec->srcpad);
396 if (!gst_pad_set_caps (musepackdec->srcpad, caps)) {
397 GST_ELEMENT_ERROR (musepackdec, CORE, NEGOTIATION, (NULL), (NULL));
398 return FALSE;
399 }
400
401 g_atomic_int_set (&musepackdec->bps, 4 * i.channels);
402 g_atomic_int_set (&musepackdec->rate, i.sample_freq);
403
404 musepackdec->segment.position = 0;
405 musepackdec->segment.duration = mpc_streaminfo_get_length_samples (&i);
406
407 /* send basic tags */
408 tags = gst_tag_list_new_empty ();
409 gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
410 GST_TAG_AUDIO_CODEC, "Musepack", NULL);
411
412 if (i.encoder[0] != '\0' && i.encoder_version > 0) {
413 gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
414 GST_TAG_ENCODER, i.encoder,
415 GST_TAG_ENCODER_VERSION, i.encoder_version, NULL);
416 }
417
418 if (i.bitrate > 0) {
419 gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
420 GST_TAG_BITRATE, i.bitrate, NULL);
421 } else if (i.average_bitrate > 0.0) {
422 gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
423 GST_TAG_BITRATE, (guint) i.average_bitrate, NULL);
424 }
425
426 if (i.gain_title != 0 || i.gain_album != 0) {
427 gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
428 GST_TAG_TRACK_GAIN, (gdouble) i.gain_title / 100.0,
429 GST_TAG_ALBUM_GAIN, (gdouble) i.gain_album / 100.0, NULL);
430 }
431
432 if (i.peak_title != 0 && i.peak_title != 32767 &&
433 i.peak_album != 0 && i.peak_album != 32767) {
434 gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
435 GST_TAG_TRACK_PEAK, (gdouble) i.peak_title / 32767.0,
436 GST_TAG_ALBUM_PEAK, (gdouble) i.peak_album / 32767.0, NULL);
437 }
438
439 GST_LOG_OBJECT (musepackdec, "Posting tags: %" GST_PTR_FORMAT, tags);
440 gst_pad_push_event (musepackdec->srcpad, gst_event_new_tag (tags));
441
442
443 return TRUE;
444 }
445
446 static gboolean
gst_musepackdec_sink_activate(GstPad * sinkpad,GstObject * parent)447 gst_musepackdec_sink_activate (GstPad * sinkpad, GstObject * parent)
448 {
449 GstQuery *query;
450 gboolean pull_mode;
451
452 query = gst_query_new_scheduling ();
453
454 if (!gst_pad_peer_query (sinkpad, query)) {
455 gst_query_unref (query);
456 return FALSE;
457 }
458
459 pull_mode = gst_query_has_scheduling_mode_with_flags (query,
460 GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
461 gst_query_unref (query);
462
463 if (!pull_mode)
464 return FALSE;
465
466 GST_DEBUG_OBJECT (sinkpad, "activating pull");
467 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
468 }
469
470 static gboolean
gst_musepackdec_sink_activate_mode(GstPad * sinkpad,GstObject * parent,GstPadMode mode,gboolean active)471 gst_musepackdec_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
472 GstPadMode mode, gboolean active)
473 {
474 gboolean result;
475
476 switch (mode) {
477 case GST_PAD_MODE_PUSH:
478 result = FALSE;
479 break;
480 case GST_PAD_MODE_PULL:
481 if (active) {
482 result = gst_pad_start_task (sinkpad,
483 (GstTaskFunction) gst_musepackdec_loop, sinkpad, NULL);
484 } else {
485 result = gst_pad_stop_task (sinkpad);
486 }
487 break;
488 default:
489 result = FALSE;
490 break;
491 }
492
493 return result;
494 }
495
496 static void
gst_musepackdec_loop(GstPad * sinkpad)497 gst_musepackdec_loop (GstPad * sinkpad)
498 {
499 GstMusepackDec *musepackdec;
500 GstFlowReturn flow;
501 GstBuffer *out;
502 GstMapInfo info;
503 mpc_frame_info frame;
504 mpc_status err;
505 gint num_samples, samplerate, bitspersample;
506
507 musepackdec = GST_MUSEPACK_DEC (GST_PAD_PARENT (sinkpad));
508
509 samplerate = g_atomic_int_get (&musepackdec->rate);
510
511 if (samplerate == 0) {
512 if (!gst_musepack_stream_init (musepackdec))
513 goto pause_task;
514
515 gst_musepackdec_send_newsegment (musepackdec);
516 samplerate = g_atomic_int_get (&musepackdec->rate);
517 }
518
519 bitspersample = g_atomic_int_get (&musepackdec->bps);
520
521 out = gst_buffer_new_allocate (NULL, MPC_DECODER_BUFFER_LENGTH * 4, NULL);
522
523 gst_buffer_map (out, &info, GST_MAP_READWRITE);
524 frame.buffer = (MPC_SAMPLE_FORMAT *) info.data;
525 err = mpc_demux_decode (musepackdec->d, &frame);
526 gst_buffer_unmap (out, &info);
527
528 if (err != MPC_STATUS_OK) {
529 GST_ERROR_OBJECT (musepackdec, "Failed to decode sample");
530 GST_ELEMENT_ERROR (musepackdec, STREAM, DECODE, (NULL), (NULL));
531 goto pause_task;
532 } else if (frame.bits == -1) {
533 goto eos_and_pause;
534 }
535
536 num_samples = frame.samples;
537
538 gst_buffer_set_size (out, num_samples * bitspersample);
539
540 GST_BUFFER_OFFSET (out) = musepackdec->segment.position;
541 GST_BUFFER_PTS (out) =
542 gst_util_uint64_scale_int (musepackdec->segment.position,
543 GST_SECOND, samplerate);
544 GST_BUFFER_DURATION (out) =
545 gst_util_uint64_scale_int (num_samples, GST_SECOND, samplerate);
546
547 musepackdec->segment.position += num_samples;
548
549 GST_LOG_OBJECT (musepackdec, "Pushing buffer, timestamp %" GST_TIME_FORMAT,
550 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (out)));
551
552 flow = gst_pad_push (musepackdec->srcpad, out);
553 if (flow != GST_FLOW_OK) {
554 GST_DEBUG_OBJECT (musepackdec, "Flow: %s", gst_flow_get_name (flow));
555 goto pause_task;
556 }
557
558 /* check if we're at the end of a configured segment */
559 if (musepackdec->segment.stop != -1 &&
560 musepackdec->segment.position >= musepackdec->segment.stop) {
561 gint64 stop_time;
562
563 GST_DEBUG_OBJECT (musepackdec, "Reached end of configured segment");
564
565 if ((musepackdec->segment.flags & GST_SEEK_FLAG_SEGMENT) == 0)
566 goto eos_and_pause;
567
568 GST_DEBUG_OBJECT (musepackdec, "Posting SEGMENT_DONE message");
569
570 stop_time = gst_util_uint64_scale_int (musepackdec->segment.stop,
571 GST_SECOND, samplerate);
572
573 gst_element_post_message (GST_ELEMENT (musepackdec),
574 gst_message_new_segment_done (GST_OBJECT (musepackdec),
575 GST_FORMAT_TIME, stop_time));
576 gst_pad_push_event (musepackdec->srcpad,
577 gst_event_new_segment_done (GST_FORMAT_TIME, stop_time));
578
579 goto pause_task;
580 }
581
582 return;
583
584 eos_and_pause:
585 {
586 GST_DEBUG_OBJECT (musepackdec, "sending EOS event");
587 gst_pad_push_event (musepackdec->srcpad, gst_event_new_eos ());
588 /* fall through to pause */
589 }
590
591 pause_task:
592 {
593 GST_DEBUG_OBJECT (musepackdec, "Pausing task");
594 gst_pad_pause_task (sinkpad);
595 return;
596 }
597 }
598
599 static GstStateChangeReturn
gst_musepackdec_change_state(GstElement * element,GstStateChange transition)600 gst_musepackdec_change_state (GstElement * element, GstStateChange transition)
601 {
602 GstMusepackDec *musepackdec = GST_MUSEPACK_DEC (element);
603 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
604
605 switch (transition) {
606 case GST_STATE_CHANGE_READY_TO_PAUSED:
607 gst_segment_init (&musepackdec->segment, GST_FORMAT_DEFAULT);
608 musepackdec->segment.position = 0;
609 break;
610 default:
611 break;
612 }
613
614 if (GST_ELEMENT_CLASS (parent_class)->change_state)
615 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
616
617 switch (transition) {
618 case GST_STATE_CHANGE_PAUSED_TO_READY:
619 gst_segment_init (&musepackdec->segment, GST_FORMAT_UNDEFINED);
620 musepackdec->offset = 0;
621 musepackdec->rate = 0;
622 musepackdec->bps = 0;
623 break;
624 default:
625 break;
626 }
627
628 return ret;
629
630 }
631
632 static gboolean
plugin_init(GstPlugin * plugin)633 plugin_init (GstPlugin * plugin)
634 {
635 return GST_ELEMENT_REGISTER (musepackdec, plugin);
636 }
637
638 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
639 GST_VERSION_MINOR,
640 musepack,
641 "Musepack decoder", plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME,
642 GST_PACKAGE_ORIGIN)
643