mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-27 01:28:34 +00:00
Merge branch 'master' into 0.11
Conflicts: ext/speex/gstspeexenc.c gst/rtpmanager/rtpsession.c
This commit is contained in:
commit
07cc855b24
9 changed files with 231 additions and 72 deletions
|
@ -462,6 +462,8 @@ gst_flac_enc_stop (GstAudioEncoder * enc)
|
||||||
g_list_free (flacenc->headers);
|
g_list_free (flacenc->headers);
|
||||||
flacenc->headers = NULL;
|
flacenc->headers = NULL;
|
||||||
|
|
||||||
|
gst_tag_setter_reset_tags (GST_TAG_SETTER (enc));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -270,6 +270,8 @@ gst_speex_enc_stop (GstAudioEncoder * benc)
|
||||||
g_slist_foreach (enc->headers, (GFunc) gst_buffer_unref, NULL);
|
g_slist_foreach (enc->headers, (GFunc) gst_buffer_unref, NULL);
|
||||||
enc->headers = NULL;
|
enc->headers = NULL;
|
||||||
|
|
||||||
|
gst_tag_setter_reset_tags (GST_TAG_SETTER (enc));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,7 +532,7 @@ gst_speex_enc_encode (GstSpeexEnc * enc, GstBuffer * buf)
|
||||||
gint frame_size = enc->frame_size;
|
gint frame_size = enc->frame_size;
|
||||||
gint bytes = frame_size * 2 * enc->channels, samples;
|
gint bytes = frame_size * 2 * enc->channels, samples;
|
||||||
gint outsize, written, dtx_ret = 0;
|
gint outsize, written, dtx_ret = 0;
|
||||||
guint8 *data, *bdata, *outdata;
|
guint8 *data, *data0 = NULL, *bdata, *outdata;
|
||||||
gsize bsize, size;
|
gsize bsize, size;
|
||||||
GstBuffer *outbuf;
|
GstBuffer *outbuf;
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
@ -542,7 +544,7 @@ gst_speex_enc_encode (GstSpeexEnc * enc, GstBuffer * buf)
|
||||||
GST_DEBUG_OBJECT (enc, "draining; adding silence samples");
|
GST_DEBUG_OBJECT (enc, "draining; adding silence samples");
|
||||||
|
|
||||||
size = ((bsize / bytes) + 1) * bytes;
|
size = ((bsize / bytes) + 1) * bytes;
|
||||||
data = g_malloc0 (size);
|
data0 = data = g_malloc0 (size);
|
||||||
memcpy (data, bdata, bsize);
|
memcpy (data, bdata, bsize);
|
||||||
gst_buffer_unmap (buf, bdata, bsize);
|
gst_buffer_unmap (buf, bdata, bsize);
|
||||||
bdata = NULL;
|
bdata = NULL;
|
||||||
|
@ -606,6 +608,7 @@ gst_speex_enc_encode (GstSpeexEnc * enc, GstBuffer * buf)
|
||||||
outbuf, samples);
|
outbuf, samples);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
g_free (data0);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -394,6 +394,8 @@ gst_flac_parse_frame_header_is_valid (GstFlacParse * flacparse,
|
||||||
|
|
||||||
/* 0 == fixed block size, 1 == variable block size */
|
/* 0 == fixed block size, 1 == variable block size */
|
||||||
blocking_strategy = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1);
|
blocking_strategy = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1);
|
||||||
|
if (flacparse->force_variable_block_size)
|
||||||
|
blocking_strategy = 1;
|
||||||
|
|
||||||
/* block size index, calculation of the real blocksize below */
|
/* block size index, calculation of the real blocksize below */
|
||||||
block_size = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
|
block_size = gst_bit_reader_get_bits_uint16_unchecked (&reader, 4);
|
||||||
|
@ -527,6 +529,16 @@ gst_flac_parse_frame_header_is_valid (GstFlacParse * flacparse,
|
||||||
if (actual_crc != expected_crc)
|
if (actual_crc != expected_crc)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
/* Sanity check sample number against blocking strategy, as it seems
|
||||||
|
some files claim fixed block size but supply sample numbers,
|
||||||
|
rather than block numbers. */
|
||||||
|
if (set && blocking_strategy == 0 && block_size == sample_number) {
|
||||||
|
GST_WARNING_OBJECT (flacparse, "This file claims fixed block size, "
|
||||||
|
"but seems to be lying: assuming variable block size");
|
||||||
|
flacparse->force_variable_block_size = TRUE;
|
||||||
|
blocking_strategy = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The FLAC format documentation says:
|
The FLAC format documentation says:
|
||||||
The "blocking strategy" bit determines how to calculate the sample number
|
The "blocking strategy" bit determines how to calculate the sample number
|
||||||
|
|
|
@ -79,6 +79,8 @@ struct _GstFlacParse {
|
||||||
|
|
||||||
GList *headers;
|
GList *headers;
|
||||||
GstBuffer *seektable;
|
GstBuffer *seektable;
|
||||||
|
|
||||||
|
gboolean force_variable_block_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstFlacParseClass {
|
struct _GstFlacParseClass {
|
||||||
|
|
|
@ -1375,30 +1375,34 @@ gst_rtp_session_event_recv_rtp_sink (GstPad * pad, GstObject * parent,
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_rtp_session_request_remote_key_unit (GstRtpSession * rtpsession,
|
gst_rtp_session_request_remote_key_unit (GstRtpSession * rtpsession,
|
||||||
guint32 ssrc, guint payload, gboolean all_headers)
|
guint32 ssrc, guint payload, gboolean all_headers, gint count)
|
||||||
{
|
{
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
gboolean requested = FALSE;
|
|
||||||
|
|
||||||
caps = gst_rtp_session_get_caps_for_pt (rtpsession, payload);
|
caps = gst_rtp_session_get_caps_for_pt (rtpsession, payload);
|
||||||
|
|
||||||
if (caps) {
|
if (caps) {
|
||||||
const GstStructure *s = gst_caps_get_structure (caps, 0);
|
const GstStructure *s = gst_caps_get_structure (caps, 0);
|
||||||
gboolean pli;
|
gboolean pli;
|
||||||
|
gboolean fir;
|
||||||
|
|
||||||
pli = gst_structure_has_field (s, "rtcp-fb-nack-pli");
|
pli = gst_structure_has_field (s, "rtcp-fb-nack-pli");
|
||||||
|
fir = gst_structure_has_field (s, "rtcp-fb-ccm-fir") && all_headers;
|
||||||
|
|
||||||
|
/* Google Talk uses FIR for repair, so send it even if we just want a
|
||||||
|
* regular PLI */
|
||||||
|
if (!pli &&
|
||||||
|
gst_structure_has_field (s, "rtcp-fb-x-gstreamer-fir-as-repair"))
|
||||||
|
fir = TRUE;
|
||||||
|
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
|
|
||||||
if (pli) {
|
if (pli || fir)
|
||||||
rtp_session_request_key_unit (rtpsession->priv->session, ssrc);
|
return rtp_session_request_key_unit (rtpsession->priv->session, ssrc,
|
||||||
rtp_session_request_early_rtcp (rtpsession->priv->session,
|
gst_clock_get_time (rtpsession->priv->sysclock), fir, count);
|
||||||
gst_clock_get_time (rtpsession->priv->sysclock), 200 * GST_MSECOND);
|
|
||||||
requested = TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return requested;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -1421,10 +1425,13 @@ gst_rtp_session_event_recv_rtp_src (GstPad * pad, GstObject * parent,
|
||||||
gst_structure_get_uint (s, "ssrc", &ssrc) &&
|
gst_structure_get_uint (s, "ssrc", &ssrc) &&
|
||||||
gst_structure_get_uint (s, "payload", &pt)) {
|
gst_structure_get_uint (s, "payload", &pt)) {
|
||||||
gboolean all_headers = FALSE;
|
gboolean all_headers = FALSE;
|
||||||
|
gint count = -1;
|
||||||
|
|
||||||
gst_structure_get_boolean (s, "all-headers", &all_headers);
|
gst_structure_get_boolean (s, "all-headers", &all_headers);
|
||||||
|
if (gst_structure_get_int (s, "count", &count) && count < 0)
|
||||||
|
count += G_MAXINT; /* Make sure count is positive if present */
|
||||||
if (gst_rtp_session_request_remote_key_unit (rtpsession, ssrc, pt,
|
if (gst_rtp_session_request_remote_key_unit (rtpsession, ssrc, pt,
|
||||||
all_headers))
|
all_headers, count))
|
||||||
forward = FALSE;
|
forward = FALSE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -567,7 +567,6 @@ rtp_session_init (RTPSession * sess)
|
||||||
sess->rtcp_immediate_feedback_threshold =
|
sess->rtcp_immediate_feedback_threshold =
|
||||||
DEFAULT_RTCP_IMMEDIATE_FEEDBACK_THRESHOLD;
|
DEFAULT_RTCP_IMMEDIATE_FEEDBACK_THRESHOLD;
|
||||||
|
|
||||||
sess->rtcp_pli_requests = g_array_new (FALSE, FALSE, sizeof (guint32));
|
|
||||||
sess->last_keyframe_request = GST_CLOCK_TIME_NONE;
|
sess->last_keyframe_request = GST_CLOCK_TIME_NONE;
|
||||||
|
|
||||||
GST_DEBUG ("%p: session using SSRC: %08x", sess, sess->source->ssrc);
|
GST_DEBUG ("%p: session using SSRC: %08x", sess, sess->source->ssrc);
|
||||||
|
@ -590,8 +589,6 @@ rtp_session_finalize (GObject * object)
|
||||||
g_hash_table_destroy (sess->cnames);
|
g_hash_table_destroy (sess->cnames);
|
||||||
g_object_unref (sess->source);
|
g_object_unref (sess->source);
|
||||||
|
|
||||||
g_array_free (sess->rtcp_pli_requests, TRUE);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (rtp_session_parent_class)->finalize (object);
|
G_OBJECT_CLASS (rtp_session_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2169,45 +2166,112 @@ rtp_session_process_app (RTPSession * sess, GstRTCPPacket * packet,
|
||||||
GST_DEBUG ("received APP");
|
GST_DEBUG ("received APP");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
rtp_session_request_local_key_unit (RTPSession * sess, RTPSource * src,
|
||||||
|
gboolean fir, GstClockTime current_time)
|
||||||
|
{
|
||||||
|
guint32 round_trip = 0;
|
||||||
|
|
||||||
|
rtp_source_get_last_rb (src, NULL, NULL, NULL, NULL, NULL, NULL, &round_trip);
|
||||||
|
|
||||||
|
if (sess->last_keyframe_request != GST_CLOCK_TIME_NONE && round_trip) {
|
||||||
|
GstClockTime round_trip_in_ns = gst_util_uint64_scale (round_trip,
|
||||||
|
GST_SECOND, 65536);
|
||||||
|
|
||||||
|
if (sess->last_keyframe_request != GST_CLOCK_TIME_NONE &&
|
||||||
|
current_time - sess->last_keyframe_request < 2 * round_trip_in_ns) {
|
||||||
|
GST_DEBUG ("Ignoring %s request because one was send without one "
|
||||||
|
"RTT (%" GST_TIME_FORMAT " < %" GST_TIME_FORMAT ")",
|
||||||
|
fir ? "FIR" : "PLI",
|
||||||
|
GST_TIME_ARGS (current_time - sess->last_keyframe_request),
|
||||||
|
GST_TIME_ARGS (round_trip_in_ns));;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sess->last_keyframe_request = current_time;
|
||||||
|
|
||||||
|
GST_LOG ("received %s request from %X %p(%p)", fir ? "FIR" : "PLI",
|
||||||
|
rtp_source_get_ssrc (src), sess->callbacks.process_rtp,
|
||||||
|
sess->callbacks.request_key_unit);
|
||||||
|
|
||||||
|
RTP_SESSION_UNLOCK (sess);
|
||||||
|
sess->callbacks.request_key_unit (sess, fir,
|
||||||
|
sess->request_key_unit_user_data);
|
||||||
|
RTP_SESSION_LOCK (sess);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rtp_session_process_pli (RTPSession * sess, guint32 sender_ssrc,
|
rtp_session_process_pli (RTPSession * sess, guint32 sender_ssrc,
|
||||||
guint32 media_ssrc, GstClockTime current_time)
|
guint32 media_ssrc, GstClockTime current_time)
|
||||||
{
|
{
|
||||||
RTPSource *src;
|
RTPSource *src;
|
||||||
guint32 round_trip = 0;
|
|
||||||
|
|
||||||
if (!sess->callbacks.request_key_unit)
|
if (!sess->callbacks.request_key_unit)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
src = g_hash_table_lookup (sess->ssrcs[sess->mask_idx],
|
src = g_hash_table_lookup (sess->ssrcs[sess->mask_idx],
|
||||||
GINT_TO_POINTER (sender_ssrc));
|
GINT_TO_POINTER (sender_ssrc));
|
||||||
|
if (!src)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rtp_session_request_local_key_unit (sess, src, FALSE, current_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rtp_session_process_fir (RTPSession * sess, guint32 sender_ssrc,
|
||||||
|
guint8 * fci_data, guint fci_length, GstClockTime current_time)
|
||||||
|
{
|
||||||
|
RTPSource *src;
|
||||||
|
guint32 ssrc;
|
||||||
|
guint position = 0;
|
||||||
|
gboolean our_request = FALSE;
|
||||||
|
|
||||||
|
if (!sess->callbacks.request_key_unit)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (fci_length < 8)
|
||||||
|
return;
|
||||||
|
|
||||||
|
src = g_hash_table_lookup (sess->ssrcs[sess->mask_idx],
|
||||||
|
GINT_TO_POINTER (sender_ssrc));
|
||||||
|
|
||||||
|
/* Hack because Google fails to set the sender_ssrc correctly */
|
||||||
|
if (!src && sender_ssrc == 1) {
|
||||||
|
GHashTableIter iter;
|
||||||
|
|
||||||
|
if (sess->stats.sender_sources >
|
||||||
|
RTP_SOURCE_IS_SENDER (sess->source) ? 2 : 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, sess->ssrcs[sess->mask_idx]);
|
||||||
|
|
||||||
|
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) & src)) {
|
||||||
|
if (src != sess->source && rtp_source_is_sender (src))
|
||||||
|
break;
|
||||||
|
src = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!src)
|
if (!src)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (sess->last_keyframe_request != GST_CLOCK_TIME_NONE &&
|
for (position = 0; position < fci_length; position += 8) {
|
||||||
rtp_source_get_last_rb (src, NULL, NULL, NULL, NULL, NULL, NULL,
|
guint8 *data = fci_data + position;
|
||||||
&round_trip)) {
|
|
||||||
GstClockTime round_trip_in_ns = gst_util_uint64_scale (round_trip,
|
|
||||||
GST_SECOND, 65536);
|
|
||||||
|
|
||||||
if (sess->last_keyframe_request != GST_CLOCK_TIME_NONE &&
|
ssrc = GST_READ_UINT32_BE (data);
|
||||||
current_time - sess->last_keyframe_request < round_trip_in_ns) {
|
|
||||||
GST_DEBUG ("Ignoring PLI because one was send without one RTT (%"
|
if (ssrc == rtp_source_get_ssrc (sess->source)) {
|
||||||
GST_TIME_FORMAT " < %" GST_TIME_FORMAT ")",
|
our_request = TRUE;
|
||||||
GST_TIME_ARGS (current_time - sess->last_keyframe_request),
|
break;
|
||||||
GST_TIME_ARGS (round_trip_in_ns));;
|
}
|
||||||
|
}
|
||||||
|
if (!our_request)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sess->last_keyframe_request = current_time;
|
rtp_session_request_local_key_unit (sess, src, TRUE, current_time);
|
||||||
|
|
||||||
GST_LOG ("received PLI from %X %p(%p)", sender_ssrc,
|
|
||||||
sess->callbacks.process_rtp, sess->callbacks.request_key_unit);
|
|
||||||
|
|
||||||
sess->callbacks.request_key_unit (sess, FALSE,
|
|
||||||
sess->request_key_unit_user_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2251,7 +2315,9 @@ rtp_session_process_feedback (RTPSession * sess, GstRTCPPacket * packet,
|
||||||
rtp_source_retain_rtcp_packet (src, packet, arrival->running_time);
|
rtp_source_retain_rtcp_packet (src, packet, arrival->running_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rtp_source_get_ssrc (sess->source) == media_ssrc) {
|
if (rtp_source_get_ssrc (sess->source) == media_ssrc ||
|
||||||
|
/* PSFB FIR puts the media ssrc inside the FCI */
|
||||||
|
(type == GST_RTCP_TYPE_PSFB && fbtype == GST_RTCP_PSFB_TYPE_FIR)) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case GST_RTCP_TYPE_PSFB:
|
case GST_RTCP_TYPE_PSFB:
|
||||||
switch (fbtype) {
|
switch (fbtype) {
|
||||||
|
@ -2259,6 +2325,10 @@ rtp_session_process_feedback (RTPSession * sess, GstRTCPPacket * packet,
|
||||||
rtp_session_process_pli (sess, sender_ssrc, media_ssrc,
|
rtp_session_process_pli (sess, sender_ssrc, media_ssrc,
|
||||||
current_time);
|
current_time);
|
||||||
break;
|
break;
|
||||||
|
case GST_RTCP_PSFB_TYPE_FIR:
|
||||||
|
rtp_session_process_fir (sess, sender_ssrc, fci_data, fci_length,
|
||||||
|
current_time);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3262,19 +3332,32 @@ rtp_session_request_early_rtcp (RTPSession * sess, GstClockTime current_time,
|
||||||
dont_send:
|
dont_send:
|
||||||
|
|
||||||
RTP_SESSION_UNLOCK (sess);
|
RTP_SESSION_UNLOCK (sess);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
gboolean
|
||||||
rtp_session_request_key_unit (RTPSession * sess, guint32 ssrc)
|
rtp_session_request_key_unit (RTPSession * sess, guint32 ssrc, GstClockTime now,
|
||||||
|
gboolean fir, gint count)
|
||||||
{
|
{
|
||||||
guint i;
|
RTPSource *src = g_hash_table_lookup (sess->ssrcs[sess->mask_idx],
|
||||||
|
GUINT_TO_POINTER (ssrc));
|
||||||
|
|
||||||
for (i = 0; i < sess->rtcp_pli_requests->len; i++)
|
if (!src)
|
||||||
if (ssrc == g_array_index (sess->rtcp_pli_requests, guint32, i))
|
return FALSE;
|
||||||
return;
|
|
||||||
|
|
||||||
g_array_append_val (sess->rtcp_pli_requests, ssrc);
|
if (fir) {
|
||||||
|
src->send_pli = FALSE;
|
||||||
|
src->send_fir = TRUE;
|
||||||
|
|
||||||
|
if (count == -1 || count != src->last_fir_count)
|
||||||
|
src->current_send_fir_seqnum++;
|
||||||
|
src->last_fir_count = count;
|
||||||
|
} else if (!src->send_fir) {
|
||||||
|
src->send_pli = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtp_session_request_early_rtcp (sess, now, 200 * GST_MSECOND);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -3302,38 +3385,77 @@ rtp_session_on_sending_rtcp (RTPSession * sess, GstBuffer * buffer,
|
||||||
gboolean early)
|
gboolean early)
|
||||||
{
|
{
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
|
GHashTableIter iter;
|
||||||
|
gpointer key, value;
|
||||||
|
gboolean started_fir = FALSE;
|
||||||
|
GstRTCPPacket fir_rtcppacket;
|
||||||
|
GstRTCPBuffer rtcp;
|
||||||
|
|
||||||
RTP_SESSION_LOCK (sess);
|
RTP_SESSION_LOCK (sess);
|
||||||
|
|
||||||
while (sess->rtcp_pli_requests->len) {
|
|
||||||
GstRTCPPacket rtcppacket;
|
|
||||||
guint media_ssrc = g_array_index (sess->rtcp_pli_requests, guint32, 0);
|
|
||||||
RTPSource *media_src = g_hash_table_lookup (sess->ssrcs[sess->mask_idx],
|
|
||||||
GUINT_TO_POINTER (media_ssrc));
|
|
||||||
|
|
||||||
if (media_src && !rtp_source_has_retained (media_src,
|
|
||||||
has_pli_compare_func, NULL)) {
|
|
||||||
GstRTCPBuffer rtcp;
|
|
||||||
|
|
||||||
gst_rtcp_buffer_map (buffer, GST_MAP_WRITE, &rtcp);
|
gst_rtcp_buffer_map (buffer, GST_MAP_WRITE, &rtcp);
|
||||||
if (gst_rtcp_buffer_add_packet (&rtcp, GST_RTCP_TYPE_PSFB, &rtcppacket)) {
|
|
||||||
gst_rtcp_packet_fb_set_type (&rtcppacket, GST_RTCP_PSFB_TYPE_PLI);
|
g_hash_table_iter_init (&iter, sess->ssrcs[sess->mask_idx]);
|
||||||
gst_rtcp_packet_fb_set_sender_ssrc (&rtcppacket,
|
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
||||||
|
guint media_ssrc = GPOINTER_TO_UINT (key);
|
||||||
|
RTPSource *media_src = value;
|
||||||
|
guint8 *fci_data;
|
||||||
|
|
||||||
|
if (media_src->send_fir) {
|
||||||
|
if (!started_fir) {
|
||||||
|
if (!gst_rtcp_buffer_add_packet (&rtcp, GST_RTCP_TYPE_PSFB,
|
||||||
|
&fir_rtcppacket))
|
||||||
|
break;
|
||||||
|
gst_rtcp_packet_fb_set_type (&fir_rtcppacket, GST_RTCP_PSFB_TYPE_FIR);
|
||||||
|
gst_rtcp_packet_fb_set_sender_ssrc (&fir_rtcppacket,
|
||||||
rtp_source_get_ssrc (sess->source));
|
rtp_source_get_ssrc (sess->source));
|
||||||
gst_rtcp_packet_fb_set_media_ssrc (&rtcppacket, media_ssrc);
|
gst_rtcp_packet_fb_set_media_ssrc (&fir_rtcppacket, 0);
|
||||||
ret = TRUE;
|
|
||||||
gst_rtcp_buffer_unmap (&rtcp);
|
if (!gst_rtcp_packet_fb_set_fci_length (&fir_rtcppacket, 2)) {
|
||||||
} else {
|
gst_rtcp_packet_remove (&fir_rtcppacket);
|
||||||
/* Break because the packet is full, will put next request in a
|
|
||||||
* further packet
|
|
||||||
*/
|
|
||||||
gst_rtcp_buffer_unmap (&rtcp);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
ret = TRUE;
|
||||||
|
started_fir = TRUE;
|
||||||
|
} else {
|
||||||
|
if (!gst_rtcp_packet_fb_set_fci_length (&fir_rtcppacket,
|
||||||
|
!gst_rtcp_packet_fb_get_fci_length (&fir_rtcppacket) + 2))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_array_remove_index (sess->rtcp_pli_requests, 0);
|
fci_data = gst_rtcp_packet_fb_get_fci (&fir_rtcppacket) -
|
||||||
|
((gst_rtcp_packet_fb_get_fci_length (&fir_rtcppacket) - 2) * 4);
|
||||||
|
|
||||||
|
GST_WRITE_UINT32_BE (fci_data, media_ssrc);
|
||||||
|
fci_data += 4;
|
||||||
|
fci_data[0] = media_src->current_send_fir_seqnum;
|
||||||
|
fci_data[1] = fci_data[2] = fci_data[3] = 0;
|
||||||
|
media_src->send_fir = FALSE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, sess->ssrcs[sess->mask_idx]);
|
||||||
|
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
||||||
|
guint media_ssrc = GPOINTER_TO_UINT (key);
|
||||||
|
RTPSource *media_src = value;
|
||||||
|
GstRTCPPacket pli_rtcppacket;
|
||||||
|
|
||||||
|
if (media_src->send_pli && !rtp_source_has_retained (media_src,
|
||||||
|
has_pli_compare_func, NULL)) {
|
||||||
|
if (!gst_rtcp_buffer_add_packet (&rtcp, GST_RTCP_TYPE_PSFB,
|
||||||
|
&pli_rtcppacket))
|
||||||
|
/* Break because the packet is full, will put next request in a
|
||||||
|
* further packet */
|
||||||
|
break;
|
||||||
|
gst_rtcp_packet_fb_set_type (&pli_rtcppacket, GST_RTCP_PSFB_TYPE_PLI);
|
||||||
|
gst_rtcp_packet_fb_set_sender_ssrc (&pli_rtcppacket,
|
||||||
|
rtp_source_get_ssrc (sess->source));
|
||||||
|
gst_rtcp_packet_fb_set_media_ssrc (&pli_rtcppacket, media_ssrc);
|
||||||
|
ret = TRUE;
|
||||||
|
}
|
||||||
|
media_src->send_pli = FALSE;
|
||||||
|
}
|
||||||
|
gst_rtcp_buffer_unmap (&rtcp);
|
||||||
|
|
||||||
RTP_SESSION_UNLOCK (sess);
|
RTP_SESSION_UNLOCK (sess);
|
||||||
|
|
||||||
|
|
|
@ -234,8 +234,8 @@ struct _RTPSession {
|
||||||
GstClockTime rtcp_feedback_retention_window;
|
GstClockTime rtcp_feedback_retention_window;
|
||||||
guint rtcp_immediate_feedback_threshold;
|
guint rtcp_immediate_feedback_threshold;
|
||||||
|
|
||||||
GArray *rtcp_pli_requests;
|
|
||||||
GstClockTime last_keyframe_request;
|
GstClockTime last_keyframe_request;
|
||||||
|
gboolean last_keyframe_all_headers;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -348,7 +348,10 @@ void rtp_session_request_early_rtcp (RTPSession * sess, GstClockT
|
||||||
GstClockTimeDiff max_delay);
|
GstClockTimeDiff max_delay);
|
||||||
|
|
||||||
/* Notify session of a request for a new key unit */
|
/* Notify session of a request for a new key unit */
|
||||||
void rtp_session_request_key_unit (RTPSession * sess,
|
gboolean rtp_session_request_key_unit (RTPSession * sess,
|
||||||
guint32 ssrc);
|
guint32 ssrc,
|
||||||
|
GstClockTime now,
|
||||||
|
gboolean fir,
|
||||||
|
gint count);
|
||||||
|
|
||||||
#endif /* __RTP_SESSION_H__ */
|
#endif /* __RTP_SESSION_H__ */
|
||||||
|
|
|
@ -172,6 +172,11 @@ struct _RTPSource {
|
||||||
GList *conflicting_addresses;
|
GList *conflicting_addresses;
|
||||||
|
|
||||||
GQueue *retained_feedback;
|
GQueue *retained_feedback;
|
||||||
|
|
||||||
|
gboolean send_pli;
|
||||||
|
gboolean send_fir;
|
||||||
|
guint8 current_send_fir_seqnum;
|
||||||
|
gint last_fir_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _RTPSourceClass {
|
struct _RTPSourceClass {
|
||||||
|
|
|
@ -1729,7 +1729,8 @@ return_data:
|
||||||
s = gst_structure_copy (template);
|
s = gst_structure_copy (template);
|
||||||
gst_structure_set (s, "width", G_TYPE_INT, (gint) width,
|
gst_structure_set (s, "width", G_TYPE_INT, (gint) width,
|
||||||
"height", G_TYPE_INT, (gint) height,
|
"height", G_TYPE_INT, (gint) height,
|
||||||
"interlaced", G_TYPE_BOOLEAN, interlaced, NULL);
|
"interlaced", G_TYPE_BOOLEAN, interlaced,
|
||||||
|
"pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL);
|
||||||
|
|
||||||
if (G_IS_VALUE (&rates)) {
|
if (G_IS_VALUE (&rates)) {
|
||||||
/* only change the framerate on the template when we have a valid probed new
|
/* only change the framerate on the template when we have a valid probed new
|
||||||
|
@ -1990,6 +1991,8 @@ default_frame_sizes:
|
||||||
gst_structure_set (tmp, "height", GST_TYPE_INT_RANGE, min_h, max_h, NULL);
|
gst_structure_set (tmp, "height", GST_TYPE_INT_RANGE, min_h, max_h, NULL);
|
||||||
|
|
||||||
gst_structure_set (tmp, "interlaced", G_TYPE_BOOLEAN, interlaced, NULL);
|
gst_structure_set (tmp, "interlaced", G_TYPE_BOOLEAN, interlaced, NULL);
|
||||||
|
gst_structure_set (tmp, "pixel-aspect-ratio",
|
||||||
|
GST_TYPE_FRACTION, 1, 1, NULL);
|
||||||
|
|
||||||
gst_caps_append_structure (ret, tmp);
|
gst_caps_append_structure (ret, tmp);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue