Bug 880067 - Part 4: Video Conduit configuration for RTCP feedback r=ekr

This commit is contained in:
Adam Roach [:abr] 2013-09-05 15:11:47 -05:00
Родитель 902df2d447
Коммит 6b3dfa04e1
9 изменённых файлов: 222 добавлений и 98 удалений

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

@ -587,6 +587,7 @@
'./src/sipcc/include/ccapi_service.h',
'./src/sipcc/include/ccapi_types.h',
'./src/sipcc/include/ccsdp.h',
'./src/sipcc/include/ccsdp_rtcp_fb.h',
'./src/sipcc/include/config_api.h',
'./src/sipcc/include/dns_util.h',
'./src/sipcc/include/plat_api.h',

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

@ -7,7 +7,7 @@
#define CODEC_CONFIG_H_
#include <string>
#include "ccsdp_rtcp_fb.h"
namespace mozilla {
@ -56,16 +56,29 @@ struct VideoCodecConfig
*/
int mType;
std::string mName;
uint32_t mRtcpFbTypes;
/* When we have resolution negotiation information (RFC 6236)
* it will be stored here.
*/
VideoCodecConfig(int type, std::string name): mType(type),
mName(name)
VideoCodecConfig(int type, std::string name, int rtcpFbTypes):
mType(type), mName(name), mRtcpFbTypes(rtcpFbTypes)
{
}
bool RtcpFbIsSet(sdp_rtcp_fb_nack_type_e type) const
{
return mRtcpFbTypes & sdp_rtcp_fb_nack_to_bitmap(type);
}
bool RtcpFbIsSet(sdp_rtcp_fb_ack_type_e type) const
{
return mRtcpFbTypes & sdp_rtcp_fb_ack_to_bitmap(type);
}
bool RtcpFbIsSet(sdp_rtcp_fb_ccm_type_e type) const
{
return mRtcpFbTypes & sdp_rtcp_fb_ccm_to_bitmap(type);
}
};
}
#endif

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

