Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chromecast / media / cma / filters / demuxer_stream_adapter.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chromecast/media/cma/filters/demuxer_stream_adapter.h"
6
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/single_thread_task_runner.h"
10 #include "chromecast/media/cma/base/balanced_media_task_runner_factory.h"
11 #include "chromecast/media/cma/base/cma_logging.h"
12 #include "chromecast/media/cma/base/decoder_buffer_adapter.h"
13 #include "chromecast/media/cma/base/media_task_runner.h"
14 #include "media/base/bind_to_current_loop.h"
15 #include "media/base/buffers.h"
16 #include "media/base/decoder_buffer.h"
17 #include "media/base/demuxer_stream.h"
18
19 namespace chromecast {
20 namespace media {
21
22 namespace {
23
24 class DummyMediaTaskRunner : public MediaTaskRunner {
25  public:
26   DummyMediaTaskRunner(
27       const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
28
29   // MediaTaskRunner implementation.
30   virtual bool PostMediaTask(
31       const tracked_objects::Location& from_here,
32       const base::Closure& task,
33       base::TimeDelta timestamp) override;
34
35  private:
36   virtual ~DummyMediaTaskRunner();
37
38   scoped_refptr<base::SingleThreadTaskRunner> const task_runner_;
39
40   DISALLOW_COPY_AND_ASSIGN(DummyMediaTaskRunner);
41 };
42
43 DummyMediaTaskRunner::DummyMediaTaskRunner(
44     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
45   : task_runner_(task_runner) {
46 }
47
48 DummyMediaTaskRunner::~DummyMediaTaskRunner() {
49 }
50
51 bool DummyMediaTaskRunner::PostMediaTask(
52     const tracked_objects::Location& from_here,
53     const base::Closure& task,
54     base::TimeDelta timestamp) {
55   return task_runner_->PostTask(from_here, task);
56 }
57
58 }  // namespace
59
60 DemuxerStreamAdapter::DemuxerStreamAdapter(
61     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
62     const scoped_refptr<BalancedMediaTaskRunnerFactory>&
63     media_task_runner_factory,
64     ::media::DemuxerStream* demuxer_stream)
65     : task_runner_(task_runner),
66       media_task_runner_factory_(media_task_runner_factory),
67       media_task_runner_(new DummyMediaTaskRunner(task_runner)),
68       demuxer_stream_(demuxer_stream),
69       is_pending_read_(false),
70       is_pending_demuxer_read_(false),
71       weak_factory_(this) {
72   weak_this_ = weak_factory_.GetWeakPtr();
73   ResetMediaTaskRunner();
74   thread_checker_.DetachFromThread();
75 }
76
77 DemuxerStreamAdapter::~DemuxerStreamAdapter() {
78   // Needed since we use weak pointers:
79   // weak pointers must be invalidated on the same thread.
80   DCHECK(thread_checker_.CalledOnValidThread());
81 }
82
83 void DemuxerStreamAdapter::Read(const ReadCB& read_cb) {
84   DCHECK(thread_checker_.CalledOnValidThread());
85
86   DCHECK(flush_cb_.is_null());
87
88   // Support only one read at a time.
89   DCHECK(!is_pending_read_);
90   is_pending_read_ = true;
91   ReadInternal(read_cb);
92 }
93
94 void DemuxerStreamAdapter::ReadInternal(const ReadCB& read_cb) {
95   bool may_run_in_future = media_task_runner_->PostMediaTask(
96       FROM_HERE,
97       base::Bind(&DemuxerStreamAdapter::RequestBuffer, weak_this_, read_cb),
98       max_pts_);
99   DCHECK(may_run_in_future);
100 }
101
102 void DemuxerStreamAdapter::Flush(const base::Closure& flush_cb) {
103   DCHECK(thread_checker_.CalledOnValidThread());
104   CMALOG(kLogControl) << __FUNCTION__;
105
106   // Flush cancels any pending read.
107   is_pending_read_ = false;
108
109   // Reset the decoder configurations.
110   audio_config_ = ::media::AudioDecoderConfig();
111   video_config_ = ::media::VideoDecoderConfig();
112
113   // Create a new media task runner for the upcoming media timeline.
114   ResetMediaTaskRunner();
115
116   DCHECK(flush_cb_.is_null());
117   if (is_pending_demuxer_read_) {
118     // If there is a pending demuxer read, the implicit contract
119     // is that the pending read must be completed before invoking the
120     // flush callback.
121     flush_cb_ = flush_cb;
122     return;
123   }
124
125   // At this point, there is no more pending demuxer read,
126   // so all the previous tasks associated with the current timeline
127   // can be cancelled.
128   weak_factory_.InvalidateWeakPtrs();
129   weak_this_ = weak_factory_.GetWeakPtr();
130
131   CMALOG(kLogControl) << "Flush done";
132   flush_cb.Run();
133 }
134
135 void DemuxerStreamAdapter::ResetMediaTaskRunner() {
136   DCHECK(thread_checker_.CalledOnValidThread());
137
138   max_pts_ = ::media::kNoTimestamp();
139   if (media_task_runner_factory_.get()) {
140     media_task_runner_ =
141         media_task_runner_factory_->CreateMediaTaskRunner(task_runner_);
142   }
143 }
144
145 void DemuxerStreamAdapter::RequestBuffer(const ReadCB& read_cb) {
146   DCHECK(thread_checker_.CalledOnValidThread());
147   is_pending_demuxer_read_ = true;
148   demuxer_stream_->Read(::media::BindToCurrentLoop(
149       base::Bind(&DemuxerStreamAdapter::OnNewBuffer, weak_this_, read_cb)));
150 }
151
152 void DemuxerStreamAdapter::OnNewBuffer(
153     const ReadCB& read_cb,
154     ::media::DemuxerStream::Status status,
155     const scoped_refptr< ::media::DecoderBuffer>& input) {
156   DCHECK(thread_checker_.CalledOnValidThread());
157
158   is_pending_demuxer_read_ = false;
159
160   // Just discard the buffer in the flush stage.
161   if (!flush_cb_.is_null()) {
162     CMALOG(kLogControl) << "Flush done";
163     base::ResetAndReturn(&flush_cb_).Run();
164     return;
165   }
166
167   if (status == ::media::DemuxerStream::kAborted) {
168     DCHECK(input.get() == NULL);
169     return;
170   }
171
172   if (status == ::media::DemuxerStream::kConfigChanged) {
173     DCHECK(input.get() == NULL);
174     if (demuxer_stream_->type() == ::media::DemuxerStream::VIDEO)
175       video_config_ = demuxer_stream_->video_decoder_config();
176     if (demuxer_stream_->type() == ::media::DemuxerStream::AUDIO)
177       audio_config_ = demuxer_stream_->audio_decoder_config();
178
179     // Got a new config, but we still need to get a frame.
180     ReadInternal(read_cb);
181     return;
182   }
183
184   DCHECK_EQ(status, ::media::DemuxerStream::kOk);
185
186   // Updates the timestamp used for task scheduling.
187   if (!input->end_of_stream() &&
188       input->timestamp() != ::media::kNoTimestamp() &&
189       (max_pts_ == ::media::kNoTimestamp() || input->timestamp() > max_pts_)) {
190     max_pts_ = input->timestamp();
191   }
192
193   // Provides the buffer as well as possibly valid audio and video configs.
194   is_pending_read_ = false;
195   scoped_refptr<DecoderBufferBase> buffer(new DecoderBufferAdapter(input));
196   read_cb.Run(buffer, audio_config_, video_config_);
197
198   // Back to the default audio/video config:
199   // an invalid audio/video config means there is no config update.
200   if (audio_config_.IsValidConfig())
201     audio_config_ = ::media::AudioDecoderConfig();
202   if (video_config_.IsValidConfig())
203     video_config_ = ::media::VideoDecoderConfig();
204 }
205
206 }  // namespace media
207 }  // namespace chromecast