mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-06 23:48:53 +00:00
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:
parent
59241d5e74
commit
4a77aaddbc
3 changed files with 107 additions and 34 deletions
18
ChangeLog
18
ChangeLog
|
@ -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>
|
2005-05-05 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* ext/ogg/Makefile.am:
|
* ext/ogg/Makefile.am:
|
||||||
|
|
|
@ -462,9 +462,6 @@ theora_dec_src_event (GstPad * pad, GstEvent * event)
|
||||||
if (!res)
|
if (!res)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* all worked, make sure we sync to keyframe */
|
|
||||||
dec->need_keyframe = TRUE;
|
|
||||||
|
|
||||||
error:
|
error:
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
break;
|
break;
|
||||||
|
@ -489,6 +486,7 @@ 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_DISCONTINUOUS:
|
case GST_EVENT_DISCONTINUOUS:
|
||||||
|
GST_STREAM_LOCK (pad);
|
||||||
if (gst_event_discont_get_value (event, GST_FORMAT_DEFAULT,
|
if (gst_event_discont_get_value (event, GST_FORMAT_DEFAULT,
|
||||||
&start_value, &end_value)) {
|
&start_value, &end_value)) {
|
||||||
dec->granulepos = start_value;
|
dec->granulepos = start_value;
|
||||||
|
@ -535,6 +533,7 @@ theora_dec_sink_event (GstPad * pad, GstEvent * event)
|
||||||
/* sync to keyframe */
|
/* sync to keyframe */
|
||||||
dec->need_keyframe = TRUE;
|
dec->need_keyframe = TRUE;
|
||||||
}
|
}
|
||||||
|
GST_STREAM_UNLOCK (pad);
|
||||||
gst_event_unref (event);
|
gst_event_unref (event);
|
||||||
break;
|
break;
|
||||||
default:
|
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
|
/* copy the visible region to the destination. This is actually pretty
|
||||||
* complicated and gstreamer doesn't support all the needed caps to do this
|
* 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
|
* 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
|
* 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;
|
guint8 *dest_y, *src_y;
|
||||||
|
|
|
@ -95,6 +95,7 @@ struct _GstTheoraEnc
|
||||||
gint keyframe_threshold;
|
gint keyframe_threshold;
|
||||||
gint keyframe_mindistance;
|
gint keyframe_mindistance;
|
||||||
gint noise_sensitivity;
|
gint noise_sensitivity;
|
||||||
|
gint sharpness;
|
||||||
|
|
||||||
gint info_width, info_height;
|
gint info_width, info_height;
|
||||||
gint width, height;
|
gint width, height;
|
||||||
|
@ -103,7 +104,7 @@ struct _GstTheoraEnc
|
||||||
|
|
||||||
guint packetno;
|
guint packetno;
|
||||||
guint64 bytes_out;
|
guint64 bytes_out;
|
||||||
guint64 next_ts;
|
guint64 initial_delay;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstTheoraEncClass
|
struct _GstTheoraEncClass
|
||||||
|
@ -126,6 +127,7 @@ struct _GstTheoraEncClass
|
||||||
#define THEORA_DEF_KEYFRAME_THRESHOLD 80
|
#define THEORA_DEF_KEYFRAME_THRESHOLD 80
|
||||||
#define THEORA_DEF_KEYFRAME_MINDISTANCE 8
|
#define THEORA_DEF_KEYFRAME_MINDISTANCE 8
|
||||||
#define THEORA_DEF_NOISE_SENSITIVITY 1
|
#define THEORA_DEF_NOISE_SENSITIVITY 1
|
||||||
|
#define THEORA_DEF_SHARPNESS 0
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -141,6 +143,7 @@ enum
|
||||||
ARG_KEYFRAME_THRESHOLD,
|
ARG_KEYFRAME_THRESHOLD,
|
||||||
ARG_KEYFRAME_MINDISTANCE,
|
ARG_KEYFRAME_MINDISTANCE,
|
||||||
ARG_NOISE_SENSITIVITY,
|
ARG_NOISE_SENSITIVITY,
|
||||||
|
ARG_SHARPNESS,
|
||||||
/* FILL ME */
|
/* FILL ME */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -243,6 +246,10 @@ gst_theora_enc_class_init (GstTheoraEncClass * klass)
|
||||||
g_param_spec_int ("noise-sensitivity", "Noise sensitivity",
|
g_param_spec_int ("noise-sensitivity", "Noise sensitivity",
|
||||||
"Noise sensitivity", 0, 32768, THEORA_DEF_NOISE_SENSITIVITY,
|
"Noise sensitivity", 0, 32768, THEORA_DEF_NOISE_SENSITIVITY,
|
||||||
(GParamFlags) G_PARAM_READWRITE));
|
(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;
|
gstelement_class->change_state = theora_enc_change_state;
|
||||||
GST_DEBUG_CATEGORY_INIT (theoraenc_debug, "theoraenc", 0, "Theora encoder");
|
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_threshold = THEORA_DEF_KEYFRAME_THRESHOLD;
|
||||||
enc->keyframe_mindistance = THEORA_DEF_KEYFRAME_MINDISTANCE;
|
enc->keyframe_mindistance = THEORA_DEF_KEYFRAME_MINDISTANCE;
|
||||||
enc->noise_sensitivity = THEORA_DEF_NOISE_SENSITIVITY;
|
enc->noise_sensitivity = THEORA_DEF_NOISE_SENSITIVITY;
|
||||||
|
enc->sharpness = THEORA_DEF_SHARPNESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
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_auto_threshold = enc->keyframe_threshold;
|
||||||
enc->info.keyframe_mindistance = enc->keyframe_mindistance;
|
enc->info.keyframe_mindistance = enc->keyframe_mindistance;
|
||||||
enc->info.noise_sensitivity = enc->noise_sensitivity;
|
enc->info.noise_sensitivity = enc->noise_sensitivity;
|
||||||
|
enc->info.sharpness = enc->sharpness;
|
||||||
|
|
||||||
theora_encode_init (&enc->state, &enc->info);
|
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 */
|
/* push out the buffer and do internal bookkeeping */
|
||||||
static void
|
static GstFlowReturn
|
||||||
theora_push_buffer (GstTheoraEnc * enc, GstBuffer * buffer)
|
theora_push_buffer (GstTheoraEnc * enc, GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
|
GstFlowReturn ret;
|
||||||
|
|
||||||
enc->bytes_out += GST_BUFFER_SIZE (buffer);
|
enc->bytes_out += GST_BUFFER_SIZE (buffer);
|
||||||
|
|
||||||
if (GST_PAD_IS_USABLE (enc->srcpad)) {
|
ret = gst_pad_push (enc->srcpad, buffer);
|
||||||
gst_pad_push (enc->srcpad, buffer);
|
|
||||||
} else {
|
return ret;
|
||||||
gst_buffer_unref (buffer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static GstFlowReturn
|
||||||
theora_push_packet (GstTheoraEnc * enc, ogg_packet * packet,
|
theora_push_packet (GstTheoraEnc * enc, ogg_packet * packet,
|
||||||
GstClockTime timestamp, GstClockTime duration)
|
GstClockTime timestamp, GstClockTime duration)
|
||||||
{
|
{
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
|
GstFlowReturn ret;
|
||||||
|
|
||||||
buf = theora_buffer_from_packet (enc, packet, timestamp, duration);
|
buf = theora_buffer_from_packet (enc, packet, timestamp, duration);
|
||||||
theora_push_buffer (enc, buf);
|
ret = theora_push_buffer (enc, buf);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstCaps *
|
static GstCaps *
|
||||||
|
@ -463,13 +475,14 @@ theora_enc_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
GstTheoraEnc *enc;
|
GstTheoraEnc *enc;
|
||||||
ogg_packet op;
|
ogg_packet op;
|
||||||
GstBuffer *buf;
|
|
||||||
GstClockTime in_time;
|
GstClockTime in_time;
|
||||||
|
GstFlowReturn ret;
|
||||||
|
|
||||||
enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
|
enc = GST_THEORA_ENC (GST_PAD_PARENT (pad));
|
||||||
|
|
||||||
buf = GST_BUFFER (buffer);
|
in_time = GST_BUFFER_TIMESTAMP (buffer);
|
||||||
in_time = GST_BUFFER_TIMESTAMP (buf);
|
|
||||||
|
GST_STREAM_LOCK (pad);
|
||||||
|
|
||||||
/* no packets written yet, setup headers */
|
/* no packets written yet, setup headers */
|
||||||
if (enc->packetno == 0) {
|
if (enc->packetno == 0) {
|
||||||
|
@ -497,16 +510,20 @@ theora_enc_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
/* mark buffers and put on caps */
|
/* mark buffers and put on caps */
|
||||||
caps = gst_pad_get_caps (enc->srcpad);
|
caps = gst_pad_get_caps (enc->srcpad);
|
||||||
caps = theora_set_header_on_caps (caps, buf1, buf2, buf3);
|
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_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps);
|
||||||
gst_pad_set_caps (enc->srcpad, 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 */
|
/* push out the header buffers */
|
||||||
theora_push_buffer (enc, buf1);
|
if ((ret = theora_push_buffer (enc, buf1)) != GST_FLOW_OK)
|
||||||
theora_push_buffer (enc, buf2);
|
goto header_push;
|
||||||
theora_push_buffer (enc, buf3);
|
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) {
|
if (enc->width == enc->info_width && enc->height == enc->info_height) {
|
||||||
/* easy case, no cropping/conversion needed */
|
/* easy case, no cropping/conversion needed */
|
||||||
pixels = GST_BUFFER_DATA (buf);
|
pixels = GST_BUFFER_DATA (buffer);
|
||||||
|
|
||||||
yuv.y = pixels;
|
yuv.y = pixels;
|
||||||
yuv.u = yuv.y + y_size;
|
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_u = yuv.u = yuv.y + y_size;
|
||||||
dest_v = yuv.v = yuv.u + y_size / 4;
|
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_u = src_y + src_y_stride * ROUND_UP_2 (height);
|
||||||
src_v = src_u + src_uv_stride * ROUND_UP_2 (height) / 2;
|
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);
|
gst_buffer_unref (buffer);
|
||||||
buf = newbuf;
|
buffer = newbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = theora_encode_YUVin (&enc->state, &yuv);
|
res = theora_encode_YUVin (&enc->state, &yuv);
|
||||||
|
|
||||||
|
ret = GST_FLOW_OK;
|
||||||
while (theora_encode_packetout (&enc->state, 0, &op)) {
|
while (theora_encode_packetout (&enc->state, 0, &op)) {
|
||||||
GstClockTime out_time;
|
GstClockTime out_time;
|
||||||
|
|
||||||
out_time = theora_granule_time (&enc->state, op.granulepos) * GST_SECOND;
|
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 (buffer);
|
||||||
gst_buffer_unref (buf);
|
|
||||||
}
|
}
|
||||||
|
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
|
static GstElementStateReturn
|
||||||
theora_enc_change_state (GstElement * element)
|
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:
|
case GST_STATE_NULL_TO_READY:
|
||||||
break;
|
break;
|
||||||
case GST_STATE_READY_TO_PAUSED:
|
case GST_STATE_READY_TO_PAUSED:
|
||||||
theora_info_init (&enc->info);
|
theora_info_init (&enc->info);
|
||||||
theora_comment_init (&enc->comment);
|
theora_comment_init (&enc->comment);
|
||||||
enc->packetno = 0;
|
enc->packetno = 0;
|
||||||
|
enc->initial_delay = 0;
|
||||||
break;
|
break;
|
||||||
case GST_STATE_PAUSED_TO_PLAYING:
|
case GST_STATE_PAUSED_TO_PLAYING:
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = parent_class->change_state (element);
|
||||||
|
|
||||||
|
switch (transition) {
|
||||||
case GST_STATE_PLAYING_TO_PAUSED:
|
case GST_STATE_PLAYING_TO_PAUSED:
|
||||||
break;
|
break;
|
||||||
case GST_STATE_PAUSED_TO_READY:
|
case GST_STATE_PAUSED_TO_READY:
|
||||||
|
GST_STREAM_LOCK (enc->sinkpad);
|
||||||
theora_clear (&enc->state);
|
theora_clear (&enc->state);
|
||||||
theora_comment_clear (&enc->comment);
|
theora_comment_clear (&enc->comment);
|
||||||
theora_info_clear (&enc->info);
|
theora_info_clear (&enc->info);
|
||||||
|
GST_STREAM_UNLOCK (enc->sinkpad);
|
||||||
break;
|
break;
|
||||||
case GST_STATE_READY_TO_NULL:
|
case GST_STATE_READY_TO_NULL:
|
||||||
break;
|
break;
|
||||||
|
@ -693,7 +743,7 @@ theora_enc_change_state (GstElement * element)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent_class->change_state (element);
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -738,6 +788,9 @@ theora_enc_set_property (GObject * object, guint prop_id,
|
||||||
case ARG_NOISE_SENSITIVITY:
|
case ARG_NOISE_SENSITIVITY:
|
||||||
enc->noise_sensitivity = g_value_get_int (value);
|
enc->noise_sensitivity = g_value_get_int (value);
|
||||||
break;
|
break;
|
||||||
|
case ARG_SHARPNESS:
|
||||||
|
enc->sharpness = g_value_get_int (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -784,6 +837,9 @@ theora_enc_get_property (GObject * object, guint prop_id,
|
||||||
case ARG_NOISE_SENSITIVITY:
|
case ARG_NOISE_SENSITIVITY:
|
||||||
g_value_set_int (value, enc->noise_sensitivity);
|
g_value_set_int (value, enc->noise_sensitivity);
|
||||||
break;
|
break;
|
||||||
|
case ARG_SHARPNESS:
|
||||||
|
g_value_set_int (value, enc->sharpness);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue