Bug 985253: Support H.264 RTP mode 1 support in webrtc signaling r=ehugg

This commit is contained in:
Randell Jesup 2014-05-24 18:28:02 -04:00
parent 41ccb95961
commit 88dd15fc1e
6 changed files with 165 additions and 95 deletions

View File

@ -60,31 +60,36 @@ struct VideoCodecConfig
* The data-types for these properties mimic the
* corresponding webrtc::VideoCodec data-types.
*/
int mType;
int mType; // payload type
std::string mName;
uint32_t mRtcpFbTypes;
unsigned int mMaxFrameSize;
unsigned int mMaxFrameRate;
LoadManager* mLoadManager;
uint8_t mProfile;
uint8_t mConstraints;
uint8_t mLevel;
uint8_t mPacketizationMode;
// TODO: add external negotiated SPS/PPS
VideoCodecConfig(int type,
std::string name,
int rtcpFbTypes,
LoadManager* load_manager = nullptr) :
LoadManager* load_manager = nullptr,
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),
mLoadManager(load_manager)
{
// Replace codec name here because WebRTC.org code has a whitelist of
// supported video codec in |webrtc::ViECodecImpl::CodecValid()| and will
// reject registration of those not in it.
// TODO: bug 995884 to support H.264 in WebRTC.org code.
if (mName == "H264_P0")
mName = "I420";
}
mLoadManager(load_manager),
mProfile(profile),
mConstraints(constraints),
mLevel(level),
mPacketizationMode(packetization) {}
VideoCodecConfig(int type,
std::string name,
@ -97,16 +102,7 @@ struct VideoCodecConfig
mRtcpFbTypes(rtcpFbTypes),
mMaxFrameSize(max_fs),
mMaxFrameRate(max_fr),
mLoadManager(load_manager)
{
// Replace codec name here because WebRTC.org code has a whitelist of
// supported video codec in |webrtc::ViECodecImpl::CodecValid()| and will
// reject registration of those not in it.
// TODO: bug 995884 to support H.264 in WebRTC.org code.
if (mName == "H264_P0")
mName = "I420";
}
mLoadManager(load_manager) {}
bool RtcpFbIsSet(sdp_rtcp_fb_nack_type_e type) const
{
@ -122,7 +118,6 @@ struct VideoCodecConfig
{
return mRtcpFbTypes & sdp_rtcp_fb_ccm_to_bitmap(type);
}
};
}
#endif

View File

