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

Unified Diff: media/filters/fake_video_decoder.cc

Issue 15085011: Add FakeVideoDecoder. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 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: media/filters/fake_video_decoder.cc
diff --git a/media/filters/fake_video_decoder.cc b/media/filters/fake_video_decoder.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b5039d51724c177e963868afcdd956c55979cc2b
--- /dev/null
+++ b/media/filters/fake_video_decoder.cc
@@ -0,0 +1,235 @@
+// Copyright (c) 2013 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 "media/filters/fake_video_decoder.h"
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/location.h"
+#include "base/message_loop_proxy.h"
+#include "media/base/bind_to_loop.h"
+#include "media/base/demuxer_stream.h"
+
+namespace media {
+
+FakeVideoDecoder::FakeVideoDecoder(int decoding_delay)
+ : message_loop_(base::MessageLoopProxy::current()),
+ weak_factory_(this),
+ decoding_delay_(decoding_delay),
+ state_(UNINITIALIZED),
+ demuxer_stream_(NULL) {
+ DCHECK_GE(decoding_delay, 0);
+}
+
+FakeVideoDecoder::~FakeVideoDecoder() {
+ DCHECK_EQ(state_, UNINITIALIZED);
+}
+
+void FakeVideoDecoder::Initialize(DemuxerStream* stream,
+ const PipelineStatusCB& status_cb,
+ const StatisticsCB& statistics_cb) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK(stream);
+ DCHECK(stream->video_decoder_config().IsValidConfig());
+ DCHECK(read_cb_.IsNull()) << "No reinitialization during pending read.";
+ DCHECK(reset_cb_.IsNull()) << "No reinitialization during pending reset.";
+
+ weak_this_ = weak_factory_.GetWeakPtr();
+
+ demuxer_stream_ = stream;
+ statistics_cb_ = statistics_cb;
+ current_config_ = stream->video_decoder_config();
+ init_cb_.SetCallback(BindToCurrentLoop(status_cb));
+
+ if (!decoded_frames_.empty()) {
+ DVLOG(1) << "Decoded frames dropped during reinitialization.";
+ decoded_frames_.clear();
+ }
+
+ state_ = NORMAL;
+ init_cb_.RunOrHold(PIPELINE_OK);
+}
+
+void FakeVideoDecoder::Read(const ReadCB& read_cb) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK(read_cb_.IsNull()) << "Overlapping decodes are not supported.";
+ DCHECK(reset_cb_.IsNull());
+ DCHECK_LE(decoded_frames_.size(), static_cast<size_t>(decoding_delay_));
+
+ read_cb_.SetCallback(BindToCurrentLoop(read_cb));
+ ReadFromDemuxerStream();
+}
+
+void FakeVideoDecoder::Reset(const base::Closure& closure) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK(reset_cb_.IsNull());
+ reset_cb_.SetCallback(BindToCurrentLoop(closure));
+
+ // Defer the reset if a read is pending.
+ if (!read_cb_.IsNull())
+ return;
+
+ DoReset();
+}
+
+void FakeVideoDecoder::Stop(const base::Closure& closure) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ stop_cb_.SetCallback(BindToCurrentLoop(closure));
+
+ // Defer the reset if a read and/or a reset is pending.
+ if (!read_cb_.IsNull() || !reset_cb_.IsNull())
+ return;
+
+ DoStop();
+}
+
+void FakeVideoDecoder::HoldNextInit() {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ init_cb_.HoldCallback();
+}
+
+void FakeVideoDecoder::HoldNextRead() {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ read_cb_.HoldCallback();
+}
+
+void FakeVideoDecoder::HoldNextReset() {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ reset_cb_.HoldCallback();
+}
+
+void FakeVideoDecoder::HoldNextStop() {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ stop_cb_.HoldCallback();
+}
+
+void FakeVideoDecoder::SatisfyInit() {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK(read_cb_.IsNull());
+ DCHECK(reset_cb_.IsNull());
+
+ init_cb_.RunHeldCallback();
+
+ if (!stop_cb_.IsNull())
+ DoStop();
+}
+
+void FakeVideoDecoder::SatisfyRead() {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ read_cb_.RunHeldCallback();
+
+ if (!reset_cb_.IsNull())
+ DoReset();
+
+ if (reset_cb_.IsNull() && !stop_cb_.IsNull())
+ DoStop();
+}
+
+void FakeVideoDecoder::SatisfyReset() {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK(read_cb_.IsNull());
+ reset_cb_.RunHeldCallback();
+
+ if (!stop_cb_.IsNull())
+ DoStop();
+}
+
+void FakeVideoDecoder::SatisfyStop() {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK(read_cb_.IsNull());
+ DCHECK(reset_cb_.IsNull());
+ stop_cb_.RunHeldCallback();
+}
+
+void FakeVideoDecoder::ReadFromDemuxerStream() {
+ DCHECK_EQ(state_, NORMAL);
+ DCHECK(!read_cb_.IsNull());
+ demuxer_stream_->Read(base::Bind(&FakeVideoDecoder::BufferReady, weak_this_));
+}
+
+void FakeVideoDecoder::BufferReady(DemuxerStream::Status status,
+ const scoped_refptr<DecoderBuffer>& buffer) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK_EQ(state_, NORMAL);
+ DCHECK(!read_cb_.IsNull());
+ DCHECK_EQ(status != DemuxerStream::kOk, !buffer) << status;
+
+ if (!stop_cb_.IsNull()) {
+ read_cb_.RunOrHold(kOk, scoped_refptr<VideoFrame>());
+ if (!reset_cb_.IsNull()) {
+ DoReset();
+ }
+ DoStop();
+ return;
+ }
+
+ if (status == DemuxerStream::kConfigChanged) {
+ DCHECK(demuxer_stream_->video_decoder_config().IsValidConfig());
+ current_config_ = demuxer_stream_->video_decoder_config();
+
+ if (reset_cb_.IsNull()) {
+ ReadFromDemuxerStream();
+ return;
+ }
+ }
+
+ if (!reset_cb_.IsNull()) {
+ read_cb_.RunOrHold(kOk, scoped_refptr<VideoFrame>());
+ DoReset();
+ return;
+ }
+
+ if (status == DemuxerStream::kAborted) {
+ read_cb_.RunOrHold(kOk, scoped_refptr<VideoFrame>());
+ return;
+ }
+
+ DCHECK_EQ(status, DemuxerStream::kOk);
+
+ // Make sure the decoder is always configured with the latest config.
+ DCHECK(current_config_.Matches(demuxer_stream_->video_decoder_config()));
+
+ if (buffer->IsEndOfStream() && decoded_frames_.empty()) {
+ read_cb_.RunOrHold(kOk, VideoFrame::CreateEmptyFrame());
+ return;
+ }
+
+ if (!buffer->IsEndOfStream()) {
+ scoped_refptr<VideoFrame> video_frame = VideoFrame::CreateColorFrame(
+ current_config_.coded_size(), 0, 0, 0, buffer->GetTimestamp());
+ decoded_frames_.push_back(video_frame);
+
+ if (decoded_frames_.size() <= static_cast<size_t>(decoding_delay_)) {
+ ReadFromDemuxerStream();
+ return;
+ }
+ }
+
+ scoped_refptr<VideoFrame> frame = decoded_frames_.front();
+ decoded_frames_.pop_front();
+ read_cb_.RunOrHold(kOk, frame);
+}
+
+void FakeVideoDecoder::DoReset() {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK(read_cb_.IsNull());
+ DCHECK(!reset_cb_.IsNull());
+
+ decoded_frames_.clear();
+ reset_cb_.RunOrHold();
+}
+
+void FakeVideoDecoder::DoStop() {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK(read_cb_.IsNull());
+ DCHECK(reset_cb_.IsNull());
+ DCHECK(!stop_cb_.IsNull());
+
+ state_ = UNINITIALIZED;
+ demuxer_stream_ = NULL;
+ decoded_frames_.clear();
+ stop_cb_.RunOrHold();
+}
+
+} // namespace media

Powered by Google App Engine
This is Rietveld 408576698