summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authorxhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-19 23:33:32 +0000
committerxhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-19 23:33:32 +0000
commita99db32f764f2b093356baa664877a9d90522f96 (patch)
tree93519878b5eafce07903b16f84d9487d4b6798fa /webkit
parentc8148d4be6a8a7045fc9320571ecb4b6db21da9a (diff)
downloadchromium_src-a99db32f764f2b093356baa664877a9d90522f96.zip
chromium_src-a99db32f764f2b093356baa664877a9d90522f96.tar.gz
chromium_src-a99db32f764f2b093356baa664877a9d90522f96.tar.bz2
Reuse PPB_Buffer_Impl in ContentDecryptorDelegate.
PPB_Buffer_Impl wraps shared memory which is expensive to allocate. Allocating shared memory involved an sync IPC to to browser. To reduce the latency caused by this, reuse PPB_Buffer_Impl in ContentDecryptorDelegate for audio and video streams. Test on Linux (Ubuntu 10.04) shows that this change reduces the time to MakeBufferResource() from 0.543ms to 0.040 ms per frame. The difference can be larger on slower platforms. BUG=none TEST=none Review URL: https://chromiumcodereview.appspot.com/11411053 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@168632 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r--webkit/plugins/ppapi/content_decryptor_delegate.cc111
-rw-r--r--webkit/plugins/ppapi/content_decryptor_delegate.h20
2 files changed, 115 insertions, 16 deletions
diff --git a/webkit/plugins/ppapi/content_decryptor_delegate.cc b/webkit/plugins/ppapi/content_decryptor_delegate.cc
index a799cc0..650d1c4 100644
--- a/webkit/plugins/ppapi/content_decryptor_delegate.cc
+++ b/webkit/plugins/ppapi/content_decryptor_delegate.cc
@@ -14,7 +14,6 @@
#include "media/base/video_decoder_config.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
-#include "ppapi/shared_impl/scoped_pp_resource.h"
#include "ppapi/shared_impl/var.h"
#include "ppapi/shared_impl/var_tracker.h"
#include "ppapi/thunk/enter.h"
@@ -39,6 +38,7 @@ namespace {
bool MakeBufferResource(PP_Instance instance,
const uint8* data, int size,
ScopedPPResource* resource) {
+ TRACE_EVENT0("eme", "ContentDecryptorDelegate - MakeBufferResource");
DCHECK(resource);
if (!data || !size) {
@@ -274,7 +274,9 @@ ContentDecryptorDelegate::ContentDecryptorDelegate(
pending_audio_decoder_init_request_id_(0),
pending_video_decoder_init_request_id_(0),
pending_audio_decode_request_id_(0),
- pending_video_decode_request_id_(0) {
+ pending_video_decode_request_id_(0),
+ audio_input_resource_size_(0),
+ video_input_resource_size_(0) {
}
void ContentDecryptorDelegate::set_decrypt_client(
@@ -335,11 +337,14 @@ bool ContentDecryptorDelegate::Decrypt(
const scoped_refptr<media::DecoderBuffer>& encrypted_buffer,
const media::Decryptor::DecryptCB& decrypt_cb) {
DVLOG(3) << "Decrypt() - stream_type: " << stream_type;
+ // |{audio|video}_input_resource_[size_]| is not being used by the plugin
+ // now because there is only one pending audio/video decrypt request at any
+ // time. This is enforced by the media pipeline.
ScopedPPResource encrypted_resource;
- if (!MakeBufferResource(pp_instance_,
- encrypted_buffer->GetData(),
- encrypted_buffer->GetDataSize(),
- &encrypted_resource) ||
+ if (!MakeMediaBufferResource(stream_type,
+ encrypted_buffer->GetData(),
+ encrypted_buffer->GetDataSize(),
+ &encrypted_resource) ||
!encrypted_resource.get()) {
return false;
}
@@ -499,11 +504,14 @@ bool ContentDecryptorDelegate::DecryptAndDecodeAudio(
// If |encrypted_buffer| is end-of-stream buffer, GetData() and GetDataSize()
// return NULL and 0 respectively. In that case, we'll just create a 0
// resource.
+ // |audio_input_resource_size_| is not being used by the plugin now
+ // because there is only one pending audio decode request at any time.
+ // This is enforced by the media pipeline.
ScopedPPResource encrypted_resource;
- if (!MakeBufferResource(pp_instance_,
- encrypted_buffer->GetData(),
- encrypted_buffer->GetDataSize(),
- &encrypted_resource)) {
+ if (!MakeMediaBufferResource(media::Decryptor::kAudio,
+ encrypted_buffer->GetData(),
+ encrypted_buffer->GetDataSize(),
+ &encrypted_resource)) {
return false;
}
@@ -543,11 +551,14 @@ bool ContentDecryptorDelegate::DecryptAndDecodeVideo(
// If |encrypted_buffer| is end-of-stream buffer, GetData() and GetDataSize()
// return NULL and 0 respectively. In that case, we'll just create a 0
// resource.
+ // |video_input_resource_size_| is not being used by the plugin now
+ // because there is only one pending video decode request at any time.
+ // This is enforced by the media pipeline.
ScopedPPResource encrypted_resource;
- if (!MakeBufferResource(pp_instance_,
- encrypted_buffer->GetData(),
- encrypted_buffer->GetDataSize(),
- &encrypted_resource)) {
+ if (!MakeMediaBufferResource(media::Decryptor::kVideo,
+ encrypted_buffer->GetData(),
+ encrypted_buffer->GetDataSize(),
+ &encrypted_resource)) {
return false;
}
@@ -558,7 +569,7 @@ bool ContentDecryptorDelegate::DecryptAndDecodeVideo(
const uint32_t request_id = next_decryption_request_id_++;
DVLOG(2) << "DecryptAndDecodeVideo() - request_id " << request_id;
TRACE_EVENT_ASYNC_BEGIN0(
- "eme", "PluginInstance::DecryptAndDecodeVideo", request_id);
+ "eme", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id);
PP_EncryptedBlockInfo block_info;
if (!MakeEncryptedBlockInfo(
@@ -772,7 +783,7 @@ void ContentDecryptorDelegate::DeliverFrame(
}
TRACE_EVENT_ASYNC_END0(
- "eme", "PluginInstance::DecryptAndDecodeVideo", request_id);
+ "eme", "ContentDecryptorDelegate::DecryptAndDecodeVideo", request_id);
DCHECK(!pending_video_decode_cb_.is_null());
pending_video_decode_request_id_ = 0;
@@ -890,5 +901,73 @@ void ContentDecryptorDelegate::CancelDecode(
}
}
+bool ContentDecryptorDelegate::MakeMediaBufferResource(
+ media::Decryptor::StreamType stream_type,
+ const uint8* data, int size,
+ ScopedPPResource* resource) {
+ TRACE_EVENT0("eme", "ContentDecryptorDelegate::MakeMediaBufferResource");
+
+ DCHECK(resource);
+
+ if (!data || !size) {
+ DCHECK(!data && !size);
+ resource->Release();
+ return true;
+ }
+
+ DCHECK(stream_type == media::Decryptor::kAudio ||
+ stream_type == media::Decryptor::kVideo);
+ ScopedPPResource& media_resource = (stream_type == media::Decryptor::kAudio) ?
+ audio_input_resource_ : video_input_resource_;
+ int& media_resource_size = (stream_type == media::Decryptor::kAudio) ?
+ audio_input_resource_size_ : video_input_resource_size_;
+
+ if (media_resource_size < size) {
+ // Media resource size starts from |kMinimumMediaBufferSize| and grows
+ // exponentially to avoid frequent re-allocation of PPB_Buffer_Impl,
+ // which is usually expensive. Since input media buffers are compressed,
+ // they are usually small (compared to outputs). The over-allocated memory
+ // should be negligible.
+
+ if (media_resource_size == 0) {
+ const int kMinimumMediaBufferSize = 1024;
+ media_resource_size = kMinimumMediaBufferSize;
+ }
+
+ while (media_resource_size < size)
+ media_resource_size *= 2;
+
+ DVLOG(2) << "Size of media buffer for "
+ << ((stream_type == media::Decryptor::kAudio) ? "audio" : "video")
+ << " stream bumped to " << media_resource_size
+ << " bytes to fit input.";
+ media_resource = ScopedPPResource(
+ ScopedPPResource::PassRef(),
+ PPB_Buffer_Impl::Create(pp_instance_, media_resource_size));
+ if (!media_resource.get()) {
+ media_resource_size = 0;
+ return false;
+ }
+ }
+
+ EnterResourceNoLock<PPB_Buffer_API> enter(media_resource, true);
+ if (enter.failed()) {
+ media_resource.Release();
+ media_resource_size = 0;
+ return false;
+ }
+
+ BufferAutoMapper mapper(enter.object());
+ if (!mapper.data() || mapper.size() < static_cast<size_t>(size)) {
+ media_resource.Release();
+ media_resource_size = 0;
+ return false;
+ }
+ memcpy(mapper.data(), data, size);
+
+ *resource = media_resource;
+ return true;
+}
+
} // namespace ppapi
} // namespace webkit
diff --git a/webkit/plugins/ppapi/content_decryptor_delegate.h b/webkit/plugins/ppapi/content_decryptor_delegate.h
index 5b7d1a5..22f0815 100644
--- a/webkit/plugins/ppapi/content_decryptor_delegate.h
+++ b/webkit/plugins/ppapi/content_decryptor_delegate.h
@@ -13,6 +13,7 @@
#include "media/base/decryptor.h"
#include "ppapi/c/private/pp_content_decryptor.h"
#include "ppapi/c/private/ppp_content_decryptor_private.h"
+#include "ppapi/shared_impl/scoped_pp_resource.h"
#include "webkit/plugins/webkit_plugins_export.h"
namespace media {
@@ -97,6 +98,18 @@ class WEBKIT_PLUGINS_EXPORT ContentDecryptorDelegate {
// Cancels the pending decrypt-and-decode callback for |stream_type|.
void CancelDecode(media::Decryptor::StreamType stream_type);
+ // Fills |resource| with a PP_Resource containing a PPB_Buffer_Impl and
+ // copies |data| into the buffer resource. This method reuses
+ // |audio_input_resource_| and |video_input_resource_| to reduce the latency
+ // in requesting new PPB_Buffer_Impl resources. The caller must make sure that
+ // |audio_input_resource_| or |video_input_resource_| is available before
+ // calling this method.
+ // If |data| is NULL, fills |resource| with a PP_Resource with ID of 0.
+ // Returns true upon success and false if any error happened.
+ bool MakeMediaBufferResource(media::Decryptor::StreamType stream_type,
+ const uint8* data, int size,
+ ::ppapi::ScopedPPResource* resource);
+
const PP_Instance pp_instance_;
const PPP_ContentDecryptor_Private* const plugin_decryption_interface_;
@@ -126,6 +139,13 @@ class WEBKIT_PLUGINS_EXPORT ContentDecryptorDelegate {
uint32_t pending_video_decode_request_id_;
media::Decryptor::VideoDecodeCB pending_video_decode_cb_;
+ // ScopedPPResource for audio and video input buffers.
+ // See MakeMediaBufferResource.
+ ::ppapi::ScopedPPResource audio_input_resource_;
+ int audio_input_resource_size_;
+ ::ppapi::ScopedPPResource video_input_resource_;
+ int video_input_resource_size_;
+
DISALLOW_COPY_AND_ASSIGN(ContentDecryptorDelegate);
};