| 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 |