Gentoo Archives: gentoo-commits

From: "Samuli Suominen (drac)" <drac@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] gentoo-x86 commit in media-libs/gst-plugins-ugly/files: gst-plugins-ugly-0.10.6-mpegaudioparse-cvs20071117.patch digest-gst-plugins-ugly-0.10.6-r1
Date: Sun, 18 Nov 2007 20:19:34
Message-Id: E1Itqc2-0004fr-SA@stork.gentoo.org
1 drac 07/11/18 20:19:26
2
3 Added:
4 gst-plugins-ugly-0.10.6-mpegaudioparse-cvs20071117.patch
5 digest-gst-plugins-ugly-0.10.6-r1
6 Log:
7 Update mpegaudioparse to CVS 20071117 to work with current core.
8 (Portage version: 2.1.3.19)
9
10 Revision Changes Path
11 1.1 media-libs/gst-plugins-ugly/files/gst-plugins-ugly-0.10.6-mpegaudioparse-cvs20071117.patch
12
13 file : http://sources.gentoo.org/viewcvs.py/gentoo-x86/media-libs/gst-plugins-ugly/files/gst-plugins-ugly-0.10.6-mpegaudioparse-cvs20071117.patch?rev=1.1&view=markup
14 plain: http://sources.gentoo.org/viewcvs.py/gentoo-x86/media-libs/gst-plugins-ugly/files/gst-plugins-ugly-0.10.6-mpegaudioparse-cvs20071117.patch?rev=1.1&content-type=text/plain
15
16 Index: gst-plugins-ugly-0.10.6-mpegaudioparse-cvs20071117.patch
17 ===================================================================
18 Index: gst/mpegaudioparse/gstmpegaudioparse.c
19 ===================================================================
20 RCS file: /cvs/gstreamer/gst-plugins-ugly/gst/mpegaudioparse/gstmpegaudioparse.c,v
21 retrieving revision 1.62
22 retrieving revision 1.74
23 diff -u -r1.62 -r1.74
24 --- gst/mpegaudioparse/gstmpegaudioparse.c 8 Jun 2007 08:39:43 -0000 1.62
25 +++ gst/mpegaudioparse/gstmpegaudioparse.c 30 Oct 2007 12:27:32 -0000 1.74
26 @@ -29,6 +29,7 @@
27 GST_DEBUG_CATEGORY_STATIC (mp3parse_debug);
28 #define GST_CAT_DEFAULT mp3parse_debug
29
30 +
31 /* elementfactory information */
32 static GstElementDetails mp3parse_details = {
33 "MPEG1 Audio Parser",
34 @@ -71,8 +72,9 @@
35
36
37 static void gst_mp3parse_class_init (GstMPEGAudioParseClass * klass);
38 -static void gst_mp3parse_base_init (GstMPEGAudioParseClass * klass);
39 -static void gst_mp3parse_init (GstMPEGAudioParse * mp3parse);
40 +static void gst_mp3parse_base_init (gpointer klass);
41 +static void gst_mp3parse_init (GstMPEGAudioParse * mp3parse,
42 + GstMPEGAudioParseClass * klass);
43
44 static gboolean gst_mp3parse_sink_event (GstPad * pad, GstEvent * event);
45 static GstFlowReturn gst_mp3parse_chain (GstPad * pad, GstBuffer * buffer);
46 @@ -95,33 +97,9 @@
47 static gboolean
48 mp3parse_total_bytes (GstMPEGAudioParse * mp3parse, gint64 * total);
49
50 -static GstElementClass *parent_class = NULL;
51 -
52 /*static guint gst_mp3parse_signals[LAST_SIGNAL] = { 0 }; */
53
54 -GType
55 -gst_mp3parse_get_type (void)
56 -{
57 - static GType mp3parse_type = 0;
58 -
59 - if (!mp3parse_type) {
60 - static const GTypeInfo mp3parse_info = {
61 - sizeof (GstMPEGAudioParseClass),
62 - (GBaseInitFunc) gst_mp3parse_base_init,
63 - NULL,
64 - (GClassInitFunc) gst_mp3parse_class_init,
65 - NULL,
66 - NULL,
67 - sizeof (GstMPEGAudioParse),
68 - 0,
69 - (GInstanceInitFunc) gst_mp3parse_init,
70 - };
71 -
72 - mp3parse_type = g_type_register_static (GST_TYPE_ELEMENT,
73 - "GstMPEGAudioParse", &mp3parse_info, 0);
74 - }
75 - return mp3parse_type;
76 -}
77 +GST_BOILERPLATE (GstMPEGAudioParse, gst_mp3parse, GstElement, GST_TYPE_ELEMENT);
78
79 static guint mp3types_bitrates[2][3][16] = {
80 {
81 @@ -218,13 +196,14 @@
82 new = gst_caps_new_simple ("audio/mpeg",
83 "mpegversion", G_TYPE_INT, 1,
84 "layer", G_TYPE_INT, layer,
85 - "rate", G_TYPE_INT, samplerate, "channels", G_TYPE_INT, channels, NULL);
86 + "rate", G_TYPE_INT, samplerate,
87 + "channels", G_TYPE_INT, channels, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
88
89 return new;
90 }
91
92 static void
93 -gst_mp3parse_base_init (GstMPEGAudioParseClass * klass)
94 +gst_mp3parse_base_init (gpointer klass)
95 {
96 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
97
98 @@ -265,8 +244,8 @@
99 {
100 mp3parse->skip = 0;
101 mp3parse->resyncing = TRUE;
102 - mp3parse->cur_offset = -1;
103 mp3parse->next_ts = GST_CLOCK_TIME_NONE;
104 + mp3parse->cur_offset = -1;
105
106 mp3parse->tracked_offset = 0;
107 mp3parse->pending_ts = GST_CLOCK_TIME_NONE;
108 @@ -276,6 +255,7 @@
109
110 mp3parse->rate = mp3parse->channels = mp3parse->layer = -1;
111 mp3parse->version = 1;
112 + mp3parse->max_bitreservoir = GST_CLOCK_TIME_NONE;
113
114 mp3parse->avg_bitrate = 0;
115 mp3parse->bitrate_sum = 0;
116 @@ -285,21 +265,34 @@
117
118 mp3parse->xing_flags = 0;
119 mp3parse->xing_bitrate = 0;
120 +
121 + if (mp3parse->seek_table) {
122 + g_list_foreach (mp3parse->seek_table, (GFunc) g_free, NULL);
123 + mp3parse->seek_table = NULL;
124 + }
125 +
126 + g_mutex_lock (mp3parse->pending_accurate_seeks_lock);
127 + if (mp3parse->pending_accurate_seeks) {
128 + g_slist_foreach (mp3parse->pending_accurate_seeks, (GFunc) g_free, NULL);
129 + mp3parse->pending_accurate_seeks = NULL;
130 + }
131 + g_mutex_unlock (mp3parse->pending_accurate_seeks_lock);
132 +
133 + mp3parse->exact_position = FALSE;
134 + gst_segment_init (&mp3parse->segment, GST_FORMAT_TIME);
135 }
136
137 static void
138 -gst_mp3parse_init (GstMPEGAudioParse * mp3parse)
139 +gst_mp3parse_init (GstMPEGAudioParse * mp3parse, GstMPEGAudioParseClass * klass)
140 {
141 mp3parse->sinkpad =
142 - gst_pad_new_from_template (gst_static_pad_template_get
143 - (&mp3_sink_template), "sink");
144 + gst_pad_new_from_static_template (&mp3_sink_template, "sink");
145 gst_pad_set_event_function (mp3parse->sinkpad, gst_mp3parse_sink_event);
146 gst_pad_set_chain_function (mp3parse->sinkpad, gst_mp3parse_chain);
147 gst_element_add_pad (GST_ELEMENT (mp3parse), mp3parse->sinkpad);
148
149 mp3parse->srcpad =
150 - gst_pad_new_from_template (gst_static_pad_template_get
151 - (&mp3_src_template), "src");
152 + gst_pad_new_from_static_template (&mp3_src_template, "src");
153 gst_pad_use_fixed_caps (mp3parse->srcpad);
154 gst_pad_set_event_function (mp3parse->srcpad, mp3parse_src_event);
155 gst_pad_set_query_function (mp3parse->srcpad, mp3parse_src_query);
156 @@ -307,6 +300,7 @@
157 gst_element_add_pad (GST_ELEMENT (mp3parse), mp3parse->srcpad);
158
159 mp3parse->adapter = gst_adapter_new ();
160 + mp3parse->pending_accurate_seeks_lock = g_mutex_new ();
161
162 gst_mp3parse_reset (mp3parse);
163 }
164 @@ -316,10 +310,14 @@
165 {
166 GstMPEGAudioParse *mp3parse = GST_MP3PARSE (object);
167
168 + gst_mp3parse_reset (mp3parse);
169 +
170 if (mp3parse->adapter) {
171 g_object_unref (mp3parse->adapter);
172 mp3parse->adapter = NULL;
173 }
174 + g_mutex_free (mp3parse->pending_accurate_seeks_lock);
175 + mp3parse->pending_accurate_seeks_lock = NULL;
176
177 G_OBJECT_CLASS (parent_class)->dispose (object);
178 }
179 @@ -329,6 +327,7 @@
180 {
181 gboolean res;
182 GstMPEGAudioParse *mp3parse;
183 + GstEvent **eventp;
184
185 mp3parse = GST_MP3PARSE (gst_pad_get_parent (pad));
186
187 @@ -343,6 +342,64 @@
188 gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
189 &format, &start, &stop, &pos);
190
191 + g_mutex_lock (mp3parse->pending_accurate_seeks_lock);
192 + if (format == GST_FORMAT_BYTES && mp3parse->pending_accurate_seeks) {
193 + MPEGAudioPendingAccurateSeek *seek = NULL;
194 + GSList *node;
195 +
196 + for (node = mp3parse->pending_accurate_seeks; node; node = node->next) {
197 + MPEGAudioPendingAccurateSeek *tmp = node->data;
198 +
199 + if (tmp->upstream_start == pos) {
200 + seek = tmp;
201 + break;
202 + }
203 + }
204 + if (seek) {
205 + GstSegment *s = &seek->segment;
206 +
207 + event =
208 + gst_event_new_new_segment_full (FALSE, s->rate, s->applied_rate,
209 + GST_FORMAT_TIME, s->start, s->stop, s->last_stop);
210 +
211 + mp3parse->segment = seek->segment;
212 +
213 + mp3parse->resyncing = FALSE;
214 + mp3parse->cur_offset = pos;
215 + mp3parse->next_ts = seek->timestamp_start;
216 + mp3parse->pending_ts = GST_CLOCK_TIME_NONE;
217 + mp3parse->tracked_offset = 0;
218 +
219 + gst_event_parse_new_segment_full (event, &update, &rate,
220 + &applied_rate, &format, &start, &stop, &pos);
221 +
222 + GST_DEBUG_OBJECT (mp3parse,
223 + "Pushing accurate newseg rate %g, applied rate %g, "
224 + "format %d, start %lld, stop %lld, pos %lld\n", rate,
225 + applied_rate, format, start, stop, pos);
226 +
227 + g_free (seek);
228 + mp3parse->pending_accurate_seeks =
229 + g_slist_delete_link (mp3parse->pending_accurate_seeks, node);
230 +
231 + g_mutex_unlock (mp3parse->pending_accurate_seeks_lock);
232 + if (s->flags & GST_SEEK_FLAG_SEGMENT) {
233 + gst_element_post_message (GST_ELEMENT_CAST (mp3parse),
234 + gst_message_new_segment_start (GST_OBJECT_CAST (mp3parse),
235 + s->format, s->last_stop));
236 + }
237 + res = gst_pad_push_event (mp3parse->srcpad, event);
238 +
239 + return res;
240 + } else {
241 + GST_WARNING_OBJECT (mp3parse,
242 + "Accurate seek not possible, didn't get an appropiate upstream segment");
243 + }
244 + }
245 + g_mutex_unlock (mp3parse->pending_accurate_seeks_lock);
246 +
247 + mp3parse->exact_position = FALSE;
248 +
249 if (format == GST_FORMAT_BYTES) {
250 GstClockTime seg_start, seg_stop, seg_pos;
251
252 @@ -356,8 +413,9 @@
253 GST_FORMAT_TIME, seg_start, seg_stop, seg_pos);
254 format = GST_FORMAT_TIME;
255 GST_DEBUG_OBJECT (mp3parse, "Converted incoming segment to TIME. "
256 - "start = %" G_GINT64_FORMAT ", stop = %" G_GINT64_FORMAT
257 - "pos = %" G_GINT64_FORMAT, seg_start, seg_stop, seg_pos);
258 + "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT
259 + ", pos = %" GST_TIME_FORMAT, GST_TIME_ARGS (seg_start),
260 + GST_TIME_ARGS (seg_stop), GST_TIME_ARGS (seg_pos));
261 }
262 }
263
264 @@ -379,12 +437,22 @@
265 GST_DEBUG_OBJECT (mp3parse, "Pushing newseg rate %g, applied rate %g, "
266 "format %d, start %lld, stop %lld, pos %lld\n",
267 rate, applied_rate, format, start, stop, pos);
268 - res = gst_pad_push_event (mp3parse->srcpad, event);
269 +
270 + gst_segment_set_newsegment_full (&mp3parse->segment, update, rate,
271 + applied_rate, format, start, stop, pos);
272 +
273 + /* save the segment for later, right before we push a new buffer so that
274 + * the caps are fixed and the next linked element can receive the segment. */
275 + eventp = &mp3parse->pending_segment;
276 + gst_event_replace (eventp, event);
277 + res = TRUE;
278 break;
279 }
280 case GST_EVENT_FLUSH_STOP:
281 /* Clear our adapter and set up for a new position */
282 gst_adapter_clear (mp3parse->adapter);
283 + eventp = &mp3parse->pending_segment;
284 + gst_event_replace (eventp, NULL);
285 res = gst_pad_push_event (mp3parse->srcpad, event);
286 break;
287 default:
288 @@ -397,14 +465,26 @@
289 return res;
290 }
291
292 +static MPEGAudioSeekEntry *
293 +mp3parse_seek_table_last_entry (GstMPEGAudioParse * mp3parse)
294 +{
295 + MPEGAudioSeekEntry *ret = NULL;
296 +
297 + if (mp3parse->seek_table) {
298 + ret = mp3parse->seek_table->data;
299 + }
300 +
301 + return ret;
302 +}
303 +
304 /* Prepare a buffer of the indicated size, timestamp it and output */
305 static GstFlowReturn
306 gst_mp3parse_emit_frame (GstMPEGAudioParse * mp3parse, guint size)
307 {
308 GstBuffer *outbuf;
309 guint bitrate;
310 -
311 - GST_DEBUG_OBJECT (mp3parse, "pushing buffer of %d bytes", size);
312 + GstFlowReturn ret = GST_FLOW_OK;
313 + GstClockTime push_start;
314
315 outbuf = gst_adapter_take_buffer (mp3parse->adapter, size);
316
317 @@ -456,6 +536,22 @@
318 }
319 }
320
321 + if (GST_BUFFER_TIMESTAMP (outbuf) == 0)
322 + mp3parse->exact_position = TRUE;
323 +
324 + if (mp3parse->exact_position && (!mp3parse->seek_table ||
325 + (mp3parse_seek_table_last_entry (mp3parse))->byte <
326 + GST_BUFFER_OFFSET (outbuf))) {
327 + MPEGAudioSeekEntry *entry = g_new0 (MPEGAudioSeekEntry, 1);
328 +
329 + entry->byte = mp3parse->cur_offset;
330 + entry->timestamp = GST_BUFFER_TIMESTAMP (outbuf);
331 + mp3parse->seek_table = g_list_prepend (mp3parse->seek_table, entry);
332 + GST_DEBUG_OBJECT (mp3parse, "Adding index entry %" GST_TIME_FORMAT
333 + " @ offset 0x%08" G_GINT64_MODIFIER "x",
334 + GST_TIME_ARGS (entry->timestamp), entry->byte);
335 + }
336 +
337 /* Update our byte offset tracking */
338 if (mp3parse->cur_offset != -1) {
339 mp3parse->cur_offset += size;
340 @@ -483,7 +579,52 @@
341 mp3parse->srcpad, taglist);
342 }
343
344 - return gst_pad_push (mp3parse->srcpad, outbuf);
345 + /* We start pushing 9 frames earlier (29 frames for MPEG2) than
346 + * segment start to be able to decode the first frame we want.
347 + * 9 (29) frames are the theoretical maximum of frames that contain
348 + * data for the current frame (bit reservoir).
349 + */
350 +
351 + if (mp3parse->segment.start == 0) {
352 + push_start = 0;
353 + } else if (GST_CLOCK_TIME_IS_VALID (mp3parse->max_bitreservoir)) {
354 + if (mp3parse->segment.start > mp3parse->max_bitreservoir)
355 + push_start = mp3parse->segment.start - mp3parse->max_bitreservoir;
356 + else
357 + push_start = 0;
358 + } else {
359 + push_start = mp3parse->segment.start;
360 + }
361 +
362 + if (G_UNLIKELY ((GST_CLOCK_TIME_IS_VALID (push_start) &&
363 + GST_BUFFER_TIMESTAMP (outbuf) + GST_BUFFER_DURATION (outbuf)
364 + < push_start)
365 + || (GST_CLOCK_TIME_IS_VALID (mp3parse->segment.stop)
366 + && GST_BUFFER_TIMESTAMP (outbuf) >= mp3parse->segment.stop))) {
367 + GST_DEBUG_OBJECT (mp3parse,
368 + "Buffer outside of configured segment range %" GST_TIME_FORMAT
369 + " to %" GST_TIME_FORMAT ", dropping, timestamp %"
370 + GST_TIME_FORMAT ", offset 0x%08" G_GINT64_MODIFIER "x",
371 + GST_TIME_ARGS (push_start), GST_TIME_ARGS (mp3parse->segment.stop),
372 + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
373 + GST_BUFFER_OFFSET (outbuf));
374 + gst_buffer_unref (outbuf);
375 + ret = GST_FLOW_OK;
376 + } else {
377 + GST_DEBUG_OBJECT (mp3parse,
378 + "pushing buffer of %d bytes, timestamp %" GST_TIME_FORMAT
379 + ", offset 0x%08" G_GINT64_MODIFIER "x", size,
380 + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
381 + GST_BUFFER_OFFSET (outbuf));
382 + mp3parse->segment.last_stop = GST_BUFFER_TIMESTAMP (outbuf);
383 + /* push any pending segment now */
384 + if (mp3parse->pending_segment)
385 + gst_pad_push_event (mp3parse->srcpad, mp3parse->pending_segment);
386 + mp3parse->pending_segment = NULL;
387 + ret = gst_pad_push (mp3parse->srcpad, outbuf);
388 + }
389 +
390 + return ret;
391 }
392
393 #define XING_FRAMES_FLAG 0x0001
394 @@ -610,14 +751,41 @@
395 mp3parse->xing_bytes = 0;
396
397 if (xing_flags & XING_TOC_FLAG) {
398 - gint i;
399 + int i, percent = 0;
400 + guchar *table = mp3parse->xing_seek_table;
401 +
402 + /* xing seek table: percent time -> 1/256 bytepos */
403 + memcpy (mp3parse->xing_seek_table, data, 100);
404
405 - for (i = 0; i < 100; i++) {
406 - mp3parse->xing_seek_table[i] = data[0];
407 - data++;
408 + /* build inverse table: 1/256 bytepos -> 1/100 percent time */
409 + for (i = 0; i < 256; i++) {
410 + while (percent < 99 && table[percent + 1] <= i)
411 + percent++;
412 +
413 + if (table[percent] == i) {
414 + mp3parse->xing_seek_table_inverse[i] = percent * 100;
415 + } else if (table[percent] < i && percent < 99) {
416 + gdouble fa, fb, fx;
417 + gint a = percent, b = percent + 1;
418 +
419 + fa = table[a];
420 + fb = table[b];
421 + fx = (b - a) / (fb - fa) * (i - fa) + a;
422 + mp3parse->xing_seek_table_inverse[i] = (guint16) (fx * 100);
423 + } else if (percent == 98 && table[percent + 1] <= i) {
424 + gdouble fa, fb, fx;
425 + gint a = percent + 1, b = 100;
426 +
427 + fa = table[a];
428 + fb = 256.0;
429 + fx = (b - a) / (fb - fa) * (i - fa) + a;
430 + mp3parse->xing_seek_table_inverse[i] = (guint16) (fx * 100);
431 + }
432 }
433 + data += 100;
434 } else {
435 memset (mp3parse->xing_seek_table, 0, 100);
436 + memset (mp3parse->xing_seek_table_inverse, 0, 256);
437 }
438
439 if (xing_flags & XING_VBR_SCALE_FLAG) {
440 @@ -777,6 +945,9 @@
441 mp3parse->spf = 1152;
442 }
443
444 + mp3parse->max_bitreservoir = gst_util_uint64_scale (GST_SECOND,
445 + ((version == 1) ? 10 : 30) * mp3parse->spf, mp3parse->rate);
446 +
447 /* Check the first frame for a Xing header to get our total length */
448 if (mp3parse->frame_count == 0) {
449 /* For the first frame in the file, look for a Xing frame after
450 @@ -930,6 +1101,45 @@
451 return result;
452 }
453
454 +static gboolean
455 +mp3parse_total_bytes (GstMPEGAudioParse * mp3parse, gint64 * total)
456 +{
457 + GstFormat fmt = GST_FORMAT_BYTES;
458 +
459 + if (gst_pad_query_peer_duration (mp3parse->sinkpad, &fmt, total))
460 + return TRUE;
461 +
462 + if (mp3parse->xing_flags & XING_BYTES_FLAG) {
463 + *total = mp3parse->xing_bytes;
464 + return TRUE;
465 + }
466 +
467 + return FALSE;
468 +}
469 +
470 +static gboolean
471 +mp3parse_total_time (GstMPEGAudioParse * mp3parse, GstClockTime * total)
472 +{
473 + gint64 total_bytes;
474 +
475 + *total = GST_CLOCK_TIME_NONE;
476 +
477 + if (mp3parse->xing_flags & XING_FRAMES_FLAG) {
478 + *total = mp3parse->xing_total_time;
479 + return TRUE;
480 + }
481 +
482 + /* Calculate time from the measured bitrate */
483 + if (!mp3parse_total_bytes (mp3parse, &total_bytes))
484 + return FALSE;
485 +
486 + if (total_bytes != -1
487 + && !mp3parse_bytepos_to_time (mp3parse, total_bytes, total))
488 + return FALSE;
489 +
490 + return TRUE;
491 +}
492 +
493 /* Convert a timestamp to the file position required to start decoding that
494 * timestamp. For now, this just uses the avg bitrate. Later, use an
495 * incrementally accumulated seek table */
496 @@ -937,12 +1147,38 @@
497 mp3parse_time_to_bytepos (GstMPEGAudioParse * mp3parse, GstClockTime ts,
498 gint64 * bytepos)
499 {
500 + gint64 total_bytes;
501 + GstClockTime total_time;
502 +
503 /* -1 always maps to -1 */
504 if (ts == -1) {
505 *bytepos = -1;
506 return TRUE;
507 }
508
509 + /* If XING seek table exists use this for time->byte conversion */
510 + if ((mp3parse->xing_flags & XING_TOC_FLAG) &&
511 + mp3parse_total_bytes (mp3parse, &total_bytes) &&
512 + mp3parse_total_time (mp3parse, &total_time)) {
513 + gdouble fa, fb, fx;
514 + gdouble percent =
515 + CLAMP ((100.0 * gst_util_guint64_to_gdouble (ts)) /
516 + gst_util_guint64_to_gdouble (total_time), 0.0, 100.0);
517 + gint index = CLAMP (percent, 0, 99);
518 +
519 + fa = mp3parse->xing_seek_table[index];
520 + if (index < 99)
521 + fb = mp3parse->xing_seek_table[index + 1];
522 + else
523 + fb = 256.0;
524 +
525 + fx = fa + (fb - fa) * (percent - index);
526 +
527 + *bytepos = (1.0 / 256.0) * fx * total_bytes;
528 +
529 + return TRUE;
530 + }
531 +
532 if (mp3parse->avg_bitrate == 0)
533 goto no_bitrate;
534
535 @@ -958,6 +1194,9 @@
536 mp3parse_bytepos_to_time (GstMPEGAudioParse * mp3parse,
537 gint64 bytepos, GstClockTime * ts)
538 {
539 + gint64 total_bytes;
540 + GstClockTime total_time;
541 +
542 if (bytepos == -1) {
543 *ts = GST_CLOCK_TIME_NONE;
544 return TRUE;
545 @@ -968,61 +1207,33 @@
546 return TRUE;
547 }
548
549 - /* Cannot convert anything except 0 if we don't have a bitrate yet */
550 - if (mp3parse->avg_bitrate == 0)
551 - return FALSE;
552 -
553 - *ts = (GstClockTime) gst_util_uint64_scale (GST_SECOND, bytepos * 8,
554 - mp3parse->avg_bitrate);
555 - return TRUE;
556 -}
557 -
558 -static gboolean
559 -mp3parse_total_bytes (GstMPEGAudioParse * mp3parse, gint64 * total)
560 -{
561 - GstQuery *query;
562 - GstPad *peer;
563 -
564 - if ((peer = gst_pad_get_peer (mp3parse->sinkpad)) != NULL) {
565 - query = gst_query_new_duration (GST_FORMAT_BYTES);
566 - gst_query_set_duration (query, GST_FORMAT_BYTES, -1);
567 -
568 - if (gst_pad_query (peer, query)) {
569 - gst_object_unref (peer);
570 - gst_query_parse_duration (query, NULL, total);
571 - return TRUE;
572 - }
573 - gst_object_unref (peer);
574 - }
575 -
576 - if (mp3parse->xing_flags & XING_BYTES_FLAG) {
577 - *total = mp3parse->xing_bytes;
578 - return TRUE;
579 - }
580 -
581 - return FALSE;
582 -}
583 + /* If XING seek table exists use this for byte->time conversion */
584 + if ((mp3parse->xing_flags & XING_TOC_FLAG) &&
585 + mp3parse_total_bytes (mp3parse, &total_bytes) &&
586 + mp3parse_total_time (mp3parse, &total_time)) {
587 + gdouble fa, fb, fx;
588 + gdouble pos = CLAMP ((bytepos * 256.0) / total_bytes, 0.0, 256.0);
589 + gint index = CLAMP (pos, 0, 255);
590 +
591 + fa = mp3parse->xing_seek_table_inverse[index];
592 + if (index < 255)
593 + fb = mp3parse->xing_seek_table_inverse[index + 1];
594 + else
595 + fb = 10000.0;
596
597 -static gboolean
598 -mp3parse_total_time (GstMPEGAudioParse * mp3parse, GstClockTime * total)
599 -{
600 - gint64 total_bytes;
601 + fx = fa + (fb - fa) * (pos - index);
602
603 - *total = GST_CLOCK_TIME_NONE;
604 + *ts = (1.0 / 10000.0) * fx * gst_util_guint64_to_gdouble (total_time);
605
606 - if (mp3parse->xing_flags & XING_FRAMES_FLAG) {
607 - *total = mp3parse->xing_total_time;
608 return TRUE;
609 }
610
611 - /* Calculate time from the measured bitrate */
612 - if (!mp3parse_total_bytes (mp3parse, &total_bytes))
613 - return FALSE;
614 -
615 - if (total_bytes != -1
616 - && !mp3parse_bytepos_to_time (mp3parse, total_bytes, total))
617 + /* Cannot convert anything except 0 if we don't have a bitrate yet */
618 + if (mp3parse->avg_bitrate == 0)
619 return FALSE;
620
621 + *ts = (GstClockTime) gst_util_uint64_scale (GST_SECOND, bytepos * 8,
622 + mp3parse->avg_bitrate);
623 return TRUE;
624 }
625
626 @@ -1036,11 +1247,12 @@
627 gint64 cur, stop;
628 gint64 byte_cur, byte_stop;
629
630 - /* FIXME: Use GstSegment for tracking our position */
631 -
632 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
633 &stop_type, &stop);
634
635 + GST_DEBUG_OBJECT (mp3parse, "Performing seek to %" GST_TIME_FORMAT,
636 + GST_TIME_ARGS (cur));
637 +
638 /* For any format other than TIME, see if upstream handles
639 * it directly or fail. For TIME, try upstream, but do it ourselves if
640 * it fails upstream */
641 @@ -1055,6 +1267,90 @@
642
643 /* Handle TIME based seeks by converting to a BYTE position */
644
645 + /* For accurate seeking get the frame 9 (MPEG1) or 29 (MPEG2) frames
646 + * before the one we want to seek to and push them all to the decoder.
647 + *
648 + * This is necessary because of the bit reservoir. See
649 + * http://www.mars.org/mailman/public/mad-dev/2002-May/000634.html
650 + *
651 + */
652 +
653 + if (flags & GST_SEEK_FLAG_ACCURATE) {
654 + MPEGAudioPendingAccurateSeek *seek =
655 + g_new0 (MPEGAudioPendingAccurateSeek, 1);
656 + GstClockTime start;
657 +
658 + seek->segment = mp3parse->segment;
659 +
660 + gst_segment_set_seek (&seek->segment, rate, GST_FORMAT_TIME,
661 + flags, cur_type, cur, stop_type, stop, NULL);
662 +
663 + if (!mp3parse->seek_table) {
664 + byte_cur = 0;
665 + byte_stop = -1;
666 + start = 0;
667 + } else {
668 + MPEGAudioSeekEntry *entry = NULL, *start_entry = NULL, *stop_entry = NULL;
669 + GList *start_node, *stop_node;
670 +
671 + for (start_node = mp3parse->seek_table; start_node;
672 + start_node = start_node->next) {
673 + entry = start_node->data;
674 +
675 + if (cur - mp3parse->max_bitreservoir >= entry->timestamp) {
676 + start_entry = entry;
677 + break;
678 + }
679 + }
680 +
681 + if (!start_entry) {
682 + start_entry = mp3parse->seek_table->data;
683 + start = start_entry->timestamp;
684 + byte_cur = start_entry->byte;
685 + } else {
686 + start = start_entry->timestamp;
687 + byte_cur = start_entry->byte;
688 + }
689 +
690 + for (stop_node = mp3parse->seek_table; stop_node;
691 + stop_node = stop_node->next) {
692 + entry = stop_node->data;
693 +
694 + if (stop >= entry->timestamp) {
695 + stop_node = stop_node->prev;
696 + stop_entry = (stop_node) ? stop_node->data : NULL;
697 + break;
698 + }
699 + }
700 +
701 + if (!stop_entry) {
702 + byte_stop = -1;
703 + } else {
704 + byte_stop = stop_entry->byte;
705 + }
706 +
707 + }
708 + g_mutex_lock (mp3parse->pending_accurate_seeks_lock);
709 + event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type,
710 + byte_cur, stop_type, byte_stop);
711 + if (gst_pad_push_event (mp3parse->sinkpad, event)) {
712 + mp3parse->exact_position = TRUE;
713 + seek->upstream_start = byte_cur;
714 + seek->timestamp_start = start;
715 + mp3parse->pending_accurate_seeks =
716 + g_slist_prepend (mp3parse->pending_accurate_seeks, seek);
717 + g_mutex_unlock (mp3parse->pending_accurate_seeks_lock);
718 + return TRUE;
719 + } else {
720 + g_mutex_unlock (mp3parse->pending_accurate_seeks_lock);
721 + mp3parse->exact_position = TRUE;
722 + g_free (seek);
723 + return TRUE;
724 + }
725 + }
726 +
727 + mp3parse->exact_position = FALSE;
728 +
729 /* Convert the TIME to the appropriate BYTE position at which to resume
730 * decoding. */
731 if (!mp3parse_time_to_bytepos (mp3parse, (GstClockTime) cur, &byte_cur))
732 @@ -1069,6 +1365,11 @@
733 event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type,
734 byte_cur, stop_type, byte_stop);
735
736 + if (flags & GST_SEEK_FLAG_SEGMENT) {
737 + gst_element_post_message (GST_ELEMENT_CAST (mp3parse),
738 + gst_message_new_segment_start (GST_OBJECT_CAST (mp3parse),
739 + GST_FORMAT_TIME, cur));
740 + }
741 return gst_pad_push_event (mp3parse->sinkpad, event);
742 no_pos:
743 GST_DEBUG_OBJECT (mp3parse,
744 Index: gst/mpegaudioparse/gstmpegaudioparse.h
745 ===================================================================
746 RCS file: /cvs/gstreamer/gst-plugins-ugly/gst/mpegaudioparse/gstmpegaudioparse.h,v
747 retrieving revision 1.16
748 retrieving revision 1.20
749 diff -u -r1.16 -r1.20
750 --- gst/mpegaudioparse/gstmpegaudioparse.h 8 Jun 2007 08:39:43 -0000 1.16
751 +++ gst/mpegaudioparse/gstmpegaudioparse.h 16 Aug 2007 11:52:57 -0000 1.20
752 @@ -40,13 +40,29 @@
753
754 typedef struct _GstMPEGAudioParse GstMPEGAudioParse;
755 typedef struct _GstMPEGAudioParseClass GstMPEGAudioParseClass;
756 +typedef struct _MPEGAudioSeekEntry MPEGAudioSeekEntry;
757 +typedef struct _MPEGAudioPendingAccurateSeek MPEGAudioPendingAccurateSeek;
758 +
759 +
760 +struct _MPEGAudioSeekEntry {
761 + gint64 byte;
762 + GstClockTime timestamp;
763 +};
764 +
765 +struct _MPEGAudioPendingAccurateSeek {
766 + GstSegment segment;
767 + gint64 upstream_start;
768 + GstClockTime timestamp_start;
769 +};
770
771 struct _GstMPEGAudioParse {
772 GstElement element;
773
774 GstPad *sinkpad, *srcpad;
775
776 + GstSegment segment;
777 GstClockTime next_ts;
778 +
779 /* Offset as supplied by incoming buffers */
780 gint64 cur_offset;
781
782 @@ -62,6 +78,7 @@
783 guint skip; /* number of frames to skip */
784 guint bit_rate; /* in kbps */
785 gint channels, rate, layer, version;
786 + GstClockTime max_bitreservoir;
787 gint spf; /* Samples per frame */
788
789 gboolean resyncing; /* True when attempting to resync (stricter checks are
790 @@ -79,9 +96,21 @@
791 guint32 xing_frames;
792 GstClockTime xing_total_time;
793 guint32 xing_bytes;
794 + /* percent -> filepos mapping */
795 guchar xing_seek_table[100];
796 + /* filepos -> percent mapping */
797 + guint16 xing_seek_table_inverse[256];
798 guint32 xing_vbr_scale;
799 guint xing_bitrate;
800 +
801 + /* Accurate seeking */
802 + GList *seek_table;
803 + GMutex *pending_accurate_seeks_lock;
804 + GSList *pending_accurate_seeks;
805 + gboolean exact_position;
806 +
807 + /* pending segment */
808 + GstEvent *pending_segment;
809 };
810
811 struct _GstMPEGAudioParseClass {
812
813
814
815 1.1 media-libs/gst-plugins-ugly/files/digest-gst-plugins-ugly-0.10.6-r1
816
817 file : http://sources.gentoo.org/viewcvs.py/gentoo-x86/media-libs/gst-plugins-ugly/files/digest-gst-plugins-ugly-0.10.6-r1?rev=1.1&view=markup
818 plain: http://sources.gentoo.org/viewcvs.py/gentoo-x86/media-libs/gst-plugins-ugly/files/digest-gst-plugins-ugly-0.10.6-r1?rev=1.1&content-type=text/plain
819
820 Index: digest-gst-plugins-ugly-0.10.6-r1
821 ===================================================================
822 MD5 f1016148ecbfba968c0ef1773066988b gst-plugins-ugly-0.10.6.tar.bz2 773777
823 RMD160 6f2ce61800e1013f8695b8e09a3f03beee1c9af8 gst-plugins-ugly-0.10.6.tar.bz2 773777
824 SHA256 9c514d4002fb2a2efc5c60e009c330be2ee05c28649d73de3aa45530161c2c62 gst-plugins-ugly-0.10.6.tar.bz2 773777
825
826
827
828 --
829 gentoo-commits@g.o mailing list