| 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), |
| 33 bits_per_channel_(0), |
| 34 channel_layout_(CHANNEL_LAYOUT_NONE), |
| 35 samples_per_second_(0) { |
| 32 } | 36 } |
| 33 | 37 |
| 34 void DecryptingVideoDecoder::Initialize( | 38 void DecryptingAudioDecoder::Initialize( |
| 35 const scoped_refptr<DemuxerStream>& stream, | 39 const scoped_refptr<DemuxerStream>& stream, |
| 36 const PipelineStatusCB& status_cb, | 40 const PipelineStatusCB& status_cb, |
| 37 const StatisticsCB& statistics_cb) { | 41 const StatisticsCB& statistics_cb) { |
| 38 DCHECK(!message_loop_); | 42 DCHECK(!message_loop_); |
| 39 message_loop_ = base::ResetAndReturn(&message_loop_factory_cb_).Run(); | 43 message_loop_ = base::ResetAndReturn(&message_loop_factory_cb_).Run(); |
| 40 message_loop_->PostTask(FROM_HERE, base::Bind( | 44 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 41 &DecryptingVideoDecoder::DoInitialize, this, | 45 &DecryptingAudioDecoder::DoInitialize, this, |
| 42 stream, status_cb, statistics_cb)); | 46 stream, status_cb, statistics_cb)); |
| 43 } | 47 } |
| 44 | 48 |
| 45 void DecryptingVideoDecoder::Read(const ReadCB& read_cb) { | 49 void DecryptingAudioDecoder::Read(const ReadCB& read_cb) { |
| 46 // Complete operation asynchronously on different stack of execution as per | 50 // Complete operation asynchronously on different stack of execution as per |
| 47 // the API contract of VideoDecoder::Read() | 51 // the API contract of AudioDecoder::Read() |
| 48 message_loop_->PostTask(FROM_HERE, base::Bind( | 52 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 49 &DecryptingVideoDecoder::DoRead, this, read_cb)); | 53 &DecryptingAudioDecoder::DoRead, this, read_cb)); |
| 50 } | 54 } |
| 51 | 55 |
| 52 void DecryptingVideoDecoder::Reset(const base::Closure& closure) { | 56 void DecryptingAudioDecoder::Reset(const base::Closure& closure) { |
| 53 if (!message_loop_->BelongsToCurrentThread()) { | 57 if (!message_loop_->BelongsToCurrentThread()) { |
| 54 message_loop_->PostTask(FROM_HERE, base::Bind( | 58 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 55 &DecryptingVideoDecoder::Reset, this, closure)); | 59 &DecryptingAudioDecoder::Reset, this, closure)); |
| 56 return; | 60 return; |
| 57 } | 61 } |
| 58 | 62 |
| 59 DVLOG(2) << "Reset() - state: " << state_; | 63 DVLOG(2) << "Reset() - state: " << state_; |
| 60 DCHECK(state_ == kIdle || | 64 DCHECK(state_ == kIdle || |
| 61 state_ == kPendingDemuxerRead || | 65 state_ == kPendingDemuxerRead || |
| 62 state_ == kPendingDecode || | 66 state_ == kPendingDecode || |
| 63 state_ == kWaitingForKey || | 67 state_ == kWaitingForKey || |
| 64 state_ == kDecodeFinished) << state_; | 68 state_ == kDecodeFinished) << state_; |
| 65 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. | 69 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. |
| 66 DCHECK(reset_cb_.is_null()); | 70 DCHECK(reset_cb_.is_null()); |
| 67 | 71 |
| 68 reset_cb_ = closure; | 72 reset_cb_ = closure; |
| 69 | 73 |
| 70 decryptor_->ResetDecoder(Decryptor::kVideo); | 74 decryptor_->ResetDecoder(Decryptor::kAudio); |
| 71 | 75 |
| 72 // Reset() cannot complete if the read callback is still pending. | 76 // Reset() cannot complete if the read callback is still pending. |
| 73 // Defer the resetting process in this case. The |reset_cb_| will be fired | 77 // Defer the resetting process in this case. The |reset_cb_| will be fired |
| 74 // after the read callback is fired - see DoDecryptAndDecodeBuffer() and | 78 // after the read callback is fired - see DoDecryptAndDecodeBuffer() and |
| 75 // DoDeliverFrame(). | 79 // DoDeliverFrame(). |
| 76 if (state_ == kPendingDemuxerRead || state_ == kPendingDecode) { | 80 if (state_ == kPendingDemuxerRead || state_ == kPendingDecode) { |
| 77 DCHECK(!read_cb_.is_null()); | 81 DCHECK(!read_cb_.is_null()); |
| 78 return; | 82 return; |
| 79 } | 83 } |
| 80 | 84 |
| 81 if (state_ == kWaitingForKey) { | 85 if (state_ == kWaitingForKey) { |
| 82 DCHECK(!read_cb_.is_null()); | 86 DCHECK(!read_cb_.is_null()); |
| 83 pending_buffer_to_decode_ = NULL; | 87 pending_buffer_to_decode_ = NULL; |
| 84 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 88 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
| 85 } | 89 } |
| 86 | 90 |
| 87 DCHECK(read_cb_.is_null()); | 91 DCHECK(read_cb_.is_null()); |
| 88 DoReset(); | 92 DoReset(); |
| 89 } | 93 } |
| 90 | 94 |
| 91 void DecryptingVideoDecoder::Stop(const base::Closure& closure) { | 95 int DecryptingAudioDecoder::bits_per_channel() { |
| 92 if (!message_loop_->BelongsToCurrentThread()) { | 96 return bits_per_channel_; |
| 93 message_loop_->PostTask(FROM_HERE, base::Bind( | |
| 94 &DecryptingVideoDecoder::Stop, this, closure)); | |
| 95 return; | |
| 96 } | |
| 97 | |
| 98 DVLOG(2) << "Stop() - state: " << state_; | |
| 99 | |
| 100 // At this point the render thread is likely paused (in WebMediaPlayerImpl's | |
| 101 // Destroy()), so running |closure| can't wait for anything that requires the | |
| 102 // render thread to be processing messages to complete (such as PPAPI | |
| 103 // callbacks). | |
| 104 if (decryptor_) | |
| 105 decryptor_->DeinitializeDecoder(Decryptor::kVideo); | |
| 106 if (!request_decryptor_notification_cb_.is_null()) { | |
| 107 base::ResetAndReturn(&request_decryptor_notification_cb_).Run( | |
| 108 DecryptorNotificationCB()); | |
| 109 } | |
| 110 pending_buffer_to_decode_ = NULL; | |
| 111 if (!init_cb_.is_null()) | |
| 112 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | |
| 113 if (!read_cb_.is_null()) | |
| 114 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | |
| 115 if (!reset_cb_.is_null()) | |
| 116 base::ResetAndReturn(&reset_cb_).Run(); | |
| 117 state_ = kStopped; | |
| 118 closure.Run(); | |
| 119 } | 97 } |
| 120 | 98 |
| 121 DecryptingVideoDecoder::~DecryptingVideoDecoder() { | 99 ChannelLayout DecryptingAudioDecoder::channel_layout() { |
| 122 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_; | 100 return channel_layout_; |
| 123 } | 101 } |
| 124 | 102 |
| 125 void DecryptingVideoDecoder::DoInitialize( | 103 int DecryptingAudioDecoder::samples_per_second() { |
| 104 return samples_per_second_; |
| 105 } |
| 106 |
| 107 DecryptingAudioDecoder::~DecryptingAudioDecoder() { |
| 108 } |
| 109 |
| 110 void DecryptingAudioDecoder::DoInitialize( |
| 126 const scoped_refptr<DemuxerStream>& stream, | 111 const scoped_refptr<DemuxerStream>& stream, |
| 127 const PipelineStatusCB& status_cb, | 112 const PipelineStatusCB& status_cb, |
| 128 const StatisticsCB& statistics_cb) { | 113 const StatisticsCB& statistics_cb) { |
| 129 DVLOG(2) << "DoInitialize()"; | 114 DVLOG(2) << "DoInitialize()"; |
| 130 DCHECK(message_loop_->BelongsToCurrentThread()); | 115 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 131 DCHECK_EQ(state_, kUninitialized) << state_; | 116 DCHECK_EQ(state_, kUninitialized) << state_; |
| 132 DCHECK(stream); | 117 DCHECK(stream); |
| 133 | 118 |
| 134 const VideoDecoderConfig& config = stream->video_decoder_config(); | 119 const AudioDecoderConfig& config = stream->audio_decoder_config(); |
| 135 if (!config.IsValidConfig()) { | 120 if (!config.IsValidConfig()) { |
| 136 DLOG(ERROR) << "Invalid video stream config: " | 121 DLOG(ERROR) << "Invalid audio stream config."; |
| 137 << config.AsHumanReadableString(); | |
| 138 status_cb.Run(PIPELINE_ERROR_DECODE); | 122 status_cb.Run(PIPELINE_ERROR_DECODE); |
| 139 return; | 123 return; |
| 140 } | 124 } |
| 141 | 125 |
| 142 // DecryptingVideoDecoder only accepts potentially encrypted stream. | 126 // DecryptingAudioDecoder only accepts potentially encrypted stream. |
| 143 if (!config.is_encrypted()) { | 127 if (!config.is_encrypted()) { |
| 144 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); | 128 status_cb.Run(DECODER_ERROR_NOT_SUPPORTED); |
| 145 return; | 129 return; |
| 146 } | 130 } |
| 147 | 131 |
| 148 DCHECK(!demuxer_stream_); | 132 DCHECK(!demuxer_stream_); |
| 149 demuxer_stream_ = stream; | 133 demuxer_stream_ = stream; |
| 150 statistics_cb_ = statistics_cb; | 134 statistics_cb_ = statistics_cb; |
| 151 | 135 |
| 152 init_cb_ = status_cb; | 136 init_cb_ = status_cb; |
| 153 | 137 |
| 154 state_ = kDecryptorRequested; | 138 state_ = kDecryptorRequested; |
| 155 request_decryptor_notification_cb_.Run( | 139 request_decryptor_notification_cb_.Run( |
| 156 BIND_TO_LOOP(&DecryptingVideoDecoder::SetDecryptor)); | 140 BIND_TO_LOOP(&DecryptingAudioDecoder::SetDecryptor)); |
| 157 } | 141 } |
| 158 | 142 |
| 159 void DecryptingVideoDecoder::SetDecryptor(Decryptor* decryptor) { | 143 void DecryptingAudioDecoder::SetDecryptor(Decryptor* decryptor) { |
| 160 DVLOG(2) << "SetDecryptor()"; | 144 DVLOG(2) << "SetDecryptor()"; |
| 161 DCHECK(message_loop_->BelongsToCurrentThread()); | 145 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 162 | |
| 163 if (state_ == kStopped) | |
| 164 return; | |
| 165 | |
| 166 DCHECK_EQ(state_, kDecryptorRequested) << state_; | 146 DCHECK_EQ(state_, kDecryptorRequested) << state_; |
| 167 DCHECK(!init_cb_.is_null()); | 147 DCHECK(!init_cb_.is_null()); |
| 148 DCHECK(!request_decryptor_notification_cb_.is_null()); |
| 168 | 149 |
| 150 request_decryptor_notification_cb_.Reset(); |
| 169 decryptor_ = decryptor; | 151 decryptor_ = decryptor; |
| 170 | 152 |
| 171 scoped_ptr<VideoDecoderConfig> scoped_config(new VideoDecoderConfig()); | 153 scoped_ptr<AudioDecoderConfig> scoped_config(new AudioDecoderConfig()); |
| 172 scoped_config->CopyFrom(demuxer_stream_->video_decoder_config()); | 154 scoped_config->CopyFrom(demuxer_stream_->audio_decoder_config()); |
| 173 | 155 |
| 174 state_ = kPendingDecoderInit; | 156 state_ = kPendingDecoderInit; |
| 175 decryptor_->InitializeVideoDecoder( | 157 decryptor_->InitializeAudioDecoder( |
| 176 scoped_config.Pass(), | 158 scoped_config.Pass(), |
| 177 BIND_TO_LOOP(&DecryptingVideoDecoder::FinishInitialization), | 159 BIND_TO_LOOP(&DecryptingAudioDecoder::FinishInitialization), |
| 178 BIND_TO_LOOP(&DecryptingVideoDecoder::OnKeyAdded)); | 160 BIND_TO_LOOP(&DecryptingAudioDecoder::OnKeyAdded)); |
| 179 } | 161 } |
| 180 | 162 |
| 181 void DecryptingVideoDecoder::FinishInitialization(bool success) { | 163 void DecryptingAudioDecoder::FinishInitialization(bool success) { |
| 182 DVLOG(2) << "FinishInitialization()"; | 164 DVLOG(2) << "FinishInitialization()"; |
| 183 DCHECK(message_loop_->BelongsToCurrentThread()); | 165 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 184 | |
| 185 if (state_ == kStopped) | |
| 186 return; | |
| 187 | |
| 188 DCHECK_EQ(state_, kPendingDecoderInit) << state_; | 166 DCHECK_EQ(state_, kPendingDecoderInit) << state_; |
| 189 DCHECK(!init_cb_.is_null()); | 167 DCHECK(!init_cb_.is_null()); |
| 190 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. | 168 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. |
| 191 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. | 169 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. |
| 192 | 170 |
| 193 if (!success) { | 171 if (!success) { |
| 194 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 172 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
| 195 state_ = kStopped; | 173 state_ = kDecodeFinished; |
| 196 return; | 174 return; |
| 197 } | 175 } |
| 198 | 176 |
| 199 // Success! | 177 // Success! |
| 178 const AudioDecoderConfig& config = demuxer_stream_->audio_decoder_config(); |
| 179 bits_per_channel_ = config.bits_per_channel(); |
| 180 channel_layout_ = config.channel_layout(); |
| 181 samples_per_second_ = config.samples_per_second(); |
| 200 state_ = kIdle; | 182 state_ = kIdle; |
| 201 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 183 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
| 202 } | 184 } |
| 203 | 185 |
| 204 void DecryptingVideoDecoder::DoRead(const ReadCB& read_cb) { | 186 void DecryptingAudioDecoder::DoRead(const ReadCB& read_cb) { |
| 205 DVLOG(3) << "DoRead()"; | 187 DVLOG(3) << "DoRead()"; |
| 206 DCHECK(message_loop_->BelongsToCurrentThread()); | 188 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 207 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; | 189 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; |
| 208 DCHECK(!read_cb.is_null()); | 190 DCHECK(!read_cb.is_null()); |
| 209 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; | 191 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; |
| 210 | 192 |
| 211 // Return empty frames if decoding has finished. | 193 // Return empty (end-of-stream) frames if decoding has finished. |
| 212 if (state_ == kDecodeFinished) { | 194 if (state_ == kDecodeFinished) { |
| 213 read_cb.Run(kOk, VideoFrame::CreateEmptyFrame()); | 195 read_cb.Run(kOk, scoped_refptr<Buffer>(new DataBuffer(0))); |
| 214 return; | 196 return; |
| 215 } | 197 } |
| 216 | 198 |
| 199 if (!queued_audio_frames_.empty()) { |
| 200 if (queued_audio_frames_.front()->IsEndOfStream()) |
| 201 state_ = kDecodeFinished; |
| 202 read_cb.Run(kOk, queued_audio_frames_.front()); |
| 203 queued_audio_frames_.pop_front(); |
| 204 return; |
| 205 } |
| 206 |
| 217 read_cb_ = read_cb; | 207 read_cb_ = read_cb; |
| 218 state_ = kPendingDemuxerRead; | 208 state_ = kPendingDemuxerRead; |
| 219 ReadFromDemuxerStream(); | 209 ReadFromDemuxerStream(); |
| 220 } | 210 } |
| 221 | 211 |
| 222 void DecryptingVideoDecoder::ReadFromDemuxerStream() { | 212 void DecryptingAudioDecoder::ReadFromDemuxerStream() { |
| 223 DCHECK(message_loop_->BelongsToCurrentThread()); | 213 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 224 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; | 214 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; |
| 225 DCHECK(!read_cb_.is_null()); | 215 DCHECK(!read_cb_.is_null()); |
| 226 | 216 |
| 227 demuxer_stream_->Read( | 217 demuxer_stream_->Read( |
| 228 base::Bind(&DecryptingVideoDecoder::DecryptAndDecodeBuffer, this)); | 218 base::Bind(&DecryptingAudioDecoder::DecryptAndDecodeBuffer, this)); |
| 229 } | 219 } |
| 230 | 220 |
| 231 void DecryptingVideoDecoder::DecryptAndDecodeBuffer( | 221 void DecryptingAudioDecoder::DecryptAndDecodeBuffer( |
| 232 DemuxerStream::Status status, | 222 DemuxerStream::Status status, |
| 233 const scoped_refptr<DecoderBuffer>& buffer) { | 223 const scoped_refptr<DecoderBuffer>& buffer) { |
| 234 // In theory, we don't need to force post the task here, because we do a | 224 // In theory, we don't need to force post the task here, because we do a |
| 235 // force task post in DeliverFrame(). Therefore, even if | 225 // force task post in DeliverFrame(). Therefore, even if |
| 236 // demuxer_stream_->Read() execute the read callback on the same execution | 226 // demuxer_stream_->Read() execute the read callback on the same execution |
| 237 // stack we are still fine. But it looks like a force post task makes the | 227 // stack we are still fine. But it looks like a force post task makes the |
| 238 // logic more understandable and manageable, so why not? | 228 // logic more understandable and manageable, so why not? |
| 239 message_loop_->PostTask(FROM_HERE, base::Bind( | 229 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 240 &DecryptingVideoDecoder::DoDecryptAndDecodeBuffer, this, status, buffer)); | 230 &DecryptingAudioDecoder::DoDecryptAndDecodeBuffer, this, status, buffer)); |
| 241 } | 231 } |
| 242 | 232 |
| 243 void DecryptingVideoDecoder::DoDecryptAndDecodeBuffer( | 233 void DecryptingAudioDecoder::DoDecryptAndDecodeBuffer( |
| 244 DemuxerStream::Status status, | 234 DemuxerStream::Status status, |
| 245 const scoped_refptr<DecoderBuffer>& buffer) { | 235 const scoped_refptr<DecoderBuffer>& buffer) { |
| 246 DVLOG(3) << "DoDecryptAndDecodeBuffer()"; | 236 DVLOG(3) << "DoDecryptAndDecodeBuffer()"; |
| 247 DCHECK(message_loop_->BelongsToCurrentThread()); | 237 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 248 | |
| 249 if (state_ == kStopped) | |
| 250 return; | |
| 251 | |
| 252 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; | 238 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; |
| 253 DCHECK(!read_cb_.is_null()); | 239 DCHECK(!read_cb_.is_null()); |
| 254 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; | 240 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; |
| 255 | 241 |
| 256 if (!reset_cb_.is_null()) { | 242 if (!reset_cb_.is_null()) { |
| 257 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 243 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
| 258 if (!reset_cb_.is_null()) | 244 DoReset(); |
| 259 DoReset(); | |
| 260 return; | 245 return; |
| 261 } | 246 } |
| 262 | 247 |
| 263 if (status == DemuxerStream::kAborted) { | 248 if (status == DemuxerStream::kAborted) { |
| 264 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kAborted"; | 249 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kAborted"; |
| 265 state_ = kIdle; | 250 state_ = kIdle; |
| 266 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 251 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
| 267 return; | 252 return; |
| 268 } | 253 } |
| 269 | 254 |
| 270 if (status == DemuxerStream::kConfigChanged) { | 255 if (status == DemuxerStream::kConfigChanged) { |
| 271 // TODO(xhwang): Add config change support. | 256 // TODO(xhwang): Add config change support. |
| 272 // The |state_| is chosen to be kDecodeFinished here to be consistent with | 257 // The |state_| is chosen to be kDecodeFinished here to be consistent with |
| 273 // the implementation of FFmpegVideoDecoder. | 258 // the implementation of FFmpegVideoDecoder. |
| 274 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged"; | 259 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged"; |
| 275 state_ = kDecodeFinished; | 260 state_ = kDecodeFinished; |
| 276 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 261 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
| 277 return; | 262 return; |
| 278 } | 263 } |
| 279 | 264 |
| 280 DCHECK_EQ(status, DemuxerStream::kOk); | 265 DCHECK_EQ(status, DemuxerStream::kOk); |
| 281 pending_buffer_to_decode_ = buffer; | 266 pending_buffer_to_decode_ = buffer; |
| 282 state_ = kPendingDecode; | 267 state_ = kPendingDecode; |
| 283 DecodePendingBuffer(); | 268 DecodePendingBuffer(); |
| 284 } | 269 } |
| 285 | 270 |
| 286 void DecryptingVideoDecoder::DecodePendingBuffer() { | 271 void DecryptingAudioDecoder::DecodePendingBuffer() { |
| 287 DCHECK(message_loop_->BelongsToCurrentThread()); | 272 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 288 DCHECK_EQ(state_, kPendingDecode) << state_; | 273 DCHECK_EQ(state_, kPendingDecode) << state_; |
| 289 decryptor_->DecryptAndDecodeVideo( | 274 decryptor_->DecryptAndDecodeAudio( |
| 290 pending_buffer_to_decode_, | 275 pending_buffer_to_decode_, |
| 291 base::Bind(&DecryptingVideoDecoder::DeliverFrame, this, | 276 base::Bind(&DecryptingAudioDecoder::DeliverFrame, this, |
| 292 pending_buffer_to_decode_->GetDataSize())); | 277 pending_buffer_to_decode_->GetDataSize())); |
| 293 } | 278 } |
| 294 | 279 |
| 295 void DecryptingVideoDecoder::DeliverFrame( | 280 void DecryptingAudioDecoder::DeliverFrame( |
| 296 int buffer_size, | 281 int buffer_size, |
| 297 Decryptor::Status status, | 282 Decryptor::Status status, |
| 298 const scoped_refptr<VideoFrame>& frame) { | 283 const Decryptor::AudioBuffers& frames) { |
| 299 // We need to force task post here because the VideoDecodeCB can be executed | 284 // We need to force task post here because the AudioDecodeCB can be executed |
| 300 // synchronously in Reset()/Stop(). Instead of using more complicated logic in | 285 // synchronously in Reset(). Instead of using more complicated logic in |
| 301 // those function to fix it, why not force task post here to make everything | 286 // those function to fix it, why not force task post here to make everything |
| 302 // simple and clear? | 287 // simple and clear? |
| 303 message_loop_->PostTask(FROM_HERE, base::Bind( | 288 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 304 &DecryptingVideoDecoder::DoDeliverFrame, this, | 289 &DecryptingAudioDecoder::DoDeliverFrame, this, |
| 305 buffer_size, status, frame)); | 290 buffer_size, status, frames)); |
| 306 } | 291 } |
| 307 | 292 |
| 308 void DecryptingVideoDecoder::DoDeliverFrame( | 293 void DecryptingAudioDecoder::DoDeliverFrame( |
| 309 int buffer_size, | 294 int buffer_size, |
| 310 Decryptor::Status status, | 295 Decryptor::Status status, |
| 311 const scoped_refptr<VideoFrame>& frame) { | 296 const Decryptor::AudioBuffers& frames) { |
| 312 DVLOG(3) << "DoDeliverFrame()"; | 297 DVLOG(3) << "DoDeliverFrame()"; |
| 313 DCHECK(message_loop_->BelongsToCurrentThread()); | 298 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 314 | |
| 315 if (state_ == kStopped) | |
| 316 return; | |
| 317 | |
| 318 DCHECK_EQ(state_, kPendingDecode) << state_; | 299 DCHECK_EQ(state_, kPendingDecode) << state_; |
| 319 DCHECK(!read_cb_.is_null()); | 300 DCHECK(!read_cb_.is_null()); |
| 320 DCHECK(pending_buffer_to_decode_); | 301 DCHECK(pending_buffer_to_decode_); |
| 302 DCHECK(queued_audio_frames_.empty()); |
| 321 | 303 |
| 322 bool need_to_try_again_if_nokey_is_returned = key_added_while_pending_decode_; | 304 bool need_to_try_again_if_nokey_is_returned = key_added_while_pending_decode_; |
| 323 key_added_while_pending_decode_ = false; | 305 key_added_while_pending_decode_ = false; |
| 324 | 306 |
| 325 if (!reset_cb_.is_null()) { | 307 if (!reset_cb_.is_null()) { |
| 326 pending_buffer_to_decode_ = NULL; | 308 pending_buffer_to_decode_ = NULL; |
| 327 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 309 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
| 328 if (!reset_cb_.is_null()) | 310 DoReset(); |
| 329 DoReset(); | |
| 330 return; | 311 return; |
| 331 } | 312 } |
| 332 | 313 |
| 333 if (status == Decryptor::kError) { | 314 if (status == Decryptor::kError) { |
| 334 DCHECK(!frame); | 315 DCHECK(frames.empty()); |
| 335 state_ = kDecodeFinished; | 316 state_ = kDecodeFinished; |
| 336 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 317 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
| 337 return; | 318 return; |
| 338 } | 319 } |
| 339 | 320 |
| 340 if (status == Decryptor::kNoKey) { | 321 if (status == Decryptor::kNoKey) { |
| 341 DCHECK(!frame); | 322 DCHECK(frames.empty()); |
| 342 if (need_to_try_again_if_nokey_is_returned) { | 323 if (need_to_try_again_if_nokey_is_returned) { |
| 343 // The |state_| is still kPendingDecode. | 324 // The |state_| is still kPendingDecode. |
| 344 DecodePendingBuffer(); | 325 DecodePendingBuffer(); |
| 345 return; | 326 return; |
| 346 } | 327 } |
| 347 | 328 |
| 348 state_ = kWaitingForKey; | 329 state_ = kWaitingForKey; |
| 349 return; | 330 return; |
| 350 } | 331 } |
| 351 | 332 |
| 352 // The buffer has been accepted by the decoder, let's report statistics. | 333 // The buffer has been accepted by the decoder, let's report statistics. |
| 353 if (buffer_size) { | 334 if (buffer_size) { |
| 354 PipelineStatistics statistics; | 335 PipelineStatistics statistics; |
| 355 statistics.video_bytes_decoded = buffer_size; | 336 statistics.audio_bytes_decoded = buffer_size; |
| 356 statistics_cb_.Run(statistics); | 337 statistics_cb_.Run(statistics); |
| 357 } | 338 } |
| 358 | 339 |
| 359 if (status == Decryptor::kNeedMoreData) { | 340 if (status == Decryptor::kNeedMoreData) { |
| 360 DCHECK(!frame); | 341 DCHECK(frames.empty()); |
| 361 state_ = kPendingDemuxerRead; | 342 state_ = kPendingDemuxerRead; |
| 362 ReadFromDemuxerStream(); | 343 ReadFromDemuxerStream(); |
| 363 return; | 344 return; |
| 364 } | 345 } |
| 365 | 346 |
| 366 DCHECK_EQ(status, Decryptor::kSuccess); | 347 DCHECK_EQ(status, Decryptor::kSuccess); |
| 367 state_ = frame->IsEndOfStream() ? kDecodeFinished : kIdle; | 348 |
| 368 base::ResetAndReturn(&read_cb_).Run(kOk, frame); | 349 DCHECK(!frames.empty()); |
| 350 queued_audio_frames_ = frames; |
| 351 |
| 352 scoped_refptr<Buffer> first_frame = queued_audio_frames_.front(); |
| 353 queued_audio_frames_.pop_front(); |
| 354 state_ = first_frame->IsEndOfStream() ? kDecodeFinished : kIdle; |
| 355 base::ResetAndReturn(&read_cb_).Run(kOk, first_frame); |
| 369 } | 356 } |
| 370 | 357 |
| 371 void DecryptingVideoDecoder::OnKeyAdded() { | 358 void DecryptingAudioDecoder::OnKeyAdded() { |
| 372 DVLOG(2) << "OnKeyAdded()"; | |
| 373 DCHECK(message_loop_->BelongsToCurrentThread()); | 359 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 374 | 360 |
| 375 if (state_ == kPendingDecode) { | 361 if (state_ == kPendingDecode) { |
| 376 key_added_while_pending_decode_ = true; | 362 key_added_while_pending_decode_ = true; |
| 377 return; | 363 return; |
| 378 } | 364 } |
| 379 | 365 |
| 380 if (state_ == kWaitingForKey) { | 366 if (state_ == kWaitingForKey) { |
| 381 state_ = kPendingDecode; | 367 state_ = kPendingDecode; |
| 382 DecodePendingBuffer(); | 368 DecodePendingBuffer(); |
| 383 } | 369 } |
| 384 } | 370 } |
| 385 | 371 |
| 386 void DecryptingVideoDecoder::DoReset() { | 372 void DecryptingAudioDecoder::DoReset() { |
| 387 DCHECK(init_cb_.is_null()); | 373 DCHECK(init_cb_.is_null()); |
| 388 DCHECK(read_cb_.is_null()); | 374 DCHECK(read_cb_.is_null()); |
| 389 state_ = kIdle; | 375 state_ = kIdle; |
| 390 base::ResetAndReturn(&reset_cb_).Run(); | 376 base::ResetAndReturn(&reset_cb_).Run(); |
| 391 } | 377 } |
| 392 | 378 |
| 393 } // namespace media | 379 } // namespace media |
| OLD | NEW |