ext/theora/: Added stream lock to decoder so that we can serialize the discont event.

Original commit message from CVS:
* ext/theora/theoradec.c: (_inc_granulepos),
(theora_dec_src_event), (theora_dec_sink_event),
(theora_handle_comment_packet), (theora_handle_type_packet),
(theora_handle_header_packet), (theora_handle_data_packet),
(theora_dec_chain):
* ext/theora/theoraenc.c: (gst_theora_enc_class_init),
(gst_theora_enc_init), (theora_enc_sink_setcaps),
(theora_push_buffer), (theora_push_packet),
(theora_enc_sink_event), (theora_enc_chain),
(theora_enc_change_state), (theora_enc_set_property),
(theora_enc_get_property):
Added stream lock to decoder so that we can serialize
the discont event.
More theoraenc porting, recover from errors, do clean
shutdown.
This commit is contained in:
Wim Taymans 2005-05-05 09:44:01 +00:00
parent 59241d5e74
commit 4a77aaddbc
3 changed files with 107 additions and 34 deletions

View file

@ -1,3 +1,21 @@
2005-05-05 Wim Taymans <wim@fluendo.com>
* ext/theora/theoradec.c: (_inc_granulepos),
(theora_dec_src_event), (theora_dec_sink_event),
(theora_handle_comment_packet), (theora_handle_type_packet),
(theora_handle_header_packet), (theora_handle_data_packet),
(theora_dec_chain):
* ext/theora/theoraenc.c: (gst_theora_enc_class_init),
(gst_theora_enc_init), (theora_enc_sink_setcaps),
(theora_push_buffer), (theora_push_packet),
(theora_enc_sink_event), (theora_enc_chain),
(theora_enc_change_state), (theora_enc_set_property),
(theora_enc_get_property):
Added stream lock to decoder so that we can serialize
the discont event.
More theoraenc porting, recover from errors, do clean
shutdown.
2005-05-05 Wim Taymans <wim@fluendo.com>
* ext/ogg/Makefile.am:

View file

