Bug 966885 - Enable audio level RTP extension. r=jesup, r=ehugg

This commit is contained in:
Gustavo Garcia 2014-02-07 15:33:01 -05:00
Родитель 3237cf6f7a
Коммит db0fba3f67
15 изменённых файлов: 384 добавлений и 42 удалений

Просмотреть файл

@ -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");