OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/base/text_renderer.h" | 5 #include "media/base/text_renderer.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 |
8 #include <utility> | 9 #include <utility> |
9 | 10 |
10 #include "base/bind.h" | 11 #include "base/bind.h" |
11 #include "base/callback_helpers.h" | 12 #include "base/callback_helpers.h" |
12 #include "base/logging.h" | 13 #include "base/logging.h" |
13 #include "base/single_thread_task_runner.h" | 14 #include "base/single_thread_task_runner.h" |
14 #include "base/stl_util.h" | |
15 #include "media/base/bind_to_current_loop.h" | 15 #include "media/base/bind_to_current_loop.h" |
16 #include "media/base/decoder_buffer.h" | 16 #include "media/base/decoder_buffer.h" |
17 #include "media/base/demuxer.h" | 17 #include "media/base/demuxer.h" |
18 #include "media/base/text_cue.h" | 18 #include "media/base/text_cue.h" |
19 | 19 |
20 namespace media { | 20 namespace media { |
21 | 21 |
22 TextRenderer::TextRenderer( | 22 TextRenderer::TextRenderer( |
23 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 23 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
24 const AddTextTrackCB& add_text_track_cb) | 24 const AddTextTrackCB& add_text_track_cb) |
25 : task_runner_(task_runner), | 25 : task_runner_(task_runner), |
26 add_text_track_cb_(add_text_track_cb), | 26 add_text_track_cb_(add_text_track_cb), |
27 state_(kUninitialized), | 27 state_(kUninitialized), |
28 pending_read_count_(0), | 28 pending_read_count_(0), |
29 weak_factory_(this) {} | 29 weak_factory_(this) {} |
30 | 30 |
31 TextRenderer::~TextRenderer() { | 31 TextRenderer::~TextRenderer() { |
32 DCHECK(task_runner_->BelongsToCurrentThread()); | 32 DCHECK(task_runner_->BelongsToCurrentThread()); |
33 base::STLDeleteValues(&text_track_state_map_); | 33 text_track_state_map_.clear(); |
34 if (!pause_cb_.is_null()) | 34 if (!pause_cb_.is_null()) |
35 base::ResetAndReturn(&pause_cb_).Run(); | 35 base::ResetAndReturn(&pause_cb_).Run(); |
36 } | 36 } |
37 | 37 |
38 void TextRenderer::Initialize(const base::Closure& ended_cb) { | 38 void TextRenderer::Initialize(const base::Closure& ended_cb) { |
39 DCHECK(task_runner_->BelongsToCurrentThread()); | 39 DCHECK(task_runner_->BelongsToCurrentThread()); |
40 DCHECK(!ended_cb.is_null()); | 40 DCHECK(!ended_cb.is_null()); |
41 DCHECK_EQ(kUninitialized, state_) << "state_ " << state_; | 41 DCHECK_EQ(kUninitialized, state_) << "state_ " << state_; |
42 DCHECK(text_track_state_map_.empty()); | 42 DCHECK(text_track_state_map_.empty()); |
43 DCHECK_EQ(pending_read_count_, 0); | 43 DCHECK_EQ(pending_read_count_, 0); |
44 DCHECK(pending_eos_set_.empty()); | 44 DCHECK(pending_eos_set_.empty()); |
45 DCHECK(ended_cb_.is_null()); | 45 DCHECK(ended_cb_.is_null()); |
46 | 46 |
47 ended_cb_ = ended_cb; | 47 ended_cb_ = ended_cb; |
48 state_ = kPaused; | 48 state_ = kPaused; |
49 } | 49 } |
50 | 50 |
51 void TextRenderer::StartPlaying() { | 51 void TextRenderer::StartPlaying() { |
52 DCHECK(task_runner_->BelongsToCurrentThread()); | 52 DCHECK(task_runner_->BelongsToCurrentThread()); |
53 DCHECK_EQ(state_, kPaused) << "state_ " << state_; | 53 DCHECK_EQ(state_, kPaused) << "state_ " << state_; |
54 | 54 |
55 for (TextTrackStateMap::iterator itr = text_track_state_map_.begin(); | 55 for (auto itr = text_track_state_map_.begin(); |
56 itr != text_track_state_map_.end(); ++itr) { | 56 itr != text_track_state_map_.end(); ++itr) { |
57 TextTrackState* state = itr->second; | 57 TextTrackState* state = itr->second.get(); |
58 if (state->read_state == TextTrackState::kReadPending) { | 58 if (state->read_state == TextTrackState::kReadPending) { |
59 DCHECK_GT(pending_read_count_, 0); | 59 DCHECK_GT(pending_read_count_, 0); |
60 continue; | 60 continue; |
61 } | 61 } |
62 | 62 |
63 Read(state, itr->first); | 63 Read(state, itr->first); |
64 } | 64 } |
65 | 65 |
66 state_ = kPlaying; | 66 state_ = kPlaying; |
67 } | 67 } |
(...skipping 11 matching lines...) Expand all Loading... |
79 | 79 |
80 pause_cb_ = callback; | 80 pause_cb_ = callback; |
81 state_ = kPausePending; | 81 state_ = kPausePending; |
82 } | 82 } |
83 | 83 |
84 void TextRenderer::Flush(const base::Closure& callback) { | 84 void TextRenderer::Flush(const base::Closure& callback) { |
85 DCHECK(task_runner_->BelongsToCurrentThread()); | 85 DCHECK(task_runner_->BelongsToCurrentThread()); |
86 DCHECK_EQ(pending_read_count_, 0); | 86 DCHECK_EQ(pending_read_count_, 0); |
87 DCHECK(state_ == kPaused) << "state_ " << state_; | 87 DCHECK(state_ == kPaused) << "state_ " << state_; |
88 | 88 |
89 for (TextTrackStateMap::iterator itr = text_track_state_map_.begin(); | 89 for (auto itr = text_track_state_map_.begin(); |
90 itr != text_track_state_map_.end(); ++itr) { | 90 itr != text_track_state_map_.end(); ++itr) { |
91 pending_eos_set_.insert(itr->first); | 91 pending_eos_set_.insert(itr->first); |
92 itr->second->text_ranges_.Reset(); | 92 itr->second->text_ranges_.Reset(); |
93 } | 93 } |
94 DCHECK_EQ(pending_eos_set_.size(), text_track_state_map_.size()); | 94 DCHECK_EQ(pending_eos_set_.size(), text_track_state_map_.size()); |
95 task_runner_->PostTask(FROM_HERE, callback); | 95 task_runner_->PostTask(FROM_HERE, callback); |
96 } | 96 } |
97 | 97 |
98 void TextRenderer::AddTextStream(DemuxerStream* text_stream, | 98 void TextRenderer::AddTextStream(DemuxerStream* text_stream, |
99 const TextTrackConfig& config) { | 99 const TextTrackConfig& config) { |
100 DCHECK(task_runner_->BelongsToCurrentThread()); | 100 DCHECK(task_runner_->BelongsToCurrentThread()); |
101 DCHECK(state_ != kUninitialized) << "state_ " << state_; | 101 DCHECK(state_ != kUninitialized) << "state_ " << state_; |
102 DCHECK(text_track_state_map_.find(text_stream) == | 102 DCHECK(text_track_state_map_.find(text_stream) == |
103 text_track_state_map_.end()); | 103 text_track_state_map_.end()); |
104 DCHECK(pending_eos_set_.find(text_stream) == | 104 DCHECK(pending_eos_set_.find(text_stream) == |
105 pending_eos_set_.end()); | 105 pending_eos_set_.end()); |
106 | 106 |
107 AddTextTrackDoneCB done_cb = | 107 AddTextTrackDoneCB done_cb = |
108 BindToCurrentLoop(base::Bind(&TextRenderer::OnAddTextTrackDone, | 108 BindToCurrentLoop(base::Bind(&TextRenderer::OnAddTextTrackDone, |
109 weak_factory_.GetWeakPtr(), | 109 weak_factory_.GetWeakPtr(), |
110 text_stream)); | 110 text_stream)); |
111 | 111 |
112 add_text_track_cb_.Run(config, done_cb); | 112 add_text_track_cb_.Run(config, done_cb); |
113 } | 113 } |
114 | 114 |
115 void TextRenderer::RemoveTextStream(DemuxerStream* text_stream) { | 115 void TextRenderer::RemoveTextStream(DemuxerStream* text_stream) { |
116 DCHECK(task_runner_->BelongsToCurrentThread()); | 116 DCHECK(task_runner_->BelongsToCurrentThread()); |
117 | 117 |
118 TextTrackStateMap::iterator itr = text_track_state_map_.find(text_stream); | 118 auto itr = text_track_state_map_.find(text_stream); |
119 DCHECK(itr != text_track_state_map_.end()); | 119 DCHECK(itr != text_track_state_map_.end()); |
120 | 120 |
121 TextTrackState* state = itr->second; | 121 TextTrackState* state = itr->second.get(); |
122 DCHECK_EQ(state->read_state, TextTrackState::kReadIdle); | 122 DCHECK_EQ(state->read_state, TextTrackState::kReadIdle); |
123 delete state; | |
124 text_track_state_map_.erase(itr); | 123 text_track_state_map_.erase(itr); |
125 | 124 |
126 pending_eos_set_.erase(text_stream); | 125 pending_eos_set_.erase(text_stream); |
127 } | 126 } |
128 | 127 |
129 bool TextRenderer::HasTracks() const { | 128 bool TextRenderer::HasTracks() const { |
130 DCHECK(task_runner_->BelongsToCurrentThread()); | 129 DCHECK(task_runner_->BelongsToCurrentThread()); |
131 return !text_track_state_map_.empty(); | 130 return !text_track_state_map_.empty(); |
132 } | 131 } |
133 | 132 |
134 void TextRenderer::BufferReady( | 133 void TextRenderer::BufferReady( |
135 DemuxerStream* stream, | 134 DemuxerStream* stream, |
136 DemuxerStream::Status status, | 135 DemuxerStream::Status status, |
137 const scoped_refptr<DecoderBuffer>& input) { | 136 const scoped_refptr<DecoderBuffer>& input) { |
138 DCHECK(task_runner_->BelongsToCurrentThread()); | 137 DCHECK(task_runner_->BelongsToCurrentThread()); |
139 DCHECK_NE(status, DemuxerStream::kConfigChanged); | 138 DCHECK_NE(status, DemuxerStream::kConfigChanged); |
140 | 139 |
141 if (status == DemuxerStream::kAborted) { | 140 if (status == DemuxerStream::kAborted) { |
142 DCHECK(!input.get()); | 141 DCHECK(!input.get()); |
143 DCHECK_GT(pending_read_count_, 0); | 142 DCHECK_GT(pending_read_count_, 0); |
144 DCHECK(pending_eos_set_.find(stream) != pending_eos_set_.end()); | 143 DCHECK(pending_eos_set_.find(stream) != pending_eos_set_.end()); |
145 | 144 |
146 TextTrackStateMap::iterator itr = text_track_state_map_.find(stream); | 145 auto itr = text_track_state_map_.find(stream); |
147 DCHECK(itr != text_track_state_map_.end()); | 146 DCHECK(itr != text_track_state_map_.end()); |
148 | 147 |
149 TextTrackState* state = itr->second; | 148 TextTrackState* state = itr->second.get(); |
150 DCHECK_EQ(state->read_state, TextTrackState::kReadPending); | 149 DCHECK_EQ(state->read_state, TextTrackState::kReadPending); |
151 | 150 |
152 --pending_read_count_; | 151 --pending_read_count_; |
153 state->read_state = TextTrackState::kReadIdle; | 152 state->read_state = TextTrackState::kReadIdle; |
154 | 153 |
155 switch (state_) { | 154 switch (state_) { |
156 case kPlaying: | 155 case kPlaying: |
157 return; | 156 return; |
158 | 157 |
159 case kPausePending: | 158 case kPausePending: |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 } | 206 } |
208 | 207 |
209 void TextRenderer::CueReady( | 208 void TextRenderer::CueReady( |
210 DemuxerStream* text_stream, | 209 DemuxerStream* text_stream, |
211 const scoped_refptr<TextCue>& text_cue) { | 210 const scoped_refptr<TextCue>& text_cue) { |
212 DCHECK(task_runner_->BelongsToCurrentThread()); | 211 DCHECK(task_runner_->BelongsToCurrentThread()); |
213 DCHECK_NE(state_, kUninitialized); | 212 DCHECK_NE(state_, kUninitialized); |
214 DCHECK_GT(pending_read_count_, 0); | 213 DCHECK_GT(pending_read_count_, 0); |
215 DCHECK(pending_eos_set_.find(text_stream) != pending_eos_set_.end()); | 214 DCHECK(pending_eos_set_.find(text_stream) != pending_eos_set_.end()); |
216 | 215 |
217 TextTrackStateMap::iterator itr = text_track_state_map_.find(text_stream); | 216 auto itr = text_track_state_map_.find(text_stream); |
218 DCHECK(itr != text_track_state_map_.end()); | 217 DCHECK(itr != text_track_state_map_.end()); |
219 | 218 |
220 TextTrackState* state = itr->second; | 219 TextTrackState* state = itr->second.get(); |
221 DCHECK_EQ(state->read_state, TextTrackState::kReadPending); | 220 DCHECK_EQ(state->read_state, TextTrackState::kReadPending); |
222 DCHECK(state->text_track); | 221 DCHECK(state->text_track); |
223 | 222 |
224 --pending_read_count_; | 223 --pending_read_count_; |
225 state->read_state = TextTrackState::kReadIdle; | 224 state->read_state = TextTrackState::kReadIdle; |
226 | 225 |
227 switch (state_) { | 226 switch (state_) { |
228 case kPlaying: { | 227 case kPlaying: { |
229 if (text_cue.get()) | 228 if (text_cue.get()) |
230 break; | 229 break; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 | 291 |
293 void TextRenderer::OnAddTextTrackDone(DemuxerStream* text_stream, | 292 void TextRenderer::OnAddTextTrackDone(DemuxerStream* text_stream, |
294 std::unique_ptr<TextTrack> text_track) { | 293 std::unique_ptr<TextTrack> text_track) { |
295 DCHECK(task_runner_->BelongsToCurrentThread()); | 294 DCHECK(task_runner_->BelongsToCurrentThread()); |
296 DCHECK_NE(state_, kUninitialized); | 295 DCHECK_NE(state_, kUninitialized); |
297 DCHECK(text_stream); | 296 DCHECK(text_stream); |
298 DCHECK(text_track); | 297 DCHECK(text_track); |
299 | 298 |
300 std::unique_ptr<TextTrackState> state( | 299 std::unique_ptr<TextTrackState> state( |
301 new TextTrackState(std::move(text_track))); | 300 new TextTrackState(std::move(text_track))); |
302 text_track_state_map_[text_stream] = state.release(); | 301 text_track_state_map_[text_stream] = std::move(state); |
303 pending_eos_set_.insert(text_stream); | 302 pending_eos_set_.insert(text_stream); |
304 | 303 |
305 if (state_ == kPlaying) | 304 if (state_ == kPlaying) |
306 Read(text_track_state_map_[text_stream], text_stream); | 305 Read(text_track_state_map_[text_stream].get(), text_stream); |
307 } | 306 } |
308 | 307 |
309 void TextRenderer::Read( | 308 void TextRenderer::Read( |
310 TextTrackState* state, | 309 TextTrackState* state, |
311 DemuxerStream* text_stream) { | 310 DemuxerStream* text_stream) { |
312 DCHECK_NE(state->read_state, TextTrackState::kReadPending); | 311 DCHECK_NE(state->read_state, TextTrackState::kReadPending); |
313 | 312 |
314 state->read_state = TextTrackState::kReadPending; | 313 state->read_state = TextTrackState::kReadPending; |
315 ++pending_read_count_; | 314 ++pending_read_count_; |
316 | 315 |
317 text_stream->Read(base::Bind( | 316 text_stream->Read(base::Bind( |
318 &TextRenderer::BufferReady, weak_factory_.GetWeakPtr(), text_stream)); | 317 &TextRenderer::BufferReady, weak_factory_.GetWeakPtr(), text_stream)); |
319 } | 318 } |
320 | 319 |
321 TextRenderer::TextTrackState::TextTrackState(std::unique_ptr<TextTrack> tt) | 320 TextRenderer::TextTrackState::TextTrackState(std::unique_ptr<TextTrack> tt) |
322 : read_state(kReadIdle), text_track(std::move(tt)) {} | 321 : read_state(kReadIdle), text_track(std::move(tt)) {} |
323 | 322 |
324 TextRenderer::TextTrackState::~TextTrackState() { | 323 TextRenderer::TextTrackState::~TextTrackState() { |
325 } | 324 } |
326 | 325 |
327 } // namespace media | 326 } // namespace media |
OLD | NEW |