From 67a9e402864c4b736732759f3a3f8da2229a4694 Mon Sep 17 00:00:00 2001 From: "pbos@webrtc.org" Date: Thu, 5 Mar 2015 13:57:37 +0000 Subject: [PATCH] Prevent encoding frames with wrong resolution. This is a speculative fix for a crash that should be able to happen if a codec is reconfigured while a frame is leaving the VideoProcessingModule, causing a mismatch between configured codec and input frame size. BUG= R=magjed@webrtc.org TBR=mflodman@webrtc.org Review URL: https://webrtc-codereview.appspot.com/48379004 Cr-Commit-Position: refs/heads/master@{#8615} git-svn-id: http://webrtc.googlecode.com/svn/trunk@8615 4adac7df-926f-26a2-2b94-8c16560cd09d --- webrtc/modules/video_coding/main/source/codec_database.cc | 4 ++++ webrtc/modules/video_coding/main/source/codec_database.h | 2 ++ webrtc/modules/video_coding/main/source/video_sender.cc | 7 +++++++ .../video_coding/main/source/video_sender_unittest.cc | 8 +++++++- 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/webrtc/modules/video_coding/main/source/codec_database.cc b/webrtc/modules/video_coding/main/source/codec_database.cc index 6ca7d9dd09..98dcc3b579 100644 --- a/webrtc/modules/video_coding/main/source/codec_database.cc +++ b/webrtc/modules/video_coding/main/source/codec_database.cc @@ -640,6 +640,10 @@ bool VCMCodecDataBase::SupportsRenderScheduling() const { return render_timing; } +bool VCMCodecDataBase::MatchesCurrentResolution(int width, int height) const { + return send_codec_.width == width && send_codec_.height == height; +} + VCMGenericDecoder* VCMCodecDataBase::CreateAndInitDecoder( uint8_t payload_type, VideoCodec* new_codec, diff --git a/webrtc/modules/video_coding/main/source/codec_database.h b/webrtc/modules/video_coding/main/source/codec_database.h index 762a909147..7078e29522 100644 --- a/webrtc/modules/video_coding/main/source/codec_database.h +++ b/webrtc/modules/video_coding/main/source/codec_database.h @@ -146,6 +146,8 @@ class VCMCodecDataBase { // the encoded frames. bool SupportsRenderScheduling() const; + bool MatchesCurrentResolution(int width, int height) const; + private: typedef std::map DecoderMap; typedef std::map ExternalDecoderMap; diff --git a/webrtc/modules/video_coding/main/source/video_sender.cc b/webrtc/modules/video_coding/main/source/video_sender.cc index bfd22bd028..5a4ed1f9d7 100644 --- a/webrtc/modules/video_coding/main/source/video_sender.cc +++ b/webrtc/modules/video_coding/main/source/video_sender.cc @@ -370,6 +370,13 @@ int32_t VideoSender::AddVideoFrame(const I420VideoFrame& videoFrame, return VCM_OK; } _mediaOpt.UpdateContentData(contentMetrics); + // TODO(pbos): Make sure setting send codec is synchronized with video + // processing so frame size always matches. + if (!_codecDataBase.MatchesCurrentResolution(videoFrame.width(), + videoFrame.height())) { + LOG(LS_ERROR) << "Incoming frame doesn't match set resolution. Dropping."; + return VCM_PARAMETER_ERROR; + } int32_t ret = _encoder->Encode(videoFrame, codecSpecificInfo, _nextFrameTypes); recorder_->Add(videoFrame); diff --git a/webrtc/modules/video_coding/main/source/video_sender_unittest.cc b/webrtc/modules/video_coding/main/source/video_sender_unittest.cc index de596d8e82..f28b9dfba4 100644 --- a/webrtc/modules/video_coding/main/source/video_sender_unittest.cc +++ b/webrtc/modules/video_coding/main/source/video_sender_unittest.cc @@ -70,12 +70,17 @@ MATCHER_P(MatchesVp8StreamInfo, expected, "") { class EmptyFrameGenerator : public FrameGenerator { public: + EmptyFrameGenerator(int width, int height) : width_(width), height_(height) {} I420VideoFrame* NextFrame() override { frame_.reset(new I420VideoFrame()); + frame_->CreateEmptyFrame(width_, height_, width_, (width_ + 1) / 2, + (width_ + 1) / 2); return frame_.get(); } private: + const int width_; + const int height_; rtc::scoped_ptr frame_; }; @@ -199,7 +204,6 @@ class TestVideoSenderWithMockEncoder : public TestVideoSender { void SetUp() override { TestVideoSender::SetUp(); - generator_.reset(new EmptyFrameGenerator()); EXPECT_EQ( 0, sender_->RegisterExternalEncoder(&encoder_, kUnusedPayloadType, false)); @@ -217,6 +221,8 @@ class TestVideoSenderWithMockEncoder : public TestVideoSender { ConfigureStream( kDefaultWidth, kDefaultHeight, 1200, &settings_.simulcastStream[2]); settings_.plType = kUnusedPayloadType; // Use the mocked encoder. + generator_.reset( + new EmptyFrameGenerator(settings_.width, settings_.height)); EXPECT_EQ(0, sender_->RegisterSendCodec(&settings_, 1, 1200)); }