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