зеркало из https://github.com/mozilla/gecko-dev.git
Bug 966885 - Enable audio level RTP extension. r=jesup, r=ehugg
This commit is contained in:
Родитель
3237cf6f7a
Коммит
db0fba3f67
|
@ -73,8 +73,10 @@ WebrtcAudioConduit::~WebrtcAudioConduit()
|
|||
{
|
||||
delete mRecvCodecList[i];
|
||||
}
|
||||
|
||||
delete mCurSendCodecConfig;
|
||||
if (mPtrVoERTP_RTCP) {
|
||||
mPtrVoERTP_RTCP->Release();
|
||||
}
|
||||
|
||||
// The first one of a pair to be deleted shuts down media for both
|
||||
if(mPtrVoEXmedia)
|
||||
|
@ -278,19 +280,22 @@ MediaConduitErrorCode WebrtcAudioConduit::Init(WebrtcAudioConduit *other)
|
|||
CSFLogError(logTag, "%s Unable to initialize VoEProcessing", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
if(!(mPtrVoEXmedia = VoEExternalMedia::GetInterface(mVoiceEngine)))
|
||||
{
|
||||
CSFLogError(logTag, "%s Unable to initialize VoEExternalMedia", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
if(!(mPtrVoERTP_RTCP = VoERTP_RTCP::GetInterface(mVoiceEngine)))
|
||||
{
|
||||
CSFLogError(logTag, "%s Unable to initialize VoERTP_RTCP", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
if(!(mPtrVoEVideoSync = VoEVideoSync::GetInterface(mVoiceEngine)))
|
||||
{
|
||||
CSFLogError(logTag, "%s Unable to initialize VoEVideoSync", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
if (!(mPtrRTP = webrtc::VoERTP_RTCP::GetInterface(mVoiceEngine)))
|
||||
{
|
||||
CSFLogError(logTag, "%s Unable to get audio RTP/RTCP interface ",
|
||||
|
@ -556,12 +561,24 @@ WebrtcAudioConduit::ConfigureRecvMediaCodecs(
|
|||
CSFLogError(logTag, "%s Starting playout Failed", __FUNCTION__);
|
||||
return kMediaConduitPlayoutError;
|
||||
}
|
||||
|
||||
//we should be good here for setting this.
|
||||
mEngineReceiving = true;
|
||||
DumpCodecDB();
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
MediaConduitErrorCode
|
||||
WebrtcAudioConduit::EnableAudioLevelExtension(bool enabled, uint8_t id)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s %d %d ", __FUNCTION__, enabled, id);
|
||||
|
||||
if (mPtrVoERTP_RTCP->SetRTPAudioLevelIndicationStatus(mChannel, enabled, id) == -1)
|
||||
{
|
||||
CSFLogError(logTag, "%s SetRTPAudioLevelIndicationStatus Failed", __FUNCTION__);
|
||||
return kMediaConduitUnknownError;
|
||||
}
|
||||
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
|
||||
MediaConduitErrorCode
|
||||
WebrtcAudioConduit::SendAudioFrame(const int16_t audio_data[],
|
||||
|
@ -570,7 +587,6 @@ WebrtcAudioConduit::SendAudioFrame(const int16_t audio_data[],
|
|||
int32_t capture_delay)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
|
||||
// Following checks need to be performed
|
||||
// 1. Non null audio buffer pointer,
|
||||
// 2. invalid sampling frequency - less than 0 or unsupported ones
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "webrtc/voice_engine/include/voe_audio_processing.h"
|
||||
#include "webrtc/voice_engine/include/voe_video_sync.h"
|
||||
#include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
|
||||
|
||||
//Some WebRTC types for short notations
|
||||
using webrtc::VoEBase;
|
||||
using webrtc::VoENetwork;
|
||||
|
@ -31,13 +30,11 @@
|
|||
using webrtc::VoEExternalMedia;
|
||||
using webrtc::VoEAudioProcessing;
|
||||
using webrtc::VoEVideoSync;
|
||||
|
||||
using webrtc::VoERTP_RTCP;
|
||||
/** This file hosts several structures identifying different aspects
|
||||
* of a RTP Session.
|
||||
*/
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Helper function
|
||||
|
||||
DOMHighResTimeStamp
|
||||
|
@ -86,13 +83,17 @@ public:
|
|||
*/
|
||||
virtual MediaConduitErrorCode ConfigureRecvMediaCodecs(
|
||||
const std::vector<AudioCodecConfig* >& codecConfigList);
|
||||
/**
|
||||
* Function to enable the audio level extension
|
||||
* @param enabled: enable extension
|
||||
*/
|
||||
virtual MediaConduitErrorCode EnableAudioLevelExtension(bool enabled, uint8_t id);
|
||||
|
||||
/**
|
||||
* Register External Transport to this Conduit. RTP and RTCP frames from the VoiceEngine
|
||||
* shall be passed to the registered transport for transporting externally.
|
||||
*/
|
||||
virtual MediaConduitErrorCode AttachTransport(mozilla::RefPtr<TransportInterface> aTransport);
|
||||
|
||||
/**
|
||||
* Function to deliver externally captured audio sample for encoding and transport
|
||||
* @param audioData [in]: Pointer to array containing a frame of audio
|
||||
|
@ -234,13 +235,12 @@ private:
|
|||
webrtc::VoEExternalMedia* mPtrVoEXmedia;
|
||||
webrtc::VoEAudioProcessing* mPtrVoEProcessing;
|
||||
webrtc::VoEVideoSync* mPtrVoEVideoSync;
|
||||
webrtc::VoERTP_RTCP* mPtrVoERTP_RTCP;
|
||||
webrtc::VoERTP_RTCP* mPtrRTP;
|
||||
|
||||
//engine states of our interets
|
||||
bool mEngineTransmitting; // If true => VoiceEngine Send-subsystem is up
|
||||
bool mEngineReceiving; // If true => VoiceEngine Receive-subsystem is up
|
||||
// and playout is enabled
|
||||
|
||||
// Keep track of each inserted RTP block and the time it was inserted
|
||||
// so we can estimate the clock time for a specific TimeStamp coming out
|
||||
// (for when we send data to MediaStreamTracks). Blocks are aged out as needed.
|
||||
|
|
|
@ -344,16 +344,18 @@ public:
|
|||
*/
|
||||
virtual MediaConduitErrorCode ConfigureRecvMediaCodecs(
|
||||
const std::vector<AudioCodecConfig* >& recvCodecConfigList) = 0;
|
||||
/**
|
||||
* Function to enable the audio level extension
|
||||
* @param enabled: enable extension
|
||||
* @param id: id to be used for this rtp header extension
|
||||
* NOTE: See AudioConduit for more information
|
||||
*/
|
||||
virtual MediaConduitErrorCode EnableAudioLevelExtension(bool enabled, uint8_t id) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -2230,12 +2230,15 @@ static int vcmTxStartICE_m(cc_mcapid_t mcap_id,
|
|||
// and are responsible for cleanly shutting down.
|
||||
mozilla::RefPtr<mozilla::AudioSessionConduit> conduit =
|
||||
mozilla::AudioSessionConduit::Create(static_cast<AudioSessionConduit *>(rx_conduit.get()));
|
||||
|
||||
if (!conduit || conduit->ConfigureSendMediaCodec(config))
|
||||
return VCM_ERROR;
|
||||
CSFLogError(logTag, "Created audio pipeline audio level %d %d",
|
||||
attrs->audio_level, attrs->audio_level_id);
|
||||
|
||||
if (!conduit || conduit->EnableAudioLevelExtension(attrs->audio_level, attrs->audio_level_id))
|
||||
return VCM_ERROR;
|
||||
|
||||
pc.impl()->media()->AddConduit(level, false, conduit);
|
||||
|
||||
mozilla::RefPtr<mozilla::MediaPipeline> pipeline =
|
||||
new mozilla::MediaPipelineTransmit(
|
||||
pc.impl()->GetHandle(),
|
||||
|
|
|
@ -514,17 +514,16 @@ gsmsdp_init_media (fsmdef_media_t *media)
|
|||
media->previous_sdp.num_payloads = 0;
|
||||
media->previous_sdp.tias_bw = SDP_INVALID_VALUE;
|
||||
media->previous_sdp.profile_level = 0;
|
||||
|
||||
media->hold = FSM_HOLD_NONE;
|
||||
media->flags = 0; /* clear all flags */
|
||||
media->cap_index = CC_MAX_MEDIA_CAP; /* max is invalid value */
|
||||
media->video = NULL;
|
||||
media->candidate_ct = 0;
|
||||
media->rtcp_mux = FALSE;
|
||||
|
||||
media->audio_level = TRUE;
|
||||
media->audio_level_id = 1;
|
||||
/* ACTPASS is the value we put in every offer */
|
||||
media->setup = SDP_SETUP_ACTPASS;
|
||||
|
||||
media->local_datachannel_port = 0;
|
||||
media->remote_datachannel_port = 0;
|
||||
media->datachannel_streams = WEBRTC_DATACHANNEL_STREAMS_DEFAULT;
|
||||
|
@ -1702,7 +1701,6 @@ gsmsdp_set_rtcp_fb_ack_attribute (uint16_t level,
|
|||
GSM_ERR_MSG("Failed to add attribute");
|
||||
return;
|
||||
}
|
||||
|
||||
result = sdp_attr_set_rtcp_fb_ack(sdp_p, level, payload_type,
|
||||
a_instance, ack_type);
|
||||
if (result != SDP_SUCCESS) {
|
||||
|
@ -1710,6 +1708,39 @@ gsmsdp_set_rtcp_fb_ack_attribute (uint16_t level,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* gsmsdp_set_audio_level_attribute
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Adds an audio level extension attributesto the specified SDP.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* level - The media level of the SDP where the media attribute exists.
|
||||
* sdp_p - Pointer to the SDP to set the attribute against.
|
||||
*/
|
||||
void
|
||||
gsmsdp_set_extmap_attribute (uint16_t level,
|
||||
void *sdp_p,
|
||||
u16 id,
|
||||
const char* uri)
|
||||
{
|
||||
uint16_t a_instance = 0;
|
||||
sdp_result_e result;
|
||||
|
||||
result = sdp_add_new_attr(sdp_p, level, 0, SDP_ATTR_EXTMAP, &a_instance);
|
||||
if (result != SDP_SUCCESS) {
|
||||
GSM_ERR_MSG("Failed to add attribute");
|
||||
return;
|
||||
}
|
||||
|
||||
result = sdp_attr_set_extmap(sdp_p, level, id, uri, a_instance);
|
||||
if (result != SDP_SUCCESS) {
|
||||
GSM_ERR_MSG("Failed to set attribute");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* gsmsdp_set_rtcp_fb_nack_attribute
|
||||
*
|
||||
|
@ -4629,6 +4660,66 @@ gsmsdp_negotiate_rtcp_fb (cc_sdp_t *cc_sdp_p,
|
|||
}
|
||||
}
|
||||
}
|
||||
return CC_CAUSE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* gsmsdp_negotiate_extmap
|
||||
*
|
||||
* Description:
|
||||
* Negotiates extmaps header extension to local SDP for supported audio codecs
|
||||
*
|
||||
* Parameters:
|
||||
* cc_sdp_p - local and remote SDP
|
||||
* media - The media structure for the current level to be negotiated
|
||||
* offer - True if the remote SDP is an offer
|
||||
*
|
||||
* returns
|
||||
* CC_CAUSE_OK - success
|
||||
* any other code - failure
|
||||
*/
|
||||
cc_causes_t
|
||||
gsmsdp_negotiate_extmap (cc_sdp_t *cc_sdp_p,
|
||||
fsmdef_media_t *media,
|
||||
boolean offer)
|
||||
{
|
||||
boolean audio_level = FALSE;
|
||||
u16 audio_level_id = 0xFFFF;
|
||||
int level = media->level;
|
||||
int i;
|
||||
const char* uri;
|
||||
|
||||
/*
|
||||
* Remove any previously negotiated extmap attributes from the
|
||||
* local SDP
|
||||
*/
|
||||
sdp_result_e result = SDP_SUCCESS;
|
||||
while (result == SDP_SUCCESS) {
|
||||
result = sdp_delete_attr (cc_sdp_p->src_sdp, level, 0,
|
||||
SDP_ATTR_EXTMAP, 1);
|
||||
}
|
||||
|
||||
i = 1;
|
||||
do {
|
||||
uri = sdp_attr_get_extmap_uri(cc_sdp_p->dest_sdp, level, i);
|
||||
|
||||
if (uri != NULL && strcmp(uri, SDP_EXTMAP_AUDIO_LEVEL) == 0) {
|
||||
audio_level = TRUE;
|
||||
audio_level_id = sdp_attr_get_extmap_id(cc_sdp_p->dest_sdp, level, i);
|
||||
}
|
||||
i++;
|
||||
} while (uri != NULL);
|
||||
|
||||
media->audio_level = audio_level;
|
||||
media->audio_level_id = audio_level_id;
|
||||
|
||||
/*
|
||||
* Now, in our local SDP, set extmap types that both we and the
|
||||
* remote party support
|
||||
*/
|
||||
if (media->audio_level) {
|
||||
gsmsdp_set_extmap_attribute (level, cc_sdp_p->src_sdp, audio_level_id, SDP_EXTMAP_AUDIO_LEVEL);
|
||||
}
|
||||
|
||||
return CC_CAUSE_OK;
|
||||
}
|
||||
|
@ -4980,11 +5071,14 @@ gsmsdp_negotiate_media_lines (fsm_fcb_t *fcb_p, cc_sdp_t *sdp_p, boolean initial
|
|||
unsupported_line = TRUE;
|
||||
update_local_ret_value = TRUE;
|
||||
}
|
||||
|
||||
/* Negotiate rtcp feedback mechanisms */
|
||||
if (media && media_type == SDP_MEDIA_VIDEO) {
|
||||
gsmsdp_negotiate_rtcp_fb (dcb_p->sdp, media, offer);
|
||||
}
|
||||
/* Negotiate redundancy mechanisms */
|
||||
if (media && media_type == SDP_MEDIA_AUDIO) {
|
||||
gsmsdp_negotiate_extmap (dcb_p->sdp, media, offer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Negotiate rtcp-mux
|
||||
|
@ -4993,7 +5087,6 @@ gsmsdp_negotiate_media_lines (fsm_fcb_t *fcb_p, cc_sdp_t *sdp_p, boolean initial
|
|||
sdp_res = sdp_attr_get_rtcp_mux_attribute(sdp_p->dest_sdp, i,
|
||||
0, SDP_ATTR_RTCP_MUX,
|
||||
1, &rtcp_mux);
|
||||
|
||||
if (SDP_SUCCESS == sdp_res) {
|
||||
media->rtcp_mux = TRUE;
|
||||
}
|
||||
|
@ -5597,10 +5690,14 @@ gsmsdp_add_media_line (fsmdef_dcb_t *dcb_p, const cc_media_cap_t *media_cap,
|
|||
sdp_rtcp_fb_nack_to_bitmap(SDP_RTCP_FB_NACK_PLI) |
|
||||
sdp_rtcp_fb_ccm_to_bitmap(SDP_RTCP_FB_CCM_FIR));
|
||||
}
|
||||
/* Add supported audio level rtp extension */
|
||||
if (media_cap->type == SDP_MEDIA_AUDIO) {
|
||||
gsmsdp_set_extmap_attribute(level, dcb_p->sdp->src_sdp, 1,
|
||||
SDP_EXTMAP_AUDIO_LEVEL);
|
||||
}
|
||||
|
||||
/* Add a=setup attribute */
|
||||
gsmsdp_set_setup_attribute(level, dcb_p->sdp->src_sdp, media->setup);
|
||||
|
||||
/*
|
||||
* wait until here to set ICE candidates as SDP is now initialized
|
||||
*/
|
||||
|
|
|
@ -201,17 +201,21 @@ typedef struct fsmdef_media_t_ {
|
|||
/* ICE Candidates */
|
||||
char **candidatesp;
|
||||
int candidate_ct;
|
||||
|
||||
/*
|
||||
* rtcp-mux indicates media stream is muxed for RTP and RTCP
|
||||
*/
|
||||
boolean rtcp_mux;
|
||||
/*
|
||||
* Flag to indicate if RTP Header extension for audio level is used
|
||||
* and the id to be used for it
|
||||
*/
|
||||
boolean audio_level;
|
||||
uint8_t audio_level_id;
|
||||
|
||||
/*
|
||||
* The value of the a=setup line
|
||||
*/
|
||||
sdp_setup_type_e setup;
|
||||
|
||||
/*
|
||||
* port number used in m= data channel line
|
||||
*/
|
||||
|
|
|
@ -1230,13 +1230,11 @@ lsm_tx_start (lsm_lcb_t *lcb, const char *fname, fsmdef_media_t *media)
|
|||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
media->xmit_chan = TRUE;
|
||||
|
||||
attrs.mute = FALSE;
|
||||
|
||||
attrs.rtcp_mux = media->rtcp_mux;
|
||||
|
||||
attrs.audio_level = media->audio_level;
|
||||
attrs.audio_level_id = (uint8_t)media->audio_level_id;
|
||||
attrs.is_video = FALSE;
|
||||
attrs.bundle_level = 0;
|
||||
attrs.bundle_stream_correlator = 0;
|
||||
|
|
|
@ -67,15 +67,14 @@
|
|||
#define SDP_SRTP_CONTEXT_SET_ENCRYPT_AUTHENTICATE(cw) \
|
||||
((cw) |= (SDP_SRTP_ENCRYPT_MASK | SDP_SRTP_AUTHENTICATE_MASK | \
|
||||
SDP_SRTCP_ENCRYPT_MASK))
|
||||
|
||||
#define SDP_SRTP_CONTEXT_RESET_SSRC(cw) ((cw) &= ~(SDP_SRTCP_SSRC_MASK))
|
||||
#define SDP_SRTP_CONTEXT_RESET_ROC(cw) ((cw) &= ~(SDP_SRTCP_ROC_MASK))
|
||||
#define SDP_SRTP_CONTEXT_RESET_KDR(cw) ((cw) &= ~(SDP_SRTCP_KDR_MASK))
|
||||
#define SDP_CONTEXT_RESET_MASTER_KEY(cw) ((cw) &= ~(SDP_SRTCP_KEY_MASK))
|
||||
#define SDP_CONTEXT_RESET_MASTER_SALT(cw) ((cw) &= ~(SDP_SRTCP_SALT_MASK))
|
||||
#define SDP_EXTMAP_AUDIO_LEVEL "urn:ietf:params:rtp-hdrext:ssrc-audio-level"
|
||||
|
||||
/* SDP Enum Types */
|
||||
|
||||
typedef enum {
|
||||
SDP_DEBUG_TRACE,
|
||||
SDP_DEBUG_WARNINGS,
|
||||
|
@ -892,6 +891,16 @@ typedef struct sdp_media_profiles {
|
|||
sdp_payload_ind_e payload_indicator[SDP_MAX_PROFILES][SDP_MAX_PAYLOAD_TYPES];
|
||||
u16 payload_type[SDP_MAX_PROFILES][SDP_MAX_PAYLOAD_TYPES];
|
||||
} sdp_media_profiles_t;
|
||||
/*
|
||||
* a=extmap:<value>["/"<direction>] <URI> <extensionattributes>
|
||||
*
|
||||
*/
|
||||
typedef struct sdp_extmap {
|
||||
u16 id;
|
||||
sdp_direction_e media_direction;
|
||||
char uri[SDP_MAX_STRING_LEN+1];
|
||||
char extension_attributes[SDP_MAX_STRING_LEN+1];
|
||||
} sdp_extmap_t;
|
||||
|
||||
|
||||
/*
|
||||
|
@ -899,7 +908,6 @@ typedef struct sdp_media_profiles {
|
|||
* This type is used to hold cryptographic context information.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct sdp_srtp_crypto_context_t_ {
|
||||
int32 tag;
|
||||
unsigned long selection_flags;
|
||||
|
@ -982,10 +990,10 @@ typedef struct sdp_attr {
|
|||
sdp_fmtp_fb_t rtcp_fb;
|
||||
sdp_setup_type_e setup;
|
||||
sdp_connection_type_e connection;
|
||||
sdp_extmap_t extmap;
|
||||
} attr;
|
||||
struct sdp_attr *next_p;
|
||||
} sdp_attr_t;
|
||||
|
||||
typedef struct sdp_srtp_crypto_suite_list_ {
|
||||
sdp_srtp_crypto_suite_t crypto_suite_val;
|
||||
char * crypto_suite_str;
|
||||
|
@ -2099,9 +2107,16 @@ sdp_attr_set_rtcp_fb_nack(void *sdp_ptr, u16 level, u16 payload_type, u16 inst,
|
|||
sdp_result_e
|
||||
sdp_attr_set_rtcp_fb_trr_int(void *sdp_ptr, u16 level, u16 payload_type,
|
||||
u16 inst, u32 interval);
|
||||
|
||||
sdp_result_e
|
||||
sdp_attr_set_rtcp_fb_ccm(void *sdp_ptr, u16 level, u16 payload_type, u16 inst,
|
||||
sdp_rtcp_fb_ccm_type_e);
|
||||
const char *
|
||||
sdp_attr_get_extmap_uri(void *sdp_ptr, u16 level, u16 inst);
|
||||
|
||||
u16
|
||||
sdp_attr_get_extmap_id(void *sdp_ptr, u16 level, u16 inst);
|
||||
|
||||
sdp_result_e
|
||||
sdp_attr_set_extmap(void *sdp_ptr, u16 level, u16 id, const char* uri, u16 inst);
|
||||
|
||||
#endif /* _SDP_H_ */
|
||||
|
|
|
@ -5145,6 +5145,79 @@ sdp_result_e sdp_parse_attr_connection(sdp_t *sdp_p,
|
|||
return SDP_FAILURE;
|
||||
break;
|
||||
}
|
||||
return SDP_SUCCESS;
|
||||
}
|
||||
|
||||
sdp_result_e sdp_build_attr_extmap(sdp_t *sdp_p,
|
||||
sdp_attr_t *attr_p,
|
||||
flex_string *fs)
|
||||
{
|
||||
flex_string_sprintf(fs, "a=extmap:%d %s\r\n",
|
||||
attr_p->attr.extmap.id,
|
||||
attr_p->attr.extmap.uri);
|
||||
|
||||
return SDP_SUCCESS;
|
||||
}
|
||||
|
||||
sdp_result_e sdp_parse_attr_extmap(sdp_t *sdp_p,
|
||||
sdp_attr_t *attr_p,
|
||||
const char *ptr)
|
||||
{
|
||||
sdp_result_e result;
|
||||
|
||||
attr_p->attr.extmap.id = 0;
|
||||
attr_p->attr.extmap.media_direction = SDP_DIRECTION_SENDRECV;
|
||||
attr_p->attr.extmap.uri[0] = '\0';
|
||||
attr_p->attr.extmap.extension_attributes[0] = '\0';
|
||||
|
||||
/* Find the payload type number. */
|
||||
attr_p->attr.extmap.id =
|
||||
(u16)sdp_getnextnumtok(ptr, &ptr, "/ \t", &result);
|
||||
if (result != SDP_SUCCESS) {
|
||||
sdp_parse_error(sdp_p->peerconnection,
|
||||
"%s Warning: Invalid extmap id specified for %s attribute.",
|
||||
sdp_p->debug_str, sdp_get_attr_name(attr_p->type));
|
||||
sdp_p->conf_p->num_invalid_param++;
|
||||
return (SDP_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
if (*ptr == '/') {
|
||||
char direction[SDP_MAX_STRING_LEN+1];
|
||||
/* Find the encoding name. */
|
||||
ptr = sdp_getnextstrtok(ptr, direction,
|
||||
sizeof(direction), " \t", &result);
|
||||
if (result != SDP_SUCCESS) {
|
||||
sdp_parse_error(sdp_p->peerconnection,
|
||||
"%s Warning: No uri specified in %s attribute.",
|
||||
sdp_p->debug_str, sdp_get_attr_name(attr_p->type));
|
||||
sdp_p->conf_p->num_invalid_param++;
|
||||
return (SDP_INVALID_PARAMETER);
|
||||
}
|
||||
}
|
||||
|
||||
ptr = sdp_getnextstrtok(ptr, attr_p->attr.extmap.uri,
|
||||
sizeof(attr_p->attr.extmap.uri), " \t", &result);
|
||||
if (result != SDP_SUCCESS) {
|
||||
sdp_parse_error(sdp_p->peerconnection,
|
||||
"%s Warning: No uri specified in %s attribute.",
|
||||
sdp_p->debug_str, sdp_get_attr_name(attr_p->type));
|
||||
sdp_p->conf_p->num_invalid_param++;
|
||||
return (SDP_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
ptr = sdp_getnextstrtok(ptr, attr_p->attr.extmap.extension_attributes,
|
||||
sizeof(attr_p->attr.extmap.extension_attributes), "\r\n", &result);
|
||||
|
||||
if (sdp_p->debug_flag[SDP_DEBUG_TRACE]) {
|
||||
SDP_PRINT("%s Parsed a=%s, id %u, direction %s, "
|
||||
"uri %s, extension %s", sdp_p->debug_str,
|
||||
sdp_get_attr_name(attr_p->type),
|
||||
attr_p->attr.extmap.id,
|
||||
SDP_DIRECTION_PRINT(attr_p->attr.extmap.media_direction),
|
||||
attr_p->attr.extmap.uri,
|
||||
attr_p->attr.extmap.extension_attributes);
|
||||
}
|
||||
|
||||
return (SDP_SUCCESS);
|
||||
}
|
||||
|
||||
|
|
|
@ -12477,10 +12477,112 @@ sdp_attr_set_rtcp_fb_ccm(void *sdp_ptr, u16 level, u16 payload_type, u16 inst,
|
|||
sdp_p->conf_p->num_invalid_param++;
|
||||
return (SDP_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
attr_p->attr.rtcp_fb.payload_num = payload_type;
|
||||
attr_p->attr.rtcp_fb.feedback_type = SDP_RTCP_FB_CCM;
|
||||
attr_p->attr.rtcp_fb.param.ccm = type;
|
||||
attr_p->attr.rtcp_fb.extra[0] = '\0';
|
||||
return (SDP_SUCCESS);
|
||||
}
|
||||
|
||||
/* Function: sdp_attr_get_extmap_uri
|
||||
* Description: Returns a pointer to the value of the encoding name
|
||||
* parameter specified for the given attribute. Value is
|
||||
* returned as a const ptr and so cannot be modified by the
|
||||
* application. If the given attribute is not defined, NULL
|
||||
* will be returned.
|
||||
* Parameters: sdp_ptr The SDP handle returned by sdp_init_description.
|
||||
* level The level to check for the attribute.
|
||||
* inst_num The attribute instance number to check.
|
||||
* Returns: Codec value or SDP_CODEC_INVALID.
|
||||
*/
|
||||
const char *sdp_attr_get_extmap_uri(void *sdp_ptr, u16 level,
|
||||
u16 inst_num)
|
||||
{
|
||||
sdp_t *sdp_p = (sdp_t *)sdp_ptr;
|
||||
sdp_attr_t *attr_p;
|
||||
|
||||
if (sdp_verify_sdp_ptr(sdp_p) == FALSE) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
attr_p = sdp_find_attr(sdp_p, level, 0, SDP_ATTR_EXTMAP, inst_num);
|
||||
if (attr_p == NULL) {
|
||||
if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
|
||||
CSFLogError(logTag, "%s extmap attribute, level %u instance %u "
|
||||
"not found.", sdp_p->debug_str, level, inst_num);
|
||||
}
|
||||
sdp_p->conf_p->num_invalid_param++;
|
||||
return (NULL);
|
||||
} else {
|
||||
return (attr_p->attr.extmap.uri);
|
||||
}
|
||||
}
|
||||
|
||||
/* Function: sdp_attr_get_extmap_id
|
||||
* Description: Returns the id of the extmap specified for the given
|
||||
* attribute. If the given attribute is not defined, 0xFFFF
|
||||
* will be returned.
|
||||
* Parameters: sdp_ptr The SDP handle returned by sdp_init_description.
|
||||
* level The level to check for the attribute.
|
||||
* inst_num The attribute instance number to check.
|
||||
* Returns: The id of the extmap attribute.
|
||||
*/
|
||||
u16 sdp_attr_get_extmap_id(void *sdp_ptr, u16 level,
|
||||
u16 inst_num)
|
||||
{
|
||||
sdp_t *sdp_p = (sdp_t *)sdp_ptr;
|
||||
sdp_attr_t *attr_p;
|
||||
|
||||
if (sdp_verify_sdp_ptr(sdp_p) == FALSE) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
attr_p = sdp_find_attr(sdp_p, level, 0, SDP_ATTR_EXTMAP, inst_num);
|
||||
if (attr_p == NULL) {
|
||||
if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
|
||||
CSFLogError(logTag, "%s extmap attribute, level %u instance %u "
|
||||
"not found.", sdp_p->debug_str, level, inst_num);
|
||||
}
|
||||
sdp_p->conf_p->num_invalid_param++;
|
||||
return 0xFFFF;
|
||||
} else {
|
||||
return (attr_p->attr.extmap.id);
|
||||
}
|
||||
}
|
||||
|
||||
/* Function: sdp_attr_set_extmap
|
||||
* Description: Sets the value of an rtcp-fb:...ccm attribute
|
||||
* Parameters: sdp_ptr The SDP handle returned by sdp_init_description.
|
||||
* level The level to set the attribute.
|
||||
* id The id to set the attribute.
|
||||
* uri The uri to set the attribute.
|
||||
* inst The attribute instance number to check.
|
||||
* Returns: SDP_SUCCESS Attribute param was set successfully.
|
||||
* SDP_INVALID_PARAMETER Specified attribute is not defined.
|
||||
*/
|
||||
sdp_result_e
|
||||
sdp_attr_set_extmap(void *sdp_ptr, u16 level, u16 id, const char* uri, u16 inst)
|
||||
{
|
||||
sdp_t *sdp_p = (sdp_t *)sdp_ptr;
|
||||
sdp_attr_t *attr_p;
|
||||
|
||||
if (!sdp_verify_sdp_ptr(sdp_p)) {
|
||||
return (SDP_INVALID_SDP_PTR);
|
||||
}
|
||||
|
||||
attr_p = sdp_find_attr(sdp_p, level, 0, SDP_ATTR_EXTMAP, inst);
|
||||
if (!attr_p) {
|
||||
if (sdp_p->debug_flag[SDP_DEBUG_ERRORS]) {
|
||||
CSFLogError(logTag, "%s extmap attribute, level %u "
|
||||
"instance %u not found.", sdp_p->debug_str, level,
|
||||
inst);
|
||||
}
|
||||
sdp_p->conf_p->num_invalid_param++;
|
||||
return (SDP_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
attr_p->attr.extmap.id = id;
|
||||
sstrncpy(attr_p->attr.extmap.uri, uri, SDP_MAX_STRING_LEN+1);
|
||||
return (SDP_SUCCESS);
|
||||
}
|
||||
|
||||
|
|
|
@ -176,8 +176,9 @@ const sdp_attrarray_t sdp_attr[SDP_MAX_ATTR_TYPES] =
|
|||
sdp_parse_attr_setup, sdp_build_attr_setup},
|
||||
{"connection", sizeof("connection"),
|
||||
sdp_parse_attr_connection, sdp_build_attr_connection},
|
||||
{"extmap", sizeof("extmap"),
|
||||
sdp_parse_attr_extmap, sdp_build_attr_extmap},
|
||||
};
|
||||
|
||||
/* Note: These *must* be in the same order as the enum types. */
|
||||
const sdp_namearray_t sdp_media[SDP_MAX_MEDIA_TYPES] =
|
||||
{
|
||||
|
|
|
@ -167,11 +167,16 @@ extern sdp_result_e sdp_parse_attr_connection(sdp_t *sdp_p,
|
|||
extern sdp_result_e sdp_build_attr_connection(sdp_t *sdp_p,
|
||||
sdp_attr_t *attr_p,
|
||||
flex_string *fs);
|
||||
extern sdp_result_e sdp_parse_attr_extmap(sdp_t *sdp_p,
|
||||
sdp_attr_t *attr_p,
|
||||
const char *ptr);
|
||||
extern sdp_result_e sdp_build_attr_extmap(sdp_t *sdp_p,
|
||||
sdp_attr_t *attr_p,
|
||||
flex_string *fs);
|
||||
extern sdp_result_e sdp_parse_attr_mptime(
|
||||
sdp_t *sdp_p, sdp_attr_t *attr_p, const char *ptr);
|
||||
extern sdp_result_e sdp_build_attr_mptime(
|
||||
sdp_t *sdp_p, sdp_attr_t *attr_p, flex_string *fs);
|
||||
|
||||
extern sdp_result_e sdp_parse_attr_x_sidin(
|
||||
sdp_t *sdp_p, sdp_attr_t *attr_p, const char *ptr);
|
||||
extern sdp_result_e sdp_build_attr_x_sidin(
|
||||
|
|
|
@ -246,10 +246,10 @@ typedef enum {
|
|||
SDP_ATTR_RTCP_FB, /* RFC 4585 */
|
||||
SDP_ATTR_SETUP,
|
||||
SDP_ATTR_CONNECTION,
|
||||
SDP_ATTR_EXTMAP, /* RFC 5285 */
|
||||
SDP_MAX_ATTR_TYPES,
|
||||
SDP_ATTR_INVALID
|
||||
} sdp_attr_e;
|
||||
|
||||
/* This is here so that it can be used in the VcmSIPCCBinding interface */
|
||||
typedef enum {
|
||||
SDP_SETUP_NOT_FOUND = -1,
|
||||
|
|
|
@ -338,6 +338,8 @@ typedef struct vcm_attrs_t_ {
|
|||
cc_boolean mute;
|
||||
cc_boolean is_video;
|
||||
cc_boolean rtcp_mux;
|
||||
cc_boolean audio_level;
|
||||
uint8_t audio_level_id;
|
||||
vcm_audioAttrs_t audio; /**< audio line attribs */
|
||||
vcm_videoAttrs_t video; /**< Video Atrribs */
|
||||
uint32_t bundle_level; /**< Where bundle transport info lives, if any */
|
||||
|
|
|
@ -191,6 +191,14 @@ class SdpTest : public ::testing::Test {
|
|||
type), SDP_SUCCESS);
|
||||
return inst_num;
|
||||
}
|
||||
u16 AddNewExtMap(int level, const char* uri) {
|
||||
u16 inst_num = 0;
|
||||
EXPECT_EQ(sdp_add_new_attr(sdp_ptr_, level, 0, SDP_ATTR_EXTMAP,
|
||||
&inst_num), SDP_SUCCESS);
|
||||
EXPECT_EQ(sdp_attr_set_extmap(sdp_ptr_, level, inst_num,
|
||||
uri, inst_num), SDP_SUCCESS);
|
||||
return inst_num;
|
||||
}
|
||||
|
||||
u16 AddNewFmtpMaxFs(int level, u32 max_fs) {
|
||||
u16 inst_num = 0;
|
||||
|
@ -725,6 +733,23 @@ TEST_F(SdpTest, parseRtcpFbAllPayloads) {
|
|||
SDP_RTCP_FB_ACK_RPSI);
|
||||
}
|
||||
}
|
||||
TEST_F(SdpTest, addExtMap) {
|
||||
InitLocalSdp();
|
||||
int level = AddNewMedia(SDP_MEDIA_VIDEO);
|
||||
AddNewExtMap(level, SDP_EXTMAP_AUDIO_LEVEL);
|
||||
std::string body = SerializeSdp();
|
||||
ASSERT_NE(body.find("a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n"), std::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(SdpTest, parseExtMap) {
|
||||
ParseSdp(kVideoSdp +
|
||||
"a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n");
|
||||
ASSERT_STREQ(sdp_attr_get_extmap_uri(sdp_ptr_, 1, 1),
|
||||
SDP_EXTMAP_AUDIO_LEVEL);
|
||||
ASSERT_EQ(sdp_attr_get_extmap_id(sdp_ptr_, 1, 1),
|
||||
1);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(SdpTest, parseFmtpMaxFs) {
|
||||
u32 val = 0;
|
||||
|
@ -732,7 +757,6 @@ TEST_F(SdpTest, parseFmtpMaxFs) {
|
|||
ASSERT_EQ(sdp_attr_get_fmtp_max_fs(sdp_ptr_, 1, 0, 1, &val), SDP_SUCCESS);
|
||||
ASSERT_EQ(val, 300);
|
||||
}
|
||||
|
||||
TEST_F(SdpTest, parseFmtpMaxFr) {
|
||||
u32 val = 0;
|
||||
ParseSdp(kVideoSdp + "a=fmtp:120 max-fs=300;max-fr=30\r\n");
|
||||
|
|
Загрузка…
Ссылка в новой задаче