| 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 // otherwise. | 80 // otherwise. |
| 81 static bool MakeEncryptedBlockInfo( | 81 static bool MakeEncryptedBlockInfo( |
| 82 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, | 82 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, |
| 83 uint32_t request_id, PP_EncryptedBlockInfo* block_info) { | 83 uint32_t request_id, PP_EncryptedBlockInfo* block_info) { |
| 84 // TODO(xhwang): Fix initialization of PP_EncryptedBlockInfo here and | 84 // TODO(xhwang): Fix initialization of PP_EncryptedBlockInfo here and |
| 85 // anywhere else. | 85 // anywhere else. |
| 86 memset(block_info, 0, sizeof(*block_info)); | 86 memset(block_info, 0, sizeof(*block_info)); |
| 87 block_info->tracking_info.request_id = request_id; | 87 block_info->tracking_info.request_id = request_id; |
| 88 | 88 |
| 89 // EOS buffers need a request ID and nothing more. | 89 // EOS buffers need a request ID and nothing more. |
| 90 if (encrypted_buffer->IsEndOfStream()) return true; | 90 if (encrypted_buffer->is_end_of_stream()) return true; |
| 91 | 91 |
| 92 DCHECK(encrypted_buffer->GetDataSize()) | 92 DCHECK(encrypted_buffer->get_data_size()) |
| 93 << "DecryptConfig is set on an empty buffer"; | 93 << "DecryptConfig is set on an empty buffer"; |
| 94 | 94 |
| 95 block_info->tracking_info.timestamp = | 95 block_info->tracking_info.timestamp = |
| 96 encrypted_buffer->GetTimestamp().InMicroseconds(); | 96 encrypted_buffer->get_timestamp().InMicroseconds(); |
| 97 block_info->data_size = encrypted_buffer->GetDataSize(); | 97 block_info->data_size = encrypted_buffer->get_data_size(); |
| 98 | 98 |
| 99 const media::DecryptConfig* decrypt_config = | 99 const media::DecryptConfig* decrypt_config = |
| 100 encrypted_buffer->GetDecryptConfig(); | 100 encrypted_buffer->get_decrypt_config(); |
| 101 block_info->data_offset = decrypt_config->data_offset(); | 101 block_info->data_offset = decrypt_config->data_offset(); |
| 102 | 102 |
| 103 if (!CopyStringToArray(decrypt_config->key_id(), block_info->key_id) || | 103 if (!CopyStringToArray(decrypt_config->key_id(), block_info->key_id) || |
| 104 !CopyStringToArray(decrypt_config->iv(), block_info->iv)) | 104 !CopyStringToArray(decrypt_config->iv(), block_info->iv)) |
| 105 return false; | 105 return false; |
| 106 | 106 |
| 107 block_info->key_id_size = decrypt_config->key_id().size(); | 107 block_info->key_id_size = decrypt_config->key_id().size(); |
| 108 block_info->iv_size = decrypt_config->iv().size(); | 108 block_info->iv_size = decrypt_config->iv().size(); |
| 109 | 109 |
| 110 if (decrypt_config->subsamples().size() > arraysize(block_info->subsamples)) | 110 if (decrypt_config->subsamples().size() > arraysize(block_info->subsamples)) |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 &encrypted_resource) || | 340 &encrypted_resource) || |
| 341 !encrypted_resource.get()) { | 341 !encrypted_resource.get()) { |
| 342 return false; | 342 return false; |
| 343 } | 343 } |
| 344 ScopedPPResource pp_resource(encrypted_resource.get()); | 344 ScopedPPResource pp_resource(encrypted_resource.get()); |
| 345 | 345 |
| 346 const uint32_t request_id = next_decryption_request_id_++; | 346 const uint32_t request_id = next_decryption_request_id_++; |
| 347 DVLOG(2) << "Decrypt() - request_id " << request_id; | 347 DVLOG(2) << "Decrypt() - request_id " << request_id; |
| 348 | 348 |
| 349 PP_EncryptedBlockInfo block_info = {}; | 349 PP_EncryptedBlockInfo block_info = {}; |
| 350 DCHECK(encrypted_buffer->GetDecryptConfig()); | 350 DCHECK(encrypted_buffer->get_decrypt_config()); |
| 351 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { | 351 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { |
| 352 return false; | 352 return false; |
| 353 } | 353 } |
| 354 | 354 |
| 355 // There is only one pending decrypt request at any time per stream. This is | 355 // There is only one pending decrypt request at any time per stream. This is |
| 356 // enforced by the media pipeline. | 356 // enforced by the media pipeline. |
| 357 switch (stream_type) { | 357 switch (stream_type) { |
| 358 case media::Decryptor::kAudio: | 358 case media::Decryptor::kAudio: |
| 359 DCHECK_EQ(pending_audio_decrypt_request_id_, 0u); | 359 DCHECK_EQ(pending_audio_decrypt_request_id_, 0u); |
| 360 DCHECK(pending_audio_decrypt_cb_.is_null()); | 360 DCHECK(pending_audio_decrypt_cb_.is_null()); |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 // |audio_input_resource_| is not being used by the plugin now | 503 // |audio_input_resource_| is not being used by the plugin now |
| 504 // because there is only one pending audio decode request at any time. | 504 // because there is only one pending audio decode request at any time. |
| 505 // This is enforced by the media pipeline. | 505 // This is enforced by the media pipeline. |
| 506 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; | 506 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; |
| 507 if (!MakeMediaBufferResource(media::Decryptor::kAudio, encrypted_buffer, | 507 if (!MakeMediaBufferResource(media::Decryptor::kAudio, encrypted_buffer, |
| 508 &encrypted_resource)) { | 508 &encrypted_resource)) { |
| 509 return false; | 509 return false; |
| 510 } | 510 } |
| 511 | 511 |
| 512 // The resource should not be NULL for non-EOS buffer. | 512 // The resource should not be NULL for non-EOS buffer. |
| 513 if (!encrypted_buffer->IsEndOfStream() && !encrypted_resource.get()) | 513 if (!encrypted_buffer->is_end_of_stream() && !encrypted_resource.get()) |
| 514 return false; | 514 return false; |
| 515 | 515 |
| 516 const uint32_t request_id = next_decryption_request_id_++; | 516 const uint32_t request_id = next_decryption_request_id_++; |
| 517 DVLOG(2) << "DecryptAndDecodeAudio() - request_id " << request_id; | 517 DVLOG(2) << "DecryptAndDecodeAudio() - request_id " << request_id; |
| 518 | 518 |
| 519 PP_EncryptedBlockInfo block_info = {}; | 519 PP_EncryptedBlockInfo block_info = {}; |
| 520 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { | 520 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { |
| 521 return false; | 521 return false; |
| 522 } | 522 } |
| 523 | 523 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 544 // |video_input_resource_| is not being used by the plugin now | 544 // |video_input_resource_| is not being used by the plugin now |
| 545 // because there is only one pending video decode request at any time. | 545 // because there is only one pending video decode request at any time. |
| 546 // This is enforced by the media pipeline. | 546 // This is enforced by the media pipeline. |
| 547 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; | 547 scoped_refptr<PPB_Buffer_Impl> encrypted_resource; |
| 548 if (!MakeMediaBufferResource(media::Decryptor::kVideo, encrypted_buffer, | 548 if (!MakeMediaBufferResource(media::Decryptor::kVideo, encrypted_buffer, |
| 549 &encrypted_resource)) { | 549 &encrypted_resource)) { |
| 550 return false; | 550 return false; |
| 551 } | 551 } |
| 552 | 552 |
| 553 // The resource should not be 0 for non-EOS buffer. | 553 // The resource should not be 0 for non-EOS buffer. |
| 554 if (!encrypted_buffer->IsEndOfStream() && !encrypted_resource.get()) | 554 if (!encrypted_buffer->is_end_of_stream() && !encrypted_resource.get()) |
| 555 return false; | 555 return false; |
| 556 | 556 |
| 557 const uint32_t request_id = next_decryption_request_id_++; | 557 const uint32_t request_id = next_decryption_request_id_++; |
| 558 DVLOG(2) << "DecryptAndDecodeVideo() - request_id " << request_id; | 558 DVLOG(2) << "DecryptAndDecodeVideo() - request_id " << request_id; |
| 559 TRACE_EVENT_ASYNC_BEGIN0( | 559 TRACE_EVENT_ASYNC_BEGIN0( |
| 560 "eme", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id); | 560 "eme", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id); |
| 561 | 561 |
| 562 PP_EncryptedBlockInfo block_info = {}; | 562 PP_EncryptedBlockInfo block_info = {}; |
| 563 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { | 563 if (!MakeEncryptedBlockInfo(encrypted_buffer, request_id, &block_info)) { |
| 564 return false; | 564 return false; |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 725 BufferAutoMapper mapper(enter.object()); | 725 BufferAutoMapper mapper(enter.object()); |
| 726 if (!mapper.data() || !mapper.size() || | 726 if (!mapper.data() || !mapper.size() || |
| 727 mapper.size() < block_info->data_size) { | 727 mapper.size() < block_info->data_size) { |
| 728 decrypt_cb.Run(media::Decryptor::kError, NULL); | 728 decrypt_cb.Run(media::Decryptor::kError, NULL); |
| 729 return; | 729 return; |
| 730 } | 730 } |
| 731 | 731 |
| 732 // TODO(tomfinegan): Find a way to take ownership of the shared memory | 732 // TODO(tomfinegan): Find a way to take ownership of the shared memory |
| 733 // managed by the PPB_Buffer_Dev, and avoid the extra copy. | 733 // managed by the PPB_Buffer_Dev, and avoid the extra copy. |
| 734 scoped_refptr<media::DecoderBuffer> decrypted_buffer( | 734 scoped_refptr<media::DecoderBuffer> decrypted_buffer( |
| 735 media::DecoderBuffer::CopyFrom(static_cast<uint8*>(mapper.data()), | 735 media::DecoderBuffer::copy_from(static_cast<uint8*>(mapper.data()), |
| 736 block_info->data_size)); | 736 block_info->data_size)); |
| 737 decrypted_buffer->SetTimestamp( | 737 decrypted_buffer->set_timestamp( |
| 738 base::TimeDelta::FromMicroseconds(block_info->tracking_info.timestamp)); | 738 base::TimeDelta::FromMicroseconds(block_info->tracking_info.timestamp)); |
| 739 decrypt_cb.Run(media::Decryptor::kSuccess, decrypted_buffer); | 739 decrypt_cb.Run(media::Decryptor::kSuccess, decrypted_buffer); |
| 740 } | 740 } |
| 741 | 741 |
| 742 // Use a non-class-member function here so that if for some reason | 742 // Use a non-class-member function here so that if for some reason |
| 743 // ContentDecryptorDelegate is destroyed before VideoFrame calls this callback, | 743 // ContentDecryptorDelegate is destroyed before VideoFrame calls this callback, |
| 744 // we can still get the shared memory unmapped. | 744 // we can still get the shared memory unmapped. |
| 745 static void BufferNoLongerNeeded( | 745 static void BufferNoLongerNeeded( |
| 746 const scoped_refptr<PPB_Buffer_Impl>& ppb_buffer, | 746 const scoped_refptr<PPB_Buffer_Impl>& ppb_buffer, |
| 747 base::Closure buffer_no_longer_needed_cb) { | 747 base::Closure buffer_no_longer_needed_cb) { |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 901 } | 901 } |
| 902 } | 902 } |
| 903 | 903 |
| 904 bool ContentDecryptorDelegate::MakeMediaBufferResource( | 904 bool ContentDecryptorDelegate::MakeMediaBufferResource( |
| 905 media::Decryptor::StreamType stream_type, | 905 media::Decryptor::StreamType stream_type, |
| 906 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, | 906 const scoped_refptr<media::DecoderBuffer>& encrypted_buffer, |
| 907 scoped_refptr<PPB_Buffer_Impl>* resource) { | 907 scoped_refptr<PPB_Buffer_Impl>* resource) { |
| 908 TRACE_EVENT0("eme", "ContentDecryptorDelegate::MakeMediaBufferResource"); | 908 TRACE_EVENT0("eme", "ContentDecryptorDelegate::MakeMediaBufferResource"); |
| 909 | 909 |
| 910 // End of stream buffers are represented as null resources. | 910 // End of stream buffers are represented as null resources. |
| 911 if (encrypted_buffer->IsEndOfStream()) { | 911 if (encrypted_buffer->is_end_of_stream()) { |
| 912 *resource = NULL; | 912 *resource = NULL; |
| 913 return true; | 913 return true; |
| 914 } | 914 } |
| 915 | 915 |
| 916 DCHECK(stream_type == media::Decryptor::kAudio || | 916 DCHECK(stream_type == media::Decryptor::kAudio || |
| 917 stream_type == media::Decryptor::kVideo); | 917 stream_type == media::Decryptor::kVideo); |
| 918 scoped_refptr<PPB_Buffer_Impl>& media_resource = | 918 scoped_refptr<PPB_Buffer_Impl>& media_resource = |
| 919 (stream_type == media::Decryptor::kAudio) ? audio_input_resource_ | 919 (stream_type == media::Decryptor::kAudio) ? audio_input_resource_ |
| 920 : video_input_resource_; | 920 : video_input_resource_; |
| 921 | 921 |
| 922 const size_t data_size = static_cast<size_t>(encrypted_buffer->GetDataSize()); | 922 const size_t data_size = static_cast<size_t>(encrypted_buffer->get_data_size()
); |
| 923 if (!media_resource.get() || media_resource->size() < data_size) { | 923 if (!media_resource.get() || media_resource->size() < data_size) { |
| 924 // Either the buffer hasn't been created yet, or we have one that isn't big | 924 // Either the buffer hasn't been created yet, or we have one that isn't big |
| 925 // enough to fit |size| bytes. | 925 // enough to fit |size| bytes. |
| 926 | 926 |
| 927 // Media resource size starts from |kMinimumMediaBufferSize| and grows | 927 // Media resource size starts from |kMinimumMediaBufferSize| and grows |
| 928 // exponentially to avoid frequent re-allocation of PPB_Buffer_Impl, | 928 // exponentially to avoid frequent re-allocation of PPB_Buffer_Impl, |
| 929 // which is usually expensive. Since input media buffers are compressed, | 929 // which is usually expensive. Since input media buffers are compressed, |
| 930 // they are usually small (compared to outputs). The over-allocated memory | 930 // they are usually small (compared to outputs). The over-allocated memory |
| 931 // should be negligible. | 931 // should be negligible. |
| 932 const uint32_t kMinimumMediaBufferSize = 1024; | 932 const uint32_t kMinimumMediaBufferSize = 1024; |
| 933 uint32_t media_resource_size = | 933 uint32_t media_resource_size = |
| 934 media_resource.get() ? media_resource->size() : kMinimumMediaBufferSize; | 934 media_resource.get() ? media_resource->size() : kMinimumMediaBufferSize; |
| 935 while (media_resource_size < data_size) media_resource_size *= 2; | 935 while (media_resource_size < data_size) media_resource_size *= 2; |
| 936 | 936 |
| 937 DVLOG(2) << "Size of media buffer for " | 937 DVLOG(2) << "Size of media buffer for " |
| 938 << ((stream_type == media::Decryptor::kAudio) ? "audio" : "video") | 938 << ((stream_type == media::Decryptor::kAudio) ? "audio" : "video") |
| 939 << " stream bumped to " << media_resource_size | 939 << " stream bumped to " << media_resource_size |
| 940 << " bytes to fit input."; | 940 << " bytes to fit input."; |
| 941 media_resource = | 941 media_resource = |
| 942 PPB_Buffer_Impl::CreateResource(pp_instance_, media_resource_size); | 942 PPB_Buffer_Impl::CreateResource(pp_instance_, media_resource_size); |
| 943 if (!media_resource.get()) return false; | 943 if (!media_resource.get()) return false; |
| 944 } | 944 } |
| 945 | 945 |
| 946 BufferAutoMapper mapper(media_resource.get()); | 946 BufferAutoMapper mapper(media_resource.get()); |
| 947 if (!mapper.data() || mapper.size() < data_size) { | 947 if (!mapper.data() || mapper.size() < data_size) { |
| 948 media_resource = NULL; | 948 media_resource = NULL; |
| 949 return false; | 949 return false; |
| 950 } | 950 } |
| 951 memcpy(mapper.data(), encrypted_buffer->GetData(), data_size); | 951 memcpy(mapper.data(), encrypted_buffer->get_data(), data_size); |
| 952 | 952 |
| 953 *resource = media_resource; | 953 *resource = media_resource; |
| 954 return true; | 954 return true; |
| 955 } | 955 } |
| 956 | 956 |
| 957 void ContentDecryptorDelegate::FreeBuffer(uint32_t buffer_id) { | 957 void ContentDecryptorDelegate::FreeBuffer(uint32_t buffer_id) { |
| 958 if (buffer_id) free_buffers_.push(buffer_id); | 958 if (buffer_id) free_buffers_.push(buffer_id); |
| 959 } | 959 } |
| 960 | 960 |
| 961 void ContentDecryptorDelegate::SetBufferToFreeInTrackingInfo( | 961 void ContentDecryptorDelegate::SetBufferToFreeInTrackingInfo( |
| 962 PP_DecryptTrackingInfo* tracking_info) { | 962 PP_DecryptTrackingInfo* tracking_info) { |
| 963 DCHECK_EQ(tracking_info->buffer_id, 0u); | 963 DCHECK_EQ(tracking_info->buffer_id, 0u); |
| 964 | 964 |
| 965 if (free_buffers_.empty()) return; | 965 if (free_buffers_.empty()) return; |
| 966 | 966 |
| 967 tracking_info->buffer_id = free_buffers_.front(); | 967 tracking_info->buffer_id = free_buffers_.front(); |
| 968 free_buffers_.pop(); | 968 free_buffers_.pop(); |
| 969 } | 969 } |
| 970 | 970 |
| 971 } // namespace ppapi | 971 } // namespace ppapi |
| 972 } // namespace webkit | 972 } // namespace webkit |
| OLD | NEW |