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

Unified Diff: chromecast/media/cma/backend/media_component_device_feeder_for_test.cc

Issue 622853002: Chromecast: adds interfaces for hardware layer of CMA pipeline. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@cma-decrypt-context
Patch Set: rebased onto CMA testing CL Created 6 years, 2 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
Index: chromecast/media/cma/backend/media_component_device_feeder_for_test.cc
diff --git a/chromecast/media/cma/backend/media_component_device_feeder_for_test.cc b/chromecast/media/cma/backend/media_component_device_feeder_for_test.cc
new file mode 100644
index 0000000000000000000000000000000000000000..87b6c0803d326761fee3283e4b3f89fa9eb67ec6
--- /dev/null
+++ b/chromecast/media/cma/backend/media_component_device_feeder_for_test.cc
@@ -0,0 +1,209 @@
+// 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 "chromecast/media/cma/backend/media_component_device_feeder_for_test.h"
+
+#include <list>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/time/time.h"
+#include "chromecast/media/base/decrypt_context.h"
+#include "chromecast/media/cma/backend/audio_pipeline_device.h"
+#include "chromecast/media/cma/backend/media_clock_device.h"
+#include "chromecast/media/cma/backend/media_pipeline_device.h"
+#include "chromecast/media/cma/backend/video_pipeline_device.h"
+#include "chromecast/media/cma/base/decoder_buffer_adapter.h"
+#include "chromecast/media/cma/base/decoder_buffer_base.h"
+#include "chromecast/media/cma/test/frame_segmenter_for_test.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/buffers.h"
+#include "media/base/decoder_buffer.h"
+#include "media/base/video_decoder_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromecast {
+namespace media {
+
+MediaComponentDeviceFeeder::MediaComponentDeviceFeeder(
+ MediaComponentDevice *device,
+ MediaClockDevice *clock,
+ const FrameList& frames)
+ : media_component_device_(device),
+ media_clock_device_(clock),
+ rendering_frame_idx_(1),
+ clock_frame_idx_(1),
+ eos_cb_(),
+ feeding_completed_(false),
+ frame_count_since_last_pause_(0),
+ frame_count_between_pause_(0),
+ delayed_feed_pattern_(),
+ delayed_feed_pattern_idx_(0) {
+ // Copy pointers over, claiming ownership on buffers
+ frames_ = frames;
+ delayed_feed_pattern_.push_back(false);
+}
+
+MediaComponentDeviceFeeder::~MediaComponentDeviceFeeder() {
+}
+
+// Accessors
+void MediaComponentDeviceFeeder::SetEosCB(base::Callback<void()> eos_cb) {
+ eos_cb_ = eos_cb;
+}
+
+void MediaComponentDeviceFeeder::SetFrameCountBetweenPause(int frame_count) {
+ ASSERT_GT(frame_count,0);
+ frame_count_between_pause_ = frame_count;
+}
+
+void MediaComponentDeviceFeeder::SetDelayedFeedPattern(
+ const std::vector<bool>& pattern) {
+ // Copy pattern over
+ delayed_feed_pattern_ = pattern;
+}
+
+void MediaComponentDeviceFeeder::Initialize() {
+ MediaComponentDevice::Client client;
+ client.eos_cb =
+ base::Bind(&MediaComponentDeviceFeeder::OnEos, base::Unretained(this));
+ media_component_device_->SetClient(client);
+
+ bool success =
+ media_component_device_->SetState(MediaComponentDevice::kStateIdle);
+ ASSERT_TRUE(success);
+ success = media_component_device_->SetStartPts(base::TimeDelta());
+ ASSERT_TRUE(success);
+ success =
+ media_component_device_->SetState(MediaComponentDevice::kStatePaused);
+ ASSERT_TRUE(success);
+}
+
+void MediaComponentDeviceFeeder::Feed() {
+ // Start rendering if needed.
+ if (rendering_frame_idx_ == 0) {
+ media_component_device_->SetState(MediaComponentDevice::kStateRunning);
+ } else {
+ rendering_frame_idx_--;
+ }
+
+ // Start the clock if needed.
+ if (clock_frame_idx_ == 0) {
+ media_clock_device_->SetState(MediaClockDevice::kStateRunning);
+ } else {
+ clock_frame_idx_--;
+ }
+
+ // Possibly feed one frame
+ DCHECK(!frames_.empty());
+ scoped_refptr<DecoderBufferBase> buffer = frames_.front();
+
+ MediaComponentDevice::FrameStatus status =
+ media_component_device_->PushFrame(
+ scoped_refptr<DecryptContext>(),
+ buffer,
+ base::Bind(&MediaComponentDeviceFeeder::OnFramePushed,
+ base::Unretained(this)));
+ EXPECT_NE(status, MediaComponentDevice::kFrameFailed);
+ frames_.pop_front();
+
+ // Feeding is done, just wait for the end of stream callback.
+ if (buffer->end_of_stream() || frames_.empty()) {
+ if (frames_.empty() && !buffer->end_of_stream()) {
+ LOG(WARNING) << "Stream emptied without feeding EOS frame";
+ }
+
+ feeding_completed_ = true;
+ return;
+ }
+
+ if (status == MediaComponentDevice::kFramePending)
+ return;
+
+ OnFramePushed(MediaComponentDevice::kFrameSuccess);
+}
+
+void MediaComponentDeviceFeeder::OnFramePushed(
+ MediaComponentDevice::FrameStatus status) {
+ EXPECT_NE(status, MediaComponentDevice::kFrameFailed);
+ if (feeding_completed_)
+ return;
+
+ // Introduce some pauses in the playback at regular intervals.
+ if (frame_count_between_pause_) {
+ frame_count_since_last_pause_ =
+ (frame_count_since_last_pause_ + 1) % frame_count_between_pause_;
+ if (frame_count_since_last_pause_ == 0) {
+ Pause();
+ return;
+ }
+ }
+
+ // Feeder loop.
+ bool delayed_feed = delayed_feed_pattern_[delayed_feed_pattern_idx_];
+ delayed_feed_pattern_idx_ =
+ (delayed_feed_pattern_idx_ + 1) % delayed_feed_pattern_.size();
+
+ if (delayed_feed) {
+ base::MessageLoopProxy::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&MediaComponentDeviceFeeder::Feed,
+ base::Unretained(this)),
+ base::TimeDelta::FromMilliseconds(50));
+ } else {
+ base::MessageLoopProxy::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&MediaComponentDeviceFeeder::Feed,
+ base::Unretained(this)));
+ }
+}
+
+void MediaComponentDeviceFeeder::Pause() {
+ media_clock_device_->SetRate(0.0);
+ media_time_ = media_clock_device_->GetTime();
+ base::MessageLoopProxy::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&MediaComponentDeviceFeeder::OnPauseCompleted,
+ base::Unretained(this)),
+ base::TimeDelta::FromMilliseconds(500));
+}
+
+void MediaComponentDeviceFeeder::OnPauseCompleted() {
+ // Make sure the media time didn't move during that time.
+ base::TimeDelta media_time = media_clock_device_->GetTime();
+
+ // TODO(gunsch): this should be EXPECT_EQ(media_time, media_time_);
+ // However, some backends may move the time forward when rendering the first
+ // frame while in paused mode. This behaviour is not intended.
+ EXPECT_GE(media_time, media_time_);
+ EXPECT_LE(media_time, media_time_ + base::TimeDelta::FromMilliseconds(50));
+
+ // Resume playback and frame feeding.
+ media_clock_device_->SetRate(1.0);
+
+ Feed();
+}
+
+void MediaComponentDeviceFeeder::OnEos() {
+ // Shutdown the pipeline.
+ bool success = media_component_device_->SetState(
+ MediaComponentDevice::kStateIdle);
+ ASSERT_TRUE(success);
+ success = media_component_device_->SetState(
+ MediaComponentDevice::kStateUninitialized);
+ ASSERT_TRUE(success);
+
+ if(!eos_cb_.is_null()) {
+ eos_cb_.Run();
+ }
+}
+
+} // namespace media
+} // namespace chromecast

Powered by Google App Engine
This is Rietveld 408576698