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

Side by Side Diff: media/filters/decoder_base.h

Issue 149475: Replaced DCHECKs to use MessageLoop::current() for FFmpegDemuxer and DecoderBase. (Closed)
Patch Set: Created 11 years, 5 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
« no previous file with comments | « no previous file | media/filters/ffmpeg_demuxer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
2 // source code is governed by a BSD-style license that can be found in the 2 // source code is governed by a BSD-style license that can be found in the
3 // LICENSE file. 3 // LICENSE file.
4 4
5 // A base class that provides the plumbing for a decoder filters. 5 // A base class that provides the plumbing for a decoder filters.
6 6
7 #ifndef MEDIA_FILTERS_DECODER_BASE_H_ 7 #ifndef MEDIA_FILTERS_DECODER_BASE_H_
8 #define MEDIA_FILTERS_DECODER_BASE_H_ 8 #define MEDIA_FILTERS_DECODER_BASE_H_
9 9
10 #include <deque> 10 #include <deque>
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 // better yet see if we can get away with not using reference counting. 58 // better yet see if we can get away with not using reference counting.
59 scoped_refptr<Buffer> buffer_ref = buffer; 59 scoped_refptr<Buffer> buffer_ref = buffer;
60 this->message_loop()->PostTask(FROM_HERE, 60 this->message_loop()->PostTask(FROM_HERE,
61 NewRunnableMethod(this, &DecoderBase::ReadCompleteTask, buffer_ref)); 61 NewRunnableMethod(this, &DecoderBase::ReadCompleteTask, buffer_ref));
62 } 62 }
63 63
64 protected: 64 protected:
65 DecoderBase() 65 DecoderBase()
66 : pending_reads_(0), 66 : pending_reads_(0),
67 seeking_(false), 67 seeking_(false),
68 state_(UNINITIALIZED), 68 state_(UNINITIALIZED) {
69 thread_id_(NULL) {
70 } 69 }
71 70
72 virtual ~DecoderBase() { 71 virtual ~DecoderBase() {
73 DCHECK(state_ == UNINITIALIZED || state_ == STOPPED); 72 DCHECK(state_ == UNINITIALIZED || state_ == STOPPED);
74 DCHECK(result_queue_.empty()); 73 DCHECK(result_queue_.empty());
75 DCHECK(read_queue_.empty()); 74 DCHECK(read_queue_.empty());
76 } 75 }
77 76
78 // This method is called by the derived class from within the OnDecode method. 77 // This method is called by the derived class from within the OnDecode method.
79 // It places an output buffer in the result queue. It must be called from 78 // It places an output buffer in the result queue. It must be called from
80 // within the OnDecode method. 79 // within the OnDecode method.
81 void EnqueueResult(Output* output) { 80 void EnqueueResult(Output* output) {
82 DCHECK_EQ(PlatformThread::CurrentId(), thread_id_); 81 DCHECK_EQ(MessageLoop::current(), this->message_loop());
83 if (!IsStopped()) { 82 if (!IsStopped()) {
84 result_queue_.push_back(output); 83 result_queue_.push_back(output);
85 } 84 }
86 } 85 }
87 86
88 // Method that must be implemented by the derived class. Called from within 87 // Method that must be implemented by the derived class. Called from within
89 // the DecoderBase::Initialize() method before any reads are submitted to 88 // the DecoderBase::Initialize() method before any reads are submitted to
90 // the demuxer stream. Returns true if successful, otherwise false indicates 89 // the demuxer stream. Returns true if successful, otherwise false indicates
91 // a fatal error. The derived class should NOT call the filter host's 90 // a fatal error. The derived class should NOT call the filter host's
92 // InitializationComplete() method. If this method returns true, then the 91 // InitializationComplete() method. If this method returns true, then the
93 // base class will call the host to complete initialization. During this 92 // base class will call the host to complete initialization. During this
94 // call, the derived class must fill in the media_format_ member. 93 // call, the derived class must fill in the media_format_ member.
95 virtual bool OnInitialize(DemuxerStream* demuxer_stream) = 0; 94 virtual bool OnInitialize(DemuxerStream* demuxer_stream) = 0;
96 95
97 // Method that may be implemented by the derived class if desired. It will 96 // Method that may be implemented by the derived class if desired. It will
98 // be called from within the MediaFilter::Stop() method prior to stopping the 97 // be called from within the MediaFilter::Stop() method prior to stopping the
99 // base class. 98 // base class.
100 virtual void OnStop() {} 99 virtual void OnStop() {}
101 100
102 // Derived class can implement this method and perform seeking logic prior 101 // Derived class can implement this method and perform seeking logic prior
103 // to the base class. 102 // to the base class.
104 virtual void OnSeek(base::TimeDelta time) {} 103 virtual void OnSeek(base::TimeDelta time) {}
105 104
106 // Method that must be implemented by the derived class. If the decode 105 // Method that must be implemented by the derived class. If the decode
107 // operation produces one or more outputs, the derived class should call 106 // operation produces one or more outputs, the derived class should call
108 // the EnequeueResult() method from within this method. 107 // the EnequeueResult() method from within this method.
109 virtual void OnDecode(Buffer* input) = 0; 108 virtual void OnDecode(Buffer* input) = 0;
110 109
111 // Used for subclasses who friend unit tests and need to set the thread id.
112 virtual void set_thread_id(PlatformThreadId thread_id) {
113 thread_id_ = thread_id;
114 }
115
116 MediaFormat media_format_; 110 MediaFormat media_format_;
117 111
118 private: 112 private:
119 bool IsStopped() { return state_ == STOPPED; } 113 bool IsStopped() { return state_ == STOPPED; }
120 114
121 void StopTask() { 115 void StopTask() {
122 DCHECK_EQ(PlatformThread::CurrentId(), thread_id_); 116 DCHECK_EQ(MessageLoop::current(), this->message_loop());
117
123 // Delegate to the subclass first. 118 // Delegate to the subclass first.
124 OnStop(); 119 OnStop();
125 120
126 // Throw away all buffers in all queues. 121 // Throw away all buffers in all queues.
127 result_queue_.clear(); 122 result_queue_.clear();
128 STLDeleteElements(&read_queue_); 123 STLDeleteElements(&read_queue_);
129 state_ = STOPPED; 124 state_ = STOPPED;
130 } 125 }
131 126
132 void SeekTask(base::TimeDelta time) { 127 void SeekTask(base::TimeDelta time) {
133 DCHECK_EQ(PlatformThread::CurrentId(), thread_id_); 128 DCHECK_EQ(MessageLoop::current(), this->message_loop());
129
134 // Delegate to the subclass first. 130 // Delegate to the subclass first.
135 OnSeek(time); 131 OnSeek(time);
136 132
137 // Flush the result queue. 133 // Flush the result queue.
138 result_queue_.clear(); 134 result_queue_.clear();
139 135
140 // Turn on the seeking flag so that we can discard buffers until a 136 // Turn on the seeking flag so that we can discard buffers until a
141 // discontinuous buffer is received. 137 // discontinuous buffer is received.
142 seeking_ = true; 138 seeking_ = true;
143 } 139 }
144 140
145 void InitializeTask(DemuxerStream* demuxer_stream) { 141 void InitializeTask(DemuxerStream* demuxer_stream) {
142 DCHECK_EQ(MessageLoop::current(), this->message_loop());
146 DCHECK(state_ == UNINITIALIZED); 143 DCHECK(state_ == UNINITIALIZED);
147 DCHECK(!demuxer_stream_); 144 DCHECK(!demuxer_stream_);
148 DCHECK(!thread_id_ || thread_id_ == PlatformThread::CurrentId());
149 demuxer_stream_ = demuxer_stream; 145 demuxer_stream_ = demuxer_stream;
150 146
151 // Grab the thread id for debugging.
152 thread_id_ = PlatformThread::CurrentId();
153
154 // Delegate to subclass first. 147 // Delegate to subclass first.
155 if (!OnInitialize(demuxer_stream_)) { 148 if (!OnInitialize(demuxer_stream_)) {
156 this->host()->Error(PIPELINE_ERROR_DECODE); 149 this->host()->Error(PIPELINE_ERROR_DECODE);
157 return; 150 return;
158 } 151 }
159 152
160 // TODO(scherkus): subclass shouldn't mutate superclass media format. 153 // TODO(scherkus): subclass shouldn't mutate superclass media format.
161 DCHECK(!media_format_.empty()) << "Subclass did not set media_format_"; 154 DCHECK(!media_format_.empty()) << "Subclass did not set media_format_";
162 state_ = INITIALIZED; 155 state_ = INITIALIZED;
163 this->host()->InitializationComplete(); 156 this->host()->InitializationComplete();
164 } 157 }
165 158
166 void ReadTask(ReadCallback* read_callback) { 159 void ReadTask(ReadCallback* read_callback) {
167 DCHECK_EQ(PlatformThread::CurrentId(), thread_id_); 160 DCHECK_EQ(MessageLoop::current(), this->message_loop());
161
168 // TODO(scherkus): should reply with a null operation (empty buffer). 162 // TODO(scherkus): should reply with a null operation (empty buffer).
169 if (IsStopped()) { 163 if (IsStopped()) {
170 delete read_callback; 164 delete read_callback;
171 return; 165 return;
172 } 166 }
173 167
174 // Enqueue the callback and attempt to fulfill it immediately. 168 // Enqueue the callback and attempt to fulfill it immediately.
175 read_queue_.push_back(read_callback); 169 read_queue_.push_back(read_callback);
176 FulfillPendingRead(); 170 FulfillPendingRead();
177 171
178 // Issue reads as necessary. 172 // Issue reads as necessary.
179 while (pending_reads_ < read_queue_.size()) { 173 while (pending_reads_ < read_queue_.size()) {
180 demuxer_stream_->Read(NewCallback(this, &DecoderBase::OnReadComplete)); 174 demuxer_stream_->Read(NewCallback(this, &DecoderBase::OnReadComplete));
181 ++pending_reads_; 175 ++pending_reads_;
182 } 176 }
183 } 177 }
184 178
185 void ReadCompleteTask(scoped_refptr<Buffer> buffer) { 179 void ReadCompleteTask(scoped_refptr<Buffer> buffer) {
186 DCHECK_EQ(PlatformThread::CurrentId(), thread_id_); 180 DCHECK_EQ(MessageLoop::current(), this->message_loop());
187 DCHECK_GT(pending_reads_, 0u); 181 DCHECK_GT(pending_reads_, 0u);
188 --pending_reads_; 182 --pending_reads_;
189 if (IsStopped()) { 183 if (IsStopped()) {
190 return; 184 return;
191 } 185 }
192 186
193 // Once the |seeking_| flag is set we ignore every buffers here 187 // Once the |seeking_| flag is set we ignore every buffers here
194 // until we receive a discontinuous buffer and we will turn off the 188 // until we receive a discontinuous buffer and we will turn off the
195 // |seeking_| flag. 189 // |seeking_| flag.
196 if (buffer->IsDiscontinuous()) { 190 if (buffer->IsDiscontinuous()) {
(...skipping 22 matching lines...) Expand all
219 DCHECK_LE(pending_reads_, read_queue_.size()); 213 DCHECK_LE(pending_reads_, read_queue_.size());
220 while (pending_reads_ < read_queue_.size()) { 214 while (pending_reads_ < read_queue_.size()) {
221 demuxer_stream_->Read(NewCallback(this, &DecoderBase::OnReadComplete)); 215 demuxer_stream_->Read(NewCallback(this, &DecoderBase::OnReadComplete));
222 ++pending_reads_; 216 ++pending_reads_;
223 } 217 }
224 } 218 }
225 219
226 // Attempts to fulfill a single pending read by dequeuing a buffer and read 220 // Attempts to fulfill a single pending read by dequeuing a buffer and read
227 // callback pair and executing the callback. 221 // callback pair and executing the callback.
228 void FulfillPendingRead() { 222 void FulfillPendingRead() {
229 DCHECK_EQ(PlatformThread::CurrentId(), thread_id_); 223 DCHECK_EQ(MessageLoop::current(), this->message_loop());
230 if (read_queue_.empty() || result_queue_.empty()) { 224 if (read_queue_.empty() || result_queue_.empty()) {
231 return; 225 return;
232 } 226 }
233 227
234 // Dequeue a frame and read callback pair. 228 // Dequeue a frame and read callback pair.
235 scoped_refptr<Output> output = result_queue_.front(); 229 scoped_refptr<Output> output = result_queue_.front();
236 scoped_ptr<ReadCallback> read_callback(read_queue_.front()); 230 scoped_ptr<ReadCallback> read_callback(read_queue_.front());
237 result_queue_.pop_front(); 231 result_queue_.pop_front();
238 read_queue_.pop_front(); 232 read_queue_.pop_front();
239 233
(...skipping 29 matching lines...) Expand all
269 ReadQueue read_queue_; 263 ReadQueue read_queue_;
270 264
271 // Simple state tracking variable. 265 // Simple state tracking variable.
272 enum State { 266 enum State {
273 UNINITIALIZED, 267 UNINITIALIZED,
274 INITIALIZED, 268 INITIALIZED,
275 STOPPED, 269 STOPPED,
276 }; 270 };
277 State state_; 271 State state_;
278 272
279 // Used for debugging.
280 PlatformThreadId thread_id_;
281
282 DISALLOW_COPY_AND_ASSIGN(DecoderBase); 273 DISALLOW_COPY_AND_ASSIGN(DecoderBase);
283 }; 274 };
284 275
285 } // namespace media 276 } // namespace media
286 277
287 #endif // MEDIA_FILTERS_DECODER_BASE_H_ 278 #endif // MEDIA_FILTERS_DECODER_BASE_H_
OLDNEW
« no previous file with comments | « no previous file | media/filters/ffmpeg_demuxer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698