summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chromecast/media/audio/cast_audio_output_stream.cc10
-rw-r--r--chromecast/media/audio/cast_audio_output_stream_unittest.cc10
-rw-r--r--chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc30
-rw-r--r--chromecast/media/cma/backend/media_pipeline_backend_default.cc6
-rw-r--r--chromecast/media/cma/base/BUILD.gn2
-rw-r--r--chromecast/media/cma/base/cast_decoder_buffer_impl.cc50
-rw-r--r--chromecast/media/cma/base/cast_decoder_buffer_impl.h54
-rw-r--r--chromecast/media/cma/base/decoder_buffer_adapter.cc4
-rw-r--r--chromecast/media/cma/base/decoder_buffer_adapter.h4
-rw-r--r--chromecast/media/cma/base/decoder_buffer_base.h54
-rw-r--r--chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.cc8
-rw-r--r--chromecast/media/cma/pipeline/audio_pipeline_impl.cc5
-rw-r--r--chromecast/media/cma/pipeline/audio_pipeline_impl.h1
-rw-r--r--chromecast/media/cma/pipeline/av_pipeline_impl.cc53
-rw-r--r--chromecast/media/cma/pipeline/av_pipeline_impl.h5
-rw-r--r--chromecast/media/cma/pipeline/decrypt_util.cc4
-rw-r--r--chromecast/media/cma/pipeline/media_pipeline_impl.cc6
-rw-r--r--chromecast/media/cma/pipeline/video_pipeline_impl.cc5
-rw-r--r--chromecast/media/cma/pipeline/video_pipeline_impl.h1
-rw-r--r--chromecast/media/media.gyp2
-rw-r--r--chromecast/public/media/cast_decoder_buffer.h14
-rw-r--r--chromecast/public/media/media_pipeline_backend.h9
22 files changed, 123 insertions, 214 deletions
diff --git a/chromecast/media/audio/cast_audio_output_stream.cc b/chromecast/media/audio/cast_audio_output_stream.cc
index 9ba059f1..e283ab0 100644
--- a/chromecast/media/audio/cast_audio_output_stream.cc
+++ b/chromecast/media/audio/cast_audio_output_stream.cc
@@ -12,7 +12,6 @@
#include "chromecast/base/task_runner_impl.h"
#include "chromecast/media/audio/cast_audio_manager.h"
#include "chromecast/media/base/media_message_loop.h"
-#include "chromecast/media/cma/base/cast_decoder_buffer_impl.h"
#include "chromecast/media/cma/base/decoder_buffer_adapter.h"
#include "chromecast/public/media/decoder_config.h"
#include "chromecast/public/media/decrypt_context.h"
@@ -67,8 +66,7 @@ class CastAudioOutputStream::Backend : public MediaPipelineBackend::Delegate {
: audio_params_(audio_params),
decoder_(nullptr),
first_start_(true),
- error_(false),
- backend_buffer_(nullptr) {
+ error_(false) {
thread_checker_.DetachFromThread();
}
~Backend() override {}
@@ -133,11 +131,11 @@ class CastAudioOutputStream::Backend : public MediaPipelineBackend::Delegate {
return;
}
- backend_buffer_.set_buffer(decoder_buffer);
+ backend_buffer_ = decoder_buffer;
completion_cb_ = completion_cb;
MediaPipelineBackend::BufferStatus status =
- decoder_->PushBuffer(nullptr /* decrypt_context */, &backend_buffer_);
+ decoder_->PushBuffer(backend_buffer_.get());
if (status != MediaPipelineBackend::kBufferPending)
OnPushBufferComplete(decoder_, status);
}
@@ -182,7 +180,7 @@ class CastAudioOutputStream::Backend : public MediaPipelineBackend::Delegate {
PushBufferCompletionCallback completion_cb_;
bool first_start_;
bool error_;
- CastDecoderBufferImpl backend_buffer_;
+ scoped_refptr<DecoderBufferBase> backend_buffer_;
base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(Backend);
};
diff --git a/chromecast/media/audio/cast_audio_output_stream_unittest.cc b/chromecast/media/audio/cast_audio_output_stream_unittest.cc
index 4c44590..608d9b6 100644
--- a/chromecast/media/audio/cast_audio_output_stream_unittest.cc
+++ b/chromecast/media/audio/cast_audio_output_stream_unittest.cc
@@ -42,15 +42,12 @@ class FakeAudioDecoder : public MediaPipelineBackend::AudioDecoder {
pipeline_status_(PIPELINE_STATUS_OK),
pending_push_(false),
pushed_buffer_count_(0),
- last_decrypt_context_(nullptr),
last_buffer_(nullptr),
delegate_(nullptr) {}
~FakeAudioDecoder() override {}
// MediaPipelineBackend::AudioDecoder overrides.
- BufferStatus PushBuffer(DecryptContext* decrypt_context,
- CastDecoderBuffer* buffer) override {
- last_decrypt_context_ = decrypt_context;
+ BufferStatus PushBuffer(CastDecoderBuffer* buffer) override {
last_buffer_ = buffer;
++pushed_buffer_count_;
@@ -93,7 +90,6 @@ class FakeAudioDecoder : public MediaPipelineBackend::AudioDecoder {
pipeline_status_ = status;
}
unsigned pushed_buffer_count() const { return pushed_buffer_count_; }
- DecryptContext* last_decrypt_context() { return last_decrypt_context_; }
CastDecoderBuffer* last_buffer() { return last_buffer_; }
void set_delegate(MediaPipelineBackend::Delegate* delegate) {
delegate_ = delegate;
@@ -106,7 +102,6 @@ class FakeAudioDecoder : public MediaPipelineBackend::AudioDecoder {
PipelineStatus pipeline_status_;
bool pending_push_;
int pushed_buffer_count_;
- DecryptContext* last_decrypt_context_;
CastDecoderBuffer* last_buffer_;
MediaPipelineBackend::Delegate* delegate_;
};
@@ -471,7 +466,6 @@ TEST_F(CastAudioOutputStreamTest, PushFrame) {
ASSERT_TRUE(audio_decoder);
// Verify initial state.
EXPECT_EQ(0u, audio_decoder->pushed_buffer_count());
- EXPECT_FALSE(audio_decoder->last_decrypt_context());
EXPECT_FALSE(audio_decoder->last_buffer());
scoped_ptr<FakeAudioSourceCallback> source_callback(
@@ -481,8 +475,6 @@ TEST_F(CastAudioOutputStreamTest, PushFrame) {
// Verify that the stream pushed frames to the backend.
EXPECT_LT(0u, audio_decoder->pushed_buffer_count());
- // DecryptContext is always NULL becuase of "raw" audio.
- EXPECT_FALSE(audio_decoder->last_decrypt_context());
EXPECT_TRUE(audio_decoder->last_buffer());
// Verify decoder buffer.
diff --git a/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc b/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc
index 38ea193..fb0d768 100644
--- a/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc
+++ b/chromecast/media/cma/backend/audio_video_pipeline_device_unittest.cc
@@ -20,7 +20,6 @@
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "chromecast/base/task_runner_impl.h"
-#include "chromecast/media/cma/base/cast_decoder_buffer_impl.h"
#include "chromecast/media/cma/base/decoder_buffer_adapter.h"
#include "chromecast/media/cma/base/decoder_config_adapter.h"
#include "chromecast/media/cma/test/frame_segmenter_for_test.h"
@@ -116,8 +115,8 @@ class AudioVideoPipelineDeviceTest : public testing::Test,
scoped_ptr<TaskRunnerImpl> task_runner_;
scoped_ptr<MediaPipelineBackend> backend_;
- CastDecoderBufferImpl backend_audio_buffer_;
- CastDecoderBufferImpl backend_video_buffer_;
+ scoped_refptr<DecoderBufferBase> backend_audio_buffer_;
+ scoped_refptr<DecoderBufferBase> backend_video_buffer_;
// Current media time.
base::TimeDelta pause_time_;
@@ -138,9 +137,7 @@ class AudioVideoPipelineDeviceTest : public testing::Test,
};
AudioVideoPipelineDeviceTest::AudioVideoPipelineDeviceTest()
- : backend_audio_buffer_(nullptr),
- backend_video_buffer_(nullptr),
- pause_pattern_(),
+ : pause_pattern_(),
audio_decoder_(nullptr),
video_decoder_(nullptr),
audio_feeding_completed_(true),
@@ -249,18 +246,16 @@ void AudioVideoPipelineDeviceTest::FeedAudioBuffer() {
if (audio_feeding_completed_)
return;
- scoped_refptr<DecoderBufferBase> buffer = audio_buffers_.front();
- backend_audio_buffer_.set_buffer(buffer);
+ backend_audio_buffer_ = audio_buffers_.front();
MediaPipelineBackend::BufferStatus status =
- audio_decoder_->PushBuffer(nullptr, // decrypt_context
- &backend_audio_buffer_);
+ audio_decoder_->PushBuffer(backend_audio_buffer_.get());
EXPECT_NE(status, MediaPipelineBackend::kBufferFailed);
audio_buffers_.pop_front();
// Feeding is done, just wait for the end of stream callback.
- if (buffer->end_of_stream() || audio_buffers_.empty()) {
- if (audio_buffers_.empty() && !buffer->end_of_stream()) {
+ if (backend_audio_buffer_->end_of_stream() || audio_buffers_.empty()) {
+ if (audio_buffers_.empty() && !backend_audio_buffer_->end_of_stream()) {
LOG(WARNING) << "Stream emptied without feeding EOS frame";
}
@@ -280,18 +275,16 @@ void AudioVideoPipelineDeviceTest::FeedVideoBuffer() {
if (video_feeding_completed_)
return;
- scoped_refptr<DecoderBufferBase> buffer = video_buffers_.front();
- backend_video_buffer_.set_buffer(buffer);
+ backend_video_buffer_ = video_buffers_.front();
MediaPipelineBackend::BufferStatus status =
- video_decoder_->PushBuffer(nullptr, // decrypt_context
- &backend_video_buffer_);
+ video_decoder_->PushBuffer(backend_video_buffer_.get());
EXPECT_NE(status, MediaPipelineBackend::kBufferFailed);
video_buffers_.pop_front();
// Feeding is done, just wait for the end of stream callback.
- if (buffer->end_of_stream() || video_buffers_.empty()) {
- if (video_buffers_.empty() && !buffer->end_of_stream()) {
+ if (backend_video_buffer_->end_of_stream() || video_buffers_.empty()) {
+ if (video_buffers_.empty() && !backend_video_buffer_->end_of_stream()) {
LOG(WARNING) << "Stream emptied without feeding EOS frame";
}
@@ -431,6 +424,7 @@ void AudioVideoPipelineDeviceTest::Initialize() {
task_runner_.reset(new TaskRunnerImpl());
MediaPipelineDeviceParams params(task_runner_.get());
backend_.reset(CastMediaShlib::CreateMediaPipelineBackend(params));
+ DCHECK(backend_);
}
TEST_F(AudioVideoPipelineDeviceTest, Mp3Playback) {
diff --git a/chromecast/media/cma/backend/media_pipeline_backend_default.cc b/chromecast/media/cma/backend/media_pipeline_backend_default.cc
index bb0cc1e..61a3315 100644
--- a/chromecast/media/cma/backend/media_pipeline_backend_default.cc
+++ b/chromecast/media/cma/backend/media_pipeline_backend_default.cc
@@ -20,8 +20,7 @@ class MediaPipelineBackendDefault::AudioDecoderDefault
}
// MediaPipelineBackend::AudioDecoder implementation:
- BufferStatus PushBuffer(DecryptContext* decrypt_context,
- CastDecoderBuffer* buffer) override {
+ BufferStatus PushBuffer(CastDecoderBuffer* buffer) override {
if (buffer->end_of_stream())
delegate_->OnEndOfStream(this);
return MediaPipelineBackend::kBufferSuccess;
@@ -52,8 +51,7 @@ class MediaPipelineBackendDefault::VideoDecoderDefault
}
// MediaPipelineBackend::VideoDecoder implementation:
- BufferStatus PushBuffer(DecryptContext* decrypt_context,
- CastDecoderBuffer* buffer) override {
+ BufferStatus PushBuffer(CastDecoderBuffer* buffer) override {
if (buffer->end_of_stream())
delegate_->OnEndOfStream(this);
return MediaPipelineBackend::kBufferSuccess;
diff --git a/chromecast/media/cma/base/BUILD.gn b/chromecast/media/cma/base/BUILD.gn
index d3eb811..b0ebefd 100644
--- a/chromecast/media/cma/base/BUILD.gn
+++ b/chromecast/media/cma/base/BUILD.gn
@@ -14,8 +14,6 @@ source_set("base") {
"buffering_frame_provider.h",
"buffering_state.cc",
"buffering_state.h",
- "cast_decoder_buffer_impl.cc",
- "cast_decoder_buffer_impl.h",
"cast_decrypt_config_impl.cc",
"cast_decrypt_config_impl.h",
"cma_logging.h",
diff --git a/chromecast/media/cma/base/cast_decoder_buffer_impl.cc b/chromecast/media/cma/base/cast_decoder_buffer_impl.cc
deleted file mode 100644
index e958048..0000000
--- a/chromecast/media/cma/base/cast_decoder_buffer_impl.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// 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 "chromecast/media/cma/base/cast_decoder_buffer_impl.h"
-
-namespace chromecast {
-namespace media {
-
-CastDecoderBufferImpl::CastDecoderBufferImpl(
- const scoped_refptr<DecoderBufferBase>& buffer)
- : buffer_(buffer) {}
-
-CastDecoderBufferImpl::~CastDecoderBufferImpl() {}
-
-StreamId CastDecoderBufferImpl::stream_id() const {
- return buffer_->stream_id();
-}
-
-int64_t CastDecoderBufferImpl::timestamp() const {
- return buffer_->timestamp().InMicroseconds();
-}
-
-const uint8* CastDecoderBufferImpl::data() const {
- return buffer_->data();
-}
-
-size_t CastDecoderBufferImpl::data_size() const {
- return buffer_->data_size();
-}
-
-const CastDecryptConfig* CastDecoderBufferImpl::decrypt_config() const {
- return buffer_->decrypt_config();
-}
-
-bool CastDecoderBufferImpl::end_of_stream() const {
- return buffer_->end_of_stream();
-}
-
-const scoped_refptr<DecoderBufferBase>& CastDecoderBufferImpl::buffer() const {
- return buffer_;
-}
-
-void CastDecoderBufferImpl::set_buffer(
- const scoped_refptr<DecoderBufferBase>& buffer) {
- buffer_ = buffer;
-}
-
-} // namespace media
-} // namespace chromecast
diff --git a/chromecast/media/cma/base/cast_decoder_buffer_impl.h b/chromecast/media/cma/base/cast_decoder_buffer_impl.h
deleted file mode 100644
index adc663c..0000000
--- a/chromecast/media/cma/base/cast_decoder_buffer_impl.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// 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.
-
-#ifndef CHROMECAST_MEDIA_CMA_BASE_CAST_DECODER_BUFFER_IMPL_H_
-#define CHROMECAST_MEDIA_CMA_BASE_CAST_DECODER_BUFFER_IMPL_H_
-
-#include "chromecast/public/media/cast_decoder_buffer.h"
-#include "chromecast/media/cma/base/decoder_buffer_base.h"
-
-namespace chromecast {
-namespace media {
-
-// Implementation of public DecoderBuffer interface.
-// Holds a (refcounted) DecoderBufferBase. This way, ownership throughout
-// the pipeline is refcounted, but without exposing RefCountedBase in
-// the public API.
-class CastDecoderBufferImpl : public CastDecoderBuffer {
- public:
- CastDecoderBufferImpl(const scoped_refptr<DecoderBufferBase>& buffer);
- ~CastDecoderBufferImpl() override;
-
- // Returns the stream id of this decoder buffer belonging to. it's optional
- // and default value is kPrimary.
- StreamId stream_id() const override;
-
- // Returns the PTS of the frame in microseconds.
- int64_t timestamp() const override;
-
- // Gets the frame data.
- const uint8* data() const override;
-
- // Returns the size of the frame in bytes.
- size_t data_size() const override;
-
- // Returns the decrypt configuration.
- // Returns NULL if the buffer has no decrypt info.
- const CastDecryptConfig* decrypt_config() const override;
-
- // Indicate if this is a special frame that indicates the end of the stream.
- // If true, functions to access the frame content cannot be called.
- bool end_of_stream() const override;
-
- const scoped_refptr<DecoderBufferBase>& buffer() const;
- void set_buffer(const scoped_refptr<DecoderBufferBase>& buffer);
-
- private:
- scoped_refptr<DecoderBufferBase> buffer_;
-};
-
-} // namespace media
-} // namespace chromecast
-
-#endif // CHROMECAST_MEDIA_CMA_BASE_CAST_DECODER_BUFFER_BASE_H_
diff --git a/chromecast/media/cma/base/decoder_buffer_adapter.cc b/chromecast/media/cma/base/decoder_buffer_adapter.cc
index 10ffddc..c7de81f 100644
--- a/chromecast/media/cma/base/decoder_buffer_adapter.cc
+++ b/chromecast/media/cma/base/decoder_buffer_adapter.cc
@@ -29,8 +29,8 @@ StreamId DecoderBufferAdapter::stream_id() const {
return stream_id_;
}
-base::TimeDelta DecoderBufferAdapter::timestamp() const {
- return buffer_->timestamp();
+int64_t DecoderBufferAdapter::timestamp() const {
+ return buffer_->timestamp().InMicroseconds();
}
void DecoderBufferAdapter::set_timestamp(base::TimeDelta timestamp) {
diff --git a/chromecast/media/cma/base/decoder_buffer_adapter.h b/chromecast/media/cma/base/decoder_buffer_adapter.h
index 5118694..9eda89c 100644
--- a/chromecast/media/cma/base/decoder_buffer_adapter.h
+++ b/chromecast/media/cma/base/decoder_buffer_adapter.h
@@ -28,9 +28,9 @@ class DecoderBufferAdapter : public DecoderBufferBase {
DecoderBufferAdapter(
StreamId stream_id, const scoped_refptr<::media::DecoderBuffer>& buffer);
- // DecoderBufferBase implementation.
+ // DecoderBufferBase implementation:
StreamId stream_id() const override;
- base::TimeDelta timestamp() const override;
+ int64_t timestamp() const override;
void set_timestamp(base::TimeDelta timestamp) override;
const uint8* data() const override;
uint8* writable_data() const override;
diff --git a/chromecast/media/cma/base/decoder_buffer_base.h b/chromecast/media/cma/base/decoder_buffer_base.h
index 08cf94b..d405da4 100644
--- a/chromecast/media/cma/base/decoder_buffer_base.h
+++ b/chromecast/media/cma/base/decoder_buffer_base.h
@@ -5,57 +5,57 @@
#ifndef CHROMECAST_MEDIA_CMA_BASE_DECODER_BUFFER_BASE_H_
#define CHROMECAST_MEDIA_CMA_BASE_DECODER_BUFFER_BASE_H_
-#include "base/basictypes.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
-#include "chromecast/public/media/stream_id.h"
+#include "chromecast/public/media/cast_decoder_buffer.h"
+#include "chromecast/public/media/decrypt_context.h"
namespace chromecast {
namespace media {
-class CastDecryptConfig;
// DecoderBufferBase exposes only the properties of an audio/video buffer.
// The way a DecoderBufferBase is created and organized in memory
// is left as a detail of the implementation of derived classes.
-class DecoderBufferBase
- : public base::RefCountedThreadSafe<DecoderBufferBase> {
+class DecoderBufferBase : public CastDecoderBuffer,
+ public base::RefCountedThreadSafe<DecoderBufferBase> {
public:
- DecoderBufferBase() {}
+ // Partial CastDecoderBuffer implementation:
+ DecryptContext* decrypt_context() const override;
- // Returns the stream id of this decoder buffer belonging to. it's optional
- // and default value is kPrimary.
- virtual StreamId stream_id() const = 0;
-
- // Returns the PTS of the frame.
- virtual base::TimeDelta timestamp() const = 0;
+ void set_decrypt_context(scoped_ptr<DecryptContext> context) {
+ decrypt_context_ = context.Pass();
+ }
// Sets the PTS of the frame.
virtual void set_timestamp(base::TimeDelta timestamp) = 0;
- // Gets the frame data.
- virtual const uint8* data() const = 0;
- virtual uint8* writable_data() const = 0;
-
- // Returns the size of the frame in bytes.
- virtual size_t data_size() const = 0;
-
- // Returns the decrypt configuration.
- // Returns NULL if the buffer has no decrypt info.
- virtual const CastDecryptConfig* decrypt_config() const = 0;
-
- // Indicate if this is a special frame that indicates the end of the stream.
- // If true, functions to access the frame content cannot be called.
- virtual bool end_of_stream() const = 0;
+ // Gets a pointer to the frame data buffer.
+ virtual uint8_t* writable_data() const = 0;
protected:
friend class base::RefCountedThreadSafe<DecoderBufferBase>;
- virtual ~DecoderBufferBase() {}
+
+ DecoderBufferBase();
+ ~DecoderBufferBase() override;
private:
+ scoped_ptr<DecryptContext> decrypt_context_;
+
DISALLOW_COPY_AND_ASSIGN(DecoderBufferBase);
};
+inline DecoderBufferBase::DecoderBufferBase() {
+}
+
+inline DecoderBufferBase::~DecoderBufferBase() {
+}
+
+inline DecryptContext* DecoderBufferBase::decrypt_context() const {
+ return decrypt_context_.get();
+}
+
} // namespace media
} // namespace chromecast
diff --git a/chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.cc b/chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.cc
index 1bc97a5..b6af72b 100644
--- a/chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.cc
+++ b/chromecast/media/cma/ipc_streamer/decoder_buffer_base_marshaller.cc
@@ -27,7 +27,7 @@ class DecoderBufferFromMsg : public DecoderBufferBase {
// DecoderBufferBase implementation.
StreamId stream_id() const override;
- base::TimeDelta timestamp() const override;
+ int64_t timestamp() const override;
void set_timestamp(base::TimeDelta timestamp) override;
const uint8* data() const override;
uint8* writable_data() const override;
@@ -113,8 +113,8 @@ StreamId DecoderBufferFromMsg::stream_id() const {
return stream_id_;
}
-base::TimeDelta DecoderBufferFromMsg::timestamp() const {
- return pts_;
+int64_t DecoderBufferFromMsg::timestamp() const {
+ return pts_.InMicroseconds();
}
void DecoderBufferFromMsg::set_timestamp(base::TimeDelta timestamp) {
@@ -154,7 +154,7 @@ void DecoderBufferBaseMarshaller::Write(
return;
CHECK(msg->WritePod(buffer->stream_id()));
- CHECK(msg->WritePod(buffer->timestamp().InMicroseconds()));
+ CHECK(msg->WritePod(buffer->timestamp()));
bool has_decrypt_config =
(buffer->decrypt_config() != NULL &&
diff --git a/chromecast/media/cma/pipeline/audio_pipeline_impl.cc b/chromecast/media/cma/pipeline/audio_pipeline_impl.cc
index b88f686..0edd474 100644
--- a/chromecast/media/cma/pipeline/audio_pipeline_impl.cc
+++ b/chromecast/media/cma/pipeline/audio_pipeline_impl.cc
@@ -73,6 +73,11 @@ void AudioPipelineImpl::Flush(const ::media::PipelineStatusCB& status_cb) {
base::Bind(&AudioPipelineImpl::OnFlushDone, weak_this_, status_cb));
}
+void AudioPipelineImpl::BackendStopped() {
+ CMALOG(kLogControl) << __FUNCTION__;
+ av_pipeline_impl_->BackendStopped();
+}
+
void AudioPipelineImpl::OnFlushDone(
const ::media::PipelineStatusCB& status_cb) {
CMALOG(kLogControl) << __FUNCTION__;
diff --git a/chromecast/media/cma/pipeline/audio_pipeline_impl.h b/chromecast/media/cma/pipeline/audio_pipeline_impl.h
index 9afe19b..014b041 100644
--- a/chromecast/media/cma/pipeline/audio_pipeline_impl.h
+++ b/chromecast/media/cma/pipeline/audio_pipeline_impl.h
@@ -46,6 +46,7 @@ class AudioPipelineImpl {
bool StartPlayingFrom(base::TimeDelta time,
const scoped_refptr<BufferingState>& buffering_state);
void Flush(const ::media::PipelineStatusCB& status_cb);
+ void BackendStopped();
void Stop();
// Update the playback statistics for this audio stream.
diff --git a/chromecast/media/cma/pipeline/av_pipeline_impl.cc b/chromecast/media/cma/pipeline/av_pipeline_impl.cc
index a8eff13..82ce75f 100644
--- a/chromecast/media/cma/pipeline/av_pipeline_impl.cc
+++ b/chromecast/media/cma/pipeline/av_pipeline_impl.cc
@@ -41,7 +41,6 @@ AvPipelineImpl::AvPipelineImpl(MediaPipelineBackend::Decoder* decoder,
playable_buffered_time_(::media::kNoTimestamp()),
enable_feeding_(false),
pending_read_(false),
- pushed_buffer_(nullptr),
enable_time_update_(false),
pending_time_update_task_(false),
media_keys_(NULL),
@@ -103,14 +102,11 @@ void AvPipelineImpl::Flush(const base::Closure& done_cb) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_EQ(state_, kFlushing);
- // Note: returning to idle state aborts any pending frame push.
- pushed_buffer_.set_buffer(nullptr);
-
// Break the feeding loop.
enable_feeding_ = false;
// Remove any pending buffer.
- pending_buffer_ = scoped_refptr<DecoderBufferBase>();
+ pending_buffer_ = nullptr;
// Finally, remove any frames left in the frame provider.
pending_read_ = false;
@@ -120,6 +116,13 @@ void AvPipelineImpl::Flush(const base::Closure& done_cb) {
frame_provider_->Flush(done_cb);
}
+void AvPipelineImpl::BackendStopped() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Note: returning to idle state aborts any pending frame push.
+ pushed_buffer_ = nullptr;
+}
+
void AvPipelineImpl::Stop() {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -149,7 +152,7 @@ void AvPipelineImpl::FetchBufferIfNeeded() {
if (!enable_feeding_)
return;
- if (pending_read_ || pending_buffer_.get())
+ if (pending_read_ || pending_buffer_)
return;
pending_read_ = true;
@@ -179,14 +182,14 @@ void AvPipelineImpl::ProcessPendingBuffer() {
return;
// Initiate a read if there isn't already one.
- if (!pending_buffer_.get() && !pending_read_) {
+ if (!pending_buffer_ && !pending_read_) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_));
return;
}
- if (!pending_buffer_.get() || pushed_buffer_.buffer())
+ if (!pending_buffer_ || pushed_buffer_)
return;
// Break the feeding loop when the end of stream is reached.
@@ -203,13 +206,12 @@ void AvPipelineImpl::ProcessPendingBuffer() {
std::string key_id(pending_buffer_->decrypt_config()->key_id());
if (!media_keys_) {
CMALOG(kLogControl) << "No CDM for frame: pts="
- << pending_buffer_->timestamp().InMilliseconds();
+ << pending_buffer_->timestamp();
return;
}
decrypt_context = media_keys_->GetDecryptContext(key_id);
if (!decrypt_context.get()) {
- CMALOG(kLogControl) << "frame(pts="
- << pending_buffer_->timestamp().InMilliseconds()
+ CMALOG(kLogControl) << "frame(pts=" << pending_buffer_->timestamp()
<< "): waiting for key id "
<< base::HexEncode(&key_id[0], key_id.size());
return;
@@ -225,16 +227,19 @@ void AvPipelineImpl::ProcessPendingBuffer() {
}
if (!pending_buffer_->end_of_stream() && buffering_state_.get()) {
- base::TimeDelta timestamp = pending_buffer_->timestamp();
+ base::TimeDelta timestamp =
+ base::TimeDelta::FromMicroseconds(pending_buffer_->timestamp());
if (timestamp != ::media::kNoTimestamp())
buffering_state_->SetMaxRenderingTime(timestamp);
}
- DCHECK(!pushed_buffer_.buffer());
- pushed_buffer_.set_buffer(pending_buffer_);
+ DCHECK(!pushed_buffer_);
+ pushed_buffer_ = pending_buffer_;
+ if (decrypt_context && decrypt_context->GetKeySystem() != KEY_SYSTEM_NONE)
+ pushed_buffer_->set_decrypt_context(decrypt_context.Pass());
+ pending_buffer_ = nullptr;
MediaPipelineBackend::BufferStatus status =
- decoder_->PushBuffer(decrypt_context.release(), &pushed_buffer_);
- pending_buffer_ = scoped_refptr<DecoderBufferBase>();
+ decoder_->PushBuffer(pushed_buffer_.get());
if (status != MediaPipelineBackend::kBufferPending)
OnBufferPushed(status);
@@ -242,7 +247,7 @@ void AvPipelineImpl::ProcessPendingBuffer() {
void AvPipelineImpl::OnBufferPushed(MediaPipelineBackend::BufferStatus status) {
DCHECK(thread_checker_.CalledOnValidThread());
- pushed_buffer_.set_buffer(nullptr);
+ pushed_buffer_ = nullptr;
if (status == MediaPipelineBackend::kBufferFailed) {
LOG(WARNING) << "AvPipelineImpl: PushFrame failed";
enable_feeding_ = false;
@@ -277,9 +282,11 @@ void AvPipelineImpl::OnDataBuffered(
if (!buffering_state_.get())
return;
- if (!buffer->end_of_stream() && (buffered_time_ == ::media::kNoTimestamp() ||
- buffered_time_ < buffer->timestamp())) {
- buffered_time_ = buffer->timestamp();
+ if (!buffer->end_of_stream() &&
+ (buffered_time_ == ::media::kNoTimestamp() ||
+ buffered_time_ <
+ base::TimeDelta::FromMicroseconds(buffer->timestamp()))) {
+ buffered_time_ = base::TimeDelta::FromMicroseconds(buffer->timestamp());
}
if (is_at_max_capacity)
@@ -312,8 +319,10 @@ void AvPipelineImpl::UpdatePlayableFrames() {
}
if (playable_buffered_time_ == ::media::kNoTimestamp() ||
- playable_buffered_time_ < non_playable_frame->timestamp()) {
- playable_buffered_time_ = non_playable_frame->timestamp();
+ playable_buffered_time_ < base::TimeDelta::FromMicroseconds(
+ non_playable_frame->timestamp())) {
+ playable_buffered_time_ =
+ base::TimeDelta::FromMicroseconds(non_playable_frame->timestamp());
buffering_state_->SetBufferedTime(playable_buffered_time_);
}
}
diff --git a/chromecast/media/cma/pipeline/av_pipeline_impl.h b/chromecast/media/cma/pipeline/av_pipeline_impl.h
index fe1a828..28a885b 100644
--- a/chromecast/media/cma/pipeline/av_pipeline_impl.h
+++ b/chromecast/media/cma/pipeline/av_pipeline_impl.h
@@ -12,7 +12,6 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
-#include "chromecast/media/cma/base/cast_decoder_buffer_impl.h"
#include "chromecast/public/media/media_pipeline_backend.h"
#include "chromecast/public/media/stream_id.h"
@@ -64,6 +63,8 @@ class AvPipelineImpl {
// Flush any remaining samples in the pipeline.
// Invoke |done_cb| when flush is completed.
void Flush(const base::Closure& done_cb);
+ // Resets any pending buffers after the backend has been stopped.
+ void BackendStopped();
// Tear down the pipeline and release the hardware resources.
void Stop();
@@ -140,7 +141,7 @@ class AvPipelineImpl {
scoped_refptr<DecoderBufferBase> pending_buffer_;
// Buffer that has been pushed to the device but not processed yet.
- CastDecoderBufferImpl pushed_buffer_;
+ scoped_refptr<DecoderBufferBase> pushed_buffer_;
// The media time is retrieved at regular intervals.
// Indicate whether time update is enabled.
diff --git a/chromecast/media/cma/pipeline/decrypt_util.cc b/chromecast/media/cma/pipeline/decrypt_util.cc
index 7f57cec..2acd5ea 100644
--- a/chromecast/media/cma/pipeline/decrypt_util.cc
+++ b/chromecast/media/cma/pipeline/decrypt_util.cc
@@ -23,7 +23,7 @@ class DecoderBufferClear : public DecoderBufferBase {
// DecoderBufferBase implementation.
StreamId stream_id() const override;
- base::TimeDelta timestamp() const override;
+ int64_t timestamp() const override;
void set_timestamp(base::TimeDelta timestamp) override;
const uint8* data() const override;
uint8* writable_data() const override;
@@ -51,7 +51,7 @@ StreamId DecoderBufferClear::stream_id() const {
return buffer_->stream_id();
}
-base::TimeDelta DecoderBufferClear::timestamp() const {
+int64_t DecoderBufferClear::timestamp() const {
return buffer_->timestamp();
}
diff --git a/chromecast/media/cma/pipeline/media_pipeline_impl.cc b/chromecast/media/cma/pipeline/media_pipeline_impl.cc
index e741470..68df661 100644
--- a/chromecast/media/cma/pipeline/media_pipeline_impl.cc
+++ b/chromecast/media/cma/pipeline/media_pipeline_impl.cc
@@ -345,6 +345,12 @@ void MediaPipelineImpl::OnFlushDone(
return;
}
+ // Clear pending buffers.
+ if (audio_pipeline_)
+ audio_pipeline_->BackendStopped();
+ if (video_pipeline_)
+ video_pipeline_->BackendStopped();
+
pending_flush_callbacks_.reset();
status_cb.Run(status);
}
diff --git a/chromecast/media/cma/pipeline/video_pipeline_impl.cc b/chromecast/media/cma/pipeline/video_pipeline_impl.cc
index e24a7f7..2d6f803 100644
--- a/chromecast/media/cma/pipeline/video_pipeline_impl.cc
+++ b/chromecast/media/cma/pipeline/video_pipeline_impl.cc
@@ -76,6 +76,11 @@ void VideoPipelineImpl::Flush(const ::media::PipelineStatusCB& status_cb) {
base::Bind(&VideoPipelineImpl::OnFlushDone, weak_this_, status_cb));
}
+void VideoPipelineImpl::BackendStopped() {
+ CMALOG(kLogControl) << __FUNCTION__;
+ av_pipeline_impl_->BackendStopped();
+}
+
void VideoPipelineImpl::OnFlushDone(
const ::media::PipelineStatusCB& status_cb) {
CMALOG(kLogControl) << __FUNCTION__;
diff --git a/chromecast/media/cma/pipeline/video_pipeline_impl.h b/chromecast/media/cma/pipeline/video_pipeline_impl.h
index 9fd3071..ff18c28 100644
--- a/chromecast/media/cma/pipeline/video_pipeline_impl.h
+++ b/chromecast/media/cma/pipeline/video_pipeline_impl.h
@@ -48,6 +48,7 @@ class VideoPipelineImpl {
bool StartPlayingFrom(base::TimeDelta time,
const scoped_refptr<BufferingState>& buffering_state);
void Flush(const ::media::PipelineStatusCB& status_cb);
+ void BackendStopped();
void Stop();
// Update the playback statistics for this video stream.
diff --git a/chromecast/media/media.gyp b/chromecast/media/media.gyp
index fe0fd7c..b3a0047 100644
--- a/chromecast/media/media.gyp
+++ b/chromecast/media/media.gyp
@@ -120,8 +120,6 @@
'cma/base/buffering_frame_provider.h',
'cma/base/buffering_state.cc',
'cma/base/buffering_state.h',
- 'cma/base/cast_decoder_buffer_impl.cc',
- 'cma/base/cast_decoder_buffer_impl.h',
'cma/base/cast_decrypt_config_impl.cc',
'cma/base/cast_decrypt_config_impl.h',
'cma/base/cma_logging.h',
diff --git a/chromecast/public/media/cast_decoder_buffer.h b/chromecast/public/media/cast_decoder_buffer.h
index bf3d76c..f6ca422 100644
--- a/chromecast/public/media/cast_decoder_buffer.h
+++ b/chromecast/public/media/cast_decoder_buffer.h
@@ -15,12 +15,16 @@ namespace chromecast {
namespace media {
class CastDecryptConfig;
+class DecryptContext;
// CastDecoderBuffer provides an interface for passing a single frame of audio
// or video data to the pipeline backend. End-of-stream is indicated by passing
// a frame where end_of_stream() returns true.
-// Buffer ownership passes to backend when they are pushed (see
-// MediaComponentDevice::PushFrame).
+// The buffer's lifetime is managed by the caller code - it MUST NOT be
+// deleted by the MediaPipelineBackend implementation, and MUST NOT be
+// dereferenced after completion of buffer push (i.e.
+// kBufferSuccess/kBufferFailure for synchronous completion, OnPushComplete
+// for kBufferPending case).
// TODO(halliwell): consider renaming functions here to camel case.
class CastDecoderBuffer {
public:
@@ -39,9 +43,13 @@ class CastDecoderBuffer {
virtual size_t data_size() const = 0;
// Returns the decrypt configuration.
- // Returns NULL if and only if the buffer is unencrypted.
+ // Returns nullptr if and only if the buffer is unencrypted.
virtual const CastDecryptConfig* decrypt_config() const = 0;
+ // Returns the decrypt context. Returns nullptr if and only if the buffer is
+ // unencrypted.
+ virtual DecryptContext* decrypt_context() const = 0;
+
// Indicates if this is a special frame that indicates the end of the stream.
// If true, functions to access the frame content cannot be called.
virtual bool end_of_stream() const = 0;
diff --git a/chromecast/public/media/media_pipeline_backend.h b/chromecast/public/media/media_pipeline_backend.h
index 53e028b..cc497b5 100644
--- a/chromecast/public/media/media_pipeline_backend.h
+++ b/chromecast/public/media/media_pipeline_backend.h
@@ -58,13 +58,12 @@ class MediaPipelineBackend {
// further buffers until OnPushComplete is invoked.
// OnPushComplete should be only be invoked to indicate completion of a
// pending buffer push - not for the immediate |kBufferSuccess| return case.
- // The decrypt_context and buffer's lifetimes are managed by the caller code
- // - they MUST NOT be deleted by the MediaPipelineBackend implementation,
- // and MUST NOT be dereferenced after completion of buffer push (i.e.
+ // The buffer's lifetime is managed by the caller code - it MUST NOT be
+ // deleted by the MediaPipelineBackend implementation, and MUST NOT be
+ // dereferenced after completion of buffer push (i.e.
// kBufferSuccess/kBufferFailure for synchronous completion, OnPushComplete
// for kBufferPending case).
- virtual BufferStatus PushBuffer(DecryptContext* decrypt_context,
- CastDecoderBuffer* buffer) = 0;
+ virtual BufferStatus PushBuffer(CastDecoderBuffer* buffer) = 0;
// Returns the playback statistics since this decoder's creation. Only
// called when playing or paused.