expand tabs
[platform/upstream/gstreamer.git] / ext / theora / theoradec.c
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 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include <gst/gst.h>
25 #include <theora/theora.h>
26 #include <string.h>
27 #include <gst/tag/tag.h>
28
29 GST_DEBUG_CATEGORY (theoradec_debug);
30 #define GST_CAT_DEFAULT theoradec_debug
31
32 #define GST_TYPE_THEORA_DEC \
33   (gst_theora_dec_get_type())
34 #define GST_THEORA_DEC(obj) \
35   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_THEORA_DEC,GstTheoraDec))
36 #define GST_THEORA_DEC_CLASS(klass) \
37   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_THEORA_DEC,GstTheoraDec))
38 #define GST_IS_THEORA_DEC(obj) \
39   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_THEORA_DEC))
40 #define GST_IS_THEORA_DEC_CLASS(obj) \
41   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_THEORA_DEC))
42
43 typedef struct _GstTheoraDec GstTheoraDec;
44 typedef struct _GstTheoraDecClass GstTheoraDecClass;
45
46 struct _GstTheoraDec
47 {
48   GstElement element;
49
50   GstPad *sinkpad;
51   GstPad *srcpad;
52
53   theora_state state;
54   theora_info info;
55   theora_comment comment;
56
57   gboolean have_header;
58   guint64 granulepos;
59
60   GstClockTime last_timestamp;
61   guint64 frame_nr;
62   gboolean need_keyframe;
63   gint width, height;
64   gint offset_x, offset_y;
65
66   gboolean crop;
67
68   GList *queued;
69
70   gdouble segment_rate;
71   gint64 segment_start;
72   gint64 segment_stop;
73   gint64 segment_time;
74 };
75
76 struct _GstTheoraDecClass
77 {
78   GstElementClass parent_class;
79 };
80
81 #define THEORA_DEF_CROP         TRUE
82 enum
83 {
84   ARG_0,
85   ARG_CROP
86 };
87
88 static GstElementDetails theora_dec_details = {
89   "TheoraDec",
90   "Codec/Decoder/Video",
91   "decode raw theora streams to raw YUV video",
92   "Benjamin Otte <in7y118@public.uni-hamburg.de>, "
93       "Wim Taymans <wim@fluendo.com>",
94 };
95
96 static GstStaticPadTemplate theora_dec_src_factory =
97 GST_STATIC_PAD_TEMPLATE ("src",
98     GST_PAD_SRC,
99     GST_PAD_ALWAYS,
100     GST_STATIC_CAPS ("video/x-raw-yuv, "
101         "format = (fourcc) I420, "
102         "framerate = (fraction) [0/1, MAX], "
103         "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
104     );
105
106 static GstStaticPadTemplate theora_dec_sink_factory =
107 GST_STATIC_PAD_TEMPLATE ("sink",
108     GST_PAD_SINK,
109     GST_PAD_ALWAYS,
110     GST_STATIC_CAPS ("video/x-theora")
111     );
112
113 GST_BOILERPLATE (GstTheoraDec, gst_theora_dec, GstElement, GST_TYPE_ELEMENT);
114
115 static void theora_dec_get_property (GObject * object, guint prop_id,
116     GValue * value, GParamSpec * pspec);
117 static void theora_dec_set_property (GObject * object, guint prop_id,
118     const GValue * value, GParamSpec * pspec);
119
120 static gboolean theora_dec_sink_event (GstPad * pad, GstEvent * event);
121 static GstFlowReturn theora_dec_chain (GstPad * pad, GstBuffer * buffer);
122 static GstStateChangeReturn theora_dec_change_state (GstElement * element,
123     GstStateChange transition);
124 static gboolean theora_dec_src_event (GstPad * pad, GstEvent * event);
125 static gboolean theora_dec_src_query (GstPad * pad, GstQuery * query);
126 static gboolean theora_dec_src_convert (GstPad * pad,
127     GstFormat src_format, gint64 src_value,
128     GstFormat * dest_format, gint64 * dest_value);
129 static gboolean theora_dec_sink_convert (GstPad * pad,
130     GstFormat src_format, gint64 src_value,
131     GstFormat * dest_format, gint64 * dest_value);
132 static gboolean theora_dec_sink_query (GstPad * pad, GstQuery * query);
133 static GstCaps *theora_dec_src_getcaps (GstPad * pad);
134
135 #if 0
136 static const GstFormat *theora_get_formats (GstPad * pad);
137 #endif
138 #if 0
139 static const GstEventMask *theora_get_event_masks (GstPad * pad);
140 #endif
141 static const GstQueryType *theora_get_query_types (GstPad * pad);
142
143
144 static void
145 gst_theora_dec_base_init (gpointer g_class)
146 {
147   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
148
149   gst_element_class_add_pad_template (element_class,
150       gst_static_pad_template_get (&theora_dec_src_factory));
151   gst_element_class_add_pad_template (element_class,
152       gst_static_pad_template_get (&theora_dec_sink_factory));
153   gst_element_class_set_details (element_class, &theora_dec_details);
154 }
155
156 static void
157 gst_theora_dec_class_init (GstTheoraDecClass * klass)
158 {
159   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
160   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
161
162   gobject_class->set_property = theora_dec_set_property;
163   gobject_class->get_property = theora_dec_get_property;
164
165   g_object_class_install_property (gobject_class, ARG_CROP,
166       g_param_spec_boolean ("crop", "Crop",
167           "Crop the image to the visible region", THEORA_DEF_CROP,
168           (GParamFlags) G_PARAM_READWRITE));
169
170   gstelement_class->change_state = theora_dec_change_state;
171
172   GST_DEBUG_CATEGORY_INIT (theoradec_debug, "theoradec", 0, "Theora decoder");
173 }
174
175 static void
176 gst_theora_dec_init (GstTheoraDec * dec, GstTheoraDecClass * g_class)
177 {
178   dec->sinkpad =
179       gst_pad_new_from_static_template (&theora_dec_sink_factory, "sink");
180   gst_pad_set_query_function (dec->sinkpad, theora_dec_sink_query);
181   gst_pad_set_event_function (dec->sinkpad, theora_dec_sink_event);
182   gst_pad_set_chain_function (dec->sinkpad, theora_dec_chain);
183   gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
184
185   dec->srcpad =
186       gst_pad_new_from_static_template (&theora_dec_src_factory, "src");
187   gst_pad_set_getcaps_function (dec->srcpad, theora_dec_src_getcaps);
188   gst_pad_set_event_function (dec->srcpad, theora_dec_src_event);
189   gst_pad_set_query_type_function (dec->srcpad, theora_get_query_types);
190   gst_pad_set_query_function (dec->srcpad, theora_dec_src_query);
191
192   gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
193
194   dec->crop = THEORA_DEF_CROP;
195   dec->queued = NULL;
196 }
197
198 /* FIXME: copy from libtheora, theora should somehow make this available for seeking */
199 static int
200 _theora_ilog (unsigned int v)
201 {
202   int ret = 0;
203
204   while (v) {
205     ret++;
206     v >>= 1;
207   }
208   return (ret);
209 }
210
211 static void
212 _inc_granulepos (GstTheoraDec * dec)
213 {
214   guint ilog;
215   gint framecount;
216
217   if (dec->granulepos == -1)
218     return;
219
220   ilog = _theora_ilog (dec->info.keyframe_frequency_force - 1);
221
222   framecount = dec->granulepos >> ilog;
223   framecount += dec->granulepos - (framecount << ilog);
224
225   GST_DEBUG_OBJECT (dec, "framecount=%d, ilog=%u", framecount, ilog);
226
227   framecount++;
228
229   dec->granulepos = (framecount << ilog);
230 }
231
232 #if 0
233 static const GstFormat *
234 theora_get_formats (GstPad * pad)
235 {
236   static GstFormat src_formats[] = {
237     GST_FORMAT_DEFAULT,         /* frames in this case */
238     GST_FORMAT_TIME,
239     GST_FORMAT_BYTES,
240     0
241   };
242   static GstFormat sink_formats[] = {
243     GST_FORMAT_DEFAULT,
244     GST_FORMAT_TIME,
245     0
246   };
247
248   return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats);
249 }
250 #endif
251
252 #if 0
253 static const GstEventMask *
254 theora_get_event_masks (GstPad * pad)
255 {
256   static const GstEventMask theora_src_event_masks[] = {
257     {GST_EVENT_SEEK, GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH},
258     {0,}
259   };
260
261   return theora_src_event_masks;
262 }
263 #endif
264
265 static const GstQueryType *
266 theora_get_query_types (GstPad * pad)
267 {
268   static const GstQueryType theora_src_query_types[] = {
269     GST_QUERY_POSITION,
270     0
271   };
272
273   return theora_src_query_types;
274 }
275
276
277 static gboolean
278 theora_dec_src_convert (GstPad * pad,
279     GstFormat src_format, gint64 src_value,
280     GstFormat * dest_format, gint64 * dest_value)
281 {
282   gboolean res = TRUE;
283   GstTheoraDec *dec;
284   guint64 scale = 1;
285
286   dec = GST_THEORA_DEC (GST_PAD_PARENT (pad));
287
288   /* we need the info part before we can done something */
289   if (!dec->have_header)
290     return FALSE;
291
292   if (src_format == *dest_format) {
293     *dest_value = src_value;
294     return TRUE;
295   }
296
297   switch (src_format) {
298     case GST_FORMAT_BYTES:
299       switch (*dest_format) {
300         case GST_FORMAT_DEFAULT:
301           *dest_value =
302               src_value * 2 / (dec->info.height * dec->info.width * 3);
303           break;
304         case GST_FORMAT_TIME:
305           /* seems like a rather silly conversion, implement me if you like */
306         default:
307           res = FALSE;
308       }
309       break;
310     case GST_FORMAT_TIME:
311       switch (*dest_format) {
312         case GST_FORMAT_BYTES:
313           scale = 3 * (dec->info.width * dec->info.height) / 2;
314         case GST_FORMAT_DEFAULT:
315           *dest_value =
316               scale * (((guint64) src_value * dec->info.fps_numerator) /
317               (dec->info.fps_denominator * GST_SECOND));
318           break;
319         default:
320           res = FALSE;
321       }
322       break;
323     case GST_FORMAT_DEFAULT:
324       switch (*dest_format) {
325         case GST_FORMAT_TIME:
326           *dest_value = src_value * (GST_SECOND * dec->info.fps_denominator /
327               dec->info.fps_numerator);
328           break;
329         case GST_FORMAT_BYTES:
330           *dest_value =
331               src_value * 3 * (dec->info.width * dec->info.height) / 2;
332           break;
333         default:
334           res = FALSE;
335       }
336       break;
337     default:
338       res = FALSE;
339   }
340
341   return res;
342 }
343
344 static gboolean
345 theora_dec_sink_convert (GstPad * pad,
346     GstFormat src_format, gint64 src_value,
347     GstFormat * dest_format, gint64 * dest_value)
348 {
349   gboolean res = TRUE;
350   GstTheoraDec *dec;
351
352   dec = GST_THEORA_DEC (GST_PAD_PARENT (pad));
353
354   /* we need the info part before we can done something */
355   if (!dec->have_header)
356     return FALSE;
357
358   if (src_format == *dest_format) {
359     *dest_value = src_value;
360     return TRUE;
361   }
362
363   switch (src_format) {
364     case GST_FORMAT_DEFAULT:
365     {
366       guint64 framecount;
367       guint ilog;
368
369       ilog = _theora_ilog (dec->info.keyframe_frequency_force - 1);
370
371       /* granulepos is last ilog bits for counting pframes since last iframe and 
372        * bits in front of that for the framenumber of the last iframe. */
373       framecount = src_value >> ilog;
374       framecount += src_value - (framecount << ilog);
375
376       switch (*dest_format) {
377         case GST_FORMAT_TIME:
378           *dest_value = framecount * (GST_SECOND * dec->info.fps_denominator /
379               dec->info.fps_numerator);
380           break;
381         default:
382           res = FALSE;
383       }
384       break;
385     }
386     case GST_FORMAT_TIME:
387     {
388       switch (*dest_format) {
389         case GST_FORMAT_DEFAULT:
390         {
391           guint ilog = _theora_ilog (dec->info.keyframe_frequency_force - 1);
392           guint rest;
393
394           /* framecount */
395           *dest_value = src_value * dec->info.fps_numerator /
396               (GST_SECOND * dec->info.fps_denominator);
397
398           /* funny way of calculating granulepos in theora */
399           rest = *dest_value / dec->info.keyframe_frequency_force;
400           *dest_value -= rest;
401           *dest_value <<= ilog;
402           *dest_value += rest;
403           break;
404         }
405         default:
406           res = FALSE;
407           break;
408       }
409       break;
410     }
411     default:
412       res = FALSE;
413   }
414
415   return res;
416 }
417
418 static gboolean
419 theora_dec_src_query (GstPad * pad, GstQuery * query)
420 {
421   GstTheoraDec *dec = GST_THEORA_DEC (GST_PAD_PARENT (pad));
422   gboolean res = FALSE;
423
424   switch (GST_QUERY_TYPE (query)) {
425     case GST_QUERY_POSITION:
426     {
427       gint64 granulepos, value;
428       GstFormat my_format, format;
429       gint64 time;
430
431       /* we can convert a granule position to everything */
432       granulepos = dec->granulepos;
433
434       GST_LOG_OBJECT (dec,
435           "query %p: we have current granule: %lld", query, granulepos);
436
437       /* parse format */
438       gst_query_parse_position (query, &format, NULL);
439
440       /* and convert to the final format in two steps with time as the 
441        * intermediate step */
442       my_format = GST_FORMAT_TIME;
443       if (!(res =
444               theora_dec_sink_convert (dec->sinkpad, GST_FORMAT_DEFAULT,
445                   granulepos, &my_format, &time)))
446         goto error;
447
448       time = (time - dec->segment_start) + dec->segment_time;
449
450       GST_LOG_OBJECT (dec,
451           "query %p: our time: %" GST_TIME_FORMAT, query, GST_TIME_ARGS (time));
452
453       if (!(res =
454               theora_dec_src_convert (pad, my_format, time, &format, &value)))
455         goto error;
456
457       gst_query_set_position (query, format, value);
458
459       GST_LOG_OBJECT (dec,
460           "query %p: we return %lld (format %u)", query, value, format);
461
462       break;
463     }
464     case GST_QUERY_DURATION:
465       /* forward to peer for total */
466       if (!(res = gst_pad_query (GST_PAD_PEER (dec->sinkpad), query)))
467         goto error;
468       break;
469     case GST_QUERY_CONVERT:
470     {
471       GstFormat src_fmt, dest_fmt;
472       gint64 src_val, dest_val;
473
474       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
475       if (!(res =
476               theora_dec_src_convert (pad, src_fmt, src_val, &dest_fmt,
477                   &dest_val)))
478         goto error;
479
480       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
481       break;
482     }
483     default:
484       res = FALSE;
485       break;
486   }
487   return res;
488
489 error:
490   GST_DEBUG ("query failed");
491   return res;
492 }
493
494 static gboolean
495 theora_dec_sink_query (GstPad * pad, GstQuery * query)
496 {
497   gboolean res = FALSE;
498
499   switch (GST_QUERY_TYPE (query)) {
500     case GST_QUERY_CONVERT:
501     {
502       GstFormat src_fmt, dest_fmt;
503       gint64 src_val, dest_val;
504
505       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
506       if (!(res =
507               theora_dec_sink_convert (pad, src_fmt, src_val, &dest_fmt,
508                   &dest_val)))
509         goto error;
510
511       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
512       break;
513     }
514     default:
515       res = FALSE;
516       break;
517   }
518
519 error:
520   return res;
521 }
522
523 static gboolean
524 theora_dec_src_event (GstPad * pad, GstEvent * event)
525 {
526   gboolean res = TRUE;
527   GstTheoraDec *dec;
528
529   dec = GST_THEORA_DEC (GST_PAD_PARENT (pad));
530
531   switch (GST_EVENT_TYPE (event)) {
532     case GST_EVENT_SEEK:{
533       GstFormat format, tformat;
534       gdouble rate;
535       GstEvent *real_seek;
536       GstSeekFlags flags;
537       GstSeekType cur_type, stop_type;
538       gint64 cur, stop;
539       gint64 tcur, tstop;
540
541       gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
542           &stop_type, &stop);
543
544       /* we have to ask our peer to seek to time here as we know
545        * nothing about how to generate a granulepos from the src
546        * formats or anything.
547        * 
548        * First bring the requested format to time 
549        */
550       tformat = GST_FORMAT_TIME;
551       if (!(res = theora_dec_src_convert (pad, format, cur, &tformat, &tcur)))
552         goto error;
553       if (!(res = theora_dec_src_convert (pad, format, stop, &tformat, &tstop)))
554         goto error;
555
556       /* then seek with time on the peer */
557       real_seek = gst_event_new_seek (rate, GST_FORMAT_TIME,
558           flags, cur_type, tcur, stop_type, tstop);
559
560       res = gst_pad_push_event (dec->sinkpad, real_seek);
561
562       gst_event_unref (event);
563       break;
564     }
565     default:
566       res = gst_pad_event_default (pad, event);
567       break;
568   }
569
570   return res;
571
572 error:
573   gst_event_unref (event);
574   return res;
575 }
576
577 static GstCaps *
578 theora_dec_src_getcaps (GstPad * pad)
579 {
580   GstCaps *caps;
581
582   GST_OBJECT_LOCK (pad);
583   if (!(caps = GST_PAD_CAPS (pad)))
584     caps = (GstCaps *) gst_pad_get_pad_template_caps (pad);
585   caps = gst_caps_ref (caps);
586   GST_OBJECT_UNLOCK (pad);
587
588   return caps;
589 }
590
591 static gboolean
592 theora_dec_sink_event (GstPad * pad, GstEvent * event)
593 {
594   gboolean ret = FALSE;
595   GstTheoraDec *dec;
596
597   dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
598
599   GST_LOG_OBJECT (dec, "handling event");
600   switch (GST_EVENT_TYPE (event)) {
601     case GST_EVENT_EOS:
602       ret = gst_pad_push_event (dec->srcpad, event);
603       break;
604     case GST_EVENT_NEWSEGMENT:
605     {
606       GstFormat format;
607       gdouble rate;
608       gint64 start, stop, time;
609
610       gst_event_parse_new_segment (event, NULL, &rate, &format, &start, &stop,
611           &time);
612
613       /* we need TIME and a positive rate */
614       if (format != GST_FORMAT_TIME)
615         goto newseg_wrong_format;
616
617       if (rate <= 0.0)
618         goto newseg_wrong_rate;
619
620       /* now copy over the values */
621       dec->segment_rate = rate;
622       dec->segment_start = start;
623       dec->segment_stop = stop;
624       dec->segment_time = time;
625
626       dec->need_keyframe = TRUE;
627       dec->granulepos = -1;
628       dec->last_timestamp = -1;
629       ret = gst_pad_push_event (dec->srcpad, event);
630       break;
631     }
632     default:
633       ret = gst_pad_push_event (dec->srcpad, event);
634       break;
635   }
636 done:
637   gst_object_unref (dec);
638
639   return ret;
640
641   /* ERRORS */
642 newseg_wrong_format:
643   {
644     GST_DEBUG ("received non TIME newsegment");
645     goto done;
646   }
647 newseg_wrong_rate:
648   {
649     GST_DEBUG ("negative rates not supported yet");
650     goto done;
651   }
652 }
653
654 #define ROUND_UP_2(x) (((x) + 1) & ~1)
655 #define ROUND_UP_4(x) (((x) + 3) & ~3)
656 #define ROUND_UP_8(x) (((x) + 7) & ~7)
657
658 static GstFlowReturn
659 theora_handle_comment_packet (GstTheoraDec * dec, ogg_packet * packet)
660 {
661   gchar *encoder = NULL;
662   GstBuffer *buf;
663   GstTagList *list;
664
665   GST_DEBUG ("parsing comment packet");
666
667   buf = gst_buffer_new_and_alloc (packet->bytes);
668   memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
669
670   list =
671       gst_tag_list_from_vorbiscomment_buffer (buf, (guint8 *) "\201theora", 7,
672       &encoder);
673
674   gst_buffer_unref (buf);
675
676   if (!list) {
677     GST_ERROR_OBJECT (dec, "couldn't decode comments");
678     list = gst_tag_list_new ();
679   }
680   if (encoder) {
681     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
682         GST_TAG_ENCODER, encoder, NULL);
683     g_free (encoder);
684   }
685   gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
686       GST_TAG_ENCODER_VERSION, dec->info.version_major,
687       GST_TAG_NOMINAL_BITRATE, dec->info.target_bitrate,
688       GST_TAG_VIDEO_CODEC, "Theora", NULL);
689
690   //gst_element_found_tags_for_pad (GST_ELEMENT (dec), dec->srcpad, 0, list);
691   gst_tag_list_free (list);
692
693   return GST_FLOW_OK;
694 }
695
696 static GstFlowReturn
697 theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
698 {
699   GstCaps *caps;
700   gint par_num, par_den;
701
702   GST_DEBUG_OBJECT (dec, "fps %d/%d, PAR %d/%d",
703       dec->info.fps_numerator, dec->info.fps_denominator,
704       dec->info.aspect_numerator, dec->info.aspect_denominator);
705
706   /* calculate par
707    * the info.aspect_* values reflect PAR;
708    * 0:0 is allowed and can be interpreted as 1:1, so correct for it */
709   par_num = dec->info.aspect_numerator;
710   par_den = dec->info.aspect_denominator;
711   if (par_num == 0 && par_den == 0) {
712     par_num = par_den = 1;
713   }
714   /* theora has:
715    *
716    *  width/height : dimension of the encoded frame 
717    *  frame_width/frame_height : dimension of the visible part
718    *  offset_x/offset_y : offset in encoded frame where visible part starts
719    */
720   GST_DEBUG_OBJECT (dec, "dimension %dx%d, PAR %d/%d", dec->info.width,
721       dec->info.height, par_num, par_den);
722   GST_DEBUG_OBJECT (dec, "frame dimension %dx%d, offset %d:%d",
723       dec->info.frame_width, dec->info.frame_height,
724       dec->info.offset_x, dec->info.offset_y);
725
726   if (dec->crop) {
727     /* add black borders to make width/height/offsets even. we need this because
728      * we cannot express an offset to the peer plugin. */
729     dec->width = ROUND_UP_2 (dec->info.frame_width + (dec->info.offset_x & 1));
730     dec->height =
731         ROUND_UP_2 (dec->info.frame_height + (dec->info.offset_y & 1));
732     dec->offset_x = dec->info.offset_x & ~1;
733     dec->offset_y = dec->info.offset_y & ~1;
734   } else {
735     /* no cropping, use the encoded dimensions */
736     dec->width = dec->info.width;
737     dec->height = dec->info.height;
738     dec->offset_x = 0;
739     dec->offset_y = 0;
740   }
741
742   GST_DEBUG_OBJECT (dec, "after fixup frame dimension %dx%d, offset %d:%d",
743       dec->width, dec->height, dec->offset_x, dec->offset_y);
744
745   /* done */
746   theora_decode_init (&dec->state, &dec->info);
747
748   caps = gst_caps_new_simple ("video/x-raw-yuv",
749       "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
750       "framerate", GST_TYPE_FRACTION,
751       dec->info.fps_numerator, dec->info.fps_denominator,
752       "pixel-aspect-ratio", GST_TYPE_FRACTION, par_num, par_den,
753       "width", G_TYPE_INT, dec->width, "height", G_TYPE_INT, dec->height, NULL);
754   gst_pad_set_caps (dec->srcpad, caps);
755   gst_caps_unref (caps);
756
757   dec->have_header = TRUE;
758
759   return GST_FLOW_OK;
760 }
761
762 static GstFlowReturn
763 theora_handle_header_packet (GstTheoraDec * dec, ogg_packet * packet)
764 {
765   GstFlowReturn res;
766
767   GST_DEBUG ("parsing header packet");
768
769   if (theora_decode_header (&dec->info, &dec->comment, packet))
770     goto header_read_error;
771
772   switch (packet->packet[0]) {
773     case 0x81:
774       res = theora_handle_comment_packet (dec, packet);
775       break;
776     case 0x82:
777       res = theora_handle_type_packet (dec, packet);
778       break;
779     default:
780       /* ignore */
781       g_warning ("unknown theora header packet found");
782     case 0x80:
783       /* nothing special, this is the identification header */
784       res = GST_FLOW_OK;
785       break;
786   }
787   return res;
788
789   /* ERRORS */
790 header_read_error:
791   {
792     GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
793         (NULL), ("couldn't read header packet"));
794     return GST_FLOW_ERROR;
795   }
796 }
797
798 static GstFlowReturn
799 theora_dec_push (GstTheoraDec * dec, GstBuffer * buf)
800 {
801   GstFlowReturn result;
802   GstClockTime outtime = GST_BUFFER_TIMESTAMP (buf);
803
804   if (outtime == GST_CLOCK_TIME_NONE) {
805     dec->queued = g_list_append (dec->queued, buf);
806     GST_DEBUG_OBJECT (dec, "queued buffer");
807     result = GST_FLOW_OK;
808   } else {
809     if (dec->queued) {
810       gint64 size;
811       GList *walk;
812
813       GST_DEBUG_OBJECT (dec, "first buffer with time %" GST_TIME_FORMAT,
814           GST_TIME_ARGS (outtime));
815
816       size = g_list_length (dec->queued);
817       for (walk = dec->queued; walk; walk = g_list_next (walk)) {
818         GstBuffer *buffer = GST_BUFFER (walk->data);
819         GstClockTime time;
820
821         time = outtime - ((size * GST_SECOND * dec->info.fps_denominator)
822             / dec->info.fps_numerator);
823
824         GST_DEBUG_OBJECT (dec, "patch buffer %lld %lld", size, time);
825         GST_BUFFER_TIMESTAMP (buffer) = time;
826         /* ignore the result */
827         gst_pad_push (dec->srcpad, buffer);
828         size--;
829       }
830       g_list_free (dec->queued);
831       dec->queued = NULL;
832     }
833     result = gst_pad_push (dec->srcpad, buf);
834   }
835
836   return result;
837 }
838
839 static GstFlowReturn
840 theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet,
841     GstClockTime outtime)
842 {
843   /* normal data packet */
844   yuv_buffer yuv;
845   GstBuffer *out;
846   guint i;
847   gboolean keyframe;
848   gint out_size;
849   gint stride_y, stride_uv;
850   gint width, height;
851   gint cwidth, cheight;
852   GstFlowReturn result;
853
854   if (!dec->have_header)
855     goto not_initialized;
856
857   /* the second most significant bit of the first data byte is cleared 
858    * for keyframes */
859   keyframe = (packet->packet[0] & 0x40) == 0;
860   if (keyframe) {
861     dec->need_keyframe = FALSE;
862   } else if (dec->need_keyframe) {
863     goto dropping;
864   }
865
866   if (theora_decode_packetin (&dec->state, packet))
867     goto could_not_read;
868
869   if (theora_decode_YUVout (&dec->state, &yuv) < 0)
870     goto decode_error;
871
872   if ((yuv.y_width != dec->info.width) || (yuv.y_height != dec->info.height))
873     goto wrong_dimensions;
874
875
876   width = dec->width;
877   height = dec->height;
878   cwidth = width / 2;
879   cheight = height / 2;
880
881   /* should get the stride from the caps, for now we round up to the nearest
882    * multiple of 4 because some element needs it. chroma needs special 
883    * treatment, see videotestsrc. */
884   stride_y = ROUND_UP_4 (width);
885   stride_uv = ROUND_UP_8 (width) / 2;
886
887   out_size = stride_y * height + stride_uv * cheight * 2;
888
889   /* now copy over the area contained in offset_x,offset_y,
890    * frame_width, frame_height */
891   result =
892       gst_pad_alloc_buffer_and_set_caps (dec->srcpad, GST_BUFFER_OFFSET_NONE,
893       out_size, GST_PAD_CAPS (dec->srcpad), &out);
894   if (result != GST_FLOW_OK)
895     goto no_buffer;
896
897   /* copy the visible region to the destination. This is actually pretty
898    * complicated and gstreamer doesn't support all the needed caps to do this
899    * correctly. For example, when we have an odd offset, we should only combine
900    * 1 row/column of luma samples with one chroma sample in colorspace conversion. 
901    * We compensate for this by adding a black border around the image when the
902    * offset or size is odd (see above).
903    */
904   {
905     guchar *dest_y, *src_y;
906     guchar *dest_u, *src_u;
907     guchar *dest_v, *src_v;
908
909     dest_y = GST_BUFFER_DATA (out);
910     dest_u = dest_y + stride_y * height;
911     dest_v = dest_u + stride_uv * cheight;
912
913     src_y = yuv.y + dec->offset_x + dec->offset_y * yuv.y_stride;
914
915     for (i = 0; i < height; i++) {
916       memcpy (dest_y, src_y, width);
917
918       dest_y += stride_y;
919       src_y += yuv.y_stride;
920     }
921
922     src_u = yuv.u + dec->offset_x / 2 + dec->offset_y / 2 * yuv.uv_stride;
923     src_v = yuv.v + dec->offset_x / 2 + dec->offset_y / 2 * yuv.uv_stride;
924
925     for (i = 0; i < cheight; i++) {
926       memcpy (dest_u, src_u, cwidth);
927       memcpy (dest_v, src_v, cwidth);
928
929       dest_u += stride_uv;
930       src_u += yuv.uv_stride;
931       dest_v += stride_uv;
932       src_v += yuv.uv_stride;
933     }
934   }
935
936   GST_BUFFER_OFFSET (out) = dec->frame_nr;
937   dec->frame_nr++;
938   GST_BUFFER_OFFSET_END (out) = dec->frame_nr;
939   GST_BUFFER_DURATION (out) =
940       GST_SECOND * ((gdouble) dec->info.fps_denominator) /
941       dec->info.fps_numerator;
942   GST_BUFFER_TIMESTAMP (out) = outtime;
943
944   result = theora_dec_push (dec, out);
945
946   return result;
947
948   /* ERRORS */
949 not_initialized:
950   {
951     GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
952         (NULL), ("no header sent yet"));
953     return GST_FLOW_ERROR;
954   }
955 dropping:
956   {
957     GST_WARNING_OBJECT (dec, "dropping frame because we need a keyframe");
958     return GST_FLOW_OK;
959   }
960 could_not_read:
961   {
962     GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
963         (NULL), ("theora decoder did not read data packet"));
964     return GST_FLOW_ERROR;
965   }
966 decode_error:
967   {
968     GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
969         (NULL), ("couldn't read out YUV image"));
970     return GST_FLOW_ERROR;
971   }
972 wrong_dimensions:
973   {
974     GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
975         (NULL), ("dimensions of image do not match header"));
976     return GST_FLOW_ERROR;
977   }
978 no_buffer:
979   {
980     return result;
981   }
982 }
983
984 static GstFlowReturn
985 theora_dec_chain (GstPad * pad, GstBuffer * buf)
986 {
987   GstTheoraDec *dec;
988   ogg_packet packet;
989   GstFlowReturn result = GST_FLOW_OK;
990
991   dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
992
993   /* make ogg_packet out of the buffer */
994   packet.packet = GST_BUFFER_DATA (buf);
995   packet.bytes = GST_BUFFER_SIZE (buf);
996   packet.granulepos = GST_BUFFER_OFFSET_END (buf);
997   packet.packetno = 0;          /* we don't really care */
998   packet.b_o_s = dec->have_header ? 0 : 1;
999   packet.e_o_s = 0;
1000
1001   if (dec->have_header) {
1002     if (packet.granulepos != -1) {
1003       dec->granulepos = packet.granulepos;
1004       dec->last_timestamp =
1005           GST_SECOND * theora_granule_time (&dec->state, packet.granulepos);
1006     } else if (dec->last_timestamp != -1) {
1007       dec->last_timestamp +=
1008           (GST_SECOND * dec->info.fps_denominator) / dec->info.fps_numerator;
1009     }
1010   } else {
1011     dec->last_timestamp = -1;
1012   }
1013
1014   GST_DEBUG_OBJECT (dec, "header=%d packetno=%lld, outtime=%" GST_TIME_FORMAT,
1015       packet.packet[0], packet.packetno, GST_TIME_ARGS (dec->last_timestamp));
1016
1017   /* switch depending on packet type */
1018   if (packet.packet[0] & 0x80) {
1019     if (dec->have_header) {
1020       GST_WARNING_OBJECT (GST_OBJECT (dec), "Ignoring header");
1021       goto done;
1022     }
1023     result = theora_handle_header_packet (dec, &packet);
1024   } else {
1025     result = theora_handle_data_packet (dec, &packet, dec->last_timestamp);
1026   }
1027
1028 done:
1029   _inc_granulepos (dec);
1030
1031   gst_object_unref (dec);
1032
1033   gst_buffer_unref (buf);
1034
1035   return result;
1036 }
1037
1038 static GstStateChangeReturn
1039 theora_dec_change_state (GstElement * element, GstStateChange transition)
1040 {
1041   GstTheoraDec *dec = GST_THEORA_DEC (element);
1042   GstStateChangeReturn ret;
1043
1044
1045   switch (transition) {
1046     case GST_STATE_CHANGE_NULL_TO_READY:
1047       break;
1048     case GST_STATE_CHANGE_READY_TO_PAUSED:
1049       theora_info_init (&dec->info);
1050       theora_comment_init (&dec->comment);
1051       dec->have_header = FALSE;
1052       dec->need_keyframe = TRUE;
1053       dec->last_timestamp = -1;
1054       dec->granulepos = -1;
1055       break;
1056     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1057       break;
1058     default:
1059       break;
1060   }
1061
1062   ret = parent_class->change_state (element, transition);
1063
1064   switch (transition) {
1065     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1066       break;
1067     case GST_STATE_CHANGE_PAUSED_TO_READY:
1068       theora_clear (&dec->state);
1069       theora_comment_clear (&dec->comment);
1070       theora_info_clear (&dec->info);
1071       dec->have_header = FALSE;
1072       dec->granulepos = -1;
1073       break;
1074     case GST_STATE_CHANGE_READY_TO_NULL:
1075       break;
1076     default:
1077       break;
1078   }
1079
1080   return ret;
1081 }
1082
1083 static void
1084 theora_dec_set_property (GObject * object, guint prop_id,
1085     const GValue * value, GParamSpec * pspec)
1086 {
1087   GstTheoraDec *dec = GST_THEORA_DEC (object);
1088
1089   switch (prop_id) {
1090     case ARG_CROP:
1091       dec->crop = g_value_get_boolean (value);
1092       break;
1093     default:
1094       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1095       break;
1096   }
1097 }
1098
1099 static void
1100 theora_dec_get_property (GObject * object, guint prop_id,
1101     GValue * value, GParamSpec * pspec)
1102 {
1103   GstTheoraDec *dec = GST_THEORA_DEC (object);
1104
1105   switch (prop_id) {
1106     case ARG_CROP:
1107       g_value_set_boolean (value, dec->crop);
1108       break;
1109     default:
1110       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1111       break;
1112   }
1113 }