Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(41)

Unified Diff: chromecast/media/cma/filters/demuxer_stream_adapter_unittest.cc

Issue 542893003: Add the frame provider base class used in cast media. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chromecast/media/cma/filters/demuxer_stream_adapter.cc ('k') | chromecast/media/media.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chromecast/media/cma/filters/demuxer_stream_adapter_unittest.cc
diff --git a/chromecast/media/cma/filters/demuxer_stream_adapter_unittest.cc b/chromecast/media/cma/filters/demuxer_stream_adapter_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a5661a48ce1f04ce99a62a42f7c0c86caa485997
--- /dev/null
+++ b/chromecast/media/cma/filters/demuxer_stream_adapter_unittest.cc
@@ -0,0 +1,324 @@
+// Copyright 2014 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 <list>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/thread.h"
+#include "base/time/time.h"
+#include "chromecast/media/cma/base/balanced_media_task_runner_factory.h"
+#include "chromecast/media/cma/base/decoder_buffer_base.h"
+#include "chromecast/media/cma/filters/demuxer_stream_adapter.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/decoder_buffer.h"
+#include "media/base/demuxer_stream.h"
+#include "media/base/video_decoder_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromecast {
+namespace media {
+
+namespace {
+
+class DummyDemuxerStream : public ::media::DemuxerStream {
+ public:
+ // Creates a demuxer stream which provides frames either with a delay
+ // or instantly. The scheduling pattern is the following:
+ // - provides |delayed_frame_count| frames with a delay,
+ // - then provides the following |cycle_count| - |delayed_frame_count|
+ // instantly,
+ // - then provides |delayed_frame_count| frames with a delay,
+ // - ... and so on.
+ // Special cases:
+ // - all frames are delayed: |delayed_frame_count| = |cycle_count|
+ // - all frames are provided instantly: |delayed_frame_count| = 0
+ // |config_idx| is a list of frame index before which there is
+ // a change of decoder configuration.
+ DummyDemuxerStream(int cycle_count,
+ int delayed_frame_count,
+ const std::list<int>& config_idx);
+ virtual ~DummyDemuxerStream();
+
+ // ::media::DemuxerStream implementation.
+ virtual void Read(const ReadCB& read_cb) OVERRIDE;
+ virtual ::media::AudioDecoderConfig audio_decoder_config() OVERRIDE;
+ virtual ::media::VideoDecoderConfig video_decoder_config() OVERRIDE;
+ virtual Type type() OVERRIDE;
+ virtual void EnableBitstreamConverter() OVERRIDE;
+ virtual bool SupportsConfigChanges() OVERRIDE;
+ virtual ::media::VideoRotation video_rotation() OVERRIDE;
+
+ private:
+ void DoRead(const ReadCB& read_cb);
+
+ // Demuxer configuration.
+ const int cycle_count_;
+ const int delayed_frame_count_;
+ std::list<int> config_idx_;
+
+ // Number of frames sent so far.
+ int frame_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(DummyDemuxerStream);
+};
+
+DummyDemuxerStream::DummyDemuxerStream(
+ int cycle_count,
+ int delayed_frame_count,
+ const std::list<int>& config_idx)
+ : cycle_count_(cycle_count),
+ delayed_frame_count_(delayed_frame_count),
+ frame_count_(0),
+ config_idx_(config_idx) {
+ DCHECK_LE(delayed_frame_count, cycle_count);
+}
+
+DummyDemuxerStream::~DummyDemuxerStream() {
+}
+
+void DummyDemuxerStream::Read(const ReadCB& read_cb) {
+ if (!config_idx_.empty() && config_idx_.front() == frame_count_) {
+ config_idx_.pop_front();
+ read_cb.Run(kConfigChanged,
+ scoped_refptr< ::media::DecoderBuffer>());
+ return;
+ }
+
+ if ((frame_count_ % cycle_count_) < delayed_frame_count_) {
+ base::MessageLoopProxy::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&DummyDemuxerStream::DoRead, base::Unretained(this),
+ read_cb),
+ base::TimeDelta::FromMilliseconds(20));
+ return;
+ }
+ DoRead(read_cb);
+}
+
+::media::AudioDecoderConfig DummyDemuxerStream::audio_decoder_config() {
+ LOG(FATAL) << "DummyDemuxerStream is a video DemuxerStream";
+ return ::media::AudioDecoderConfig();
+}
+
+::media::VideoDecoderConfig DummyDemuxerStream::video_decoder_config() {
+ gfx::Size coded_size(640, 480);
+ gfx::Rect visible_rect(640, 480);
+ gfx::Size natural_size(640, 480);
+ return ::media::VideoDecoderConfig(
+ ::media::kCodecH264,
+ ::media::VIDEO_CODEC_PROFILE_UNKNOWN,
+ ::media::VideoFrame::YV12,
+ coded_size,
+ visible_rect,
+ natural_size,
+ NULL, 0,
+ false);
+}
+
+::media::DemuxerStream::Type DummyDemuxerStream::type() {
+ return VIDEO;
+}
+
+void DummyDemuxerStream::EnableBitstreamConverter() {
+}
+
+bool DummyDemuxerStream::SupportsConfigChanges() {
+ return true;
+}
+
+::media::VideoRotation DummyDemuxerStream::video_rotation() {
+ return ::media::VIDEO_ROTATION_0;
+}
+
+void DummyDemuxerStream::DoRead(const ReadCB& read_cb) {
+ scoped_refptr< ::media::DecoderBuffer> buffer(
+ new ::media::DecoderBuffer(16));
+ buffer->set_timestamp(frame_count_ * base::TimeDelta::FromMilliseconds(40));
+ frame_count_++;
+ read_cb.Run(kOk, buffer);
+}
+
+} // namespace
+
+class DemuxerStreamAdapterTest : public testing::Test {
+ public:
+ DemuxerStreamAdapterTest();
+ virtual ~DemuxerStreamAdapterTest();
+
+ void Initialize(::media::DemuxerStream* demuxer_stream);
+ void Start();
+
+ protected:
+ void OnTestTimeout();
+ void OnNewFrame(const scoped_refptr<DecoderBufferBase>& buffer,
+ const ::media::AudioDecoderConfig& audio_config,
+ const ::media::VideoDecoderConfig& video_config);
+ void OnFlushCompleted();
+
+ // Total number of frames to request.
+ int total_frames_;
+
+ // Number of demuxer read before issuing an early flush.
+ int early_flush_idx_;
+
+ // Number of expected read frames.
+ int total_expected_frames_;
+
+ // Number of frames actually read so far.
+ int frame_received_count_;
+
+ // List of expected frame indices with decoder config changes.
+ std::list<int> config_idx_;
+
+ scoped_ptr<CodedFrameProvider> coded_frame_provider_;
+
+ DISALLOW_COPY_AND_ASSIGN(DemuxerStreamAdapterTest);
+};
+
+DemuxerStreamAdapterTest::DemuxerStreamAdapterTest() {
+}
+
+DemuxerStreamAdapterTest::~DemuxerStreamAdapterTest() {
+}
+
+void DemuxerStreamAdapterTest::Initialize(
+ ::media::DemuxerStream* demuxer_stream) {
+ coded_frame_provider_.reset(
+ new DemuxerStreamAdapter(
+ base::MessageLoopProxy::current(),
+ scoped_refptr<BalancedMediaTaskRunnerFactory>(),
+ demuxer_stream));
+}
+
+void DemuxerStreamAdapterTest::Start() {
+ frame_received_count_ = 0;
+
+ // TODO(damienv): currently, test assertions which fail do not trigger the
+ // exit of the unit test, the message loop is still running. Find a different
+ // way to exit the unit test.
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&DemuxerStreamAdapterTest::OnTestTimeout,
+ base::Unretained(this)),
+ base::TimeDelta::FromSeconds(5));
+
+ coded_frame_provider_->Read(
+ base::Bind(&DemuxerStreamAdapterTest::OnNewFrame,
+ base::Unretained(this)));
+}
+
+void DemuxerStreamAdapterTest::OnTestTimeout() {
+ ADD_FAILURE() << "Test timed out";
+ if (base::MessageLoop::current())
+ base::MessageLoop::current()->QuitWhenIdle();
+}
+
+void DemuxerStreamAdapterTest::OnNewFrame(
+ const scoped_refptr<DecoderBufferBase>& buffer,
+ const ::media::AudioDecoderConfig& audio_config,
+ const ::media::VideoDecoderConfig& video_config) {
+ if (video_config.IsValidConfig()) {
+ ASSERT_GT(config_idx_.size(), 0);
+ ASSERT_EQ(frame_received_count_, config_idx_.front());
+ config_idx_.pop_front();
+ }
+
+ ASSERT_TRUE(buffer.get() != NULL);
+ ASSERT_EQ(buffer->timestamp(),
+ frame_received_count_ * base::TimeDelta::FromMilliseconds(40));
+ frame_received_count_++;
+
+ if (frame_received_count_ >= total_frames_) {
+ coded_frame_provider_->Flush(
+ base::Bind(&DemuxerStreamAdapterTest::OnFlushCompleted,
+ base::Unretained(this)));
+ return;
+ }
+
+ coded_frame_provider_->Read(
+ base::Bind(&DemuxerStreamAdapterTest::OnNewFrame,
+ base::Unretained(this)));
+
+ ASSERT_LE(frame_received_count_, early_flush_idx_);
+ if (frame_received_count_ == early_flush_idx_) {
+ coded_frame_provider_->Flush(
+ base::Bind(&DemuxerStreamAdapterTest::OnFlushCompleted,
+ base::Unretained(this)));
+ return;
+ }
+}
+
+void DemuxerStreamAdapterTest::OnFlushCompleted() {
+ ASSERT_EQ(frame_received_count_, total_expected_frames_);
+ base::MessageLoop::current()->QuitWhenIdle();
+}
+
+TEST_F(DemuxerStreamAdapterTest, NoDelay) {
+ total_frames_ = 10;
+ early_flush_idx_ = total_frames_; // No early flush.
+ total_expected_frames_ = 10;
+ config_idx_.push_back(0);
+ config_idx_.push_back(5);
+
+ int cycle_count = 1;
+ int delayed_frame_count = 0;
+ scoped_ptr<DummyDemuxerStream> demuxer_stream(
+ new DummyDemuxerStream(
+ cycle_count, delayed_frame_count, config_idx_));
+
+ scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
+ Initialize(demuxer_stream.get());
+ message_loop->PostTask(
+ FROM_HERE,
+ base::Bind(&DemuxerStreamAdapterTest::Start, base::Unretained(this)));
+ message_loop->Run();
+}
+
+TEST_F(DemuxerStreamAdapterTest, AllDelayed) {
+ total_frames_ = 10;
+ early_flush_idx_ = total_frames_; // No early flush.
+ total_expected_frames_ = 10;
+ config_idx_.push_back(0);
+ config_idx_.push_back(5);
+
+ int cycle_count = 1;
+ int delayed_frame_count = 1;
+ scoped_ptr<DummyDemuxerStream> demuxer_stream(
+ new DummyDemuxerStream(
+ cycle_count, delayed_frame_count, config_idx_));
+
+ scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
+ Initialize(demuxer_stream.get());
+ message_loop->PostTask(
+ FROM_HERE,
+ base::Bind(&DemuxerStreamAdapterTest::Start, base::Unretained(this)));
+ message_loop->Run();
+}
+
+TEST_F(DemuxerStreamAdapterTest, AllDelayedEarlyFlush) {
+ total_frames_ = 10;
+ early_flush_idx_ = 5;
+ total_expected_frames_ = 5;
+ config_idx_.push_back(0);
+ config_idx_.push_back(5);
+
+ int cycle_count = 1;
+ int delayed_frame_count = 1;
+ scoped_ptr<DummyDemuxerStream> demuxer_stream(
+ new DummyDemuxerStream(
+ cycle_count, delayed_frame_count, config_idx_));
+
+ scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
+ Initialize(demuxer_stream.get());
+ message_loop->PostTask(
+ FROM_HERE,
+ base::Bind(&DemuxerStreamAdapterTest::Start, base::Unretained(this)));
+ message_loop->Run();
+}
+
+} // namespace media
+} // namespace chromecast
« no previous file with comments | « chromecast/media/cma/filters/demuxer_stream_adapter.cc ('k') | chromecast/media/media.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698