gst_plugins_base/ext/theora/theoradec.c
branchRCL_3
changeset 30 7e817e7e631c
parent 0 0e761a78d257
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
       
     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, &timestamp);
       
   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 }