Implement Base::ConstrainNewCodec2.
BUG=1788 R=wu@webrtc.org Review URL: https://webrtc-codereview.appspot.com/15009004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@6743 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
3edbaaf337
commit
8fdeee6abf
@ -73,28 +73,8 @@ VideoCodecPref kUlpfecPref = {117, kUlpfecCodecName, -1};
|
||||
|
||||
// The formats are sorted by the descending order of width. We use the order to
|
||||
// find the next format for CPU and bandwidth adaptation.
|
||||
const VideoFormatPod kDefaultVideoFormat = {
|
||||
const VideoFormatPod kDefaultMaxVideoFormat = {
|
||||
640, 400, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY};
|
||||
const VideoFormatPod kVideoFormats[] = {
|
||||
{1280, 800, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
|
||||
{1280, 720, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
|
||||
{960, 600, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
|
||||
{960, 540, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
|
||||
kDefaultVideoFormat,
|
||||
{640, 360, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
|
||||
{640, 480, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
|
||||
{480, 300, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
|
||||
{480, 270, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
|
||||
{480, 360, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
|
||||
{320, 200, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
|
||||
{320, 180, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
|
||||
{320, 240, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
|
||||
{240, 150, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
|
||||
{240, 135, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
|
||||
{240, 180, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
|
||||
{160, 100, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
|
||||
{160, 90, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY},
|
||||
{160, 120, FPS_TO_INTERVAL(kDefaultFramerate), FOURCC_ANY}, };
|
||||
|
||||
static bool FindFirstMatchingCodec(const std::vector<VideoCodec>& codecs,
|
||||
const VideoCodec& requested_codec,
|
||||
@ -107,49 +87,6 @@ static bool FindFirstMatchingCodec(const std::vector<VideoCodec>& codecs,
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static bool FindBestVideoFormat(int max_width,
|
||||
int max_height,
|
||||
int aspect_width,
|
||||
int aspect_height,
|
||||
VideoFormat* video_format) {
|
||||
assert(max_width > 0);
|
||||
assert(max_height > 0);
|
||||
assert(aspect_width > 0);
|
||||
assert(aspect_height > 0);
|
||||
VideoFormat best_format;
|
||||
for (int i = 0; i < ARRAY_SIZE(kVideoFormats); ++i) {
|
||||
const VideoFormat format(kVideoFormats[i]);
|
||||
|
||||
// Skip any format that is larger than the local or remote maximums, or
|
||||
// smaller than the current best match
|
||||
if (format.width > max_width || format.height > max_height ||
|
||||
(format.width < best_format.width &&
|
||||
format.height < best_format.height)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we don't have any matches yet, this is the best so far.
|
||||
if (best_format.width == 0) {
|
||||
best_format = format;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Prefer closer aspect ratios i.e:
|
||||
// |format| aspect - requested aspect <
|
||||
// |best_format| aspect - requested aspect
|
||||
if (abs(format.width * aspect_height * best_format.height -
|
||||
aspect_width * format.height * best_format.height) <
|
||||
abs(best_format.width * aspect_height * format.height -
|
||||
aspect_width * format.height * best_format.height)) {
|
||||
best_format = format;
|
||||
}
|
||||
}
|
||||
if (best_format.width != 0) {
|
||||
*video_format = best_format;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void AddDefaultFeedbackParams(VideoCodec* codec) {
|
||||
const FeedbackParam kFir(kRtcpFbParamCcm, kRtcpFbCcmParamFir);
|
||||
@ -170,8 +107,8 @@ static bool IsNackEnabled(const VideoCodec& codec) {
|
||||
static VideoCodec DefaultVideoCodec() {
|
||||
VideoCodec default_codec(kDefaultVideoCodecPref.payload_type,
|
||||
kDefaultVideoCodecPref.name,
|
||||
kDefaultVideoFormat.width,
|
||||
kDefaultVideoFormat.height,
|
||||
kDefaultMaxVideoFormat.width,
|
||||
kDefaultMaxVideoFormat.height,
|
||||
kDefaultFramerate,
|
||||
0);
|
||||
AddDefaultFeedbackParams(&default_codec);
|
||||
@ -267,7 +204,7 @@ void WebRtcVideoEngine2::Construct(WebRtcVideoChannelFactory* channel_factory,
|
||||
channel_factory_ = channel_factory;
|
||||
|
||||
video_codecs_ = DefaultVideoCodecs();
|
||||
default_codec_format_ = VideoFormat(kDefaultVideoFormat);
|
||||
default_codec_format_ = VideoFormat(kDefaultMaxVideoFormat);
|
||||
|
||||
rtp_header_extensions_.push_back(
|
||||
RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension,
|
||||
@ -320,8 +257,21 @@ bool WebRtcVideoEngine2::SetOptions(const VideoOptions& options) {
|
||||
|
||||
bool WebRtcVideoEngine2::SetDefaultEncoderConfig(
|
||||
const VideoEncoderConfig& config) {
|
||||
// TODO(pbos): Implement. Should be covered by corresponding unit tests.
|
||||
LOG(LS_VERBOSE) << "SetDefaultEncoderConfig()";
|
||||
const VideoCodec& codec = config.max_codec;
|
||||
// TODO(pbos): Make use of external encoder factory.
|
||||
if (!GetVideoEncoderFactory()->SupportsCodec(codec)) {
|
||||
LOG(LS_ERROR) << "SetDefaultEncoderConfig, codec not supported:"
|
||||
<< codec.ToString();
|
||||
return false;
|
||||
}
|
||||
|
||||
default_codec_format_ =
|
||||
VideoFormat(codec.width,
|
||||
codec.height,
|
||||
VideoFormat::FpsToInterval(codec.framerate),
|
||||
FOURCC_ANY);
|
||||
video_codecs_.clear();
|
||||
video_codecs_.push_back(codec);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -382,17 +332,10 @@ bool WebRtcVideoEngine2::FindCodec(const VideoCodec& in) {
|
||||
// TODO(pbos): Probe encoder factory to figure out that the codec is supported
|
||||
// if supported by the encoder factory. Add a corresponding test that fails
|
||||
// with this code (that doesn't ask the factory).
|
||||
for (int i = 0; i < ARRAY_SIZE(kVideoFormats); ++i) {
|
||||
const VideoFormat fmt(kVideoFormats[i]);
|
||||
if ((in.width != 0 || in.height != 0) &&
|
||||
(fmt.width != in.width || fmt.height != in.height)) {
|
||||
continue;
|
||||
}
|
||||
for (size_t j = 0; j < video_codecs_.size(); ++j) {
|
||||
VideoCodec codec(video_codecs_[j].id, video_codecs_[j].name, 0, 0, 0, 0);
|
||||
if (codec.Matches(in)) {
|
||||
return true;
|
||||
}
|
||||
for (size_t j = 0; j < video_codecs_.size(); ++j) {
|
||||
VideoCodec codec(video_codecs_[j].id, video_codecs_[j].name, 0, 0, 0, 0);
|
||||
if (codec.Matches(in)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -406,7 +349,6 @@ bool WebRtcVideoEngine2::CanSendCodec(const VideoCodec& requested,
|
||||
const VideoCodec& current,
|
||||
VideoCodec* out) {
|
||||
assert(out != NULL);
|
||||
// TODO(pbos): Implement.
|
||||
|
||||
if (requested.width != requested.height &&
|
||||
(requested.height == 0 || requested.width == 0)) {
|
||||
@ -420,37 +362,26 @@ bool WebRtcVideoEngine2::CanSendCodec(const VideoCodec& requested,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pick the best quality that is within their and our bounds and has the
|
||||
// correct aspect ratio.
|
||||
VideoFormat format;
|
||||
if (requested.width == 0 && requested.height == 0) {
|
||||
// Special case with resolution 0. The channel should not send frames.
|
||||
} else {
|
||||
int max_width = talk_base::_min(requested.width, matching_codec.width);
|
||||
int max_height = talk_base::_min(requested.height, matching_codec.height);
|
||||
int aspect_width = max_width;
|
||||
int aspect_height = max_height;
|
||||
if (current.width > 0 && current.height > 0) {
|
||||
aspect_width = current.width;
|
||||
aspect_height = current.height;
|
||||
}
|
||||
if (!FindBestVideoFormat(
|
||||
max_width, max_height, aspect_width, aspect_height, &format)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
out->id = requested.id;
|
||||
out->name = requested.name;
|
||||
out->preference = requested.preference;
|
||||
out->params = requested.params;
|
||||
out->framerate =
|
||||
talk_base::_min(requested.framerate, matching_codec.framerate);
|
||||
out->width = format.width;
|
||||
out->height = format.height;
|
||||
out->params = requested.params;
|
||||
out->feedback_params = requested.feedback_params;
|
||||
return true;
|
||||
out->width = requested.width;
|
||||
out->height = requested.height;
|
||||
if (requested.width == 0 && requested.height == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
while (out->width > matching_codec.width) {
|
||||
out->width /= 2;
|
||||
out->height /= 2;
|
||||
}
|
||||
|
||||
return out->width > 0 && out->height > 0;
|
||||
}
|
||||
|
||||
bool WebRtcVideoEngine2::SetVoiceEngine(WebRtcVoiceEngine* voice_engine) {
|
||||
|
@ -350,8 +350,10 @@ TEST_F(WebRtcVideoEngine2Test, FindCodec) {
|
||||
vp8_diff_id.id = 97;
|
||||
EXPECT_TRUE(engine_.FindCodec(vp8_diff_id));
|
||||
|
||||
// FindCodec ignores the codec size.
|
||||
// Test that FindCodec can accept uncommon codec size.
|
||||
cricket::VideoCodec vp8_diff_res(104, "VP8", 320, 111, 30, 0);
|
||||
EXPECT_FALSE(engine_.FindCodec(vp8_diff_res));
|
||||
EXPECT_TRUE(engine_.FindCodec(vp8_diff_res));
|
||||
|
||||
// PeerConnection doesn't negotiate the resolution at this point.
|
||||
// Test that FindCodec can handle the case when width/height is 0.
|
||||
@ -424,6 +426,17 @@ TEST_F(WebRtcVideoEngine2Test, SetSendFailsBeforeSettingCodecs) {
|
||||
<< "Channel should be stoppable even without set codecs.";
|
||||
}
|
||||
|
||||
class WebRtcVideoEngine2BaseTest
|
||||
: public VideoEngineTest<cricket::WebRtcVideoEngine2> {
|
||||
protected:
|
||||
typedef VideoEngineTest<cricket::WebRtcVideoEngine2> Base;
|
||||
};
|
||||
|
||||
#define WEBRTC_ENGINE_BASE_TEST(test) \
|
||||
TEST_F(WebRtcVideoEngine2BaseTest, test) { Base::test##Body(); }
|
||||
|
||||
WEBRTC_ENGINE_BASE_TEST(ConstrainNewCodec2);
|
||||
|
||||
class WebRtcVideoChannel2BaseTest
|
||||
: public VideoMediaChannelTest<WebRtcVideoEngine2, WebRtcVideoChannel2> {
|
||||
protected:
|
||||
@ -431,118 +444,74 @@ class WebRtcVideoChannel2BaseTest
|
||||
typedef VideoMediaChannelTest<WebRtcVideoEngine2, WebRtcVideoChannel2> Base;
|
||||
};
|
||||
|
||||
#define WEBRTC_BASE_TEST(test) \
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, test) { Base::test(); }
|
||||
|
||||
#define WEBRTC_DISABLED_BASE_TEST(test) \
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, DISABLED_ ## test) { Base::test(); }
|
||||
|
||||
// TODO(pbos): Fix WebRtcVideoEngine2BaseTest, where we want CheckCoInitialize.
|
||||
#if 0
|
||||
// TODO(juberti): Figure out why ViE is munging the COM refcount.
|
||||
#ifdef WIN32
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, DISABLED_CheckCoInitialize) {
|
||||
WEBRTC_DISABLED_BASE_TEST(CheckCoInitialize) {
|
||||
Base::CheckCoInitialize();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, SetSend) { Base::SetSend(); }
|
||||
WEBRTC_BASE_TEST(SetSend);
|
||||
WEBRTC_BASE_TEST(SetSendWithoutCodecs);
|
||||
WEBRTC_BASE_TEST(SetSendSetsTransportBufferSizes);
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, SetSendWithoutCodecs) {
|
||||
Base::SetSendWithoutCodecs();
|
||||
}
|
||||
WEBRTC_BASE_TEST(GetStats);
|
||||
WEBRTC_BASE_TEST(GetStatsMultipleRecvStreams);
|
||||
WEBRTC_BASE_TEST(GetStatsMultipleSendStreams);
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, SetSendSetsTransportBufferSizes) {
|
||||
Base::SetSendSetsTransportBufferSizes();
|
||||
}
|
||||
WEBRTC_BASE_TEST(SetSendBandwidth);
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, GetStats) { Base::GetStats(); }
|
||||
WEBRTC_BASE_TEST(SetSendSsrc);
|
||||
WEBRTC_BASE_TEST(SetSendSsrcAfterSetCodecs);
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, GetStatsMultipleRecvStreams) {
|
||||
Base::GetStatsMultipleRecvStreams();
|
||||
}
|
||||
WEBRTC_BASE_TEST(SetRenderer);
|
||||
WEBRTC_BASE_TEST(AddRemoveRecvStreams);
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, GetStatsMultipleSendStreams) {
|
||||
Base::GetStatsMultipleSendStreams();
|
||||
}
|
||||
WEBRTC_DISABLED_BASE_TEST(AddRemoveRecvStreamAndRender);
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, SetSendBandwidth) {
|
||||
Base::SetSendBandwidth();
|
||||
}
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, SetSendSsrc) { Base::SetSendSsrc(); }
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, SetSendSsrcAfterSetCodecs) {
|
||||
Base::SetSendSsrcAfterSetCodecs();
|
||||
}
|
||||
WEBRTC_BASE_TEST(AddRemoveRecvStreamsNoConference);
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, SetRenderer) { Base::SetRenderer(); }
|
||||
WEBRTC_BASE_TEST(AddRemoveSendStreams);
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, AddRemoveRecvStreams) {
|
||||
Base::AddRemoveRecvStreams();
|
||||
}
|
||||
WEBRTC_BASE_TEST(SimulateConference);
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, DISABLED_AddRemoveRecvStreamAndRender) {
|
||||
Base::AddRemoveRecvStreamAndRender();
|
||||
}
|
||||
WEBRTC_BASE_TEST(AddRemoveCapturer);
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, AddRemoveRecvStreamsNoConference) {
|
||||
Base::AddRemoveRecvStreamsNoConference();
|
||||
}
|
||||
WEBRTC_BASE_TEST(RemoveCapturerWithoutAdd);
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, AddRemoveSendStreams) {
|
||||
Base::AddRemoveSendStreams();
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, SimulateConference) {
|
||||
Base::SimulateConference();
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, AddRemoveCapturer) {
|
||||
Base::AddRemoveCapturer();
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, RemoveCapturerWithoutAdd) {
|
||||
Base::RemoveCapturerWithoutAdd();
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, AddRemoveCapturerMultipleSources) {
|
||||
Base::AddRemoveCapturerMultipleSources();
|
||||
}
|
||||
WEBRTC_BASE_TEST(AddRemoveCapturerMultipleSources);
|
||||
|
||||
// TODO(pbos): Figure out why this fails so often.
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, DISABLED_HighAspectHighHeightCapturer) {
|
||||
Base::HighAspectHighHeightCapturer();
|
||||
}
|
||||
WEBRTC_DISABLED_BASE_TEST(HighAspectHighHeightCapturer);
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, RejectEmptyStreamParams) {
|
||||
Base::RejectEmptyStreamParams();
|
||||
}
|
||||
WEBRTC_BASE_TEST(RejectEmptyStreamParams);
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, AdaptResolution16x10) {
|
||||
Base::AdaptResolution16x10();
|
||||
}
|
||||
WEBRTC_BASE_TEST(AdaptResolution16x10);
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, AdaptResolution4x3) {
|
||||
Base::AdaptResolution4x3();
|
||||
}
|
||||
WEBRTC_BASE_TEST(AdaptResolution4x3);
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, MuteStream) { Base::MuteStream(); }
|
||||
WEBRTC_BASE_TEST(MuteStream);
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, MultipleSendStreams) {
|
||||
Base::MultipleSendStreams();
|
||||
}
|
||||
WEBRTC_BASE_TEST(MultipleSendStreams);
|
||||
|
||||
// TODO(juberti): Restore this test once we support sending 0 fps.
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, DISABLED_AdaptDropAllFrames) {
|
||||
Base::AdaptDropAllFrames();
|
||||
}
|
||||
WEBRTC_DISABLED_BASE_TEST(AdaptDropAllFrames);
|
||||
// TODO(juberti): Understand why we get decode errors on this test.
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, DISABLED_AdaptFramerate) {
|
||||
Base::AdaptFramerate();
|
||||
}
|
||||
WEBRTC_DISABLED_BASE_TEST(AdaptFramerate);
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, SetSendStreamFormat0x0) {
|
||||
Base::SetSendStreamFormat0x0();
|
||||
}
|
||||
WEBRTC_BASE_TEST(SetSendStreamFormat0x0);
|
||||
|
||||
// TODO(zhurunz): Fix the flakey test.
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, DISABLED_SetSendStreamFormat) {
|
||||
Base::SetSendStreamFormat();
|
||||
}
|
||||
WEBRTC_DISABLED_BASE_TEST(SetSendStreamFormat);
|
||||
|
||||
TEST_F(WebRtcVideoChannel2BaseTest, TwoStreamsSendAndReceive) {
|
||||
Base::TwoStreamsSendAndReceive(kVp8Codec);
|
||||
|
Loading…
x
Reference in New Issue
Block a user