Bug 1022008: Hook up SDP negotiation for H.264 GMP codecs r=ehugg

This commit is contained in:
Randell Jesup 2014-07-08 15:28:56 -04:00
Родитель 39e8e6e97c
Коммит cf095091a1
9 изменённых файлов: 146 добавлений и 63 удалений

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

@ -45,12 +45,31 @@ struct AudioCodecConfig
};
/*
* Minimalisitc video codec configuration
* Minimalistic video codec configuration
* More to be added later depending on the use-case
*/
struct VideoCodecConfig
#define MAX_SPROP_LEN 128
// used for holding SDP negotiation results
struct VideoCodecConfigH264
{
char sprop_parameter_sets[MAX_SPROP_LEN];
int packetization_mode;
int profile_level_id;
int max_mbps;
int max_fs;
int max_cpb;
int max_dpb;
int max_br;
int tias_bw;
};
// class so the std::strings can get freed more easily/reliably
class VideoCodecConfig
{
public:
/*
* The data-types for these properties mimic the
* corresponding webrtc::VideoCodec data-types.
@ -60,6 +79,10 @@ struct VideoCodecConfig
uint32_t mRtcpFbTypes;
unsigned int mMaxFrameSize;
unsigned int mMaxFrameRate;
unsigned int mMaxMBPS; // in macroblocks-per-second
unsigned int mMaxBitrate;
// max_cpb & max_dpb would be streaming/mode-2 only
std::string mSpropParameterSets;
uint8_t mProfile;
uint8_t mConstraints;
uint8_t mLevel;
@ -69,30 +92,34 @@ struct VideoCodecConfig
VideoCodecConfig(int type,
std::string name,
int rtcpFbTypes,
uint8_t profile = 0x42,
uint8_t constraints = 0xC0,
uint8_t level = 30,
uint8_t packetization = 0) :
mType(type),
mName(name),
mRtcpFbTypes(rtcpFbTypes),
mMaxFrameSize(0),
mMaxFrameRate(0),
mProfile(profile),
mConstraints(constraints),
mLevel(level),
mPacketizationMode(packetization) {}
VideoCodecConfig(int type,
std::string name,
int rtcpFbTypes,
unsigned int max_fs,
unsigned int max_fr) :
mType(type),
mName(name),
mRtcpFbTypes(rtcpFbTypes),
mMaxFrameSize(max_fs),
mMaxFrameRate(max_fr) {}
unsigned int max_fs = 0,
unsigned int max_fr = 0,
const struct VideoCodecConfigH264 *h264 = nullptr) :
mType(type),
mName(name),
mRtcpFbTypes(rtcpFbTypes),
mMaxFrameSize(max_fs), // may be overridden
mMaxFrameRate(max_fr),
mMaxMBPS(0),
mMaxBitrate(0),
mProfile(0x42),
mConstraints(0xE0),
mLevel(0x0C),
mPacketizationMode(1)
{
if (h264) {
if (max_fs == 0 || (h264->max_fs != 0 && (unsigned int) h264->max_fs < max_fs)) {
mMaxFrameSize = h264->max_fs;
}
mMaxMBPS = h264->max_mbps;
mMaxBitrate = h264->max_br;
mProfile = (h264->profile_level_id & 0x00FF0000) >> 16;
mConstraints = (h264->profile_level_id & 0x0000FF00) >> 8;
mLevel = (h264->profile_level_id & 0x000000FF);
mPacketizationMode = h264->packetization_mode;
mSpropParameterSets = h264->sprop_parameter_sets;
}
}
bool RtcpFbIsSet(sdp_rtcp_fb_nack_type_e type) const
{

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

@ -1309,6 +1309,14 @@ WebrtcVideoConduit::CodecConfigToWebRTCCodec(const VideoCodecConfig* codecInfo,
cinst.codecSpecific.H264.constraints = codecInfo->mConstraints;
cinst.codecSpecific.H264.level = codecInfo->mLevel;
cinst.codecSpecific.H264.packetizationMode = codecInfo->mPacketizationMode;
if (codecInfo->mMaxBitrate > 0 && codecInfo->mMaxBitrate < cinst.maxBitrate) {
cinst.maxBitrate = codecInfo->mMaxBitrate;
}
if (codecInfo->mMaxMBPS > 0) {
// Not supported yet!
CSFLogError(logTag, "%s H.264 max_mbps not supported yet ", __FUNCTION__);
}
// XXX parse the encoded SPS/PPS data
// paranoia
cinst.codecSpecific.H264.spsData = nullptr;
cinst.codecSpecific.H264.spsLen = 0;

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

@ -385,23 +385,8 @@ extern "C" {
#define CREATE_MT_MAP(a,b) ((a << 16) | b)
#define DYNAMIC_PAYLOAD_TYPE(x) ((x >> 16) & 0xFFFF)
#define MAX_SPROP_LEN 32
#define VCM_ERROR -1
struct h264_video
{
char sprop_parameter_set[MAX_SPROP_LEN];
int packetization_mode;
int profile_level_id;
int max_mbps;
int max_fs;
int max_cpb;
int max_dpb;
int max_br;
int tias_bw;
};
/**
* start/stop ringing
*
@ -2394,15 +2379,24 @@ static int vcmTxCreateAudioConduit(int level,
static int vcmTxCreateVideoConduit(int level,
const vcm_payload_info_t *payload,
sipcc::PeerConnectionWrapper &pc,
const vcm_mediaAttrs_t *attrs,
mozilla::RefPtr<mozilla::MediaSessionConduit> &conduit)
{
mozilla::VideoCodecConfig *config_raw;
struct VideoCodecConfigH264 *negotiated = nullptr;
if (attrs->video.opaque &&
(payload->codec_type == RTP_H264_P0 || payload->codec_type == RTP_H264_P1)) {
negotiated = static_cast<struct VideoCodecConfigH264 *>(attrs->video.opaque);
}
config_raw = new mozilla::VideoCodecConfig(
payload->remote_rtp_pt,
ccsdpCodecName(payload->codec_type),
payload->video.rtcp_fb_types,
payload->video.max_fs,
payload->video.max_fr);
payload->video.max_fr,
negotiated);
// Take possession of this pointer
mozilla::ScopedDeletePtr<mozilla::VideoCodecConfig> config(config_raw);
@ -2508,7 +2502,7 @@ static int vcmTxStartICE_m(cc_mcapid_t mcap_id,
err = vcmTxCreateAudioConduit(level, payload, pc, attrs, conduit);
} else if (CC_IS_VIDEO(mcap_id)) {
mediaType = "video";
err = vcmTxCreateVideoConduit(level, payload, pc, conduit);
err = vcmTxCreateVideoConduit(level, payload, pc, attrs, conduit);
} else {
CSFLogError(logTag, "%s: mcap_id unrecognized", __FUNCTION__);
}
@ -2957,17 +2951,23 @@ void vcmFreeMediaPtr(void *ptr)
* @return cc_boolean - true if attributes are accepted false otherwise
*/
cc_boolean vcmCheckAttribs(cc_uint32_t media_type, void *sdp_p, int level, void **rcapptr)
cc_boolean vcmCheckAttribs(cc_uint32_t media_type, void *sdp_p, int level,
int remote_pt, void **rcapptr)
{
CSFLogDebug( logTag, "vcmCheckAttribs(): media=%d", media_type);
cc_uint16_t temp;
const char *ptr;
uint32_t t_uint;
struct h264_video *rcap;
struct VideoCodecConfigH264 *rcap;
*rcapptr = nullptr;
int fmtp_inst = ccsdpAttrGetFmtpInst(sdp_p, level, remote_pt);
if (fmtp_inst < 0) {
return TRUE;
}
switch (media_type)
{
case RTP_VP8:
@ -2976,26 +2976,26 @@ cc_boolean vcmCheckAttribs(cc_uint32_t media_type, void *sdp_p, int level, void
case RTP_H264_P0:
case RTP_H264_P1:
rcap = (struct h264_video *) cpr_malloc( sizeof(struct h264_video) );
rcap = (struct VideoCodecConfigH264 *) cpr_malloc( sizeof(struct VideoCodecConfigH264) );
if ( rcap == nullptr )
{
CSFLogDebug( logTag, "vcmCheckAttribs(): Malloc Failed for rcap");
return FALSE;
}
memset( rcap, 0, sizeof(struct h264_video) );
memset( rcap, 0, sizeof(struct VideoCodecConfigH264) );
if ( (ptr = ccsdpAttrGetFmtpParamSets(sdp_p, level, 0, 1)) != nullptr )
if ( (ptr = ccsdpAttrGetFmtpParamSets(sdp_p, level, 0, fmtp_inst)) != nullptr )
{
memset(rcap->sprop_parameter_set, 0, csf_countof(rcap->sprop_parameter_set));
sstrncpy(rcap->sprop_parameter_set, ptr, csf_countof(rcap->sprop_parameter_set));
memset(rcap->sprop_parameter_sets, 0, csf_countof(rcap->sprop_parameter_sets));
sstrncpy(rcap->sprop_parameter_sets, ptr, csf_countof(rcap->sprop_parameter_sets));
}
if ( ccsdpAttrGetFmtpPackMode(sdp_p, level, 0, 1, &temp) == SDP_SUCCESS )
if ( ccsdpAttrGetFmtpPackMode(sdp_p, level, 0, fmtp_inst, &temp) == SDP_SUCCESS )
{
rcap->packetization_mode = temp;
}
if ( (ptr = ccsdpAttrGetFmtpProfileLevelId(sdp_p, level, 0, 1)) != nullptr )
if ( (ptr = ccsdpAttrGetFmtpProfileLevelId(sdp_p, level, 0, fmtp_inst)) != nullptr )
{
#ifdef _WIN32
sscanf_s(ptr, "%x", &rcap->profile_level_id, sizeof(int*));
@ -3004,32 +3004,32 @@ cc_boolean vcmCheckAttribs(cc_uint32_t media_type, void *sdp_p, int level, void
#endif
}
if ( ccsdpAttrGetFmtpMaxMbps(sdp_p, level, 0, 1, &t_uint) == SDP_SUCCESS )
if ( ccsdpAttrGetFmtpMaxMbps(sdp_p, level, 0, fmtp_inst, &t_uint) == SDP_SUCCESS )
{
rcap->max_mbps = t_uint;
}
if ( ccsdpAttrGetFmtpMaxFs(sdp_p, level, 0, 1, &t_uint) == SDP_SUCCESS )
if ( ccsdpAttrGetFmtpMaxFs(sdp_p, level, 0, fmtp_inst, &t_uint) == SDP_SUCCESS )
{
rcap->max_fs = t_uint;
}
if ( ccsdpAttrGetFmtpMaxCpb(sdp_p, level, 0, 1, &t_uint) == SDP_SUCCESS )
if ( ccsdpAttrGetFmtpMaxCpb(sdp_p, level, 0, fmtp_inst, &t_uint) == SDP_SUCCESS )
{
rcap->max_cpb = t_uint;
}
if ( ccsdpAttrGetFmtpMaxCpb(sdp_p, level, 0, 1, &t_uint) == SDP_SUCCESS )
if ( ccsdpAttrGetFmtpMaxCpb(sdp_p, level, 0, fmtp_inst, &t_uint) == SDP_SUCCESS )
{
rcap->max_dpb = t_uint;
}
if ( ccsdpAttrGetFmtpMaxCpb(sdp_p, level, 0, 1, &t_uint) == SDP_SUCCESS )
if ( ccsdpAttrGetFmtpMaxCpb(sdp_p, level, 0, fmtp_inst, &t_uint) == SDP_SUCCESS )
{
rcap->max_br = t_uint;
}
rcap->tias_bw = ccsdpGetBandwidthValue(sdp_p, level, 1);
rcap->tias_bw = ccsdpGetBandwidthValue(sdp_p, level, fmtp_inst);
if ( rcap->tias_bw == 0 )
{
// received bandwidth of 0 reject this
@ -3043,7 +3043,7 @@ cc_boolean vcmCheckAttribs(cc_uint32_t media_type, void *sdp_p, int level, void
}
CSFLogDebug( logTag, "vcmCheckAttribs(): Negotiated media attrs\nsprop=%s\npack_mode=%d\nprofile_level_id=%X\nmbps=%d\nmax_fs=%d\nmax_cpb=%d\nmax_dpb=%d\nbr=%d bw=%d\n",
rcap->sprop_parameter_set,
rcap->sprop_parameter_sets,
rcap->packetization_mode,
rcap->profile_level_id,
rcap->max_mbps,

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

@ -3501,12 +3501,12 @@ gsmsdp_negotiate_codec (fsmdef_dcb_t *dcb_p, cc_sdp_t *sdp_p,
} else if (media->type == SDP_MEDIA_VIDEO) {
if ( media-> video != NULL ) {
if ( media->video != NULL ) {
vcmFreeMediaPtr(media->video);
media->video = NULL;
}
if (!vcmCheckAttribs(codec, sdp_p, level,
if (!vcmCheckAttribs(codec, sdp_p, level, remote_pt,
&media->video)) {
GSM_DEBUG(DEB_L_C_F_PREFIX"codec= %d ignored - "
"attribs not accepted\n",

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

@ -5,6 +5,14 @@
#include "sdp.h"
#include "ccapi.h"
int ccsdpAttrGetFmtpInst(void *sdp_ptr, u16 level, u16 payload_num)
{
cc_sdp_t *sdpp = sdp_ptr;
if ( sdpp->dest_sdp == NULL ) {
return NULL;
}
return sdp_find_fmtp_inst(sdpp->dest_sdp, level, payload_num);
}
const char* ccsdpAttrGetFmtpParamSets(void *sdp_ptr, u16 level,
u8 cap_num, u16 inst_num)

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

@ -1225,6 +1225,7 @@ extern sdp_result_e sdp_add_media_profile_payload_type(void *sdp_ptr,
sdp_payload_ind_e indicator);
/* sdp_attr_access.c */
extern int sdp_find_fmtp_inst(sdp_t *sdp_ptr, u16 level, u16 payload_num);
extern sdp_result_e sdp_add_new_attr(void *sdp_ptr, u16 level, u8 cap_num,
sdp_attr_e attr_type, u16 *inst_num);
extern sdp_result_e sdp_copy_attr (void *src_sdp_ptr, void *dst_sdp_ptr,

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

@ -1736,6 +1736,33 @@ sdp_result_e sdp_find_attr_list (sdp_t *sdp_p, u16 level, u8 cap_num,
return (SDP_SUCCESS);
}
/* Find fmtp inst_num with correct payload value or -1 for failure */
int sdp_find_fmtp_inst (sdp_t *sdp_p, u16 level, u16 payload_num)
{
u16 attr_count=0;
sdp_mca_t *mca_p;
sdp_mca_t *cap_p;
sdp_attr_t *attr_p;
/* Attr is at a media level */
mca_p = sdp_find_media_level(sdp_p, level);
if (mca_p == NULL) {
return (-1);
}
for (attr_p = mca_p->media_attrs_p; attr_p != NULL;
attr_p = attr_p->next_p) {
if (attr_p->type == SDP_ATTR_FMTP) {
attr_count++;
if (attr_p->attr.fmtp.payload_num == payload_num) {
return (attr_count);
}
}
}
return (-1);
}
/* Function: sdp_find_attr
* Description: Find the specified attribute in an SDP structure.
* Note: This is not an API for the application but an internal
@ -12628,4 +12655,3 @@ sdp_attr_set_extmap(void *sdp_ptr, u16 level, u16 id, const char* uri, u16 inst)
sstrncpy(attr_p->attr.extmap.uri, uri, SDP_MAX_STRING_LEN+1);
return (SDP_SUCCESS);
}

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

@ -263,6 +263,17 @@ typedef enum {
SDP_SETUP_UNKNOWN
} sdp_setup_type_e;
/**
* Returns the inst_num value for the specified FTMP attr
*
* @param[in] sdp_handle The SDP handle
* @param[in] level The level to check for the attribute.
*
* @return inst_num The attribute instance number to check, or -1 for failure
*/
int ccsdpAttrGetFmtpInst(void *sdp_handle, uint16_t level, uint16_t payload_num);
/**
* Gets the value of the fmtp attribute- parameter-sets parameter for H.264 codec
*

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

@ -1009,12 +1009,14 @@ void vcmSetRtcpDscp(cc_groupid_t group_id, int dscp);
* @param [in] media_type - codec for which we are negotiating
* @param [in] sdp_p - opaque SDP pointer to be used via SDP helper APIs
* @param [in] level - Parameter to be used with SDP helper APIs
* @param [in] remote_pt - payload type remote is using for this codec
* @param [out] rcapptr - variable to return the allocated attrib structure
*
* @return cc_boolean - true if attributes are accepted false otherwise
*/
cc_boolean vcmCheckAttribs(cc_uint32_t media_type, void *sdp_p, int level, void **rcapptr);
cc_boolean vcmCheckAttribs(cc_uint32_t media_type, void *sdp_p, int level,
int remote_pt, void **rcapptr);
/**
* Add Video attributes in the offer/answer SDP