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 |