mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 04:45:36 +00:00
Merge remote-tracking branch 'origin/master' into 0.11
Conflicts: ext/vorbis/gstvorbisenc.c gst/playback/gstdecodebin2.c gst/playback/gstplaysinkconvertbin.c gst/videorate/gstvideorate.c
This commit is contained in:
commit
32b14c6ed3
14 changed files with 350 additions and 112 deletions
ext
gst-libs/gst
gst
|
@ -461,6 +461,9 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet,
|
|||
|
||||
cret = GST_FLOW_OK;
|
||||
|
||||
GST_DEBUG_OBJECT (pad, "Chaining %d %d %" GST_TIME_FORMAT " %d %p",
|
||||
ogg->pullmode, ogg->push_state, GST_TIME_ARGS (ogg->push_time_length),
|
||||
ogg->push_disable_seeking, ogg->building_chain);
|
||||
GST_PUSH_LOCK (ogg);
|
||||
if (!ogg->pullmode && ogg->push_state == PUSH_PLAYING
|
||||
&& ogg->push_time_length == GST_CLOCK_TIME_NONE
|
||||
|
@ -1056,6 +1059,8 @@ gst_ogg_pad_stream_out (GstOggPad * pad, gint npackets)
|
|||
break;
|
||||
case 1:
|
||||
GST_LOG_OBJECT (ogg, "packetout gave packet of size %ld", packet.bytes);
|
||||
if (packet.bytes > ogg->max_packet_size)
|
||||
ogg->max_packet_size = packet.bytes;
|
||||
result = gst_ogg_pad_submit_packet (pad, &packet);
|
||||
/* not linked is not a problem, it's possible that we are still
|
||||
* collecting headers and that we don't have exposed the pads yet */
|
||||
|
@ -1097,19 +1102,22 @@ gst_ogg_demux_setup_bisection_bounds (GstOggDemux * ogg)
|
|||
GST_TIME_ARGS (ogg->push_last_seek_time - ogg->push_seek_time_target));
|
||||
ogg->push_offset1 = ogg->push_last_seek_offset;
|
||||
ogg->push_time1 = ogg->push_last_seek_time;
|
||||
ogg->seek_undershot = FALSE;
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (ogg, "We undershot by %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (ogg->push_seek_time_target - ogg->push_last_seek_time));
|
||||
ogg->push_offset0 = ogg->push_last_seek_offset;
|
||||
ogg->push_time0 = ogg->push_last_seek_time;
|
||||
ogg->seek_undershot = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static gint64
|
||||
gst_ogg_demux_estimate_bisection_target (GstOggDemux * ogg)
|
||||
gst_ogg_demux_estimate_bisection_target (GstOggDemux * ogg, float seek_quality)
|
||||
{
|
||||
gint64 best;
|
||||
gint64 segment_bitrate;
|
||||
gint64 skew;
|
||||
|
||||
/* we might not know the length of the stream in time,
|
||||
so push_time1 might not be set */
|
||||
|
@ -1136,6 +1144,7 @@ gst_ogg_demux_estimate_bisection_target (GstOggDemux * ogg)
|
|||
ogg->push_offset0 +
|
||||
gst_util_uint64_scale (ogg->push_seek_time_target - ogg->push_time0,
|
||||
segment_bitrate, 8 * GST_SECOND);
|
||||
ogg->seek_secant = TRUE;
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (ogg,
|
||||
"New segment to consider: bytes %" G_GINT64_FORMAT " %" G_GINT64_FORMAT
|
||||
|
@ -1152,20 +1161,63 @@ gst_ogg_demux_estimate_bisection_target (GstOggDemux * ogg)
|
|||
"Local bitrate on the %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT
|
||||
" segment: %" G_GINT64_FORMAT, GST_TIME_ARGS (ogg->push_time0),
|
||||
GST_TIME_ARGS (ogg->push_time1), segment_bitrate);
|
||||
|
||||
best =
|
||||
ogg->push_offset0 +
|
||||
gst_util_uint64_scale (ogg->push_seek_time_target - ogg->push_time0,
|
||||
segment_bitrate, 8 * GST_SECOND);
|
||||
if (seek_quality < 0.5f && ogg->seek_secant) {
|
||||
gint64 new_best, best2 = (ogg->push_offset0 + ogg->push_offset1) / 2;
|
||||
/* if dire result, give as much as 25% weight to a dumb bisection guess */
|
||||
float secant_weight = 1.0f - ((0.5 - seek_quality) / 0.5f) * 0.25;
|
||||
new_best = (best * secant_weight + best2 * (1.0f - secant_weight));
|
||||
GST_DEBUG_OBJECT (ogg,
|
||||
"Secant says %" G_GINT64_FORMAT ", straight is %" G_GINT64_FORMAT
|
||||
", new best %" G_GINT64_FORMAT " with secant_weight %f", best,
|
||||
best2, new_best, secant_weight);
|
||||
best = new_best;
|
||||
ogg->seek_secant = FALSE;
|
||||
} else {
|
||||
ogg->seek_secant = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* offset by typical page size */
|
||||
best -= CHUNKSIZE;
|
||||
GST_DEBUG_OBJECT (ogg, "Raw best guess: %" G_GINT64_FORMAT, best);
|
||||
|
||||
/* offset the guess down as we need to capture the start of the
|
||||
page we are targetting - but only do so if we did not undershoot
|
||||
last time, as we're likely to still do this time */
|
||||
if (!ogg->seek_undershot) {
|
||||
/* very small packets are packed on pages, so offset by at least
|
||||
a value which is likely to get us at least one page where the
|
||||
packet starts */
|
||||
skew =
|
||||
ogg->max_packet_size >
|
||||
ogg->max_page_size ? ogg->max_packet_size : ogg->max_page_size;
|
||||
GST_DEBUG_OBJECT (ogg, "Offsetting by %" G_GINT64_FORMAT, skew);
|
||||
best -= skew;
|
||||
}
|
||||
|
||||
/* do not seek too close to the bounds, as we stop seeking
|
||||
when we get to within max_packet_size before the target */
|
||||
if (best > ogg->push_offset1 - ogg->max_packet_size) {
|
||||
best = ogg->push_offset1 - ogg->max_packet_size;
|
||||
GST_DEBUG_OBJECT (ogg,
|
||||
"Too close to high bound, pushing back to %" G_GINT64_FORMAT, best);
|
||||
} else if (best < ogg->push_offset0 + ogg->max_packet_size) {
|
||||
best = ogg->push_offset0 + ogg->max_packet_size;
|
||||
GST_DEBUG_OBJECT (ogg,
|
||||
"Too close to low bound, pushing forth to %" G_GINT64_FORMAT, best);
|
||||
}
|
||||
|
||||
/* keep within bounds */
|
||||
if (best > ogg->push_offset1)
|
||||
best = ogg->push_offset1;
|
||||
if (best < ogg->push_offset0)
|
||||
best = ogg->push_offset0;
|
||||
if (best < 0)
|
||||
best = 0;
|
||||
|
||||
GST_DEBUG_OBJECT (ogg, "Choosing target %" G_GINT64_FORMAT, best);
|
||||
return best;
|
||||
}
|
||||
|
||||
|
@ -1242,6 +1294,60 @@ gst_ogg_demux_seek_back_after_push_duration_check_unlock (GstOggDemux * ogg)
|
|||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static float
|
||||
gst_ogg_demux_estimate_seek_quality (GstOggDemux * ogg)
|
||||
{
|
||||
gint64 diff; /* how far from the goal we ended up */
|
||||
gint64 dist; /* how far we moved this iteration */
|
||||
float seek_quality;
|
||||
|
||||
if (ogg->push_prev_seek_time == GST_CLOCK_TIME_NONE) {
|
||||
/* for the first seek, we pretend we got a good seek,
|
||||
as we don't have a previous seek yet */
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
/* We take a guess at how good the last seek was at guessing
|
||||
the byte target by comparing the amplitude of the last
|
||||
seek to the error */
|
||||
diff = ogg->push_seek_time_target - ogg->push_last_seek_time;
|
||||
if (diff < 0)
|
||||
diff = -diff;
|
||||
dist = ogg->push_last_seek_time - ogg->push_prev_seek_time;
|
||||
if (dist < 0)
|
||||
dist = -dist;
|
||||
|
||||
seek_quality = (dist == 0) ? 0.0f : 1.0f / (1.0f + diff / (float) dist);
|
||||
|
||||
GST_DEBUG_OBJECT (ogg,
|
||||
"We moved %" GST_TIME_FORMAT ", we're off by %" GST_TIME_FORMAT
|
||||
", seek quality %f", GST_TIME_ARGS (dist), GST_TIME_ARGS (diff),
|
||||
seek_quality);
|
||||
return seek_quality;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ogg_demux_update_bisection_stats (GstOggDemux * ogg)
|
||||
{
|
||||
int n;
|
||||
|
||||
GST_INFO_OBJECT (ogg, "Bisection needed %d + %d steps",
|
||||
ogg->push_bisection_steps[0], ogg->push_bisection_steps[1]);
|
||||
|
||||
for (n = 0; n < 2; ++n) {
|
||||
ogg->stats_bisection_steps[n] += ogg->push_bisection_steps[n];
|
||||
if (ogg->stats_bisection_max_steps[n] < ogg->push_bisection_steps[n])
|
||||
ogg->stats_bisection_max_steps[n] = ogg->push_bisection_steps[n];
|
||||
}
|
||||
ogg->stats_nbisections++;
|
||||
|
||||
GST_INFO_OBJECT (ogg,
|
||||
"So far, %.2f + %.2f bisections needed per seek (max %d + %d)",
|
||||
ogg->stats_bisection_steps[0] / (float) ogg->stats_nbisections,
|
||||
ogg->stats_bisection_steps[1] / (float) ogg->stats_nbisections,
|
||||
ogg->stats_bisection_max_steps[0], ogg->stats_bisection_max_steps[1]);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_ogg_pad_handle_push_mode_state (GstOggPad * pad, ogg_page * page)
|
||||
{
|
||||
|
@ -1317,6 +1423,7 @@ gst_ogg_pad_handle_push_mode_state (GstOggPad * pad, ogg_page * page)
|
|||
GstEvent *sevent;
|
||||
int res;
|
||||
gboolean close_enough;
|
||||
float seek_quality;
|
||||
|
||||
/* ignore -1 granpos when seeking, we want to sync on a real granpos */
|
||||
if (granpos < 0) {
|
||||
|
@ -1354,14 +1461,18 @@ gst_ogg_pad_handle_push_mode_state (GstOggPad * pad, ogg_page * page)
|
|||
GST_TIME_ARGS (ogg->push_seek_time_target));
|
||||
|
||||
if (ogg->push_time1 != GST_CLOCK_TIME_NONE) {
|
||||
seek_quality = gst_ogg_demux_estimate_seek_quality (ogg);
|
||||
GST_DEBUG_OBJECT (ogg,
|
||||
"Interval was %" G_GINT64_FORMAT " - %" G_GINT64_FORMAT " (%"
|
||||
G_GINT64_FORMAT "), time %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT
|
||||
" (%" GST_TIME_FORMAT ")", ogg->push_offset0, ogg->push_offset1,
|
||||
ogg->push_offset1 - ogg->push_offset0,
|
||||
" (%" GST_TIME_FORMAT "), seek quality %f", ogg->push_offset0,
|
||||
ogg->push_offset1, ogg->push_offset1 - ogg->push_offset0,
|
||||
GST_TIME_ARGS (ogg->push_time0), GST_TIME_ARGS (ogg->push_time1),
|
||||
GST_TIME_ARGS (ogg->push_time1 - ogg->push_time0));
|
||||
GST_TIME_ARGS (ogg->push_time1 - ogg->push_time0), seek_quality);
|
||||
} else {
|
||||
/* in a open ended seek, we can't do bisection, so we pretend
|
||||
we like our result so far */
|
||||
seek_quality = 1.0f;
|
||||
GST_DEBUG_OBJECT (ogg,
|
||||
"Interval was %" G_GINT64_FORMAT " - %" G_GINT64_FORMAT " (%"
|
||||
G_GINT64_FORMAT "), time %" GST_TIME_FORMAT " - unknown",
|
||||
|
@ -1369,30 +1480,39 @@ gst_ogg_pad_handle_push_mode_state (GstOggPad * pad, ogg_page * page)
|
|||
ogg->push_offset1 - ogg->push_offset0,
|
||||
GST_TIME_ARGS (ogg->push_time0));
|
||||
}
|
||||
ogg->push_prev_seek_time = ogg->push_last_seek_time;
|
||||
|
||||
gst_ogg_demux_setup_bisection_bounds (ogg);
|
||||
|
||||
best = gst_ogg_demux_estimate_bisection_target (ogg);
|
||||
best = gst_ogg_demux_estimate_bisection_target (ogg, seek_quality);
|
||||
|
||||
if (ogg->push_seek_time_target == 0) {
|
||||
GST_DEBUG_OBJECT (ogg, "Seeking to 0, deemed close enough");
|
||||
close_enough = (ogg->push_last_seek_time == 0);
|
||||
} else {
|
||||
/* TODO: make this dependent on framerate ? */
|
||||
GstClockTime threshold = GST_SECOND / 2;
|
||||
GstClockTime time_threshold = GST_SECOND / 2;
|
||||
guint64 byte_threshold =
|
||||
(ogg->max_packet_size >
|
||||
64 * 1024 ? ogg->max_packet_size : 64 * 1024);
|
||||
|
||||
/* We want to be within half a second before the target */
|
||||
if (threshold > ogg->push_seek_time_target)
|
||||
threshold = ogg->push_seek_time_target;
|
||||
/* We want to be within half a second before the target,
|
||||
or before the target and half less or equal to the max
|
||||
packet size left to search in */
|
||||
if (time_threshold > ogg->push_seek_time_target)
|
||||
time_threshold = ogg->push_seek_time_target;
|
||||
close_enough = ogg->push_last_seek_time < ogg->push_seek_time_target
|
||||
&& ogg->push_last_seek_time >=
|
||||
ogg->push_seek_time_target - threshold;
|
||||
&& (ogg->push_last_seek_time >=
|
||||
ogg->push_seek_time_target - time_threshold
|
||||
|| ogg->push_offset1 <= ogg->push_offset0 + byte_threshold);
|
||||
GST_DEBUG_OBJECT (ogg,
|
||||
"testing if we're close enough: %" GST_TIME_FORMAT " <= %"
|
||||
GST_TIME_FORMAT " < %" GST_TIME_FORMAT " ? %s",
|
||||
GST_TIME_ARGS (ogg->push_seek_time_target - threshold),
|
||||
GST_TIME_FORMAT " < %" GST_TIME_FORMAT ", or %" G_GUINT64_FORMAT
|
||||
" <= %" G_GUINT64_FORMAT " ? %s",
|
||||
GST_TIME_ARGS (ogg->push_seek_time_target - time_threshold),
|
||||
GST_TIME_ARGS (ogg->push_last_seek_time),
|
||||
GST_TIME_ARGS (ogg->push_seek_time_target),
|
||||
ogg->push_offset1 - ogg->push_offset0, byte_threshold,
|
||||
close_enough ? "Yes" : "No");
|
||||
}
|
||||
|
||||
|
@ -1422,14 +1542,13 @@ gst_ogg_pad_handle_push_mode_state (GstOggPad * pad, ogg_page * page)
|
|||
GST_TIME_ARGS (ogg->push_seek_time_original_target));
|
||||
ogg->push_state = PUSH_LINEAR2;
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (ogg, "Seek to keyframe done, playing");
|
||||
GST_INFO_OBJECT (ogg, "Seek to keyframe done, playing");
|
||||
|
||||
/* we're synced to the seek target, so flush stream and stuff
|
||||
any queued pages into the stream so we start decoding there */
|
||||
ogg->push_state = PUSH_PLAYING;
|
||||
}
|
||||
GST_INFO_OBJECT (ogg, "Bisection needed %d + %d steps",
|
||||
ogg->push_bisection_steps[0], ogg->push_bisection_steps[1]);
|
||||
gst_ogg_demux_update_bisection_stats (ogg);
|
||||
}
|
||||
}
|
||||
} else if (ogg->push_state == PUSH_LINEAR1) {
|
||||
|
@ -1443,14 +1562,30 @@ gst_ogg_pad_handle_push_mode_state (GstOggPad * pad, ogg_page * page)
|
|||
GST_TIME_ARGS (pad->push_kf_time));
|
||||
earliest_keyframe_time = gst_ogg_demux_get_earliest_keyframe_time (ogg);
|
||||
if (earliest_keyframe_time != GST_CLOCK_TIME_NONE) {
|
||||
GST_DEBUG_OBJECT (ogg,
|
||||
"All non sparse streams now have a previous keyframe time,"
|
||||
"bisecting again to %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (earliest_keyframe_time));
|
||||
ogg->push_seek_time_target = earliest_keyframe_time;
|
||||
if (earliest_keyframe_time > ogg->push_last_seek_time) {
|
||||
GST_INFO_OBJECT (ogg,
|
||||
"All non sparse streams now have a previous keyframe time, "
|
||||
"and we already decoded it, switching to playing");
|
||||
ogg->push_state = PUSH_PLAYING;
|
||||
gst_ogg_demux_update_bisection_stats (ogg);
|
||||
} else {
|
||||
GST_INFO_OBJECT (ogg,
|
||||
"All non sparse streams now have a previous keyframe time, "
|
||||
"bisecting again to %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (earliest_keyframe_time));
|
||||
|
||||
ogg->push_state = PUSH_BISECT2;
|
||||
best = gst_ogg_demux_estimate_bisection_target (ogg);
|
||||
ogg->push_seek_time_target = earliest_keyframe_time;
|
||||
ogg->push_offset0 = 0;
|
||||
ogg->push_time0 = ogg->push_start_time;
|
||||
ogg->push_offset1 = ogg->push_last_seek_offset;
|
||||
ogg->push_time1 = ogg->push_last_seek_time;
|
||||
ogg->push_prev_seek_time = GST_CLOCK_TIME_NONE;
|
||||
ogg->seek_secant = FALSE;
|
||||
ogg->seek_undershot = FALSE;
|
||||
|
||||
ogg->push_state = PUSH_BISECT2;
|
||||
best = gst_ogg_demux_estimate_bisection_target (ogg, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1555,6 +1690,9 @@ gst_ogg_pad_submit_page (GstOggPad * pad, ogg_page * page)
|
|||
return result;
|
||||
}
|
||||
|
||||
if (page->header_len + page->body_len > ogg->max_page_size)
|
||||
ogg->max_page_size = page->header_len + page->body_len;
|
||||
|
||||
if (ogg_stream_pagein (&pad->map.stream, page) != 0)
|
||||
goto choked;
|
||||
|
||||
|
@ -1837,6 +1975,12 @@ gst_ogg_demux_init (GstOggDemux * ogg)
|
|||
ogg->push_lock = g_mutex_new ();
|
||||
ogg->chains = g_array_new (FALSE, TRUE, sizeof (GstOggChain *));
|
||||
|
||||
ogg->stats_nbisections = 0;
|
||||
ogg->stats_bisection_steps[0] = 0;
|
||||
ogg->stats_bisection_steps[1] = 0;
|
||||
ogg->stats_bisection_max_steps[0] = 0;
|
||||
ogg->stats_bisection_max_steps[1] = 0;
|
||||
|
||||
ogg->newsegment = NULL;
|
||||
}
|
||||
|
||||
|
@ -3233,8 +3377,11 @@ gst_ogg_demux_perform_seek_push (GstOggDemux * ogg, GstEvent * event)
|
|||
ogg->push_time0 = ogg->push_start_time;
|
||||
ogg->push_time1 = ogg->push_time_length;
|
||||
ogg->push_seek_time_target = start;
|
||||
ogg->push_prev_seek_time = GST_CLOCK_TIME_NONE;
|
||||
ogg->push_seek_time_original_target = start;
|
||||
ogg->push_state = PUSH_BISECT1;
|
||||
ogg->seek_secant = FALSE;
|
||||
ogg->seek_undershot = FALSE;
|
||||
|
||||
/* reset pad push mode seeking state */
|
||||
for (i = 0; i < chain->streams->len; i++) {
|
||||
|
|
|
@ -145,6 +145,10 @@ struct _GstOggDemux
|
|||
gboolean need_chains;
|
||||
gboolean resync;
|
||||
|
||||
/* keep track of how large pages and packets are,
|
||||
useful for skewing when seeking */
|
||||
guint64 max_packet_size, max_page_size;
|
||||
|
||||
/* state */
|
||||
GMutex *chain_lock; /* we need the lock to protect the chains */
|
||||
GArray *chains; /* list of chains we know */
|
||||
|
@ -185,8 +189,14 @@ struct _GstOggDemux
|
|||
GstSeekFlags push_seek_flags;
|
||||
GstEvent *push_mode_seek_delayed_event;
|
||||
gboolean push_disable_seeking;
|
||||
gboolean seek_secant;
|
||||
gboolean seek_undershot;
|
||||
GstClockTime push_prev_seek_time;
|
||||
|
||||
gint push_bisection_steps[2];
|
||||
gint stats_bisection_steps[2];
|
||||
gint stats_bisection_max_steps[2];
|
||||
gint stats_nbisections;
|
||||
|
||||
/* ogg stuff */
|
||||
ogg_sync_state sync;
|
||||
|
|
|
@ -448,7 +448,7 @@ gst_ogg_mux_request_new_pad (GstElement * element,
|
|||
|
||||
oggpad = (GstOggPadData *)
|
||||
gst_collect_pads2_add_pad_full (ogg_mux->collect, newpad,
|
||||
sizeof (GstOggPadData), gst_ogg_mux_ogg_pad_destroy_notify, TRUE);
|
||||
sizeof (GstOggPadData), gst_ogg_mux_ogg_pad_destroy_notify, FALSE);
|
||||
ogg_mux->active_pads++;
|
||||
|
||||
oggpad->map.serialno = serial;
|
||||
|
@ -968,6 +968,12 @@ gst_ogg_mux_queue_pads (GstOggMux * ogg_mux, gboolean * popped)
|
|||
} else {
|
||||
GST_DEBUG_OBJECT (pad, "caps detected: %" GST_PTR_FORMAT,
|
||||
pad->map.caps);
|
||||
|
||||
if (pad->map.is_sparse) {
|
||||
GST_DEBUG_OBJECT (pad, "Pad is sparse, marking as such");
|
||||
gst_collect_pads2_set_waiting (ogg_mux->collect,
|
||||
(GstCollectData2 *) pad, FALSE);
|
||||
}
|
||||
}
|
||||
if (caps)
|
||||
gst_caps_unref (caps);
|
||||
|
@ -1325,8 +1331,8 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
|
|||
|
||||
GST_LOG_OBJECT (mux, "looking at pad %s:%s", GST_DEBUG_PAD_NAME (thepad));
|
||||
|
||||
/* if the pad has no buffer, we don't care */
|
||||
if (pad->buffer == NULL)
|
||||
/* if the pad has no buffer and is not sparse, we don't care */
|
||||
if (pad->buffer == NULL && !pad->map.is_sparse)
|
||||
continue;
|
||||
|
||||
/* now figure out the headers */
|
||||
|
|
|
@ -11,7 +11,7 @@ libgstvorbis_la_SOURCES = gstvorbis.c \
|
|||
gstvorbistag.c \
|
||||
gstvorbiscommon.c
|
||||
|
||||
libgstvorbis_la_CFLAGS = -DGST_USE_UNSTABLE_API \
|
||||
libgstvorbis_la_CFLAGS = \
|
||||
$(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(VORBIS_CFLAGS)
|
||||
## AM_PATH_VORBIS also sets VORBISENC_LIBS
|
||||
libgstvorbis_la_LIBADD = \
|
||||
|
@ -28,7 +28,7 @@ plugin_LTLIBRARIES += libgstivorbisdec.la
|
|||
|
||||
libgstivorbisdec_la_SOURCES = gstivorbisdec.c \
|
||||
gstvorbisdec.c gstvorbisdeclib.c gstvorbiscommon.c
|
||||
libgstivorbisdec_la_CFLAGS = -DGST_USE_UNSTABLE_API \
|
||||
libgstivorbisdec_la_CFLAGS = \
|
||||
$(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) \
|
||||
-DTREMOR $(IVORBIS_CFLAGS)
|
||||
libgstivorbisdec_la_LIBADD = \
|
||||
|
|
|
@ -65,7 +65,7 @@ GST_STATIC_PAD_TEMPLATE ("sink",
|
|||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("audio/x-raw, "
|
||||
"format = (string) " GST_AUDIO_NE (F32) ", "
|
||||
"rate = (int) [ 1, 200000 ], " "channels = (int) [ 1, 256 ]")
|
||||
"rate = (int) [ 1, 200000 ], " "channels = (int) [ 1, 255 ]")
|
||||
);
|
||||
|
||||
static GstStaticPadTemplate vorbis_enc_src_factory =
|
||||
|
@ -295,7 +295,7 @@ gst_vorbis_enc_generate_sink_caps (void)
|
|||
gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw",
|
||||
"format", G_TYPE_STRING, GST_AUDIO_NE (F32),
|
||||
"rate", GST_TYPE_INT_RANGE, 1, 200000,
|
||||
"channels", GST_TYPE_INT_RANGE, 9, 256, NULL));
|
||||
"channels", GST_TYPE_INT_RANGE, 9, 255, NULL));
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
|
|
@ -80,7 +80,6 @@ GstAudio-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstaudio-@GST_MAJORMI
|
|||
--nsversion=@GST_MAJORMINOR@ \
|
||||
--warn-all \
|
||||
--strip-prefix=Gst \
|
||||
-DGST_USE_UNSTABLE_API \
|
||||
-I$(top_srcdir)/gst-libs \
|
||||
-I$(top_builddir)/gst-libs \
|
||||
$(gir_cincludes) \
|
||||
|
|
|
@ -23,11 +23,6 @@
|
|||
#ifndef _GST_AUDIO_DECODER_H_
|
||||
#define _GST_AUDIO_DECODER_H_
|
||||
|
||||
#ifndef GST_USE_UNSTABLE_API
|
||||
#warning "GstAudioDecoder is unstable API and may change in future."
|
||||
#warning "You can define GST_USE_UNSTABLE_API to avoid this warning."
|
||||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/audio/audio.h>
|
||||
#include <gst/base/gstadapter.h>
|
||||
|
|
|
@ -22,11 +22,6 @@
|
|||
#ifndef __GST_AUDIO_ENCODER_H__
|
||||
#define __GST_AUDIO_ENCODER_H__
|
||||
|
||||
#ifndef GST_USE_UNSTABLE_API
|
||||
#warning "GstAudioEncoder is unstable API and may change in future."
|
||||
#warning "You can define GST_USE_UNSTABLE_API to avoid this warning."
|
||||
#endif
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/audio/audio.h>
|
||||
|
||||
|
|
|
@ -46,6 +46,8 @@ G_BEGIN_DECLS
|
|||
#define GST_RIFF_TAG_JUNQ GST_MAKE_FOURCC ('J','U','N','Q')
|
||||
#define GST_RIFF_TAG_idx1 GST_MAKE_FOURCC ('i','d','x','1')
|
||||
#define GST_RIFF_TAG_dmlh GST_MAKE_FOURCC ('d','m','l','h')
|
||||
#define GST_RIFF_TAG_ID32 GST_MAKE_FOURCC ('I','D','3','2')
|
||||
#define GST_RIFF_TAG_IDVX GST_MAKE_FOURCC ('I','D','V','X')
|
||||
/* WAV stuff */
|
||||
#define GST_RIFF_TAG_fmt GST_MAKE_FOURCC ('f','m','t',' ')
|
||||
#define GST_RIFF_TAG_data GST_MAKE_FOURCC ('d','a','t','a')
|
||||
|
|
|
@ -173,8 +173,6 @@ struct _GstDecodeBin
|
|||
|
||||
gboolean expose_allstreams; /* Whether to expose unknow type streams or not */
|
||||
|
||||
gboolean upstream_seekable; /* if upstream is seekable */
|
||||
|
||||
GList *filtered; /* elements for which error messages are filtered */
|
||||
};
|
||||
|
||||
|
@ -268,7 +266,7 @@ static void type_found (GstElement * typefind, guint probability,
|
|||
GstCaps * caps, GstDecodeBin * decode_bin);
|
||||
|
||||
static void decodebin_set_queue_size (GstDecodeBin * dbin,
|
||||
GstElement * multiqueue, gboolean preroll);
|
||||
GstElement * multiqueue, gboolean preroll, gboolean seekable);
|
||||
|
||||
static gboolean gst_decode_bin_autoplug_continue (GstElement * element,
|
||||
GstPad * pad, GstCaps * caps);
|
||||
|
@ -293,6 +291,8 @@ static GstStateChangeReturn gst_decode_bin_change_state (GstElement * element,
|
|||
GstStateChange transition);
|
||||
static void gst_decode_bin_handle_message (GstBin * bin, GstMessage * message);
|
||||
|
||||
static gboolean check_upstream_seekable (GstDecodeBin * dbin, GstPad * pad);
|
||||
|
||||
#define EXPOSE_LOCK(dbin) G_STMT_START { \
|
||||
GST_LOG_OBJECT (dbin, \
|
||||
"expose locking from thread %p", \
|
||||
|
@ -393,6 +393,7 @@ struct _GstDecodeChain
|
|||
GstPad *pad; /* srcpad that caused creation of this chain */
|
||||
|
||||
gboolean demuxer; /* TRUE if elements->data is a demuxer */
|
||||
gboolean seekable; /* TRUE if this chain ends on a demuxer and is seekable */
|
||||
GList *elements; /* All elements in this group, first
|
||||
is the latest and most downstream element */
|
||||
|
||||
|
@ -2203,40 +2204,39 @@ beach:
|
|||
*
|
||||
* Check if upstream is seekable.
|
||||
*/
|
||||
static void
|
||||
static gboolean
|
||||
check_upstream_seekable (GstDecodeBin * dbin, GstPad * pad)
|
||||
{
|
||||
GstQuery *query;
|
||||
gint64 start = -1, stop = -1;
|
||||
|
||||
dbin->upstream_seekable = FALSE;
|
||||
gboolean seekable = FALSE;
|
||||
|
||||
query = gst_query_new_seeking (GST_FORMAT_BYTES);
|
||||
if (!gst_pad_peer_query (pad, query)) {
|
||||
GST_DEBUG_OBJECT (dbin, "seeking query failed");
|
||||
gst_query_unref (query);
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gst_query_parse_seeking (query, NULL, &dbin->upstream_seekable,
|
||||
&start, &stop);
|
||||
gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
|
||||
|
||||
gst_query_unref (query);
|
||||
|
||||
/* try harder to query upstream size if we didn't get it the first time */
|
||||
if (dbin->upstream_seekable && stop == -1) {
|
||||
if (seekable && stop == -1) {
|
||||
GST_DEBUG_OBJECT (dbin, "doing duration query to fix up unset stop");
|
||||
gst_pad_peer_query_duration (pad, GST_FORMAT_BYTES, &stop);
|
||||
}
|
||||
|
||||
/* if upstream doesn't know the size, it's likely that it's not seekable in
|
||||
* practice even if it technically may be seekable */
|
||||
if (dbin->upstream_seekable && (start != 0 || stop <= start)) {
|
||||
if (seekable && (start != 0 || stop <= start)) {
|
||||
GST_DEBUG_OBJECT (dbin, "seekable but unknown start/stop -> disable");
|
||||
dbin->upstream_seekable = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (dbin, "upstream seekable: %d", dbin->upstream_seekable);
|
||||
GST_DEBUG_OBJECT (dbin, "upstream seekable: %d", seekable);
|
||||
return seekable;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2267,10 +2267,6 @@ type_found (GstElement * typefind, guint probability,
|
|||
pad = gst_element_get_static_pad (typefind, "src");
|
||||
sink_pad = gst_element_get_static_pad (typefind, "sink");
|
||||
|
||||
/* if upstream is seekable we can safely set a limit in time to the queues so
|
||||
* that streams at low bitrates can preroll */
|
||||
check_upstream_seekable (decode_bin, sink_pad);
|
||||
|
||||
/* need some lock here to prevent race with shutdown state change
|
||||
* which might yank away e.g. decode_chain while building stuff here.
|
||||
* In typical cases, STREAM_LOCK is held and handles that, it need not
|
||||
|
@ -2404,7 +2400,8 @@ no_more_pads_cb (GstElement * element, GstDecodeChain * chain)
|
|||
* we can probably set its buffering state to playing now */
|
||||
GST_DEBUG_OBJECT (group->dbin, "Setting group %p multiqueue to "
|
||||
"'playing' buffering mode", group);
|
||||
decodebin_set_queue_size (group->dbin, group->multiqueue, FALSE);
|
||||
decodebin_set_queue_size (group->dbin, group->multiqueue, FALSE,
|
||||
(group->parent ? group->parent->seekable : TRUE));
|
||||
CHAIN_MUTEX_UNLOCK (chain);
|
||||
|
||||
EXPOSE_LOCK (chain->dbin);
|
||||
|
@ -2753,6 +2750,12 @@ multi_queue_overrun_cb (GstElement * queue, GstDecodeGroup * group)
|
|||
queue);
|
||||
|
||||
group->overrun = TRUE;
|
||||
/* this group has prerolled enough to not need more pads,
|
||||
* we can probably set its buffering state to playing now */
|
||||
GST_DEBUG_OBJECT (group->dbin, "Setting group %p multiqueue to "
|
||||
"'playing' buffering mode", group);
|
||||
decodebin_set_queue_size (group->dbin, group->multiqueue, FALSE,
|
||||
(group->parent ? group->parent->seekable : TRUE));
|
||||
|
||||
/* FIXME: We should make sure that everything gets exposed now
|
||||
* even if child chains are not complete because the will never
|
||||
|
@ -2858,7 +2861,7 @@ gst_decode_group_hide (GstDecodeGroup * group)
|
|||
* playing or prerolling. */
|
||||
static void
|
||||
decodebin_set_queue_size (GstDecodeBin * dbin, GstElement * multiqueue,
|
||||
gboolean preroll)
|
||||
gboolean preroll, gboolean seekable)
|
||||
{
|
||||
guint max_bytes, max_buffers;
|
||||
guint64 max_time;
|
||||
|
@ -2871,7 +2874,7 @@ decodebin_set_queue_size (GstDecodeBin * dbin, GstElement * multiqueue,
|
|||
if ((max_buffers = dbin->max_size_buffers) == 0)
|
||||
max_buffers = AUTO_PREROLL_SIZE_BUFFERS;
|
||||
if ((max_time = dbin->max_size_time) == 0)
|
||||
max_time = dbin->upstream_seekable ? AUTO_PREROLL_SEEKABLE_SIZE_TIME :
|
||||
max_time = seekable ? AUTO_PREROLL_SEEKABLE_SIZE_TIME :
|
||||
AUTO_PREROLL_NOT_SEEKABLE_SIZE_TIME;
|
||||
} else {
|
||||
/* update runtime limits. At runtime, we try to keep the amount of buffers
|
||||
|
@ -2901,6 +2904,7 @@ gst_decode_group_new (GstDecodeBin * dbin, GstDecodeChain * parent)
|
|||
{
|
||||
GstDecodeGroup *group = g_slice_new0 (GstDecodeGroup);
|
||||
GstElement *mq;
|
||||
gboolean seekable;
|
||||
|
||||
GST_DEBUG_OBJECT (dbin, "Creating new group %p with parent chain %p", group,
|
||||
parent);
|
||||
|
@ -2921,7 +2925,17 @@ gst_decode_group_new (GstDecodeBin * dbin, GstDecodeChain * parent)
|
|||
}
|
||||
|
||||
/* configure queue sizes for preroll */
|
||||
decodebin_set_queue_size (dbin, mq, TRUE);
|
||||
seekable = FALSE;
|
||||
if (parent && parent->demuxer) {
|
||||
GstElement *element =
|
||||
((GstDecodeElement *) parent->elements->data)->element;
|
||||
GstPad *pad = gst_element_get_static_pad (element, "sink");
|
||||
if (pad) {
|
||||
seekable = parent->seekable = check_upstream_seekable (dbin, pad);
|
||||
gst_object_unref (pad);
|
||||
}
|
||||
}
|
||||
decodebin_set_queue_size (dbin, mq, TRUE, seekable);
|
||||
|
||||
group->overrunsig = g_signal_connect (G_OBJECT (mq), "overrun",
|
||||
G_CALLBACK (multi_queue_overrun_cb), group);
|
||||
|
@ -3682,7 +3696,7 @@ gst_decode_chain_expose (GstDecodeChain * chain, GList ** endpads,
|
|||
dbin = group->dbin;
|
||||
|
||||
/* configure queues for playback */
|
||||
decodebin_set_queue_size (dbin, group->multiqueue, FALSE);
|
||||
decodebin_set_queue_size (dbin, group->multiqueue, FALSE, TRUE);
|
||||
|
||||
/* we can now disconnect any overrun signal, which is used to expose the
|
||||
* group. */
|
||||
|
|
|
@ -825,6 +825,8 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
|
|||
*
|
||||
* This signal is emitted when the current uri is about to finish. You can
|
||||
* set the uri and suburi to make sure that playback continues.
|
||||
*
|
||||
* This signal is emitted from the context of a GStreamer streaming thread.
|
||||
*/
|
||||
gst_play_bin_signals[SIGNAL_ABOUT_TO_FINISH] =
|
||||
g_signal_new ("about-to-finish", G_TYPE_FROM_CLASS (klass),
|
||||
|
@ -839,7 +841,12 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
|
|||
* This signal is emitted whenever the number or order of the video
|
||||
* streams has changed. The application will most likely want to select
|
||||
* a new video stream.
|
||||
*
|
||||
* This signal is usually emitted from the context of a GStreamer streaming
|
||||
* thread. You can use gst_message_new_application() and
|
||||
* gst_element_post_message() to notify your application's main thread.
|
||||
*/
|
||||
/* FIXME 0.11: turn video-changed signal into message? */
|
||||
gst_play_bin_signals[SIGNAL_VIDEO_CHANGED] =
|
||||
g_signal_new ("video-changed", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
|
@ -852,7 +859,12 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
|
|||
* This signal is emitted whenever the number or order of the audio
|
||||
* streams has changed. The application will most likely want to select
|
||||
* a new audio stream.
|
||||
*
|
||||
* This signal may be emitted from the context of a GStreamer streaming thread.
|
||||
* You can use gst_message_new_application() and gst_element_post_message()
|
||||
* to notify your application's main thread.
|
||||
*/
|
||||
/* FIXME 0.11: turn audio-changed signal into message? */
|
||||
gst_play_bin_signals[SIGNAL_AUDIO_CHANGED] =
|
||||
g_signal_new ("audio-changed", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
|
@ -865,7 +877,12 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
|
|||
* This signal is emitted whenever the number or order of the text
|
||||
* streams has changed. The application will most likely want to select
|
||||
* a new text stream.
|
||||
*
|
||||
* This signal may be emitted from the context of a GStreamer streaming thread.
|
||||
* You can use gst_message_new_application() and gst_element_post_message()
|
||||
* to notify your application's main thread.
|
||||
*/
|
||||
/* FIXME 0.11: turn text-changed signal into message? */
|
||||
gst_play_bin_signals[SIGNAL_TEXT_CHANGED] =
|
||||
g_signal_new ("text-changed", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
|
@ -880,6 +897,10 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
|
|||
* This signal is emitted whenever the tags of a video stream have changed.
|
||||
* The application will most likely want to get the new tags.
|
||||
*
|
||||
* This signal may be emitted from the context of a GStreamer streaming thread.
|
||||
* You can use gst_message_new_application() and gst_element_post_message()
|
||||
* to notify your application's main thread.
|
||||
*
|
||||
* Since: 0.10.24
|
||||
*/
|
||||
gst_play_bin_signals[SIGNAL_VIDEO_TAGS_CHANGED] =
|
||||
|
@ -896,6 +917,10 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
|
|||
* This signal is emitted whenever the tags of an audio stream have changed.
|
||||
* The application will most likely want to get the new tags.
|
||||
*
|
||||
* This signal may be emitted from the context of a GStreamer streaming thread.
|
||||
* You can use gst_message_new_application() and gst_element_post_message()
|
||||
* to notify your application's main thread.
|
||||
*
|
||||
* Since: 0.10.24
|
||||
*/
|
||||
gst_play_bin_signals[SIGNAL_AUDIO_TAGS_CHANGED] =
|
||||
|
@ -912,6 +937,10 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
|
|||
* This signal is emitted whenever the tags of a text stream have changed.
|
||||
* The application will most likely want to get the new tags.
|
||||
*
|
||||
* This signal may be emitted from the context of a GStreamer streaming thread.
|
||||
* You can use gst_message_new_application() and gst_element_post_message()
|
||||
* to notify your application's main thread.
|
||||
*
|
||||
* Since: 0.10.24
|
||||
*/
|
||||
gst_play_bin_signals[SIGNAL_TEXT_TAGS_CHANGED] =
|
||||
|
@ -931,6 +960,9 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
|
|||
* an audio cd source). This is functionally equivalent to connecting to
|
||||
* the notify::source signal, but more convenient.
|
||||
*
|
||||
* This signal is usually emitted from the context of a GStreamer streaming
|
||||
* thread.
|
||||
*
|
||||
* Since: 0.10.33
|
||||
*/
|
||||
gst_play_bin_signals[SIGNAL_SOURCE_SETUP] =
|
||||
|
|
|
@ -179,12 +179,12 @@ gst_play_sink_audio_convert_class_init (GstPlaySinkAudioConvertClass * klass)
|
|||
g_object_class_install_property (gobject_class, PROP_USE_CONVERTERS,
|
||||
g_param_spec_boolean ("use-converters", "Use converters",
|
||||
"Whether to use conversion elements", FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_USE_VOLUME,
|
||||
g_param_spec_boolean ("use-volume", "Use volume",
|
||||
"Whether to use a volume element", FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
gst_element_class_set_details_simple (gstelement_class,
|
||||
"Player Sink Audio Converter", "Audio/Bin/Converter",
|
||||
|
|
|
@ -137,7 +137,8 @@ gst_play_sink_convert_bin_add_identity (GstPlaySinkConvertBin * self)
|
|||
|
||||
);
|
||||
} else {
|
||||
g_object_set (self->identity, "silent", TRUE, NULL);
|
||||
g_object_set (self->identity, "silent", TRUE, "signal-handoffs", FALSE,
|
||||
NULL);
|
||||
gst_bin_add (GST_BIN_CAST (self), self->identity);
|
||||
}
|
||||
}
|
||||
|
@ -335,11 +336,23 @@ gst_play_sink_convert_bin_sink_setcaps (GstPlaySinkConvertBin * self,
|
|||
|
||||
GST_DEBUG_OBJECT (self, "raw %d, self->raw %d, blocked %d",
|
||||
raw, self->raw, gst_pad_is_blocked (self->sink_proxypad));
|
||||
|
||||
if (raw) {
|
||||
if (!self->raw && !gst_pad_is_blocked (self->sink_proxypad)) {
|
||||
GST_DEBUG_OBJECT (self, "Changing caps from non-raw to raw");
|
||||
reconfigure = TRUE;
|
||||
block_proxypad (self);
|
||||
if (!gst_pad_is_blocked (self->sink_proxypad)) {
|
||||
GstPad *target = gst_ghost_pad_get_target (GST_GHOST_PAD (self->sinkpad));
|
||||
|
||||
if (!self->raw || (target && !gst_pad_query_accept_caps (target, caps))) {
|
||||
if (!self->raw)
|
||||
GST_DEBUG_OBJECT (self, "Changing caps from non-raw to raw");
|
||||
else
|
||||
GST_DEBUG_OBJECT (self, "Changing caps in an incompatible way");
|
||||
|
||||
reconfigure = TRUE;
|
||||
block_proxypad (self);
|
||||
}
|
||||
|
||||
if (target)
|
||||
gst_object_unref (target);
|
||||
}
|
||||
} else {
|
||||
if (self->raw && !gst_pad_is_blocked (self->sink_proxypad)) {
|
||||
|
@ -402,6 +415,22 @@ gst_play_sink_convert_bin_getcaps (GstPad * pad, GstCaps * filter)
|
|||
|
||||
gst_object_unref (self);
|
||||
|
||||
GST_DEBUG_OBJECT (pad, "Returning caps %" GST_PTR_FORMAT, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_play_sink_convert_bin_acceptcaps (GstPad * pad, GstCaps * caps)
|
||||
{
|
||||
GstCaps *allowed_caps;
|
||||
gboolean ret;
|
||||
|
||||
allowed_caps = gst_pad_query_caps (pad, NULL);
|
||||
/* FIXME 0.11: Should be a subset check now */
|
||||
ret = gst_caps_can_intersect (caps, allowed_caps);
|
||||
gst_caps_unref (allowed_caps);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -412,6 +441,16 @@ gst_play_sink_convert_bin_query (GstPad * pad, GstObject * parent,
|
|||
gboolean res = FALSE;
|
||||
|
||||
switch (GST_QUERY_TYPE (query)) {
|
||||
case GST_QUERY_ACCEPT_CAPS:
|
||||
{
|
||||
GstCaps *caps;
|
||||
|
||||
gst_query_parse_accept_caps (query, &caps);
|
||||
gst_query_set_accept_caps_result (query,
|
||||
gst_play_sink_convert_bin_acceptcaps (pad, caps));
|
||||
res = TRUE;
|
||||
break;
|
||||
}
|
||||
case GST_QUERY_CAPS:
|
||||
{
|
||||
GstCaps *filter, *caps;
|
||||
|
|
|
@ -92,18 +92,17 @@ enum
|
|||
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_IN,
|
||||
ARG_OUT,
|
||||
ARG_DUP,
|
||||
ARG_DROP,
|
||||
ARG_SILENT,
|
||||
ARG_NEW_PREF,
|
||||
ARG_SKIP_TO_FIRST,
|
||||
ARG_DROP_ONLY,
|
||||
ARG_AVERAGE_PERIOD,
|
||||
ARG_MAX_RATE
|
||||
/* FILL ME */
|
||||
PROP_0,
|
||||
PROP_IN,
|
||||
PROP_OUT,
|
||||
PROP_DUP,
|
||||
PROP_DROP,
|
||||
PROP_SILENT,
|
||||
PROP_NEW_PREF,
|
||||
PROP_SKIP_TO_FIRST,
|
||||
PROP_DROP_ONLY,
|
||||
PROP_AVERAGE_PERIOD,
|
||||
PROP_MAX_RATE
|
||||
};
|
||||
|
||||
static GstStaticPadTemplate gst_video_rate_src_template =
|
||||
|
@ -172,25 +171,25 @@ gst_video_rate_class_init (GstVideoRateClass * klass)
|
|||
base_class->fixate_caps = GST_DEBUG_FUNCPTR (gst_video_rate_fixate_caps);
|
||||
base_class->query = GST_DEBUG_FUNCPTR (gst_video_rate_query);
|
||||
|
||||
g_object_class_install_property (object_class, ARG_IN,
|
||||
g_object_class_install_property (object_class, PROP_IN,
|
||||
g_param_spec_uint64 ("in", "In",
|
||||
"Number of input frames", 0, G_MAXUINT64, 0,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (object_class, ARG_OUT,
|
||||
g_object_class_install_property (object_class, PROP_OUT,
|
||||
g_param_spec_uint64 ("out", "Out", "Number of output frames", 0,
|
||||
G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
pspec_duplicate = g_param_spec_uint64 ("duplicate", "Duplicate",
|
||||
"Number of duplicated frames", 0, G_MAXUINT64, 0,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
g_object_class_install_property (object_class, ARG_DUP, pspec_duplicate);
|
||||
g_object_class_install_property (object_class, PROP_DUP, pspec_duplicate);
|
||||
pspec_drop = g_param_spec_uint64 ("drop", "Drop", "Number of dropped frames",
|
||||
0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
g_object_class_install_property (object_class, ARG_DROP, pspec_drop);
|
||||
g_object_class_install_property (object_class, ARG_SILENT,
|
||||
g_object_class_install_property (object_class, PROP_DROP, pspec_drop);
|
||||
g_object_class_install_property (object_class, PROP_SILENT,
|
||||
g_param_spec_boolean ("silent", "silent",
|
||||
"Don't emit notify for dropped and duplicated frames", DEFAULT_SILENT,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (object_class, ARG_NEW_PREF,
|
||||
g_object_class_install_property (object_class, PROP_NEW_PREF,
|
||||
g_param_spec_double ("new-pref", "New Pref",
|
||||
"Value indicating how much to prefer new frames (unused)", 0.0, 1.0,
|
||||
DEFAULT_NEW_PREF, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
@ -202,7 +201,7 @@ gst_video_rate_class_init (GstVideoRateClass * klass)
|
|||
*
|
||||
* Since: 0.10.25
|
||||
*/
|
||||
g_object_class_install_property (object_class, ARG_SKIP_TO_FIRST,
|
||||
g_object_class_install_property (object_class, PROP_SKIP_TO_FIRST,
|
||||
g_param_spec_boolean ("skip-to-first", "Skip to first buffer",
|
||||
"Don't produce buffers before the first one we receive",
|
||||
DEFAULT_SKIP_TO_FIRST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
@ -214,7 +213,7 @@ gst_video_rate_class_init (GstVideoRateClass * klass)
|
|||
*
|
||||
* Since: 0.10.36
|
||||
*/
|
||||
g_object_class_install_property (object_class, ARG_DROP_ONLY,
|
||||
g_object_class_install_property (object_class, PROP_DROP_ONLY,
|
||||
g_param_spec_boolean ("drop-only", "Only Drop",
|
||||
"Only drop frames, no duplicates are produced",
|
||||
DEFAULT_DROP_ONLY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
@ -228,7 +227,7 @@ gst_video_rate_class_init (GstVideoRateClass * klass)
|
|||
*
|
||||
* Since: 0.10.36
|
||||
*/
|
||||
g_object_class_install_property (object_class, ARG_AVERAGE_PERIOD,
|
||||
g_object_class_install_property (object_class, PROP_AVERAGE_PERIOD,
|
||||
g_param_spec_uint64 ("average-period", "Period over which to average",
|
||||
"Period over which to average the framerate (in ns) (0 = disabled)",
|
||||
0, G_MAXINT64, DEFAULT_AVERAGE_PERIOD,
|
||||
|
@ -241,7 +240,7 @@ gst_video_rate_class_init (GstVideoRateClass * klass)
|
|||
*
|
||||
* Since: 0.10.36
|
||||
*/
|
||||
g_object_class_install_property (object_class, ARG_MAX_RATE,
|
||||
g_object_class_install_property (object_class, PROP_MAX_RATE,
|
||||
g_param_spec_int ("max-rate", "maximum framerate",
|
||||
"Maximum framerate allowed to pass through "
|
||||
"(in frames per second, implies drop-only)",
|
||||
|
@ -1123,23 +1122,23 @@ gst_video_rate_set_property (GObject * object,
|
|||
|
||||
GST_OBJECT_LOCK (videorate);
|
||||
switch (prop_id) {
|
||||
case ARG_SILENT:
|
||||
case PROP_SILENT:
|
||||
videorate->silent = g_value_get_boolean (value);
|
||||
break;
|
||||
case ARG_NEW_PREF:
|
||||
case PROP_NEW_PREF:
|
||||
videorate->new_pref = g_value_get_double (value);
|
||||
break;
|
||||
case ARG_SKIP_TO_FIRST:
|
||||
case PROP_SKIP_TO_FIRST:
|
||||
videorate->skip_to_first = g_value_get_boolean (value);
|
||||
break;
|
||||
case ARG_DROP_ONLY:
|
||||
case PROP_DROP_ONLY:
|
||||
videorate->drop_only = g_value_get_boolean (value);
|
||||
goto reconfigure;
|
||||
break;
|
||||
case ARG_AVERAGE_PERIOD:
|
||||
case PROP_AVERAGE_PERIOD:
|
||||
videorate->average_period_set = g_value_get_uint64 (value);
|
||||
break;
|
||||
case ARG_MAX_RATE:
|
||||
case PROP_MAX_RATE:
|
||||
g_atomic_int_set (&videorate->max_rate, g_value_get_int (value));
|
||||
goto reconfigure;
|
||||
break;
|
||||
|
@ -1163,34 +1162,34 @@ gst_video_rate_get_property (GObject * object,
|
|||
|
||||
GST_OBJECT_LOCK (videorate);
|
||||
switch (prop_id) {
|
||||
case ARG_IN:
|
||||
case PROP_IN:
|
||||
g_value_set_uint64 (value, videorate->in);
|
||||
break;
|
||||
case ARG_OUT:
|
||||
case PROP_OUT:
|
||||
g_value_set_uint64 (value, videorate->out);
|
||||
break;
|
||||
case ARG_DUP:
|
||||
case PROP_DUP:
|
||||
g_value_set_uint64 (value, videorate->dup);
|
||||
break;
|
||||
case ARG_DROP:
|
||||
case PROP_DROP:
|
||||
g_value_set_uint64 (value, videorate->drop);
|
||||
break;
|
||||
case ARG_SILENT:
|
||||
case PROP_SILENT:
|
||||
g_value_set_boolean (value, videorate->silent);
|
||||
break;
|
||||
case ARG_NEW_PREF:
|
||||
case PROP_NEW_PREF:
|
||||
g_value_set_double (value, videorate->new_pref);
|
||||
break;
|
||||
case ARG_SKIP_TO_FIRST:
|
||||
case PROP_SKIP_TO_FIRST:
|
||||
g_value_set_boolean (value, videorate->skip_to_first);
|
||||
break;
|
||||
case ARG_DROP_ONLY:
|
||||
case PROP_DROP_ONLY:
|
||||
g_value_set_boolean (value, videorate->drop_only);
|
||||
break;
|
||||
case ARG_AVERAGE_PERIOD:
|
||||
case PROP_AVERAGE_PERIOD:
|
||||
g_value_set_uint64 (value, videorate->average_period_set);
|
||||
break;
|
||||
case ARG_MAX_RATE:
|
||||
case PROP_MAX_RATE:
|
||||
g_value_set_int (value, g_atomic_int_get (&videorate->max_rate));
|
||||
break;
|
||||
default:
|
||||
|
|
Loading…
Reference in a new issue