Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(190)

Side by Side Diff: media/base/text_renderer.cc

Issue 23702007: Render inband text tracks in the media pipeline (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: incorporated more of aaron's comments Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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/base/text_renderer.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_cue.h"
14 #include "media/base/text_decoder.h"
15
16 namespace media {
17
18 TextRenderer::TextRenderer(
19 const scoped_refptr<base::MessageLoopProxy>& message_loop,
20 scoped_ptr<TextDecoder> decoder,
21 const AddTextStreamCB& add_text_stream_cb,
22 const CueReadyCB& cue_ready_cb)
23 : message_loop_(message_loop),
24 weak_factory_(this),
25 decoder_(decoder.Pass()),
26 add_text_stream_cb_(add_text_stream_cb),
27 cue_ready_cb_(cue_ready_cb),
28 state_(kUninitialized),
29 pending_read_count_(0),
30 pending_eos_count_(0) {
31 }
32
33 TextRenderer::~TextRenderer() {
34 DCHECK(state_ == kUninitialized || state_ == kStopped);
35 DCHECK_EQ(pending_read_count_, 0);
36 }
37
38 void TextRenderer::Initialize(const base::Closure& ended_cb) {
39 DCHECK(message_loop_->BelongsToCurrentThread());
40 DCHECK(!ended_cb.is_null());
41 DCHECK_EQ(kUninitialized, state_);
42 DCHECK(read_state_.empty());
43 DCHECK_EQ(pending_read_count_, 0);
44 DCHECK_EQ(pending_eos_count_, 0);
45 DCHECK(ended_cb_.is_null());
46
47 weak_this_ = weak_factory_.GetWeakPtr();
48 ended_cb_ = ended_cb;
49 state_ = kPaused;
50 decoder_->Initialize();
51 }
52
53 void TextRenderer::Play(const base::Closure& callback) {
54 DCHECK(message_loop_->BelongsToCurrentThread());
55 DCHECK(state_ == kPaused);
56
57 state_ = kPlaying;
58 callback.Run();
59
60 for (ReadStateMap::iterator itr = read_state_.begin();
61 itr != read_state_.end(); ++itr) {
62 ReadStateMap::value_type& val = *itr;
63
64 if (val.second == kReadPending) {
65 DCHECK_GT(pending_read_count_, 0);
66 continue;
67 }
68
69 val.second = kReadPending;
70 ++pending_read_count_;
71 decoder_->Read(val.first,
72 base::Bind(&TextRenderer::CueReady, weak_this_));
73 }
74 }
75
76 void TextRenderer::Pause(const base::Closure& callback) {
77 DCHECK(message_loop_->BelongsToCurrentThread());
78 DCHECK(state_ == kPlaying || state_ == kEnded);
79 pause_cb_ = callback;
80
81 if (pending_read_count_ <= 0) {
82 state_ = kPaused;
83 base::ResetAndReturn(&pause_cb_).Run();
84 return;
85 }
86
87 state_ = kPausePending;
88 }
89
90 void TextRenderer::Flush(const base::Closure& callback) {
91 DCHECK(message_loop_->BelongsToCurrentThread());
92 DCHECK_EQ(pending_read_count_, 0);
93 DCHECK(state_ == kPaused || state_ == kEnded);
94
95 pending_eos_count_ = read_state_.size();
96
97 callback.Run();
98 }
99
100 void TextRenderer::Stop(const base::Closure& cb) {
101 DCHECK(message_loop_->BelongsToCurrentThread());
102 DCHECK(!cb.is_null());
103 DCHECK(state_ == kPlaying || state_ == kPaused || state_ == kEnded);
104
105 stop_cb_ = cb;
106
107 if (pending_read_count_ <= 0) {
108 state_ = kStopped;
109 base::ResetAndReturn(&stop_cb_).Run();
110 return;
111 }
112
113 state_ = kStopPending;
114 }
115
116 void TextRenderer::AddTextStream(DemuxerStream* text_stream,
117 TextKind kind,
118 const std::string& label,
119 const std::string& language) {
120 DCHECK(message_loop_->BelongsToCurrentThread());
121 DCHECK(state_ != kUninitialized && state_ != kStopped);
122 add_text_stream_cb_.Run(text_stream, kind, label, language);
123 ++pending_eos_count_;
124
125 if (state_ != kPlaying) {
126 read_state_[text_stream] = kReadIdle;
127 } else {
128 read_state_[text_stream] = kReadPending;
129 ++pending_read_count_;
130
131 decoder_->Read(text_stream,
132 base::Bind(&TextRenderer::CueReady, weak_this_));
133 }
134 }
135
136 void TextRenderer::CueReady(
137 DemuxerStream* text_stream,
138 const scoped_refptr<TextCue>& text_cue) {
139 DCHECK(message_loop_->BelongsToCurrentThread());
140 DCHECK_NE(state_, kUninitialized);
141 DCHECK_NE(state_, kStopped);
142 DCHECK_GT(pending_read_count_, 0);
143 DCHECK_GT(pending_eos_count_, 0);
144 DCHECK_EQ(read_state_[text_stream], kReadPending);
145
146 --pending_read_count_;
147 read_state_[text_stream] = kReadIdle;
148
149 switch (state_) {
150 case kPlaying:
151 if (text_cue)
152 break;
153
154 // A NULL buffer means that we have reached EOS (or there's an error).
155
156 --pending_eos_count_;
157
158 if (pending_read_count_ > 0)
159 return;
160
161 if (pending_eos_count_ <= 0) {
162 state_ = kEnded;
163 ended_cb_.Run();
164 }
165
166 return;
167
168 case kPausePending:
169 if (pending_read_count_ <= 0) {
170 state_ = kPaused;
171 pause_cb_.Run();
172 }
173
174 return;
175
176 case kStopPending:
177 if (pending_read_count_ <= 0) {
178 state_ = kStopped;
179 stop_cb_.Run();
180 }
181
182 return;
183
184 case kPaused:
185 case kStopped:
186 case kUninitialized:
187 default:
188 NOTREACHED();
189 return;
190 }
191
192 if (!text_cue->text().empty())
193 cue_ready_cb_.Run(text_stream, text_cue);
194
195 read_state_[text_stream] = kReadPending;
196 ++pending_read_count_;
197 decoder_->Read(text_stream,
198 base::Bind(&TextRenderer::CueReady, weak_this_));
199 }
200
201 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698