summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authorxhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-24 01:48:17 +0000
committerxhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-24 01:48:17 +0000
commitbf7971e5bbdb46b7aee5bf0fb106dc6bfefed158 (patch)
treefcbf5fbb921228f4e0ab24afd70fb32a09721fe9 /webkit
parent985b6727d8634737e7ffbfb1bec23cd5631f63a9 (diff)
downloadchromium_src-bf7971e5bbdb46b7aee5bf0fb106dc6bfefed158.zip
chromium_src-bf7971e5bbdb46b7aee5bf0fb106dc6bfefed158.tar.gz
chromium_src-bf7971e5bbdb46b7aee5bf0fb106dc6bfefed158.tar.bz2
Clear key CDM handles EOS buffer correctly.
BUG=none TEST=none Review URL: https://chromiumcodereview.appspot.com/11235066 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@163744 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r--webkit/media/crypto/ppapi/clear_key_cdm.cc96
-rw-r--r--webkit/media/crypto/ppapi/clear_key_cdm.h12
-rw-r--r--webkit/media/crypto/ppapi/ffmpeg_cdm_video_decoder.cc19
3 files changed, 73 insertions, 54 deletions
diff --git a/webkit/media/crypto/ppapi/clear_key_cdm.cc b/webkit/media/crypto/ppapi/clear_key_cdm.cc
index ced22e4..00a11a3 100644
--- a/webkit/media/crypto/ppapi/clear_key_cdm.cc
+++ b/webkit/media/crypto/ppapi/clear_key_cdm.cc
@@ -41,9 +41,15 @@ static bool g_cdm_module_initialized = InitializeFFmpegLibraries();
static const char kClearKeyCdmVersion[] = "0.1.0.0";
+// Copies |input_buffer| into a media::DecoderBuffer. If the |input_buffer| is
+// empty, an empty (end-of-stream) media::DecoderBuffer is returned.
static scoped_refptr<media::DecoderBuffer> CopyDecoderBufferFrom(
const cdm::InputBuffer& input_buffer) {
- DCHECK(input_buffer.data);
+ if (!input_buffer.data) {
+ DCHECK_EQ(input_buffer.data_size, 0);
+ return media::DecoderBuffer::CreateEOSBuffer();
+ }
+
// TODO(tomfinegan): Get rid of this copy.
scoped_refptr<media::DecoderBuffer> output_buffer =
media::DecoderBuffer::CopyFrom(input_buffer.data, input_buffer.data_size);
@@ -236,33 +242,21 @@ cdm::Status ClearKeyCdm::Decrypt(
const cdm::InputBuffer& encrypted_buffer,
cdm::DecryptedBlock* decrypted_block) {
DVLOG(1) << "Decrypt()";
+ DCHECK(encrypted_buffer.data);
- scoped_refptr<media::DecoderBuffer> decoder_buffer =
- CopyDecoderBufferFrom(encrypted_buffer);
-
- // Callback is called synchronously, so we can use variables on the stack.
- media::Decryptor::Status status;
scoped_refptr<media::DecoderBuffer> buffer;
- // We don't care what stream type it is here. So just pick video.
- decryptor_.Decrypt(media::Decryptor::kVideo,
- decoder_buffer,
- base::Bind(&CopyDecryptResults, &status, &buffer));
+ cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer);
- if (status == media::Decryptor::kError)
- return cdm::kDecryptError;
+ if (status != cdm::kSuccess)
+ return status;
- if (status == media::Decryptor::kNoKey)
- return cdm::kNoKey;
-
- DCHECK(buffer);
- int data_size = buffer->GetDataSize();
-
- decrypted_block->set_buffer(allocator_->Allocate(data_size));
+ DCHECK(buffer->GetData());
+ decrypted_block->set_buffer(allocator_->Allocate(buffer->GetDataSize()));
memcpy(reinterpret_cast<void*>(decrypted_block->buffer()->data()),
buffer->GetData(),
- data_size);
-
+ buffer->GetDataSize());
decrypted_block->set_timestamp(buffer->GetTimestamp().InMicroseconds());
+
return cdm::kSuccess;
}
@@ -309,35 +303,28 @@ void ClearKeyCdm::DeinitializeDecoder(cdm::StreamType decoder_type) {
cdm::Status ClearKeyCdm::DecryptAndDecodeFrame(
const cdm::InputBuffer& encrypted_buffer,
cdm::VideoFrame* decoded_frame) {
- // TODO(xhwang): Need to flush the video decoder with empty buffer.
- if (!encrypted_buffer.data)
- return cdm::kNeedMoreData;
-
- scoped_refptr<media::DecoderBuffer> decoder_buffer =
- CopyDecoderBufferFrom(encrypted_buffer);
+ DVLOG(1) << "DecryptAndDecodeFrame()";
- // Callback is called synchronously, so we can use variables on the stack.
- media::Decryptor::Status status;
scoped_refptr<media::DecoderBuffer> buffer;
- decryptor_.Decrypt(media::Decryptor::kVideo,
- decoder_buffer,
- base::Bind(&CopyDecryptResults, &status, &buffer));
+ cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer);
- if (status == media::Decryptor::kError)
- return cdm::kDecryptError;
-
- if (status == media::Decryptor::kNoKey)
- return cdm::kNoKey;
+ if (status != cdm::kSuccess)
+ return status;
#if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
- DCHECK(status == media::Decryptor::kSuccess);
+ DCHECK(status == cdm::kSuccess);
DCHECK(buffer);
return video_decoder_->DecodeFrame(buffer.get()->GetData(),
buffer->GetDataSize(),
encrypted_buffer.timestamp,
decoded_frame);
#elif defined(CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER)
- GenerateFakeVideoFrame(decoder_buffer->GetTimestamp(), decoded_frame);
+ // The fake decoder does not buffer any frames internally. So if the input is
+ // empty (EOS), just return kNeedMoreData.
+ if (buffer->IsEndOfStream())
+ return cdm::kNeedMoreData;
+
+ GenerateFakeVideoFrame(buffer->GetTimestamp(), decoded_frame);
return cdm::kSuccess;
#else
NOTIMPLEMENTED();
@@ -345,6 +332,37 @@ cdm::Status ClearKeyCdm::DecryptAndDecodeFrame(
#endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER
}
+cdm::Status ClearKeyCdm::DecryptToMediaDecoderBuffer(
+ const cdm::InputBuffer& encrypted_buffer,
+ scoped_refptr<media::DecoderBuffer>* decrypted_buffer) {
+ DCHECK(decrypted_buffer);
+ scoped_refptr<media::DecoderBuffer> buffer =
+ CopyDecoderBufferFrom(encrypted_buffer);
+
+ if (buffer->IsEndOfStream()) {
+ *decrypted_buffer = buffer;
+ return cdm::kSuccess;
+ }
+
+ // Callback is called synchronously, so we can use variables on the stack.
+ media::Decryptor::Status status = media::Decryptor::kError;
+ // The AesDecryptor does not care what the stream type is. Pass kVideo
+ // for both audio and video decryption.
+ decryptor_.Decrypt(
+ media::Decryptor::kVideo,
+ buffer,
+ base::Bind(&CopyDecryptResults, &status, decrypted_buffer));
+
+ if (status == media::Decryptor::kError)
+ return cdm::kDecryptError;
+
+ if (status == media::Decryptor::kNoKey)
+ return cdm::kNoKey;
+
+ DCHECK_EQ(status, media::Decryptor::kSuccess);
+ return cdm::kSuccess;
+}
+
#if defined(CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER)
void ClearKeyCdm::GenerateFakeVideoFrame(base::TimeDelta timestamp,
cdm::VideoFrame* video_frame) {
diff --git a/webkit/media/crypto/ppapi/clear_key_cdm.h b/webkit/media/crypto/ppapi/clear_key_cdm.h
index e5a6cc7..e490b95 100644
--- a/webkit/media/crypto/ppapi/clear_key_cdm.h
+++ b/webkit/media/crypto/ppapi/clear_key_cdm.h
@@ -113,6 +113,18 @@ class ClearKeyCdm : public cdm::ContentDecryptionModule {
std::string default_url_;
};
+ // Decrypts the |encrypted_buffer| and puts the result in |decrypted_buffer|.
+ // Returns cdm::kSuccess if decryption succeeded. The decrypted result is
+ // put in |decrypted_buffer|. If |encrypted_buffer| is empty, the
+ // |decrypted_buffer| is set to an empty (EOS) buffer.
+ // Returns cdm::kNoKey if no decryption key was available. In this case
+ // |decrypted_buffer| should be ignored by the caller.
+ // Returns cdm::kDecryptError if any decryption error occurred. In this case
+ // |decrypted_buffer| should be ignored by the caller.
+ cdm::Status DecryptToMediaDecoderBuffer(
+ const cdm::InputBuffer& encrypted_buffer,
+ scoped_refptr<media::DecoderBuffer>* decrypted_buffer);
+
#if defined(CLEAR_KEY_CDM_USE_FAKE_VIDEO_DECODER)
void GenerateFakeVideoFrame(base::TimeDelta timestamp,
cdm::VideoFrame* video_frame);
diff --git a/webkit/media/crypto/ppapi/ffmpeg_cdm_video_decoder.cc b/webkit/media/crypto/ppapi/ffmpeg_cdm_video_decoder.cc
index 94d2af5..ebf482d 100644
--- a/webkit/media/crypto/ppapi/ffmpeg_cdm_video_decoder.cc
+++ b/webkit/media/crypto/ppapi/ffmpeg_cdm_video_decoder.cc
@@ -221,21 +221,10 @@ cdm::Status FFmpegCdmVideoDecoder::DecodeFrame(
return cdm::kDecodeError;
}
- // If no frame was produced then signal that more data is required to
- // produce more frames. This can happen under two circumstances:
- // 1) Decoder was recently initialized/flushed
- // 2) End of stream was reached and all internal frames have been output
- if (frame_decoded == 0) {
- // There was an input frame, but FFmpeg did not produce an output frame.
- // More input data is needed to produce output.
- if (compressed_frame && compressed_frame_size > 0)
- return cdm::kNeedMoreData;
-
- // No output frame was produced by FFmpeg, and there was no input data.
- // The decoder has been flushed.
- else
- return cdm::kSuccess;
- }
+ // If no frame was produced then signal that more data is required to produce
+ // more frames.
+ if (frame_decoded == 0)
+ return cdm::kNeedMoreData;
// The decoder is in a bad state and not decoding correctly.
// Checking for NULL avoids a crash.