gstreamer/ext/theora/theoradec.c

1549 lines
42 KiB
C
Raw Normal View History

/* GStreamer
* Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* SECTION:element-theoradec
* @see_also: theoraenc, oggdemux
*
* <refsect2>
* <para>
* This element decodes theora streams into raw video
* <ulink url="http://www.theora.org/">Theora</ulink> is a royalty-free
* video codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org
* Foundation</ulink>, based on the VP3 codec.
* </para>
* <para>
* </para>
* <title>Example pipeline</title>
* <programlisting>
* gst-launch -v filesrc location=videotestsrc.ogg ! oggdemux ! theoradec ! xvimagesink
* </programlisting>
* This example pipeline will decode an ogg stream and decodes the theora video. Refer to
* the theoraenc example to create the ogg file.
* </refsect2>
*
* Last reviewed on 2006-03-01 (0.10.4)
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "gsttheoradec.h"
#include <gst/tag/tag.h>
#define GST_CAT_DEFAULT theoradec_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define THEORA_DEF_CROP TRUE
enum
{
ARG_0,
ARG_CROP
};
make GstElementDetails const Original commit message from CVS: * ext/alsa/gstalsamixerelement.c: * ext/alsa/gstalsasrc.c: * ext/cdparanoia/gstcdparanoiasrc.c: * ext/gnomevfs/gstgnomevfssink.c: * ext/gnomevfs/gstgnomevfssrc.c: * ext/ogg/gstoggdemux.c: * ext/ogg/gstoggmux.c: * ext/ogg/gstoggparse.c: * ext/ogg/gstogmparse.c: * ext/pango/gstclockoverlay.c: * ext/pango/gsttextoverlay.c: * ext/pango/gsttextrender.c: * ext/pango/gsttimeoverlay.c: * ext/theora/theoradec.c: * ext/theora/theoraenc.c: * ext/vorbis/vorbisdec.c: * ext/vorbis/vorbisenc.c: * gst-libs/gst/audio/gstaudiofilter.c: * gst-libs/gst/audio/gstaudiofiltertemplate.c: * gst/audioconvert/gstaudioconvert.c: * gst/audiorate/gstaudiorate.c: * gst/audioresample/gstaudioresample.c: * gst/audiotestsrc/gstaudiotestsrc.c: * gst/ffmpegcolorspace/gstffmpegcolorspace.c: * gst/playback/gstdecodebin.c: * gst/playback/gstplaybin.c: * gst/playback/gststreamselector.c: * gst/subparse/gstsubparse.c: * gst/tcp/gstmultifdsink.c: * gst/tcp/gsttcpclientsink.c: * gst/tcp/gsttcpclientsrc.c: * gst/tcp/gsttcpserversink.c: * gst/tcp/gsttcpserversrc.c: * gst/typefind/gsttypefindfunctions.c: (plugin_init): * gst/videorate/gstvideorate.c: * gst/videoscale/gstvideoscale.c: * gst/videotestsrc/gstvideotestsrc.c: * gst/volume/gstvolume.c: * sys/v4l/gstv4ljpegsrc.c: * sys/v4l/gstv4lmjpegsink.c: * sys/v4l/gstv4lmjpegsrc.c: * sys/v4l/gstv4lsrc.c: * sys/ximage/ximagesink.c: * sys/xvimage/xvimagesink.c: * tests/check/libs/cddabasesrc.c: make GstElementDetails const
2006-04-28 19:46:37 +00:00
static const GstElementDetails theora_dec_details =
GST_ELEMENT_DETAILS ("Theora video decoder",
Add docs for adder, use GST_ELEMENT_DETAILS macro, define GstElementDetails at the top Original commit message from CVS: * docs/plugins/Makefile.am: * docs/plugins/gst-plugins-base-plugins-docs.sgml: * docs/plugins/gst-plugins-base-plugins-sections.txt: * ext/cdparanoia/gstcdparanoiasrc.c: * ext/gnomevfs/gstgnomevfssink.c: (gst_gnome_vfs_sink_base_init), (gst_gnome_vfs_sink_class_init): * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_base_init): * ext/ogg/gstoggdemux.c: (gst_ogg_demux_base_init): * ext/ogg/gstoggmux.c: * ext/ogg/gstoggparse.c: (gst_ogg_parse_base_init): * ext/ogg/gstogmparse.c: (gst_ogm_audio_parse_base_init), (gst_ogm_video_parse_base_init), (gst_ogm_text_parse_base_init): * ext/pango/gsttextoverlay.c: * ext/pango/gsttextrender.c: * ext/theora/theoradec.c: * ext/theora/theoraenc.c: * ext/vorbis/vorbisdec.c: * ext/vorbis/vorbisenc.c: * gst-libs/gst/audio/gstaudiofilter.c: (gst_audio_filter_base_init): * gst-libs/gst/audio/gstaudiofiltertemplate.c: (gst_audio_filter_template_base_init): * gst/adder/gstadder.c: (gst_adder_get_type): * gst/adder/gstadder.h: * gst/audioconvert/gstaudioconvert.c: * gst/audiotestsrc/gstaudiotestsrc.c: (gst_audiostestsrc_wave_get_type), (gst_audio_test_src_class_init), (gst_audio_test_src_create): * gst/ffmpegcolorspace/gstffmpegcolorspace.c: * gst/playback/gstdecodebin.c: * gst/playback/gstplaybin.c: * gst/playback/gststreamselector.c: (gst_stream_selector_base_init): * gst/subparse/gstsubparse.c: (gst_sub_parse_base_init): * gst/volume/gstvolume.c: * sys/v4l/gstv4lmjpegsink.c: * sys/v4l/gstv4lmjpegsrc.c: * tests/check/libs/cddabasesrc.c: * tests/old/examples/gob/gst-identity2.gob: Add docs for adder, use GST_ELEMENT_DETAILS macro, define GstElementDetails at the top
2006-03-24 10:42:11 +00:00
"Codec/Decoder/Video",
"decode raw theora streams to raw YUV video",
"Benjamin Otte <in7y118@public.uni-hamburg.de>, "
"Wim Taymans <wim@fluendo.com>");
static GstStaticPadTemplate theora_dec_src_factory =
GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw-yuv, "
"format = (fourcc) I420, "
Convert elements to use fractions for their framerate. Original commit message from CVS: * ext/libvisual/visual.c: (gst_visual_src_setcaps), (get_buffer), (gst_visual_chain): * ext/ogg/gstogmparse.c: (gst_ogm_parse_chain): * ext/theora/theoradec.c: (theora_handle_type_packet): * ext/theora/theoraenc.c: (theora_enc_sink_setcaps), (theora_enc_chain): * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): * gst-libs/gst/video/video.c: (gst_video_frame_rate): * gst-libs/gst/video/video.h: * gst/ffmpegcolorspace/avcodec.h: * gst/ffmpegcolorspace/gstffmpegcodecmap.c: (gst_ffmpeg_caps_to_pixfmt): * gst/ffmpegcolorspace/gstffmpegcolorspace.c: (gst_ffmpegcsp_set_caps): * gst/videorate/gstvideorate.c: (gst_videorate_transformcaps), (gst_videorate_setcaps), (gst_videorate_blank_data), (gst_videorate_chain): * gst/videotestsrc/gstvideotestsrc.c: (gst_videotestsrc_src_fixate), (gst_videotestsrc_getcaps), (gst_videotestsrc_parse_caps), (gst_videotestsrc_setcaps), (gst_videotestsrc_event), (gst_videotestsrc_create): * gst/videotestsrc/gstvideotestsrc.h: * sys/ximage/ximagesink.c: (gst_ximagesink_xcontext_get), (gst_ximagesink_setcaps), (gst_ximagesink_change_state), (gst_ximagesink_get_times), (gst_ximagesink_init): * sys/ximage/ximagesink.h: * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support), (gst_xvimagesink_setcaps), (gst_xvimagesink_change_state), (gst_xvimagesink_get_times), (gst_xvimagesink_init): * sys/xvimage/xvimagesink.h: Convert elements to use fractions for their framerate. V4L elements to come later tonight.
2005-11-22 16:08:37 +00:00
"framerate = (fraction) [0/1, MAX], "
"width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
);
static GstStaticPadTemplate theora_dec_sink_factory =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-theora")
);
GST_BOILERPLATE (GstTheoraDec, gst_theora_dec, GstElement, GST_TYPE_ELEMENT);
static void theora_dec_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static void theora_dec_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static gboolean theora_dec_sink_event (GstPad * pad, GstEvent * event);
static GstFlowReturn theora_dec_chain (GstPad * pad, GstBuffer * buffer);
static GstStateChangeReturn theora_dec_change_state (GstElement * element,
GstStateChange transition);
static gboolean theora_dec_src_event (GstPad * pad, GstEvent * event);
static gboolean theora_dec_src_query (GstPad * pad, GstQuery * query);
static gboolean theora_dec_src_convert (GstPad * pad,
GstFormat src_format, gint64 src_value,
GstFormat * dest_format, gint64 * dest_value);
static gboolean theora_dec_sink_convert (GstPad * pad,
GstFormat src_format, gint64 src_value,
GstFormat * dest_format, gint64 * dest_value);
static gboolean theora_dec_sink_query (GstPad * pad, GstQuery * query);
#if 0
static const GstFormat *theora_get_formats (GstPad * pad);
#endif
#if 0
static const GstEventMask *theora_get_event_masks (GstPad * pad);
#endif
static const GstQueryType *theora_get_query_types (GstPad * pad);
static void
gst_theora_dec_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&theora_dec_src_factory));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&theora_dec_sink_factory));
gst_element_class_set_details (element_class, &theora_dec_details);
}
static void
gst_theora_dec_class_init (GstTheoraDecClass * klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
gobject_class->set_property = theora_dec_set_property;
gobject_class->get_property = theora_dec_get_property;
g_object_class_install_property (gobject_class, ARG_CROP,
g_param_spec_boolean ("crop", "Crop",
"Crop the image to the visible region", THEORA_DEF_CROP,
Use G_PARAM_STATIC_STRINGS everywhere for GParamSpecs that use static strings (i.e. all). This gives us less memory u... Original commit message from CVS: * configure.ac: * ext/alsa/gstalsamixerelement.c: (gst_alsa_mixer_element_class_init): * ext/alsa/gstalsasink.c: (gst_alsasink_class_init): * ext/alsa/gstalsasrc.c: (gst_alsasrc_class_init): * ext/cdparanoia/gstcdparanoiasrc.c: (gst_cd_paranoia_src_class_init): * ext/gio/gstgiosink.c: (gst_gio_sink_class_init): * ext/gio/gstgiosrc.c: (gst_gio_src_class_init): * ext/gio/gstgiostreamsink.c: (gst_gio_stream_sink_class_init): * ext/gio/gstgiostreamsrc.c: (gst_gio_stream_src_class_init): * ext/gnomevfs/gstgnomevfssink.c: (gst_gnome_vfs_sink_class_init): * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_class_init): * ext/ogg/gstoggmux.c: (gst_ogg_mux_class_init): * ext/pango/gsttextoverlay.c: (gst_text_overlay_class_init): * ext/pango/gsttextrender.c: (gst_text_render_class_init): * ext/theora/theoradec.c: (gst_theora_dec_class_init): * ext/theora/theoraenc.c: (gst_theora_enc_class_init): * ext/theora/theoraparse.c: (gst_theora_parse_class_init): * ext/vorbis/vorbisenc.c: (gst_vorbis_enc_class_init): * gst-libs/gst/audio/gstaudiofiltertemplate.c: (gst_audio_filter_template_class_init): * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_class_init): * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_class_init): * gst-libs/gst/cdda/gstcddabasesrc.c: (gst_cdda_base_src_class_init): * gst-libs/gst/interfaces/mixertrack.c: (gst_mixer_track_class_init): * gst-libs/gst/rtp/gstbasertpdepayload.c: (gst_base_rtp_depayload_class_init): * gst-libs/gst/rtp/gstbasertppayload.c: (gst_basertppayload_class_init): * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_class_init): * gst/audiorate/gstaudiorate.c: (gst_audio_rate_class_init): * gst/audioresample/gstaudioresample.c: (gst_audioresample_class_init): * gst/audiotestsrc/gstaudiotestsrc.c: (gst_audio_test_src_class_init): * gst/gdp/gstgdppay.c: (gst_gdp_pay_class_init): * gst/playback/gstdecodebin2.c: (gst_decode_bin_class_init): * gst/playback/gstplaybasebin.c: (gst_play_base_bin_class_init), (preroll_unlinked): * gst/playback/gstplaybin.c: (gst_play_bin_class_init): * gst/playback/gstplaybin2.c: (gst_play_bin_class_init): * gst/playback/gstplaysink.c: (gst_play_sink_class_init): * gst/playback/gstqueue2.c: (gst_queue_class_init): * gst/playback/gststreaminfo.c: (gst_stream_info_class_init): * gst/playback/gststreamselector.c: (gst_selector_pad_class_init), (gst_stream_selector_class_init): * gst/playback/gsturidecodebin.c: (gst_uri_decode_bin_class_init): * gst/subparse/gstsubparse.c: (gst_sub_parse_class_init): * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_class_init): * gst/tcp/gsttcpclientsink.c: (gst_tcp_client_sink_class_init): * gst/tcp/gsttcpclientsrc.c: (gst_tcp_client_src_class_init): * gst/tcp/gsttcpserversink.c: (gst_tcp_server_sink_class_init): * gst/tcp/gsttcpserversrc.c: (gst_tcp_server_src_class_init): * gst/videorate/gstvideorate.c: (gst_video_rate_class_init): * gst/videoscale/gstvideoscale.c: (gst_video_scale_class_init): * gst/videotestsrc/gstvideotestsrc.c: (gst_video_test_src_class_init): * gst/volume/gstvolume.c: (gst_volume_class_init): * sys/v4l/gstv4lelement.c: (gst_v4lelement_class_init): * sys/v4l/gstv4lmjpegsink.c: (gst_v4lmjpegsink_class_init): * sys/v4l/gstv4lmjpegsrc.c: (gst_v4lmjpegsrc_class_init): * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_class_init): * sys/ximage/ximagesink.c: (gst_ximagesink_class_init): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_class_init): Use G_PARAM_STATIC_STRINGS everywhere for GParamSpecs that use static strings (i.e. all). This gives us less memory usage, fewer allocations and thus less memory defragmentation. Depend on core CVS for this. Fixes bug #523806.
2008-03-22 15:00:53 +00:00
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gstelement_class->change_state = theora_dec_change_state;
GST_DEBUG_CATEGORY_INIT (theoradec_debug, "theoradec", 0, "Theora decoder");
}
static void
gst_theora_dec_init (GstTheoraDec * dec, GstTheoraDecClass * g_class)
{
dec->sinkpad =
gst_pad_new_from_static_template (&theora_dec_sink_factory, "sink");
gst_pad_set_query_function (dec->sinkpad, theora_dec_sink_query);
gst_pad_set_event_function (dec->sinkpad, theora_dec_sink_event);
gst_pad_set_chain_function (dec->sinkpad, theora_dec_chain);
gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
dec->srcpad =
gst_pad_new_from_static_template (&theora_dec_src_factory, "src");
gst_pad_set_event_function (dec->srcpad, theora_dec_src_event);
gst_pad_set_query_type_function (dec->srcpad, theora_get_query_types);
gst_pad_set_query_function (dec->srcpad, theora_dec_src_query);
gst_pad_use_fixed_caps (dec->srcpad);
gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
dec->crop = THEORA_DEF_CROP;
dec->gather = NULL;
dec->decode = NULL;
dec->queued = NULL;
}
static void
gst_theora_dec_reset (GstTheoraDec * dec)
{
dec->need_keyframe = TRUE;
dec->sent_newsegment = FALSE;
dec->last_timestamp = -1;
dec->granulepos = -1;
dec->discont = TRUE;
dec->frame_nr = -1;
gst_segment_init (&dec->segment, GST_FORMAT_TIME);
GST_OBJECT_LOCK (dec);
dec->proportion = 1.0;
dec->earliest_time = -1;
GST_OBJECT_UNLOCK (dec);
g_list_foreach (dec->queued, (GFunc) gst_mini_object_unref, NULL);
g_list_free (dec->queued);
dec->queued = NULL;
g_list_foreach (dec->gather, (GFunc) gst_mini_object_unref, NULL);
g_list_free (dec->gather);
dec->gather = NULL;
g_list_foreach (dec->decode, (GFunc) gst_mini_object_unref, NULL);
g_list_free (dec->decode);
dec->decode = NULL;
if (dec->tags) {
gst_tag_list_free (dec->tags);
dec->tags = NULL;
}
}
static int
_theora_ilog (unsigned int v)
{
int ret = 0;
while (v) {
ret++;
v >>= 1;
}
return (ret);
}
/* Return the frame number (starting from zero) corresponding to this
* granulepos */
static gint64
_theora_granule_frame (GstTheoraDec * dec, gint64 granulepos)
{
guint ilog;
gint framenum;
if (granulepos == -1)
return -1;
ilog = dec->granule_shift;
/* granulepos is last ilog bits for counting pframes since last iframe and
* bits in front of that for the framenumber of the last iframe. */
framenum = granulepos >> ilog;
framenum += granulepos - (framenum << ilog);
/* This is 0-based for old bitstreams, 1-based for new. Fix up. */
if (!dec->is_old_bitstream)
framenum -= 1;
GST_DEBUG_OBJECT (dec, "framecount=%d, ilog=%u", framenum, ilog);
return framenum;
}
/* Return the frame start time corresponding to this granulepos */
static GstClockTime
_theora_granule_start_time (GstTheoraDec * dec, gint64 granulepos)
{
gint64 framecount;
/* invalid granule results in invalid time */
if (granulepos == -1)
return -1;
/* get framecount */
framecount = _theora_granule_frame (dec, granulepos);
return gst_util_uint64_scale_int (framecount * GST_SECOND,
dec->info.fps_denominator, dec->info.fps_numerator);
}
static gint64
_inc_granulepos (GstTheoraDec * dec, gint64 granulepos)
{
gint framecount;
if (granulepos == -1)
return -1;
framecount = _theora_granule_frame (dec, granulepos);
return (framecount + 1 +
(dec->is_old_bitstream ? 0 : 1)) << dec->granule_shift;
}
#if 0
static const GstFormat *
theora_get_formats (GstPad * pad)
{
static GstFormat src_formats[] = {
GST_FORMAT_DEFAULT, /* frames in this case */
GST_FORMAT_TIME,
GST_FORMAT_BYTES,
0
};
static GstFormat sink_formats[] = {
GST_FORMAT_DEFAULT,
GST_FORMAT_TIME,
0
};
return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats);
}
#endif
#if 0
static const GstEventMask *
theora_get_event_masks (GstPad * pad)
{
static const GstEventMask theora_src_event_masks[] = {
{GST_EVENT_SEEK, GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH},
{0,}
};
return theora_src_event_masks;
}
#endif
static const GstQueryType *
theora_get_query_types (GstPad * pad)
{
static const GstQueryType theora_src_query_types[] = {
GST_QUERY_POSITION,
GST_QUERY_DURATION,
GST_QUERY_CONVERT,
0
};
return theora_src_query_types;
}
static gboolean
theora_dec_src_convert (GstPad * pad,
GstFormat src_format, gint64 src_value,
GstFormat * dest_format, gint64 * dest_value)
{
gboolean res = TRUE;
GstTheoraDec *dec;
guint64 scale = 1;
if (src_format == *dest_format) {
*dest_value = src_value;
return TRUE;
}
dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
/* we need the info part before we can done something */
if (!dec->have_header)
goto no_header;
switch (src_format) {
case GST_FORMAT_BYTES:
switch (*dest_format) {
case GST_FORMAT_DEFAULT:
*dest_value = gst_util_uint64_scale_int (src_value, 2,
dec->info.height * dec->info.width * 3);
break;
case GST_FORMAT_TIME:
/* seems like a rather silly conversion, implement me if you like */
default:
res = FALSE;
}
break;
case GST_FORMAT_TIME:
switch (*dest_format) {
case GST_FORMAT_BYTES:
scale = 3 * (dec->info.width * dec->info.height) / 2;
case GST_FORMAT_DEFAULT:
*dest_value = scale * gst_util_uint64_scale (src_value,
dec->info.fps_numerator, dec->info.fps_denominator * GST_SECOND);
break;
default:
res = FALSE;
}
break;
case GST_FORMAT_DEFAULT:
switch (*dest_format) {
case GST_FORMAT_TIME:
*dest_value = gst_util_uint64_scale (src_value,
GST_SECOND * dec->info.fps_denominator, dec->info.fps_numerator);
break;
case GST_FORMAT_BYTES:
*dest_value = gst_util_uint64_scale_int (src_value,
3 * dec->info.width * dec->info.height, 2);
break;
default:
res = FALSE;
}
break;
default:
res = FALSE;
}
done:
gst_object_unref (dec);
return res;
/* ERRORS */
no_header:
{
GST_DEBUG_OBJECT (dec, "no header yet, cannot convert");
res = FALSE;
goto done;
}
}
static gboolean
theora_dec_sink_convert (GstPad * pad,
GstFormat src_format, gint64 src_value,
GstFormat * dest_format, gint64 * dest_value)
{
gboolean res = TRUE;
GstTheoraDec *dec;
if (src_format == *dest_format) {
*dest_value = src_value;
return TRUE;
}
dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
/* we need the info part before we can done something */
if (!dec->have_header)
goto no_header;
switch (src_format) {
case GST_FORMAT_DEFAULT:
switch (*dest_format) {
case GST_FORMAT_TIME:
*dest_value = _theora_granule_start_time (dec, src_value);
break;
default:
res = FALSE;
}
break;
case GST_FORMAT_TIME:
switch (*dest_format) {
case GST_FORMAT_DEFAULT:
{
guint rest;
/* framecount */
*dest_value = gst_util_uint64_scale (src_value,
dec->info.fps_numerator, GST_SECOND * dec->info.fps_denominator);
/* funny way of calculating granulepos in theora */
rest = *dest_value / dec->info.keyframe_frequency_force;
*dest_value -= rest;
*dest_value <<= dec->granule_shift;
*dest_value += rest;
break;
}
default:
res = FALSE;
break;
}
break;
default:
res = FALSE;
}
done:
gst_object_unref (dec);
return res;
/* ERRORS */
no_header:
{
GST_DEBUG_OBJECT (dec, "no header yet, cannot convert");
res = FALSE;
goto done;
}
}
static gboolean
theora_dec_src_query (GstPad * pad, GstQuery * query)
{
GstTheoraDec *dec;
gboolean res = FALSE;
dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_POSITION:
{
gint64 granulepos, value;
GstFormat my_format, format;
gint64 time;
/* we can convert a granule position to everything */
granulepos = dec->granulepos;
GST_LOG_OBJECT (dec,
"query %p: we have current granule: %lld", query, granulepos);
/* parse format */
gst_query_parse_position (query, &format, NULL);
/* and convert to the final format in two steps with time as the
* intermediate step */
my_format = GST_FORMAT_TIME;
if (!(res =
theora_dec_sink_convert (dec->sinkpad, GST_FORMAT_DEFAULT,
granulepos, &my_format, &time)))
goto error;
time = gst_segment_to_stream_time (&dec->segment, GST_FORMAT_TIME, time);
GST_LOG_OBJECT (dec,
"query %p: our time: %" GST_TIME_FORMAT, query, GST_TIME_ARGS (time));
if (!(res =
theora_dec_src_convert (pad, my_format, time, &format, &value)))
goto error;
gst_query_set_position (query, format, value);
GST_LOG_OBJECT (dec,
"query %p: we return %lld (format %u)", query, value, format);
break;
}
case GST_QUERY_DURATION:
{
GstPad *peer;
if (!(peer = gst_pad_get_peer (dec->sinkpad)))
goto error;
/* forward to peer for total */
res = gst_pad_query (peer, query);
gst_object_unref (peer);
if (!res)
goto error;
break;
}
case GST_QUERY_CONVERT:
{
GstFormat src_fmt, dest_fmt;
gint64 src_val, dest_val;
gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
if (!(res =
theora_dec_src_convert (pad, src_fmt, src_val, &dest_fmt,
&dest_val)))
goto error;
gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
break;
}
default:
res = gst_pad_query_default (pad, query);
break;
}
done:
gst_object_unref (dec);
return res;
/* ERRORS */
error:
{
GST_DEBUG_OBJECT (dec, "query failed");
goto done;
}
}
static gboolean
theora_dec_sink_query (GstPad * pad, GstQuery * query)
{
gboolean res = FALSE;
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_CONVERT:
{
GstFormat src_fmt, dest_fmt;
gint64 src_val, dest_val;
gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
if (!(res =
theora_dec_sink_convert (pad, src_fmt, src_val, &dest_fmt,
&dest_val)))
goto error;
gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
break;
}
default:
res = gst_pad_query_default (pad, query);
break;
}
error:
return res;
}
static gboolean
theora_dec_src_event (GstPad * pad, GstEvent * event)
{
gboolean res = TRUE;
GstTheoraDec *dec;
dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_SEEK:
{
examples/seeking/seek.c: Update seek example. Original commit message from CVS: * examples/seeking/seek.c: (setup_dynamic_link), (make_dv_pipeline), (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (do_seek): Update seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_event), (gst_ogg_pad_typefind), (gst_ogg_demux_chain_elem_pad), (gst_ogg_demux_queue_data), (gst_ogg_demux_chain_peer), (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_handle_event), (gst_ogg_demux_deactivate_current_chain), (gst_ogg_demux_activate_chain), (gst_ogg_demux_perform_seek), (gst_ogg_demux_collect_chain_info), (gst_ogg_demux_collect_info), (gst_ogg_demux_chain), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): * ext/ogg/gstoggmux.c: (gst_ogg_mux_collected): * ext/theora/theoradec.c: (theora_dec_src_event), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_dec_push), (theora_dec_chain): * ext/vorbis/Makefile.am: * ext/vorbis/vorbisdec.c: (vorbis_dec_src_event), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet): * ext/vorbis/vorbisenc.c: (gst_vorbisenc_sink_event), (gst_vorbisenc_chain): * gst/playback/gststreaminfo.c: (cb_probe): * gst/subparse/gstsubparse.c: (gst_subparse_src_event): * gst/videorate/gstvideorate.c: (gst_videorate_event): * gst/videoscale/gstvideoscale.c: (gst_videoscale_handle_src_event): * gst/videotestsrc/gstvideotestsrc.c: (gst_videotestsrc_event): * sys/ximage/ximagesink.c: (gst_ximagesink_show_frame), (gst_ximagesink_navigation_send_event): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_navigation_send_event): Various event updates and cleanups
2005-07-27 18:34:29 +00:00
GstFormat format, tformat;
gdouble rate;
GstEvent *real_seek;
examples/seeking/seek.c: Update seek example. Original commit message from CVS: * examples/seeking/seek.c: (setup_dynamic_link), (make_dv_pipeline), (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (do_seek): Update seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_event), (gst_ogg_pad_typefind), (gst_ogg_demux_chain_elem_pad), (gst_ogg_demux_queue_data), (gst_ogg_demux_chain_peer), (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_handle_event), (gst_ogg_demux_deactivate_current_chain), (gst_ogg_demux_activate_chain), (gst_ogg_demux_perform_seek), (gst_ogg_demux_collect_chain_info), (gst_ogg_demux_collect_info), (gst_ogg_demux_chain), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): * ext/ogg/gstoggmux.c: (gst_ogg_mux_collected): * ext/theora/theoradec.c: (theora_dec_src_event), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_dec_push), (theora_dec_chain): * ext/vorbis/Makefile.am: * ext/vorbis/vorbisdec.c: (vorbis_dec_src_event), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet): * ext/vorbis/vorbisenc.c: (gst_vorbisenc_sink_event), (gst_vorbisenc_chain): * gst/playback/gststreaminfo.c: (cb_probe): * gst/subparse/gstsubparse.c: (gst_subparse_src_event): * gst/videorate/gstvideorate.c: (gst_videorate_event): * gst/videoscale/gstvideoscale.c: (gst_videoscale_handle_src_event): * gst/videotestsrc/gstvideotestsrc.c: (gst_videotestsrc_event): * sys/ximage/ximagesink.c: (gst_ximagesink_show_frame), (gst_ximagesink_navigation_send_event): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_navigation_send_event): Various event updates and cleanups
2005-07-27 18:34:29 +00:00
GstSeekFlags flags;
GstSeekType cur_type, stop_type;
gint64 cur, stop;
gint64 tcur, tstop;
gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
&stop_type, &stop);
gst_event_unref (event);
/* we have to ask our peer to seek to time here as we know
* nothing about how to generate a granulepos from the src
* formats or anything.
*
* First bring the requested format to time
*/
examples/seeking/seek.c: Update seek example. Original commit message from CVS: * examples/seeking/seek.c: (setup_dynamic_link), (make_dv_pipeline), (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (do_seek): Update seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_event), (gst_ogg_pad_typefind), (gst_ogg_demux_chain_elem_pad), (gst_ogg_demux_queue_data), (gst_ogg_demux_chain_peer), (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_handle_event), (gst_ogg_demux_deactivate_current_chain), (gst_ogg_demux_activate_chain), (gst_ogg_demux_perform_seek), (gst_ogg_demux_collect_chain_info), (gst_ogg_demux_collect_info), (gst_ogg_demux_chain), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): * ext/ogg/gstoggmux.c: (gst_ogg_mux_collected): * ext/theora/theoradec.c: (theora_dec_src_event), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_dec_push), (theora_dec_chain): * ext/vorbis/Makefile.am: * ext/vorbis/vorbisdec.c: (vorbis_dec_src_event), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet): * ext/vorbis/vorbisenc.c: (gst_vorbisenc_sink_event), (gst_vorbisenc_chain): * gst/playback/gststreaminfo.c: (cb_probe): * gst/subparse/gstsubparse.c: (gst_subparse_src_event): * gst/videorate/gstvideorate.c: (gst_videorate_event): * gst/videoscale/gstvideoscale.c: (gst_videoscale_handle_src_event): * gst/videotestsrc/gstvideotestsrc.c: (gst_videotestsrc_event): * sys/ximage/ximagesink.c: (gst_ximagesink_show_frame), (gst_ximagesink_navigation_send_event): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_navigation_send_event): Various event updates and cleanups
2005-07-27 18:34:29 +00:00
tformat = GST_FORMAT_TIME;
if (!(res = theora_dec_src_convert (pad, format, cur, &tformat, &tcur)))
goto convert_error;
examples/seeking/seek.c: Update seek example. Original commit message from CVS: * examples/seeking/seek.c: (setup_dynamic_link), (make_dv_pipeline), (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (do_seek): Update seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_event), (gst_ogg_pad_typefind), (gst_ogg_demux_chain_elem_pad), (gst_ogg_demux_queue_data), (gst_ogg_demux_chain_peer), (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_handle_event), (gst_ogg_demux_deactivate_current_chain), (gst_ogg_demux_activate_chain), (gst_ogg_demux_perform_seek), (gst_ogg_demux_collect_chain_info), (gst_ogg_demux_collect_info), (gst_ogg_demux_chain), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): * ext/ogg/gstoggmux.c: (gst_ogg_mux_collected): * ext/theora/theoradec.c: (theora_dec_src_event), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_dec_push), (theora_dec_chain): * ext/vorbis/Makefile.am: * ext/vorbis/vorbisdec.c: (vorbis_dec_src_event), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet): * ext/vorbis/vorbisenc.c: (gst_vorbisenc_sink_event), (gst_vorbisenc_chain): * gst/playback/gststreaminfo.c: (cb_probe): * gst/subparse/gstsubparse.c: (gst_subparse_src_event): * gst/videorate/gstvideorate.c: (gst_videorate_event): * gst/videoscale/gstvideoscale.c: (gst_videoscale_handle_src_event): * gst/videotestsrc/gstvideotestsrc.c: (gst_videotestsrc_event): * sys/ximage/ximagesink.c: (gst_ximagesink_show_frame), (gst_ximagesink_navigation_send_event): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_navigation_send_event): Various event updates and cleanups
2005-07-27 18:34:29 +00:00
if (!(res = theora_dec_src_convert (pad, format, stop, &tformat, &tstop)))
goto convert_error;
/* then seek with time on the peer */
examples/seeking/seek.c: Update seek example. Original commit message from CVS: * examples/seeking/seek.c: (setup_dynamic_link), (make_dv_pipeline), (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (do_seek): Update seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_event), (gst_ogg_pad_typefind), (gst_ogg_demux_chain_elem_pad), (gst_ogg_demux_queue_data), (gst_ogg_demux_chain_peer), (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_handle_event), (gst_ogg_demux_deactivate_current_chain), (gst_ogg_demux_activate_chain), (gst_ogg_demux_perform_seek), (gst_ogg_demux_collect_chain_info), (gst_ogg_demux_collect_info), (gst_ogg_demux_chain), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): * ext/ogg/gstoggmux.c: (gst_ogg_mux_collected): * ext/theora/theoradec.c: (theora_dec_src_event), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_dec_push), (theora_dec_chain): * ext/vorbis/Makefile.am: * ext/vorbis/vorbisdec.c: (vorbis_dec_src_event), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet): * ext/vorbis/vorbisenc.c: (gst_vorbisenc_sink_event), (gst_vorbisenc_chain): * gst/playback/gststreaminfo.c: (cb_probe): * gst/subparse/gstsubparse.c: (gst_subparse_src_event): * gst/videorate/gstvideorate.c: (gst_videorate_event): * gst/videoscale/gstvideoscale.c: (gst_videoscale_handle_src_event): * gst/videotestsrc/gstvideotestsrc.c: (gst_videotestsrc_event): * sys/ximage/ximagesink.c: (gst_ximagesink_show_frame), (gst_ximagesink_navigation_send_event): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_navigation_send_event): Various event updates and cleanups
2005-07-27 18:34:29 +00:00
real_seek = gst_event_new_seek (rate, GST_FORMAT_TIME,
flags, cur_type, tcur, stop_type, tstop);
examples/seeking/seek.c: Update seek example. Original commit message from CVS: * examples/seeking/seek.c: (setup_dynamic_link), (make_dv_pipeline), (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (do_seek): Update seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_event), (gst_ogg_pad_typefind), (gst_ogg_demux_chain_elem_pad), (gst_ogg_demux_queue_data), (gst_ogg_demux_chain_peer), (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_handle_event), (gst_ogg_demux_deactivate_current_chain), (gst_ogg_demux_activate_chain), (gst_ogg_demux_perform_seek), (gst_ogg_demux_collect_chain_info), (gst_ogg_demux_collect_info), (gst_ogg_demux_chain), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): * ext/ogg/gstoggmux.c: (gst_ogg_mux_collected): * ext/theora/theoradec.c: (theora_dec_src_event), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_dec_push), (theora_dec_chain): * ext/vorbis/Makefile.am: * ext/vorbis/vorbisdec.c: (vorbis_dec_src_event), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet): * ext/vorbis/vorbisenc.c: (gst_vorbisenc_sink_event), (gst_vorbisenc_chain): * gst/playback/gststreaminfo.c: (cb_probe): * gst/subparse/gstsubparse.c: (gst_subparse_src_event): * gst/videorate/gstvideorate.c: (gst_videorate_event): * gst/videoscale/gstvideoscale.c: (gst_videoscale_handle_src_event): * gst/videotestsrc/gstvideotestsrc.c: (gst_videotestsrc_event): * sys/ximage/ximagesink.c: (gst_ximagesink_show_frame), (gst_ximagesink_navigation_send_event): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_navigation_send_event): Various event updates and cleanups
2005-07-27 18:34:29 +00:00
res = gst_pad_push_event (dec->sinkpad, real_seek);
break;
}
case GST_EVENT_QOS:
{
gdouble proportion;
GstClockTimeDiff diff;
GstClockTime timestamp;
gst_event_parse_qos (event, &proportion, &diff, &timestamp);
/* we cannot randomly skip frame decoding since we don't have
* B frames. we can however use the timestamp and diff to not
* push late frames. This would at least save us the time to
* crop/memcpy the data. */
GST_OBJECT_LOCK (dec);
dec->proportion = proportion;
dec->earliest_time = timestamp + diff;
GST_OBJECT_UNLOCK (dec);
GST_DEBUG_OBJECT (dec, "got QoS %" GST_TIME_FORMAT ", %" G_GINT64_FORMAT,
GST_TIME_ARGS (timestamp), diff);
res = gst_pad_push_event (dec->sinkpad, event);
break;
}
default:
res = gst_pad_push_event (dec->sinkpad, event);
break;
}
done:
gst_object_unref (dec);
return res;
/* ERRORS */
convert_error:
{
GST_DEBUG_OBJECT (dec, "could not convert format");
goto done;
}
}
static gboolean
theora_dec_sink_event (GstPad * pad, GstEvent * event)
{
gboolean ret = FALSE;
GstTheoraDec *dec;
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
GST_LOG_OBJECT (dec, "handling event");
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_START:
ret = gst_pad_push_event (dec->srcpad, event);
break;
case GST_EVENT_FLUSH_STOP:
gst_theora_dec_reset (dec);
ret = gst_pad_push_event (dec->srcpad, event);
break;
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
case GST_EVENT_EOS:
ret = gst_pad_push_event (dec->srcpad, event);
break;
examples/seeking/seek.c: Update seek example. Original commit message from CVS: * examples/seeking/seek.c: (setup_dynamic_link), (make_dv_pipeline), (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (do_seek): Update seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_event), (gst_ogg_pad_typefind), (gst_ogg_demux_chain_elem_pad), (gst_ogg_demux_queue_data), (gst_ogg_demux_chain_peer), (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_handle_event), (gst_ogg_demux_deactivate_current_chain), (gst_ogg_demux_activate_chain), (gst_ogg_demux_perform_seek), (gst_ogg_demux_collect_chain_info), (gst_ogg_demux_collect_info), (gst_ogg_demux_chain), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): * ext/ogg/gstoggmux.c: (gst_ogg_mux_collected): * ext/theora/theoradec.c: (theora_dec_src_event), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_dec_push), (theora_dec_chain): * ext/vorbis/Makefile.am: * ext/vorbis/vorbisdec.c: (vorbis_dec_src_event), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet): * ext/vorbis/vorbisenc.c: (gst_vorbisenc_sink_event), (gst_vorbisenc_chain): * gst/playback/gststreaminfo.c: (cb_probe): * gst/subparse/gstsubparse.c: (gst_subparse_src_event): * gst/videorate/gstvideorate.c: (gst_videorate_event): * gst/videoscale/gstvideoscale.c: (gst_videoscale_handle_src_event): * gst/videotestsrc/gstvideotestsrc.c: (gst_videotestsrc_event): * sys/ximage/ximagesink.c: (gst_ximagesink_show_frame), (gst_ximagesink_navigation_send_event): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_navigation_send_event): Various event updates and cleanups
2005-07-27 18:34:29 +00:00
case GST_EVENT_NEWSEGMENT:
{
gboolean update;
GstFormat format;
gdouble rate, arate;
gint64 start, stop, time;
gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
&start, &stop, &time);
/* we need TIME format */
if (format != GST_FORMAT_TIME)
goto newseg_wrong_format;
/* now configure the values */
gst_segment_set_newsegment_full (&dec->segment, update,
rate, arate, format, start, stop, time);
/* We don't forward this unless/until the decoder is initialised */
if (dec->have_header) {
ret = gst_pad_push_event (dec->srcpad, event);
dec->sent_newsegment = TRUE;
} else {
gst_event_unref (event);
ret = TRUE;
}
break;
}
default:
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
ret = gst_pad_push_event (dec->srcpad, event);
break;
}
done:
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
gst_object_unref (dec);
return ret;
/* ERRORS */
newseg_wrong_format:
{
GST_DEBUG_OBJECT (dec, "received non TIME newsegment");
gst_event_unref (event);
goto done;
}
}
static GstFlowReturn
theora_handle_comment_packet (GstTheoraDec * dec, ogg_packet * packet)
{
gchar *encoder = NULL;
GstBuffer *buf;
GstTagList *list;
GST_DEBUG_OBJECT (dec, "parsing comment packet");
buf = gst_buffer_new_and_alloc (packet->bytes);
memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
ext/: ext/ogg/gstoggdemux.c (gst_ogg_demux_perform_seek) (gst_ogg_demux_read_chain, gst_ogg_demux_read_end_chain) ext... Original commit message from CVS: 2005-05-09 Andy Wingo <wingo@pobox.com> * ext/alsa/gstalsasink.h: * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnomevfssrc_get_icy_metadata): * ext/ogg/gstoggdemux.c (gst_ogg_demux_perform_seek) (gst_ogg_demux_read_chain, gst_ogg_demux_read_end_chain) * ext/theora/theoradec.c (theora_dec_src_query) (theora_dec_src_event, theora_dec_sink_event) (theora_handle_comment_packet, theora_handle_data_packet): * ext/theora/theoraenc.c (theora_enc_chain): * ext/vorbis/vorbisdec.c (vorbis_dec_src_event) (vorbis_dec_sink_event, vorbis_handle_comment_packet): * gst/audioconvert/gstaudioconvert.c (gst_audio_convert_getcaps): * gst/typefind/gsttypefindfunctions.c (mp3_type_find) (qt_type_find): * gst/videotestsrc/videotestsrc.c (paint_setup_I420) (paint_setup_YV12, paint_setup_YUY2, paint_setup_UYVY) (paint_setup_YVYU, paint_setup_IYU2, paint_setup_Y41B) (paint_setup_Y42B, paint_setup_Y800, paint_setup_IMC1) (paint_setup_IMC2, paint_setup_IMC3, paint_setup_IMC4) (paint_setup_YVU9, paint_setup_YUV9, paint_setup_xRGB8888) (paint_setup_xBGR8888, paint_setup_RGBx8888) (paint_setup_BGRx8888, paint_setup_RGB888, paint_setup_BGR888) (paint_setup_RGB565, paint_setup_xRGB1555): * gst/videotestsrc/videotestsrc.h: * sys/ximage/ximagesink.c (gst_ximagesink_buffer_alloc): * sys/xvimage/xvimagesink.c (gst_xvimagesink_get_xv_support) (gst_xvimagesink_setcaps, gst_xvimagesink_buffer_alloc): GCC4 fixes. * ext/ogg/gstoggdemux.c (gst_ogg_demux_find_chains): Use the new gst_pad_query_position. Fixes oggdemux.
2005-05-09 07:03:13 +00:00
list =
gst_tag_list_from_vorbiscomment_buffer (buf, (guint8 *) "\201theora", 7,
&encoder);
gst_buffer_unref (buf);
if (!list) {
GST_ERROR_OBJECT (dec, "couldn't decode comments");
list = gst_tag_list_new ();
}
if (encoder) {
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
GST_TAG_ENCODER, encoder, NULL);
g_free (encoder);
}
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
GST_TAG_ENCODER_VERSION, dec->info.version_major,
GST_TAG_VIDEO_CODEC, "Theora", NULL);
if (dec->info.target_bitrate > 0) {
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
GST_TAG_BITRATE, dec->info.target_bitrate,
GST_TAG_NOMINAL_BITRATE, dec->info.target_bitrate, NULL);
}
dec->tags = list;
return GST_FLOW_OK;
}
static GstFlowReturn
theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
{
GstCaps *caps;
gint par_num, par_den;
GstFlowReturn ret = GST_FLOW_OK;
gboolean eret;
GstEvent *event;
guint32 bitstream_version;
GST_DEBUG_OBJECT (dec, "fps %d/%d, PAR %d/%d",
dec->info.fps_numerator, dec->info.fps_denominator,
dec->info.aspect_numerator, dec->info.aspect_denominator);
/* calculate par
* the info.aspect_* values reflect PAR;
* 0:0 is allowed and can be interpreted as 1:1, so correct for it.
* x:0 for other x isn't technically allowed, but it's seen in the wild and
* is reasonable to treat the same.
*/
par_num = dec->info.aspect_numerator;
par_den = dec->info.aspect_denominator;
if (par_den == 0) {
par_num = par_den = 1;
}
/* theora has:
*
* width/height : dimension of the encoded frame
* frame_width/frame_height : dimension of the visible part
* offset_x/offset_y : offset in encoded frame where visible part starts
*/
GST_DEBUG_OBJECT (dec, "dimension %dx%d, PAR %d/%d", dec->info.width,
dec->info.height, par_num, par_den);
GST_DEBUG_OBJECT (dec, "frame dimension %dx%d, offset %d:%d",
dec->info.frame_width, dec->info.frame_height,
dec->info.offset_x, dec->info.offset_y);
if (dec->info.pixelformat != OC_PF_420) {
GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
(NULL), ("pixel formats other than 4:2:0 not yet supported"));
return GST_FLOW_ERROR;
}
if (dec->crop) {
/* add black borders to make width/height/offsets even. we need this because
* we cannot express an offset to the peer plugin. */
dec->width =
GST_ROUND_UP_2 (dec->info.frame_width + (dec->info.offset_x & 1));
dec->height =
GST_ROUND_UP_2 (dec->info.frame_height + (dec->info.offset_y & 1));
dec->offset_x = dec->info.offset_x & ~1;
dec->offset_y = dec->info.offset_y & ~1;
} else {
/* no cropping, use the encoded dimensions */
dec->width = dec->info.width;
dec->height = dec->info.height;
dec->offset_x = 0;
dec->offset_y = 0;
}
dec->granule_shift = _theora_ilog (dec->info.keyframe_frequency_force - 1);
/* With libtheora-1.0beta1 the granulepos scheme was changed:
* where earlier the granulepos refered to the index/beginning
* of a frame, it now refers to the end, which matches the use
* in vorbis/speex. We check the bitstream version from the header so
* we know which way to interpret the incoming granuepos
*/
bitstream_version = (dec->info.version_major << 16) |
(dec->info.version_minor << 8) | dec->info.version_subminor;
dec->is_old_bitstream = (bitstream_version <= 0x00030200);
GST_DEBUG_OBJECT (dec, "after fixup frame dimension %dx%d, offset %d:%d",
dec->width, dec->height, dec->offset_x, dec->offset_y);
/* done */
theora_decode_init (&dec->state, &dec->info);
caps = gst_caps_new_simple ("video/x-raw-yuv",
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
Convert elements to use fractions for their framerate. Original commit message from CVS: * ext/libvisual/visual.c: (gst_visual_src_setcaps), (get_buffer), (gst_visual_chain): * ext/ogg/gstogmparse.c: (gst_ogm_parse_chain): * ext/theora/theoradec.c: (theora_handle_type_packet): * ext/theora/theoraenc.c: (theora_enc_sink_setcaps), (theora_enc_chain): * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): * gst-libs/gst/video/video.c: (gst_video_frame_rate): * gst-libs/gst/video/video.h: * gst/ffmpegcolorspace/avcodec.h: * gst/ffmpegcolorspace/gstffmpegcodecmap.c: (gst_ffmpeg_caps_to_pixfmt): * gst/ffmpegcolorspace/gstffmpegcolorspace.c: (gst_ffmpegcsp_set_caps): * gst/videorate/gstvideorate.c: (gst_videorate_transformcaps), (gst_videorate_setcaps), (gst_videorate_blank_data), (gst_videorate_chain): * gst/videotestsrc/gstvideotestsrc.c: (gst_videotestsrc_src_fixate), (gst_videotestsrc_getcaps), (gst_videotestsrc_parse_caps), (gst_videotestsrc_setcaps), (gst_videotestsrc_event), (gst_videotestsrc_create): * gst/videotestsrc/gstvideotestsrc.h: * sys/ximage/ximagesink.c: (gst_ximagesink_xcontext_get), (gst_ximagesink_setcaps), (gst_ximagesink_change_state), (gst_ximagesink_get_times), (gst_ximagesink_init): * sys/ximage/ximagesink.h: * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support), (gst_xvimagesink_setcaps), (gst_xvimagesink_change_state), (gst_xvimagesink_get_times), (gst_xvimagesink_init): * sys/xvimage/xvimagesink.h: Convert elements to use fractions for their framerate. V4L elements to come later tonight.
2005-11-22 16:08:37 +00:00
"framerate", GST_TYPE_FRACTION,
dec->info.fps_numerator, dec->info.fps_denominator,
"pixel-aspect-ratio", GST_TYPE_FRACTION, par_num, par_den,
"width", G_TYPE_INT, dec->width, "height", G_TYPE_INT, dec->height, NULL);
gst_pad_set_caps (dec->srcpad, caps);
gst_caps_unref (caps);
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
dec->have_header = TRUE;
if (!dec->sent_newsegment) {
GST_DEBUG_OBJECT (dec, "Sending newsegment event");
event = gst_event_new_new_segment_full (FALSE,
dec->segment.rate, dec->segment.applied_rate,
dec->segment.format, dec->segment.start, dec->segment.stop,
dec->segment.time);
eret = gst_pad_push_event (dec->srcpad, event);
dec->sent_newsegment = TRUE;
}
if (dec->tags) {
gst_element_found_tags_for_pad (GST_ELEMENT_CAST (dec), dec->srcpad,
dec->tags);
dec->tags = NULL;
}
return ret;
}
static GstFlowReturn
theora_handle_header_packet (GstTheoraDec * dec, ogg_packet * packet)
{
GstFlowReturn res;
GST_DEBUG_OBJECT (dec, "parsing header packet");
if (theora_decode_header (&dec->info, &dec->comment, packet))
goto header_read_error;
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
switch (packet->packet[0]) {
case 0x81:
res = theora_handle_comment_packet (dec, packet);
break;
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
case 0x82:
res = theora_handle_type_packet (dec, packet);
break;
default:
/* ignore */
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
g_warning ("unknown theora header packet found");
case 0x80:
/* nothing special, this is the identification header */
res = GST_FLOW_OK;
break;
}
return res;
/* ERRORS */
header_read_error:
{
GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
(NULL), ("couldn't read header packet"));
return GST_FLOW_ERROR;
}
}
/* returns TRUE if buffer is within segment, else FALSE.
* if Buffer is on segment border, it's timestamp and duration will be clipped */
static gboolean
clip_buffer (GstTheoraDec * dec, GstBuffer * buf)
{
gboolean res = TRUE;
GstClockTime in_ts, in_dur, stop;
gint64 cstart, cstop;
in_ts = GST_BUFFER_TIMESTAMP (buf);
in_dur = GST_BUFFER_DURATION (buf);
GST_LOG_OBJECT (dec,
"timestamp:%" GST_TIME_FORMAT " , duration:%" GST_TIME_FORMAT,
GST_TIME_ARGS (in_ts), GST_TIME_ARGS (in_dur));
/* can't clip without TIME segment */
if (dec->segment.format != GST_FORMAT_TIME)
goto beach;
/* we need a start time */
if (!GST_CLOCK_TIME_IS_VALID (in_ts))
goto beach;
/* generate valid stop, if duration unknown, we have unknown stop */
stop =
GST_CLOCK_TIME_IS_VALID (in_dur) ? (in_ts + in_dur) : GST_CLOCK_TIME_NONE;
/* now clip */
if (!(res = gst_segment_clip (&dec->segment, GST_FORMAT_TIME,
in_ts, stop, &cstart, &cstop)))
goto beach;
/* update timestamp and possibly duration if the clipped stop time is
* valid */
GST_BUFFER_TIMESTAMP (buf) = cstart;
if (GST_CLOCK_TIME_IS_VALID (cstop))
GST_BUFFER_DURATION (buf) = cstop - cstart;
beach:
GST_LOG_OBJECT (dec, "%sdropping", (res ? "not " : ""));
return res;
}
/* FIXME, this needs to be moved to the demuxer */
static GstFlowReturn
theora_dec_push_forward (GstTheoraDec * dec, GstBuffer * buf)
{
GstFlowReturn result = GST_FLOW_OK;
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
GstClockTime outtime = GST_BUFFER_TIMESTAMP (buf);
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
if (outtime == GST_CLOCK_TIME_NONE) {
dec->queued = g_list_append (dec->queued, buf);
GST_DEBUG_OBJECT (dec, "queued buffer");
} else {
if (dec->queued) {
gint64 size;
GList *walk;
GST_DEBUG_OBJECT (dec, "first buffer with time %" GST_TIME_FORMAT,
GST_TIME_ARGS (outtime));
size = g_list_length (dec->queued);
for (walk = dec->queued; walk; walk = g_list_next (walk)) {
GstBuffer *buffer = GST_BUFFER (walk->data);
GstClockTime time;
time = outtime - gst_util_uint64_scale_int (size * GST_SECOND,
dec->info.fps_denominator, dec->info.fps_numerator);
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
GST_DEBUG_OBJECT (dec, "patch buffer %lld %lld", size, time);
GST_BUFFER_TIMESTAMP (buffer) = time;
/* Next timestamp - this one is duration */
GST_BUFFER_DURATION (buffer) =
(outtime - gst_util_uint64_scale_int ((size - 1) * GST_SECOND,
dec->info.fps_denominator, dec->info.fps_numerator)) - time;
if (dec->discont) {
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
dec->discont = FALSE;
}
/* ignore the result.. */
if (clip_buffer (dec, buffer))
gst_pad_push (dec->srcpad, buffer);
else
gst_buffer_unref (buffer);
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
size--;
}
g_list_free (dec->queued);
dec->queued = NULL;
}
if (dec->discont) {
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
dec->discont = FALSE;
}
if (clip_buffer (dec, buf))
result = gst_pad_push (dec->srcpad, buf);
else
gst_buffer_unref (buf);
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
}
return result;
}
static GstFlowReturn
theora_dec_push_reverse (GstTheoraDec * dec, GstBuffer * buf)
{
GstFlowReturn result = GST_FLOW_OK;
dec->queued = g_list_prepend (dec->queued, buf);
return result;
}
static GstFlowReturn
theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet,
GstClockTime outtime)
{
/* normal data packet */
yuv_buffer yuv;
GstBuffer *out;
guint i;
gboolean keyframe;
gint out_size;
gint stride_y, stride_uv;
gint width, height;
gint cwidth, cheight;
GstFlowReturn result;
if (G_UNLIKELY (!dec->have_header))
goto not_initialized;
/* the second most significant bit of the first data byte is cleared
* for keyframes. We can only check it if it's not a zero-length packet. */
keyframe = packet->bytes && ((packet->packet[0] & 0x40) == 0);
if (G_UNLIKELY (keyframe)) {
GST_DEBUG_OBJECT (dec, "we have a keyframe");
dec->need_keyframe = FALSE;
} else if (G_UNLIKELY (dec->need_keyframe)) {
goto dropping;
}
GST_DEBUG_OBJECT (dec, "parsing data packet");
/* this does the decoding */
if (G_UNLIKELY (theora_decode_packetin (&dec->state, packet)))
goto decode_error;
if (outtime != -1) {
gboolean need_skip;
GstClockTime qostime;
/* qos needs to be done on running time */
qostime = gst_segment_to_running_time (&dec->segment, GST_FORMAT_TIME,
outtime);
GST_OBJECT_LOCK (dec);
/* check for QoS, don't perform the last steps of getting and
* pushing the buffers that are known to be late. */
/* FIXME, we can also entirely skip decoding if the next valid buffer is
* known to be after a keyframe (using the granule_shift) */
need_skip = dec->earliest_time != -1 && qostime <= dec->earliest_time;
GST_OBJECT_UNLOCK (dec);
if (need_skip)
goto dropping_qos;
}
/* this does postprocessing and set up the decoded frame
* pointers in our yuv variable */
if (G_UNLIKELY (theora_decode_YUVout (&dec->state, &yuv) < 0))
goto no_yuv;
if (G_UNLIKELY ((yuv.y_width != dec->info.width)
|| (yuv.y_height != dec->info.height)))
goto wrong_dimensions;
width = dec->width;
height = dec->height;
cwidth = width / 2;
cheight = height / 2;
/* should get the stride from the caps, for now we round up to the nearest
* multiple of 4 because some element needs it. chroma needs special
* treatment, see videotestsrc. */
stride_y = GST_ROUND_UP_4 (width);
stride_uv = GST_ROUND_UP_8 (width) / 2;
out_size = stride_y * height + stride_uv * cheight * 2;
/* now copy over the area contained in offset_x,offset_y,
* frame_width, frame_height */
result =
gst_pad_alloc_buffer_and_set_caps (dec->srcpad, GST_BUFFER_OFFSET_NONE,
out_size, GST_PAD_CAPS (dec->srcpad), &out);
if (G_UNLIKELY (result != GST_FLOW_OK))
goto no_buffer;
/* copy the visible region to the destination. This is actually pretty
* complicated and gstreamer doesn't support all the needed caps to do this
* correctly. For example, when we have an odd offset, we should only combine
* 1 row/column of luma samples with one chroma sample in colorspace conversion.
* We compensate for this by adding a black border around the image when the
* offset or size is odd (see above).
*/
{
guchar *dest_y, *src_y;
guchar *dest_u, *src_u;
guchar *dest_v, *src_v;
gint offset;
dest_y = GST_BUFFER_DATA (out);
dest_u = dest_y + stride_y * height;
dest_v = dest_u + stride_uv * cheight;
src_y = yuv.y + dec->offset_x + dec->offset_y * yuv.y_stride;
for (i = 0; i < height; i++) {
memcpy (dest_y, src_y, width);
dest_y += stride_y;
src_y += yuv.y_stride;
}
offset = dec->offset_x / 2 + dec->offset_y / 2 * yuv.uv_stride;
src_u = yuv.u + offset;
src_v = yuv.v + offset;
for (i = 0; i < cheight; i++) {
memcpy (dest_u, src_u, cwidth);
memcpy (dest_v, src_v, cwidth);
dest_u += stride_uv;
src_u += yuv.uv_stride;
dest_v += stride_uv;
src_v += yuv.uv_stride;
}
}
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
GST_BUFFER_OFFSET (out) = dec->frame_nr;
if (dec->frame_nr != -1)
dec->frame_nr++;
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
GST_BUFFER_OFFSET_END (out) = dec->frame_nr;
if (dec->granulepos != -1) {
gint64 cf = _theora_granule_frame (dec, dec->granulepos) + 1;
GST_BUFFER_DURATION (out) = gst_util_uint64_scale_int (cf * GST_SECOND,
dec->info.fps_denominator, dec->info.fps_numerator) - outtime;
} else {
GST_BUFFER_DURATION (out) =
gst_util_uint64_scale_int (GST_SECOND, dec->info.fps_denominator,
dec->info.fps_numerator);
}
GST_BUFFER_TIMESTAMP (out) = outtime;
if (dec->segment.rate >= 0.0)
result = theora_dec_push_forward (dec, out);
else
result = theora_dec_push_reverse (dec, out);
return result;
/* ERRORS */
not_initialized:
{
GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
(NULL), ("no header sent yet"));
return GST_FLOW_ERROR;
}
dropping:
{
GST_WARNING_OBJECT (dec, "dropping frame because we need a keyframe");
dec->discont = TRUE;
return GST_FLOW_OK;
}
dropping_qos:
{
if (dec->frame_nr != -1)
dec->frame_nr++;
dec->discont = TRUE;
GST_WARNING_OBJECT (dec, "dropping frame because of QoS");
return GST_FLOW_OK;
}
decode_error:
{
GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
(NULL), ("theora decoder did not decode data packet"));
return GST_FLOW_ERROR;
}
no_yuv:
{
GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
(NULL), ("couldn't read out YUV image"));
return GST_FLOW_ERROR;
}
wrong_dimensions:
{
GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, FORMAT,
(NULL), ("dimensions of image do not match header"));
return GST_FLOW_ERROR;
}
no_buffer:
{
GST_DEBUG_OBJECT (dec, "could not get buffer, reason: %s",
gst_flow_get_name (result));
return result;
}
}
static GstFlowReturn
theora_dec_decode_buffer (GstTheoraDec * dec, GstBuffer * buf)
{
ogg_packet packet;
GstFlowReturn result = GST_FLOW_OK;
/* make ogg_packet out of the buffer */
packet.packet = GST_BUFFER_DATA (buf);
packet.bytes = GST_BUFFER_SIZE (buf);
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
packet.granulepos = GST_BUFFER_OFFSET_END (buf);
packet.packetno = 0; /* we don't really care */
packet.b_o_s = dec->have_header ? 0 : 1;
/* EOS does not matter for the decoder */
packet.e_o_s = 0;
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
if (dec->have_header) {
if (packet.granulepos != -1) {
dec->granulepos = packet.granulepos;
dec->last_timestamp = _theora_granule_start_time (dec, packet.granulepos);
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
} else if (dec->last_timestamp != -1) {
dec->last_timestamp = _theora_granule_start_time (dec, dec->granulepos);
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
}
if (dec->last_timestamp == -1 && GST_BUFFER_TIMESTAMP_IS_VALID (buf))
dec->last_timestamp = GST_BUFFER_TIMESTAMP (buf);
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
} else {
dec->last_timestamp = -1;
}
GST_DEBUG_OBJECT (dec, "header=%02x packetno=%lld, granule pos=%"
G_GINT64_FORMAT ", outtime=%" GST_TIME_FORMAT,
packet.bytes ? packet.packet[0] : -1, packet.packetno, packet.granulepos,
GST_TIME_ARGS (dec->last_timestamp));
/* switch depending on packet type. A zero byte packet is always a data
* packet; we don't dereference it in that case. */
if (packet.bytes && packet.packet[0] & 0x80) {
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
if (dec->have_header) {
GST_WARNING_OBJECT (GST_OBJECT (dec), "Ignoring header");
goto done;
}
result = theora_handle_header_packet (dec, &packet);
} else {
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
result = theora_handle_data_packet (dec, &packet, dec->last_timestamp);
}
done:
/* interpolate granule pos */
dec->granulepos = _inc_granulepos (dec, dec->granulepos);
return result;
}
/* For reverse playback we use a technique that can be used for
* any keyframe based video codec.
*
* Input:
* Buffer decoding order: 7 8 9 4 5 6 1 2 3 EOS
* Keyframe flag: K K
* Discont flag: D D D
*
* - Each Discont marks a discont in the decoding order.
* - The keyframes mark where we can start decoding.
*
* First we prepend incomming buffers to the gather queue, whenever we receive
* a discont, we flush out the gather queue.
*
* The above data will be accumulated in the gather queue like this:
*
* gather queue: 9 8 7
* D
*
* Whe buffer 4 is received (with a DISCONT), we flush the gather queue like
* this:
*
* while (gather)
* take head of queue and prepend to decode queue.
* if we copied a keyframe, decode the decode queue.
*
* After we flushed the gather queue, we add 4 to the (now empty) gather queue.
* We get the following situation:
*
* gather queue: 4
* decode queue: 7 8 9
*
* After we received 5 (Keyframe) and 6:
*
* gather queue: 6 5 4
* decode queue: 7 8 9
*
* When we receive 1 (DISCONT) which triggers a flush of the gather queue:
*
* Copy head of the gather queue (6) to decode queue:
*
* gather queue: 5 4
* decode queue: 6 7 8 9
*
* Copy head of the gather queue (5) to decode queue. This is a keyframe so we
* can start decoding.
*
* gather queue: 4
* decode queue: 5 6 7 8 9
*
* Decode frames in decode queue, store raw decoded data in output queue, we
* can take the head of the decode queue and prepend the decoded result in the
* output queue:
*
* gather queue: 4
* decode queue:
* output queue: 9 8 7 6 5
*
* Now output all the frames in the output queue, picking a frame from the
* head of the queue.
*
* Copy head of the gather queue (4) to decode queue, we flushed the gather
* queue and can now store input buffer in the gather queue:
*
* gather queue: 1
* decode queue: 4
*
* When we receive EOS, the queue looks like:
*
* gather queue: 3 2 1
* decode queue: 4
*
* Fill decode queue, first keyframe we copy is 2:
*
* gather queue: 1
* decode queue: 2 3 4
*
* Decoded output:
*
* gather queue: 1
* decode queue:
* output queue: 4 3 2
*
* Leftover buffer 1 cannot be decoded and must be discarded.
*/
static GstFlowReturn
theora_dec_flush_decode (GstTheoraDec * dec)
{
GstFlowReturn res = GST_FLOW_OK;
while (dec->decode) {
GstBuffer *buf = GST_BUFFER_CAST (dec->decode->data);
GST_DEBUG_OBJECT (dec, "decoding buffer %p, ts %" GST_TIME_FORMAT,
buf, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
/* decode buffer, prepend to output queue */
res = theora_dec_decode_buffer (dec, buf);
/* don't need it anymore now */
gst_buffer_unref (buf);
dec->decode = g_list_delete_link (dec->decode, dec->decode);
}
while (dec->queued) {
GstBuffer *buf = GST_BUFFER_CAST (dec->queued->data);
/* iterate ouput queue an push downstream */
res = gst_pad_push (dec->srcpad, buf);
dec->queued = g_list_delete_link (dec->queued, dec->queued);
}
return res;
}
static GstFlowReturn
theora_dec_chain_reverse (GstTheoraDec * dec, gboolean discont, GstBuffer * buf)
{
GstFlowReturn res = GST_FLOW_OK;
/* if we have a discont, move buffers to the decode list */
if (G_UNLIKELY (discont)) {
GST_DEBUG_OBJECT (dec, "received discont,gathering buffers");
while (dec->gather) {
GstBuffer *gbuf;
guint8 *data;
gbuf = GST_BUFFER_CAST (dec->gather->data);
/* remove from the gather list */
dec->gather = g_list_delete_link (dec->gather, dec->gather);
/* copy to decode queue */
dec->decode = g_list_prepend (dec->decode, gbuf);
/* if we copied a keyframe, flush and decode the decode queue */
data = GST_BUFFER_DATA (gbuf);
if ((data[0] & 0x40) == 0) {
GST_DEBUG_OBJECT (dec, "copied keyframe");
res = theora_dec_flush_decode (dec);
}
}
}
/* add buffer to gather queue */
GST_DEBUG_OBJECT (dec, "gathering buffer %p, size %u", buf,
GST_BUFFER_SIZE (buf));
dec->gather = g_list_prepend (dec->gather, buf);
return res;
}
static GstFlowReturn
theora_dec_chain_forward (GstTheoraDec * dec, gboolean discont,
GstBuffer * buffer)
{
GstFlowReturn result;
result = theora_dec_decode_buffer (dec, buffer);
gst_buffer_unref (buffer);
return result;
}
static GstFlowReturn
theora_dec_chain (GstPad * pad, GstBuffer * buf)
{
GstTheoraDec *dec;
GstFlowReturn res;
gboolean discont;
dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
/* peel of DISCONT flag */
discont = GST_BUFFER_IS_DISCONT (buf);
/* resync on DISCONT */
if (G_UNLIKELY (discont)) {
GST_DEBUG_OBJECT (dec, "received DISCONT buffer");
dec->need_keyframe = TRUE;
dec->last_timestamp = -1;
dec->granulepos = -1;
dec->discont = TRUE;
}
if (dec->segment.rate > 0.0)
res = theora_dec_chain_forward (dec, discont, buf);
else
res = theora_dec_chain_reverse (dec, discont, buf);
gst_object_unref (dec);
return res;
}
static GstStateChangeReturn
theora_dec_change_state (GstElement * element, GstStateChange transition)
{
GstTheoraDec *dec = GST_THEORA_DEC (element);
GstStateChangeReturn ret;
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
theora_info_init (&dec->info);
theora_comment_init (&dec->comment);
GST_DEBUG_OBJECT (dec, "Setting have_header to FALSE in READY->PAUSED");
Updated seek example. Original commit message from CVS: * docs/libs/tmpl/gstringbuffer.sgml: * examples/seeking/seek.c: (make_vorbis_theora_pipeline), (query_rates), (query_positions_elems), (query_positions_pads), (update_scale), (do_seek): Updated seek example. * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), (gst_ogg_pad_submit_page), (gst_ogg_demux_activate_chain), (gst_ogg_demux_find_chains), (gst_ogg_demux_send_event), (gst_ogg_demux_loop): Push out correct discont values. * ext/theora/theoradec.c: (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_getcaps), (theora_dec_sink_event), (theora_handle_type_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Better timestamping. * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain): * ext/vorbis/vorbisdec.h: Better timestamping. * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_get_time), (gst_base_audio_sink_get_times), (gst_base_audio_sink_event), (gst_base_audio_sink_render): Handle syncing on timestamps instead of sample offsets. Make use of DISCONT values as described in design docs. * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_get_time): * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_acquire), (gst_ring_buffer_set_sample), (gst_ring_buffer_commit), (gst_ring_buffer_read): * gst-libs/gst/audio/gstringbuffer.h: * sys/ximage/ximagesink.c: (gst_ximagesink_get_times), (gst_ximagesink_show_frame): * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_times): Correcly convert buffer timestamp to stream time.
2005-07-16 14:47:27 +00:00
dec->have_header = FALSE;
gst_theora_dec_reset (dec);
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
break;
default:
break;
}
ret = parent_class->change_state (element, transition);
switch (transition) {
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
theora_clear (&dec->state);
theora_comment_clear (&dec->comment);
theora_info_clear (&dec->info);
gst_theora_dec_reset (dec);
break;
case GST_STATE_CHANGE_READY_TO_NULL:
break;
default:
break;
}
return ret;
}
static void
theora_dec_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstTheoraDec *dec = GST_THEORA_DEC (object);
switch (prop_id) {
case ARG_CROP:
dec->crop = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
theora_dec_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstTheoraDec *dec = GST_THEORA_DEC (object);
switch (prop_id) {
case ARG_CROP:
g_value_set_boolean (value, dec->crop);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}