OLD | NEW |
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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 DCHECK(state_ == UNINITIALIZED || state_ == STOPPED); | 73 DCHECK(state_ == UNINITIALIZED || state_ == STOPPED); |
74 DCHECK(result_queue_.empty()); | 74 DCHECK(result_queue_.empty()); |
75 DCHECK(read_queue_.empty()); | 75 DCHECK(read_queue_.empty()); |
76 } | 76 } |
77 | 77 |
78 // This method is called by the derived class from within the OnDecode method. | 78 // 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 | 79 // It places an output buffer in the result queue. It must be called from |
80 // within the OnDecode method. | 80 // within the OnDecode method. |
81 void EnqueueResult(Output* output) { | 81 void EnqueueResult(Output* output) { |
82 DCHECK_EQ(PlatformThread::CurrentId(), thread_id_); | 82 DCHECK_EQ(PlatformThread::CurrentId(), thread_id_); |
83 if (!stopped_) { | 83 if (!IsStopped()) { |
84 result_queue_.push_back(output); | 84 result_queue_.push_back(output); |
85 } | 85 } |
86 } | 86 } |
87 | 87 |
88 // Method that must be implemented by the derived class. Called from within | 88 // Method that must be implemented by the derived class. Called from within |
89 // the DecoderBase::Initialize() method before any reads are submitted to | 89 // the DecoderBase::Initialize() method before any reads are submitted to |
90 // the demuxer stream. Returns true if successful, otherwise false indicates | 90 // the demuxer stream. Returns true if successful, otherwise false indicates |
91 // a fatal error. The derived class should NOT call the filter host's | 91 // a fatal error. The derived class should NOT call the filter host's |
92 // InitializationComplete() method. If this method returns true, then the | 92 // InitializationComplete() method. If this method returns true, then the |
93 // base class will call the host to complete initialization. During this | 93 // base class will call the host to complete initialization. During this |
(...skipping 21 matching lines...) Expand all Loading... |
115 | 115 |
116 MediaFormat media_format_; | 116 MediaFormat media_format_; |
117 | 117 |
118 private: | 118 private: |
119 // GCC doesn't let us access superclass member variables directly, so use | 119 // GCC doesn't let us access superclass member variables directly, so use |
120 // a helper to get around the situation. | 120 // a helper to get around the situation. |
121 // | 121 // |
122 // TODO(scherkus): another reason to add protected accessors to MediaFilter. | 122 // TODO(scherkus): another reason to add protected accessors to MediaFilter. |
123 FilterHost* host() const { return Decoder::host_; } | 123 FilterHost* host() const { return Decoder::host_; } |
124 MessageLoop* message_loop() const { return Decoder::message_loop_; } | 124 MessageLoop* message_loop() const { return Decoder::message_loop_; } |
| 125 bool IsStopped() { return state_ == STOPPED; } |
125 | 126 |
126 void StopTask() { | 127 void StopTask() { |
127 DCHECK_EQ(PlatformThread::CurrentId(), thread_id_); | 128 DCHECK_EQ(PlatformThread::CurrentId(), thread_id_); |
128 // Delegate to the subclass first. | 129 // Delegate to the subclass first. |
129 OnStop(); | 130 OnStop(); |
130 | 131 |
131 // Throw away all buffers in all queues. | 132 // Throw away all buffers in all queues. |
132 result_queue_.clear(); | 133 result_queue_.clear(); |
133 STLDeleteElements(&read_queue_); | 134 STLDeleteElements(&read_queue_); |
134 state_ = STOPPED; | 135 state_ = STOPPED; |
(...skipping 29 matching lines...) Expand all Loading... |
164 | 165 |
165 // TODO(scherkus): subclass shouldn't mutate superclass media format. | 166 // TODO(scherkus): subclass shouldn't mutate superclass media format. |
166 DCHECK(!media_format_.empty()) << "Subclass did not set media_format_"; | 167 DCHECK(!media_format_.empty()) << "Subclass did not set media_format_"; |
167 state_ = INITIALIZED; | 168 state_ = INITIALIZED; |
168 host()->InitializationComplete(); | 169 host()->InitializationComplete(); |
169 } | 170 } |
170 | 171 |
171 void ReadTask(ReadCallback* read_callback) { | 172 void ReadTask(ReadCallback* read_callback) { |
172 DCHECK_EQ(PlatformThread::CurrentId(), thread_id_); | 173 DCHECK_EQ(PlatformThread::CurrentId(), thread_id_); |
173 // TODO(scherkus): should reply with a null operation (empty buffer). | 174 // TODO(scherkus): should reply with a null operation (empty buffer). |
174 if (stopped_) { | 175 if (IsStopped()) { |
175 delete read_callback; | 176 delete read_callback; |
176 return; | 177 return; |
177 } | 178 } |
178 | 179 |
179 // Enqueue the callback and attempt to fulfill it immediately. | 180 // Enqueue the callback and attempt to fulfill it immediately. |
180 read_queue_.push_back(read_callback); | 181 read_queue_.push_back(read_callback); |
181 FulfillPendingRead(); | 182 FulfillPendingRead(); |
182 | 183 |
183 // Issue reads as necessary. | 184 // Issue reads as necessary. |
184 while (pending_reads_ < read_queue_.size()) { | 185 while (pending_reads_ < read_queue_.size()) { |
185 demuxer_stream_->Read(NewCallback(this, &DecoderBase::OnReadComplete)); | 186 demuxer_stream_->Read(NewCallback(this, &DecoderBase::OnReadComplete)); |
186 ++pending_reads_; | 187 ++pending_reads_; |
187 } | 188 } |
188 } | 189 } |
189 | 190 |
190 void ReadCompleteTask(scoped_refptr<Buffer> buffer) { | 191 void ReadCompleteTask(scoped_refptr<Buffer> buffer) { |
191 DCHECK_EQ(PlatformThread::CurrentId(), thread_id_); | 192 DCHECK_EQ(PlatformThread::CurrentId(), thread_id_); |
192 DCHECK_GT(pending_reads_, 0u); | 193 DCHECK_GT(pending_reads_, 0u); |
193 --pending_reads_; | 194 --pending_reads_; |
194 if (stopped_) { | 195 if (IsStopped()) { |
195 return; | 196 return; |
196 } | 197 } |
197 | 198 |
198 // Once the |seeking_| flag is set we ignore every buffers here | 199 // Once the |seeking_| flag is set we ignore every buffers here |
199 // until we receive a discontinuous buffer and we will turn off the | 200 // until we receive a discontinuous buffer and we will turn off the |
200 // |seeking_| flag. | 201 // |seeking_| flag. |
201 if (buffer->IsDiscontinuous()) { | 202 if (buffer->IsDiscontinuous()) { |
202 // TODO(hclam): put a DCHECK here to assert |seeking_| being true. | 203 // TODO(hclam): put a DCHECK here to assert |seeking_| being true. |
203 // I cannot do this now because seek operation is not fully | 204 // I cannot do this now because seek operation is not fully |
204 // asynchronous. There may be pending seek requests even before the | 205 // asynchronous. There may be pending seek requests even before the |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 read_queue_.pop_front(); | 244 read_queue_.pop_front(); |
244 | 245 |
245 // Execute the callback! | 246 // Execute the callback! |
246 read_callback->Run(output); | 247 read_callback->Run(output); |
247 } | 248 } |
248 | 249 |
249 // Tracks the number of asynchronous reads issued to |demuxer_stream_|. | 250 // Tracks the number of asynchronous reads issued to |demuxer_stream_|. |
250 // Using size_t since it is always compared against deque::size(). | 251 // Using size_t since it is always compared against deque::size(). |
251 size_t pending_reads_; | 252 size_t pending_reads_; |
252 | 253 |
253 // If true, then Stop() has been called and no further processing of buffers | |
254 // should occur. | |
255 bool stopped_; | |
256 | |
257 // An internal state of the decoder that indicates that are waiting for seek | 254 // An internal state of the decoder that indicates that are waiting for seek |
258 // to complete. We expect to receive a discontinuous frame/packet from the | 255 // to complete. We expect to receive a discontinuous frame/packet from the |
259 // demuxer to signal that seeking is completed. | 256 // demuxer to signal that seeking is completed. |
260 bool seeking_; | 257 bool seeking_; |
261 | 258 |
262 // Pointer to the demuxer stream that will feed us compressed buffers. | 259 // Pointer to the demuxer stream that will feed us compressed buffers. |
263 scoped_refptr<DemuxerStream> demuxer_stream_; | 260 scoped_refptr<DemuxerStream> demuxer_stream_; |
264 | 261 |
265 // Queue of decoded samples produced in the OnDecode() method of the decoder. | 262 // Queue of decoded samples produced in the OnDecode() method of the decoder. |
266 // Any samples placed in this queue will be assigned to the OutputQueue | 263 // Any samples placed in this queue will be assigned to the OutputQueue |
(...skipping 20 matching lines...) Expand all Loading... |
287 | 284 |
288 // Used for debugging. | 285 // Used for debugging. |
289 PlatformThreadId thread_id_; | 286 PlatformThreadId thread_id_; |
290 | 287 |
291 DISALLOW_COPY_AND_ASSIGN(DecoderBase); | 288 DISALLOW_COPY_AND_ASSIGN(DecoderBase); |
292 }; | 289 }; |
293 | 290 |
294 } // namespace media | 291 } // namespace media |
295 | 292 |
296 #endif // MEDIA_FILTERS_DECODER_BASE_H_ | 293 #endif // MEDIA_FILTERS_DECODER_BASE_H_ |
OLD | NEW |