| Index: content/renderer/media/video_track_recorder_unittest.cc
|
| diff --git a/content/renderer/media/video_track_recorder_unittest.cc b/content/renderer/media/video_track_recorder_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ca3dc03d36744748ce52a44e886c8caba2de526a
|
| --- /dev/null
|
| +++ b/content/renderer/media/video_track_recorder_unittest.cc
|
| @@ -0,0 +1,151 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/location.h"
|
| +#include "base/macros.h"
|
| +#include "base/memory/ref_counted.h"
|
| +#include "base/memory/scoped_ptr.h"
|
| +#include "base/run_loop.h"
|
| +#include "base/strings/utf_string_conversions.h"
|
| +#include "content/child/child_process.h"
|
| +#include "content/renderer/media/media_stream_video_track.h"
|
| +#include "content/renderer/media/mock_media_stream_video_source.h"
|
| +#include "content/renderer/media/video_track_recorder.h"
|
| +#include "media/base/video_frame.h"
|
| +#include "testing/gmock/include/gmock/gmock.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +#include "third_party/WebKit/public/platform/WebString.h"
|
| +#include "third_party/WebKit/public/web/WebHeap.h"
|
| +
|
| +using ::testing::_;
|
| +using ::testing::Mock;
|
| +using ::testing::Return;
|
| +using ::testing::SaveArg;
|
| +using ::testing::InSequence;
|
| +
|
| +namespace content {
|
| +
|
| +ACTION_P(RunClosure, closure) {
|
| + closure.Run();
|
| +}
|
| +
|
| +// Dummy interface class to be able to MOCK its methods.
|
| +class EncodedVideoHandlerInterface {
|
| + public:
|
| + virtual uint64_t OnFirstFrame(const gfx::Size& frame_size,
|
| + double frame_rate) = 0;
|
| + virtual void OnEncodedVideo(uint64_t track_number,
|
| + const base::StringPiece& encoded_data,
|
| + base::TimeDelta timestamp,
|
| + bool keyframe) = 0;
|
| + virtual ~EncodedVideoHandlerInterface() {}
|
| +};
|
| +
|
| +class VideoTrackRecorderTest : public testing::Test,
|
| + public EncodedVideoHandlerInterface {
|
| + public:
|
| + VideoTrackRecorderTest()
|
| + : child_process_(new ChildProcess()),
|
| + mock_source_(new MockMediaStreamVideoSource(false)) {
|
| + const blink::WebString webkit_track_id(base::UTF8ToUTF16("dummy"));
|
| + blink_source_.initialize(webkit_track_id,
|
| + blink::WebMediaStreamSource::TypeVideo,
|
| + webkit_track_id);
|
| + blink_source_.setExtraData(mock_source_);
|
| + blink_track_.initialize(blink_source_);
|
| +
|
| + blink::WebMediaConstraints constraints;
|
| + constraints.initialize();
|
| + track_ = new MediaStreamVideoTrack(mock_source_, constraints,
|
| + MediaStreamSource::ConstraintsCallback(),
|
| + true /* enabled */);
|
| + blink_track_.setExtraData(track_);
|
| +
|
| + video_track_recorder_.reset(new VideoTrackRecorder(
|
| + blink_track_, base::Bind(&VideoTrackRecorderTest::OnFirstFrame,
|
| + base::Unretained(this)),
|
| + base::Bind(&VideoTrackRecorderTest::OnEncodedVideo,
|
| + base::Unretained(this))));
|
| +
|
| + // Paranoia checks.
|
| + EXPECT_EQ(blink_track_.source().extraData(), blink_source_.extraData());
|
| + EXPECT_TRUE(message_loop_.IsCurrent());
|
| + }
|
| +
|
| + MOCK_METHOD2(OnFirstFrame,
|
| + uint64_t(const gfx::Size& frame_size, double frame_rate));
|
| + MOCK_METHOD4(OnEncodedVideo,
|
| + void(uint64_t track_index,
|
| + const base::StringPiece& encoded_data,
|
| + base::TimeDelta timestamp,
|
| + bool keyframe));
|
| +
|
| + void Encode(const scoped_refptr<media::VideoFrame>& frame,
|
| + const base::TimeTicks& estimated_capture_time) {
|
| + child_process_->io_message_loop()->PostTask(
|
| + FROM_HERE, base::Bind(&VideoTrackRecorder::EncodeOnIoForTesting,
|
| + base::Unretained(video_track_recorder_.get()),
|
| + frame, estimated_capture_time));
|
| + }
|
| +
|
| + bool IsEncoderConfigurationDone() const {
|
| + return video_track_recorder_->IsEncoderConfigurationDoneForTesting();
|
| + }
|
| +
|
| + // A ChildProcess and a MessageLoopForUI are both needed to fool the tracks
|
| + // and sources below into believing they are on the right threads.
|
| + const base::MessageLoopForUI message_loop_;
|
| + const scoped_ptr<ChildProcess> child_process_;
|
| + // All members are non-const due to the series of initialize() calls needed.
|
| + // |mock_source_| is owned by |blink_source_|, |track_| by |blink_track_|.
|
| + MockMediaStreamVideoSource* mock_source_;
|
| + blink::WebMediaStreamSource blink_source_;
|
| + MediaStreamVideoTrack* track_;
|
| + blink::WebMediaStreamTrack blink_track_;
|
| +
|
| + scoped_ptr<VideoTrackRecorder> video_track_recorder_;
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(VideoTrackRecorderTest);
|
| +};
|
| +
|
| +// Creates the encoder and encodes a frame; the encoder should be initialised
|
| +// and produce a keyframe.
|
| +TEST_F(VideoTrackRecorderTest, VideoEncoding) {
|
| + const int kWidth = 160; // Cannot be arbitrarily small, should be reasonable.
|
| + const int kHeight = 80;
|
| + const gfx::Size frame_size(kWidth, kHeight);
|
| + const scoped_refptr<media::VideoFrame> video_frame =
|
| + media::VideoFrame::CreateBlackFrame(frame_size);
|
| + const double kFrameRate = 60.0f;
|
| + video_frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE,
|
| + kFrameRate);
|
| + const base::TimeTicks capture_time = base::TimeTicks::Now();
|
| + const int kTrackIndex = 5;
|
| + const base::TimeDelta timedelta = base::TimeDelta::FromMilliseconds(0);
|
| +
|
| + EXPECT_FALSE(IsEncoderConfigurationDone());
|
| +
|
| + InSequence s;
|
| + EXPECT_CALL(*this, OnFirstFrame(frame_size, kFrameRate))
|
| + .Times(1)
|
| + .WillOnce(Return(kTrackIndex));
|
| + base::StringPiece encoded_data;
|
| + EXPECT_CALL(*this, OnEncodedVideo(kTrackIndex, _, timedelta, true))
|
| + .Times(1)
|
| + .WillOnce(SaveArg<1>(&encoded_data));
|
| + Encode(video_frame, capture_time);
|
| +
|
| + base::MessageLoopForUI::current()->RunUntilIdle();
|
| + child_process_->io_message_loop()->RunUntilIdle();
|
| +
|
| + EXPECT_TRUE(IsEncoderConfigurationDone());
|
| + const size_t kEncodedDataSize = 52;
|
| + EXPECT_EQ(encoded_data.size(), kEncodedDataSize);
|
| +
|
| + Mock::VerifyAndClearExpectations(this);
|
| +}
|
| +
|
| +} // namespace content
|
|
|