|
1 /* GStreamer |
|
2 * Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de> |
|
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., 59 Temple Place - Suite 330, |
|
17 * Boston, MA 02111-1307, USA. |
|
18 */ |
|
19 |
|
20 /** |
|
21 * SECTION:element-theoradec |
|
22 * @see_also: theoraenc, oggdemux |
|
23 * |
|
24 * <refsect2> |
|
25 * <para> |
|
26 * This element decodes theora streams into raw video |
|
27 * <ulink url="http://www.theora.org/">Theora</ulink> is a royalty-free |
|
28 * video codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org |
|
29 * Foundation</ulink>, based on the VP3 codec. |
|
30 * </para> |
|
31 * <para> |
|
32 * </para> |
|
33 * <title>Example pipeline</title> |
|
34 * <programlisting> |
|
35 * gst-launch -v filesrc location=videotestsrc.ogg ! oggdemux ! theoradec ! xvimagesink |
|
36 * </programlisting> |
|
37 * This example pipeline will decode an ogg stream and decodes the theora video. Refer to |
|
38 * the theoraenc example to create the ogg file. |
|
39 * </refsect2> |
|
40 * |
|
41 * Last reviewed on 2006-03-01 (0.10.4) |
|
42 */ |
|
43 |
|
44 #ifdef HAVE_CONFIG_H |
|
45 # include "config.h" |
|
46 #endif |
|
47 |
|
48 #include "gsttheoradec.h" |
|
49 #include <gst/tag/tag.h> |
|
50 |
|
51 #define GST_CAT_DEFAULT theoradec_debug |
|
52 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); |
|
53 |
|
54 #define THEORA_DEF_CROP TRUE |
|
55 enum |
|
56 { |
|
57 ARG_0, |
|
58 ARG_CROP |
|
59 }; |
|
60 |
|
61 static const GstElementDetails theora_dec_details = |
|
62 GST_ELEMENT_DETAILS ("Theora video decoder", |
|
63 "Codec/Decoder/Video", |
|
64 "decode raw theora streams to raw YUV video", |
|
65 "Benjamin Otte <in7y118@public.uni-hamburg.de>, " |
|
66 "Wim Taymans <wim@fluendo.com>"); |
|
67 |
|
68 static GstStaticPadTemplate theora_dec_src_factory = |
|
69 GST_STATIC_PAD_TEMPLATE ("src", |
|
70 GST_PAD_SRC, |
|
71 GST_PAD_ALWAYS, |
|
72 GST_STATIC_CAPS ("video/x-raw-yuv, " |
|
73 "format = (fourcc) I420, " |
|
74 "framerate = (fraction) [0/1, MAX], " |
|
75 "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]") |
|
76 ); |
|
77 |
|
78 static GstStaticPadTemplate theora_dec_sink_factory = |
|
79 GST_STATIC_PAD_TEMPLATE ("sink", |
|
80 GST_PAD_SINK, |
|
81 GST_PAD_ALWAYS, |
|
82 GST_STATIC_CAPS ("video/x-theora") |
|
83 ); |
|
84 |
|
85 GST_BOILERPLATE (GstTheoraDec, gst_theora_dec, GstElement, GST_TYPE_ELEMENT); |
|
86 |
|
87 static void theora_dec_get_property (GObject * object, guint prop_id, |
|
88 GValue * value, GParamSpec * pspec); |
|
89 static void theora_dec_set_property (GObject * object, guint prop_id, |
|
90 const GValue * value, GParamSpec * pspec); |
|
91 |
|
92 static gboolean theora_dec_sink_event (GstPad * pad, GstEvent * event); |
|
93 static GstFlowReturn theora_dec_chain (GstPad * pad, GstBuffer * buffer); |
|
94 static GstStateChangeReturn theora_dec_change_state (GstElement * element, |
|
95 GstStateChange transition); |
|
96 static gboolean theora_dec_src_event (GstPad * pad, GstEvent * event); |
|
97 static gboolean theora_dec_src_query (GstPad * pad, GstQuery * query); |
|
98 static gboolean theora_dec_src_convert (GstPad * pad, |
|
99 GstFormat src_format, gint64 src_value, |
|
100 GstFormat * dest_format, gint64 * dest_value); |
|
101 static gboolean theora_dec_sink_convert (GstPad * pad, |
|
102 GstFormat src_format, gint64 src_value, |
|
103 GstFormat * dest_format, gint64 * dest_value); |
|
104 static gboolean theora_dec_sink_query (GstPad * pad, GstQuery * query); |
|
105 |
|
106 #if 0 |
|
107 static const GstFormat *theora_get_formats (GstPad * pad); |
|
108 #endif |
|
109 #if 0 |
|
110 static const GstEventMask *theora_get_event_masks (GstPad * pad); |
|
111 #endif |
|
112 static const GstQueryType *theora_get_query_types (GstPad * pad); |
|
113 |
|
114 |
|
115 static void |
|
116 gst_theora_dec_base_init (gpointer g_class) |
|
117 { |
|
118 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); |
|
119 |
|
120 gst_element_class_add_pad_template (element_class, |
|
121 gst_static_pad_template_get (&theora_dec_src_factory)); |
|
122 gst_element_class_add_pad_template (element_class, |
|
123 gst_static_pad_template_get (&theora_dec_sink_factory)); |
|
124 gst_element_class_set_details (element_class, &theora_dec_details); |
|
125 } |
|
126 |
|
127 static void |
|
128 gst_theora_dec_class_init (GstTheoraDecClass * klass) |
|
129 { |
|
130 GObjectClass *gobject_class = G_OBJECT_CLASS (klass); |
|
131 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); |
|
132 |
|
133 gobject_class->set_property = theora_dec_set_property; |
|
134 gobject_class->get_property = theora_dec_get_property; |
|
135 |
|
136 g_object_class_install_property (gobject_class, ARG_CROP, |
|
137 g_param_spec_boolean ("crop", "Crop", |
|
138 "Crop the image to the visible region", THEORA_DEF_CROP, |
|
139 (GParamFlags) G_PARAM_READWRITE)); |
|
140 |
|
141 gstelement_class->change_state = theora_dec_change_state; |
|
142 |
|
143 GST_DEBUG_CATEGORY_INIT (theoradec_debug, "theoradec", 0, "Theora decoder"); |
|
144 } |
|
145 |
|
146 static void |
|
147 gst_theora_dec_init (GstTheoraDec * dec, GstTheoraDecClass * g_class) |
|
148 { |
|
149 dec->sinkpad = |
|
150 gst_pad_new_from_static_template (&theora_dec_sink_factory, "sink"); |
|
151 gst_pad_set_query_function (dec->sinkpad, theora_dec_sink_query); |
|
152 gst_pad_set_event_function (dec->sinkpad, theora_dec_sink_event); |
|
153 gst_pad_set_chain_function (dec->sinkpad, theora_dec_chain); |
|
154 gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad); |
|
155 |
|
156 dec->srcpad = |
|
157 gst_pad_new_from_static_template (&theora_dec_src_factory, "src"); |
|
158 gst_pad_set_event_function (dec->srcpad, theora_dec_src_event); |
|
159 gst_pad_set_query_type_function (dec->srcpad, theora_get_query_types); |
|
160 gst_pad_set_query_function (dec->srcpad, theora_dec_src_query); |
|
161 gst_pad_use_fixed_caps (dec->srcpad); |
|
162 |
|
163 gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad); |
|
164 |
|
165 dec->crop = THEORA_DEF_CROP; |
|
166 dec->gather = NULL; |
|
167 dec->decode = NULL; |
|
168 dec->queued = NULL; |
|
169 } |
|
170 |
|
171 static void |
|
172 gst_theora_dec_reset (GstTheoraDec * dec) |
|
173 { |
|
174 dec->need_keyframe = TRUE; |
|
175 dec->sent_newsegment = FALSE; |
|
176 dec->last_timestamp = -1; |
|
177 dec->granulepos = -1; |
|
178 dec->discont = TRUE; |
|
179 dec->frame_nr = -1; |
|
180 gst_segment_init (&dec->segment, GST_FORMAT_TIME); |
|
181 |
|
182 GST_OBJECT_LOCK (dec); |
|
183 dec->proportion = 1.0; |
|
184 dec->earliest_time = -1; |
|
185 GST_OBJECT_UNLOCK (dec); |
|
186 |
|
187 g_list_foreach (dec->queued, (GFunc) gst_mini_object_unref, NULL); |
|
188 g_list_free (dec->queued); |
|
189 dec->queued = NULL; |
|
190 g_list_foreach (dec->gather, (GFunc) gst_mini_object_unref, NULL); |
|
191 g_list_free (dec->gather); |
|
192 dec->gather = NULL; |
|
193 g_list_foreach (dec->decode, (GFunc) gst_mini_object_unref, NULL); |
|
194 g_list_free (dec->decode); |
|
195 dec->decode = NULL; |
|
196 |
|
197 if (dec->tags) { |
|
198 gst_tag_list_free (dec->tags); |
|
199 dec->tags = NULL; |
|
200 } |
|
201 } |
|
202 |
|
203 static int |
|
204 _theora_ilog (unsigned int v) |
|
205 { |
|
206 int ret = 0; |
|
207 |
|
208 while (v) { |
|
209 ret++; |
|
210 v >>= 1; |
|
211 } |
|
212 return (ret); |
|
213 } |
|
214 |
|
215 /* Return the frame number (starting from zero) corresponding to this |
|
216 * granulepos */ |
|
217 static gint64 |
|
218 _theora_granule_frame (GstTheoraDec * dec, gint64 granulepos) |
|
219 { |
|
220 guint ilog; |
|
221 gint framenum; |
|
222 |
|
223 if (granulepos == -1) |
|
224 return -1; |
|
225 |
|
226 ilog = dec->granule_shift; |
|
227 |
|
228 /* granulepos is last ilog bits for counting pframes since last iframe and |
|
229 * bits in front of that for the framenumber of the last iframe. */ |
|
230 framenum = granulepos >> ilog; |
|
231 framenum += granulepos - (framenum << ilog); |
|
232 |
|
233 /* This is 0-based for old bitstreams, 1-based for new. Fix up. */ |
|
234 if (!dec->is_old_bitstream) |
|
235 framenum -= 1; |
|
236 |
|
237 GST_DEBUG_OBJECT (dec, "framecount=%d, ilog=%u", framenum, ilog); |
|
238 |
|
239 return framenum; |
|
240 } |
|
241 |
|
242 /* Return the frame start time corresponding to this granulepos */ |
|
243 static GstClockTime |
|
244 _theora_granule_start_time (GstTheoraDec * dec, gint64 granulepos) |
|
245 { |
|
246 gint64 framecount; |
|
247 |
|
248 /* invalid granule results in invalid time */ |
|
249 if (granulepos == -1) |
|
250 return -1; |
|
251 |
|
252 /* get framecount */ |
|
253 framecount = _theora_granule_frame (dec, granulepos); |
|
254 |
|
255 return gst_util_uint64_scale_int (framecount * GST_SECOND, |
|
256 dec->info.fps_denominator, dec->info.fps_numerator); |
|
257 } |
|
258 |
|
259 static gint64 |
|
260 _inc_granulepos (GstTheoraDec * dec, gint64 granulepos) |
|
261 { |
|
262 gint framecount; |
|
263 |
|
264 if (granulepos == -1) |
|
265 return -1; |
|
266 |
|
267 framecount = _theora_granule_frame (dec, granulepos); |
|
268 |
|
269 return (framecount + 1 + |
|
270 (dec->is_old_bitstream ? 0 : 1)) << dec->granule_shift; |
|
271 } |
|
272 |
|
273 #if 0 |
|
274 static const GstFormat * |
|
275 theora_get_formats (GstPad * pad) |
|
276 { |
|
277 static GstFormat src_formats[] = { |
|
278 GST_FORMAT_DEFAULT, /* frames in this case */ |
|
279 GST_FORMAT_TIME, |
|
280 GST_FORMAT_BYTES, |
|
281 0 |
|
282 }; |
|
283 static GstFormat sink_formats[] = { |
|
284 GST_FORMAT_DEFAULT, |
|
285 GST_FORMAT_TIME, |
|
286 0 |
|
287 }; |
|
288 |
|
289 return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats); |
|
290 } |
|
291 #endif |
|
292 |
|
293 #if 0 |
|
294 static const GstEventMask * |
|
295 theora_get_event_masks (GstPad * pad) |
|
296 { |
|
297 static const GstEventMask theora_src_event_masks[] = { |
|
298 {GST_EVENT_SEEK, GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH}, |
|
299 {0,} |
|
300 }; |
|
301 |
|
302 return theora_src_event_masks; |
|
303 } |
|
304 #endif |
|
305 |
|
306 static const GstQueryType * |
|
307 theora_get_query_types (GstPad * pad) |
|
308 { |
|
309 static const GstQueryType theora_src_query_types[] = { |
|
310 GST_QUERY_POSITION, |
|
311 GST_QUERY_DURATION, |
|
312 GST_QUERY_CONVERT, |
|
313 0 |
|
314 }; |
|
315 |
|
316 return theora_src_query_types; |
|
317 } |
|
318 |
|
319 |
|
320 static gboolean |
|
321 theora_dec_src_convert (GstPad * pad, |
|
322 GstFormat src_format, gint64 src_value, |
|
323 GstFormat * dest_format, gint64 * dest_value) |
|
324 { |
|
325 gboolean res = TRUE; |
|
326 GstTheoraDec *dec; |
|
327 guint64 scale = 1; |
|
328 |
|
329 if (src_format == *dest_format) { |
|
330 *dest_value = src_value; |
|
331 return TRUE; |
|
332 } |
|
333 |
|
334 dec = GST_THEORA_DEC (gst_pad_get_parent (pad)); |
|
335 |
|
336 /* we need the info part before we can done something */ |
|
337 if (!dec->have_header) |
|
338 goto no_header; |
|
339 |
|
340 switch (src_format) { |
|
341 case GST_FORMAT_BYTES: |
|
342 switch (*dest_format) { |
|
343 case GST_FORMAT_DEFAULT: |
|
344 *dest_value = gst_util_uint64_scale_int (src_value, 2, |
|
345 dec->info.height * dec->info.width * 3); |
|
346 break; |
|
347 case GST_FORMAT_TIME: |
|
348 /* seems like a rather silly conversion, implement me if you like */ |
|
349 default: |
|
350 res = FALSE; |
|
351 } |
|
352 break; |
|
353 case GST_FORMAT_TIME: |
|
354 switch (*dest_format) { |
|
355 case GST_FORMAT_BYTES: |
|
356 scale = 3 * (dec->info.width * dec->info.height) / 2; |
|
357 case GST_FORMAT_DEFAULT: |
|
358 *dest_value = scale * gst_util_uint64_scale (src_value, |
|
359 dec->info.fps_numerator, dec->info.fps_denominator * GST_SECOND); |
|
360 break; |
|
361 default: |
|
362 res = FALSE; |
|
363 } |
|
364 break; |
|
365 case GST_FORMAT_DEFAULT: |
|
366 switch (*dest_format) { |
|
367 case GST_FORMAT_TIME: |
|
368 *dest_value = gst_util_uint64_scale (src_value, |
|
369 GST_SECOND * dec->info.fps_denominator, dec->info.fps_numerator); |
|
370 break; |
|
371 case GST_FORMAT_BYTES: |
|
372 *dest_value = gst_util_uint64_scale_int (src_value, |
|
373 3 * dec->info.width * dec->info.height, 2); |
|
374 break; |
|
375 default: |
|
376 res = FALSE; |
|
377 } |
|
378 break; |
|
379 default: |
|
380 res = FALSE; |
|
381 } |
|
382 done: |
|
383 gst_object_unref (dec); |
|
384 return res; |
|
385 |
|
386 /* ERRORS */ |
|
387 no_header: |
|
388 { |
|
389 GST_DEBUG_OBJECT (dec, "no header yet, cannot convert"); |
|
390 res = FALSE; |
|
391 goto done; |
|
392 } |
|
393 } |
|
394 |
|
395 static gboolean |
|
396 theora_dec_sink_convert (GstPad * pad, |
|
397 GstFormat src_format, gint64 src_value, |
|
398 GstFormat * dest_format, gint64 * dest_value) |
|
399 { |
|
400 gboolean res = TRUE; |
|
401 GstTheoraDec *dec; |
|
402 |
|
403 if (src_format == *dest_format) { |
|
404 *dest_value = src_value; |
|
405 return TRUE; |
|
406 } |
|
407 |
|
408 dec = GST_THEORA_DEC (gst_pad_get_parent (pad)); |
|
409 |
|
410 /* we need the info part before we can done something */ |
|
411 if (!dec->have_header) |
|
412 goto no_header; |
|
413 |
|
414 switch (src_format) { |
|
415 case GST_FORMAT_DEFAULT: |
|
416 switch (*dest_format) { |
|
417 case GST_FORMAT_TIME: |
|
418 *dest_value = _theora_granule_start_time (dec, src_value); |
|
419 break; |
|
420 default: |
|
421 res = FALSE; |
|
422 } |
|
423 break; |
|
424 case GST_FORMAT_TIME: |
|
425 switch (*dest_format) { |
|
426 case GST_FORMAT_DEFAULT: |
|
427 { |
|
428 guint rest; |
|
429 |
|
430 /* framecount */ |
|
431 *dest_value = gst_util_uint64_scale (src_value, |
|
432 dec->info.fps_numerator, GST_SECOND * dec->info.fps_denominator); |
|
433 |
|
434 /* funny way of calculating granulepos in theora */ |
|
435 rest = *dest_value / dec->info.keyframe_frequency_force; |
|
436 *dest_value -= rest; |
|
437 *dest_value <<= dec->granule_shift; |
|
438 *dest_value += rest; |
|
439 break; |
|
440 } |
|
441 default: |
|
442 res = FALSE; |
|
443 break; |
|
444 } |
|
445 break; |
|
446 default: |
|
447 res = FALSE; |
|
448 } |
|
449 done: |
|
450 gst_object_unref (dec); |
|
451 return res; |
|
452 |
|
453 /* ERRORS */ |
|
454 no_header: |
|
455 { |
|
456 GST_DEBUG_OBJECT (dec, "no header yet, cannot convert"); |
|
457 res = FALSE; |
|
458 goto done; |
|
459 } |
|
460 } |
|
461 |
|
462 static gboolean |
|
463 theora_dec_src_query (GstPad * pad, GstQuery * query) |
|
464 { |
|
465 GstTheoraDec *dec; |
|
466 |
|
467 gboolean res = FALSE; |
|
468 |
|
469 dec = GST_THEORA_DEC (gst_pad_get_parent (pad)); |
|
470 |
|
471 switch (GST_QUERY_TYPE (query)) { |
|
472 case GST_QUERY_POSITION: |
|
473 { |
|
474 gint64 granulepos, value; |
|
475 GstFormat my_format, format; |
|
476 gint64 time; |
|
477 |
|
478 /* we can convert a granule position to everything */ |
|
479 granulepos = dec->granulepos; |
|
480 |
|
481 GST_LOG_OBJECT (dec, |
|
482 "query %p: we have current granule: %lld", query, granulepos); |
|
483 |
|
484 /* parse format */ |
|
485 gst_query_parse_position (query, &format, NULL); |
|
486 |
|
487 /* and convert to the final format in two steps with time as the |
|
488 * intermediate step */ |
|
489 my_format = GST_FORMAT_TIME; |
|
490 if (!(res = |
|
491 theora_dec_sink_convert (dec->sinkpad, GST_FORMAT_DEFAULT, |
|
492 granulepos, &my_format, &time))) |
|
493 goto error; |
|
494 |
|
495 time = gst_segment_to_stream_time (&dec->segment, GST_FORMAT_TIME, time); |
|
496 |
|
497 GST_LOG_OBJECT (dec, |
|
498 "query %p: our time: %" GST_TIME_FORMAT, query, GST_TIME_ARGS (time)); |
|
499 |
|
500 if (!(res = |
|
501 theora_dec_src_convert (pad, my_format, time, &format, &value))) |
|
502 goto error; |
|
503 |
|
504 gst_query_set_position (query, format, value); |
|
505 |
|
506 GST_LOG_OBJECT (dec, |
|
507 "query %p: we return %lld (format %u)", query, value, format); |
|
508 |
|
509 break; |
|
510 } |
|
511 case GST_QUERY_DURATION: |
|
512 { |
|
513 GstPad *peer; |
|
514 |
|
515 if (!(peer = gst_pad_get_peer (dec->sinkpad))) |
|
516 goto error; |
|
517 |
|
518 /* forward to peer for total */ |
|
519 res = gst_pad_query (peer, query); |
|
520 gst_object_unref (peer); |
|
521 if (!res) |
|
522 goto error; |
|
523 |
|
524 break; |
|
525 } |
|
526 case GST_QUERY_CONVERT: |
|
527 { |
|
528 GstFormat src_fmt, dest_fmt; |
|
529 gint64 src_val, dest_val; |
|
530 |
|
531 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); |
|
532 if (!(res = |
|
533 theora_dec_src_convert (pad, src_fmt, src_val, &dest_fmt, |
|
534 &dest_val))) |
|
535 goto error; |
|
536 |
|
537 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); |
|
538 break; |
|
539 } |
|
540 default: |
|
541 res = gst_pad_query_default (pad, query); |
|
542 break; |
|
543 } |
|
544 done: |
|
545 gst_object_unref (dec); |
|
546 |
|
547 return res; |
|
548 |
|
549 /* ERRORS */ |
|
550 error: |
|
551 { |
|
552 GST_DEBUG_OBJECT (dec, "query failed"); |
|
553 goto done; |
|
554 } |
|
555 } |
|
556 |
|
557 static gboolean |
|
558 theora_dec_sink_query (GstPad * pad, GstQuery * query) |
|
559 { |
|
560 gboolean res = FALSE; |
|
561 |
|
562 switch (GST_QUERY_TYPE (query)) { |
|
563 case GST_QUERY_CONVERT: |
|
564 { |
|
565 GstFormat src_fmt, dest_fmt; |
|
566 gint64 src_val, dest_val; |
|
567 |
|
568 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); |
|
569 if (!(res = |
|
570 theora_dec_sink_convert (pad, src_fmt, src_val, &dest_fmt, |
|
571 &dest_val))) |
|
572 goto error; |
|
573 |
|
574 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); |
|
575 break; |
|
576 } |
|
577 default: |
|
578 res = gst_pad_query_default (pad, query); |
|
579 break; |
|
580 } |
|
581 |
|
582 error: |
|
583 return res; |
|
584 } |
|
585 |
|
586 static gboolean |
|
587 theora_dec_src_event (GstPad * pad, GstEvent * event) |
|
588 { |
|
589 gboolean res = TRUE; |
|
590 GstTheoraDec *dec; |
|
591 |
|
592 dec = GST_THEORA_DEC (gst_pad_get_parent (pad)); |
|
593 |
|
594 switch (GST_EVENT_TYPE (event)) { |
|
595 case GST_EVENT_SEEK: |
|
596 { |
|
597 GstFormat format, tformat; |
|
598 gdouble rate; |
|
599 GstEvent *real_seek; |
|
600 GstSeekFlags flags; |
|
601 GstSeekType cur_type, stop_type; |
|
602 gint64 cur, stop; |
|
603 gint64 tcur, tstop; |
|
604 |
|
605 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur, |
|
606 &stop_type, &stop); |
|
607 gst_event_unref (event); |
|
608 |
|
609 /* we have to ask our peer to seek to time here as we know |
|
610 * nothing about how to generate a granulepos from the src |
|
611 * formats or anything. |
|
612 * |
|
613 * First bring the requested format to time |
|
614 */ |
|
615 tformat = GST_FORMAT_TIME; |
|
616 if (!(res = theora_dec_src_convert (pad, format, cur, &tformat, &tcur))) |
|
617 goto convert_error; |
|
618 if (!(res = theora_dec_src_convert (pad, format, stop, &tformat, &tstop))) |
|
619 goto convert_error; |
|
620 |
|
621 /* then seek with time on the peer */ |
|
622 real_seek = gst_event_new_seek (rate, GST_FORMAT_TIME, |
|
623 flags, cur_type, tcur, stop_type, tstop); |
|
624 |
|
625 res = gst_pad_push_event (dec->sinkpad, real_seek); |
|
626 break; |
|
627 } |
|
628 case GST_EVENT_QOS: |
|
629 { |
|
630 gdouble proportion; |
|
631 GstClockTimeDiff diff; |
|
632 GstClockTime timestamp; |
|
633 |
|
634 gst_event_parse_qos (event, &proportion, &diff, ×tamp); |
|
635 |
|
636 /* we cannot randomly skip frame decoding since we don't have |
|
637 * B frames. we can however use the timestamp and diff to not |
|
638 * push late frames. This would at least save us the time to |
|
639 * crop/memcpy the data. */ |
|
640 GST_OBJECT_LOCK (dec); |
|
641 dec->proportion = proportion; |
|
642 dec->earliest_time = timestamp + diff; |
|
643 GST_OBJECT_UNLOCK (dec); |
|
644 |
|
645 GST_DEBUG_OBJECT (dec, "got QoS %" GST_TIME_FORMAT ", %" G_GINT64_FORMAT, |
|
646 GST_TIME_ARGS (timestamp), diff); |
|
647 |
|
648 res = gst_pad_push_event (dec->sinkpad, event); |
|
649 break; |
|
650 } |
|
651 default: |
|
652 res = gst_pad_push_event (dec->sinkpad, event); |
|
653 break; |
|
654 } |
|
655 done: |
|
656 gst_object_unref (dec); |
|
657 |
|
658 return res; |
|
659 |
|
660 /* ERRORS */ |
|
661 convert_error: |
|
662 { |
|
663 GST_DEBUG_OBJECT (dec, "could not convert format"); |
|
664 goto done; |
|
665 } |
|
666 } |
|
667 |
|
668 static gboolean |
|
669 theora_dec_sink_event (GstPad * pad, GstEvent * event) |
|
670 { |
|
671 gboolean ret = FALSE; |
|
672 GstTheoraDec *dec; |
|
673 |
|
674 dec = GST_THEORA_DEC (gst_pad_get_parent (pad)); |
|
675 |
|
676 GST_LOG_OBJECT (dec, "handling event"); |
|
677 switch (GST_EVENT_TYPE (event)) { |
|
678 case GST_EVENT_FLUSH_START: |
|
679 ret = gst_pad_push_event (dec->srcpad, event); |
|
680 break; |
|
681 case GST_EVENT_FLUSH_STOP: |
|
682 gst_theora_dec_reset (dec); |
|
683 ret = gst_pad_push_event (dec->srcpad, event); |
|
684 break; |
|
685 case GST_EVENT_EOS: |
|
686 ret = gst_pad_push_event (dec->srcpad, event); |
|
687 break; |
|
688 case GST_EVENT_NEWSEGMENT: |
|
689 { |
|
690 gboolean update; |
|
691 GstFormat format; |
|
692 gdouble rate, arate; |
|
693 gint64 start, stop, time; |
|
694 |
|
695 gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, |
|
696 &start, &stop, &time); |
|
697 |
|
698 /* we need TIME format */ |
|
699 if (format != GST_FORMAT_TIME) |
|
700 goto newseg_wrong_format; |
|
701 |
|
702 /* now configure the values */ |
|
703 gst_segment_set_newsegment_full (&dec->segment, update, |
|
704 rate, arate, format, start, stop, time); |
|
705 |
|
706 /* We don't forward this unless/until the decoder is initialised */ |
|
707 if (dec->have_header) { |
|
708 ret = gst_pad_push_event (dec->srcpad, event); |
|
709 dec->sent_newsegment = TRUE; |
|
710 } else { |
|
711 gst_event_unref (event); |
|
712 ret = TRUE; |
|
713 } |
|
714 break; |
|
715 } |
|
716 default: |
|
717 ret = gst_pad_push_event (dec->srcpad, event); |
|
718 break; |
|
719 } |
|
720 done: |
|
721 gst_object_unref (dec); |
|
722 |
|
723 return ret; |
|
724 |
|
725 /* ERRORS */ |
|
726 newseg_wrong_format: |
|
727 { |
|
728 GST_DEBUG_OBJECT (dec, "received non TIME newsegment"); |
|
729 gst_event_unref (event); |
|
730 goto done; |
|
731 } |
|
732 } |
|
733 |
|
734 static GstFlowReturn |
|
735 theora_handle_comment_packet (GstTheoraDec * dec, ogg_packet * packet) |
|
736 { |
|
737 gchar *encoder = NULL; |
|
738 GstBuffer *buf; |
|
739 GstTagList *list; |
|
740 |
|
741 GST_DEBUG_OBJECT (dec, "parsing comment packet"); |
|
742 |
|
743 buf = gst_buffer_new_and_alloc (packet->bytes); |
|
744 memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes); |
|
745 |
|
746 list = |
|
747 gst_tag_list_from_vorbiscomment_buffer (buf, (guint8 *) "\201theora", 7, |
|
748 &encoder); |
|
749 |
|
750 gst_buffer_unref (buf); |
|
751 |
|
752 if (!list) { |
|
753 GST_ERROR_OBJECT (dec, "couldn't decode comments"); |
|
754 list = gst_tag_list_new (); |
|
755 } |
|
756 if (encoder) { |
|
757 gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, |
|
758 GST_TAG_ENCODER, encoder, NULL); |
|
759 g_free (encoder); |
|
760 } |
|
761 gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, |
|
762 GST_TAG_ENCODER_VERSION, dec->info.version_major, |
|
763 GST_TAG_VIDEO_CODEC, "Theora", NULL); |
|
764 |
|
765 if (dec->info.target_bitrate > 0) { |
|
766 gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, |
|
767 GST_TAG_BITRATE, dec->info.target_bitrate, |
|
768 GST_TAG_NOMINAL_BITRATE, dec->info.target_bitrate, NULL); |
|
769 } |
|
770 |
|
771 dec->tags = list; |
|
772 |
|
773 return GST_FLOW_OK; |
|
774 } |
|
775 |
|
776 static GstFlowReturn |
|
777 theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet) |
|
778 { |
|
779 GstCaps *caps; |
|
780 gint par_num, par_den; |
|
781 GstFlowReturn ret = GST_FLOW_OK; |
|
782 gboolean eret; |
|
783 GstEvent *event; |
|
784 guint32 bitstream_version; |
|
785 |
|
786 GST_DEBUG_OBJECT (dec, "fps %d/%d, PAR %d/%d", |
|
787 dec->info.fps_numerator, dec->info.fps_denominator, |
|
788 dec->info.aspect_numerator, dec->info.aspect_denominator); |
|
789 |
|
790 /* calculate par |
|
791 * the info.aspect_* values reflect PAR; |
|
792 * 0:0 is allowed and can be interpreted as 1:1, so correct for it */ |
|
793 par_num = dec->info.aspect_numerator; |
|
794 par_den = dec->info.aspect_denominator; |
|
795 if (par_num == 0 && par_den == 0) { |
|
796 par_num = par_den = 1; |
|
797 } |
|
798 /* theora has: |
|
799 * |
|
800 * width/height : dimension of the encoded frame |
|
801 * frame_width/frame_height : dimension of the visible part |
|
802 * offset_x/offset_y : offset in encoded frame where visible part starts |
|
803 */ |
|
804 GST_DEBUG_OBJECT (dec, "dimension %dx%d, PAR %d/%d", dec->info.width, |
|
805 dec->info.height, par_num, par_den); |
|
806 GST_DEBUG_OBJECT (dec, "frame dimension %dx%d, offset %d:%d", |
|
807 dec->info.frame_width, dec->info.frame_height, |
|
808 dec->info.offset_x, dec->info.offset_y); |
|
809 if (dec->info.pixelformat != OC_PF_420) { |
|
810 GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE, |
|
811 (NULL), ("pixel formats other than 4:2:0 not yet supported")); |
|
812 |
|
813 return GST_FLOW_ERROR; |
|
814 } |
|
815 |
|
816 if (dec->crop) { |
|
817 /* add black borders to make width/height/offsets even. we need this because |
|
818 * we cannot express an offset to the peer plugin. */ |
|
819 dec->width = |
|
820 GST_ROUND_UP_2 (dec->info.frame_width + (dec->info.offset_x & 1)); |
|
821 dec->height = |
|
822 GST_ROUND_UP_2 (dec->info.frame_height + (dec->info.offset_y & 1)); |
|
823 dec->offset_x = dec->info.offset_x & ~1; |
|
824 dec->offset_y = dec->info.offset_y & ~1; |
|
825 } else { |
|
826 /* no cropping, use the encoded dimensions */ |
|
827 dec->width = dec->info.width; |
|
828 dec->height = dec->info.height; |
|
829 dec->offset_x = 0; |
|
830 dec->offset_y = 0; |
|
831 } |
|
832 |
|
833 dec->granule_shift = _theora_ilog (dec->info.keyframe_frequency_force - 1); |
|
834 |
|
835 /* With libtheora-1.0beta1 the granulepos scheme was changed: |
|
836 * where earlier the granulepos refered to the index/beginning |
|
837 * of a frame, it now refers to the end, which matches the use |
|
838 * in vorbis/speex. We check the bitstream version from the header so |
|
839 * we know which way to interpret the incoming granuepos |
|
840 */ |
|
841 bitstream_version = (dec->info.version_major << 16) | |
|
842 (dec->info.version_minor << 8) | dec->info.version_subminor; |
|
843 dec->is_old_bitstream = (bitstream_version <= 0x00030200); |
|
844 |
|
845 GST_DEBUG_OBJECT (dec, "after fixup frame dimension %dx%d, offset %d:%d", |
|
846 dec->width, dec->height, dec->offset_x, dec->offset_y); |
|
847 |
|
848 /* done */ |
|
849 theora_decode_init (&dec->state, &dec->info); |
|
850 |
|
851 caps = gst_caps_new_simple ("video/x-raw-yuv", |
|
852 "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'), |
|
853 "framerate", GST_TYPE_FRACTION, |
|
854 dec->info.fps_numerator, dec->info.fps_denominator, |
|
855 "pixel-aspect-ratio", GST_TYPE_FRACTION, par_num, par_den, |
|
856 "width", G_TYPE_INT, dec->width, "height", G_TYPE_INT, dec->height, NULL); |
|
857 gst_pad_set_caps (dec->srcpad, caps); |
|
858 gst_caps_unref (caps); |
|
859 |
|
860 dec->have_header = TRUE; |
|
861 if (!dec->sent_newsegment) { |
|
862 GST_DEBUG_OBJECT (dec, "Sending newsegment event"); |
|
863 |
|
864 event = gst_event_new_new_segment_full (FALSE, |
|
865 dec->segment.rate, dec->segment.applied_rate, |
|
866 dec->segment.format, dec->segment.start, dec->segment.stop, |
|
867 dec->segment.time); |
|
868 eret = gst_pad_push_event (dec->srcpad, event); |
|
869 if (!eret) |
|
870 ret = GST_FLOW_ERROR; |
|
871 dec->sent_newsegment = TRUE; |
|
872 } |
|
873 |
|
874 if (dec->tags) { |
|
875 gst_element_found_tags_for_pad (GST_ELEMENT_CAST (dec), dec->srcpad, |
|
876 dec->tags); |
|
877 dec->tags = NULL; |
|
878 } |
|
879 |
|
880 return ret; |
|
881 } |
|
882 |
|
883 static GstFlowReturn |
|
884 theora_handle_header_packet (GstTheoraDec * dec, ogg_packet * packet) |
|
885 { |
|
886 GstFlowReturn res; |
|
887 |
|
888 GST_DEBUG_OBJECT (dec, "parsing header packet"); |
|
889 |
|
890 if (theora_decode_header (&dec->info, &dec->comment, packet)) |
|
891 goto header_read_error; |
|
892 |
|
893 switch (packet->packet[0]) { |
|
894 case 0x81: |
|
895 res = theora_handle_comment_packet (dec, packet); |
|
896 break; |
|
897 case 0x82: |
|
898 res = theora_handle_type_packet (dec, packet); |
|
899 break; |
|
900 default: |
|
901 /* ignore */ |
|
902 g_warning ("unknown theora header packet found"); |
|
903 case 0x80: |
|
904 /* nothing special, this is the identification header */ |
|
905 res = GST_FLOW_OK; |
|
906 break; |
|
907 } |
|
908 return res; |
|
909 |
|
910 /* ERRORS */ |
|
911 header_read_error: |
|
912 { |
|
913 GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE, |
|
914 (NULL), ("couldn't read header packet")); |
|
915 return GST_FLOW_ERROR; |
|
916 } |
|
917 } |
|
918 |
|
919 /* returns TRUE if buffer is within segment, else FALSE. |
|
920 * if Buffer is on segment border, it's timestamp and duration will be clipped */ |
|
921 static gboolean |
|
922 clip_buffer (GstTheoraDec * dec, GstBuffer * buf) |
|
923 { |
|
924 gboolean res = TRUE; |
|
925 GstClockTime in_ts, in_dur, stop; |
|
926 gint64 cstart, cstop; |
|
927 |
|
928 in_ts = GST_BUFFER_TIMESTAMP (buf); |
|
929 in_dur = GST_BUFFER_DURATION (buf); |
|
930 |
|
931 GST_LOG_OBJECT (dec, |
|
932 "timestamp:%" GST_TIME_FORMAT " , duration:%" GST_TIME_FORMAT, |
|
933 GST_TIME_ARGS (in_ts), GST_TIME_ARGS (in_dur)); |
|
934 |
|
935 /* can't clip without TIME segment */ |
|
936 if (dec->segment.format != GST_FORMAT_TIME) |
|
937 goto beach; |
|
938 |
|
939 /* we need a start time */ |
|
940 if (!GST_CLOCK_TIME_IS_VALID (in_ts)) |
|
941 goto beach; |
|
942 |
|
943 /* generate valid stop, if duration unknown, we have unknown stop */ |
|
944 stop = |
|
945 GST_CLOCK_TIME_IS_VALID (in_dur) ? (in_ts + in_dur) : GST_CLOCK_TIME_NONE; |
|
946 |
|
947 /* now clip */ |
|
948 if (!(res = gst_segment_clip (&dec->segment, GST_FORMAT_TIME, |
|
949 in_ts, stop, &cstart, &cstop))) |
|
950 goto beach; |
|
951 |
|
952 /* update timestamp and possibly duration if the clipped stop time is |
|
953 * valid */ |
|
954 GST_BUFFER_TIMESTAMP (buf) = cstart; |
|
955 if (GST_CLOCK_TIME_IS_VALID (cstop)) |
|
956 GST_BUFFER_DURATION (buf) = cstop - cstart; |
|
957 |
|
958 beach: |
|
959 GST_LOG_OBJECT (dec, "%sdropping", (res ? "not " : "")); |
|
960 return res; |
|
961 } |
|
962 |
|
963 /* FIXME, this needs to be moved to the demuxer */ |
|
964 static GstFlowReturn |
|
965 theora_dec_push_forward (GstTheoraDec * dec, GstBuffer * buf) |
|
966 { |
|
967 GstFlowReturn result = GST_FLOW_OK; |
|
968 GstClockTime outtime = GST_BUFFER_TIMESTAMP (buf); |
|
969 |
|
970 if (outtime == GST_CLOCK_TIME_NONE) { |
|
971 dec->queued = g_list_append (dec->queued, buf); |
|
972 GST_DEBUG_OBJECT (dec, "queued buffer"); |
|
973 } else { |
|
974 if (dec->queued) { |
|
975 gint64 size; |
|
976 GList *walk; |
|
977 |
|
978 GST_DEBUG_OBJECT (dec, "first buffer with time %" GST_TIME_FORMAT, |
|
979 GST_TIME_ARGS (outtime)); |
|
980 |
|
981 size = g_list_length (dec->queued); |
|
982 for (walk = dec->queued; walk; walk = g_list_next (walk)) { |
|
983 GstBuffer *buffer = GST_BUFFER (walk->data); |
|
984 GstClockTime time; |
|
985 |
|
986 time = outtime - gst_util_uint64_scale_int (size * GST_SECOND, |
|
987 dec->info.fps_denominator, dec->info.fps_numerator); |
|
988 |
|
989 GST_DEBUG_OBJECT (dec, "patch buffer %lld %lld", size, time); |
|
990 GST_BUFFER_TIMESTAMP (buffer) = time; |
|
991 /* Next timestamp - this one is duration */ |
|
992 GST_BUFFER_DURATION (buffer) = |
|
993 (outtime - gst_util_uint64_scale_int ((size - 1) * GST_SECOND, |
|
994 dec->info.fps_denominator, dec->info.fps_numerator)) - time; |
|
995 |
|
996 if (dec->discont) { |
|
997 GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); |
|
998 dec->discont = FALSE; |
|
999 } |
|
1000 /* ignore the result.. */ |
|
1001 if (clip_buffer (dec, buffer)) |
|
1002 gst_pad_push (dec->srcpad, buffer); |
|
1003 else |
|
1004 gst_buffer_unref (buffer); |
|
1005 size--; |
|
1006 } |
|
1007 g_list_free (dec->queued); |
|
1008 dec->queued = NULL; |
|
1009 } |
|
1010 if (dec->discont) { |
|
1011 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); |
|
1012 dec->discont = FALSE; |
|
1013 } |
|
1014 if (clip_buffer (dec, buf)) |
|
1015 result = gst_pad_push (dec->srcpad, buf); |
|
1016 else |
|
1017 gst_buffer_unref (buf); |
|
1018 } |
|
1019 return result; |
|
1020 } |
|
1021 |
|
1022 static GstFlowReturn |
|
1023 theora_dec_push_reverse (GstTheoraDec * dec, GstBuffer * buf) |
|
1024 { |
|
1025 GstFlowReturn result = GST_FLOW_OK; |
|
1026 |
|
1027 dec->queued = g_list_prepend (dec->queued, buf); |
|
1028 |
|
1029 return result; |
|
1030 } |
|
1031 |
|
1032 static GstFlowReturn |
|
1033 theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet, |
|
1034 GstClockTime outtime) |
|
1035 { |
|
1036 /* normal data packet */ |
|
1037 yuv_buffer yuv; |
|
1038 GstBuffer *out; |
|
1039 guint i; |
|
1040 gboolean keyframe; |
|
1041 gint out_size; |
|
1042 gint stride_y, stride_uv; |
|
1043 gint width, height; |
|
1044 gint cwidth, cheight; |
|
1045 GstFlowReturn result; |
|
1046 |
|
1047 if (G_UNLIKELY (!dec->have_header)) |
|
1048 goto not_initialized; |
|
1049 |
|
1050 /* the second most significant bit of the first data byte is cleared |
|
1051 * for keyframes. We can only check it if it's not a zero-length packet. */ |
|
1052 keyframe = packet->bytes && ((packet->packet[0] & 0x40) == 0); |
|
1053 if (G_UNLIKELY (keyframe)) { |
|
1054 GST_DEBUG_OBJECT (dec, "we have a keyframe"); |
|
1055 dec->need_keyframe = FALSE; |
|
1056 } else if (G_UNLIKELY (dec->need_keyframe)) { |
|
1057 goto dropping; |
|
1058 } |
|
1059 |
|
1060 GST_DEBUG_OBJECT (dec, "parsing data packet"); |
|
1061 |
|
1062 /* this does the decoding */ |
|
1063 if (G_UNLIKELY (theora_decode_packetin (&dec->state, packet))) |
|
1064 goto decode_error; |
|
1065 |
|
1066 if (outtime != -1) { |
|
1067 gboolean need_skip; |
|
1068 GstClockTime qostime; |
|
1069 |
|
1070 /* qos needs to be done on running time */ |
|
1071 qostime = gst_segment_to_running_time (&dec->segment, GST_FORMAT_TIME, |
|
1072 outtime); |
|
1073 |
|
1074 GST_OBJECT_LOCK (dec); |
|
1075 /* check for QoS, don't perform the last steps of getting and |
|
1076 * pushing the buffers that are known to be late. */ |
|
1077 /* FIXME, we can also entirely skip decoding if the next valid buffer is |
|
1078 * known to be after a keyframe (using the granule_shift) */ |
|
1079 need_skip = dec->earliest_time != -1 && qostime <= dec->earliest_time; |
|
1080 GST_OBJECT_UNLOCK (dec); |
|
1081 |
|
1082 if (need_skip) |
|
1083 goto dropping_qos; |
|
1084 } |
|
1085 |
|
1086 /* this does postprocessing and set up the decoded frame |
|
1087 * pointers in our yuv variable */ |
|
1088 if (G_UNLIKELY (theora_decode_YUVout (&dec->state, &yuv) < 0)) |
|
1089 goto no_yuv; |
|
1090 |
|
1091 if (G_UNLIKELY ((yuv.y_width != dec->info.width) |
|
1092 || (yuv.y_height != dec->info.height))) |
|
1093 goto wrong_dimensions; |
|
1094 |
|
1095 width = dec->width; |
|
1096 height = dec->height; |
|
1097 cwidth = width / 2; |
|
1098 cheight = height / 2; |
|
1099 |
|
1100 /* should get the stride from the caps, for now we round up to the nearest |
|
1101 * multiple of 4 because some element needs it. chroma needs special |
|
1102 * treatment, see videotestsrc. */ |
|
1103 stride_y = GST_ROUND_UP_4 (width); |
|
1104 stride_uv = GST_ROUND_UP_8 (width) / 2; |
|
1105 |
|
1106 out_size = stride_y * height + stride_uv * cheight * 2; |
|
1107 |
|
1108 /* now copy over the area contained in offset_x,offset_y, |
|
1109 * frame_width, frame_height */ |
|
1110 result = |
|
1111 gst_pad_alloc_buffer_and_set_caps (dec->srcpad, GST_BUFFER_OFFSET_NONE, |
|
1112 out_size, GST_PAD_CAPS (dec->srcpad), &out); |
|
1113 if (G_UNLIKELY (result != GST_FLOW_OK)) |
|
1114 goto no_buffer; |
|
1115 |
|
1116 /* copy the visible region to the destination. This is actually pretty |
|
1117 * complicated and gstreamer doesn't support all the needed caps to do this |
|
1118 * correctly. For example, when we have an odd offset, we should only combine |
|
1119 * 1 row/column of luma samples with one chroma sample in colorspace conversion. |
|
1120 * We compensate for this by adding a black border around the image when the |
|
1121 * offset or size is odd (see above). |
|
1122 */ |
|
1123 { |
|
1124 guchar *dest_y, *src_y; |
|
1125 guchar *dest_u, *src_u; |
|
1126 guchar *dest_v, *src_v; |
|
1127 gint offset; |
|
1128 |
|
1129 dest_y = GST_BUFFER_DATA (out); |
|
1130 dest_u = dest_y + stride_y * height; |
|
1131 dest_v = dest_u + stride_uv * cheight; |
|
1132 |
|
1133 src_y = yuv.y + dec->offset_x + dec->offset_y * yuv.y_stride; |
|
1134 |
|
1135 for (i = 0; i < height; i++) { |
|
1136 memcpy (dest_y, src_y, width); |
|
1137 |
|
1138 dest_y += stride_y; |
|
1139 src_y += yuv.y_stride; |
|
1140 } |
|
1141 |
|
1142 offset = dec->offset_x / 2 + dec->offset_y / 2 * yuv.uv_stride; |
|
1143 |
|
1144 src_u = yuv.u + offset; |
|
1145 src_v = yuv.v + offset; |
|
1146 |
|
1147 for (i = 0; i < cheight; i++) { |
|
1148 memcpy (dest_u, src_u, cwidth); |
|
1149 memcpy (dest_v, src_v, cwidth); |
|
1150 |
|
1151 dest_u += stride_uv; |
|
1152 src_u += yuv.uv_stride; |
|
1153 dest_v += stride_uv; |
|
1154 src_v += yuv.uv_stride; |
|
1155 } |
|
1156 } |
|
1157 |
|
1158 GST_BUFFER_OFFSET (out) = dec->frame_nr; |
|
1159 if (dec->frame_nr != -1) |
|
1160 dec->frame_nr++; |
|
1161 GST_BUFFER_OFFSET_END (out) = dec->frame_nr; |
|
1162 if (dec->granulepos != -1) { |
|
1163 gint64 cf = _theora_granule_frame (dec, dec->granulepos) + 1; |
|
1164 |
|
1165 GST_BUFFER_DURATION (out) = gst_util_uint64_scale_int (cf * GST_SECOND, |
|
1166 dec->info.fps_denominator, dec->info.fps_numerator) - outtime; |
|
1167 } else { |
|
1168 GST_BUFFER_DURATION (out) = |
|
1169 gst_util_uint64_scale_int (GST_SECOND, dec->info.fps_denominator, |
|
1170 dec->info.fps_numerator); |
|
1171 } |
|
1172 GST_BUFFER_TIMESTAMP (out) = outtime; |
|
1173 |
|
1174 if (dec->segment.rate >= 0.0) |
|
1175 result = theora_dec_push_forward (dec, out); |
|
1176 else |
|
1177 result = theora_dec_push_reverse (dec, out); |
|
1178 |
|
1179 return result; |
|
1180 |
|
1181 /* ERRORS */ |
|
1182 not_initialized: |
|
1183 { |
|
1184 GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE, |
|
1185 (NULL), ("no header sent yet")); |
|
1186 return GST_FLOW_ERROR; |
|
1187 } |
|
1188 dropping: |
|
1189 { |
|
1190 GST_WARNING_OBJECT (dec, "dropping frame because we need a keyframe"); |
|
1191 dec->discont = TRUE; |
|
1192 return GST_FLOW_OK; |
|
1193 } |
|
1194 dropping_qos: |
|
1195 { |
|
1196 if (dec->frame_nr != -1) |
|
1197 dec->frame_nr++; |
|
1198 dec->discont = TRUE; |
|
1199 GST_WARNING_OBJECT (dec, "dropping frame because of QoS"); |
|
1200 return GST_FLOW_OK; |
|
1201 } |
|
1202 decode_error: |
|
1203 { |
|
1204 GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE, |
|
1205 (NULL), ("theora decoder did not decode data packet")); |
|
1206 return GST_FLOW_ERROR; |
|
1207 } |
|
1208 no_yuv: |
|
1209 { |
|
1210 GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE, |
|
1211 (NULL), ("couldn't read out YUV image")); |
|
1212 return GST_FLOW_ERROR; |
|
1213 } |
|
1214 wrong_dimensions: |
|
1215 { |
|
1216 GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, FORMAT, |
|
1217 (NULL), ("dimensions of image do not match header")); |
|
1218 return GST_FLOW_ERROR; |
|
1219 } |
|
1220 no_buffer: |
|
1221 { |
|
1222 GST_DEBUG_OBJECT (dec, "could not get buffer, reason: %s", |
|
1223 gst_flow_get_name (result)); |
|
1224 return result; |
|
1225 } |
|
1226 } |
|
1227 |
|
1228 static GstFlowReturn |
|
1229 theora_dec_decode_buffer (GstTheoraDec * dec, GstBuffer * buf) |
|
1230 { |
|
1231 ogg_packet packet; |
|
1232 GstFlowReturn result = GST_FLOW_OK; |
|
1233 |
|
1234 /* make ogg_packet out of the buffer */ |
|
1235 packet.packet = GST_BUFFER_DATA (buf); |
|
1236 packet.bytes = GST_BUFFER_SIZE (buf); |
|
1237 packet.granulepos = GST_BUFFER_OFFSET_END (buf); |
|
1238 packet.packetno = 0; /* we don't really care */ |
|
1239 packet.b_o_s = dec->have_header ? 0 : 1; |
|
1240 /* EOS does not matter for the decoder */ |
|
1241 packet.e_o_s = 0; |
|
1242 |
|
1243 if (dec->have_header) { |
|
1244 if (packet.granulepos != -1) { |
|
1245 dec->granulepos = packet.granulepos; |
|
1246 dec->last_timestamp = _theora_granule_start_time (dec, packet.granulepos); |
|
1247 } else if (dec->last_timestamp != -1) { |
|
1248 dec->last_timestamp = _theora_granule_start_time (dec, dec->granulepos); |
|
1249 } |
|
1250 if (dec->last_timestamp == -1 && GST_BUFFER_TIMESTAMP_IS_VALID (buf)) |
|
1251 dec->last_timestamp = GST_BUFFER_TIMESTAMP (buf); |
|
1252 } else { |
|
1253 dec->last_timestamp = -1; |
|
1254 } |
|
1255 |
|
1256 GST_DEBUG_OBJECT (dec, "header=%02x packetno=%lld, granule pos=%" |
|
1257 G_GINT64_FORMAT ", outtime=%" GST_TIME_FORMAT, |
|
1258 packet.bytes ? packet.packet[0] : -1, packet.packetno, packet.granulepos, |
|
1259 GST_TIME_ARGS (dec->last_timestamp)); |
|
1260 |
|
1261 /* switch depending on packet type. A zero byte packet is always a data |
|
1262 * packet; we don't dereference it in that case. */ |
|
1263 if (packet.bytes && packet.packet[0] & 0x80) { |
|
1264 if (dec->have_header) { |
|
1265 GST_WARNING_OBJECT (GST_OBJECT (dec), "Ignoring header"); |
|
1266 goto done; |
|
1267 } |
|
1268 result = theora_handle_header_packet (dec, &packet); |
|
1269 } else { |
|
1270 result = theora_handle_data_packet (dec, &packet, dec->last_timestamp); |
|
1271 } |
|
1272 |
|
1273 done: |
|
1274 /* interpolate granule pos */ |
|
1275 dec->granulepos = _inc_granulepos (dec, dec->granulepos); |
|
1276 |
|
1277 return result; |
|
1278 } |
|
1279 |
|
1280 /* For reverse playback we use a technique that can be used for |
|
1281 * any keyframe based video codec. |
|
1282 * |
|
1283 * Input: |
|
1284 * Buffer decoding order: 7 8 9 4 5 6 1 2 3 EOS |
|
1285 * Keyframe flag: K K |
|
1286 * Discont flag: D D D |
|
1287 * |
|
1288 * - Each Discont marks a discont in the decoding order. |
|
1289 * - The keyframes mark where we can start decoding. |
|
1290 * |
|
1291 * First we prepend incomming buffers to the gather queue, whenever we receive |
|
1292 * a discont, we flush out the gather queue. |
|
1293 * |
|
1294 * The above data will be accumulated in the gather queue like this: |
|
1295 * |
|
1296 * gather queue: 9 8 7 |
|
1297 * D |
|
1298 * |
|
1299 * Whe buffer 4 is received (with a DISCONT), we flush the gather queue like |
|
1300 * this: |
|
1301 * |
|
1302 * while (gather) |
|
1303 * take head of queue and prepend to decode queue. |
|
1304 * if we copied a keyframe, decode the decode queue. |
|
1305 * |
|
1306 * After we flushed the gather queue, we add 4 to the (now empty) gather queue. |
|
1307 * We get the following situation: |
|
1308 * |
|
1309 * gather queue: 4 |
|
1310 * decode queue: 7 8 9 |
|
1311 * |
|
1312 * After we received 5 (Keyframe) and 6: |
|
1313 * |
|
1314 * gather queue: 6 5 4 |
|
1315 * decode queue: 7 8 9 |
|
1316 * |
|
1317 * When we receive 1 (DISCONT) which triggers a flush of the gather queue: |
|
1318 * |
|
1319 * Copy head of the gather queue (6) to decode queue: |
|
1320 * |
|
1321 * gather queue: 5 4 |
|
1322 * decode queue: 6 7 8 9 |
|
1323 * |
|
1324 * Copy head of the gather queue (5) to decode queue. This is a keyframe so we |
|
1325 * can start decoding. |
|
1326 * |
|
1327 * gather queue: 4 |
|
1328 * decode queue: 5 6 7 8 9 |
|
1329 * |
|
1330 * Decode frames in decode queue, store raw decoded data in output queue, we |
|
1331 * can take the head of the decode queue and prepend the decoded result in the |
|
1332 * output queue: |
|
1333 * |
|
1334 * gather queue: 4 |
|
1335 * decode queue: |
|
1336 * output queue: 9 8 7 6 5 |
|
1337 * |
|
1338 * Now output all the frames in the output queue, picking a frame from the |
|
1339 * head of the queue. |
|
1340 * |
|
1341 * Copy head of the gather queue (4) to decode queue, we flushed the gather |
|
1342 * queue and can now store input buffer in the gather queue: |
|
1343 * |
|
1344 * gather queue: 1 |
|
1345 * decode queue: 4 |
|
1346 * |
|
1347 * When we receive EOS, the queue looks like: |
|
1348 * |
|
1349 * gather queue: 3 2 1 |
|
1350 * decode queue: 4 |
|
1351 * |
|
1352 * Fill decode queue, first keyframe we copy is 2: |
|
1353 * |
|
1354 * gather queue: 1 |
|
1355 * decode queue: 2 3 4 |
|
1356 * |
|
1357 * Decoded output: |
|
1358 * |
|
1359 * gather queue: 1 |
|
1360 * decode queue: |
|
1361 * output queue: 4 3 2 |
|
1362 * |
|
1363 * Leftover buffer 1 cannot be decoded and must be discarded. |
|
1364 */ |
|
1365 static GstFlowReturn |
|
1366 theora_dec_flush_decode (GstTheoraDec * dec) |
|
1367 { |
|
1368 GstFlowReturn res = GST_FLOW_OK; |
|
1369 |
|
1370 while (dec->decode) { |
|
1371 GstBuffer *buf = GST_BUFFER_CAST (dec->decode->data); |
|
1372 |
|
1373 GST_DEBUG_OBJECT (dec, "decoding buffer %p, ts %" GST_TIME_FORMAT, |
|
1374 buf, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); |
|
1375 |
|
1376 /* decode buffer, prepend to output queue */ |
|
1377 res = theora_dec_decode_buffer (dec, buf); |
|
1378 |
|
1379 /* don't need it anymore now */ |
|
1380 gst_buffer_unref (buf); |
|
1381 |
|
1382 dec->decode = g_list_delete_link (dec->decode, dec->decode); |
|
1383 } |
|
1384 while (dec->queued) { |
|
1385 GstBuffer *buf = GST_BUFFER_CAST (dec->queued->data); |
|
1386 |
|
1387 /* iterate ouput queue an push downstream */ |
|
1388 res = gst_pad_push (dec->srcpad, buf); |
|
1389 |
|
1390 dec->queued = g_list_delete_link (dec->queued, dec->queued); |
|
1391 } |
|
1392 |
|
1393 return res; |
|
1394 } |
|
1395 |
|
1396 static GstFlowReturn |
|
1397 theora_dec_chain_reverse (GstTheoraDec * dec, gboolean discont, GstBuffer * buf) |
|
1398 { |
|
1399 GstFlowReturn res = GST_FLOW_OK; |
|
1400 |
|
1401 /* if we have a discont, move buffers to the decode list */ |
|
1402 if (G_UNLIKELY (discont)) { |
|
1403 GST_DEBUG_OBJECT (dec, "received discont,gathering buffers"); |
|
1404 while (dec->gather) { |
|
1405 GstBuffer *gbuf; |
|
1406 guint8 *data; |
|
1407 |
|
1408 gbuf = GST_BUFFER_CAST (dec->gather->data); |
|
1409 /* remove from the gather list */ |
|
1410 dec->gather = g_list_delete_link (dec->gather, dec->gather); |
|
1411 /* copy to decode queue */ |
|
1412 dec->decode = g_list_prepend (dec->decode, gbuf); |
|
1413 |
|
1414 /* if we copied a keyframe, flush and decode the decode queue */ |
|
1415 data = GST_BUFFER_DATA (gbuf); |
|
1416 if ((data[0] & 0x40) == 0) { |
|
1417 GST_DEBUG_OBJECT (dec, "copied keyframe"); |
|
1418 res = theora_dec_flush_decode (dec); |
|
1419 } |
|
1420 } |
|
1421 } |
|
1422 |
|
1423 /* add buffer to gather queue */ |
|
1424 GST_DEBUG_OBJECT (dec, "gathering buffer %p, size %u", buf, |
|
1425 GST_BUFFER_SIZE (buf)); |
|
1426 dec->gather = g_list_prepend (dec->gather, buf); |
|
1427 |
|
1428 return res; |
|
1429 } |
|
1430 |
|
1431 static GstFlowReturn |
|
1432 theora_dec_chain_forward (GstTheoraDec * dec, gboolean discont, |
|
1433 GstBuffer * buffer) |
|
1434 { |
|
1435 GstFlowReturn result; |
|
1436 |
|
1437 result = theora_dec_decode_buffer (dec, buffer); |
|
1438 |
|
1439 gst_buffer_unref (buffer); |
|
1440 |
|
1441 return result; |
|
1442 } |
|
1443 |
|
1444 static GstFlowReturn |
|
1445 theora_dec_chain (GstPad * pad, GstBuffer * buf) |
|
1446 { |
|
1447 GstTheoraDec *dec; |
|
1448 GstFlowReturn res; |
|
1449 gboolean discont; |
|
1450 |
|
1451 dec = GST_THEORA_DEC (gst_pad_get_parent (pad)); |
|
1452 |
|
1453 /* peel of DISCONT flag */ |
|
1454 discont = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT); |
|
1455 |
|
1456 /* resync on DISCONT */ |
|
1457 if (G_UNLIKELY (discont)) { |
|
1458 GST_DEBUG_OBJECT (dec, "received DISCONT buffer"); |
|
1459 dec->need_keyframe = TRUE; |
|
1460 dec->last_timestamp = -1; |
|
1461 dec->granulepos = -1; |
|
1462 dec->discont = TRUE; |
|
1463 } |
|
1464 |
|
1465 if (dec->segment.rate > 0.0) |
|
1466 res = theora_dec_chain_forward (dec, discont, buf); |
|
1467 else |
|
1468 res = theora_dec_chain_reverse (dec, discont, buf); |
|
1469 |
|
1470 gst_object_unref (dec); |
|
1471 |
|
1472 return res; |
|
1473 } |
|
1474 |
|
1475 static GstStateChangeReturn |
|
1476 theora_dec_change_state (GstElement * element, GstStateChange transition) |
|
1477 { |
|
1478 GstTheoraDec *dec = GST_THEORA_DEC (element); |
|
1479 GstStateChangeReturn ret; |
|
1480 |
|
1481 switch (transition) { |
|
1482 case GST_STATE_CHANGE_NULL_TO_READY: |
|
1483 break; |
|
1484 case GST_STATE_CHANGE_READY_TO_PAUSED: |
|
1485 theora_info_init (&dec->info); |
|
1486 theora_comment_init (&dec->comment); |
|
1487 GST_DEBUG_OBJECT (dec, "Setting have_header to FALSE in READY->PAUSED"); |
|
1488 dec->have_header = FALSE; |
|
1489 gst_theora_dec_reset (dec); |
|
1490 break; |
|
1491 case GST_STATE_CHANGE_PAUSED_TO_PLAYING: |
|
1492 break; |
|
1493 default: |
|
1494 break; |
|
1495 } |
|
1496 |
|
1497 ret = parent_class->change_state (element, transition); |
|
1498 |
|
1499 switch (transition) { |
|
1500 case GST_STATE_CHANGE_PLAYING_TO_PAUSED: |
|
1501 break; |
|
1502 case GST_STATE_CHANGE_PAUSED_TO_READY: |
|
1503 theora_clear (&dec->state); |
|
1504 theora_comment_clear (&dec->comment); |
|
1505 theora_info_clear (&dec->info); |
|
1506 gst_theora_dec_reset (dec); |
|
1507 break; |
|
1508 case GST_STATE_CHANGE_READY_TO_NULL: |
|
1509 break; |
|
1510 default: |
|
1511 break; |
|
1512 } |
|
1513 |
|
1514 return ret; |
|
1515 } |
|
1516 |
|
1517 static void |
|
1518 theora_dec_set_property (GObject * object, guint prop_id, |
|
1519 const GValue * value, GParamSpec * pspec) |
|
1520 { |
|
1521 GstTheoraDec *dec = GST_THEORA_DEC (object); |
|
1522 |
|
1523 switch (prop_id) { |
|
1524 case ARG_CROP: |
|
1525 dec->crop = g_value_get_boolean (value); |
|
1526 break; |
|
1527 default: |
|
1528 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
|
1529 break; |
|
1530 } |
|
1531 } |
|
1532 |
|
1533 static void |
|
1534 theora_dec_get_property (GObject * object, guint prop_id, |
|
1535 GValue * value, GParamSpec * pspec) |
|
1536 { |
|
1537 GstTheoraDec *dec = GST_THEORA_DEC (object); |
|
1538 |
|
1539 switch (prop_id) { |
|
1540 case ARG_CROP: |
|
1541 g_value_set_boolean (value, dec->crop); |
|
1542 break; |
|
1543 default: |
|
1544 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
|
1545 break; |
|
1546 } |
|
1547 } |