| 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 "webkit/plugins/ppapi/content_decryptor_delegate.h" | 5 #include "webkit/plugins/ppapi/content_decryptor_delegate.h" |
| 6 | 6 |
| 7 #include "base/callback_helpers.h" | 7 #include "base/callback_helpers.h" |
| 8 #include "base/debug/trace_event.h" | 8 #include "base/debug/trace_event.h" |
| 9 #include "base/message_loop/message_loop_proxy.h" | 9 #include "base/message_loop/message_loop_proxy.h" |
| 10 #include "media/base/audio_decoder_config.h" | 10 #include "media/base/audio_decoder_config.h" |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 static bool MakeEncryptedBlockInfo( | 85 static bool MakeEncryptedBlockInfo( |
| 86 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, | 86 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, |
| 87 uint32_t request_id, | 87 uint32_t request_id, |
| 88 PP_EncryptedBlockInfo* block_info) { | 88 PP_EncryptedBlockInfo* block_info) { |
| 89 // TODO(xhwang): Fix initialization of PP_EncryptedBlockInfo here and | 89 // TODO(xhwang): Fix initialization of PP_EncryptedBlockInfo here and |
| 90 // anywhere else. | 90 // anywhere else. |
| 91 memset(block_info, 0, sizeof(*block_info)); | 91 memset(block_info, 0, sizeof(*block_info)); |
| 92 block_info->tracking_info.request_id = request_id; | 92 block_info->tracking_info.request_id = request_id; |
| 93 | 93 |
| 94 // EOS buffers need a request ID and nothing more. | 94 // EOS buffers need a request ID and nothing more. |
| 95 if (encrypted_buffer->IsEndOfStream()) | 95 if (encrypted_buffer->end_of_stream()) |
| 96 return true; | 96 return true; |
| 97 | 97 |
| 98 DCHECK(encrypted_buffer->GetDataSize()) | 98 DCHECK(encrypted_buffer->data_size()) |
| 99 << "DecryptConfig is set on an empty buffer"; | 99 << "DecryptConfig is set on an empty buffer"; |
| 100 | 100 |
| 101 block_info->tracking_info.timestamp = | 101 block_info->tracking_info.timestamp = |
| 102 encrypted_buffer->GetTimestamp().InMicroseconds(); | 102 encrypted_buffer->timestamp().InMicroseconds(); |
| 103 block_info->data_size = encrypted_buffer->GetDataSize(); | 103 block_info->data_size = encrypted_buffer->data_size(); |
| 104 | 104 |
| 105 const media::DecryptConfig* decrypt_config = | 105 const media::DecryptConfig* decrypt_config = |
| 106 encrypted_buffer->GetDecryptConfig(); | 106 encrypted_buffer->decrypt_config(); |
| 107 block_info->data_offset = decrypt_config->data_offset(); | 107 block_info->data_offset = decrypt_config->data_offset(); |
| 108 | 108 |
| 109 if (!CopyStringToArray(decrypt_config->key_id(), block_info->key_id) || | 109 if (!CopyStringToArray(decrypt_config->key_id(), block_info->key_id) || |
| 110 !CopyStringToArray(decrypt_config->iv(), block_info->iv)) | 110 !CopyStringToArray(decrypt_config->iv(), block_info->iv)) |
| 111 return false; | 111 return false; |
| 112 | 112 |
| 113 block_info->key_id_size = decrypt_config->key_id().size(); | 113 block_info->key_id_size = decrypt_config->key_id().size(); |
| 114 block_info->iv_size = decrypt_config->iv().size(); | 114 block_info->iv_size = decrypt_config->iv().size(); |
| 115 | 115 |
| 116 if (decrypt_config->subsamples().size() > arraysize(block_info->subsamples)) | 116 if (decrypt_config->subsamples().size() > arraysize(block_info->subsamples)) |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 stream_type, encrypted_buffer, &encrypted_resource) || | 359 stream_type, encrypted_buffer, &encrypted_resource) || |
| 360 !encrypted_resource.get()) { | 360 !encrypted_resource.get()) { |
| 361 return false; | 361 return false; |
| 362 } | 362 } |
| 363 ScopedPPResource pp_resource(encrypted_resource.get()); | 363 ScopedPPResource pp_resource(encrypted_resource.get()); |
| 364 | 364 |
| 365 const uint32_t request_id = next_decryption_request_id_++; | 365 const uint32_t request_id = next_decryption_request_id_++; |
| 366 DVLOG(2) << "Decrypt() - request_id " << request_id; | 366 DVLOG(2) << "Decrypt() - request_id " << request_id; |
| 367 | 367 |
| 368 PP_EncryptedBlockInfo block_info = {}; | 368 PP_EncryptedBlockInfo block_info = {}; |
| 369 DCHECK(encrypted_buffer->GetDecryptConfig()); | 369 DCHECK(encrypted_buffer->decrypt_config()); |
| 370 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { | 370 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { |
| 371 return false; | 371 return false; |
| 372 } | 372 } |
| 373 | 373 |
| 374 // There is only one pending decrypt request at any time per stream. This is | 374 // There is only one pending decrypt request at any time per stream. This is |
| 375 // enforced by the media pipeline. | 375 // enforced by the media pipeline. |
| 376 switch (stream_type) { | 376 switch (stream_type) { |
| 377 case media::Decryptor::kAudio: | 377 case media::Decryptor::kAudio: |
| 378 DCHECK_EQ(pending_audio_decrypt_request_id_, 0u); | 378 DCHECK_EQ(pending_audio_decrypt_request_id_, 0u); |
| 379 DCHECK(pending_audio_decrypt_cb_.is_null()); | 379 DCHECK(pending_audio_decrypt_cb_.is_null()); |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 // because there is only one pending audio decode request at any time. | 530 // because there is only one pending audio decode request at any time. |
| 531 // This is enforced by the media pipeline. | 531 // This is enforced by the media pipeline. |
| 532 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; | 532 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; |
| 533 if (!MakeMediaBufferResource(media::Decryptor::kAudio, | 533 if (!MakeMediaBufferResource(media::Decryptor::kAudio, |
| 534 encrypted_buffer, | 534 encrypted_buffer, |
| 535 &encrypted_resource)) { | 535 &encrypted_resource)) { |
| 536 return false; | 536 return false; |
| 537 } | 537 } |
| 538 | 538 |
| 539 // The resource should not be NULL for non-EOS buffer. | 539 // The resource should not be NULL for non-EOS buffer. |
| 540 if (!encrypted_buffer->IsEndOfStream() && !encrypted_resource.get()) | 540 if (!encrypted_buffer->end_of_stream() && !encrypted_resource.get()) |
| 541 return false; | 541 return false; |
| 542 | 542 |
| 543 const uint32_t request_id = next_decryption_request_id_++; | 543 const uint32_t request_id = next_decryption_request_id_++; |
| 544 DVLOG(2) << "DecryptAndDecodeAudio() - request_id " << request_id; | 544 DVLOG(2) << "DecryptAndDecodeAudio() - request_id " << request_id; |
| 545 | 545 |
| 546 PP_EncryptedBlockInfo block_info = {}; | 546 PP_EncryptedBlockInfo block_info = {}; |
| 547 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { | 547 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { |
| 548 return false; | 548 return false; |
| 549 } | 549 } |
| 550 | 550 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 574 // because there is only one pending video decode request at any time. | 574 // because there is only one pending video decode request at any time. |
| 575 // This is enforced by the media pipeline. | 575 // This is enforced by the media pipeline. |
| 576 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; | 576 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; |
| 577 if (!MakeMediaBufferResource(media::Decryptor::kVideo, | 577 if (!MakeMediaBufferResource(media::Decryptor::kVideo, |
| 578 encrypted_buffer, | 578 encrypted_buffer, |
| 579 &encrypted_resource)) { | 579 &encrypted_resource)) { |
| 580 return false; | 580 return false; |
| 581 } | 581 } |
| 582 | 582 |
| 583 // The resource should not be 0 for non-EOS buffer. | 583 // The resource should not be 0 for non-EOS buffer. |
| 584 if (!encrypted_buffer->IsEndOfStream() && !encrypted_resource.get()) | 584 if (!encrypted_buffer->end_of_stream() && !encrypted_resource.get()) |
| 585 return false; | 585 return false; |
| 586 | 586 |
| 587 const uint32_t request_id = next_decryption_request_id_++; | 587 const uint32_t request_id = next_decryption_request_id_++; |
| 588 DVLOG(2) << "DecryptAndDecodeVideo() - request_id " << request_id; | 588 DVLOG(2) << "DecryptAndDecodeVideo() - request_id " << request_id; |
| 589 TRACE_EVENT_ASYNC_BEGIN0( | 589 TRACE_EVENT_ASYNC_BEGIN0( |
| 590 "eme", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id); | 590 "eme", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id); |
| 591 | 591 |
| 592 PP_EncryptedBlockInfo block_info = {}; | 592 PP_EncryptedBlockInfo block_info = {}; |
| 593 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { | 593 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { |
| 594 return false; | 594 return false; |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 772 mapper.size() < block_info->data_size) { | 772 mapper.size() < block_info->data_size) { |
| 773 decrypt_cb.Run(media::Decryptor::kError, NULL); | 773 decrypt_cb.Run(media::Decryptor::kError, NULL); |
| 774 return; | 774 return; |
| 775 } | 775 } |
| 776 | 776 |
| 777 // TODO(tomfinegan): Find a way to take ownership of the shared memory | 777 // TODO(tomfinegan): Find a way to take ownership of the shared memory |
| 778 // managed by the PPB_Buffer_Dev, and avoid the extra copy. | 778 // managed by the PPB_Buffer_Dev, and avoid the extra copy. |
| 779 scoped_refptr<media::DecoderBuffer> decrypted_buffer( | 779 scoped_refptr<media::DecoderBuffer> decrypted_buffer( |
| 780 media::DecoderBuffer::CopyFrom( | 780 media::DecoderBuffer::CopyFrom( |
| 781 static_cast<uint8*>(mapper.data()), block_info->data_size)); | 781 static_cast<uint8*>(mapper.data()), block_info->data_size)); |
| 782 decrypted_buffer->SetTimestamp(base::TimeDelta::FromMicroseconds( | 782 decrypted_buffer->set_timestamp(base::TimeDelta::FromMicroseconds( |
| 783 block_info->tracking_info.timestamp)); | 783 block_info->tracking_info.timestamp)); |
| 784 decrypt_cb.Run(media::Decryptor::kSuccess, decrypted_buffer); | 784 decrypt_cb.Run(media::Decryptor::kSuccess, decrypted_buffer); |
| 785 } | 785 } |
| 786 | 786 |
| 787 // Use a non-class-member function here so that if for some reason | 787 // Use a non-class-member function here so that if for some reason |
| 788 // ContentDecryptorDelegate is destroyed before VideoFrame calls this callback, | 788 // ContentDecryptorDelegate is destroyed before VideoFrame calls this callback, |
| 789 // we can still get the shared memory unmapped. | 789 // we can still get the shared memory unmapped. |
| 790 static void BufferNoLongerNeeded( | 790 static void BufferNoLongerNeeded( |
| 791 const scoped_refptr<PPB_Buffer_Impl>& ppb_buffer, | 791 const scoped_refptr<PPB_Buffer_Impl>& ppb_buffer, |
| 792 base::Closure buffer_no_longer_needed_cb) { | 792 base::Closure buffer_no_longer_needed_cb) { |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 } | 952 } |
| 953 } | 953 } |
| 954 | 954 |
| 955 bool ContentDecryptorDelegate::MakeMediaBufferResource( | 955 bool ContentDecryptorDelegate::MakeMediaBufferResource( |
| 956 media::Decryptor::StreamType stream_type, | 956 media::Decryptor::StreamType stream_type, |
| 957 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, | 957 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, |
| 958 scoped_refptr<PPB_Buffer_Impl>* resource) { | 958 scoped_refptr<PPB_Buffer_Impl>* resource) { |
| 959 TRACE_EVENT0("eme", "ContentDecryptorDelegate::MakeMediaBufferResource"); | 959 TRACE_EVENT0("eme", "ContentDecryptorDelegate::MakeMediaBufferResource"); |
| 960 | 960 |
| 961 // End of stream buffers are represented as null resources. | 961 // End of stream buffers are represented as null resources. |
| 962 if (encrypted_buffer->IsEndOfStream()) { | 962 if (encrypted_buffer->end_of_stream()) { |
| 963 *resource = NULL; | 963 *resource = NULL; |
| 964 return true; | 964 return true; |
| 965 } | 965 } |
| 966 | 966 |
| 967 DCHECK(stream_type == media::Decryptor::kAudio || | 967 DCHECK(stream_type == media::Decryptor::kAudio || |
| 968 stream_type == media::Decryptor::kVideo); | 968 stream_type == media::Decryptor::kVideo); |
| 969 scoped_refptr<PPB_Buffer_Impl>& media_resource = | 969 scoped_refptr<PPB_Buffer_Impl>& media_resource = |
| 970 (stream_type == media::Decryptor::kAudio) ? audio_input_resource_ : | 970 (stream_type == media::Decryptor::kAudio) ? audio_input_resource_ : |
| 971 video_input_resource_; | 971 video_input_resource_; |
| 972 | 972 |
| 973 const size_t data_size = static_cast<size_t>(encrypted_buffer->GetDataSize()); | 973 const size_t data_size = static_cast<size_t>(encrypted_buffer->data_size()); |
| 974 if (!media_resource.get() || media_resource->size() < data_size) { | 974 if (!media_resource.get() || media_resource->size() < data_size) { |
| 975 // Either the buffer hasn't been created yet, or we have one that isn't big | 975 // Either the buffer hasn't been created yet, or we have one that isn't big |
| 976 // enough to fit |size| bytes. | 976 // enough to fit |size| bytes. |
| 977 | 977 |
| 978 // Media resource size starts from |kMinimumMediaBufferSize| and grows | 978 // Media resource size starts from |kMinimumMediaBufferSize| and grows |
| 979 // exponentially to avoid frequent re-allocation of PPB_Buffer_Impl, | 979 // exponentially to avoid frequent re-allocation of PPB_Buffer_Impl, |
| 980 // which is usually expensive. Since input media buffers are compressed, | 980 // which is usually expensive. Since input media buffers are compressed, |
| 981 // they are usually small (compared to outputs). The over-allocated memory | 981 // they are usually small (compared to outputs). The over-allocated memory |
| 982 // should be negligible. | 982 // should be negligible. |
| 983 const uint32_t kMinimumMediaBufferSize = 1024; | 983 const uint32_t kMinimumMediaBufferSize = 1024; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 994 media_resource_size); | 994 media_resource_size); |
| 995 if (!media_resource.get()) | 995 if (!media_resource.get()) |
| 996 return false; | 996 return false; |
| 997 } | 997 } |
| 998 | 998 |
| 999 BufferAutoMapper mapper(media_resource.get()); | 999 BufferAutoMapper mapper(media_resource.get()); |
| 1000 if (!mapper.data() || mapper.size() < data_size) { | 1000 if (!mapper.data() || mapper.size() < data_size) { |
| 1001 media_resource = NULL; | 1001 media_resource = NULL; |
| 1002 return false; | 1002 return false; |
| 1003 } | 1003 } |
| 1004 memcpy(mapper.data(), encrypted_buffer->GetData(), data_size); | 1004 memcpy(mapper.data(), encrypted_buffer->data(), data_size); |
| 1005 | 1005 |
| 1006 *resource = media_resource; | 1006 *resource = media_resource; |
| 1007 return true; | 1007 return true; |
| 1008 } | 1008 } |
| 1009 | 1009 |
| 1010 void ContentDecryptorDelegate::FreeBuffer(uint32_t buffer_id) { | 1010 void ContentDecryptorDelegate::FreeBuffer(uint32_t buffer_id) { |
| 1011 if (buffer_id) | 1011 if (buffer_id) |
| 1012 free_buffers_.push(buffer_id); | 1012 free_buffers_.push(buffer_id); |
| 1013 } | 1013 } |
| 1014 | 1014 |
| 1015 void ContentDecryptorDelegate::SetBufferToFreeInTrackingInfo( | 1015 void ContentDecryptorDelegate::SetBufferToFreeInTrackingInfo( |
| 1016 PP_DecryptTrackingInfo* tracking_info) { | 1016 PP_DecryptTrackingInfo* tracking_info) { |
| 1017 DCHECK_EQ(tracking_info->buffer_id, 0u); | 1017 DCHECK_EQ(tracking_info->buffer_id, 0u); |
| 1018 | 1018 |
| 1019 if (free_buffers_.empty()) | 1019 if (free_buffers_.empty()) |
| 1020 return; | 1020 return; |
| 1021 | 1021 |
| 1022 tracking_info->buffer_id = free_buffers_.front(); | 1022 tracking_info->buffer_id = free_buffers_.front(); |
| 1023 free_buffers_.pop(); | 1023 free_buffers_.pop(); |
| 1024 } | 1024 } |
| 1025 | 1025 |
| 1026 } // namespace ppapi | 1026 } // namespace ppapi |
| 1027 } // namespace webkit | 1027 } // namespace webkit |
| OLD | NEW |