Index: media/filters/adaptive_demuxer.cc |
diff --git a/media/filters/adaptive_demuxer.cc b/media/filters/adaptive_demuxer.cc |
index 9a94d11bbd797606ab9035571ece8d1201ba60bf..5599b15c3b0eb9b7d61d28f1c40d9b6a8f71cc85 100644 |
--- a/media/filters/adaptive_demuxer.cc |
+++ b/media/filters/adaptive_demuxer.cc |
@@ -2,6 +2,7 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+#include "base/bind.h" |
#include "base/logging.h" |
#include "base/string_number_conversions.h" |
#include "base/string_split.h" |
@@ -160,6 +161,8 @@ Demuxer* AdaptiveDemuxer::current_demuxer(DemuxerStream::Type type) { |
// Helper class that wraps a FilterCallback and expects to get called a set |
// number of times, after which the wrapped callback is fired (and deleted). |
+// |
+// TODO: Remove this class once Stop() is converted to FilterStatusCB. |
class CountingCallback { |
public: |
CountingCallback(int count, FilterCallback* orig_cb) |
@@ -191,21 +194,69 @@ class CountingCallback { |
scoped_ptr<FilterCallback> orig_cb_; |
}; |
+// Helper class that wraps FilterStatusCB and expects to get called a set |
+// number of times, after which the wrapped callback is fired. If an error |
+// is reported in any of the callbacks, only the first error code is passed |
+// to the wrapped callback. |
+class CountingStatusCB : public base::RefCountedThreadSafe<CountingStatusCB> { |
+ public: |
+ CountingStatusCB(int count, const FilterStatusCB& orig_cb) |
+ : remaining_count_(count), orig_cb_(orig_cb), |
+ overall_status_(PIPELINE_OK) { |
+ DCHECK_GT(remaining_count_, 0); |
+ DCHECK(!orig_cb.is_null()); |
+ } |
+ |
+ FilterStatusCB GetACallback() { |
+ return base::Bind(&CountingStatusCB::OnChildCallbackDone, this); |
+ } |
+ |
+ private: |
+ void OnChildCallbackDone(PipelineStatus status) { |
+ bool fire_orig_cb = false; |
+ PipelineStatus overall_status = PIPELINE_OK; |
+ |
+ { |
+ base::AutoLock auto_lock(lock_); |
+ |
+ if (overall_status_ == PIPELINE_OK && status != PIPELINE_OK) |
+ overall_status_ = status; |
+ |
+ if (--remaining_count_ == 0) { |
+ fire_orig_cb = true; |
+ overall_status = overall_status_; |
+ } |
+ } |
+ |
+ if (fire_orig_cb) |
+ orig_cb_.Run(overall_status); |
+ } |
+ |
+ base::Lock lock_; |
+ int remaining_count_; |
+ FilterStatusCB orig_cb_; |
+ PipelineStatus overall_status_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(CountingStatusCB); |
+}; |
+ |
void AdaptiveDemuxer::Stop(FilterCallback* callback) { |
// Stop() must be called on all of the demuxers even though only one demuxer |
// is actively delivering audio and another one is delivering video. This |
// just satisfies the contract that all demuxers must have Stop() called on |
// them before they are destroyed. |
+ // |
+ // TODO: Remove CountingCallback once Stop() is converted to FilterStatusCB. |
CountingCallback* wrapper = new CountingCallback(demuxers_.size(), callback); |
for (size_t i = 0; i < demuxers_.size(); ++i) |
demuxers_[i]->Stop(wrapper->GetACallback()); |
} |
-void AdaptiveDemuxer::Seek(base::TimeDelta time, FilterCallback* callback) { |
+void AdaptiveDemuxer::Seek(base::TimeDelta time, const FilterStatusCB& cb) { |
Demuxer* audio = current_demuxer(DemuxerStream::AUDIO); |
Demuxer* video = current_demuxer(DemuxerStream::VIDEO); |
int count = (audio ? 1 : 0) + (video && audio != video ? 1 : 0); |
- CountingCallback* wrapper = new CountingCallback(count, callback); |
+ CountingStatusCB* wrapper = new CountingStatusCB(count, cb); |
if (audio) |
audio->Seek(time, wrapper->GetACallback()); |
if (video && audio != video) |