Bug 844177: set codec resolution based on input mediastream resolution r=ekr

This commit is contained in:
Randell Jesup 2013-02-22 15:02:34 -05:00
parent b4bba45507
commit 5c85934a22
6 changed files with 96 additions and 45 deletions

View File

@ -50,25 +50,22 @@ struct AudioCodecConfig
struct VideoCodecConfig
{
/*
* The data-types for these properties mimic the
* corresponding webrtc::VideoCodec data-types.
*/
int mType;
std::string mName;
int mWidth;
int mHeight;
VideoCodecConfig(int type, std::string name,int width,
int height): mType(type),
mName(name),
mWidth(width),
mHeight(height)
/* When we have resolution negotiation information (RFC 6236)
* it will be stored here.
*/
VideoCodecConfig(int type, std::string name): mType(type),
mName(name)
{
}
};
}
#endif
#endif

View File

@ -374,7 +374,7 @@ WebrtcVideoConduit::ConfigureSendMediaCodec(const VideoCodecConfig* codecConfig)
if(mPtrViEBase->StopSend(mChannel) == -1)
{
CSFLogError(logTag, "%s StopSend() Failed %d ",__FUNCTION__,
mPtrViEBase->LastError());
mPtrViEBase->LastError());
return kMediaConduitUnknownError;
}
}
@ -412,14 +412,16 @@ WebrtcVideoConduit::ConfigureSendMediaCodec(const VideoCodecConfig* codecConfig)
return kMediaConduitInvalidSendCodec;
}
CSFLogError(logTag, "%s SetSendCodec Failed %d ", __FUNCTION__,
mPtrViEBase->LastError());
mPtrViEBase->LastError());
return kMediaConduitUnknownError;
}
mSendingWidth = 0;
mSendingHeight = 0;
if(mPtrViEBase->StartSend(mChannel) == -1)
{
CSFLogError(logTag, "%s Start Send Error %d ", __FUNCTION__,
mPtrViEBase->LastError());
mPtrViEBase->LastError());
return kMediaConduitUnknownError;
}
@ -427,9 +429,7 @@ WebrtcVideoConduit::ConfigureSendMediaCodec(const VideoCodecConfig* codecConfig)
delete mCurSendCodecConfig;
mCurSendCodecConfig = new VideoCodecConfig(codecConfig->mType,
codecConfig->mName,
codecConfig->mWidth,
codecConfig->mHeight);
codecConfig->mName);
mPtrRTP->SetRembStatus(mChannel, true, false);
@ -440,7 +440,7 @@ WebrtcVideoConduit::ConfigureSendMediaCodec(const VideoCodecConfig* codecConfig)
MediaConduitErrorCode
WebrtcVideoConduit::ConfigureRecvMediaCodecs(
const std::vector<VideoCodecConfig* >& codecConfigList)
const std::vector<VideoCodecConfig* >& codecConfigList)
{
CSFLogDebug(logTag, "%s ", __FUNCTION__);
MediaConduitErrorCode condError = kMediaConduitNoError;
@ -460,7 +460,7 @@ WebrtcVideoConduit::ConfigureRecvMediaCodecs(
mEngineReceiving = false;
} else {
CSFLogError(logTag, "%s StopReceive() Failed %d ", __FUNCTION__,
mPtrViEBase->LastError());
mPtrViEBase->LastError());
return kMediaConduitUnknownError;
}
}
@ -498,10 +498,10 @@ WebrtcVideoConduit::ConfigureRecvMediaCodecs(
if(mPtrViECodec->SetReceiveCodec(mChannel,video_codec) == -1)
{
CSFLogError(logTag, "%s Invalid Receive Codec %d ", __FUNCTION__,
mPtrViEBase->LastError());
mPtrViEBase->LastError());
} else {
CSFLogError(logTag, "%s Successfully Set the codec %s", __FUNCTION__,
codecConfigList[i]->mName.c_str());
codecConfigList[i]->mName.c_str());
if(CopyCodecToDB(codecConfigList[i]))
{
success = true;
@ -539,6 +539,51 @@ WebrtcVideoConduit::ConfigureRecvMediaCodecs(
return kMediaConduitNoError;
}
// XXX we need to figure out how to feed back changes in preferred capture
// resolution to the getUserMedia source
bool
WebrtcVideoConduit::SelectSendResolution(unsigned short width,
unsigned short height)
{
// XXX This will do bandwidth-resolution adaptation as well - bug 877954
// Adapt to getUserMedia resolution changes
// check if we need to reconfigure the sending resolution
if (mSendingWidth != width || mSendingHeight != height)
{
// This will avoid us continually retrying this operation if it fails.
// If the resolution changes, we'll try again. In the meantime, we'll
// keep using the old size in the encoder.
mSendingWidth = width;
mSendingHeight = height;
// Get current vie codec.
webrtc::VideoCodec vie_codec;
WebRtc_Word32 err;
if ((err = mPtrViECodec->GetSendCodec(mChannel, vie_codec)) != 0)
{
CSFLogError(logTag, "%s: GetSendCodec failed, err %d", __FUNCTION__, err);
return false;
}
if (vie_codec.width != width || vie_codec.height != height)
{
vie_codec.width = width;
vie_codec.height = height;
if ((err = mPtrViECodec->SetSendCodec(mChannel, vie_codec)) != 0)
{
CSFLogError(logTag, "%s: SetSendCodec(%ux%u) failed, err %d",
__FUNCTION__, width, height, err);
return false;
}
CSFLogDebug(logTag, "%s: Encoder resolution changed to %ux%u",
__FUNCTION__, width, height);
} // else no change; mSendingWidth likely was 0
}
return true;
}
MediaConduitErrorCode
WebrtcVideoConduit::SendVideoFrame(unsigned char* video_frame,
@ -553,7 +598,7 @@ WebrtcVideoConduit::SendVideoFrame(unsigned char* video_frame,
//check for the parameters sanity
if(!video_frame || video_frame_length == 0 ||
width == 0 || height == 0)
width == 0 || height == 0)
{
CSFLogError(logTag, "%s Invalid Parameters ",__FUNCTION__);
MOZ_ASSERT(PR_FALSE);
@ -580,6 +625,15 @@ WebrtcVideoConduit::SendVideoFrame(unsigned char* video_frame,
return kMediaConduitSessionNotInited;
}
// enforce even width/height (paranoia)
MOZ_ASSERT(!(width & 1));
MOZ_ASSERT(!(height & 1));
if (!SelectSendResolution(width, height))
{
return kMediaConduitCaptureError;
}
//insert the frame to video engine in I420 format only
if(mPtrExtCapture->IncomingFrame(video_frame,
video_frame_length,
@ -726,8 +780,7 @@ WebrtcVideoConduit::CodecConfigToWebRTCCodec(const VideoCodecConfig* codecInfo,
webrtc::VideoCodec& cinst)
{
cinst.plType = codecInfo->mType;
cinst.width = codecInfo->mWidth;
cinst.height = codecInfo->mHeight;
// leave width/height alone; they'll be overridden on the first frame
cinst.minBitrate = 200;
cinst.startBitrate = 300;
cinst.maxBitrate = 2000;
@ -737,9 +790,7 @@ bool
WebrtcVideoConduit::CopyCodecToDB(const VideoCodecConfig* codecInfo)
{
VideoCodecConfig* cdcConfig = new VideoCodecConfig(codecInfo->mType,
codecInfo->mName,
codecInfo->mWidth,
codecInfo->mHeight);
codecInfo->mName);
mRecvCodecList.push_back(cdcConfig);
return true;
}
@ -774,9 +825,7 @@ WebrtcVideoConduit::CheckCodecsForMatch(const VideoCodecConfig* curCodecConfig,
}
if(curCodecConfig->mType == codecInfo->mType &&
(curCodecConfig->mName.compare(codecInfo->mName) == 0) &&
curCodecConfig->mWidth == codecInfo->mWidth &&
curCodecConfig->mHeight == codecInfo->mHeight)
curCodecConfig->mName.compare(codecInfo->mName) == 0)
{
return true;
}
@ -830,10 +879,7 @@ WebrtcVideoConduit::DumpCodecDB() const
{
CSFLogDebug(logTag,"Payload Name: %s", mRecvCodecList[i]->mName.c_str());
CSFLogDebug(logTag,"Payload Type: %d", mRecvCodecList[i]->mType);
CSFLogDebug(logTag,"Payload Width: %d", mRecvCodecList[i]->mWidth);
CSFLogDebug(logTag,"Payload Height: %d", mRecvCodecList[i]->mHeight);
}
}
}// end namespace

View File

@ -103,6 +103,14 @@ public:
*/
virtual MediaConduitErrorCode AttachTransport(mozilla::RefPtr<TransportInterface> aTransport);
/**
* Function to select and change the encoding resolution based on incoming frame size
* and current available bandwidth.
* @param width, height: dimensions of the frame
*/
virtual bool SelectSendResolution(unsigned short width,
unsigned short height);
/**
* Function to deliver a capture video frame for encoding and transport
* @param video_frame: pointer to captured video-frame.
@ -160,7 +168,9 @@ public:
mEngineReceiving(false),
mChannel(-1),
mCapId(-1),
mCurSendCodecConfig(nullptr)
mCurSendCodecConfig(nullptr),
mSendingWidth(0),
mSendingHeight(0)
{
}
@ -218,6 +228,8 @@ private:
int mCapId; // Capturer for this conduit
RecvCodecList mRecvCodecList;
VideoCodecConfig* mCurSendCodecConfig;
unsigned short mSendingWidth;
unsigned short mSendingHeight;
mozilla::RefPtr<WebrtcAudioConduit> mSyncedTo;
};

View File

@ -1480,9 +1480,7 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id,
{
config_raw = new mozilla::VideoCodecConfig(
payloads[i].remote_rtp_pt,
ccsdpCodecName(payloads[i].codec_type),
payloads[i].video.width,
payloads[i].video.height);
ccsdpCodecName(payloads[i].codec_type));
configs.push_back(config_raw);
}
@ -2106,9 +2104,7 @@ 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),
payload->video.width,
payload->video.height);
ccsdpCodecName(payload->codec_type));
// Take possession of this pointer
mozilla::ScopedDeletePtr<mozilla::VideoCodecConfig> config(config_raw);

View File

@ -574,8 +574,8 @@ class TransportConduitTest : public ::testing::Test
ASSERT_EQ(mozilla::kMediaConduitNoError, err);
//configure send and recv codecs on theconduit
mozilla::VideoCodecConfig cinst1(120, "VP8", 640, 480);
mozilla::VideoCodecConfig cinst2(124, "I420", 640, 480);
mozilla::VideoCodecConfig cinst1(120, "VP8");
mozilla::VideoCodecConfig cinst2(124, "I420");
std::vector<mozilla::VideoCodecConfig* > rcvCodecList;
@ -638,8 +638,8 @@ class TransportConduitTest : public ::testing::Test
cerr << " 1. Same Codec (VP8) Repeated Twice " << endl;
cerr << " *************************************************" << endl;
mozilla::VideoCodecConfig cinst1(120, "VP8", 640, 480);
mozilla::VideoCodecConfig cinst2(120, "VP8", 640, 480);
mozilla::VideoCodecConfig cinst1(120, "VP8");
mozilla::VideoCodecConfig cinst2(120, "VP8");
rcvCodecList.push_back(&cinst1);
rcvCodecList.push_back(&cinst2);
err = mVideoSession->ConfigureRecvMediaCodecs(rcvCodecList);
@ -655,8 +655,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", 352, 288);
mozilla::VideoCodecConfig cinst4(124, "", 352, 288);
mozilla::VideoCodecConfig cinst3(124, "I4201234tttttthhhyyyy89087987y76t567r7756765rr6u6676");
mozilla::VideoCodecConfig cinst4(124, "");
rcvCodecList.push_back(&cinst3);
rcvCodecList.push_back(&cinst4);

View File

@ -54,7 +54,7 @@ class TestAgent {
audio_pipeline_(),
video_flow_(new TransportFlow()),
video_prsock_(new TransportLayerPrsock()),
video_config_(120, "VP8", 640, 480),
video_config_(120, "VP8"),
video_conduit_(mozilla::VideoSessionConduit::Create()),
video_(),
video_pipeline_() {