@ -279,7 +279,7 @@ public:
* @param encoder
* @result: on success, we will use the specified encoder
*/
virtual MediaConduitErrorCode SetExternalSendCodec(int pltype,
virtual MediaConduitErrorCode SetExternalSendCodec(VideoCodecConfig* config,
VideoEncoder* encoder) = 0;
/**
@ -287,7 +287,7 @@ public:
* @param decoder
* @result: on success, we will use the specified decoder
*/
virtual MediaConduitErrorCode SetExternalRecvCodec(int pltype,
virtual MediaConduitErrorCode SetExternalRecvCodec(VideoCodecConfig* config,
VideoDecoder* decoder) = 0;
/**

View File

@ -4,6 +4,7 @@
#include "CSFLog.h"
#include "nspr.h"
#include "plstr.h"
// For rtcp-fb constants
#include "ccsdp.h"
@ -479,7 +480,7 @@ WebrtcVideoConduit::AttachTransport(mozilla::RefPtr<TransportInterface> aTranspo
MediaConduitErrorCode
WebrtcVideoConduit::ConfigureSendMediaCodec(const VideoCodecConfig* codecConfig)
{
CSFLogDebug(logTag, "%s ", __FUNCTION__);
CSFLogDebug(logTag, "%s for %s", __FUNCTION__, codecConfig->mName.c_str());
bool codecFound = false;
MediaConduitErrorCode condError = kMediaConduitNoError;
int error = 0; //webrtc engine errors
@ -509,35 +510,52 @@ WebrtcVideoConduit::ConfigureSendMediaCodec(const VideoCodecConfig* codecConfig)
mPtrViEBase->LastError());
return kMediaConduitUnknownError;
}
}
mEngineTransmitting = false;
mEngineTransmitting = false;
}
if (codecConfig->mLoadManager) {
mPtrViEBase->RegisterCpuOveruseObserver(mChannel, codecConfig->mLoadManager);
mPtrViEBase->SetLoadManager(codecConfig->mLoadManager);
}
// we should be good here to set the new codec.
for(int idx=0; idx < mPtrViECodec->NumberOfCodecs(); idx++)
{
if(0 == mPtrViECodec->GetCodec(idx, video_codec))
if (mExternalSendCodec &&
codecConfig->mType == mExternalSendCodec->mType) {
CSFLogError(logTag, "%s Configuring External H264 Send Codec", __FUNCTION__);
// width/height will be overridden on the first frame
video_codec.width = 320;
video_codec.height = 240;
video_codec.qpMax = 56;
video_codec.numberOfSimulcastStreams = 1;
video_codec.mode = webrtc::kRealtimeVideo;
codecFound = true;
} else {
// we should be good here to set the new codec.
for(int idx=0; idx < mPtrViECodec->NumberOfCodecs(); idx++)
{
payloadName = video_codec.plName;
if(codecConfig->mName.compare(payloadName) == 0)
if(0 == mPtrViECodec->GetCodec(idx, video_codec))
{
CodecConfigToWebRTCCodec(codecConfig, video_codec);
codecFound = true;
break;
payloadName = video_codec.plName;
if(codecConfig->mName.compare(payloadName) == 0)
{
// Note: side-effect of this is that video_codec is filled in
// by GetCodec()
codecFound = true;
break;
}
}
}
}//for
}//for
}
if(codecFound == false)
{
CSFLogError(logTag, "%s Codec Mismatch ", __FUNCTION__);
return kMediaConduitInvalidSendCodec;
}
// Note: only for overriding parameters from GetCodec()!
CodecConfigToWebRTCCodec(codecConfig, video_codec);
if(mPtrViECodec->SetSendCodec(mChannel, video_codec) == -1)
{
@ -656,35 +674,61 @@ WebrtcVideoConduit::ConfigureRecvMediaCodecs(
mEngineReceiving = false;
memset(&video_codec, 0, sizeof(webrtc::VideoCodec));
//Retrieve pre-populated codec structure for our codec.
for(int idx=0; idx < mPtrViECodec->NumberOfCodecs(); idx++)
{
if(mPtrViECodec->GetCodec(idx, video_codec) == 0)
if (mExternalRecvCodec &&
codecConfigList[i]->mType == mExternalRecvCodec->mType) {
CSFLogError(logTag, "%s Configuring External H264 Receive Codec", __FUNCTION__);
// XXX Do we need a separate setting for receive maxbitrate? Is it
// different for hardware codecs? For now assume symmetry.
CodecConfigToWebRTCCodec(codecConfigList[i], video_codec);
// values SetReceiveCodec() cares about are name, type, maxbitrate
if(mPtrViECodec->SetReceiveCodec(mChannel,video_codec) == -1)
{
payloadName = video_codec.plName;
if(codecConfigList[i]->mName.compare(payloadName) == 0)
CSFLogError(logTag, "%s Invalid Receive Codec %d ", __FUNCTION__,
mPtrViEBase->LastError());
} else {
CSFLogError(logTag, "%s Successfully Set the codec %s", __FUNCTION__,
codecConfigList[i]->mName.c_str());
if(CopyCodecToDB(codecConfigList[i]))
{
CodecConfigToWebRTCCodec(codecConfigList[i], video_codec);
if(mPtrViECodec->SetReceiveCodec(mChannel,video_codec) == -1)
{
CSFLogError(logTag, "%s Invalid Receive Codec %d ", __FUNCTION__,
mPtrViEBase->LastError());
} else {
CSFLogError(logTag, "%s Successfully Set the codec %s", __FUNCTION__,
codecConfigList[i]->mName.c_str());
if(CopyCodecToDB(codecConfigList[i]))
{
success = true;
} else {
CSFLogError(logTag,"%s Unable to updated Codec Database", __FUNCTION__);
return kMediaConduitUnknownError;
}
}
break; //we found a match
success = true;
} else {
CSFLogError(logTag,"%s Unable to update Codec Database", __FUNCTION__);
return kMediaConduitUnknownError;
}
}
}//end for codeclist
} else {
//Retrieve pre-populated codec structure for our codec.
for(int idx=0; idx < mPtrViECodec->NumberOfCodecs(); idx++)
{
if(mPtrViECodec->GetCodec(idx, video_codec) == 0)
{
payloadName = video_codec.plName;
if(codecConfigList[i]->mName.compare(payloadName) == 0)
{
CodecConfigToWebRTCCodec(codecConfigList[i], video_codec);
if(mPtrViECodec->SetReceiveCodec(mChannel,video_codec) == -1)
{
CSFLogError(logTag, "%s Invalid Receive Codec %d ", __FUNCTION__,
mPtrViEBase->LastError());
} else {
CSFLogError(logTag, "%s Successfully Set the codec %s", __FUNCTION__,
codecConfigList[i]->mName.c_str());
if(CopyCodecToDB(codecConfigList[i]))
{
success = true;
} else {
CSFLogError(logTag,"%s Unable to update Codec Database", __FUNCTION__);
return kMediaConduitUnknownError;
}
}
break; //we found a match
}
}
}//end for codeclist
}
}//end for
if(!success)
@ -882,22 +926,28 @@ WebrtcVideoConduit::SelectSendResolution(unsigned short width,
}
MediaConduitErrorCode
WebrtcVideoConduit::SetExternalSendCodec(int pltype,
WebrtcVideoConduit::SetExternalSendCodec(VideoCodecConfig* config,
VideoEncoder* encoder) {
int ret = mPtrExtCodec->RegisterExternalSendCodec(mChannel,
pltype,
static_cast<WebrtcVideoEncoder*>(encoder),
false);
return ret ? kMediaConduitInvalidSendCodec : kMediaConduitNoError;
if (!mPtrExtCodec->RegisterExternalSendCodec(mChannel,
config->mType,
static_cast<WebrtcVideoEncoder*>(encoder),
false)) {
mExternalSendCodec = new VideoCodecConfig(*config);
return kMediaConduitNoError;
}
return kMediaConduitInvalidSendCodec;
}
MediaConduitErrorCode
WebrtcVideoConduit::SetExternalRecvCodec(int pltype,
WebrtcVideoConduit::SetExternalRecvCodec(VideoCodecConfig* config,
VideoDecoder* decoder) {
int ret = mPtrExtCodec->RegisterExternalReceiveCodec(mChannel,
pltype,
static_cast<WebrtcVideoDecoder*>(decoder));
return ret ? kMediaConduitInvalidReceiveCodec : kMediaConduitNoError;
if (!mPtrExtCodec->RegisterExternalReceiveCodec(mChannel,
config->mType,
static_cast<WebrtcVideoDecoder*>(decoder))) {
mExternalRecvCodec = new VideoCodecConfig(*config);
return kMediaConduitNoError;
}
return kMediaConduitInvalidReceiveCodec;
}
MediaConduitErrorCode
@ -1141,8 +1191,23 @@ void
WebrtcVideoConduit::CodecConfigToWebRTCCodec(const VideoCodecConfig* codecInfo,
webrtc::VideoCodec& cinst)
{
// Note: this assumes cinst is initialized to a base state either by
// hand or from a config fetched with GetConfig(); this modifies the config
// to match parameters from VideoCodecConfig
cinst.plType = codecInfo->mType;
// leave width/height alone; they'll be overridden on the first frame
if (codecInfo->mName == "H264_P0" || codecInfo->mName == "H264_P1") {
cinst.codecType = webrtc::kVideoCodecH264;
PL_strncpyz(cinst.plName, "H264", sizeof(cinst.plName));
} else if (codecInfo->mName == "VP8") {
cinst.codecType = webrtc::kVideoCodecVP8;
PL_strncpyz(cinst.plName, "VP8", sizeof(cinst.plName));
} else if (codecInfo->mName == "I420") {
cinst.codecType = webrtc::kVideoCodecI420;
PL_strncpyz(cinst.plName, "I420", sizeof(cinst.plName));
}
// width/height will be overridden on the first frame; they must be 'sane' for
// SetSendCodec()
if (codecInfo->mMaxFrameRate > 0)
{
cinst.maxFramerate = codecInfo->mMaxFrameRate;
@ -1150,6 +1215,19 @@ WebrtcVideoConduit::CodecConfigToWebRTCCodec(const VideoCodecConfig* codecInfo,
cinst.minBitrate = mMinBitrate;
cinst.startBitrate = mStartBitrate;
cinst.maxBitrate = mMaxBitrate;
if (cinst.codecType == webrtc::kVideoCodecH264)
{
cinst.codecSpecific.H264.profile = codecInfo->mProfile;
cinst.codecSpecific.H264.constraints = codecInfo->mConstraints;
cinst.codecSpecific.H264.level = codecInfo->mLevel;
cinst.codecSpecific.H264.packetizationMode = codecInfo->mPacketizationMode;
// paranoia
cinst.codecSpecific.H264.spsData = nullptr;
cinst.codecSpecific.H264.spsLen = 0;
cinst.codecSpecific.H264.ppsData = nullptr;
cinst.codecSpecific.H264.ppsLen = 0;
}
}
//Copy the codec passed into Conduit's database

View File

@ -5,6 +5,7 @@
#ifndef VIDEO_SESSION_H_
#define VIDEO_SESSION_H_
#include "nsAutoPtr.h"
#include "mozilla/Attributes.h"
#include "MediaConduitInterface.h"
@ -146,14 +147,14 @@ public:
* Set an external encoder object |encoder| to the payload type |pltype|
* for sender side codec.
*/
virtual MediaConduitErrorCode SetExternalSendCodec(int pltype,
virtual MediaConduitErrorCode SetExternalSendCodec(VideoCodecConfig* config,
VideoEncoder* encoder);
/**
* Set an external decoder object |decoder| to the payload type |pltype|
* for receiver side codec.
*/
virtual MediaConduitErrorCode SetExternalRecvCodec(int pltype,
virtual MediaConduitErrorCode SetExternalRecvCodec(VideoCodecConfig* config,
VideoDecoder* decoder);
@ -338,6 +339,9 @@ private:
static const unsigned int sRoundingPadding = 1024;
mozilla::RefPtr<WebrtcAudioConduit> mSyncedTo;
nsAutoPtr<VideoCodecConfig> mExternalSendCodec;
nsAutoPtr<VideoCodecConfig> mExternalRecvCodec;
};
} // end namespace

View File

@ -2135,7 +2135,7 @@ static int vcmEnsureExternalCodec(
// whitelist internal codecs; I420 will be here once we resolve bug 995884
return 0;
#ifdef MOZ_WEBRTC_OMX
} else if (config->mName == "I420") {
} else if (config->mName == "H264_P0" || config->mName == "H264_P1") {
// Here we use "I420" to register H.264 because WebRTC.org code has a
// whitelist of supported video codec in |webrtc::ViECodecImpl::CodecValid()|
// and will reject registration of those not in it.
@ -2145,14 +2145,14 @@ static int vcmEnsureExternalCodec(
if (send) {
VideoEncoder* encoder = OMXVideoCodec::CreateEncoder(OMXVideoCodec::CodecType::CODEC_H264);
if (encoder) {
return conduit->SetExternalSendCodec(config->mType, encoder);
return conduit->SetExternalSendCodec(config, encoder);
} else {
return kMediaConduitInvalidSendCodec;
}
} else {
VideoDecoder* decoder = OMXVideoCodec::CreateDecoder(OMXVideoCodec::CodecType::CODEC_H264);
if (decoder) {
return conduit->SetExternalRecvCodec(config->mType, decoder);
return conduit->SetExternalRecvCodec(config, decoder);
} else {
return kMediaConduitInvalidReceiveCodec;
}
@ -2740,7 +2740,8 @@ int vcmGetVideoCodecList(int request_type)
*/
int vcmGetVideoMaxSupportedPacketizationMode()
{
return 0;
// We support mode 1 packetization in webrtc
return 1;
}
/**
@ -3015,7 +3016,9 @@ void vcmPopulateAttribs(void *sdp_p, int level, cc_uint32_t media_type,
(void) ccsdpAttrSetFmtpPayloadType(sdp_p, level, 0, a_inst, payload_number);
//(void) sdp_attr_set_fmtp_pack_mode(sdp_p, level, 0, a_inst, 1 /*packetization_mode*/);
if (media_type == RTP_H264_P1) {
(void) ccsdpAttrSetFmtpPackMode(sdp_p, level, 0, a_inst, 1 /*packetization_mode*/);
}
//(void) sdp_attr_set_fmtp_parameter_sets(sdp_p, level, 0, a_inst, "J0KAFJWgUH5A,KM4H8n=="); // NAL units 27 42 80 14 95 a0 50 7e 40 28 ce 07 f2
//profile = 0x42E000 + H264ToSDPLevel( vt_GetClientProfileLevel() );

View File

@ -604,7 +604,6 @@ sip_config_video_supported_codecs_get (rtp_ptype aSupportedCodecs[],
{
uint16_t count = 0;
int codec_mask;
cc_uint32_t major_ver, minor_ver;
if ( isOffer ) {
codec_mask = vcmGetVideoCodecList(VCM_DSP_FULLDUPLEX);
@ -615,18 +614,9 @@ sip_config_video_supported_codecs_get (rtp_ptype aSupportedCodecs[],
codec_mask = vcmGetVideoCodecList(VCM_DSP_IGNORE);
}
if ( codec_mask & VCM_CODEC_RESOURCE_H264) {
/*
* include payload type for packetization mode 1 only if ucm sis version
* is equal to or greater than 5.1.0 (AngelFire).
*/
platGetSISProtocolVer(&major_ver, &minor_ver, NULL, NULL);
if ((major_ver > SIS_PROTOCOL_MAJOR_VERSION_ANGELFIRE) ||
(major_ver == SIS_PROTOCOL_MAJOR_VERSION_ANGELFIRE &&
minor_ver >= SIS_PROTOCOL_MINOR_VERSION_ANGELFIRE)) {
if (vcmGetVideoMaxSupportedPacketizationMode() == 1) {
aSupportedCodecs[count] = RTP_H264_P1;
count++;
}
if (vcmGetVideoMaxSupportedPacketizationMode() == 1) {
aSupportedCodecs[count] = RTP_H264_P1;
count++;
}
aSupportedCodecs[count] = RTP_H264_P0;
count++;