Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/filters/decrypting_video_decoder.h" | 5 #include "media/filters/decrypting_audio_decoder.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
| 9 #include "base/location.h" | 9 #include "base/location.h" |
| 10 #include "base/message_loop_proxy.h" | 10 #include "base/message_loop_proxy.h" |
| 11 #include "media/base/audio_decoder_config.h" | |
| 11 #include "media/base/bind_to_loop.h" | 12 #include "media/base/bind_to_loop.h" |
| 13 #include "media/base/buffers.h" | |
| 14 #include "media/base/data_buffer.h" | |
| 12 #include "media/base/decoder_buffer.h" | 15 #include "media/base/decoder_buffer.h" |
| 13 #include "media/base/decryptor.h" | 16 #include "media/base/decryptor.h" |
| 14 #include "media/base/demuxer_stream.h" | 17 #include "media/base/demuxer_stream.h" |
| 15 #include "media/base/pipeline.h" | 18 #include "media/base/pipeline.h" |
| 16 #include "media/base/video_decoder_config.h" | |
| 17 #include "media/base/video_frame.h" | |
| 18 | 19 |
| 19 namespace media { | 20 namespace media { |
| 20 | 21 |
| 21 #define BIND_TO_LOOP(function) \ | 22 #define BIND_TO_LOOP(function) \ |
| 22 media::BindToLoop(message_loop_, base::Bind(function, this)) | 23 media::BindToLoop(message_loop_, base::Bind(function, this)) |
| 23 | 24 |
| 24 DecryptingVideoDecoder::DecryptingVideoDecoder( | 25 DecryptingAudioDecoder::DecryptingAudioDecoder( |
| 25 const MessageLoopFactoryCB& message_loop_factory_cb, | 26 const MessageLoopFactoryCB& message_loop_factory_cb, |
| 26 const RequestDecryptorNotificationCB& request_decryptor_notification_cb) | 27 const RequestDecryptorNotificationCB& request_decryptor_notification_cb) |
| 27 : message_loop_factory_cb_(message_loop_factory_cb), | 28 : message_loop_factory_cb_(message_loop_factory_cb), |
| 28 state_(kUninitialized), | 29 state_(kUninitialized), |
| 29 request_decryptor_notification_cb_(request_decryptor_notification_cb), | 30 request_decryptor_notification_cb_(request_decryptor_notification_cb), |
| 30 decryptor_(NULL), | 31 decryptor_(NULL), |
| 31 key_added_while_pending_decode_(false) { | 32 key_added_while_pending_decode_(false) { |
| 32 } | 33 } |
| 33 | 34 |
| 34 void DecryptingVideoDecoder::Initialize( | 35 void DecryptingAudioDecoder::Initialize( |
| 35 const scoped_refptr<DemuxerStream>& stream, | 36 const scoped_refptr<DemuxerStream>& stream, |
| 36 const PipelineStatusCB& status_cb, | 37 const PipelineStatusCB& status_cb, |
| 37 const StatisticsCB& statistics_cb) { | 38 const StatisticsCB& statistics_cb) { |
| 38 DCHECK(!message_loop_); | 39 DCHECK(!message_loop_); |
| 39 message_loop_ = base::ResetAndReturn(&message_loop_factory_cb_).Run(); | 40 message_loop_ = base::ResetAndReturn(&message_loop_factory_cb_).Run(); |
| 40 message_loop_->PostTask(FROM_HERE, base::Bind( | 41 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 41 &DecryptingVideoDecoder::DoInitialize, this, | 42 &DecryptingAudioDecoder::DoInitialize, this, |
| 42 stream, status_cb, statistics_cb)); | 43 stream, status_cb, statistics_cb)); |
| 43 } | 44 } |
| 44 | 45 |
| 45 void DecryptingVideoDecoder::Read(const ReadCB& read_cb) { | 46 void DecryptingAudioDecoder::Read(const ReadCB& read_cb) { |
| 46 // Complete operation asynchronously on different stack of execution as per | 47 // Complete operation asynchronously on different stack of execution as per |
| 47 // the API contract of VideoDecoder::Read() | 48 // the API contract of AudioDecoder::Read() |
| 48 message_loop_->PostTask(FROM_HERE, base::Bind( | 49 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 49 &DecryptingVideoDecoder::DoRead, this, read_cb)); | 50 &DecryptingAudioDecoder::DoRead, this, read_cb)); |
| 50 } | 51 } |
| 51 | 52 |
| 52 void DecryptingVideoDecoder::Reset(const base::Closure& closure) { | 53 void DecryptingAudioDecoder::Reset(const base::Closure& closure) { |
| 53 if (!message_loop_->BelongsToCurrentThread()) { | 54 if (!message_loop_->BelongsToCurrentThread()) { |
| 54 message_loop_->PostTask(FROM_HERE, base::Bind( | 55 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 55 &DecryptingVideoDecoder::Reset, this, closure)); | 56 &DecryptingAudioDecoder::Reset, this, closure)); |
| 56 return; | 57 return; |
| 57 } | 58 } |
| 58 | 59 |
| 59 DVLOG(2) << "Reset() - state: " << state_; | 60 DVLOG(2) << "Reset() - state: " << state_; |
| 60 DCHECK(state_ == kIdle || | 61 DCHECK(state_ == kIdle || |
| 61 state_ == kPendingDemuxerRead || | 62 state_ == kPendingDemuxerRead || |
| 62 state_ == kPendingDecode || | 63 state_ == kPendingDecode || |
| 63 state_ == kWaitingForKey || | 64 state_ == kWaitingForKey || |
| 64 state_ == kDecodeFinished) << state_; | 65 state_ == kDecodeFinished) << state_; |
| 65 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. | 66 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. |
| 66 DCHECK(stop_cb_.is_null()); // No Reset() during pending Stop(). | 67 DCHECK(stop_cb_.is_null()); // No Reset() during pending Stop(). |
| 67 DCHECK(reset_cb_.is_null()); | 68 DCHECK(reset_cb_.is_null()); |
| 68 | 69 |
| 69 reset_cb_ = closure; | 70 reset_cb_ = closure; |
| 70 | 71 |
| 71 decryptor_->ResetDecoder(Decryptor::kVideo); | 72 decryptor_->ResetDecoder(Decryptor::kAudio); |
| 72 | 73 |
| 73 // Reset() cannot complete if the read callback is still pending. | 74 // Reset() cannot complete if the read callback is still pending. |
| 74 // Defer the resetting process in this case. The |reset_cb_| will be fired | 75 // Defer the resetting process in this case. The |reset_cb_| will be fired |
| 75 // after the read callback is fired - see DoDecryptAndDecodeBuffer() and | 76 // after the read callback is fired - see DoDecryptAndDecodeBuffer() and |
| 76 // DoDeliverFrame(). | 77 // DoDeliverFrame(). |
| 77 if (state_ == kPendingDemuxerRead || state_ == kPendingDecode) { | 78 if (state_ == kPendingDemuxerRead || state_ == kPendingDecode) { |
| 78 DCHECK(!read_cb_.is_null()); | 79 DCHECK(!read_cb_.is_null()); |
| 79 return; | 80 return; |
| 80 } | 81 } |
| 81 | 82 |
| 82 if (state_ == kWaitingForKey) { | 83 if (state_ == kWaitingForKey) { |
| 83 DCHECK(!read_cb_.is_null()); | 84 DCHECK(!read_cb_.is_null()); |
| 84 pending_buffer_to_decode_ = NULL; | 85 pending_buffer_to_decode_ = NULL; |
| 85 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 86 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
| 86 } | 87 } |
| 87 | 88 |
| 88 DCHECK(read_cb_.is_null()); | 89 DCHECK(read_cb_.is_null()); |
| 89 DoReset(); | 90 DoReset(); |
| 90 } | 91 } |
| 91 | 92 |
| 92 void DecryptingVideoDecoder::Stop(const base::Closure& closure) { | 93 int DecryptingAudioDecoder::bits_per_channel() { |
| 94 return bits_per_channel_; | |
| 95 } | |
| 96 | |
| 97 ChannelLayout DecryptingAudioDecoder::channel_layout() { | |
| 98 return channel_layout_; | |
| 99 } | |
| 100 | |
| 101 int DecryptingAudioDecoder::samples_per_second() { | |
| 102 return samples_per_second_; | |
| 103 } | |
| 104 | |
| 105 void DecryptingAudioDecoder::Stop(const base::Closure& closure) { | |
|
xhwang
2012/10/18 02:14:10
If we decided to have Stop(), this needs to be cha
| |
| 93 if (!message_loop_->BelongsToCurrentThread()) { | 106 if (!message_loop_->BelongsToCurrentThread()) { |
| 94 message_loop_->PostTask(FROM_HERE, base::Bind( | 107 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 95 &DecryptingVideoDecoder::Stop, this, closure)); | 108 &DecryptingAudioDecoder::Stop, this, closure)); |
| 96 return; | 109 return; |
| 97 } | 110 } |
| 98 | 111 |
| 99 DVLOG(2) << "Stop() - state: " << state_; | 112 DVLOG(2) << "Stop() - state: " << state_; |
| 100 DCHECK(stop_cb_.is_null()); | 113 DCHECK(stop_cb_.is_null()); |
| 101 stop_cb_ = closure; | 114 stop_cb_ = closure; |
| 102 | 115 |
| 103 // We need to call Decryptor::DeinitializeDecoder(Decryptor::kVideo) if we | 116 // We need to call Decryptor::DeinitializeDecoder(Decryptor::kAudio) if we |
| 104 // ever called Decryptor::InitializeVideoDecoder() to cancel the pending | 117 // ever called Decryptor::InitializeAudioDecoder() to cancel the pending |
| 105 // initialization if the initialization is still pending, or to stop the video | 118 // initialization if the initialization is still pending, or to stop the |
| 106 // decoder if the initialization has completed. | 119 // audio decoder if the initialization has completed. |
| 107 // When the state is kUninitialized and kDecryptorRequested, | 120 // When the state is kUninitialized and kDecryptorRequested, |
| 108 // InitializeVideoDecoder() has not been called, so we are okay. | 121 // InitializeAudioDecoder() has not been called, so we are okay. |
| 109 // When the state is kStopped, the video decoder should have already been | 122 // When the state is kStopped, the audio decoder should have already been |
| 110 // stopped, so no need to call DeinitializeDecoder(Decryptor::kVideo) either. | 123 // stopped, so no need to call DeinitializeDecoder(Decryptor::kAudio) either. |
| 111 // In all other cases, we need to call DeinitializeDecoder(Decryptor::kVideo)! | 124 // In all other cases, we need to call DeinitializeDecoder(Decryptor::kAudio)! |
| 112 switch (state_) { | 125 switch (state_) { |
| 113 case kUninitialized: | 126 case kUninitialized: |
| 114 case kStopped: | 127 case kStopped: |
| 115 DoStop(); | 128 DoStop(); |
| 116 break; | 129 break; |
| 117 case kDecryptorRequested: | 130 case kDecryptorRequested: |
| 118 // Stop() cannot complete if the decryptor request is still pending. | 131 // Stop() cannot complete if the decryptor request is still pending. |
| 119 // Defer the stopping process in this case. The |stop_cb_| will be fired | 132 // Defer the stopping process in this case. The |stop_cb_| will be fired |
| 120 // after the request decryptor callback is fired - see SetDecryptor(). | 133 // after the request decryptor callback is fired - see SetDecryptor(). |
| 121 request_decryptor_notification_cb_.Run(DecryptorNotificationCB()); | 134 request_decryptor_notification_cb_.Run(DecryptorNotificationCB()); |
| 122 break; | 135 break; |
| 123 case kIdle: | 136 case kIdle: |
| 124 case kDecodeFinished: | 137 case kDecodeFinished: |
| 125 decryptor_->DeinitializeDecoder(Decryptor::kVideo); | 138 decryptor_->DeinitializeDecoder(Decryptor::kAudio); |
| 126 DoStop(); | 139 DoStop(); |
| 127 break; | 140 break; |
| 128 case kWaitingForKey: | 141 case kWaitingForKey: |
| 129 decryptor_->DeinitializeDecoder(Decryptor::kVideo); | 142 decryptor_->DeinitializeDecoder(Decryptor::kAudio); |
| 130 DCHECK(!read_cb_.is_null()); | 143 DCHECK(!read_cb_.is_null()); |
| 131 pending_buffer_to_decode_ = NULL; | 144 pending_buffer_to_decode_ = NULL; |
| 132 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 145 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
| 133 DoStop(); | 146 DoStop(); |
| 134 break; | 147 break; |
| 135 case kPendingDecoderInit: | 148 case kPendingDecoderInit: |
| 136 case kPendingDemuxerRead: | 149 case kPendingDemuxerRead: |
| 137 case kPendingDecode: | 150 case kPendingDecode: |
| 138 // Stop() cannot complete if the init or read callback is still pending. | 151 // Stop() cannot complete if the init or read callback is still pending. |
| 139 // Defer the stopping process in these cases. The |stop_cb_| will be | 152 // Defer the stopping process in these cases. The |stop_cb_| will be |
| 140 // fired after the init or read callback is fired - see | 153 // fired after the init or read callback is fired - see |
| 141 // FinishInitialization(), DoDecryptAndDecodeBuffer() and | 154 // FinishInitialization(), DoDecryptAndDecodeBuffer() and |
| 142 // DoDeliverFrame(), respectively. | 155 // DoDeliverFrame(), respectively. |
| 143 decryptor_->DeinitializeDecoder(Decryptor::kVideo); | 156 decryptor_->DeinitializeDecoder(Decryptor::kAudio); |
| 144 DCHECK(!init_cb_.is_null() || !read_cb_.is_null()); | 157 DCHECK(!init_cb_.is_null() || !read_cb_.is_null()); |
| 145 break; | 158 break; |
| 146 default: | 159 default: |
| 147 NOTREACHED(); | 160 NOTREACHED(); |
| 148 } | 161 } |
| 149 } | 162 } |
| 150 | 163 |
| 151 DecryptingVideoDecoder::~DecryptingVideoDecoder() { | 164 DecryptingAudioDecoder::~DecryptingAudioDecoder() { |
| 152 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_; | 165 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_; |
| 153 } | 166 } |
| 154 | 167 |
| 155 void DecryptingVideoDecoder::DoInitialize( | 168 void DecryptingAudioDecoder::DoInitialize( |
| 156 const scoped_refptr<DemuxerStream>& stream, | 169 const scoped_refptr<DemuxerStream>& stream, |
| 157 const PipelineStatusCB& status_cb, | 170 const PipelineStatusCB& status_cb, |
| 158 const StatisticsCB& statistics_cb) { | 171 const StatisticsCB& statistics_cb) { |
| 159 DVLOG(2) << "DoInitialize()"; | |
| 160 DCHECK(message_loop_->BelongsToCurrentThread()); | 172 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 161 DCHECK_EQ(state_, kUninitialized) << state_; | 173 DCHECK_EQ(state_, kUninitialized) << state_; |
| 162 DCHECK(stream); | 174 DCHECK(stream); |
| 163 | 175 |
| 164 const VideoDecoderConfig& config = stream->video_decoder_config(); | 176 const AudioDecoderConfig& config = stream->audio_decoder_config(); |
| 165 if (!config.IsValidConfig()) { | 177 if (!config.IsValidConfig()) { |
| 166 DLOG(ERROR) << "Invalid video stream config: " | 178 DLOG(ERROR) << "Invalid audio stream config."; |
| 167 << config.AsHumanReadableString(); | |
| 168 status_cb.Run(PIPELINE_ERROR_DECODE); | 179 status_cb.Run(PIPELINE_ERROR_DECODE); |
| 169 return; | 180 return; |
| 170 } | 181 } |
| 171 | 182 |
| 172 // DecryptingVideoDecoder only accepts potentially encrypted stream. | 183 // DecryptingAudioDecoder only accepts potentially encrypted stream. |
| 173 if (!config.is_encrypted()) { | 184 if (!config.is_encrypted()) { |
| 174 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); | 185 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); |
| 175 return; | 186 return; |
| 176 } | 187 } |
| 177 | 188 |
| 178 DCHECK(!demuxer_stream_); | 189 DCHECK(!demuxer_stream_); |
| 179 demuxer_stream_ = stream; | 190 demuxer_stream_ = stream; |
| 180 statistics_cb_ = statistics_cb; | 191 statistics_cb_ = statistics_cb; |
| 181 | 192 |
| 182 init_cb_ = status_cb; | 193 init_cb_ = status_cb; |
| 183 | 194 |
| 184 state_ = kDecryptorRequested; | 195 state_ = kDecryptorRequested; |
| 185 request_decryptor_notification_cb_.Run( | 196 request_decryptor_notification_cb_.Run( |
| 186 BIND_TO_LOOP(&DecryptingVideoDecoder::SetDecryptor)); | 197 BIND_TO_LOOP(&DecryptingAudioDecoder::SetDecryptor)); |
| 187 } | 198 } |
| 188 | 199 |
| 189 void DecryptingVideoDecoder::SetDecryptor(Decryptor* decryptor) { | 200 void DecryptingAudioDecoder::SetDecryptor(Decryptor* decryptor) { |
| 190 DVLOG(2) << "SetDecryptor()"; | 201 DVLOG(2) << "SetDecryptor()"; |
| 191 DCHECK(message_loop_->BelongsToCurrentThread()); | 202 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 192 DCHECK_EQ(state_, kDecryptorRequested) << state_; | 203 DCHECK_EQ(state_, kDecryptorRequested) << state_; |
| 193 DCHECK(!init_cb_.is_null()); | 204 DCHECK(!init_cb_.is_null()); |
| 194 | 205 |
| 195 if (!stop_cb_.is_null()) { | 206 if (!stop_cb_.is_null()) { |
| 196 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 207 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
| 197 DoStop(); | 208 DoStop(); |
| 198 return; | 209 return; |
| 199 } | 210 } |
| 200 | 211 |
| 201 decryptor_ = decryptor; | 212 decryptor_ = decryptor; |
| 202 | 213 |
| 203 scoped_ptr<VideoDecoderConfig> scoped_config(new VideoDecoderConfig()); | 214 scoped_ptr<AudioDecoderConfig> scoped_config(new AudioDecoderConfig()); |
| 204 scoped_config->CopyFrom(demuxer_stream_->video_decoder_config()); | 215 scoped_config->CopyFrom(demuxer_stream_->audio_decoder_config()); |
| 205 | 216 |
| 206 state_ = kPendingDecoderInit; | 217 state_ = kPendingDecoderInit; |
| 207 decryptor_->InitializeVideoDecoder( | 218 decryptor_->InitializeAudioDecoder( |
| 208 scoped_config.Pass(), | 219 scoped_config.Pass(), |
| 209 BIND_TO_LOOP(&DecryptingVideoDecoder::FinishInitialization), | 220 BIND_TO_LOOP(&DecryptingAudioDecoder::FinishInitialization), |
| 210 BIND_TO_LOOP(&DecryptingVideoDecoder::OnKeyAdded)); | 221 BIND_TO_LOOP(&DecryptingAudioDecoder::OnKeyAdded)); |
| 211 } | 222 } |
| 212 | 223 |
| 213 void DecryptingVideoDecoder::FinishInitialization(bool success) { | 224 void DecryptingAudioDecoder::FinishInitialization(bool success) { |
| 214 DVLOG(2) << "FinishInitialization()"; | |
| 215 DCHECK(message_loop_->BelongsToCurrentThread()); | 225 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 216 DCHECK_EQ(state_, kPendingDecoderInit) << state_; | 226 DCHECK_EQ(state_, kPendingDecoderInit) << state_; |
| 217 DCHECK(!init_cb_.is_null()); | 227 DCHECK(!init_cb_.is_null()); |
| 218 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. | 228 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. |
| 219 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. | 229 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. |
| 220 | 230 |
| 221 if (!stop_cb_.is_null()) { | 231 if (!stop_cb_.is_null()) { |
| 222 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 232 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
| 223 DoStop(); | 233 DoStop(); |
| 224 return; | 234 return; |
| 225 } | 235 } |
| 226 | 236 |
| 227 if (!success) { | 237 if (!success) { |
| 228 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 238 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
| 229 state_ = kStopped; | 239 state_ = kStopped; |
| 230 return; | 240 return; |
| 231 } | 241 } |
| 232 | 242 |
| 233 // Success! | 243 // Success! |
| 244 const AudioDecoderConfig& config = demuxer_stream_->audio_decoder_config(); | |
| 245 bits_per_channel_ = config.bits_per_channel(); | |
| 246 channel_layout_ = config.channel_layout(); | |
| 247 samples_per_second_ = config.samples_per_second(); | |
| 234 state_ = kIdle; | 248 state_ = kIdle; |
| 235 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 249 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
| 236 } | 250 } |
| 237 | 251 |
| 238 void DecryptingVideoDecoder::DoRead(const ReadCB& read_cb) { | 252 void DecryptingAudioDecoder::DoRead(const ReadCB& read_cb) { |
| 239 DVLOG(3) << "DoRead()"; | 253 DVLOG(3) << "DoRead()"; |
| 240 DCHECK(message_loop_->BelongsToCurrentThread()); | 254 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 241 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; | 255 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; |
| 242 DCHECK(!read_cb.is_null()); | 256 DCHECK(!read_cb.is_null()); |
| 243 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; | 257 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; |
| 244 | 258 |
| 245 // Return empty frames if decoding has finished. | 259 // Return empty (end-of-stream) frames if decoding has finished. |
| 246 if (state_ == kDecodeFinished) { | 260 if (state_ == kDecodeFinished) { |
| 247 read_cb.Run(kOk, VideoFrame::CreateEmptyFrame()); | 261 read_cb.Run(kOk, scoped_refptr<Buffer>(new DataBuffer(0))); |
| 248 return; | 262 return; |
| 249 } | 263 } |
| 250 | 264 |
| 265 if (!queued_audio_frames_.empty()) { | |
| 266 if (queued_audio_frames_.front()->IsEndOfStream()) | |
| 267 state_ = kDecodeFinished; | |
| 268 read_cb.Run(kOk, queued_audio_frames_.front()); | |
| 269 queued_audio_frames_.pop_front(); | |
| 270 return; | |
| 271 } | |
| 272 | |
| 251 read_cb_ = read_cb; | 273 read_cb_ = read_cb; |
| 252 state_ = kPendingDemuxerRead; | 274 state_ = kPendingDemuxerRead; |
| 253 ReadFromDemuxerStream(); | 275 ReadFromDemuxerStream(); |
| 254 } | 276 } |
| 255 | 277 |
| 256 void DecryptingVideoDecoder::ReadFromDemuxerStream() { | 278 void DecryptingAudioDecoder::ReadFromDemuxerStream() { |
| 257 DCHECK(message_loop_->BelongsToCurrentThread()); | 279 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 258 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; | 280 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; |
| 259 DCHECK(!read_cb_.is_null()); | 281 DCHECK(!read_cb_.is_null()); |
| 260 | 282 |
| 261 demuxer_stream_->Read( | 283 demuxer_stream_->Read( |
| 262 base::Bind(&DecryptingVideoDecoder::DecryptAndDecodeBuffer, this)); | 284 base::Bind(&DecryptingAudioDecoder::DecryptAndDecodeBuffer, this)); |
| 263 } | 285 } |
| 264 | 286 |
| 265 void DecryptingVideoDecoder::DecryptAndDecodeBuffer( | 287 void DecryptingAudioDecoder::DecryptAndDecodeBuffer( |
| 266 DemuxerStream::Status status, | 288 DemuxerStream::Status status, |
| 267 const scoped_refptr<DecoderBuffer>& buffer) { | 289 const scoped_refptr<DecoderBuffer>& buffer) { |
| 268 // In theory, we don't need to force post the task here, because we do a | 290 // In theory, we don't need to force post the task here, because we do a |
| 269 // force task post in DeliverFrame(). Therefore, even if | 291 // force task post in DeliverFrame(). Therefore, even if |
| 270 // demuxer_stream_->Read() execute the read callback on the same execution | 292 // demuxer_stream_->Read() execute the read callback on the same execution |
| 271 // stack we are still fine. But it looks like a force post task makes the | 293 // stack we are still fine. But it looks like a force post task makes the |
| 272 // logic more understandable and manageable, so why not? | 294 // logic more understandable and manageable, so why not? |
| 273 message_loop_->PostTask(FROM_HERE, base::Bind( | 295 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 274 &DecryptingVideoDecoder::DoDecryptAndDecodeBuffer, this, status, buffer)); | 296 &DecryptingAudioDecoder::DoDecryptAndDecodeBuffer, this, status, buffer)); |
| 275 } | 297 } |
| 276 | 298 |
| 277 void DecryptingVideoDecoder::DoDecryptAndDecodeBuffer( | 299 void DecryptingAudioDecoder::DoDecryptAndDecodeBuffer( |
| 278 DemuxerStream::Status status, | 300 DemuxerStream::Status status, |
| 279 const scoped_refptr<DecoderBuffer>& buffer) { | 301 const scoped_refptr<DecoderBuffer>& buffer) { |
| 280 DVLOG(3) << "DoDecryptAndDecodeBuffer()"; | 302 DVLOG(3) << "DoDecryptAndDecodeBuffer()"; |
| 281 DCHECK(message_loop_->BelongsToCurrentThread()); | 303 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 282 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; | 304 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; |
| 283 DCHECK(!read_cb_.is_null()); | 305 DCHECK(!read_cb_.is_null()); |
| 284 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; | 306 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; |
| 285 | 307 |
| 286 if (!reset_cb_.is_null() || !stop_cb_.is_null()) { | 308 if (!reset_cb_.is_null() || !stop_cb_.is_null()) { |
| 287 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 309 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
| 288 if (!reset_cb_.is_null()) | 310 if (!reset_cb_.is_null()) |
| 289 DoReset(); | 311 DoReset(); |
| 290 if (!stop_cb_.is_null()) | 312 if (!stop_cb_.is_null()) |
| 291 DoStop(); | 313 DoStop(); |
| 292 return; | 314 return; |
| 293 } | 315 } |
| 294 | 316 |
| 295 if (status == DemuxerStream::kAborted) { | 317 if (status == DemuxerStream::kAborted) { |
| 296 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kAborted"; | 318 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kAborted"; |
| 297 state_ = kIdle; | 319 state_ = kIdle; |
| 298 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 320 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
| 299 return; | 321 return; |
| 300 } | 322 } |
| 301 | 323 |
| 302 if (status == DemuxerStream::kConfigChanged) { | 324 if (status == DemuxerStream::kConfigChanged) { |
| 303 // TODO(xhwang): Add config change support. | 325 // TODO(xhwang): Add config change support. |
| 304 // The |state_| is chosen to be kDecodeFinished here to be consistent with | 326 // The |state_| is chosen to be kDecodeFinished here to be consistent with |
| 305 // the implementation of FFmpegVideoDecoder. | 327 // the implementation of FFmpegAudioDecoder. |
| 306 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged"; | 328 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged"; |
| 307 state_ = kDecodeFinished; | 329 state_ = kDecodeFinished; |
| 308 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 330 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
| 309 return; | 331 return; |
| 310 } | 332 } |
| 311 | 333 |
| 312 DCHECK_EQ(status, DemuxerStream::kOk); | 334 DCHECK_EQ(status, DemuxerStream::kOk); |
| 313 pending_buffer_to_decode_ = buffer; | 335 pending_buffer_to_decode_ = buffer; |
| 314 state_ = kPendingDecode; | 336 state_ = kPendingDecode; |
| 315 DecodePendingBuffer(); | 337 DecodePendingBuffer(); |
| 316 } | 338 } |
| 317 | 339 |
| 318 void DecryptingVideoDecoder::DecodePendingBuffer() { | 340 void DecryptingAudioDecoder::DecodePendingBuffer() { |
| 319 DCHECK(message_loop_->BelongsToCurrentThread()); | 341 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 320 DCHECK_EQ(state_, kPendingDecode) << state_; | 342 DCHECK_EQ(state_, kPendingDecode) << state_; |
| 321 decryptor_->DecryptAndDecodeVideo( | 343 decryptor_->DecryptAndDecodeAudio( |
| 322 pending_buffer_to_decode_, | 344 pending_buffer_to_decode_, |
| 323 base::Bind(&DecryptingVideoDecoder::DeliverFrame, this, | 345 base::Bind(&DecryptingAudioDecoder::DeliverFrame, this, |
| 324 pending_buffer_to_decode_->GetDataSize())); | 346 pending_buffer_to_decode_->GetDataSize())); |
| 325 } | 347 } |
| 326 | 348 |
| 327 void DecryptingVideoDecoder::DeliverFrame( | 349 void DecryptingAudioDecoder::DeliverFrame( |
| 328 int buffer_size, | 350 int buffer_size, |
| 329 Decryptor::Status status, | 351 Decryptor::Status status, |
| 330 const scoped_refptr<VideoFrame>& frame) { | 352 const Decryptor::AudioBuffers& frames) { |
| 331 // We need to force task post here because the VideoDecodeCB can be executed | 353 // We need to force task post here because the AudioDecodeCB can be executed |
| 332 // synchronously in Reset()/Stop(). Instead of using more complicated logic in | 354 // synchronously in Reset()/Stop(). Instead of using more complicated logic in |
| 333 // those function to fix it, why not force task post here to make everything | 355 // those function to fix it, why not force task post here to make everything |
| 334 // simple and clear? | 356 // simple and clear? |
| 335 message_loop_->PostTask(FROM_HERE, base::Bind( | 357 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 336 &DecryptingVideoDecoder::DoDeliverFrame, this, | 358 &DecryptingAudioDecoder::DoDeliverFrame, this, |
| 337 buffer_size, status, frame)); | 359 buffer_size, status, frames)); |
| 338 } | 360 } |
| 339 | 361 |
| 340 void DecryptingVideoDecoder::DoDeliverFrame( | 362 void DecryptingAudioDecoder::DoDeliverFrame( |
| 341 int buffer_size, | 363 int buffer_size, |
| 342 Decryptor::Status status, | 364 Decryptor::Status status, |
| 343 const scoped_refptr<VideoFrame>& frame) { | 365 const Decryptor::AudioBuffers& frames) { |
| 344 DVLOG(3) << "DoDeliverFrame()"; | 366 DVLOG(3) << "DoDeliverFrame()"; |
| 345 DCHECK(message_loop_->BelongsToCurrentThread()); | 367 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 346 DCHECK_EQ(state_, kPendingDecode) << state_; | 368 DCHECK_EQ(state_, kPendingDecode) << state_; |
| 347 DCHECK(!read_cb_.is_null()); | 369 DCHECK(!read_cb_.is_null()); |
| 348 DCHECK(pending_buffer_to_decode_); | 370 DCHECK(pending_buffer_to_decode_); |
| 371 DCHECK(queued_audio_frames_.empty()); | |
| 349 | 372 |
| 350 bool need_to_try_again_if_nokey_is_returned = key_added_while_pending_decode_; | 373 bool need_to_try_again_if_nokey_is_returned = key_added_while_pending_decode_; |
| 351 key_added_while_pending_decode_ = false; | 374 key_added_while_pending_decode_ = false; |
| 352 | 375 |
| 353 if (!reset_cb_.is_null() || !stop_cb_.is_null()) { | 376 if (!reset_cb_.is_null() || !stop_cb_.is_null()) { |
| 354 pending_buffer_to_decode_ = NULL; | 377 pending_buffer_to_decode_ = NULL; |
| 355 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 378 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
| 356 if (!reset_cb_.is_null()) | 379 if (!reset_cb_.is_null()) |
| 357 DoReset(); | 380 DoReset(); |
| 358 if (!stop_cb_.is_null()) | 381 if (!stop_cb_.is_null()) |
| 359 DoStop(); | 382 DoStop(); |
| 360 return; | 383 return; |
| 361 } | 384 } |
| 362 | 385 |
| 363 if (status == Decryptor::kError) { | 386 if (status == Decryptor::kError) { |
| 364 DCHECK(!frame); | 387 DCHECK(frames.empty()); |
| 365 state_ = kDecodeFinished; | 388 state_ = kDecodeFinished; |
| 366 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 389 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
| 367 return; | 390 return; |
| 368 } | 391 } |
| 369 | 392 |
| 370 if (status == Decryptor::kNoKey) { | 393 if (status == Decryptor::kNoKey) { |
| 371 DCHECK(!frame); | 394 DCHECK(frames.empty()); |
| 372 if (need_to_try_again_if_nokey_is_returned) { | 395 if (need_to_try_again_if_nokey_is_returned) { |
| 373 // The |state_| is still kPendingDecode. | 396 // The |state_| is still kPendingDecode. |
| 374 DecodePendingBuffer(); | 397 DecodePendingBuffer(); |
| 375 return; | 398 return; |
| 376 } | 399 } |
| 377 | 400 |
| 378 state_ = kWaitingForKey; | 401 state_ = kWaitingForKey; |
| 379 return; | 402 return; |
| 380 } | 403 } |
| 381 | 404 |
| 382 // The buffer has been accepted by the decoder, let's report statistics. | 405 // The buffer has been accepted by the decoder, let's report statistics. |
| 383 if (buffer_size) { | 406 if (buffer_size) { |
| 384 PipelineStatistics statistics; | 407 PipelineStatistics statistics; |
| 385 statistics.video_bytes_decoded = buffer_size; | 408 statistics.audio_bytes_decoded = buffer_size; |
| 386 statistics_cb_.Run(statistics); | 409 statistics_cb_.Run(statistics); |
| 387 } | 410 } |
| 388 | 411 |
| 389 if (status == Decryptor::kNeedMoreData) { | 412 if (status == Decryptor::kNeedMoreData) { |
| 390 DCHECK(!frame); | 413 DCHECK(frames.empty()); |
| 391 state_ = kPendingDemuxerRead; | 414 state_ = kPendingDemuxerRead; |
| 392 ReadFromDemuxerStream(); | 415 ReadFromDemuxerStream(); |
| 393 return; | 416 return; |
| 394 } | 417 } |
| 395 | 418 |
| 396 DCHECK_EQ(status, Decryptor::kSuccess); | 419 DCHECK_EQ(status, Decryptor::kSuccess); |
| 397 state_ = frame->IsEndOfStream() ? kDecodeFinished : kIdle; | 420 |
| 398 base::ResetAndReturn(&read_cb_).Run(kOk, frame); | 421 DCHECK(!frames.empty()); |
| 422 queued_audio_frames_ = frames; | |
| 423 | |
| 424 scoped_refptr<Buffer> first_frame = queued_audio_frames_.front(); | |
| 425 queued_audio_frames_.pop_front(); | |
| 426 state_ = first_frame->IsEndOfStream() ? kDecodeFinished : kIdle; | |
| 427 base::ResetAndReturn(&read_cb_).Run(kOk, first_frame); | |
| 399 } | 428 } |
| 400 | 429 |
| 401 void DecryptingVideoDecoder::OnKeyAdded() { | 430 void DecryptingAudioDecoder::OnKeyAdded() { |
| 402 DVLOG(2) << "OnKeyAdded()"; | |
| 403 DCHECK(message_loop_->BelongsToCurrentThread()); | 431 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 404 | 432 |
| 405 if (state_ == kPendingDecode) { | 433 if (state_ == kPendingDecode) { |
| 406 key_added_while_pending_decode_ = true; | 434 key_added_while_pending_decode_ = true; |
| 407 return; | 435 return; |
| 408 } | 436 } |
| 409 | 437 |
| 410 if (state_ == kWaitingForKey) { | 438 if (state_ == kWaitingForKey) { |
| 411 state_ = kPendingDecode; | 439 state_ = kPendingDecode; |
| 412 DecodePendingBuffer(); | 440 DecodePendingBuffer(); |
| 413 } | 441 } |
| 414 } | 442 } |
| 415 | 443 |
| 416 void DecryptingVideoDecoder::DoReset() { | 444 void DecryptingAudioDecoder::DoReset() { |
| 417 DCHECK(init_cb_.is_null()); | 445 DCHECK(init_cb_.is_null()); |
| 418 DCHECK(read_cb_.is_null()); | 446 DCHECK(read_cb_.is_null()); |
| 419 state_ = kIdle; | 447 state_ = kIdle; |
| 420 base::ResetAndReturn(&reset_cb_).Run(); | 448 base::ResetAndReturn(&reset_cb_).Run(); |
| 421 } | 449 } |
| 422 | 450 |
| 423 void DecryptingVideoDecoder::DoStop() { | 451 void DecryptingAudioDecoder::DoStop() { |
| 424 DCHECK(init_cb_.is_null()); | 452 DCHECK(init_cb_.is_null()); |
| 425 DCHECK(read_cb_.is_null()); | 453 DCHECK(read_cb_.is_null()); |
| 426 state_ = kStopped; | 454 state_ = kStopped; |
| 427 base::ResetAndReturn(&stop_cb_).Run(); | 455 base::ResetAndReturn(&stop_cb_).Run(); |
| 428 } | 456 } |
| 429 | 457 |
| 430 } // namespace media | 458 } // namespace media |
| OLD | NEW |