2 * Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
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.
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.
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.
25 #include <theora/theora.h>
27 #include <gst/tag/tag.h>
29 GST_DEBUG_CATEGORY (theoradec_debug);
30 #define GST_CAT_DEFAULT theoradec_debug
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))
43 typedef struct _GstTheoraDec GstTheoraDec;
44 typedef struct _GstTheoraDecClass GstTheoraDecClass;
55 theora_comment comment;
60 GstClockTime last_timestamp;
62 gboolean need_keyframe;
64 gint offset_x, offset_y;
76 struct _GstTheoraDecClass
78 GstElementClass parent_class;
81 #define THEORA_DEF_CROP TRUE
88 static GstElementDetails theora_dec_details = {
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>",
96 static GstStaticPadTemplate theora_dec_src_factory =
97 GST_STATIC_PAD_TEMPLATE ("src",
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 ]")
106 static GstStaticPadTemplate theora_dec_sink_factory =
107 GST_STATIC_PAD_TEMPLATE ("sink",
110 GST_STATIC_CAPS ("video/x-theora")
113 GST_BOILERPLATE (GstTheoraDec, gst_theora_dec, GstElement, GST_TYPE_ELEMENT);
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);
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);
136 static const GstFormat *theora_get_formats (GstPad * pad);
139 static const GstEventMask *theora_get_event_masks (GstPad * pad);
141 static const GstQueryType *theora_get_query_types (GstPad * pad);
145 gst_theora_dec_base_init (gpointer g_class)
147 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
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);
157 gst_theora_dec_class_init (GstTheoraDecClass * klass)
159 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
160 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
162 gobject_class->set_property = theora_dec_set_property;
163 gobject_class->get_property = theora_dec_get_property;
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));
170 gstelement_class->change_state = theora_dec_change_state;
172 GST_DEBUG_CATEGORY_INIT (theoradec_debug, "theoradec", 0, "Theora decoder");
176 gst_theora_dec_init (GstTheoraDec * dec, GstTheoraDecClass * g_class)
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);
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);
192 gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
194 dec->crop = THEORA_DEF_CROP;
198 /* FIXME: copy from libtheora, theora should somehow make this available for seeking */
200 _theora_ilog (unsigned int v)
212 _inc_granulepos (GstTheoraDec * dec)
217 if (dec->granulepos == -1)
220 ilog = _theora_ilog (dec->info.keyframe_frequency_force - 1);
222 framecount = dec->granulepos >> ilog;
223 framecount += dec->granulepos - (framecount << ilog);
225 GST_DEBUG_OBJECT (dec, "framecount=%d, ilog=%u", framecount, ilog);
229 dec->granulepos = (framecount << ilog);
233 static const GstFormat *
234 theora_get_formats (GstPad * pad)
236 static GstFormat src_formats[] = {
237 GST_FORMAT_DEFAULT, /* frames in this case */
242 static GstFormat sink_formats[] = {
248 return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats);
253 static const GstEventMask *
254 theora_get_event_masks (GstPad * pad)
256 static const GstEventMask theora_src_event_masks[] = {
257 {GST_EVENT_SEEK, GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH},
261 return theora_src_event_masks;
265 static const GstQueryType *
266 theora_get_query_types (GstPad * pad)
268 static const GstQueryType theora_src_query_types[] = {
273 return theora_src_query_types;
278 theora_dec_src_convert (GstPad * pad,
279 GstFormat src_format, gint64 src_value,
280 GstFormat * dest_format, gint64 * dest_value)
286 dec = GST_THEORA_DEC (GST_PAD_PARENT (pad));
288 /* we need the info part before we can done something */
289 if (!dec->have_header)
292 if (src_format == *dest_format) {
293 *dest_value = src_value;
297 switch (src_format) {
298 case GST_FORMAT_BYTES:
299 switch (*dest_format) {
300 case GST_FORMAT_DEFAULT:
302 src_value * 2 / (dec->info.height * dec->info.width * 3);
304 case GST_FORMAT_TIME:
305 /* seems like a rather silly conversion, implement me if you like */
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:
316 scale * (((guint64) src_value * dec->info.fps_numerator) /
317 (dec->info.fps_denominator * GST_SECOND));
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);
329 case GST_FORMAT_BYTES:
331 src_value * 3 * (dec->info.width * dec->info.height) / 2;
345 theora_dec_sink_convert (GstPad * pad,
346 GstFormat src_format, gint64 src_value,
347 GstFormat * dest_format, gint64 * dest_value)
352 dec = GST_THEORA_DEC (GST_PAD_PARENT (pad));
354 /* we need the info part before we can done something */
355 if (!dec->have_header)
358 if (src_format == *dest_format) {
359 *dest_value = src_value;
363 switch (src_format) {
364 case GST_FORMAT_DEFAULT:
369 ilog = _theora_ilog (dec->info.keyframe_frequency_force - 1);
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);
376 switch (*dest_format) {
377 case GST_FORMAT_TIME:
378 *dest_value = framecount * (GST_SECOND * dec->info.fps_denominator /
379 dec->info.fps_numerator);
386 case GST_FORMAT_TIME:
388 switch (*dest_format) {
389 case GST_FORMAT_DEFAULT:
391 guint ilog = _theora_ilog (dec->info.keyframe_frequency_force - 1);
395 *dest_value = src_value * dec->info.fps_numerator /
396 (GST_SECOND * dec->info.fps_denominator);
398 /* funny way of calculating granulepos in theora */
399 rest = *dest_value / dec->info.keyframe_frequency_force;
401 *dest_value <<= ilog;
419 theora_dec_src_query (GstPad * pad, GstQuery * query)
421 GstTheoraDec *dec = GST_THEORA_DEC (GST_PAD_PARENT (pad));
422 gboolean res = FALSE;
424 switch (GST_QUERY_TYPE (query)) {
425 case GST_QUERY_POSITION:
427 gint64 granulepos, value;
428 GstFormat my_format, format;
431 /* we can convert a granule position to everything */
432 granulepos = dec->granulepos;
435 "query %p: we have current granule: %lld", query, granulepos);
438 gst_query_parse_position (query, &format, NULL);
440 /* and convert to the final format in two steps with time as the
441 * intermediate step */
442 my_format = GST_FORMAT_TIME;
444 theora_dec_sink_convert (dec->sinkpad, GST_FORMAT_DEFAULT,
445 granulepos, &my_format, &time)))
448 time = (time - dec->segment_start) + dec->segment_time;
451 "query %p: our time: %" GST_TIME_FORMAT, query, GST_TIME_ARGS (time));
454 theora_dec_src_convert (pad, my_format, time, &format, &value)))
457 gst_query_set_position (query, format, value);
460 "query %p: we return %lld (format %u)", query, value, format);
464 case GST_QUERY_DURATION:
465 /* forward to peer for total */
466 if (!(res = gst_pad_query (GST_PAD_PEER (dec->sinkpad), query)))
469 case GST_QUERY_CONVERT:
471 GstFormat src_fmt, dest_fmt;
472 gint64 src_val, dest_val;
474 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
476 theora_dec_src_convert (pad, src_fmt, src_val, &dest_fmt,
480 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
490 GST_DEBUG ("query failed");
495 theora_dec_sink_query (GstPad * pad, GstQuery * query)
497 gboolean res = FALSE;
499 switch (GST_QUERY_TYPE (query)) {
500 case GST_QUERY_CONVERT:
502 GstFormat src_fmt, dest_fmt;
503 gint64 src_val, dest_val;
505 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
507 theora_dec_sink_convert (pad, src_fmt, src_val, &dest_fmt,
511 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
524 theora_dec_src_event (GstPad * pad, GstEvent * event)
529 dec = GST_THEORA_DEC (GST_PAD_PARENT (pad));
531 switch (GST_EVENT_TYPE (event)) {
532 case GST_EVENT_SEEK:{
533 GstFormat format, tformat;
537 GstSeekType cur_type, stop_type;
541 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
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.
548 * First bring the requested format to time
550 tformat = GST_FORMAT_TIME;
551 if (!(res = theora_dec_src_convert (pad, format, cur, &tformat, &tcur)))
553 if (!(res = theora_dec_src_convert (pad, format, stop, &tformat, &tstop)))
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);
560 res = gst_pad_push_event (dec->sinkpad, real_seek);
562 gst_event_unref (event);
566 res = gst_pad_event_default (pad, event);
573 gst_event_unref (event);
578 theora_dec_src_getcaps (GstPad * pad)
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);
592 theora_dec_sink_event (GstPad * pad, GstEvent * event)
594 gboolean ret = FALSE;
597 dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
599 GST_LOG_OBJECT (dec, "handling event");
600 switch (GST_EVENT_TYPE (event)) {
602 ret = gst_pad_push_event (dec->srcpad, event);
604 case GST_EVENT_NEWSEGMENT:
608 gint64 start, stop, time;
610 gst_event_parse_new_segment (event, NULL, &rate, &format, &start, &stop,
613 /* we need TIME and a positive rate */
614 if (format != GST_FORMAT_TIME)
615 goto newseg_wrong_format;
618 goto newseg_wrong_rate;
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;
626 dec->need_keyframe = TRUE;
627 dec->granulepos = -1;
628 dec->last_timestamp = -1;
629 ret = gst_pad_push_event (dec->srcpad, event);
633 ret = gst_pad_push_event (dec->srcpad, event);
637 gst_object_unref (dec);
644 GST_DEBUG ("received non TIME newsegment");
649 GST_DEBUG ("negative rates not supported yet");
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)
659 theora_handle_comment_packet (GstTheoraDec * dec, ogg_packet * packet)
661 gchar *encoder = NULL;
665 GST_DEBUG ("parsing comment packet");
667 buf = gst_buffer_new_and_alloc (packet->bytes);
668 memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
671 gst_tag_list_from_vorbiscomment_buffer (buf, (guint8 *) "\201theora", 7,
674 gst_buffer_unref (buf);
677 GST_ERROR_OBJECT (dec, "couldn't decode comments");
678 list = gst_tag_list_new ();
681 gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
682 GST_TAG_ENCODER, encoder, NULL);
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);
690 //gst_element_found_tags_for_pad (GST_ELEMENT (dec), dec->srcpad, 0, list);
691 gst_tag_list_free (list);
697 theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
700 gint par_num, par_den;
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);
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;
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
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);
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));
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;
735 /* no cropping, use the encoded dimensions */
736 dec->width = dec->info.width;
737 dec->height = dec->info.height;
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);
746 theora_decode_init (&dec->state, &dec->info);
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);
757 dec->have_header = TRUE;
763 theora_handle_header_packet (GstTheoraDec * dec, ogg_packet * packet)
767 GST_DEBUG ("parsing header packet");
769 if (theora_decode_header (&dec->info, &dec->comment, packet))
770 goto header_read_error;
772 switch (packet->packet[0]) {
774 res = theora_handle_comment_packet (dec, packet);
777 res = theora_handle_type_packet (dec, packet);
781 g_warning ("unknown theora header packet found");
783 /* nothing special, this is the identification header */
792 GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
793 (NULL), ("couldn't read header packet"));
794 return GST_FLOW_ERROR;
799 theora_dec_push (GstTheoraDec * dec, GstBuffer * buf)
801 GstFlowReturn result;
802 GstClockTime outtime = GST_BUFFER_TIMESTAMP (buf);
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;
813 GST_DEBUG_OBJECT (dec, "first buffer with time %" GST_TIME_FORMAT,
814 GST_TIME_ARGS (outtime));
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);
821 time = outtime - ((size * GST_SECOND * dec->info.fps_denominator)
822 / dec->info.fps_numerator);
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);
830 g_list_free (dec->queued);
833 result = gst_pad_push (dec->srcpad, buf);
840 theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet,
841 GstClockTime outtime)
843 /* normal data packet */
849 gint stride_y, stride_uv;
851 gint cwidth, cheight;
852 GstFlowReturn result;
854 if (!dec->have_header)
855 goto not_initialized;
857 /* the second most significant bit of the first data byte is cleared
859 keyframe = (packet->packet[0] & 0x40) == 0;
861 dec->need_keyframe = FALSE;
862 } else if (dec->need_keyframe) {
866 if (theora_decode_packetin (&dec->state, packet))
869 if (theora_decode_YUVout (&dec->state, &yuv) < 0)
872 if ((yuv.y_width != dec->info.width) || (yuv.y_height != dec->info.height))
873 goto wrong_dimensions;
877 height = dec->height;
879 cheight = height / 2;
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;
887 out_size = stride_y * height + stride_uv * cheight * 2;
889 /* now copy over the area contained in offset_x,offset_y,
890 * frame_width, frame_height */
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)
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).
905 guchar *dest_y, *src_y;
906 guchar *dest_u, *src_u;
907 guchar *dest_v, *src_v;
909 dest_y = GST_BUFFER_DATA (out);
910 dest_u = dest_y + stride_y * height;
911 dest_v = dest_u + stride_uv * cheight;
913 src_y = yuv.y + dec->offset_x + dec->offset_y * yuv.y_stride;
915 for (i = 0; i < height; i++) {
916 memcpy (dest_y, src_y, width);
919 src_y += yuv.y_stride;
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;
925 for (i = 0; i < cheight; i++) {
926 memcpy (dest_u, src_u, cwidth);
927 memcpy (dest_v, src_v, cwidth);
930 src_u += yuv.uv_stride;
932 src_v += yuv.uv_stride;
936 GST_BUFFER_OFFSET (out) = 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;
944 result = theora_dec_push (dec, out);
951 GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
952 (NULL), ("no header sent yet"));
953 return GST_FLOW_ERROR;
957 GST_WARNING_OBJECT (dec, "dropping frame because we need a keyframe");
962 GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
963 (NULL), ("theora decoder did not read data packet"));
964 return GST_FLOW_ERROR;
968 GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
969 (NULL), ("couldn't read out YUV image"));
970 return GST_FLOW_ERROR;
974 GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
975 (NULL), ("dimensions of image do not match header"));
976 return GST_FLOW_ERROR;
985 theora_dec_chain (GstPad * pad, GstBuffer * buf)
989 GstFlowReturn result = GST_FLOW_OK;
991 dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
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;
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;
1011 dec->last_timestamp = -1;
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));
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");
1023 result = theora_handle_header_packet (dec, &packet);
1025 result = theora_handle_data_packet (dec, &packet, dec->last_timestamp);
1029 _inc_granulepos (dec);
1031 gst_object_unref (dec);
1033 gst_buffer_unref (buf);
1038 static GstStateChangeReturn
1039 theora_dec_change_state (GstElement * element, GstStateChange transition)
1041 GstTheoraDec *dec = GST_THEORA_DEC (element);
1042 GstStateChangeReturn ret;
1045 switch (transition) {
1046 case GST_STATE_CHANGE_NULL_TO_READY:
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;
1056 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1062 ret = parent_class->change_state (element, transition);
1064 switch (transition) {
1065 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
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;
1074 case GST_STATE_CHANGE_READY_TO_NULL:
1084 theora_dec_set_property (GObject * object, guint prop_id,
1085 const GValue * value, GParamSpec * pspec)
1087 GstTheoraDec *dec = GST_THEORA_DEC (object);
1091 dec->crop = g_value_get_boolean (value);
1094 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1100 theora_dec_get_property (GObject * object, guint prop_id,
1101 GValue * value, GParamSpec * pspec)
1103 GstTheoraDec *dec = GST_THEORA_DEC (object);
1107 g_value_set_boolean (value, dec->crop);
1110 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);