@ -462,9 +462,6 @@ theora_dec_src_event (GstPad * pad, GstEvent * event)
if (!res)
goto error;
/* all worked, make sure we sync to keyframe */
dec->need_keyframe = TRUE;
error:
gst_event_unref (event);
break;
@ -489,6 +486,7 @@ theora_dec_sink_event (GstPad * pad, GstEvent * event)
GST_LOG_OBJECT (dec, "handling event");
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_DISCONTINUOUS:
GST_STREAM_LOCK (pad);
if (gst_event_discont_get_value (event, GST_FORMAT_DEFAULT,
&start_value, &end_value)) {
dec->granulepos = start_value;
@ -535,6 +533,7 @@ theora_dec_sink_event (GstPad * pad, GstEvent * event)
/* sync to keyframe */
dec->need_keyframe = TRUE;
}
GST_STREAM_UNLOCK (pad);
gst_event_unref (event);
break;
default:
@ -744,9 +743,9 @@ theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet,
/* 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 on chroma sample in colorspace conversion.
* 1 row/column of luma samples with one chroma sample in colorspace conversion.
* We compensate for this by adding a block border around the image when the
* offset of size is odd (see above).
* offset or size is odd (see above).
*/
{
guint8 *dest_y, *src_y;

View file

@ -95,6 +95,7 @@ struct _GstTheoraEnc
gint keyframe_threshold;
gint keyframe_mindistance;
gint noise_sensitivity;
gint sharpness;
gint info_width, info_height;
gint width, height;
@ -103,7 +104,7 @@ struct _GstTheoraEnc
guint packetno;
guint64 bytes_out;
guint64 next_ts;
guint64 initial_delay;
};
struct _GstTheoraEncClass
@ -126,6 +127,7 @@ struct _GstTheoraEncClass
#define THEORA_DEF_KEYFRAME_THRESHOLD 80
#define THEORA_DEF_KEYFRAME_MINDISTANCE 8
#define THEORA_DEF_NOISE_SENSITIVITY 1
#define THEORA_DEF_SHARPNESS 0
enum
{
@ -141,6 +143,7 @@ enum
ARG_KEYFRAME_THRESHOLD,
ARG_KEYFRAME_MINDISTANCE,
ARG_NOISE_SENSITIVITY,
ARG_SHARPNESS,
/* FILL ME */
};
@ -243,6 +246,10 @@ gst_theora_enc_class_init (GstTheoraEncClass * klass)
g_param_spec_int ("noise-sensitivity", "Noise sensitivity",
"Noise sensitivity", 0, 32768, THEORA_DEF_NOISE_SENSITIVITY,
(GParamFlags) G_PARAM_READWRITE));
g_object_class_install_property (gobject_class, ARG_SHARPNESS,
g_param_spec_int ("sharpness", "Sharpness",
"Sharpness", 0, 2, THEORA_DEF_SHARPNESS,
(GParamFlags) G_PARAM_READWRITE));
gstelement_class->change_state = theora_enc_change_state;
GST_DEBUG_CATEGORY_INIT (theoraenc_debug, "theoraenc", 0, "Theora encoder");
@ -276,6 +283,7 @@ gst_theora_enc_init (GstTheoraEnc * enc)
enc->keyframe_threshold = THEORA_DEF_KEYFRAME_THRESHOLD;
enc->keyframe_mindistance = THEORA_DEF_KEYFRAME_MINDISTANCE;
enc->noise_sensitivity = THEORA_DEF_NOISE_SENSITIVITY;
enc->sharpness = THEORA_DEF_SHARPNESS;
}
static gboolean
@ -344,6 +352,7 @@ theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
enc->info.keyframe_auto_threshold = enc->keyframe_threshold;
enc->info.keyframe_mindistance = enc->keyframe_mindistance;
enc->info.noise_sensitivity = enc->noise_sensitivity;
enc->info.sharpness = enc->sharpness;
theora_encode_init (&enc->state, &enc->info);
@ -379,26 +388,29 @@ theora_buffer_from_packet (GstTheoraEnc * enc, ogg_packet * packet,
}
/* push out the buffer and do internal bookkeeping */
static void
static GstFlowReturn
theora_push_buffer (GstTheoraEnc * enc, GstBuffer * buffer)
{
GstFlowReturn ret;
enc->bytes_out += GST_BUFFER_SIZE (buffer);
if (GST_PAD_IS_USABLE (enc->srcpad)) {
gst_pad_push (enc->srcpad, buffer);
} else {
gst_buffer_unref (buffer);
}
ret = gst_pad_push (enc->srcpad, buffer);
return ret;
}
static void
static GstFlowReturn
theora_push_packet (GstTheoraEnc * enc, ogg_packet * packet,
GstClockTime timestamp, GstClockTime duration)
{
GstBuffer *buf;
GstFlowReturn ret;
buf = theora_buffer_from_packet (enc, packet, timestamp, duration);
theora_push_buffer (enc, buf);
ret = theora_push_buffer (enc, buf);
return ret;
}
static GstCaps *
@ -463,13 +475,14 @@ theora_enc_chain (GstPad * pad, GstBuffer * buffer)
{
GstTheoraEnc *enc;
ogg_packet op;
GstBuffer *buf;
GstClockTime in_time;
GstFlowReturn ret;
enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
buf = GST_BUFFER (buffer);
in_time = GST_BUFFER_TIMESTAMP (buf);
in_time = GST_BUFFER_TIMESTAMP (buffer);
GST_STREAM_LOCK (pad);
/* no packets written yet, setup headers */
if (enc->packetno == 0) {
@ -497,16 +510,20 @@ theora_enc_chain (GstPad * pad, GstBuffer * buffer)
/* mark buffers and put on caps */
caps = gst_pad_get_caps (enc->srcpad);
caps = theora_set_header_on_caps (caps, buf1, buf2, buf3);
gst_pad_set_caps (enc->srcpad, caps);
/* negotiate with these caps */
GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
gst_pad_set_caps (enc->srcpad, caps);
gst_buffer_set_caps (buf1, caps);
gst_buffer_set_caps (buf2, caps);
gst_buffer_set_caps (buf3, caps);
/* push out the header buffers */
theora_push_buffer (enc, buf1);
theora_push_buffer (enc, buf2);
theora_push_buffer (enc, buf3);
if ((ret = theora_push_buffer (enc, buf1)) != GST_FLOW_OK)
goto header_push;
if ((ret = theora_push_buffer (enc, buf2)) != GST_FLOW_OK)
goto header_push;
if ((ret = theora_push_buffer (enc, buf3)) != GST_FLOW_OK)
goto header_push;
}
{
@ -527,7 +544,7 @@ theora_enc_chain (GstPad * pad, GstBuffer * buffer)
if (enc->width == enc->info_width && enc->height == enc->info_height) {
/* easy case, no cropping/conversion needed */
pixels = GST_BUFFER_DATA (buf);
pixels = GST_BUFFER_DATA (buffer);
yuv.y = pixels;
yuv.u = yuv.y + y_size;
@ -566,7 +583,7 @@ theora_enc_chain (GstPad * pad, GstBuffer * buffer)
dest_u = yuv.u = yuv.y + y_size;
dest_v = yuv.v = yuv.u + y_size / 4;
src_y = GST_BUFFER_DATA (buf);
src_y = GST_BUFFER_DATA (buffer);
src_u = src_y + src_y_stride * ROUND_UP_2 (height);
src_v = src_u + src_uv_stride * ROUND_UP_2 (height) / 2;
@ -647,45 +664,78 @@ theora_enc_chain (GstPad * pad, GstBuffer * buffer)
}
}
gst_buffer_unref (buf);
buf = newbuf;
gst_buffer_unref (buffer);
buffer = newbuf;
}
res = theora_encode_YUVin (&enc->state, &yuv);
ret = GST_FLOW_OK;
while (theora_encode_packetout (&enc->state, 0, &op)) {
GstClockTime out_time;
out_time = theora_granule_time (&enc->state, op.granulepos) * GST_SECOND;
theora_push_packet (enc, &op, out_time, GST_SECOND / enc->fps);
if ((ret = theora_push_packet (enc, &op, out_time, GST_SECOND / enc->fps))
!= GST_FLOW_OK)
goto data_push;
}
gst_buffer_unref (buf);
gst_buffer_unref (buffer);
}
GST_STREAM_UNLOCK (pad);
return GST_FLOW_OK;
return ret;
/* ERRORS */
header_push:
{
gst_buffer_unref (buffer);
GST_STREAM_UNLOCK (pad);
return ret;
}
data_push:
{
gst_buffer_unref (buffer);
GST_STREAM_UNLOCK (pad);
return ret;
}
}
static GstElementStateReturn
theora_enc_change_state (GstElement * element)
{
GstTheoraEnc *enc = GST_THEORA_ENC (element);
GstTheoraEnc *enc;
gint transition;
GstElementStateReturn ret;
switch (GST_STATE_TRANSITION (element)) {
transition = GST_STATE_TRANSITION (element);
enc = GST_THEORA_ENC (element);
switch (transition) {
case GST_STATE_NULL_TO_READY:
break;
case GST_STATE_READY_TO_PAUSED:
theora_info_init (&enc->info);
theora_comment_init (&enc->comment);
enc->packetno = 0;
enc->initial_delay = 0;
break;
case GST_STATE_PAUSED_TO_PLAYING:
break;
default:
break;
}
ret = parent_class->change_state (element);
switch (transition) {
case GST_STATE_PLAYING_TO_PAUSED:
break;
case GST_STATE_PAUSED_TO_READY:
GST_STREAM_LOCK (enc->sinkpad);
theora_clear (&enc->state);
theora_comment_clear (&enc->comment);
theora_info_clear (&enc->info);
GST_STREAM_UNLOCK (enc->sinkpad);
break;
case GST_STATE_READY_TO_NULL:
break;
@ -693,7 +743,7 @@ theora_enc_change_state (GstElement * element)
break;
}
return parent_class->change_state (element);
return ret;
}
static void
@ -738,6 +788,9 @@ theora_enc_set_property (GObject * object, guint prop_id,
case ARG_NOISE_SENSITIVITY:
enc->noise_sensitivity = g_value_get_int (value);
break;
case ARG_SHARPNESS:
enc->sharpness = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -784,6 +837,9 @@ theora_enc_get_property (GObject * object, guint prop_id,
case ARG_NOISE_SENSITIVITY:
g_value_set_int (value, enc->noise_sensitivity);
break;
case ARG_SHARPNESS:
g_value_set_int (value, enc->sharpness);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;