mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-24 02:31:03 +00:00
Merge branch 'master' into 0.11
Conflicts: gst/audioparsers/gstamrparse.c gst/isomp4/qtdemux.c
This commit is contained in:
commit
33f18b8ea4
10 changed files with 160 additions and 21 deletions
|
@ -1370,7 +1370,7 @@ gst_soup_http_src_do_seek (GstBaseSrc * bsrc, GstSegment * segment)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (segment->rate != 1.0 || segment->format != GST_FORMAT_BYTES) {
|
||||
if (segment->rate < 0.0 || segment->format != GST_FORMAT_BYTES) {
|
||||
GST_WARNING_OBJECT (src, "Invalid seek segment");
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -296,12 +296,28 @@ gst_amr_parse_check_valid_frame (GstBaseParse * parse,
|
|||
* to contain a valid header as well (and there is enough data to
|
||||
* perform this check)
|
||||
*/
|
||||
if (fsize &&
|
||||
(!GST_BASE_PARSE_LOST_SYNC (parse) || GST_BASE_PARSE_DRAINING (parse)
|
||||
|| (dsize > fsize && (data[fsize] & 0x83) == 0))) {
|
||||
*framesize = fsize;
|
||||
ret = TRUE;
|
||||
goto done;
|
||||
if (fsize) {
|
||||
gboolean found = FALSE;
|
||||
|
||||
/* in sync, no further check */
|
||||
if (!GST_BASE_PARSE_LOST_SYNC (parse)) {
|
||||
found = TRUE;
|
||||
} else if (dsize > fsize) {
|
||||
/* enough data, check for next sync */
|
||||
if ((data[fsize] & 0x83) == 0)
|
||||
found = TRUE;
|
||||
} else if (GST_BASE_PARSE_DRAINING (parse)) {
|
||||
/* not enough, but draining, so ok */
|
||||
found = TRUE;
|
||||
} else {
|
||||
/* indicate we need not skip, but need more data */
|
||||
*skipsize = 0;
|
||||
*framesize = fsize + 1;
|
||||
}
|
||||
if (found) {
|
||||
*framesize = fsize;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
GST_LOG ("sync lost");
|
||||
|
|
|
@ -318,7 +318,7 @@ struct _QtDemuxStream
|
|||
guint32 stts_samples;
|
||||
guint32 n_sample_times;
|
||||
guint32 stts_sample_index;
|
||||
guint32 stts_time;
|
||||
guint64 stts_time;
|
||||
guint32 stts_duration;
|
||||
/* stss */
|
||||
gboolean stss_present;
|
||||
|
@ -1311,7 +1311,10 @@ gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment)
|
|||
GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (desired_offset));
|
||||
|
||||
if (segment->flags & GST_SEEK_FLAG_KEY_UNIT) {
|
||||
/* may not have enough fragmented info to do this adjustment,
|
||||
* and we can't scan (and probably should not) at this time with
|
||||
* possibly flushing upstream */
|
||||
if ((segment->flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
|
||||
gint64 min_offset;
|
||||
|
||||
gst_qtdemux_adjust_seek (qtdemux, desired_offset, &min_offset, NULL);
|
||||
|
@ -1864,6 +1867,8 @@ gst_qtdemux_change_state (GstElement * element, GstStateChange transition)
|
|||
gst_segment_init (&qtdemux->segment, GST_FORMAT_TIME);
|
||||
qtdemux->requested_seek_time = GST_CLOCK_TIME_NONE;
|
||||
qtdemux->seek_offset = 0;
|
||||
qtdemux->upstream_seekable = FALSE;
|
||||
qtdemux->upstream_size = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -2103,6 +2108,14 @@ qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
|
|||
stream->track_id, d_sample_duration, d_sample_size, d_sample_flags,
|
||||
*base_offset);
|
||||
|
||||
/* presence of stss or not can't really tell us much,
|
||||
* and flags and so on tend to be marginally reliable in these files */
|
||||
if (stream->subtype == FOURCC_soun) {
|
||||
GST_DEBUG_OBJECT (qtdemux,
|
||||
"sound track in fragmented file; marking all keyframes");
|
||||
stream->all_keyframe = TRUE;
|
||||
}
|
||||
|
||||
if (!gst_byte_reader_skip (trun, 1) ||
|
||||
!gst_byte_reader_get_uint24_be (trun, &flags))
|
||||
goto fail;
|
||||
|
@ -3971,6 +3984,47 @@ qtdemux_seek_offset (GstQTDemux * demux, guint64 offset)
|
|||
return res;
|
||||
}
|
||||
|
||||
/* check for seekable upstream, above and beyond a mere query */
|
||||
static void
|
||||
gst_qtdemux_check_seekability (GstQTDemux * demux)
|
||||
{
|
||||
GstQuery *query;
|
||||
gboolean seekable = FALSE;
|
||||
gint64 start = -1, stop = -1;
|
||||
|
||||
if (demux->upstream_size)
|
||||
return;
|
||||
|
||||
query = gst_query_new_seeking (GST_FORMAT_BYTES);
|
||||
if (!gst_pad_peer_query (demux->sinkpad, query)) {
|
||||
GST_DEBUG_OBJECT (demux, "seeking query failed");
|
||||
goto done;
|
||||
}
|
||||
|
||||
gst_query_parse_seeking (query, NULL, &seekable, &start, &stop);
|
||||
|
||||
/* try harder to query upstream size if we didn't get it the first time */
|
||||
if (seekable && stop == -1) {
|
||||
GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
|
||||
gst_pad_query_peer_duration (demux->sinkpad, 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 (seekable && (start != 0 || stop <= start)) {
|
||||
GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
|
||||
seekable = FALSE;
|
||||
}
|
||||
|
||||
done:
|
||||
gst_query_unref (query);
|
||||
|
||||
GST_DEBUG_OBJECT (demux, "seekable: %d (%" G_GUINT64_FORMAT " - %"
|
||||
G_GUINT64_FORMAT ")", seekable, start, stop);
|
||||
demux->upstream_seekable = seekable;
|
||||
demux->upstream_size = seekable ? stop : -1;
|
||||
}
|
||||
|
||||
/* FIXME, unverified after edit list updates */
|
||||
static GstFlowReturn
|
||||
gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
|
||||
|
@ -4002,6 +4056,8 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
|
|||
guint32 fourcc;
|
||||
guint64 size;
|
||||
|
||||
gst_qtdemux_check_seekability (demux);
|
||||
|
||||
data = gst_adapter_map (demux->adapter, demux->neededbytes);
|
||||
|
||||
/* get fourcc/length, set neededbytes */
|
||||
|
@ -4040,7 +4096,15 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
|
|||
target = old + size;
|
||||
|
||||
/* try to jump over the atom with a seek */
|
||||
res = qtdemux_seek_offset (demux, target);
|
||||
/* only bother if it seems worth doing so,
|
||||
* and avoids possible upstream/server problems */
|
||||
if (demux->upstream_seekable &&
|
||||
demux->upstream_size > 4 * (1 << 20)) {
|
||||
res = qtdemux_seek_offset (demux, target);
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (demux, "skipping seek");
|
||||
res = FALSE;
|
||||
}
|
||||
|
||||
if (res) {
|
||||
GST_DEBUG_OBJECT (demux, "seek success");
|
||||
|
@ -4058,7 +4122,7 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
|
|||
} else {
|
||||
/* seek failed, need to buffer */
|
||||
demux->offset = old;
|
||||
GST_DEBUG_OBJECT (demux, "seek failed");
|
||||
GST_DEBUG_OBJECT (demux, "seek failed/skipped");
|
||||
/* there may be multiple mdat (or alike) buffers */
|
||||
/* sanity check */
|
||||
if (demux->mdatbuffer)
|
||||
|
@ -4153,6 +4217,7 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
|
|||
* put preceding buffered data ahead of current moov data.
|
||||
* This should also handle evil mdat, moov, mdat cases and alike */
|
||||
gst_adapter_clear (demux->adapter);
|
||||
gst_adapter_push (demux->adapter, demux->mdatbuffer);
|
||||
demux->mdatbuffer = NULL;
|
||||
demux->offset = demux->mdatoffset;
|
||||
demux->neededbytes = next_entry_size (demux);
|
||||
|
@ -5640,8 +5705,8 @@ done2:
|
|||
|
||||
for (i = stream->stts_index; i < n_sample_times; i++) {
|
||||
guint32 stts_samples;
|
||||
guint32 stts_duration;
|
||||
guint32 stts_time;
|
||||
gint32 stts_duration;
|
||||
gint64 stts_time;
|
||||
|
||||
if (stream->stts_sample_index >= stream->stts_samples
|
||||
|| !stream->stts_sample_index) {
|
||||
|
@ -5671,7 +5736,9 @@ done2:
|
|||
cur->timestamp = stts_time;
|
||||
cur->duration = stts_duration;
|
||||
|
||||
stts_time += stts_duration;
|
||||
/* avoid 32-bit wrap-around,
|
||||
* but still mind possible 'negative' duration */
|
||||
stts_time += (gint64) stts_duration;
|
||||
cur++;
|
||||
|
||||
if (G_UNLIKELY (cur > last)) {
|
||||
|
|
|
@ -108,6 +108,9 @@ struct _GstQTDemux {
|
|||
|
||||
gint64 requested_seek_time;
|
||||
guint64 seek_offset;
|
||||
|
||||
gboolean upstream_seekable;
|
||||
gboolean upstream_size;
|
||||
};
|
||||
|
||||
struct _GstQTDemuxClass {
|
||||
|
|
|
@ -157,9 +157,32 @@ static gboolean
|
|||
gst_rtp_h263p_pay_setcaps (GstBaseRTPPayload * payload, GstCaps * caps)
|
||||
{
|
||||
gboolean res;
|
||||
GstCaps *peercaps;
|
||||
gchar *encoding_name = NULL;
|
||||
|
||||
gst_basertppayload_set_options (payload, "video", TRUE, "H263-1998", 90000);
|
||||
g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
|
||||
|
||||
peercaps =
|
||||
gst_pad_peer_get_caps (GST_BASE_RTP_PAYLOAD_SRCPAD (payload), NULL);
|
||||
if (peercaps) {
|
||||
GstCaps *intersect = gst_caps_intersect (peercaps,
|
||||
gst_pad_get_pad_template_caps (GST_BASE_RTP_PAYLOAD_SRCPAD (payload)));
|
||||
|
||||
gst_caps_unref (peercaps);
|
||||
if (!gst_caps_is_empty (intersect)) {
|
||||
GstStructure *s = gst_caps_get_structure (intersect, 0);
|
||||
encoding_name = g_strdup (gst_structure_get_string (s, "encoding-name"));
|
||||
}
|
||||
gst_caps_unref (intersect);
|
||||
}
|
||||
|
||||
if (!encoding_name)
|
||||
encoding_name = g_strdup ("H263-1998");
|
||||
|
||||
gst_basertppayload_set_options (payload, "video", TRUE,
|
||||
(gchar *) encoding_name, 90000);
|
||||
res = gst_basertppayload_set_outcaps (payload, NULL);
|
||||
g_free (encoding_name);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -567,6 +567,7 @@ rtp_session_init (RTPSession * sess)
|
|||
DEFAULT_RTCP_IMMEDIATE_FEEDBACK_THRESHOLD;
|
||||
|
||||
sess->rtcp_pli_requests = g_array_new (FALSE, FALSE, sizeof (guint32));
|
||||
sess->last_keyframe_request = GST_CLOCK_TIME_NONE;
|
||||
|
||||
GST_DEBUG ("%p: session using SSRC: %08x", sess, sess->source->ssrc);
|
||||
}
|
||||
|
|
|
@ -173,6 +173,7 @@ gst_rtsp_src_buffer_mode_get_type (void)
|
|||
#define DEFAULT_USER_PW NULL
|
||||
#define DEFAULT_BUFFER_MODE BUFFER_MODE_AUTO
|
||||
#define DEFAULT_PORT_RANGE NULL
|
||||
#define DEFAULT_SHORT_HEADER FALSE
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -194,6 +195,7 @@ enum
|
|||
PROP_BUFFER_MODE,
|
||||
PROP_PORT_RANGE,
|
||||
PROP_UDP_BUFFER_SIZE,
|
||||
PROP_SHORT_HEADER,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
|
@ -444,6 +446,18 @@ gst_rtspsrc_class_init (GstRTSPSrcClass * klass)
|
|||
0, G_MAXINT, DEFAULT_UDP_BUFFER_SIZE,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* GstRTSPSrc::short-header:
|
||||
*
|
||||
* Only send the basic RTSP headers for broken encoders.
|
||||
*
|
||||
* Since: 0.10.31
|
||||
*/
|
||||
g_object_class_install_property (gobject_class, PROP_SHORT_HEADER,
|
||||
g_param_spec_boolean ("short-header", "Short Header",
|
||||
"Only send the basic RTSP headers for broken encoders",
|
||||
DEFAULT_SHORT_HEADER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
gstelement_class->send_event = gst_rtspsrc_send_event;
|
||||
gstelement_class->change_state = gst_rtspsrc_change_state;
|
||||
|
||||
|
@ -492,6 +506,7 @@ gst_rtspsrc_init (GstRTSPSrc * src)
|
|||
src->client_port_range.min = 0;
|
||||
src->client_port_range.max = 0;
|
||||
src->udp_buffer_size = DEFAULT_UDP_BUFFER_SIZE;
|
||||
src->short_header = DEFAULT_SHORT_HEADER;
|
||||
|
||||
/* get a list of all extensions */
|
||||
src->extensions = gst_rtsp_ext_list_get ();
|
||||
|
@ -685,6 +700,9 @@ gst_rtspsrc_set_property (GObject * object, guint prop_id, const GValue * value,
|
|||
case PROP_UDP_BUFFER_SIZE:
|
||||
rtspsrc->udp_buffer_size = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_SHORT_HEADER:
|
||||
rtspsrc->short_header = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -777,6 +795,9 @@ gst_rtspsrc_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
case PROP_UDP_BUFFER_SIZE:
|
||||
g_value_set_int (value, rtspsrc->udp_buffer_size);
|
||||
break;
|
||||
case PROP_SHORT_HEADER:
|
||||
g_value_set_boolean (value, rtspsrc->short_header);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -4399,7 +4420,8 @@ gst_rtspsrc_try_send (GstRTSPSrc * src, GstRTSPConnection * conn,
|
|||
gint try = 0;
|
||||
|
||||
again:
|
||||
gst_rtsp_ext_list_before_send (src->extensions, request);
|
||||
if (!src->short_header)
|
||||
gst_rtsp_ext_list_before_send (src->extensions, request);
|
||||
|
||||
GST_DEBUG_OBJECT (src, "sending message");
|
||||
|
||||
|
|
|
@ -214,6 +214,7 @@ struct _GstRTSPSrc {
|
|||
gint buffer_mode;
|
||||
GstRTSPRange client_port_range;
|
||||
gint udp_buffer_size;
|
||||
gboolean short_header;
|
||||
|
||||
/* state */
|
||||
GstRTSPState state;
|
||||
|
|
|
@ -174,7 +174,8 @@ gst_multiudpsink_class_init (GstMultiUDPSinkClass * klass)
|
|||
* of destinations.
|
||||
*/
|
||||
gst_multiudpsink_signals[SIGNAL_ADD] =
|
||||
g_signal_new ("add", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
g_signal_new ("add", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
|
||||
G_STRUCT_OFFSET (GstMultiUDPSinkClass, add),
|
||||
NULL, NULL, gst_udp_marshal_VOID__STRING_INT, G_TYPE_NONE, 2,
|
||||
G_TYPE_STRING, G_TYPE_INT);
|
||||
|
@ -188,7 +189,8 @@ gst_multiudpsink_class_init (GstMultiUDPSinkClass * klass)
|
|||
* clients.
|
||||
*/
|
||||
gst_multiudpsink_signals[SIGNAL_REMOVE] =
|
||||
g_signal_new ("remove", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
g_signal_new ("remove", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
|
||||
G_STRUCT_OFFSET (GstMultiUDPSinkClass, remove),
|
||||
NULL, NULL, gst_udp_marshal_VOID__STRING_INT, G_TYPE_NONE, 2,
|
||||
G_TYPE_STRING, G_TYPE_INT);
|
||||
|
@ -199,7 +201,8 @@ gst_multiudpsink_class_init (GstMultiUDPSinkClass * klass)
|
|||
* Clear the list of clients.
|
||||
*/
|
||||
gst_multiudpsink_signals[SIGNAL_CLEAR] =
|
||||
g_signal_new ("clear", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
g_signal_new ("clear", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
|
||||
G_STRUCT_OFFSET (GstMultiUDPSinkClass, clear),
|
||||
NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
|
||||
/**
|
||||
|
@ -214,7 +217,8 @@ gst_multiudpsink_class_init (GstMultiUDPSinkClass * klass)
|
|||
* connect_time (in epoch seconds), disconnect_time (in epoch seconds)
|
||||
*/
|
||||
gst_multiudpsink_signals[SIGNAL_GET_STATS] =
|
||||
g_signal_new ("get-stats", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
g_signal_new ("get-stats", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
|
||||
G_STRUCT_OFFSET (GstMultiUDPSinkClass, get_stats),
|
||||
NULL, NULL, gst_udp_marshal_BOXED__STRING_INT, G_TYPE_VALUE_ARRAY, 2,
|
||||
G_TYPE_STRING, G_TYPE_INT);
|
||||
|
|
|
@ -339,7 +339,9 @@ gst_parser_test_drain_garbage (guint8 * data, guint size, guint8 * garbage,
|
|||
{
|
||||
GstParserTest ptest;
|
||||
|
||||
gst_parser_test_init (&ptest, data, size, 1);
|
||||
/* provide enough initial frames since it may take some parsers some
|
||||
* time to be convinced of proper sync */
|
||||
gst_parser_test_init (&ptest, data, size, 10);
|
||||
ptest.series[1].data = garbage;
|
||||
ptest.series[1].size = gsize;
|
||||
ptest.series[1].num = 1;
|
||||
|
|
Loading…
Reference in a new issue