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