ext/libvisual/visual.c: Small cleanups.
Original commit message from CVS: * ext/libvisual/visual.c: (gst_visual_get_type), (gst_visual_src_setcaps), (gst_vis_src_negotiate), (gst_visual_chain): Small cleanups. * ext/theora/gsttheoradec.h: * ext/theora/theoradec.c: (gst_theora_dec_init), (gst_theora_dec_reset), (_theora_granule_time), (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_query), (theora_dec_src_event), (theora_dec_sink_event), (theora_handle_comment_packet), (theora_handle_header_packet), (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), (theora_dec_change_state): Add simple QoS.
This commit is contained in:
parent
ba3d2db624
commit
808d7edd02
18
ChangeLog
18
ChangeLog
@ -1,3 +1,21 @@
|
|||||||
|
2006-03-09 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
* ext/libvisual/visual.c: (gst_visual_get_type),
|
||||||
|
(gst_visual_src_setcaps), (gst_vis_src_negotiate),
|
||||||
|
(gst_visual_chain):
|
||||||
|
Small cleanups.
|
||||||
|
|
||||||
|
* ext/theora/gsttheoradec.h:
|
||||||
|
* ext/theora/theoradec.c: (gst_theora_dec_init),
|
||||||
|
(gst_theora_dec_reset), (_theora_granule_time),
|
||||||
|
(theora_dec_src_convert), (theora_dec_sink_convert),
|
||||||
|
(theora_dec_src_query), (theora_dec_src_event),
|
||||||
|
(theora_dec_sink_event), (theora_handle_comment_packet),
|
||||||
|
(theora_handle_header_packet), (theora_dec_push),
|
||||||
|
(theora_handle_data_packet), (theora_dec_chain),
|
||||||
|
(theora_dec_change_state):
|
||||||
|
Add simple QoS.
|
||||||
|
|
||||||
2006-03-09 Wim Taymans <wim@fluendo.com>
|
2006-03-09 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* ext/gnomevfs/gstgnomevfssrc.c: (audiocast_init),
|
* ext/gnomevfs/gstgnomevfssrc.c: (audiocast_init),
|
||||||
|
@ -134,7 +134,7 @@ gst_visual_get_type (void)
|
|||||||
{
|
{
|
||||||
static GType type = 0;
|
static GType type = 0;
|
||||||
|
|
||||||
if (!type) {
|
if (G_UNLIKELY (type == 0)) {
|
||||||
static const GTypeInfo info = {
|
static const GTypeInfo info = {
|
||||||
sizeof (GstVisualClass),
|
sizeof (GstVisualClass),
|
||||||
NULL,
|
NULL,
|
||||||
@ -337,8 +337,10 @@ gst_visual_src_setcaps (GstPad * pad, GstCaps * caps)
|
|||||||
gst_object_unref (visual);
|
gst_object_unref (visual);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
error:
|
error:
|
||||||
{
|
{
|
||||||
|
GST_DEBUG_OBJECT (visual, "error parsing caps");
|
||||||
gst_object_unref (visual);
|
gst_object_unref (visual);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -397,6 +399,7 @@ gst_vis_src_negotiate (GstVisual * visual)
|
|||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
no_format:
|
no_format:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (visual, STREAM, FORMAT, (NULL),
|
GST_ELEMENT_ERROR (visual, STREAM, FORMAT, (NULL),
|
||||||
@ -535,7 +538,7 @@ gst_visual_chain (GstPad * pad, GstBuffer * buffer)
|
|||||||
|
|
||||||
if (visual->next_ts != -1) {
|
if (visual->next_ts != -1) {
|
||||||
GST_OBJECT_LOCK (visual);
|
GST_OBJECT_LOCK (visual);
|
||||||
/* check for QoS, don't compute buffers that are known to be latea */
|
/* check for QoS, don't compute buffers that are known to be late */
|
||||||
need_skip = visual->earliest_time != -1 &&
|
need_skip = visual->earliest_time != -1 &&
|
||||||
visual->next_ts <= visual->earliest_time;
|
visual->next_ts <= visual->earliest_time;
|
||||||
GST_OBJECT_UNLOCK (visual);
|
GST_OBJECT_UNLOCK (visual);
|
||||||
|
@ -53,9 +53,11 @@ struct _GstTheoraDec
|
|||||||
{
|
{
|
||||||
GstElement element;
|
GstElement element;
|
||||||
|
|
||||||
|
/* Pads */
|
||||||
GstPad *sinkpad;
|
GstPad *sinkpad;
|
||||||
GstPad *srcpad;
|
GstPad *srcpad;
|
||||||
|
|
||||||
|
/* theora decoder state */
|
||||||
theora_state state;
|
theora_state state;
|
||||||
theora_info info;
|
theora_info info;
|
||||||
theora_comment comment;
|
theora_comment comment;
|
||||||
@ -65,7 +67,7 @@ struct _GstTheoraDec
|
|||||||
guint64 granule_shift;
|
guint64 granule_shift;
|
||||||
|
|
||||||
GstClockTime last_timestamp;
|
GstClockTime last_timestamp;
|
||||||
guint64 frame_nr;
|
guint64 frame_nr; /* unused */
|
||||||
gboolean need_keyframe;
|
gboolean need_keyframe;
|
||||||
gint width, height;
|
gint width, height;
|
||||||
gint offset_x, offset_y;
|
gint offset_x, offset_y;
|
||||||
@ -74,10 +76,12 @@ struct _GstTheoraDec
|
|||||||
|
|
||||||
GList *queued;
|
GList *queued;
|
||||||
|
|
||||||
gdouble segment_rate;
|
/* segment info */ /* with STREAM_LOCK */
|
||||||
gint64 segment_start;
|
GstSegment segment;
|
||||||
gint64 segment_stop;
|
|
||||||
gint64 segment_time;
|
/* QoS stuff */ /* with LOCK*/
|
||||||
|
gboolean proportion;
|
||||||
|
GstClockTime earliest_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstTheoraDecClass
|
struct _GstTheoraDecClass
|
||||||
|
@ -103,7 +103,6 @@ static gboolean theora_dec_sink_convert (GstPad * pad,
|
|||||||
GstFormat src_format, gint64 src_value,
|
GstFormat src_format, gint64 src_value,
|
||||||
GstFormat * dest_format, gint64 * dest_value);
|
GstFormat * dest_format, gint64 * dest_value);
|
||||||
static gboolean theora_dec_sink_query (GstPad * pad, GstQuery * query);
|
static gboolean theora_dec_sink_query (GstPad * pad, GstQuery * query);
|
||||||
static GstCaps *theora_dec_src_getcaps (GstPad * pad);
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static const GstFormat *theora_get_formats (GstPad * pad);
|
static const GstFormat *theora_get_formats (GstPad * pad);
|
||||||
@ -157,10 +156,10 @@ gst_theora_dec_init (GstTheoraDec * dec, GstTheoraDecClass * g_class)
|
|||||||
|
|
||||||
dec->srcpad =
|
dec->srcpad =
|
||||||
gst_pad_new_from_static_template (&theora_dec_src_factory, "src");
|
gst_pad_new_from_static_template (&theora_dec_src_factory, "src");
|
||||||
gst_pad_set_getcaps_function (dec->srcpad, theora_dec_src_getcaps);
|
|
||||||
gst_pad_set_event_function (dec->srcpad, theora_dec_src_event);
|
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_type_function (dec->srcpad, theora_get_query_types);
|
||||||
gst_pad_set_query_function (dec->srcpad, theora_dec_src_query);
|
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);
|
gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
|
||||||
|
|
||||||
@ -168,6 +167,20 @@ gst_theora_dec_init (GstTheoraDec * dec, GstTheoraDecClass * g_class)
|
|||||||
dec->queued = NULL;
|
dec->queued = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_theora_dec_reset (GstTheoraDec * dec)
|
||||||
|
{
|
||||||
|
dec->need_keyframe = TRUE;
|
||||||
|
dec->last_timestamp = -1;
|
||||||
|
dec->granulepos = -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);
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME: copy from libtheora, theora should somehow make this available for seeking */
|
/* FIXME: copy from libtheora, theora should somehow make this available for seeking */
|
||||||
static int
|
static int
|
||||||
_theora_ilog (unsigned int v)
|
_theora_ilog (unsigned int v)
|
||||||
@ -207,9 +220,11 @@ _theora_granule_time (GstTheoraDec * dec, gint64 granulepos)
|
|||||||
{
|
{
|
||||||
gint framecount;
|
gint framecount;
|
||||||
|
|
||||||
|
/* invalid granule results in invalid time */
|
||||||
if (granulepos == -1)
|
if (granulepos == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
/* get framecount */
|
||||||
framecount = _theora_granule_frame (dec, granulepos);
|
framecount = _theora_granule_frame (dec, granulepos);
|
||||||
|
|
||||||
return gst_util_uint64_scale_int (framecount * GST_SECOND,
|
return gst_util_uint64_scale_int (framecount * GST_SECOND,
|
||||||
@ -283,17 +298,17 @@ theora_dec_src_convert (GstPad * pad,
|
|||||||
GstTheoraDec *dec;
|
GstTheoraDec *dec;
|
||||||
guint64 scale = 1;
|
guint64 scale = 1;
|
||||||
|
|
||||||
dec = GST_THEORA_DEC (GST_PAD_PARENT (pad));
|
|
||||||
|
|
||||||
/* we need the info part before we can done something */
|
|
||||||
if (!dec->have_header)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (src_format == *dest_format) {
|
if (src_format == *dest_format) {
|
||||||
*dest_value = src_value;
|
*dest_value = src_value;
|
||||||
return TRUE;
|
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) {
|
switch (src_format) {
|
||||||
case GST_FORMAT_BYTES:
|
case GST_FORMAT_BYTES:
|
||||||
switch (*dest_format) {
|
switch (*dest_format) {
|
||||||
@ -326,8 +341,8 @@ theora_dec_src_convert (GstPad * pad,
|
|||||||
GST_SECOND * dec->info.fps_denominator, dec->info.fps_numerator);
|
GST_SECOND * dec->info.fps_denominator, dec->info.fps_numerator);
|
||||||
break;
|
break;
|
||||||
case GST_FORMAT_BYTES:
|
case GST_FORMAT_BYTES:
|
||||||
*dest_value =
|
*dest_value = gst_util_uint64_scale_int (src_value,
|
||||||
src_value * 3 * (dec->info.width * dec->info.height) / 2;
|
3 * dec->info.width * dec->info.height, 2);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
@ -336,8 +351,17 @@ theora_dec_src_convert (GstPad * pad,
|
|||||||
default:
|
default:
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
}
|
}
|
||||||
|
done:
|
||||||
|
gst_object_unref (dec);
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
no_header:
|
||||||
|
{
|
||||||
|
GST_DEBUG_OBJECT (dec, "no header yet, cannot convert");
|
||||||
|
res = FALSE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -348,20 +372,19 @@ theora_dec_sink_convert (GstPad * pad,
|
|||||||
gboolean res = TRUE;
|
gboolean res = TRUE;
|
||||||
GstTheoraDec *dec;
|
GstTheoraDec *dec;
|
||||||
|
|
||||||
dec = GST_THEORA_DEC (GST_PAD_PARENT (pad));
|
|
||||||
|
|
||||||
/* we need the info part before we can done something */
|
|
||||||
if (!dec->have_header)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (src_format == *dest_format) {
|
if (src_format == *dest_format) {
|
||||||
*dest_value = src_value;
|
*dest_value = src_value;
|
||||||
return TRUE;
|
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) {
|
switch (src_format) {
|
||||||
case GST_FORMAT_DEFAULT:
|
case GST_FORMAT_DEFAULT:
|
||||||
{
|
|
||||||
switch (*dest_format) {
|
switch (*dest_format) {
|
||||||
case GST_FORMAT_TIME:
|
case GST_FORMAT_TIME:
|
||||||
*dest_value = _theora_granule_time (dec, src_value);
|
*dest_value = _theora_granule_time (dec, src_value);
|
||||||
@ -370,9 +393,7 @@ theora_dec_sink_convert (GstPad * pad,
|
|||||||
res = FALSE;
|
res = FALSE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case GST_FORMAT_TIME:
|
case GST_FORMAT_TIME:
|
||||||
{
|
|
||||||
switch (*dest_format) {
|
switch (*dest_format) {
|
||||||
case GST_FORMAT_DEFAULT:
|
case GST_FORMAT_DEFAULT:
|
||||||
{
|
{
|
||||||
@ -394,20 +415,31 @@ theora_dec_sink_convert (GstPad * pad,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
}
|
}
|
||||||
|
done:
|
||||||
|
gst_object_unref (dec);
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
no_header:
|
||||||
|
{
|
||||||
|
GST_DEBUG_OBJECT (dec, "no header yet, cannot convert");
|
||||||
|
res = FALSE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
theora_dec_src_query (GstPad * pad, GstQuery * query)
|
theora_dec_src_query (GstPad * pad, GstQuery * query)
|
||||||
{
|
{
|
||||||
GstTheoraDec *dec = GST_THEORA_DEC (GST_PAD_PARENT (pad));
|
GstTheoraDec *dec;
|
||||||
|
|
||||||
gboolean res = FALSE;
|
gboolean res = FALSE;
|
||||||
|
|
||||||
|
dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
|
||||||
|
|
||||||
switch (GST_QUERY_TYPE (query)) {
|
switch (GST_QUERY_TYPE (query)) {
|
||||||
case GST_QUERY_POSITION:
|
case GST_QUERY_POSITION:
|
||||||
{
|
{
|
||||||
@ -432,7 +464,7 @@ theora_dec_src_query (GstPad * pad, GstQuery * query)
|
|||||||
granulepos, &my_format, &time)))
|
granulepos, &my_format, &time)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
time = (time - dec->segment_start) + dec->segment_time;
|
time = (time - dec->segment.start) + dec->segment.time;
|
||||||
|
|
||||||
GST_LOG_OBJECT (dec,
|
GST_LOG_OBJECT (dec,
|
||||||
"query %p: our time: %" GST_TIME_FORMAT, query, GST_TIME_ARGS (time));
|
"query %p: our time: %" GST_TIME_FORMAT, query, GST_TIME_ARGS (time));
|
||||||
@ -471,11 +503,17 @@ theora_dec_src_query (GstPad * pad, GstQuery * query)
|
|||||||
res = gst_pad_query_default (pad, query);
|
res = gst_pad_query_default (pad, query);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
done:
|
||||||
|
gst_object_unref (dec);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
error:
|
error:
|
||||||
GST_DEBUG ("query failed");
|
{
|
||||||
return res;
|
GST_DEBUG_OBJECT (dec, "query failed");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -513,10 +551,11 @@ theora_dec_src_event (GstPad * pad, GstEvent * event)
|
|||||||
gboolean res = TRUE;
|
gboolean res = TRUE;
|
||||||
GstTheoraDec *dec;
|
GstTheoraDec *dec;
|
||||||
|
|
||||||
dec = GST_THEORA_DEC (GST_PAD_PARENT (pad));
|
dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
|
||||||
|
|
||||||
switch (GST_EVENT_TYPE (event)) {
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
case GST_EVENT_SEEK:{
|
case GST_EVENT_SEEK:
|
||||||
|
{
|
||||||
GstFormat format, tformat;
|
GstFormat format, tformat;
|
||||||
gdouble rate;
|
gdouble rate;
|
||||||
GstEvent *real_seek;
|
GstEvent *real_seek;
|
||||||
@ -536,9 +575,9 @@ theora_dec_src_event (GstPad * pad, GstEvent * event)
|
|||||||
*/
|
*/
|
||||||
tformat = GST_FORMAT_TIME;
|
tformat = GST_FORMAT_TIME;
|
||||||
if (!(res = theora_dec_src_convert (pad, format, cur, &tformat, &tcur)))
|
if (!(res = theora_dec_src_convert (pad, format, cur, &tformat, &tcur)))
|
||||||
goto error;
|
goto convert_error;
|
||||||
if (!(res = theora_dec_src_convert (pad, format, stop, &tformat, &tstop)))
|
if (!(res = theora_dec_src_convert (pad, format, stop, &tformat, &tstop)))
|
||||||
goto error;
|
goto convert_error;
|
||||||
|
|
||||||
/* then seek with time on the peer */
|
/* then seek with time on the peer */
|
||||||
real_seek = gst_event_new_seek (rate, GST_FORMAT_TIME,
|
real_seek = gst_event_new_seek (rate, GST_FORMAT_TIME,
|
||||||
@ -549,30 +588,41 @@ theora_dec_src_event (GstPad * pad, GstEvent * event)
|
|||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case GST_EVENT_QOS:
|
||||||
|
{
|
||||||
|
gdouble proportion;
|
||||||
|
GstClockTimeDiff diff;
|
||||||
|
GstClockTime timestamp;
|
||||||
|
|
||||||
|
gst_event_parse_qos (event, &proportion, &diff, ×tamp);
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
GST_OBJECT_LOCK (dec);
|
||||||
|
dec->proportion = proportion;
|
||||||
|
dec->earliest_time = timestamp + diff;
|
||||||
|
GST_OBJECT_UNLOCK (dec);
|
||||||
|
|
||||||
|
res = gst_pad_event_default (pad, event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
res = gst_pad_event_default (pad, event);
|
res = gst_pad_event_default (pad, event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
done:
|
||||||
|
gst_object_unref (dec);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
error:
|
/* ERRORS */
|
||||||
gst_event_unref (event);
|
convert_error:
|
||||||
return res;
|
{
|
||||||
}
|
GST_DEBUG_OBJECT (dec, "could not convert format");
|
||||||
|
gst_event_unref (event);
|
||||||
static GstCaps *
|
goto done;
|
||||||
theora_dec_src_getcaps (GstPad * pad)
|
}
|
||||||
{
|
|
||||||
GstCaps *caps;
|
|
||||||
|
|
||||||
GST_OBJECT_LOCK (pad);
|
|
||||||
if (!(caps = GST_PAD_CAPS (pad)))
|
|
||||||
caps = (GstCaps *) gst_pad_get_pad_template_caps (pad);
|
|
||||||
caps = gst_caps_ref (caps);
|
|
||||||
GST_OBJECT_UNLOCK (pad);
|
|
||||||
|
|
||||||
return caps;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -585,17 +635,25 @@ theora_dec_sink_event (GstPad * pad, GstEvent * event)
|
|||||||
|
|
||||||
GST_LOG_OBJECT (dec, "handling event");
|
GST_LOG_OBJECT (dec, "handling event");
|
||||||
switch (GST_EVENT_TYPE (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;
|
||||||
case GST_EVENT_EOS:
|
case GST_EVENT_EOS:
|
||||||
ret = gst_pad_push_event (dec->srcpad, event);
|
ret = gst_pad_push_event (dec->srcpad, event);
|
||||||
break;
|
break;
|
||||||
case GST_EVENT_NEWSEGMENT:
|
case GST_EVENT_NEWSEGMENT:
|
||||||
{
|
{
|
||||||
|
gboolean update;
|
||||||
GstFormat format;
|
GstFormat format;
|
||||||
gdouble rate;
|
gdouble rate;
|
||||||
gint64 start, stop, time;
|
gint64 start, stop, time;
|
||||||
|
|
||||||
gst_event_parse_new_segment (event, NULL, &rate, &format, &start, &stop,
|
gst_event_parse_new_segment (event, &update, &rate, &format, &start,
|
||||||
&time);
|
&stop, &time);
|
||||||
|
|
||||||
/* we need TIME and a positive rate */
|
/* we need TIME and a positive rate */
|
||||||
if (format != GST_FORMAT_TIME)
|
if (format != GST_FORMAT_TIME)
|
||||||
@ -604,15 +662,11 @@ theora_dec_sink_event (GstPad * pad, GstEvent * event)
|
|||||||
if (rate <= 0.0)
|
if (rate <= 0.0)
|
||||||
goto newseg_wrong_rate;
|
goto newseg_wrong_rate;
|
||||||
|
|
||||||
/* now copy over the values */
|
/* now configure the values */
|
||||||
dec->segment_rate = rate;
|
gst_segment_set_newsegment (&dec->segment, update,
|
||||||
dec->segment_start = start;
|
rate, format, start, stop, time);
|
||||||
dec->segment_stop = stop;
|
|
||||||
dec->segment_time = time;
|
|
||||||
|
|
||||||
dec->need_keyframe = TRUE;
|
/* and forward */
|
||||||
dec->granulepos = -1;
|
|
||||||
dec->last_timestamp = -1;
|
|
||||||
ret = gst_pad_push_event (dec->srcpad, event);
|
ret = gst_pad_push_event (dec->srcpad, event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -628,12 +682,12 @@ done:
|
|||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
newseg_wrong_format:
|
newseg_wrong_format:
|
||||||
{
|
{
|
||||||
GST_DEBUG ("received non TIME newsegment");
|
GST_DEBUG_OBJECT (dec, "received non TIME newsegment");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
newseg_wrong_rate:
|
newseg_wrong_rate:
|
||||||
{
|
{
|
||||||
GST_DEBUG ("negative rates not supported yet");
|
GST_DEBUG_OBJECT (dec, "negative rates not supported yet");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -649,7 +703,7 @@ theora_handle_comment_packet (GstTheoraDec * dec, ogg_packet * packet)
|
|||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
GstTagList *list;
|
GstTagList *list;
|
||||||
|
|
||||||
GST_DEBUG ("parsing comment packet");
|
GST_DEBUG_OBJECT (dec, "parsing comment packet");
|
||||||
|
|
||||||
buf = gst_buffer_new_and_alloc (packet->bytes);
|
buf = gst_buffer_new_and_alloc (packet->bytes);
|
||||||
memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
|
memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
|
||||||
@ -757,7 +811,7 @@ theora_handle_header_packet (GstTheoraDec * dec, ogg_packet * packet)
|
|||||||
{
|
{
|
||||||
GstFlowReturn res;
|
GstFlowReturn res;
|
||||||
|
|
||||||
GST_DEBUG ("parsing header packet");
|
GST_DEBUG_OBJECT (dec, "parsing header packet");
|
||||||
|
|
||||||
if (theora_decode_header (&dec->info, &dec->comment, packet))
|
if (theora_decode_header (&dec->info, &dec->comment, packet))
|
||||||
goto header_read_error;
|
goto header_read_error;
|
||||||
@ -788,6 +842,7 @@ header_read_error:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME, this needs to be moved to the demuxer */
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
theora_dec_push (GstTheoraDec * dec, GstBuffer * buf)
|
theora_dec_push (GstTheoraDec * dec, GstBuffer * buf)
|
||||||
{
|
{
|
||||||
@ -811,12 +866,12 @@ theora_dec_push (GstTheoraDec * dec, GstBuffer * buf)
|
|||||||
GstBuffer *buffer = GST_BUFFER (walk->data);
|
GstBuffer *buffer = GST_BUFFER (walk->data);
|
||||||
GstClockTime time;
|
GstClockTime time;
|
||||||
|
|
||||||
time = outtime - ((size * GST_SECOND * dec->info.fps_denominator)
|
time = outtime - gst_util_uint64_scale_int (size * GST_SECOND,
|
||||||
/ dec->info.fps_numerator);
|
dec->info.fps_denominator, dec->info.fps_numerator);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (dec, "patch buffer %lld %lld", size, time);
|
GST_DEBUG_OBJECT (dec, "patch buffer %lld %lld", size, time);
|
||||||
GST_BUFFER_TIMESTAMP (buffer) = time;
|
GST_BUFFER_TIMESTAMP (buffer) = time;
|
||||||
/* ignore the result */
|
/* ignore the result.. */
|
||||||
gst_pad_push (dec->srcpad, buffer);
|
gst_pad_push (dec->srcpad, buffer);
|
||||||
size--;
|
size--;
|
||||||
}
|
}
|
||||||
@ -856,16 +911,33 @@ theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet,
|
|||||||
goto dropping;
|
goto dropping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this does the decoding */
|
||||||
if (theora_decode_packetin (&dec->state, packet))
|
if (theora_decode_packetin (&dec->state, packet))
|
||||||
goto could_not_read;
|
|
||||||
|
|
||||||
if (theora_decode_YUVout (&dec->state, &yuv) < 0)
|
|
||||||
goto decode_error;
|
goto decode_error;
|
||||||
|
|
||||||
|
if (outtime != -1) {
|
||||||
|
gboolean need_skip;
|
||||||
|
|
||||||
|
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 && outtime <= 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 (theora_decode_YUVout (&dec->state, &yuv) < 0)
|
||||||
|
goto no_yuv;
|
||||||
|
|
||||||
if ((yuv.y_width != dec->info.width) || (yuv.y_height != dec->info.height))
|
if ((yuv.y_width != dec->info.width) || (yuv.y_height != dec->info.height))
|
||||||
goto wrong_dimensions;
|
goto wrong_dimensions;
|
||||||
|
|
||||||
|
|
||||||
width = dec->width;
|
width = dec->width;
|
||||||
height = dec->height;
|
height = dec->height;
|
||||||
cwidth = width / 2;
|
cwidth = width / 2;
|
||||||
@ -898,6 +970,7 @@ theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet,
|
|||||||
guchar *dest_y, *src_y;
|
guchar *dest_y, *src_y;
|
||||||
guchar *dest_u, *src_u;
|
guchar *dest_u, *src_u;
|
||||||
guchar *dest_v, *src_v;
|
guchar *dest_v, *src_v;
|
||||||
|
guint offset;
|
||||||
|
|
||||||
dest_y = GST_BUFFER_DATA (out);
|
dest_y = GST_BUFFER_DATA (out);
|
||||||
dest_u = dest_y + stride_y * height;
|
dest_u = dest_y + stride_y * height;
|
||||||
@ -912,8 +985,10 @@ theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet,
|
|||||||
src_y += yuv.y_stride;
|
src_y += yuv.y_stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
src_u = yuv.u + dec->offset_x / 2 + dec->offset_y / 2 * yuv.uv_stride;
|
offset = dec->offset_x / 2 + dec->offset_y / 2 * yuv.uv_stride;
|
||||||
src_v = yuv.v + 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++) {
|
for (i = 0; i < cheight; i++) {
|
||||||
memcpy (dest_u, src_u, cwidth);
|
memcpy (dest_u, src_u, cwidth);
|
||||||
@ -926,6 +1001,7 @@ theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME, frame_nr not correct */
|
||||||
GST_BUFFER_OFFSET (out) = dec->frame_nr;
|
GST_BUFFER_OFFSET (out) = dec->frame_nr;
|
||||||
dec->frame_nr++;
|
dec->frame_nr++;
|
||||||
GST_BUFFER_OFFSET_END (out) = dec->frame_nr;
|
GST_BUFFER_OFFSET_END (out) = dec->frame_nr;
|
||||||
@ -950,13 +1026,19 @@ dropping:
|
|||||||
GST_WARNING_OBJECT (dec, "dropping frame because we need a keyframe");
|
GST_WARNING_OBJECT (dec, "dropping frame because we need a keyframe");
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
could_not_read:
|
dropping_qos:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
|
dec->frame_nr++;
|
||||||
(NULL), ("theora decoder did not read data packet"));
|
GST_WARNING_OBJECT (dec, "dropping frame because of QoS");
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
decode_error:
|
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,
|
GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
|
||||||
(NULL), ("couldn't read out YUV image"));
|
(NULL), ("couldn't read out YUV image"));
|
||||||
@ -964,12 +1046,14 @@ decode_error:
|
|||||||
}
|
}
|
||||||
wrong_dimensions:
|
wrong_dimensions:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
|
GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, FORMAT,
|
||||||
(NULL), ("dimensions of image do not match header"));
|
(NULL), ("dimensions of image do not match header"));
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
no_buffer:
|
no_buffer:
|
||||||
{
|
{
|
||||||
|
GST_DEBUG_OBJECT (dec, "could not get buffer, reason: %s",
|
||||||
|
gst_flow_get_name (result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -983,12 +1067,20 @@ theora_dec_chain (GstPad * pad, GstBuffer * buf)
|
|||||||
|
|
||||||
dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
|
dec = GST_THEORA_DEC (gst_pad_get_parent (pad));
|
||||||
|
|
||||||
|
/* resync on DISCONT */
|
||||||
|
if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT))) {
|
||||||
|
dec->need_keyframe = TRUE;
|
||||||
|
dec->last_timestamp = -1;
|
||||||
|
dec->granulepos = -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* make ogg_packet out of the buffer */
|
/* make ogg_packet out of the buffer */
|
||||||
packet.packet = GST_BUFFER_DATA (buf);
|
packet.packet = GST_BUFFER_DATA (buf);
|
||||||
packet.bytes = GST_BUFFER_SIZE (buf);
|
packet.bytes = GST_BUFFER_SIZE (buf);
|
||||||
packet.granulepos = GST_BUFFER_OFFSET_END (buf);
|
packet.granulepos = GST_BUFFER_OFFSET_END (buf);
|
||||||
packet.packetno = 0; /* we don't really care */
|
packet.packetno = 0; /* we don't really care */
|
||||||
packet.b_o_s = dec->have_header ? 0 : 1;
|
packet.b_o_s = dec->have_header ? 0 : 1;
|
||||||
|
/* EOS does not matter for the decoder */
|
||||||
packet.e_o_s = 0;
|
packet.e_o_s = 0;
|
||||||
|
|
||||||
if (dec->have_header) {
|
if (dec->have_header) {
|
||||||
@ -1017,6 +1109,7 @@ theora_dec_chain (GstPad * pad, GstBuffer * buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
/* interpollate granule pos */
|
||||||
dec->granulepos = _inc_granulepos (dec, dec->granulepos);
|
dec->granulepos = _inc_granulepos (dec, dec->granulepos);
|
||||||
|
|
||||||
gst_object_unref (dec);
|
gst_object_unref (dec);
|
||||||
@ -1040,9 +1133,7 @@ theora_dec_change_state (GstElement * element, GstStateChange transition)
|
|||||||
theora_info_init (&dec->info);
|
theora_info_init (&dec->info);
|
||||||
theora_comment_init (&dec->comment);
|
theora_comment_init (&dec->comment);
|
||||||
dec->have_header = FALSE;
|
dec->have_header = FALSE;
|
||||||
dec->need_keyframe = TRUE;
|
gst_theora_dec_reset (dec);
|
||||||
dec->last_timestamp = -1;
|
|
||||||
dec->granulepos = -1;
|
|
||||||
break;
|
break;
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
||||||
break;
|
break;
|
||||||
@ -1059,8 +1150,6 @@ theora_dec_change_state (GstElement * element, GstStateChange transition)
|
|||||||
theora_clear (&dec->state);
|
theora_clear (&dec->state);
|
||||||
theora_comment_clear (&dec->comment);
|
theora_comment_clear (&dec->comment);
|
||||||
theora_info_clear (&dec->info);
|
theora_info_clear (&dec->info);
|
||||||
dec->have_header = FALSE;
|
|
||||||
dec->granulepos = -1;
|
|
||||||
break;
|
break;
|
||||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
case GST_STATE_CHANGE_READY_TO_NULL:
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user