| 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()); |
| 168 DCHECK(!request_decryptor_notification_cb_.is_null()); | 148 DCHECK(!request_decryptor_notification_cb_.is_null()); |
| 149 |
| 169 request_decryptor_notification_cb_.Reset(); | 150 request_decryptor_notification_cb_.Reset(); |
| 170 | |
| 171 decryptor_ = decryptor; | 151 decryptor_ = decryptor; |
| 172 | 152 |
| 173 scoped_ptr<VideoDecoderConfig> scoped_config(new VideoDecoderConfig()); | 153 scoped_ptr<AudioDecoderConfig> scoped_config(new AudioDecoderConfig()); |
| 174 scoped_config->CopyFrom(demuxer_stream_->video_decoder_config()); | 154 scoped_config->CopyFrom(demuxer_stream_->audio_decoder_config()); |
| 175 | 155 |
| 176 state_ = kPendingDecoderInit; | 156 state_ = kPendingDecoderInit; |
| 177 decryptor_->InitializeVideoDecoder( | 157 decryptor_->InitializeAudioDecoder( |
| 178 scoped_config.Pass(), | 158 scoped_config.Pass(), |
| 179 BIND_TO_LOOP(&DecryptingVideoDecoder::FinishInitialization), | 159 BIND_TO_LOOP(&DecryptingAudioDecoder::FinishInitialization), |
| 180 BIND_TO_LOOP(&DecryptingVideoDecoder::OnKeyAdded)); | 160 BIND_TO_LOOP(&DecryptingAudioDecoder::OnKeyAdded)); |
| 181 } | 161 } |
| 182 | 162 |
| 183 void DecryptingVideoDecoder::FinishInitialization(bool success) { | 163 void DecryptingAudioDecoder::FinishInitialization(bool success) { |
| 184 DVLOG(2) << "FinishInitialization()"; | 164 DVLOG(2) << "FinishInitialization()"; |
| 185 DCHECK(message_loop_->BelongsToCurrentThread()); | 165 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 186 | |
| 187 if (state_ == kStopped) | |
| 188 return; | |
| 189 | |
| 190 DCHECK_EQ(state_, kPendingDecoderInit) << state_; | 166 DCHECK_EQ(state_, kPendingDecoderInit) << state_; |
| 191 DCHECK(!init_cb_.is_null()); | 167 DCHECK(!init_cb_.is_null()); |
| 192 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. | 168 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. |
| 193 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. | 169 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. |
| 194 | 170 |
| 195 if (!success) { | 171 if (!success) { |
| 196 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 172 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
| 197 state_ = kStopped; | 173 state_ = kDecodeFinished; |
| 198 return; | 174 return; |
| 199 } | 175 } |
| 200 | 176 |
| 201 // 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(); |
| 202 state_ = kIdle; | 182 state_ = kIdle; |
| 203 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 183 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
| 204 } | 184 } |
| 205 | 185 |
| 206 void DecryptingVideoDecoder::DoRead(const ReadCB& read_cb) { | 186 void DecryptingAudioDecoder::DoRead(const ReadCB& read_cb) { |
| 207 DVLOG(3) << "DoRead()"; | 187 DVLOG(3) << "DoRead()"; |
| 208 DCHECK(message_loop_->BelongsToCurrentThread()); | 188 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 209 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; | 189 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; |
| 210 DCHECK(!read_cb.is_null()); | 190 DCHECK(!read_cb.is_null()); |
| 211 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; | 191 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; |
| 212 | 192 |
| 213 // Return empty frames if decoding has finished. | 193 // Return empty (end-of-stream) frames if decoding has finished. |
| 214 if (state_ == kDecodeFinished) { | 194 if (state_ == kDecodeFinished) { |
| 215 read_cb.Run(kOk, VideoFrame::CreateEmptyFrame()); | 195 read_cb.Run(kOk, scoped_refptr<Buffer>(new DataBuffer(0))); |
| 216 return; | 196 return; |
| 217 } | 197 } |
| 218 | 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 |
| 219 read_cb_ = read_cb; | 207 read_cb_ = read_cb; |
| 220 state_ = kPendingDemuxerRead; | 208 state_ = kPendingDemuxerRead; |
| 221 ReadFromDemuxerStream(); | 209 ReadFromDemuxerStream(); |
| 222 } | 210 } |
| 223 | 211 |
| 224 void DecryptingVideoDecoder::ReadFromDemuxerStream() { | 212 void DecryptingAudioDecoder::ReadFromDemuxerStream() { |
| 225 DCHECK(message_loop_->BelongsToCurrentThread()); | 213 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 226 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; | 214 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; |
| 227 DCHECK(!read_cb_.is_null()); | 215 DCHECK(!read_cb_.is_null()); |
| 228 | 216 |
| 229 demuxer_stream_->Read( | 217 demuxer_stream_->Read( |
| 230 base::Bind(&DecryptingVideoDecoder::DecryptAndDecodeBuffer, this)); | 218 base::Bind(&DecryptingAudioDecoder::DecryptAndDecodeBuffer, this)); |
| 231 } | 219 } |
| 232 | 220 |
| 233 void DecryptingVideoDecoder::DecryptAndDecodeBuffer( | 221 void DecryptingAudioDecoder::DecryptAndDecodeBuffer( |
| 234 DemuxerStream::Status status, | 222 DemuxerStream::Status status, |
| 235 const scoped_refptr<DecoderBuffer>& buffer) { | 223 const scoped_refptr<DecoderBuffer>& buffer) { |
| 236 // 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 |
| 237 // force task post in DeliverFrame(). Therefore, even if | 225 // force task post in DeliverFrame(). Therefore, even if |
| 238 // demuxer_stream_->Read() execute the read callback on the same execution | 226 // demuxer_stream_->Read() execute the read callback on the same execution |
| 239 // 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 |
| 240 // logic more understandable and manageable, so why not? | 228 // logic more understandable and manageable, so why not? |
| 241 message_loop_->PostTask(FROM_HERE, base::Bind( | 229 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 242 &DecryptingVideoDecoder::DoDecryptAndDecodeBuffer, this, status, buffer)); | 230 &DecryptingAudioDecoder::DoDecryptAndDecodeBuffer, this, status, buffer)); |
| 243 } | 231 } |
| 244 | 232 |
| 245 void DecryptingVideoDecoder::DoDecryptAndDecodeBuffer( | 233 void DecryptingAudioDecoder::DoDecryptAndDecodeBuffer( |
| 246 DemuxerStream::Status status, | 234 DemuxerStream::Status status, |
| 247 const scoped_refptr<DecoderBuffer>& buffer) { | 235 const scoped_refptr<DecoderBuffer>& buffer) { |
| 248 DVLOG(3) << "DoDecryptAndDecodeBuffer()"; | 236 DVLOG(3) << "DoDecryptAndDecodeBuffer()"; |
| 249 DCHECK(message_loop_->BelongsToCurrentThread()); | 237 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 250 | |
| 251 if (state_ == kStopped) | |
| 252 return; | |
| 253 | |
| 254 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; | 238 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; |
| 255 DCHECK(!read_cb_.is_null()); | 239 DCHECK(!read_cb_.is_null()); |
| 256 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; | 240 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; |
| 257 | 241 |
| 258 if (!reset_cb_.is_null()) { | 242 if (!reset_cb_.is_null()) { |
| 259 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 243 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
| 260 if (!reset_cb_.is_null()) | 244 DoReset(); |
| 261 DoReset(); | |
| 262 return; | 245 return; |
| 263 } | 246 } |
| 264 | 247 |
| 265 if (status == DemuxerStream::kAborted) { | 248 if (status == DemuxerStream::kAborted) { |
| 266 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kAborted"; | 249 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kAborted"; |
| 267 state_ = kIdle; | 250 state_ = kIdle; |
| 268 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 251 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
| 269 return; | 252 return; |
| 270 } | 253 } |
| 271 | 254 |
| 272 if (status == DemuxerStream::kConfigChanged) { | 255 if (status == DemuxerStream::kConfigChanged) { |
| 273 // TODO(xhwang): Add config change support. | 256 // TODO(xhwang): Add config change support. |
| 274 // 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 |
| 275 // the implementation of FFmpegVideoDecoder. | 258 // the implementation of FFmpegVideoDecoder. |
| 276 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged"; | 259 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged"; |
| 277 state_ = kDecodeFinished; | 260 state_ = kDecodeFinished; |
| 278 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 261 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
| 279 return; | 262 return; |
| 280 } | 263 } |
| 281 | 264 |
| 282 DCHECK_EQ(status, DemuxerStream::kOk); | 265 DCHECK_EQ(status, DemuxerStream::kOk); |
| 283 pending_buffer_to_decode_ = buffer; | 266 pending_buffer_to_decode_ = buffer; |
| 284 state_ = kPendingDecode; | 267 state_ = kPendingDecode; |
| 285 DecodePendingBuffer(); | 268 DecodePendingBuffer(); |
| 286 } | 269 } |
| 287 | 270 |
| 288 void DecryptingVideoDecoder::DecodePendingBuffer() { | 271 void DecryptingAudioDecoder::DecodePendingBuffer() { |
| 289 DCHECK(message_loop_->BelongsToCurrentThread()); | 272 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 290 DCHECK_EQ(state_, kPendingDecode) << state_; | 273 DCHECK_EQ(state_, kPendingDecode) << state_; |
| 291 decryptor_->DecryptAndDecodeVideo( | 274 decryptor_->DecryptAndDecodeAudio( |
| 292 pending_buffer_to_decode_, | 275 pending_buffer_to_decode_, |
| 293 base::Bind(&DecryptingVideoDecoder::DeliverFrame, this, | 276 base::Bind(&DecryptingAudioDecoder::DeliverFrame, this, |
| 294 pending_buffer_to_decode_->GetDataSize())); | 277 pending_buffer_to_decode_->GetDataSize())); |
| 295 } | 278 } |
| 296 | 279 |
| 297 void DecryptingVideoDecoder::DeliverFrame( | 280 void DecryptingAudioDecoder::DeliverFrame( |
| 298 int buffer_size, | 281 int buffer_size, |
| 299 Decryptor::Status status, | 282 Decryptor::Status status, |
| 300 const scoped_refptr<VideoFrame>& frame) { | 283 const Decryptor::AudioBuffers& frames) { |
| 301 // 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 |
| 302 // synchronously in Reset()/Stop(). Instead of using more complicated logic in | 285 // synchronously in Reset(). Instead of using more complicated logic in |
| 303 // 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 |
| 304 // simple and clear? | 287 // simple and clear? |
| 305 message_loop_->PostTask(FROM_HERE, base::Bind( | 288 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 306 &DecryptingVideoDecoder::DoDeliverFrame, this, | 289 &DecryptingAudioDecoder::DoDeliverFrame, this, |
| 307 buffer_size, status, frame)); | 290 buffer_size, status, frames)); |
| 308 } | 291 } |
| 309 | 292 |
| 310 void DecryptingVideoDecoder::DoDeliverFrame( | 293 void DecryptingAudioDecoder::DoDeliverFrame( |
| 311 int buffer_size, | 294 int buffer_size, |
| 312 Decryptor::Status status, | 295 Decryptor::Status status, |
| 313 const scoped_refptr<VideoFrame>& frame) { | 296 const Decryptor::AudioBuffers& frames) { |
| 314 DVLOG(3) << "DoDeliverFrame()"; | 297 DVLOG(3) << "DoDeliverFrame()"; |
| 315 DCHECK(message_loop_->BelongsToCurrentThread()); | 298 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 316 | |
| 317 if (state_ == kStopped) | |
| 318 return; | |
| 319 | |
| 320 DCHECK_EQ(state_, kPendingDecode) << state_; | 299 DCHECK_EQ(state_, kPendingDecode) << state_; |
| 321 DCHECK(!read_cb_.is_null()); | 300 DCHECK(!read_cb_.is_null()); |
| 322 DCHECK(pending_buffer_to_decode_); | 301 DCHECK(pending_buffer_to_decode_); |
| 302 DCHECK(queued_audio_frames_.empty()); |
| 323 | 303 |
| 324 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_; |
| 325 key_added_while_pending_decode_ = false; | 305 key_added_while_pending_decode_ = false; |
| 326 | 306 |
| 327 if (!reset_cb_.is_null()) { | 307 if (!reset_cb_.is_null()) { |
| 328 pending_buffer_to_decode_ = NULL; | 308 pending_buffer_to_decode_ = NULL; |
| 329 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 309 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
| 330 if (!reset_cb_.is_null()) | 310 DoReset(); |
| 331 DoReset(); | |
| 332 return; | 311 return; |
| 333 } | 312 } |
| 334 | 313 |
| 335 if (status == Decryptor::kError) { | 314 if (status == Decryptor::kError) { |
| 336 DCHECK(!frame); | 315 DCHECK(frames.empty()); |
| 337 state_ = kDecodeFinished; | 316 state_ = kDecodeFinished; |
| 338 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 317 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
| 339 return; | 318 return; |
| 340 } | 319 } |
| 341 | 320 |
| 342 if (status == Decryptor::kNoKey) { | 321 if (status == Decryptor::kNoKey) { |
| 343 DCHECK(!frame); | 322 DCHECK(frames.empty()); |
| 344 if (need_to_try_again_if_nokey_is_returned) { | 323 if (need_to_try_again_if_nokey_is_returned) { |
| 345 // The |state_| is still kPendingDecode. | 324 // The |state_| is still kPendingDecode. |
| 346 DecodePendingBuffer(); | 325 DecodePendingBuffer(); |
| 347 return; | 326 return; |
| 348 } | 327 } |
| 349 | 328 |
| 350 state_ = kWaitingForKey; | 329 state_ = kWaitingForKey; |
| 351 return; | 330 return; |
| 352 } | 331 } |
| 353 | 332 |
| 354 // 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. |
| 355 if (buffer_size) { | 334 if (buffer_size) { |
| 356 PipelineStatistics statistics; | 335 PipelineStatistics statistics; |
| 357 statistics.video_bytes_decoded = buffer_size; | 336 statistics.audio_bytes_decoded = buffer_size; |
| 358 statistics_cb_.Run(statistics); | 337 statistics_cb_.Run(statistics); |
| 359 } | 338 } |
| 360 | 339 |
| 361 if (status == Decryptor::kNeedMoreData) { | 340 if (status == Decryptor::kNeedMoreData) { |
| 362 DCHECK(!frame); | 341 DCHECK(frames.empty()); |
| 363 state_ = kPendingDemuxerRead; | 342 state_ = kPendingDemuxerRead; |
| 364 ReadFromDemuxerStream(); | 343 ReadFromDemuxerStream(); |
| 365 return; | 344 return; |
| 366 } | 345 } |
| 367 | 346 |
| 368 DCHECK_EQ(status, Decryptor::kSuccess); | 347 DCHECK_EQ(status, Decryptor::kSuccess); |
| 369 state_ = frame->IsEndOfStream() ? kDecodeFinished : kIdle; | 348 |
| 370 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); |
| 371 } | 356 } |
| 372 | 357 |
| 373 void DecryptingVideoDecoder::OnKeyAdded() { | 358 void DecryptingAudioDecoder::OnKeyAdded() { |
| 374 DVLOG(2) << "OnKeyAdded()"; | |
| 375 DCHECK(message_loop_->BelongsToCurrentThread()); | 359 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 376 | 360 |
| 377 if (state_ == kPendingDecode) { | 361 if (state_ == kPendingDecode) { |
| 378 key_added_while_pending_decode_ = true; | 362 key_added_while_pending_decode_ = true; |
| 379 return; | 363 return; |
| 380 } | 364 } |
| 381 | 365 |
| 382 if (state_ == kWaitingForKey) { | 366 if (state_ == kWaitingForKey) { |
| 383 state_ = kPendingDecode; | 367 state_ = kPendingDecode; |
| 384 DecodePendingBuffer(); | 368 DecodePendingBuffer(); |
| 385 } | 369 } |
| 386 } | 370 } |
| 387 | 371 |
| 388 void DecryptingVideoDecoder::DoReset() { | 372 void DecryptingAudioDecoder::DoReset() { |
| 389 DCHECK(init_cb_.is_null()); | 373 DCHECK(init_cb_.is_null()); |
| 390 DCHECK(read_cb_.is_null()); | 374 DCHECK(read_cb_.is_null()); |
| 391 state_ = kIdle; | 375 state_ = kIdle; |
| 392 base::ResetAndReturn(&reset_cb_).Run(); | 376 base::ResetAndReturn(&reset_cb_).Run(); |
| 393 } | 377 } |
| 394 | 378 |
| 395 } // namespace media | 379 } // namespace media |
| OLD | NEW |