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:
Wim Taymans 2006-03-09 17:58:00 +00:00
parent ba3d2db624
commit 808d7edd02
4 changed files with 201 additions and 87 deletions

View File

@ -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),

View File

@ -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);

View File

@ -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

View File

@ -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, &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. */
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;