| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/mojo/clients/mojo_decryptor.h" | 5 #include "media/mojo/clients/mojo_decryptor.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <utility> | 10 #include <utility> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/numerics/safe_conversions.h" | 13 #include "base/numerics/safe_conversions.h" |
| 14 #include "media/base/audio_buffer.h" | 14 #include "media/base/audio_buffer.h" |
| 15 #include "media/base/decoder_buffer.h" | 15 #include "media/base/decoder_buffer.h" |
| 16 #include "media/base/video_frame.h" | 16 #include "media/base/video_frame.h" |
| 17 #include "media/mojo/common/media_type_converters.h" | 17 #include "media/mojo/common/media_type_converters.h" |
| 18 #include "media/mojo/common/mojo_decoder_buffer_converter.h" |
| 18 #include "media/mojo/common/mojo_shared_buffer_video_frame.h" | 19 #include "media/mojo/common/mojo_shared_buffer_video_frame.h" |
| 19 #include "media/mojo/interfaces/decryptor.mojom.h" | 20 #include "media/mojo/interfaces/decryptor.mojom.h" |
| 20 #include "services/shell/public/cpp/connect.h" | 21 #include "services/shell/public/cpp/connect.h" |
| 21 | 22 |
| 22 namespace media { | 23 namespace media { |
| 23 | 24 |
| 24 MojoDecryptor::MojoDecryptor(mojom::DecryptorPtr remote_decryptor) | 25 MojoDecryptor::MojoDecryptor(mojom::DecryptorPtr remote_decryptor) |
| 25 : remote_decryptor_(std::move(remote_decryptor)), weak_factory_(this) { | 26 : remote_decryptor_(std::move(remote_decryptor)), weak_factory_(this) { |
| 26 DVLOG(1) << __FUNCTION__; | 27 DVLOG(1) << __FUNCTION__; |
| 27 CreateDataPipes(); | 28 |
| 29 // Allocate DataPipe size based on video content. |
| 30 |
| 31 mojo::ScopedDataPipeConsumerHandle remote_consumer_handle; |
| 32 mojo_decoder_buffer_writer_ = MojoDecoderBufferWriter::Create( |
| 33 DemuxerStream::VIDEO, &remote_consumer_handle); |
| 34 |
| 35 mojo::ScopedDataPipeProducerHandle remote_producer_handle; |
| 36 mojo_decoder_buffer_reader_ = MojoDecoderBufferReader::Create( |
| 37 DemuxerStream::VIDEO, &remote_producer_handle); |
| 38 |
| 39 // Pass the other end of each pipe to |remote_decryptor_|. |
| 40 remote_decryptor_->Initialize(std::move(remote_consumer_handle), |
| 41 std::move(remote_producer_handle)); |
| 28 } | 42 } |
| 29 | 43 |
| 30 MojoDecryptor::~MojoDecryptor() { | 44 MojoDecryptor::~MojoDecryptor() { |
| 31 DVLOG(1) << __FUNCTION__; | 45 DVLOG(1) << __FUNCTION__; |
| 32 DCHECK(thread_checker_.CalledOnValidThread()); | 46 DCHECK(thread_checker_.CalledOnValidThread()); |
| 33 } | 47 } |
| 34 | 48 |
| 35 void MojoDecryptor::RegisterNewKeyCB(StreamType stream_type, | 49 void MojoDecryptor::RegisterNewKeyCB(StreamType stream_type, |
| 36 const NewKeyCB& key_added_cb) { | 50 const NewKeyCB& key_added_cb) { |
| 37 DCHECK(thread_checker_.CalledOnValidThread()); | 51 DCHECK(thread_checker_.CalledOnValidThread()); |
| 38 switch (stream_type) { | 52 switch (stream_type) { |
| 39 case kAudio: | 53 case kAudio: |
| 40 new_audio_key_cb_ = key_added_cb; | 54 new_audio_key_cb_ = key_added_cb; |
| 41 break; | 55 break; |
| 42 case kVideo: | 56 case kVideo: |
| 43 new_video_key_cb_ = key_added_cb; | 57 new_video_key_cb_ = key_added_cb; |
| 44 break; | 58 break; |
| 45 default: | 59 default: |
| 46 NOTREACHED(); | 60 NOTREACHED(); |
| 47 } | 61 } |
| 48 } | 62 } |
| 49 | 63 |
| 50 void MojoDecryptor::Decrypt(StreamType stream_type, | 64 void MojoDecryptor::Decrypt(StreamType stream_type, |
| 51 const scoped_refptr<DecoderBuffer>& encrypted, | 65 const scoped_refptr<DecoderBuffer>& encrypted, |
| 52 const DecryptCB& decrypt_cb) { | 66 const DecryptCB& decrypt_cb) { |
| 53 DVLOG(3) << __FUNCTION__; | 67 DVLOG(3) << __FUNCTION__; |
| 54 DCHECK(thread_checker_.CalledOnValidThread()); | 68 DCHECK(thread_checker_.CalledOnValidThread()); |
| 55 | 69 |
| 70 mojom::DecoderBufferPtr mojo_buffer = |
| 71 mojo_decoder_buffer_writer_->ConvertDecoderBuffer(encrypted); |
| 72 if (!mojo_buffer) { |
| 73 decrypt_cb.Run(kError, nullptr); |
| 74 return; |
| 75 } |
| 76 |
| 56 remote_decryptor_->Decrypt( | 77 remote_decryptor_->Decrypt( |
| 57 static_cast<mojom::DemuxerStream::Type>(stream_type), | 78 static_cast<mojom::DemuxerStream::Type>(stream_type), |
| 58 TransferDecoderBuffer(encrypted), | 79 std::move(mojo_buffer), |
| 59 base::Bind(&MojoDecryptor::OnBufferDecrypted, weak_factory_.GetWeakPtr(), | 80 base::Bind(&MojoDecryptor::OnBufferDecrypted, weak_factory_.GetWeakPtr(), |
| 60 decrypt_cb)); | 81 decrypt_cb)); |
| 61 } | 82 } |
| 62 | 83 |
| 63 void MojoDecryptor::CancelDecrypt(StreamType stream_type) { | 84 void MojoDecryptor::CancelDecrypt(StreamType stream_type) { |
| 64 DVLOG(1) << __FUNCTION__; | 85 DVLOG(1) << __FUNCTION__; |
| 65 DCHECK(thread_checker_.CalledOnValidThread()); | 86 DCHECK(thread_checker_.CalledOnValidThread()); |
| 66 | 87 |
| 67 remote_decryptor_->CancelDecrypt( | 88 remote_decryptor_->CancelDecrypt( |
| 68 static_cast<mojom::DemuxerStream::Type>(stream_type)); | 89 static_cast<mojom::DemuxerStream::Type>(stream_type)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 85 remote_decryptor_->InitializeVideoDecoder( | 106 remote_decryptor_->InitializeVideoDecoder( |
| 86 mojom::VideoDecoderConfig::From(config), init_cb); | 107 mojom::VideoDecoderConfig::From(config), init_cb); |
| 87 } | 108 } |
| 88 | 109 |
| 89 void MojoDecryptor::DecryptAndDecodeAudio( | 110 void MojoDecryptor::DecryptAndDecodeAudio( |
| 90 const scoped_refptr<DecoderBuffer>& encrypted, | 111 const scoped_refptr<DecoderBuffer>& encrypted, |
| 91 const AudioDecodeCB& audio_decode_cb) { | 112 const AudioDecodeCB& audio_decode_cb) { |
| 92 DVLOG(3) << __FUNCTION__; | 113 DVLOG(3) << __FUNCTION__; |
| 93 DCHECK(thread_checker_.CalledOnValidThread()); | 114 DCHECK(thread_checker_.CalledOnValidThread()); |
| 94 | 115 |
| 116 mojom::DecoderBufferPtr mojo_buffer = |
| 117 mojo_decoder_buffer_writer_->ConvertDecoderBuffer(encrypted); |
| 118 if (!mojo_buffer) { |
| 119 audio_decode_cb.Run(kError, AudioFrames()); |
| 120 return; |
| 121 } |
| 122 |
| 95 remote_decryptor_->DecryptAndDecodeAudio( | 123 remote_decryptor_->DecryptAndDecodeAudio( |
| 96 TransferDecoderBuffer(encrypted), | 124 std::move(mojo_buffer), |
| 97 base::Bind(&MojoDecryptor::OnAudioDecoded, weak_factory_.GetWeakPtr(), | 125 base::Bind(&MojoDecryptor::OnAudioDecoded, weak_factory_.GetWeakPtr(), |
| 98 audio_decode_cb)); | 126 audio_decode_cb)); |
| 99 } | 127 } |
| 100 | 128 |
| 101 void MojoDecryptor::DecryptAndDecodeVideo( | 129 void MojoDecryptor::DecryptAndDecodeVideo( |
| 102 const scoped_refptr<DecoderBuffer>& encrypted, | 130 const scoped_refptr<DecoderBuffer>& encrypted, |
| 103 const VideoDecodeCB& video_decode_cb) { | 131 const VideoDecodeCB& video_decode_cb) { |
| 104 DVLOG(3) << __FUNCTION__; | 132 DVLOG(3) << __FUNCTION__; |
| 105 DCHECK(thread_checker_.CalledOnValidThread()); | 133 DCHECK(thread_checker_.CalledOnValidThread()); |
| 106 | 134 |
| 135 mojom::DecoderBufferPtr mojo_buffer = |
| 136 mojo_decoder_buffer_writer_->ConvertDecoderBuffer(encrypted); |
| 137 if (!mojo_buffer) { |
| 138 video_decode_cb.Run(kError, nullptr); |
| 139 return; |
| 140 } |
| 141 |
| 107 remote_decryptor_->DecryptAndDecodeVideo( | 142 remote_decryptor_->DecryptAndDecodeVideo( |
| 108 TransferDecoderBuffer(encrypted), | 143 std::move(mojo_buffer), |
| 109 base::Bind(&MojoDecryptor::OnVideoDecoded, weak_factory_.GetWeakPtr(), | 144 base::Bind(&MojoDecryptor::OnVideoDecoded, weak_factory_.GetWeakPtr(), |
| 110 video_decode_cb)); | 145 video_decode_cb)); |
| 111 } | 146 } |
| 112 | 147 |
| 113 void MojoDecryptor::ResetDecoder(StreamType stream_type) { | 148 void MojoDecryptor::ResetDecoder(StreamType stream_type) { |
| 114 DVLOG(1) << __FUNCTION__; | 149 DVLOG(1) << __FUNCTION__; |
| 115 DCHECK(thread_checker_.CalledOnValidThread()); | 150 DCHECK(thread_checker_.CalledOnValidThread()); |
| 116 | 151 |
| 117 remote_decryptor_->ResetDecoder( | 152 remote_decryptor_->ResetDecoder( |
| 118 static_cast<mojom::DemuxerStream::Type>(stream_type)); | 153 static_cast<mojom::DemuxerStream::Type>(stream_type)); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 143 DVLOG_IF(1, status != mojom::Decryptor::Status::SUCCESS) | 178 DVLOG_IF(1, status != mojom::Decryptor::Status::SUCCESS) |
| 144 << __FUNCTION__ << "(" << status << ")"; | 179 << __FUNCTION__ << "(" << status << ")"; |
| 145 DVLOG_IF(3, status == mojom::Decryptor::Status::SUCCESS) << __FUNCTION__; | 180 DVLOG_IF(3, status == mojom::Decryptor::Status::SUCCESS) << __FUNCTION__; |
| 146 DCHECK(thread_checker_.CalledOnValidThread()); | 181 DCHECK(thread_checker_.CalledOnValidThread()); |
| 147 | 182 |
| 148 if (buffer.is_null()) { | 183 if (buffer.is_null()) { |
| 149 decrypt_cb.Run(static_cast<Decryptor::Status>(status), nullptr); | 184 decrypt_cb.Run(static_cast<Decryptor::Status>(status), nullptr); |
| 150 return; | 185 return; |
| 151 } | 186 } |
| 152 | 187 |
| 153 decrypt_cb.Run(static_cast<Decryptor::Status>(status), | 188 scoped_refptr<DecoderBuffer> media_buffer = |
| 154 ReadDecoderBuffer(std::move(buffer))); | 189 mojo_decoder_buffer_reader_->ConvertDecoderBuffer(buffer); |
| 190 if (!media_buffer) { |
| 191 decrypt_cb.Run(kError, nullptr); |
| 192 return; |
| 193 } |
| 194 |
| 195 decrypt_cb.Run(static_cast<Decryptor::Status>(status), media_buffer); |
| 155 } | 196 } |
| 156 | 197 |
| 157 void MojoDecryptor::OnAudioDecoded( | 198 void MojoDecryptor::OnAudioDecoded( |
| 158 const AudioDecodeCB& audio_decode_cb, | 199 const AudioDecodeCB& audio_decode_cb, |
| 159 mojom::Decryptor::Status status, | 200 mojom::Decryptor::Status status, |
| 160 mojo::Array<mojom::AudioBufferPtr> audio_buffers) { | 201 mojo::Array<mojom::AudioBufferPtr> audio_buffers) { |
| 161 DVLOG_IF(1, status != mojom::Decryptor::Status::SUCCESS) | 202 DVLOG_IF(1, status != mojom::Decryptor::Status::SUCCESS) |
| 162 << __FUNCTION__ << "(" << status << ")"; | 203 << __FUNCTION__ << "(" << status << ")"; |
| 163 DVLOG_IF(3, status == mojom::Decryptor::Status::SUCCESS) << __FUNCTION__; | 204 DVLOG_IF(3, status == mojom::Decryptor::Status::SUCCESS) << __FUNCTION__; |
| 164 DCHECK(thread_checker_.CalledOnValidThread()); | 205 DCHECK(thread_checker_.CalledOnValidThread()); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 } | 239 } |
| 199 | 240 |
| 200 void MojoDecryptor::ReleaseSharedBuffer(mojo::ScopedSharedBufferHandle buffer, | 241 void MojoDecryptor::ReleaseSharedBuffer(mojo::ScopedSharedBufferHandle buffer, |
| 201 size_t buffer_size) { | 242 size_t buffer_size) { |
| 202 DVLOG(1) << __FUNCTION__; | 243 DVLOG(1) << __FUNCTION__; |
| 203 DCHECK(thread_checker_.CalledOnValidThread()); | 244 DCHECK(thread_checker_.CalledOnValidThread()); |
| 204 | 245 |
| 205 remote_decryptor_->ReleaseSharedBuffer(std::move(buffer), buffer_size); | 246 remote_decryptor_->ReleaseSharedBuffer(std::move(buffer), buffer_size); |
| 206 } | 247 } |
| 207 | 248 |
| 208 void MojoDecryptor::CreateDataPipes() { | |
| 209 // Allocate DataPipe size based on video content. Video can get quite large; | |
| 210 // at 4K, VP9 delivers packets which are ~1MB in size; so allow for 50% | |
| 211 // headroom. | |
| 212 MojoCreateDataPipeOptions options; | |
| 213 options.struct_size = sizeof(MojoCreateDataPipeOptions); | |
| 214 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; | |
| 215 options.element_num_bytes = 1; | |
| 216 options.capacity_num_bytes = 1.5 * (1024 * 1024); | |
| 217 | |
| 218 // Create 2 pipes, one for each direction. | |
| 219 mojo::DataPipe write_pipe(options); | |
| 220 mojo::DataPipe read_pipe(options); | |
| 221 | |
| 222 // Keep one end of each pipe. | |
| 223 producer_handle_ = std::move(write_pipe.producer_handle); | |
| 224 consumer_handle_ = std::move(read_pipe.consumer_handle); | |
| 225 | |
| 226 // Pass the other end of each pipe to |remote_decryptor_|. | |
| 227 remote_decryptor_->Initialize(std::move(write_pipe.consumer_handle), | |
| 228 std::move(read_pipe.producer_handle)); | |
| 229 } | |
| 230 | |
| 231 mojom::DecoderBufferPtr MojoDecryptor::TransferDecoderBuffer( | |
| 232 const scoped_refptr<DecoderBuffer>& encrypted) { | |
| 233 mojom::DecoderBufferPtr buffer = mojom::DecoderBuffer::From(encrypted); | |
| 234 if (encrypted->end_of_stream()) | |
| 235 return buffer; | |
| 236 | |
| 237 // Serialize the data section of the DecoderBuffer into our pipe. | |
| 238 uint32_t num_bytes = base::checked_cast<uint32_t>(encrypted->data_size()); | |
| 239 DCHECK_GT(num_bytes, 0u); | |
| 240 CHECK_EQ(WriteDataRaw(producer_handle_.get(), encrypted->data(), &num_bytes, | |
| 241 MOJO_READ_DATA_FLAG_ALL_OR_NONE), | |
| 242 MOJO_RESULT_OK); | |
| 243 CHECK_EQ(num_bytes, static_cast<uint32_t>(encrypted->data_size())); | |
| 244 return buffer; | |
| 245 } | |
| 246 | |
| 247 scoped_refptr<DecoderBuffer> MojoDecryptor::ReadDecoderBuffer( | |
| 248 mojom::DecoderBufferPtr buffer) { | |
| 249 scoped_refptr<DecoderBuffer> media_buffer( | |
| 250 buffer.To<scoped_refptr<DecoderBuffer>>()); | |
| 251 if (media_buffer->end_of_stream()) | |
| 252 return media_buffer; | |
| 253 | |
| 254 // Wait for the data to become available in the DataPipe. | |
| 255 MojoHandleSignalsState state; | |
| 256 CHECK_EQ(MOJO_RESULT_OK, | |
| 257 MojoWait(consumer_handle_.get().value(), MOJO_HANDLE_SIGNAL_READABLE, | |
| 258 MOJO_DEADLINE_INDEFINITE, &state)); | |
| 259 CHECK_EQ(MOJO_HANDLE_SIGNAL_READABLE, state.satisfied_signals); | |
| 260 | |
| 261 // Read the inner data for the DecoderBuffer from our DataPipe. | |
| 262 uint32_t num_bytes = base::checked_cast<uint32_t>(media_buffer->data_size()); | |
| 263 DCHECK_GT(num_bytes, 0u); | |
| 264 CHECK_EQ(ReadDataRaw(consumer_handle_.get(), media_buffer->writable_data(), | |
| 265 &num_bytes, MOJO_READ_DATA_FLAG_ALL_OR_NONE), | |
| 266 MOJO_RESULT_OK); | |
| 267 CHECK_EQ(num_bytes, static_cast<uint32_t>(media_buffer->data_size())); | |
| 268 return media_buffer; | |
| 269 } | |
| 270 | |
| 271 } // namespace media | 249 } // namespace media |
| OLD | NEW |