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

Unified Diff: media/filters/video_frame_stream.cc

Issue 12818004: Introduce VideoFrameStream, the video frame provider in media pipeline. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Prettier name for test. Created 7 years, 9 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 | « media/filters/video_frame_stream.h ('k') | media/filters/video_frame_stream_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/filters/video_frame_stream.cc
diff --git a/media/filters/video_frame_stream.cc b/media/filters/video_frame_stream.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c9cca1beaedfd68ace9fc5604b2e7a5f232f3f71
--- /dev/null
+++ b/media/filters/video_frame_stream.cc
@@ -0,0 +1,206 @@
+// 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/video_frame_stream.h"
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/message_loop_proxy.h"
+#include "media/base/bind_to_loop.h"
+#include "media/base/demuxer_stream.h"
+#include "media/base/video_decoder_config.h"
+#include "media/filters/decrypting_demuxer_stream.h"
+#include "media/filters/video_decoder_selector.h"
+
+namespace media {
+
+VideoFrameStream::VideoFrameStream(
+ const scoped_refptr<base::MessageLoopProxy>& message_loop,
+ const SetDecryptorReadyCB& set_decryptor_ready_cb)
+ : message_loop_(message_loop),
+ weak_factory_(this),
+ state_(UNINITIALIZED),
+ set_decryptor_ready_cb_(set_decryptor_ready_cb) {
+}
+
+VideoFrameStream::~VideoFrameStream() {
+ DCHECK(state_ == UNINITIALIZED || state_ == STOPPED) << state_;
+}
+
+void VideoFrameStream::Initialize(const scoped_refptr<DemuxerStream>& stream,
+ const VideoDecoderList& decoders,
+ const StatisticsCB& statistics_cb,
+ const InitCB& init_cb) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK_EQ(state_, UNINITIALIZED);
+
+ weak_this_ = weak_factory_.GetWeakPtr();
+
+ DCHECK(init_cb_.is_null());
+ DCHECK(!init_cb.is_null());
+ init_cb_ = init_cb;
+
+ scoped_ptr<VideoDecoderSelector> decoder_selector(
+ new VideoDecoderSelector(message_loop_,
+ decoders,
+ set_decryptor_ready_cb_));
+
+ // To avoid calling |decoder_selector| methods and passing ownership of
+ // |decoder_selector| in the same line.
+ VideoDecoderSelector* decoder_selector_ptr = decoder_selector.get();
+
+ decoder_selector_ptr->SelectVideoDecoder(
+ stream,
+ statistics_cb,
+ base::Bind(&VideoFrameStream::OnDecoderSelected, weak_this_,
+ base::Passed(&decoder_selector)));
+}
+
+void VideoFrameStream::ReadFrame(const VideoDecoder::ReadCB& read_cb) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK_EQ(state_, NORMAL);
+ // No two reads in the flight at any time.
+ DCHECK(read_cb_.is_null());
+ // No read during resetting or stopping process.
+ DCHECK(reset_cb_.is_null());
+ DCHECK(stop_cb_.is_null());
+
+ read_cb_ = read_cb;
+
+ decoder_->Read(base::Bind(&VideoFrameStream::OnFrameRead, weak_this_));
+}
+
+void VideoFrameStream::Reset(const base::Closure& closure) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK_EQ(state_, NORMAL);
+ DCHECK(reset_cb_.is_null());
+ DCHECK(stop_cb_.is_null());
+
+ reset_cb_ = closure;
+
+ // We may or may not have pending read, but we'll start to reset everything
+ // regardless.
+
+ if (decrypting_demuxer_stream_) {
+ decrypting_demuxer_stream_->Reset(base::Bind(
+ &VideoFrameStream::ResetDecoder, weak_this_));
+ return;
+ }
+
+ ResetDecoder();
+}
+
+void VideoFrameStream::Stop(const base::Closure& closure) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK_NE(state_, STOPPED);
+ DCHECK(stop_cb_.is_null());
+
+ stop_cb_ = closure;
+
+ // The stopping will continue after all of the following pending callbacks
+ // (if they are not null) are satisfied.
+ // TODO(xhwang): Now we cannot stop the initialization process through
+ // VideoDecoderSelector. Fix this. See: http://crbug.com/222054
+ if (!init_cb_.is_null())
+ return;
+
+ // We may or may not have pending read and/or pending reset, but we'll start
+ // to stop everything regardless.
+
+ if (decrypting_demuxer_stream_) {
+ decrypting_demuxer_stream_->Reset(base::Bind(
+ &VideoFrameStream::StopDecoder, weak_this_));
+ return;
+ }
+
+ if (decoder_) {
+ StopDecoder();
+ return;
+ }
+
+ state_ = STOPPED;
+ message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&stop_cb_));
+}
+
+bool VideoFrameStream::HasOutputFrameAvailable() const {
+ return decoder_->HasOutputFrameAvailable();
+}
+
+void VideoFrameStream::OnDecoderSelected(
+ scoped_ptr<VideoDecoderSelector> decoder_selector,
+ const scoped_refptr<VideoDecoder>& selected_decoder,
+ const scoped_refptr<DecryptingDemuxerStream>& decrypting_demuxer_stream) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK_EQ(state_, UNINITIALIZED);
+ DCHECK(!init_cb_.is_null());
+
+ if (!selected_decoder) {
+ state_ = UNINITIALIZED;
+ base::ResetAndReturn(&init_cb_).Run(false, false);
+ } else {
+ decoder_ = selected_decoder;
+ decrypting_demuxer_stream_ = decrypting_demuxer_stream;
+ state_ = NORMAL;
+ base::ResetAndReturn(&init_cb_).Run(true, decoder_->HasAlpha());
+ }
+
+ // Stop() called during initialization.
+ if (!stop_cb_.is_null()) {
+ Stop(base::ResetAndReturn(&stop_cb_));
+ return;
+ }
+}
+
+void VideoFrameStream::OnFrameRead(const VideoDecoder::Status status,
+ const scoped_refptr<VideoFrame>& frame) {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK_EQ(state_, NORMAL);
+ DCHECK(!read_cb_.is_null());
+
+ base::ResetAndReturn(&read_cb_).Run(status, frame);
+}
+
+void VideoFrameStream::ResetDecoder() {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK_EQ(state_, NORMAL);
+ DCHECK(!reset_cb_.is_null());
+
+ decoder_->Reset(base::Bind(&VideoFrameStream::OnDecoderReset, weak_this_));
+}
+
+void VideoFrameStream::OnDecoderReset() {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK_EQ(state_, NORMAL);
+ // If Reset() was called during pending read, read callback should be fired
+ // before the reset callback is fired.
+ DCHECK(read_cb_.is_null());
+ DCHECK(!reset_cb_.is_null());
+
+ base::ResetAndReturn(&reset_cb_).Run();
+}
+
+void VideoFrameStream::StopDecoder() {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK_EQ(state_, NORMAL);
+ DCHECK(!stop_cb_.is_null());
+
+ decoder_->Stop(base::Bind(&VideoFrameStream::OnDecoderStopped, weak_this_));
+}
+
+void VideoFrameStream::OnDecoderStopped() {
+ DCHECK(message_loop_->BelongsToCurrentThread());
+ DCHECK_EQ(state_, NORMAL);
+ // If Stop() was called during pending read/reset, read/reset callback should
+ // be fired before the stop callback is fired.
+ DCHECK(read_cb_.is_null());
+ DCHECK(reset_cb_.is_null());
+ DCHECK(!stop_cb_.is_null());
+
+ state_ = STOPPED;
+ base::ResetAndReturn(&stop_cb_).Run();
+}
+
+} // namespace media
« no previous file with comments | « media/filters/video_frame_stream.h ('k') | media/filters/video_frame_stream_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698