| 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 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 // otherwise. | 82 // otherwise. |
| 83 static bool MakeEncryptedBlockInfo( | 83 static bool MakeEncryptedBlockInfo( |
| 84 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, | 84 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, |
| 85 uint32_t request_id, PP_EncryptedBlockInfo* block_info) { | 85 uint32_t request_id, PP_EncryptedBlockInfo* block_info) { |
| 86 // TODO(xhwang): Fix initialization of PP_EncryptedBlockInfo here and | 86 // TODO(xhwang): Fix initialization of PP_EncryptedBlockInfo here and |
| 87 // anywhere else. | 87 // anywhere else. |
| 88 memset(block_info, 0, sizeof(*block_info)); | 88 memset(block_info, 0, sizeof(*block_info)); |
| 89 block_info->tracking_info.request_id = request_id; | 89 block_info->tracking_info.request_id = request_id; |
| 90 | 90 |
| 91 // EOS buffers need a request ID and nothing more. | 91 // EOS buffers need a request ID and nothing more. |
| 92 if (encrypted_buffer->IsEndOfStream()) | 92 if (encrypted_buffer->end_of_stream()) |
| 93 return true; | 93 return true; |
| 94 | 94 |
| 95 DCHECK(encrypted_buffer->GetDataSize()) | 95 DCHECK(encrypted_buffer->data_size()) |
| 96 << "DecryptConfig is set on an empty buffer"; | 96 << "DecryptConfig is set on an empty buffer"; |
| 97 | 97 |
| 98 block_info->tracking_info.timestamp = | 98 block_info->tracking_info.timestamp = |
| 99 encrypted_buffer->GetTimestamp().InMicroseconds(); | 99 encrypted_buffer->timestamp().InMicroseconds(); |
| 100 block_info->data_size = encrypted_buffer->GetDataSize(); | 100 block_info->data_size = encrypted_buffer->data_size(); |
| 101 | 101 |
| 102 const media::DecryptConfig* decrypt_config = | 102 const media::DecryptConfig* decrypt_config = |
| 103 encrypted_buffer->GetDecryptConfig(); | 103 encrypted_buffer->decrypt_config(); |
| 104 block_info->data_offset = decrypt_config->data_offset(); | 104 block_info->data_offset = decrypt_config->data_offset(); |
| 105 | 105 |
| 106 if (!CopyStringToArray(decrypt_config->key_id(), block_info->key_id) || | 106 if (!CopyStringToArray(decrypt_config->key_id(), block_info->key_id) || |
| 107 !CopyStringToArray(decrypt_config->iv(), block_info->iv)) | 107 !CopyStringToArray(decrypt_config->iv(), block_info->iv)) |
| 108 return false; | 108 return false; |
| 109 | 109 |
| 110 block_info->key_id_size = decrypt_config->key_id().size(); | 110 block_info->key_id_size = decrypt_config->key_id().size(); |
| 111 block_info->iv_size = decrypt_config->iv().size(); | 111 block_info->iv_size = decrypt_config->iv().size(); |
| 112 | 112 |
| 113 if (decrypt_config->subsamples().size() > arraysize(block_info->subsamples)) | 113 if (decrypt_config->subsamples().size() > arraysize(block_info->subsamples)) |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 346 &encrypted_resource) || | 346 &encrypted_resource) || |
| 347 !encrypted_resource.get()) { | 347 !encrypted_resource.get()) { |
| 348 return false; | 348 return false; |
| 349 } | 349 } |
| 350 ScopedPPResource pp_resource(encrypted_resource.get()); | 350 ScopedPPResource pp_resource(encrypted_resource.get()); |
| 351 | 351 |
| 352 const uint32_t request_id = next_decryption_request_id_++; | 352 const uint32_t request_id = next_decryption_request_id_++; |
| 353 DVLOG(2) << "Decrypt() - request_id " << request_id; | 353 DVLOG(2) << "Decrypt() - request_id " << request_id; |
| 354 | 354 |
| 355 PP_EncryptedBlockInfo block_info = {}; | 355 PP_EncryptedBlockInfo block_info = {}; |
| 356 DCHECK(encrypted_buffer->GetDecryptConfig()); | 356 DCHECK(encrypted_buffer->decrypt_config()); |
| 357 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { | 357 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { |
| 358 return false; | 358 return false; |
| 359 } | 359 } |
| 360 | 360 |
| 361 // There is only one pending decrypt request at any time per stream. This is | 361 // There is only one pending decrypt request at any time per stream. This is |
| 362 // enforced by the media pipeline. | 362 // enforced by the media pipeline. |
| 363 switch (stream_type) { | 363 switch (stream_type) { |
| 364 case media::Decryptor::kAudio: | 364 case media::Decryptor::kAudio: |
| 365 DCHECK_EQ(pending_audio_decrypt_request_id_, 0u); | 365 DCHECK_EQ(pending_audio_decrypt_request_id_, 0u); |
| 366 DCHECK(pending_audio_decrypt_cb_.is_null()); | 366 DCHECK(pending_audio_decrypt_cb_.is_null()); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 510 // |audio_input_resource_| is not being used by the plugin now | 510 // |audio_input_resource_| is not being used by the plugin now |
| 511 // because there is only one pending audio decode request at any time. | 511 // because there is only one pending audio decode request at any time. |
| 512 // This is enforced by the media pipeline. | 512 // This is enforced by the media pipeline. |
| 513 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; | 513 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; |
| 514 if (!MakeMediaBufferResource(media::Decryptor::kAudio, encrypted_buffer, | 514 if (!MakeMediaBufferResource(media::Decryptor::kAudio, encrypted_buffer, |
| 515 &encrypted_resource)) { | 515 &encrypted_resource)) { |
| 516 return false; | 516 return false; |
| 517 } | 517 } |
| 518 | 518 |
| 519 // The resource should not be NULL for non-EOS buffer. | 519 // The resource should not be NULL for non-EOS buffer. |
| 520 if (!encrypted_buffer->IsEndOfStream() && !encrypted_resource.get()) | 520 if (!encrypted_buffer->end_of_stream() && !encrypted_resource.get()) |
| 521 return false; | 521 return false; |
| 522 | 522 |
| 523 const uint32_t request_id = next_decryption_request_id_++; | 523 const uint32_t request_id = next_decryption_request_id_++; |
| 524 DVLOG(2) << "DecryptAndDecodeAudio() - request_id " << request_id; | 524 DVLOG(2) << "DecryptAndDecodeAudio() - request_id " << request_id; |
| 525 | 525 |
| 526 PP_EncryptedBlockInfo block_info = {}; | 526 PP_EncryptedBlockInfo block_info = {}; |
| 527 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { | 527 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { |
| 528 return false; | 528 return false; |
| 529 } | 529 } |
| 530 | 530 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 551 // |video_input_resource_| is not being used by the plugin now | 551 // |video_input_resource_| is not being used by the plugin now |
| 552 // because there is only one pending video decode request at any time. | 552 // because there is only one pending video decode request at any time. |
| 553 // This is enforced by the media pipeline. | 553 // This is enforced by the media pipeline. |
| 554 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; | 554 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; |
| 555 if (!MakeMediaBufferResource(media::Decryptor::kVideo, encrypted_buffer, | 555 if (!MakeMediaBufferResource(media::Decryptor::kVideo, encrypted_buffer, |
| 556 &encrypted_resource)) { | 556 &encrypted_resource)) { |
| 557 return false; | 557 return false; |
| 558 } | 558 } |
| 559 | 559 |
| 560 // The resource should not be 0 for non-EOS buffer. | 560 // The resource should not be 0 for non-EOS buffer. |
| 561 if (!encrypted_buffer->IsEndOfStream() && !encrypted_resource.get()) | 561 if (!encrypted_buffer->end_of_stream() && !encrypted_resource.get()) |
| 562 return false; | 562 return false; |
| 563 | 563 |
| 564 const uint32_t request_id = next_decryption_request_id_++; | 564 const uint32_t request_id = next_decryption_request_id_++; |
| 565 DVLOG(2) << "DecryptAndDecodeVideo() - request_id " << request_id; | 565 DVLOG(2) << "DecryptAndDecodeVideo() - request_id " << request_id; |
| 566 TRACE_EVENT_ASYNC_BEGIN0( | 566 TRACE_EVENT_ASYNC_BEGIN0( |
| 567 "eme", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id); | 567 "eme", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id); |
| 568 | 568 |
| 569 PP_EncryptedBlockInfo block_info = {}; | 569 PP_EncryptedBlockInfo block_info = {}; |
| 570 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { | 570 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { |
| 571 return false; | 571 return false; |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 737 mapper.size() < block_info->data_size) { | 737 mapper.size() < block_info->data_size) { |
| 738 decrypt_cb.Run(media::Decryptor::kError, NULL); | 738 decrypt_cb.Run(media::Decryptor::kError, NULL); |
| 739 return; | 739 return; |
| 740 } | 740 } |
| 741 | 741 |
| 742 // TODO(tomfinegan): Find a way to take ownership of the shared memory | 742 // TODO(tomfinegan): Find a way to take ownership of the shared memory |
| 743 // managed by the PPB_Buffer_Dev, and avoid the extra copy. | 743 // managed by the PPB_Buffer_Dev, and avoid the extra copy. |
| 744 scoped_refptr<media::DecoderBuffer> decrypted_buffer( | 744 scoped_refptr<media::DecoderBuffer> decrypted_buffer( |
| 745 media::DecoderBuffer::CopyFrom(static_cast<uint8*>(mapper.data()), | 745 media::DecoderBuffer::CopyFrom(static_cast<uint8*>(mapper.data()), |
| 746 block_info->data_size)); | 746 block_info->data_size)); |
| 747 decrypted_buffer->SetTimestamp( | 747 decrypted_buffer->set_timestamp( |
| 748 base::TimeDelta::FromMicroseconds(block_info->tracking_info.timestamp)); | 748 base::TimeDelta::FromMicroseconds(block_info->tracking_info.timestamp)); |
| 749 decrypt_cb.Run(media::Decryptor::kSuccess, decrypted_buffer); | 749 decrypt_cb.Run(media::Decryptor::kSuccess, decrypted_buffer); |
| 750 } | 750 } |
| 751 | 751 |
| 752 // Use a non-class-member function here so that if for some reason | 752 // Use a non-class-member function here so that if for some reason |
| 753 // ContentDecryptorDelegate is destroyed before VideoFrame calls this callback, | 753 // ContentDecryptorDelegate is destroyed before VideoFrame calls this callback, |
| 754 // we can still get the shared memory unmapped. | 754 // we can still get the shared memory unmapped. |
| 755 static void BufferNoLongerNeeded( | 755 static void BufferNoLongerNeeded( |
| 756 const scoped_refptr<PPB_Buffer_Impl>& ppb_buffer, | 756 const scoped_refptr<PPB_Buffer_Impl>& ppb_buffer, |
| 757 base::Closure buffer_no_longer_needed_cb) { | 757 base::Closure buffer_no_longer_needed_cb) { |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 913 } | 913 } |
| 914 } | 914 } |
| 915 | 915 |
| 916 bool ContentDecryptorDelegate::MakeMediaBufferResource( | 916 bool ContentDecryptorDelegate::MakeMediaBufferResource( |
| 917 media::Decryptor::StreamType stream_type, | 917 media::Decryptor::StreamType stream_type, |
| 918 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, | 918 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, |
| 919 scoped_refptr<PPB_Buffer_Impl>* resource) { | 919 scoped_refptr<PPB_Buffer_Impl>* resource) { |
| 920 TRACE_EVENT0("eme", "ContentDecryptorDelegate::MakeMediaBufferResource"); | 920 TRACE_EVENT0("eme", "ContentDecryptorDelegate::MakeMediaBufferResource"); |
| 921 | 921 |
| 922 // End of stream buffers are represented as null resources. | 922 // End of stream buffers are represented as null resources. |
| 923 if (encrypted_buffer->IsEndOfStream()) { | 923 if (encrypted_buffer->end_of_stream()) { |
| 924 *resource = NULL; | 924 *resource = NULL; |
| 925 return true; | 925 return true; |
| 926 } | 926 } |
| 927 | 927 |
| 928 DCHECK(stream_type == media::Decryptor::kAudio || | 928 DCHECK(stream_type == media::Decryptor::kAudio || |
| 929 stream_type == media::Decryptor::kVideo); | 929 stream_type == media::Decryptor::kVideo); |
| 930 scoped_refptr<PPB_Buffer_Impl>& media_resource = | 930 scoped_refptr<PPB_Buffer_Impl>& media_resource = |
| 931 (stream_type == media::Decryptor::kAudio) ? audio_input_resource_ | 931 (stream_type == media::Decryptor::kAudio) ? audio_input_resource_ |
| 932 : video_input_resource_; | 932 : video_input_resource_; |
| 933 | 933 |
| 934 const size_t data_size = static_cast<size_t>(encrypted_buffer->GetDataSize()); | 934 const size_t data_size = static_cast<size_t>(encrypted_buffer->data_size()); |
| 935 if (!media_resource.get() || media_resource->size() < data_size) { | 935 if (!media_resource.get() || media_resource->size() < data_size) { |
| 936 // Either the buffer hasn't been created yet, or we have one that isn't big | 936 // Either the buffer hasn't been created yet, or we have one that isn't big |
| 937 // enough to fit |size| bytes. | 937 // enough to fit |size| bytes. |
| 938 | 938 |
| 939 // Media resource size starts from |kMinimumMediaBufferSize| and grows | 939 // Media resource size starts from |kMinimumMediaBufferSize| and grows |
| 940 // exponentially to avoid frequent re-allocation of PPB_Buffer_Impl, | 940 // exponentially to avoid frequent re-allocation of PPB_Buffer_Impl, |
| 941 // which is usually expensive. Since input media buffers are compressed, | 941 // which is usually expensive. Since input media buffers are compressed, |
| 942 // they are usually small (compared to outputs). The over-allocated memory | 942 // they are usually small (compared to outputs). The over-allocated memory |
| 943 // should be negligible. | 943 // should be negligible. |
| 944 const uint32_t kMinimumMediaBufferSize = 1024; | 944 const uint32_t kMinimumMediaBufferSize = 1024; |
| 945 uint32_t media_resource_size = | 945 uint32_t media_resource_size = |
| 946 media_resource.get() ? media_resource->size() : kMinimumMediaBufferSize; | 946 media_resource.get() ? media_resource->size() : kMinimumMediaBufferSize; |
| 947 while (media_resource_size < data_size) media_resource_size *= 2; | 947 while (media_resource_size < data_size) media_resource_size *= 2; |
| 948 | 948 |
| 949 DVLOG(2) << "Size of media buffer for " | 949 DVLOG(2) << "Size of media buffer for " |
| 950 << ((stream_type == media::Decryptor::kAudio) ? "audio" : "video") | 950 << ((stream_type == media::Decryptor::kAudio) ? "audio" : "video") |
| 951 << " stream bumped to " << media_resource_size | 951 << " stream bumped to " << media_resource_size |
| 952 << " bytes to fit input."; | 952 << " bytes to fit input."; |
| 953 media_resource = | 953 media_resource = |
| 954 PPB_Buffer_Impl::CreateResource(pp_instance_, media_resource_size); | 954 PPB_Buffer_Impl::CreateResource(pp_instance_, media_resource_size); |
| 955 if (!media_resource.get()) | 955 if (!media_resource.get()) |
| 956 return false; | 956 return false; |
| 957 } | 957 } |
| 958 | 958 |
| 959 BufferAutoMapper mapper(media_resource.get()); | 959 BufferAutoMapper mapper(media_resource.get()); |
| 960 if (!mapper.data() || mapper.size() < data_size) { | 960 if (!mapper.data() || mapper.size() < data_size) { |
| 961 media_resource = NULL; | 961 media_resource = NULL; |
| 962 return false; | 962 return false; |
| 963 } | 963 } |
| 964 memcpy(mapper.data(), encrypted_buffer->GetData(), data_size); | 964 memcpy(mapper.data(), encrypted_buffer->data(), data_size); |
| 965 | 965 |
| 966 *resource = media_resource; | 966 *resource = media_resource; |
| 967 return true; | 967 return true; |
| 968 } | 968 } |
| 969 | 969 |
| 970 void ContentDecryptorDelegate::FreeBuffer(uint32_t buffer_id) { | 970 void ContentDecryptorDelegate::FreeBuffer(uint32_t buffer_id) { |
| 971 if (buffer_id) | 971 if (buffer_id) |
| 972 free_buffers_.push(buffer_id); | 972 free_buffers_.push(buffer_id); |
| 973 } | 973 } |
| 974 | 974 |
| 975 void ContentDecryptorDelegate::SetBufferToFreeInTrackingInfo( | 975 void ContentDecryptorDelegate::SetBufferToFreeInTrackingInfo( |
| 976 PP_DecryptTrackingInfo* tracking_info) { | 976 PP_DecryptTrackingInfo* tracking_info) { |
| 977 DCHECK_EQ(tracking_info->buffer_id, 0u); | 977 DCHECK_EQ(tracking_info->buffer_id, 0u); |
| 978 | 978 |
| 979 if (free_buffers_.empty()) | 979 if (free_buffers_.empty()) |
| 980 return; | 980 return; |
| 981 | 981 |
| 982 tracking_info->buffer_id = free_buffers_.front(); | 982 tracking_info->buffer_id = free_buffers_.front(); |
| 983 free_buffers_.pop(); | 983 free_buffers_.pop(); |
| 984 } | 984 } |
| 985 | 985 |
| 986 } // namespace ppapi | 986 } // namespace ppapi |
| 987 } // namespace webkit | 987 } // namespace webkit |
| OLD | NEW |