X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gst-libs%2Fgst%2Faudio%2Fgstaudioencoder.c;h=997b0692e8b22bd6d0f49a6c6fb2b4004f411560;hb=f71511edd2d054ba8c76a086cfa9af14b07acd52;hp=b3ad1d4f6e5eb7b7b33072a2536790d651595bde;hpb=4fa9749106ae8377b8091b79fe66dcb2e8bcfb7f;p=platform%2Fupstream%2Fgstreamer.git diff --git a/gst-libs/gst/audio/gstaudioencoder.c b/gst-libs/gst/audio/gstaudioencoder.c index b3ad1d4..997b069 100644 --- a/gst-libs/gst/audio/gstaudioencoder.c +++ b/gst-libs/gst/audio/gstaudioencoder.c @@ -151,7 +151,6 @@ # include "config.h" #endif -#define GST_USE_UNSTABLE_API #include "gstaudioencoder.h" #include #include @@ -247,6 +246,45 @@ struct _GstAudioEncoderPrivate GList *pending_events; }; + +static GstElementClass *parent_class = NULL; + +static void gst_audio_encoder_class_init (GstAudioEncoderClass * klass); +static void gst_audio_encoder_init (GstAudioEncoder * parse, + GstAudioEncoderClass * klass); + +GType +gst_audio_encoder_get_type (void) +{ + static GType audio_encoder_type = 0; + + if (!audio_encoder_type) { + static const GTypeInfo audio_encoder_info = { + sizeof (GstAudioEncoderClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gst_audio_encoder_class_init, + NULL, + NULL, + sizeof (GstAudioEncoder), + 0, + (GInstanceInitFunc) gst_audio_encoder_init, + }; + const GInterfaceInfo preset_interface_info = { + NULL, /* interface_init */ + NULL, /* interface_finalize */ + NULL /* interface_data */ + }; + + audio_encoder_type = g_type_register_static (GST_TYPE_ELEMENT, + "GstAudioEncoder", &audio_encoder_info, G_TYPE_FLAG_ABSTRACT); + + g_type_add_interface_static (audio_encoder_type, GST_TYPE_PRESET, + &preset_interface_info); + } + return audio_encoder_type; +} + static void gst_audio_encoder_finalize (GObject * object); static void gst_audio_encoder_reset (GstAudioEncoder * enc, gboolean full); @@ -259,27 +297,13 @@ static gboolean gst_audio_encoder_sink_activate_push (GstPad * pad, gboolean active); static gboolean gst_audio_encoder_sink_event (GstPad * pad, GstEvent * event); -static gboolean gst_audio_encoder_sink_setcaps (GstPad * pad, GstCaps * caps); +static gboolean gst_audio_encoder_sink_setcaps (GstAudioEncoder * enc, + GstCaps * caps); static GstFlowReturn gst_audio_encoder_chain (GstPad * pad, GstBuffer * buffer); static gboolean gst_audio_encoder_src_query (GstPad * pad, GstQuery * query); static gboolean gst_audio_encoder_sink_query (GstPad * pad, GstQuery * query); static const GstQueryType *gst_audio_encoder_get_query_types (GstPad * pad); -static GstCaps *gst_audio_encoder_sink_getcaps (GstPad * pad); - -static void -do_init (GType gtype) -{ - const GInterfaceInfo preset_interface_info = { - NULL, /* interface_init */ - NULL, /* interface_finalize */ - NULL /* interface_data */ - }; - - g_type_add_interface_static (gtype, GST_TYPE_PRESET, &preset_interface_info); -} - -GST_BOILERPLATE_FULL (GstAudioEncoder, gst_audio_encoder, GstElement, - GST_TYPE_ELEMENT, do_init); +static GstCaps *gst_audio_encoder_sink_getcaps (GstPad * pad, GstCaps * filter); static void gst_audio_encoder_class_init (GstAudioEncoderClass * klass) @@ -287,6 +311,7 @@ gst_audio_encoder_class_init (GstAudioEncoderClass * klass) GObjectClass *gobject_class; gobject_class = G_OBJECT_CLASS (klass); + parent_class = g_type_class_peek_parent (klass); GST_DEBUG_CATEGORY_INIT (gst_audio_encoder_debug, "audioencoder", 0, "audio encoder base class"); @@ -319,11 +344,6 @@ gst_audio_encoder_class_init (GstAudioEncoderClass * klass) } static void -gst_audio_encoder_base_init (gpointer g_class) -{ -} - -static void gst_audio_encoder_init (GstAudioEncoder * enc, GstAudioEncoderClass * bclass) { GstPadTemplate *pad_template; @@ -339,8 +359,6 @@ gst_audio_encoder_init (GstAudioEncoder * enc, GstAudioEncoderClass * bclass) enc->sinkpad = gst_pad_new_from_template (pad_template, "sink"); gst_pad_set_event_function (enc->sinkpad, GST_DEBUG_FUNCPTR (gst_audio_encoder_sink_event)); - gst_pad_set_setcaps_function (enc->sinkpad, - GST_DEBUG_FUNCPTR (gst_audio_encoder_sink_setcaps)); gst_pad_set_getcaps_function (enc->sinkpad, GST_DEBUG_FUNCPTR (gst_audio_encoder_sink_getcaps)); gst_pad_set_query_function (enc->sinkpad, @@ -392,7 +410,7 @@ gst_audio_encoder_reset (GstAudioEncoder * enc, gboolean full) enc->priv->active = FALSE; enc->priv->samples_in = 0; enc->priv->bytes_out = 0; - gst_audio_info_clear (&enc->priv->ctx.info); + gst_audio_info_init (&enc->priv->ctx.info); memset (&enc->priv->ctx, 0, sizeof (enc->priv->ctx)); if (enc->priv->tags) @@ -469,9 +487,9 @@ gst_audio_encoder_finish_frame (GstAudioEncoder * enc, GstBuffer * buf, ctx = &enc->priv->ctx; /* subclass should know what it is producing by now */ - g_return_val_if_fail (GST_PAD_CAPS (enc->srcpad) != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (gst_pad_has_current_caps (enc->srcpad), GST_FLOW_ERROR); /* subclass should not hand us no data */ - g_return_val_if_fail (buf == NULL || GST_BUFFER_SIZE (buf) > 0, + g_return_val_if_fail (buf == NULL || gst_buffer_get_size (buf) > 0, GST_FLOW_ERROR); GST_AUDIO_ENCODER_STREAM_LOCK (enc); @@ -492,7 +510,7 @@ gst_audio_encoder_finish_frame (GstAudioEncoder * enc, GstBuffer * buf, } GST_LOG_OBJECT (enc, "accepting %d bytes encoded data as %d samples", - buf ? GST_BUFFER_SIZE (buf) : -1, samples); + buf ? gst_buffer_get_size (buf) : -1, samples); /* mark subclass still alive and providing */ priv->got_data = TRUE; @@ -582,11 +600,14 @@ gst_audio_encoder_finish_frame (GstAudioEncoder * enc, GstBuffer * buf, /* collect output */ if (G_LIKELY (buf)) { - GST_LOG_OBJECT (enc, "taking %d bytes for output", GST_BUFFER_SIZE (buf)); - buf = gst_buffer_make_metadata_writable (buf); + gsize size; + + size = gst_buffer_get_size (buf); + + GST_LOG_OBJECT (enc, "taking %d bytes for output", size); + buf = gst_buffer_make_writable (buf); /* decorate */ - gst_buffer_set_caps (buf, GST_PAD_CAPS (enc->srcpad)); if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (priv->base_ts))) { /* FIXME ? lookahead could lead to weird ts and duration ? * (particularly if not in perfect mode) */ @@ -618,11 +639,11 @@ gst_audio_encoder_finish_frame (GstAudioEncoder * enc, GstBuffer * buf, ctx->info.rate); } else { GST_BUFFER_OFFSET (buf) = priv->bytes_out; - GST_BUFFER_OFFSET_END (buf) = priv->bytes_out + GST_BUFFER_SIZE (buf); + GST_BUFFER_OFFSET_END (buf) = priv->bytes_out + size; } } - priv->bytes_out += GST_BUFFER_SIZE (buf); + priv->bytes_out += size; if (G_UNLIKELY (priv->discont)) { GST_LOG_OBJECT (enc, "marking discont"); @@ -643,7 +664,7 @@ gst_audio_encoder_finish_frame (GstAudioEncoder * enc, GstBuffer * buf, } GST_LOG_OBJECT (enc, "pushing buffer of size %d with ts %" GST_TIME_FORMAT - ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buf), + ", duration %" GST_TIME_FORMAT, size, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); @@ -734,10 +755,12 @@ gst_audio_encoder_push_buffers (GstAudioEncoder * enc, gboolean force) } if (need) { - buf = gst_buffer_new (); - GST_BUFFER_DATA (buf) = (guint8 *) - gst_adapter_peek (priv->adapter, priv->offset + need) + priv->offset; - GST_BUFFER_SIZE (buf) = need; + const guint8 *data; + + data = gst_adapter_map (priv->adapter, priv->offset + need); + buf = + gst_buffer_new_wrapped_full ((gpointer) data, NULL, priv->offset, + need); } GST_LOG_OBJECT (enc, "providing subclass with %d bytes at offset %d", @@ -751,8 +774,10 @@ gst_audio_encoder_push_buffers (GstAudioEncoder * enc, gboolean force) priv->got_data = FALSE; ret = klass->handle_frame (enc, buf); - if (G_LIKELY (buf)) + if (G_LIKELY (buf)) { gst_buffer_unref (buf); + gst_adapter_unmap (priv->adapter, 0); + } /* no data to feed, no leftover provided, then bail out */ if (G_UNLIKELY (!buf && !priv->got_data)) { @@ -809,6 +834,7 @@ gst_audio_encoder_chain (GstPad * pad, GstBuffer * buffer) GstAudioEncoderContext *ctx; GstFlowReturn ret = GST_FLOW_OK; gboolean discont; + gsize size; enc = GST_AUDIO_ENCODER (GST_OBJECT_PARENT (pad)); @@ -821,14 +847,16 @@ gst_audio_encoder_chain (GstPad * pad, GstBuffer * buffer) if (!ctx->info.bpf) goto not_negotiated; + size = gst_buffer_get_size (buffer); + GST_LOG_OBJECT (enc, "received buffer of size %d with ts %" GST_TIME_FORMAT - ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer), + ", duration %" GST_TIME_FORMAT, size, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), GST_TIME_ARGS (GST_BUFFER_DURATION (buffer))); /* input shoud be whole number of sample frames */ - if (GST_BUFFER_SIZE (buffer) % ctx->info.bpf) + if (size % ctx->info.bpf) goto wrong_buffer; #ifndef GST_DISABLE_GST_DEBUG @@ -837,7 +865,7 @@ gst_audio_encoder_chain (GstPad * pad, GstBuffer * buffer) GstClockTimeDiff diff; /* verify buffer duration */ - duration = gst_util_uint64_scale (GST_BUFFER_SIZE (buffer), GST_SECOND, + duration = gst_util_uint64_scale (size, GST_SECOND, ctx->info.rate * ctx->info.bpf); diff = GST_CLOCK_DIFF (duration, GST_BUFFER_DURATION (buffer)); if (GST_BUFFER_DURATION (buffer) != GST_CLOCK_TIME_NONE && @@ -866,9 +894,11 @@ gst_audio_encoder_chain (GstPad * pad, GstBuffer * buffer) goto done; } + size = gst_buffer_get_size (buffer); + GST_LOG_OBJECT (enc, "buffer after segment clipping has size %d with ts %" GST_TIME_FORMAT - ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer), + ", duration %" GST_TIME_FORMAT, size, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), GST_TIME_ARGS (GST_BUFFER_DURATION (buffer))); @@ -919,13 +949,12 @@ gst_audio_encoder_chain (GstPad * pad, GstBuffer * buffer) diff_bytes = GST_CLOCK_TIME_TO_FRAMES (-diff, ctx->info.rate) * ctx->info.bpf; - if (diff_bytes >= GST_BUFFER_SIZE (buffer)) { + if (diff_bytes >= size) { gst_buffer_unref (buffer); goto done; } - buffer = gst_buffer_make_metadata_writable (buffer); - GST_BUFFER_DATA (buffer) += diff_bytes; - GST_BUFFER_SIZE (buffer) -= diff_bytes; + buffer = gst_buffer_make_writable (buffer); + gst_buffer_resize (buffer, diff_bytes, size - diff_bytes); GST_BUFFER_TIMESTAMP (buffer) += diff; /* care even less about duration after this */ @@ -965,7 +994,7 @@ not_negotiated: wrong_buffer: { GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL), - ("buffer size %d not a multiple of %d", GST_BUFFER_SIZE (buffer), + ("buffer size %d not a multiple of %d", gst_buffer_get_size (buffer), ctx->info.bpf)); gst_buffer_unref (buffer); ret = GST_FLOW_ERROR; @@ -993,23 +1022,20 @@ audio_info_is_equal (GstAudioInfo * from, GstAudioInfo * to) } static gboolean -gst_audio_encoder_sink_setcaps (GstPad * pad, GstCaps * caps) +gst_audio_encoder_sink_setcaps (GstAudioEncoder * enc, GstCaps * caps) { - GstAudioEncoder *enc; GstAudioEncoderClass *klass; GstAudioEncoderContext *ctx; - GstAudioInfo *state, *old_state; + GstAudioInfo state; gboolean res = TRUE, changed = FALSE; guint old_rate; - enc = GST_AUDIO_ENCODER (GST_PAD_PARENT (pad)); klass = GST_AUDIO_ENCODER_GET_CLASS (enc); /* subclass must do something here ... */ g_return_val_if_fail (klass->set_format != NULL, FALSE); ctx = &enc->priv->ctx; - state = &ctx->info; GST_AUDIO_ENCODER_STREAM_LOCK (enc); @@ -1019,19 +1045,17 @@ gst_audio_encoder_sink_setcaps (GstPad * pad, GstCaps * caps) goto refuse_caps; /* adjust ts tracking to new sample rate */ - old_rate = GST_AUDIO_INFO_RATE (state); + old_rate = GST_AUDIO_INFO_RATE (&ctx->info); if (GST_CLOCK_TIME_IS_VALID (enc->priv->base_ts) && old_rate) { enc->priv->base_ts += GST_FRAMES_TO_CLOCK_TIME (enc->priv->samples, old_rate); enc->priv->samples = 0; } - old_state = gst_audio_info_copy (state); - if (!gst_audio_info_from_caps (state, caps)) + if (!gst_audio_info_from_caps (&state, caps)) goto refuse_caps; - changed = !audio_info_is_equal (state, old_state); - gst_audio_info_free (old_state); + changed = !audio_info_is_equal (&state, &ctx->info); if (changed) { GstClockTime old_min_latency; @@ -1053,7 +1077,7 @@ gst_audio_encoder_sink_setcaps (GstPad * pad, GstCaps * caps) GST_OBJECT_UNLOCK (enc); if (klass->set_format) - res = klass->set_format (enc, state); + res = klass->set_format (enc, &state); /* notify if new latency */ GST_OBJECT_LOCK (enc); @@ -1166,7 +1190,7 @@ done: } static GstCaps * -gst_audio_encoder_sink_getcaps (GstPad * pad) +gst_audio_encoder_sink_getcaps (GstPad * pad, GstCaps * filter) { GstAudioEncoder *enc; GstAudioEncoderClass *klass; @@ -1177,7 +1201,7 @@ gst_audio_encoder_sink_getcaps (GstPad * pad) g_assert (pad == enc->sinkpad); if (klass->getcaps) - caps = klass->getcaps (enc); + caps = klass->getcaps (enc, filter); else caps = gst_audio_encoder_proxy_getcaps (enc, NULL); gst_object_unref (enc); @@ -1196,26 +1220,16 @@ gst_audio_encoder_sink_eventfunc (GstAudioEncoder * enc, GstEvent * event) klass = GST_AUDIO_ENCODER_GET_CLASS (enc); switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NEWSEGMENT: + case GST_EVENT_SEGMENT: { - GstFormat format; - gdouble rate, arate; - gint64 start, stop, time; - gboolean update; - - gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, - &start, &stop, &time); - - if (format == GST_FORMAT_TIME) { - GST_DEBUG_OBJECT (enc, "received TIME NEW_SEGMENT %" GST_TIME_FORMAT - " -- %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT - ", rate %g, applied_rate %g", - GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time), - rate, arate); + GstSegment seg; + + gst_event_copy_segment (event, &seg); + + if (seg.format == GST_FORMAT_TIME) { + GST_DEBUG_OBJECT (enc, "received TIME SEGMENT %" GST_PTR_FORMAT, &seg); } else { - GST_DEBUG_OBJECT (enc, "received NEW_SEGMENT %" G_GINT64_FORMAT - " -- %" G_GINT64_FORMAT ", time %" G_GINT64_FORMAT - ", rate %g, applied_rate %g", start, stop, time, rate, arate); + GST_DEBUG_OBJECT (enc, "received SEGMENT %" GST_PTR_FORMAT, &seg); GST_DEBUG_OBJECT (enc, "unsupported format; ignoring"); break; } @@ -1226,8 +1240,7 @@ gst_audio_encoder_sink_eventfunc (GstAudioEncoder * enc, GstEvent * event) /* reset partially for new segment */ gst_audio_encoder_reset (enc, FALSE); /* and follow along with segment */ - gst_segment_set_newsegment_full (&enc->segment, update, rate, arate, - format, start, stop, time); + enc->segment = seg; GST_AUDIO_ENCODER_STREAM_UNLOCK (enc); break; } @@ -1276,6 +1289,17 @@ gst_audio_encoder_sink_eventfunc (GstAudioEncoder * enc, GstEvent * event) break; } + case GST_EVENT_CAPS: + { + GstCaps *caps; + + gst_event_parse_caps (event, &caps); + gst_audio_encoder_sink_setcaps (enc, caps); + gst_event_unref (event); + handled = TRUE; + break; + } + default: break; } @@ -1490,10 +1514,10 @@ gst_audio_encoder_src_query (GstPad * pad, GstQuery * query) gst_query_parse_position (query, &req_fmt, NULL); fmt = GST_FORMAT_TIME; - if (!(res = gst_pad_query_position (peerpad, &fmt, &pos))) + if (!(res = gst_pad_query_position (peerpad, fmt, &pos))) break; - if ((res = gst_pad_query_convert (peerpad, fmt, pos, &req_fmt, &val))) { + if ((res = gst_pad_query_convert (peerpad, fmt, pos, req_fmt, &val))) { gst_query_set_position (query, req_fmt, val); } break; @@ -1515,10 +1539,10 @@ gst_audio_encoder_src_query (GstPad * pad, GstQuery * query) gst_query_parse_duration (query, &req_fmt, NULL); fmt = GST_FORMAT_TIME; - if (!(res = gst_pad_query_duration (peerpad, &fmt, &dur))) + if (!(res = gst_pad_query_duration (peerpad, fmt, &dur))) break; - if ((res = gst_pad_query_convert (peerpad, fmt, dur, &req_fmt, &val))) { + if ((res = gst_pad_query_convert (peerpad, fmt, dur, req_fmt, &val))) { gst_query_set_duration (query, req_fmt, val); } break; @@ -1711,6 +1735,9 @@ gst_audio_encoder_get_audio_info (GstAudioEncoder * enc) * Sets number of samples (per channel) subclass needs to be handed, * at least or will be handed all available if 0. * + * If an exact number of samples is required, gst_audio_encoder_set_frame_samples_max() + * must be called with the same number. + * * Since: 0.10.36 */ void @@ -1745,6 +1772,9 @@ gst_audio_encoder_get_frame_samples_min (GstAudioEncoder * enc) * Sets number of samples (per channel) subclass needs to be handed, * at most or will be handed all available if 0. * + * If an exact number of samples is required, gst_audio_encoder_set_frame_samples_min() + * must be called with the same number. + * * Since: 0.10.36 */ void