OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2013 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 "media/filters/text_renderer_impl.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/callback_helpers.h" | |
9 #include "base/logging.h" | |
10 #include "base/message_loop/message_loop_proxy.h" | |
11 #include "media/base/demuxer.h" | |
12 #include "media/base/demuxer_stream.h" | |
13 #include "media/base/text_buffer.h" | |
14 #include "media/base/text_decoder.h" | |
15 | |
16 namespace media { | |
17 | |
18 TextRendererImpl::TextRendererImpl( | |
19 const scoped_refptr<base::MessageLoopProxy>& message_loop, | |
20 scoped_ptr<TextDecoder> decoder, | |
21 const CueReadyCB& cue_ready_cb) | |
22 : message_loop_(message_loop), | |
23 weak_factory_(this), | |
24 decoder_(decoder.Pass()), | |
25 cue_ready_cb_(cue_ready_cb), | |
26 state_(kUninitialized), | |
27 text_stream_count_(0), | |
28 pending_read_count_(0), | |
29 eos_count_(0) { | |
30 } | |
31 | |
32 TextRendererImpl::~TextRendererImpl() { | |
33 DCHECK(state_ == kUninitialized || state_ == kStopped); | |
34 DCHECK_EQ(pending_read_count_, 0); | |
35 } | |
36 | |
37 void TextRendererImpl::Initialize(Demuxer* demuxer, | |
38 const PipelineStatusCB& init_cb, | |
39 const base::Closure& ended_cb) { | |
40 DCHECK(message_loop_->BelongsToCurrentThread()); | |
41 DCHECK_NE(demuxer, static_cast<Demuxer*>(NULL)); | |
42 DCHECK(!init_cb.is_null()); | |
43 DCHECK(!ended_cb.is_null()); | |
44 DCHECK_EQ(kUninitialized, state_); | |
45 DCHECK_EQ(text_stream_count_, 0); | |
46 DCHECK_EQ(pending_read_count_, 0); | |
47 DCHECK_EQ(eos_count_, 0); | |
48 DCHECK(init_cb_.is_null()); | |
49 DCHECK(ended_cb_.is_null()); | |
50 | |
51 weak_this_ = weak_factory_.GetWeakPtr(); | |
52 init_cb_ = init_cb; | |
53 ended_cb_ = ended_cb; | |
54 | |
55 decoder_->Initialize(demuxer); | |
56 | |
57 const int stream_count = demuxer->GetStreamCount(); | |
58 read_state_.reserve(stream_count); | |
59 | |
60 for (int idx = 0; idx < stream_count; ++idx) { | |
61 DemuxerStream* stream = demuxer->GetStreamByIndex(idx); | |
62 if (stream == NULL || stream->type() != DemuxerStream::TEXT) { | |
63 read_state_.push_back(kReadInactive); | |
64 } else { | |
65 read_state_.push_back(kReadIdle); | |
66 ++text_stream_count_; | |
67 } | |
68 } | |
69 | |
70 // Start the machine in the stopped state. We transition out | |
71 // of the stopped state via a Pause() or Play() request. | |
72 state_ = kStopped; | |
acolwell GONE FROM CHROMIUM
2013/09/12 00:15:15
It seems like state_ = kPaused and eos_count_ = te
Matthew Heaney (Chromium)
2013/09/13 19:51:54
Done.
| |
73 | |
74 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | |
acolwell GONE FROM CHROMIUM
2013/09/12 00:15:15
This method doesn't look like it actually needs to
Matthew Heaney (Chromium)
2013/09/13 19:51:54
Done.
| |
75 } | |
76 | |
77 void TextRendererImpl::Play(const base::Closure& callback) { | |
78 DCHECK(message_loop_->BelongsToCurrentThread()); | |
79 base::AutoLock auto_lock(lock_); | |
80 DCHECK_NE(state_, kUninitialized); | |
acolwell GONE FROM CHROMIUM
2013/09/12 00:15:15
nit: Remove since the DCHECK below is more specifi
Matthew Heaney (Chromium)
2013/09/13 19:51:54
Done.
| |
81 DCHECK(state_ == kPaused || state_ == kStopped); | |
82 | |
83 if (state_ == kStopped) | |
84 eos_count_ = text_stream_count_; | |
85 | |
86 state_ = kPlaying; | |
87 callback.Run(); | |
88 | |
89 for (std::vector<ReadState>::size_type idx = 0; | |
90 idx < read_state_.size(); ++idx) { | |
91 if (read_state_[idx] == kReadInactive) | |
92 continue; | |
93 | |
94 if (read_state_[idx] == kReadPending) { | |
95 DCHECK_GT(pending_read_count_, 0); | |
96 continue; | |
97 } | |
98 | |
99 read_state_[idx] = kReadPending; | |
100 ++pending_read_count_; | |
101 decoder_->Read(idx, base::Bind(&TextRendererImpl::CueReady, weak_this_)); | |
102 } | |
103 } | |
104 | |
105 void TextRendererImpl::Pause(const base::Closure& callback) { | |
106 DCHECK(message_loop_->BelongsToCurrentThread()); | |
107 base::AutoLock auto_lock(lock_); | |
108 DCHECK_NE(state_, kUninitialized); | |
109 DCHECK_NE(state_, kStopPending); | |
110 pause_cb_ = callback; | |
111 | |
112 if (state_ == kStopped) { | |
113 eos_count_ = text_stream_count_; | |
acolwell GONE FROM CHROMIUM
2013/09/12 00:15:15
Why is this line here? This doesn't feel right to
Matthew Heaney (Chromium)
2013/09/13 19:51:54
Done.
| |
114 state_ = kPaused; | |
115 base::ResetAndReturn(&pause_cb_).Run(); | |
116 return; | |
117 } | |
118 | |
119 if (state_ == kPaused) { | |
acolwell GONE FROM CHROMIUM
2013/09/12 00:15:15
You shouldn't get a Pause() call if you are alread
Matthew Heaney (Chromium)
2013/09/13 19:51:54
Done.
| |
120 DCHECK_EQ(pending_read_count_, 0); | |
121 base::ResetAndReturn(&pause_cb_).Run(); | |
122 return; | |
123 } | |
124 | |
125 if (state_ == kPausePending) | |
acolwell GONE FROM CHROMIUM
2013/09/12 00:15:15
You shouldn't get another Pause() call if the curr
Matthew Heaney (Chromium)
2013/09/13 19:51:54
Done.
| |
126 return; | |
127 | |
128 if (pending_read_count_ <= 0) { | |
129 state_ = kPaused; | |
130 base::ResetAndReturn(&pause_cb_).Run(); | |
131 return; | |
132 } | |
133 | |
134 state_ = kPausePending; | |
135 } | |
136 | |
acolwell GONE FROM CHROMIUM
2013/09/12 00:15:15
It seems like you would need a Flush() method so t
Matthew Heaney (Chromium)
2013/09/13 19:51:54
Done.
| |
137 void TextRendererImpl::Stop(const base::Closure& cb) { | |
138 DCHECK(message_loop_->BelongsToCurrentThread()); | |
139 DCHECK(!cb.is_null()); | |
140 base::AutoLock auto_lock(lock_); | |
141 DCHECK_NE(state_, kUninitialized); | |
142 | |
143 stop_cb_ = cb; | |
144 | |
145 if (state_ == kStopped) { | |
acolwell GONE FROM CHROMIUM
2013/09/12 00:15:15
You shound't get a stop if you have already receiv
Matthew Heaney (Chromium)
2013/09/13 19:51:54
Done.
| |
146 DCHECK_EQ(pending_read_count_, 0); | |
147 base::ResetAndReturn(&stop_cb_).Run(); | |
148 return; | |
149 } | |
150 | |
151 if (state_ == kStopPending) { | |
acolwell GONE FROM CHROMIUM
2013/09/12 00:15:15
You should not get a Stop() if the previous one is
Matthew Heaney (Chromium)
2013/09/13 19:51:54
Done.
| |
152 DCHECK_GT(pending_read_count_, 0); | |
153 stop_cb_ = cb; | |
154 return; | |
155 } | |
156 | |
157 if (pending_read_count_ <= 0) { | |
158 state_ = kStopped; | |
159 base::ResetAndReturn(&stop_cb_).Run(); | |
160 return; | |
161 } | |
162 | |
163 state_ = kStopPending; | |
164 } | |
165 | |
166 void TextRendererImpl::CueReady( | |
167 int index, | |
168 const scoped_refptr<TextBuffer>& buffer) { | |
169 base::AutoLock auto_lock(lock_); | |
170 DCHECK_NE(state_, kUninitialized); | |
acolwell GONE FROM CHROMIUM
2013/09/12 00:15:15
can't you DCHECK(message_loop_->BelongsToCurrentTh
Matthew Heaney (Chromium)
2013/09/13 19:51:54
Done.
| |
171 DCHECK_NE(state_, kStopped); | |
172 DCHECK_GT(pending_read_count_, 0); | |
173 DCHECK_GT(eos_count_, 0); | |
174 DCHECK_EQ(read_state_[index], kReadPending); | |
175 | |
176 --pending_read_count_; | |
177 read_state_[index] = kReadIdle; | |
178 | |
179 switch (state_) { | |
180 case kPlaying: | |
181 if (buffer.get()) | |
acolwell GONE FROM CHROMIUM
2013/09/12 00:15:15
nit: You shouldn't need the get()
Matthew Heaney (Chromium)
2013/09/13 19:51:54
Done.
| |
182 break; | |
183 | |
184 // A NULL buffer means that we have reached EOS (or there's an error). | |
185 | |
186 --eos_count_; | |
187 | |
188 if (pending_read_count_ > 0) | |
acolwell GONE FROM CHROMIUM
2013/09/12 00:15:15
DCHECK
Matthew Heaney (Chromium)
2013/09/13 19:51:54
Multiple read requests can be pending simultaneous
acolwell GONE FROM CHROMIUM
2013/09/13 20:57:30
Ok. Right. I don't know what I was thinking here.
| |
189 return; | |
190 | |
191 if (eos_count_ <= 0) { | |
192 state_ = kStopped; | |
acolwell GONE FROM CHROMIUM
2013/09/12 00:15:15
it seems like an kEnded state would be more approp
Matthew Heaney (Chromium)
2013/09/13 19:51:54
Done.
| |
193 ended_cb_.Run(); | |
194 } | |
195 | |
196 return; | |
197 | |
198 case kPausePending: | |
199 if (pending_read_count_ <= 0) { | |
200 state_ = kPaused; | |
201 pause_cb_.Run(); | |
202 } | |
203 | |
204 return; | |
205 | |
206 case kStopPending: | |
207 if (pending_read_count_ <= 0) { | |
208 state_ = kStopped; | |
209 stop_cb_.Run(); | |
210 } | |
211 | |
212 return; | |
213 | |
214 case kPaused: | |
215 case kStopped: | |
216 case kUninitialized: | |
217 default: | |
218 NOTREACHED(); | |
219 return; | |
220 } | |
221 | |
222 cue_ready_cb_.Run(index, buffer); | |
223 | |
224 read_state_[index] = kReadPending; | |
225 ++pending_read_count_; | |
226 decoder_->Read(index, base::Bind(&TextRendererImpl::CueReady, weak_this_)); | |
227 } | |
228 | |
229 } // namespace media | |
OLD | NEW |