mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +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>
|
||||
|
||||
* ext/ogg/Makefile.am:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue