| Index: media/base/composite_filter.cc
|
| diff --git a/media/base/composite_filter.cc b/media/base/composite_filter.cc
|
| deleted file mode 100644
|
| index 21bad5cb1f1976f00b74184945d20ef945f83956..0000000000000000000000000000000000000000
|
| --- a/media/base/composite_filter.cc
|
| +++ /dev/null
|
| @@ -1,471 +0,0 @@
|
| -// Copyright (c) 2012 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/base/composite_filter.h"
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/callback.h"
|
| -#include "base/callback_helpers.h"
|
| -#include "base/location.h"
|
| -#include "base/message_loop_proxy.h"
|
| -#include "base/stl_util.h"
|
| -
|
| -namespace media {
|
| -
|
| -class CompositeFilter::FilterHostImpl : public FilterHost {
|
| - public:
|
| - FilterHostImpl(CompositeFilter* parent, FilterHost* host);
|
| -
|
| - FilterHost* host();
|
| -
|
| - // media::FilterHost methods.
|
| - virtual void SetError(PipelineStatus error) OVERRIDE;
|
| - virtual base::TimeDelta GetTime() const OVERRIDE;
|
| - virtual base::TimeDelta GetDuration() const OVERRIDE;
|
| - virtual void SetNaturalVideoSize(const gfx::Size& size) OVERRIDE;
|
| - virtual void NotifyEnded() OVERRIDE;
|
| -
|
| - private:
|
| - CompositeFilter* parent_;
|
| - FilterHost* host_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(FilterHostImpl);
|
| -};
|
| -
|
| -CompositeFilter::CompositeFilter(
|
| - const scoped_refptr<base::MessageLoopProxy>& message_loop)
|
| - : state_(kCreated),
|
| - sequence_index_(0),
|
| - message_loop_(message_loop),
|
| - status_(PIPELINE_OK),
|
| - weak_ptr_factory_(this) {
|
| - DCHECK(message_loop);
|
| -}
|
| -
|
| -CompositeFilter::~CompositeFilter() {
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| - DCHECK(state_ == kCreated || state_ == kStopped);
|
| -
|
| - filters_.clear();
|
| -}
|
| -
|
| -void CompositeFilter::AddFilter(scoped_refptr<Filter> filter) {
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| - CHECK(filter && state_ == kCreated && host());
|
| -
|
| - // Register ourselves as the filter's host.
|
| - filter->SetHost(host_impl_.get());
|
| - filters_.push_back(make_scoped_refptr(filter.get()));
|
| -}
|
| -
|
| -void CompositeFilter::SetHost(FilterHost* host) {
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| - DCHECK(host);
|
| - DCHECK(!host_impl_.get());
|
| - host_impl_.reset(new FilterHostImpl(this, host));
|
| -}
|
| -
|
| -void CompositeFilter::Play(const base::Closure& play_cb) {
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| - if (IsOperationPending()) {
|
| - SendErrorToHost(PIPELINE_ERROR_OPERATION_PENDING);
|
| - play_cb.Run();
|
| - return;
|
| - } else if (state_ == kPlaying) {
|
| - play_cb.Run();
|
| - return;
|
| - } else if (!host() || (state_ != kPaused && state_ != kCreated)) {
|
| - SendErrorToHost(PIPELINE_ERROR_INVALID_STATE);
|
| - play_cb.Run();
|
| - return;
|
| - }
|
| -
|
| - ChangeState(kPlayPending);
|
| - callback_ = play_cb;
|
| - StartSerialCallSequence();
|
| -}
|
| -
|
| -void CompositeFilter::Pause(const base::Closure& pause_cb) {
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| - if (IsOperationPending()) {
|
| - SendErrorToHost(PIPELINE_ERROR_OPERATION_PENDING);
|
| - pause_cb.Run();
|
| - return;
|
| - } else if (state_ == kPaused) {
|
| - pause_cb.Run();
|
| - return;
|
| - } else if (!host() || state_ != kPlaying) {
|
| - SendErrorToHost(PIPELINE_ERROR_INVALID_STATE);
|
| - pause_cb.Run();
|
| - return;
|
| - }
|
| -
|
| - ChangeState(kPausePending);
|
| - callback_ = pause_cb;
|
| - StartSerialCallSequence();
|
| -}
|
| -
|
| -void CompositeFilter::Flush(const base::Closure& flush_cb) {
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| - if (IsOperationPending()) {
|
| - SendErrorToHost(PIPELINE_ERROR_OPERATION_PENDING);
|
| - flush_cb.Run();
|
| - return;
|
| - } else if (!host() || (state_ != kCreated && state_ != kPaused)) {
|
| - SendErrorToHost(PIPELINE_ERROR_INVALID_STATE);
|
| - flush_cb.Run();
|
| - return;
|
| - }
|
| -
|
| - ChangeState(kFlushPending);
|
| - callback_ = flush_cb;
|
| - StartParallelCallSequence();
|
| -}
|
| -
|
| -void CompositeFilter::Stop(const base::Closure& stop_cb) {
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| - if (!host()) {
|
| - SendErrorToHost(PIPELINE_ERROR_INVALID_STATE);
|
| - stop_cb.Run();
|
| - return;
|
| - } else if (state_ == kStopped) {
|
| - stop_cb.Run();
|
| - return;
|
| - }
|
| -
|
| - switch (state_) {
|
| - case kError:
|
| - case kCreated:
|
| - case kPaused:
|
| - case kPlaying:
|
| - ChangeState(kStopPending);
|
| - break;
|
| - case kPlayPending:
|
| - ChangeState(kStopWhilePlayPending);
|
| - break;
|
| - case kPausePending:
|
| - ChangeState(kStopWhilePausePending);
|
| - break;
|
| - case kFlushPending:
|
| - ChangeState(kStopWhileFlushPending);
|
| - break;
|
| - case kSeekPending:
|
| - ChangeState(kStopWhileSeekPending);
|
| - break;
|
| - default:
|
| - SendErrorToHost(PIPELINE_ERROR_INVALID_STATE);
|
| - stop_cb.Run();
|
| - return;
|
| - }
|
| -
|
| - if (!status_cb_.is_null()) {
|
| - DCHECK_EQ(state_, kStopWhileSeekPending);
|
| - status_cb_.Reset();
|
| - }
|
| -
|
| - callback_ = stop_cb;
|
| - if (state_ == kStopPending) {
|
| - StartSerialCallSequence();
|
| - }
|
| -}
|
| -
|
| -void CompositeFilter::SetPlaybackRate(float playback_rate) {
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| - for (FilterVector::iterator iter = filters_.begin();
|
| - iter != filters_.end();
|
| - ++iter) {
|
| - (*iter)->SetPlaybackRate(playback_rate);
|
| - }
|
| -}
|
| -
|
| -void CompositeFilter::Seek(base::TimeDelta time,
|
| - const PipelineStatusCB& seek_cb) {
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| -
|
| - if (IsOperationPending()) {
|
| - seek_cb.Run(PIPELINE_ERROR_OPERATION_PENDING);
|
| - return;
|
| - } else if (!host() || (state_ != kPaused && state_ != kCreated)) {
|
| - seek_cb.Run(PIPELINE_ERROR_INVALID_STATE);
|
| - return;
|
| - }
|
| -
|
| - ChangeState(kSeekPending);
|
| - status_cb_ = seek_cb;
|
| - pending_seek_time_ = time;
|
| - StartSerialCallSequence();
|
| -}
|
| -
|
| -void CompositeFilter::ChangeState(State new_state) {
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| - state_ = new_state;
|
| -}
|
| -
|
| -void CompositeFilter::StartSerialCallSequence() {
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| - status_ = PIPELINE_OK;
|
| - sequence_index_ = 0;
|
| -
|
| - if (!filters_.empty()) {
|
| - CallFilter(filters_[sequence_index_],
|
| - NewThreadSafeCallback(&CompositeFilter::SerialCallback));
|
| - } else {
|
| - SerialCallback();
|
| - }
|
| -}
|
| -
|
| -void CompositeFilter::StartParallelCallSequence() {
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| - status_ = PIPELINE_OK;
|
| - sequence_index_ = 0;
|
| -
|
| - if (!filters_.empty()) {
|
| - for (size_t i = 0; i < filters_.size(); i++) {
|
| - CallFilter(filters_[i],
|
| - NewThreadSafeCallback(&CompositeFilter::ParallelCallback));
|
| - }
|
| - } else {
|
| - ParallelCallback();
|
| - }
|
| -}
|
| -
|
| -void CompositeFilter::CallFilter(scoped_refptr<Filter>& filter,
|
| - const base::Closure& callback) {
|
| - switch (state_) {
|
| - case kPlayPending:
|
| - filter->Play(callback);
|
| - break;
|
| - case kPausePending:
|
| - filter->Pause(callback);
|
| - break;
|
| - case kFlushPending:
|
| - filter->Flush(callback);
|
| - break;
|
| - case kStopPending:
|
| - filter->Stop(callback);
|
| - break;
|
| - case kSeekPending:
|
| - filter->Seek(pending_seek_time_,
|
| - base::Bind(&CompositeFilter::OnStatusCB, this, callback));
|
| - break;
|
| - default:
|
| - ChangeState(kError);
|
| - DispatchPendingCallback(PIPELINE_ERROR_INVALID_STATE);
|
| - }
|
| -}
|
| -
|
| -void CompositeFilter::DispatchPendingCallback(PipelineStatus status) {
|
| - DCHECK(status_cb_.is_null() ^ callback_.is_null());
|
| -
|
| - if (!status_cb_.is_null()) {
|
| - base::ResetAndReturn(&status_cb_).Run(status);
|
| - return;
|
| - }
|
| -
|
| - if (!callback_.is_null()) {
|
| - if (status != PIPELINE_OK)
|
| - SendErrorToHost(status);
|
| - base::ResetAndReturn(&callback_).Run();
|
| - }
|
| -}
|
| -
|
| -CompositeFilter::State CompositeFilter::GetNextState(State state) const {
|
| - State ret = kInvalid;
|
| - switch (state) {
|
| - case kPlayPending:
|
| - ret = kPlaying;
|
| - break;
|
| - case kPausePending:
|
| - case kFlushPending:
|
| - ret = kPaused;
|
| - break;
|
| - case kStopPending:
|
| - ret = kStopped;
|
| - break;
|
| - case kSeekPending:
|
| - ret = kPaused;
|
| - break;
|
| - case kStopWhilePlayPending:
|
| - case kStopWhilePausePending:
|
| - case kStopWhileFlushPending:
|
| - case kStopWhileSeekPending:
|
| - ret = kStopPending;
|
| - break;
|
| -
|
| - case kInvalid:
|
| - case kCreated:
|
| - case kPlaying:
|
| - case kPaused:
|
| - case kStopped:
|
| - case kError:
|
| - ret = kInvalid;
|
| - break;
|
| -
|
| - // default: intentionally left out to catch missing states.
|
| - }
|
| -
|
| - return ret;
|
| -}
|
| -
|
| -void CompositeFilter::SerialCallback() {
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| - if (status_ != PIPELINE_OK) {
|
| - // We encountered an error. Terminate the sequence now.
|
| - ChangeState(kError);
|
| - DispatchPendingCallback(status_);
|
| - return;
|
| - }
|
| - if (!filters_.empty())
|
| - sequence_index_++;
|
| -
|
| - if (sequence_index_ == filters_.size()) {
|
| - // All filters have been successfully called without error.
|
| - OnCallSequenceDone();
|
| - } else if (GetNextState(state_) == kStopPending) {
|
| - // Abort sequence early and start issuing Stop() calls.
|
| - ChangeState(kStopPending);
|
| - StartSerialCallSequence();
|
| - } else {
|
| - // We aren't done with the sequence. Call the next filter.
|
| - CallFilter(filters_[sequence_index_],
|
| - NewThreadSafeCallback(&CompositeFilter::SerialCallback));
|
| - }
|
| -}
|
| -
|
| -void CompositeFilter::ParallelCallback() {
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| -
|
| - if (!filters_.empty())
|
| - sequence_index_++;
|
| -
|
| - if (sequence_index_ == filters_.size()) {
|
| - if (status_ != PIPELINE_OK) {
|
| - // We encountered an error.
|
| - ChangeState(kError);
|
| - DispatchPendingCallback(status_);
|
| - return;
|
| - }
|
| -
|
| - OnCallSequenceDone();
|
| - }
|
| -}
|
| -
|
| -void CompositeFilter::OnCallSequenceDone() {
|
| - State next_state = GetNextState(state_);
|
| - if (next_state == kInvalid) {
|
| - // We somehow got into an unexpected state.
|
| - ChangeState(kError);
|
| - DispatchPendingCallback(PIPELINE_ERROR_INVALID_STATE);
|
| - return;
|
| - }
|
| -
|
| - ChangeState(next_state);
|
| -
|
| - if (state_ == kStopPending) {
|
| - // Handle a deferred Stop().
|
| - StartSerialCallSequence();
|
| - } else {
|
| - // Call the callback to indicate that the operation has completed.
|
| - DispatchPendingCallback(PIPELINE_OK);
|
| - }
|
| -}
|
| -
|
| -void CompositeFilter::SendErrorToHost(PipelineStatus error) {
|
| - if (host_impl_.get())
|
| - host_impl_.get()->host()->SetError(error);
|
| -}
|
| -
|
| -// Execute |closure| if on |message_loop|, otherwise post to it.
|
| -static void TrampolineClosureIfNecessary(
|
| - const scoped_refptr<base::MessageLoopProxy>& message_loop,
|
| - const base::Closure& closure) {
|
| - if (message_loop->BelongsToCurrentThread())
|
| - closure.Run();
|
| - else
|
| - message_loop->PostTask(FROM_HERE, closure);
|
| -}
|
| -
|
| -base::Closure CompositeFilter::NewThreadSafeCallback(
|
| - void (CompositeFilter::*method)()) {
|
| - return base::Bind(&TrampolineClosureIfNecessary,
|
| - message_loop_,
|
| - base::Bind(method, weak_ptr_factory_.GetWeakPtr()));
|
| -}
|
| -
|
| -bool CompositeFilter::CanForwardError() {
|
| - return (state_ == kCreated) || (state_ == kPlaying) || (state_ == kPaused);
|
| -}
|
| -
|
| -bool CompositeFilter::IsOperationPending() const {
|
| - DCHECK(callback_.is_null() || status_cb_.is_null());
|
| -
|
| - return !callback_.is_null() || !status_cb_.is_null();
|
| -}
|
| -
|
| -void CompositeFilter::OnStatusCB(const base::Closure& callback,
|
| - PipelineStatus status) {
|
| - if (status != PIPELINE_OK)
|
| - SetError(status);
|
| -
|
| - callback.Run();
|
| -}
|
| -
|
| -FilterHost* CompositeFilter::host() {
|
| - return host_impl_.get() ? host_impl_.get()->host() : NULL;
|
| -}
|
| -
|
| -void CompositeFilter::SetError(PipelineStatus error) {
|
| - if (!message_loop_->BelongsToCurrentThread()) {
|
| - message_loop_->PostTask(FROM_HERE,
|
| - base::Bind(&CompositeFilter::SetError, this, error));
|
| - return;
|
| - }
|
| -
|
| - DCHECK(message_loop_->BelongsToCurrentThread());
|
| - DCHECK_NE(state_, kCreated);
|
| -
|
| - // Drop errors recieved while stopping or stopped.
|
| - // This shields the owner of this object from having
|
| - // to deal with errors it can't do anything about.
|
| - if (state_ == kStopPending || state_ == kStopped)
|
| - return;
|
| -
|
| - status_ = error;
|
| - if (CanForwardError())
|
| - SendErrorToHost(error);
|
| -}
|
| -
|
| -CompositeFilter::FilterHostImpl::FilterHostImpl(CompositeFilter* parent,
|
| - FilterHost* host)
|
| - : parent_(parent),
|
| - host_(host) {
|
| -}
|
| -
|
| -FilterHost* CompositeFilter::FilterHostImpl::host() {
|
| - return host_;
|
| -}
|
| -
|
| -// media::FilterHost methods.
|
| -void CompositeFilter::FilterHostImpl::SetError(PipelineStatus error) {
|
| - parent_->SetError(error);
|
| -}
|
| -
|
| -base::TimeDelta CompositeFilter::FilterHostImpl::GetTime() const {
|
| - return host_->GetTime();
|
| -}
|
| -
|
| -base::TimeDelta CompositeFilter::FilterHostImpl::GetDuration() const {
|
| - return host_->GetDuration();
|
| -}
|
| -
|
| -void CompositeFilter::FilterHostImpl::SetNaturalVideoSize(
|
| - const gfx::Size& size) {
|
| - host_->SetNaturalVideoSize(size);
|
| -}
|
| -
|
| -void CompositeFilter::FilterHostImpl::NotifyEnded() {
|
| - host_->NotifyEnded();
|
| -}
|
| -
|
| -} // namespace media
|
|
|