@ -5,6 +5,9 @@
#include "CSFLog.h"
#include "nspr.h"
// For rtcp-fb constants
#include "ccsdp.h"
#include "VideoConduit.h"
#include "AudioConduit.h"
#include "webrtc/video_engine/include/vie_errors.h"
@ -245,22 +248,6 @@ MediaConduitErrorCode WebrtcVideoConduit::Init()
mPtrViEBase->LastError());
return kMediaConduitRTCPStatusError;
}
// Enable pli as key frame request method.
if(mPtrRTP->SetKeyFrameRequestMethod(mChannel,
webrtc::kViEKeyFrameRequestPliRtcp) != 0)
{
CSFLogError(logTag, "%s KeyFrameRequest Failed %d ", __FUNCTION__,
mPtrViEBase->LastError());
return kMediaConduitKeyFrameRequestError;
}
// Enable lossless transport
// XXX Note: We may want to disable this or limit it
if (mPtrRTP->SetNACKStatus(mChannel, true) != 0)
{
CSFLogError(logTag, "%s NACKStatus Failed %d ", __FUNCTION__,
mPtrViEBase->LastError());
return kMediaConduitNACKStatusError;
}
CSFLogError(logTag, "%s Initialization Done", __FUNCTION__);
return kMediaConduitNoError;
}
@ -418,6 +405,16 @@ WebrtcVideoConduit::ConfigureSendMediaCodec(const VideoCodecConfig* codecConfig)
mSendingWidth = 0;
mSendingHeight = 0;
if(codecConfig->RtcpFbIsSet(SDP_RTCP_FB_NACK_BASIC)) {
CSFLogDebug(logTag, "Enabling NACK (send) for video stream\n");
if (mPtrRTP->SetNACKStatus(mChannel, true) != 0)
{
CSFLogError(logTag, "%s NACKStatus Failed %d ", __FUNCTION__,
mPtrViEBase->LastError());
return kMediaConduitNACKStatusError;
}
}
if(mPtrViEBase->StartSend(mChannel) == -1)
{
CSFLogError(logTag, "%s Start Send Error %d ", __FUNCTION__,
@ -428,8 +425,7 @@ WebrtcVideoConduit::ConfigureSendMediaCodec(const VideoCodecConfig* codecConfig)
//Copy the applied codec for future reference
delete mCurSendCodecConfig;
mCurSendCodecConfig = new VideoCodecConfig(codecConfig->mType,
codecConfig->mName);
mCurSendCodecConfig = new VideoCodecConfig(*codecConfig);
mPtrRTP->SetRembStatus(mChannel, true, false);
@ -472,7 +468,10 @@ WebrtcVideoConduit::ConfigureRecvMediaCodecs(
return kMediaConduitMalformedArgument;
}
//Try Applying the codecs in the list
webrtc::ViEKeyFrameRequestMethod kf_request = webrtc::kViEKeyFrameRequestNone;
bool use_nack_basic = false;
// Try Applying the codecs in the list
// we treat as success if atleast one codec was applied and reception was
// started successfully.
for(std::vector<VideoCodecConfig*>::size_type i=0;i < codecConfigList.size();i++)
@ -483,7 +482,25 @@ WebrtcVideoConduit::ConfigureRecvMediaCodecs(
return condError;
}
// Check for the keyframe request type: PLI is preferred
// over FIR, and FIR is preferred over none.
if (codecConfigList[i]->RtcpFbIsSet(SDP_RTCP_FB_NACK_PLI))
{
kf_request = webrtc::kViEKeyFrameRequestPliRtcp;
} else if(kf_request == webrtc::kViEKeyFrameRequestNone &&
codecConfigList[i]->RtcpFbIsSet(SDP_RTCP_FB_CCM_FIR))
{
kf_request = webrtc::kViEKeyFrameRequestFirRtcp;
}
// Check whether NACK is requested
if(codecConfigList[i]->RtcpFbIsSet(SDP_RTCP_FB_NACK_BASIC))
{
use_nack_basic = true;
}
webrtc::VideoCodec video_codec;
mEngineReceiving = false;
memset(&video_codec, 0, sizeof(webrtc::VideoCodec));
//Retrieve pre-populated codec structure for our codec.
@ -523,6 +540,51 @@ WebrtcVideoConduit::ConfigureRecvMediaCodecs(
return kMediaConduitInvalidReceiveCodec;
}
// XXX Currently, we gather up all of the feedback types that the remote
// party indicated it supports for all video codecs and configure the entire
// conduit based on those capabilities. This is technically out of spec,
// as these values should be configured on a per-codec basis. However,
// the video engine only provides this API on a per-conduit basis, so that's
// how we have to do it. The approach of considering the remote capablities
// for the entire conduit to be a union of all remote codec capabilities
// (rather than the more conservative approach of using an intersection)
// is made to provide as many feedback mechanisms as are likely to be
// processed by the remote party (and should be relatively safe, since the
// remote party is required to ignore feedback types that it does not
// understand).
//
// Note that our configuration uses this union of remote capabilites as
// input to the configuration. It is not isomorphic to the configuration.
// For example, it only makes sense to have one frame request mechanism
// active at a time; so, if the remote party indicates more than one
// supported mechanism, we're only configuring the one we most prefer.
//
// See http://code.google.com/p/webrtc/issues/detail?id=2331
if (kf_request != webrtc::kViEKeyFrameRequestNone)
{
CSFLogDebug(logTag, "Enabling %s frame requests for video stream\n",
(kf_request == webrtc::kViEKeyFrameRequestPliRtcp ?
"PLI" : "FIR"));
if(mPtrRTP->SetKeyFrameRequestMethod(mChannel, kf_request) != 0)
{
CSFLogError(logTag, "%s KeyFrameRequest Failed %d ", __FUNCTION__,
mPtrViEBase->LastError());
return kMediaConduitKeyFrameRequestError;
}
}
if(use_nack_basic)
{
CSFLogDebug(logTag, "Enabling NACK (recv) for video stream\n");
if (mPtrRTP->SetNACKStatus(mChannel, true) != 0)
{
CSFLogError(logTag, "%s NACKStatus Failed %d ", __FUNCTION__,
mPtrViEBase->LastError());
return kMediaConduitNACKStatusError;
}
}
//Start Receive on the video engine
if(mPtrViEBase->StartReceive(mChannel) == -1)
{
@ -789,8 +851,7 @@ WebrtcVideoConduit::CodecConfigToWebRTCCodec(const VideoCodecConfig* codecInfo,
bool
WebrtcVideoConduit::CopyCodecToDB(const VideoCodecConfig* codecInfo)
{
VideoCodecConfig* cdcConfig = new VideoCodecConfig(codecInfo->mType,
codecInfo->mName);
VideoCodecConfig* cdcConfig = new VideoCodecConfig(*codecInfo);
mRecvCodecList.push_back(cdcConfig);
return true;
}

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

@ -1486,7 +1486,8 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id,
{
config_raw = new mozilla::VideoCodecConfig(
payloads[i].remote_rtp_pt,
ccsdpCodecName(payloads[i].codec_type));
ccsdpCodecName(payloads[i].codec_type),
payloads[i].video.rtcp_fb_types);
configs.push_back(config_raw);
}
@ -2117,7 +2118,8 @@ static int vcmTxStartICE_m(cc_mcapid_t mcap_id,
mozilla::VideoCodecConfig *config_raw;
config_raw = new mozilla::VideoCodecConfig(
payload->remote_rtp_pt,
ccsdpCodecName(payload->codec_type));
ccsdpCodecName(payload->codec_type),
payload->video.rtcp_fb_types);
// Take possession of this pointer
mozilla::ScopedDeletePtr<mozilla::VideoCodecConfig> config(config_raw);

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

@ -4507,21 +4507,21 @@ gsmsdp_add_rtcp_fb (int level, sdp_t *sdp_p,
/* Add requested a=rtcp-fb:nack attributes */
for (j = 0; j < SDP_MAX_RTCP_FB_NACK; j++) {
if (types & SDP_RTCP_FB_NACK_TO_BITMAP(j)) {
if (types & sdp_rtcp_fb_nack_to_bitmap(j)) {
gsmsdp_set_rtcp_fb_nack_attribute(level, sdp_p, pt, j);
}
}
/* Add requested a=rtcp-fb:ack attributes */
for (j = 0; j < SDP_MAX_RTCP_FB_ACK; j++) {
if (types & SDP_RTCP_FB_ACK_TO_BITMAP(j)) {
if (types & sdp_rtcp_fb_ack_to_bitmap(j)) {
gsmsdp_set_rtcp_fb_nack_attribute(level, sdp_p, pt, j);
}
}
/* Add requested a=rtcp-fb:ccm attributes */
for (j = 0; j < SDP_MAX_RTCP_FB_CCM; j++) {
if (types & SDP_RTCP_FB_CCM_TO_BITMAP(j)) {
if (types & sdp_rtcp_fb_ccm_to_bitmap(j)) {
gsmsdp_set_rtcp_fb_ccm_attribute(level, sdp_p, pt, j);
}
}
@ -4591,7 +4591,7 @@ gsmsdp_negotiate_rtcp_fb (cc_sdp_t *cc_sdp_p,
nack_type = sdp_attr_get_rtcp_fb_nack(cc_sdp_p->dest_sdp,
level, remote_pt, i);
if (nack_type >= 0 && nack_type < SDP_MAX_RTCP_FB_NACK) {
fb_types |= SDP_RTCP_FB_NACK_TO_BITMAP(nack_type);
fb_types |= sdp_rtcp_fb_nack_to_bitmap(nack_type);
}
i++;
} while (nack_type != SDP_RTCP_FB_NACK_NOT_FOUND);
@ -4602,7 +4602,7 @@ gsmsdp_negotiate_rtcp_fb (cc_sdp_t *cc_sdp_p,
ack_type = sdp_attr_get_rtcp_fb_ack(cc_sdp_p->dest_sdp,
level, remote_pt, i);
if (ack_type >= 0 && ack_type < SDP_MAX_RTCP_FB_ACK) {
fb_types |= SDP_RTCP_FB_ACK_TO_BITMAP(ack_type);
fb_types |= sdp_rtcp_fb_ack_to_bitmap(ack_type);
}
i++;
} while (ack_type != SDP_RTCP_FB_ACK_NOT_FOUND);
@ -4613,7 +4613,7 @@ gsmsdp_negotiate_rtcp_fb (cc_sdp_t *cc_sdp_p,
ccm_type = sdp_attr_get_rtcp_fb_ccm(cc_sdp_p->dest_sdp,
level, remote_pt, i);
if (ccm_type >= 0 && ccm_type < SDP_MAX_RTCP_FB_CCM) {
fb_types |= SDP_RTCP_FB_CCM_TO_BITMAP(ccm_type);
fb_types |= sdp_rtcp_fb_ccm_to_bitmap(ccm_type);
}
i++;
} while (ccm_type != SDP_RTCP_FB_CCM_NOT_FOUND);
@ -4624,9 +4624,9 @@ gsmsdp_negotiate_rtcp_fb (cc_sdp_t *cc_sdp_p,
switch (codec) {
case RTP_VP8:
fb_types &=
SDP_RTCP_FB_NACK_TO_BITMAP(SDP_RTCP_FB_NACK_BASIC) |
SDP_RTCP_FB_NACK_TO_BITMAP(SDP_RTCP_FB_NACK_PLI) |
SDP_RTCP_FB_CCM_TO_BITMAP(SDP_RTCP_FB_CCM_FIR);
sdp_rtcp_fb_nack_to_bitmap(SDP_RTCP_FB_NACK_BASIC) |
sdp_rtcp_fb_nack_to_bitmap(SDP_RTCP_FB_NACK_PLI) |
sdp_rtcp_fb_ccm_to_bitmap(SDP_RTCP_FB_CCM_FIR);
break;
default:
fb_types = 0;
@ -5554,9 +5554,9 @@ gsmsdp_add_media_line (fsmdef_dcb_t *dcb_p, const cc_media_cap_t *media_cap,
/* Add supported rtcp-fb types */
if (media_cap->type == SDP_MEDIA_VIDEO) {
gsmsdp_add_rtcp_fb (level, dcb_p->sdp->src_sdp, RTP_VP8,
SDP_RTCP_FB_NACK_TO_BITMAP(SDP_RTCP_FB_NACK_BASIC) |
SDP_RTCP_FB_NACK_TO_BITMAP(SDP_RTCP_FB_NACK_PLI) |
SDP_RTCP_FB_CCM_TO_BITMAP(SDP_RTCP_FB_CCM_FIR));
sdp_rtcp_fb_nack_to_bitmap(SDP_RTCP_FB_NACK_BASIC) |
sdp_rtcp_fb_nack_to_bitmap(SDP_RTCP_FB_NACK_PLI) |
sdp_rtcp_fb_ccm_to_bitmap(SDP_RTCP_FB_CCM_FIR));
}
/* setup and connection attributes */

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

@ -474,51 +474,6 @@ typedef enum {
SDP_RTCP_UNICAST_MODE_NOT_PRESENT
} sdp_rtcp_unicast_mode_e;
/* a=rtcp-fb enumerations */
typedef enum {
SDP_RTCP_FB_ANY = -1,
SDP_RTCP_FB_ACK = 0,
SDP_RTCP_FB_CCM,
SDP_RTCP_FB_NACK,
SDP_RTCP_FB_TRR_INT,
SDP_MAX_RTCP_FB,
SDP_RTCP_FB_UNKNOWN
} sdp_rtcp_fb_type_e;
typedef enum {
SDP_RTCP_FB_NACK_NOT_FOUND = -1,
SDP_RTCP_FB_NACK_BASIC = 0,
SDP_RTCP_FB_NACK_SLI,
SDP_RTCP_FB_NACK_PLI,
SDP_RTCP_FB_NACK_RPSI,
SDP_RTCP_FB_NACK_APP,
SDP_RTCP_FB_NACK_RAI,
SDP_RTCP_FB_NACK_TLLEI,
SDP_RTCP_FB_NACK_PSLEI,
SDP_RTCP_FB_NACK_ECN,
SDP_MAX_RTCP_FB_NACK,
SDP_RTCP_FB_NACK_UNKNOWN
} sdp_rtcp_fb_nack_type_e;
typedef enum {
SDP_RTCP_FB_ACK_NOT_FOUND = -1,
SDP_RTCP_FB_ACK_RPSI = 0,
SDP_RTCP_FB_ACK_APP,
SDP_MAX_RTCP_FB_ACK,
SDP_RTCP_FB_ACK_UNKNOWN
} sdp_rtcp_fb_ack_type_e;
typedef enum {
SDP_RTCP_FB_CCM_NOT_FOUND = -1,
SDP_RTCP_FB_CCM_FIR = 0,
SDP_RTCP_FB_CCM_TMMBR,
SDP_RTCP_FB_CCM_TSTR,
SDP_RTCP_FB_CCM_VBCM,
SDP_MAX_RTCP_FB_CCM,
SDP_RTCP_FB_CCM_UNKNOWN
} sdp_rtcp_fb_ccm_type_e;
typedef enum {
SDP_CONNECTION_NOT_FOUND = -1,
SDP_CONNECTION_NEW = 0,
@ -527,11 +482,6 @@ typedef enum {
SDP_CONNECTION_UNKNOWN
} sdp_connection_type_e;
#define SDP_RTCP_FB_NACK_TO_BITMAP(type) (1 << (type))
#define SDP_RTCP_FB_ACK_TO_BITMAP(type) (1 << (SDP_MAX_RTCP_FB_NACK + (type)))
#define SDP_RTCP_FB_CCM_TO_BITMAP(type) (1 << (SDP_MAX_RTCP_FB_NACK + \
SDP_MAX_RTCP_FB_ACK + (type)))
/*
* sdp_srtp_fec_order_t
* This type defines the order in which to perform FEC

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

@ -47,6 +47,7 @@
#define __CCSDP_H__
#include "cpr_types.h"
#include "ccsdp_rtcp_fb.h"
#define SIPSDP_ILBC_MODE20 20

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

@ -0,0 +1,96 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __CCSDP_RTCP_FB_H__
#define __CCSDP_RTCP_FB_H__
/* a=rtcp-fb enumerations */
typedef enum {
SDP_RTCP_FB_ANY = -1,
SDP_RTCP_FB_ACK = 0,
SDP_RTCP_FB_CCM,
SDP_RTCP_FB_NACK,
SDP_RTCP_FB_TRR_INT,
SDP_MAX_RTCP_FB,
SDP_RTCP_FB_UNKNOWN
} sdp_rtcp_fb_type_e;
typedef enum {
SDP_RTCP_FB_NACK_NOT_FOUND = -1,
SDP_RTCP_FB_NACK_BASIC = 0,
SDP_RTCP_FB_NACK_SLI,
SDP_RTCP_FB_NACK_PLI,
SDP_RTCP_FB_NACK_RPSI,
SDP_RTCP_FB_NACK_APP,
SDP_RTCP_FB_NACK_RAI,
SDP_RTCP_FB_NACK_TLLEI,
SDP_RTCP_FB_NACK_PSLEI,
SDP_RTCP_FB_NACK_ECN,
SDP_MAX_RTCP_FB_NACK,
SDP_RTCP_FB_NACK_UNKNOWN
} sdp_rtcp_fb_nack_type_e;
typedef enum {
SDP_RTCP_FB_ACK_NOT_FOUND = -1,
SDP_RTCP_FB_ACK_RPSI = 0,
SDP_RTCP_FB_ACK_APP,
SDP_MAX_RTCP_FB_ACK,
SDP_RTCP_FB_ACK_UNKNOWN
} sdp_rtcp_fb_ack_type_e;
typedef enum {
SDP_RTCP_FB_CCM_NOT_FOUND = -1,
SDP_RTCP_FB_CCM_FIR = 0,
SDP_RTCP_FB_CCM_TMMBR,
SDP_RTCP_FB_CCM_TSTR,
SDP_RTCP_FB_CCM_VBCM,
SDP_MAX_RTCP_FB_CCM,
SDP_RTCP_FB_CCM_UNKNOWN
} sdp_rtcp_fb_ccm_type_e;
#if defined(__has_extension) && __has_extension(cxx_static_assert)
static_assert(SDP_MAX_RTCP_FB_NACK +
SDP_MAX_RTCP_FB_ACK +
SDP_MAX_RTCP_FB_CCM < 32,
"rtcp-fb Bitmap is larger than 32 bits");
#endif
static inline int32_t
sdp_rtcp_fb_nack_to_bitmap(sdp_rtcp_fb_nack_type_e type)
{
int bitnumber = type;
if (type < 0 || type >= SDP_MAX_RTCP_FB_NACK) {
return 0;
}
return (1 << bitnumber);
}
static inline int32_t
sdp_rtcp_fb_ack_to_bitmap(sdp_rtcp_fb_ack_type_e type)
{
int bitnumber = type + SDP_MAX_RTCP_FB_NACK;
if (type < 0 || type >= SDP_MAX_RTCP_FB_ACK) {
return 0;
}
return (1 << bitnumber);
}
static inline int32_t
sdp_rtcp_fb_ccm_to_bitmap(sdp_rtcp_fb_ccm_type_e type)
{
int bitnumber = type + SDP_MAX_RTCP_FB_NACK + SDP_MAX_RTCP_FB_ACK;
if (type < 0 || type >= SDP_MAX_RTCP_FB_CCM) {
return 0;
}
return (1 << bitnumber);
}
#endif

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

@ -573,8 +573,8 @@ class TransportConduitTest : public ::testing::Test
ASSERT_EQ(mozilla::kMediaConduitNoError, err);
//configure send and recv codecs on theconduit
mozilla::VideoCodecConfig cinst1(120, "VP8");
mozilla::VideoCodecConfig cinst2(124, "I420");
mozilla::VideoCodecConfig cinst1(120, "VP8", 0);
mozilla::VideoCodecConfig cinst2(124, "I420", 0);
std::vector<mozilla::VideoCodecConfig* > rcvCodecList;
@ -637,8 +637,8 @@ class TransportConduitTest : public ::testing::Test
cerr << " 1. Same Codec (VP8) Repeated Twice " << endl;
cerr << " *************************************************" << endl;
mozilla::VideoCodecConfig cinst1(120, "VP8");
mozilla::VideoCodecConfig cinst2(120, "VP8");
mozilla::VideoCodecConfig cinst1(120, "VP8", 0);
mozilla::VideoCodecConfig cinst2(120, "VP8", 0);
rcvCodecList.push_back(&cinst1);
rcvCodecList.push_back(&cinst2);
err = mVideoSession->ConfigureRecvMediaCodecs(rcvCodecList);
@ -654,8 +654,8 @@ class TransportConduitTest : public ::testing::Test
cerr << " Setting payload 1 with name: I4201234tttttthhhyyyy89087987y76t567r7756765rr6u6676" << endl;
cerr << " Setting payload 2 with name of zero length" << endl;
mozilla::VideoCodecConfig cinst3(124, "I4201234tttttthhhyyyy89087987y76t567r7756765rr6u6676");
mozilla::VideoCodecConfig cinst4(124, "");
mozilla::VideoCodecConfig cinst3(124, "I4201234tttttthhhyyyy89087987y76t567r7756765rr6u6676", 0);
mozilla::VideoCodecConfig cinst4(124, "", 0);
rcvCodecList.push_back(&cinst3);
rcvCodecList.push_back(&cinst4);