diff options
author | xhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-24 01:48:17 +0000 |
---|---|---|
committer | xhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-24 01:48:17 +0000 |
commit | bf7971e5bbdb46b7aee5bf0fb106dc6bfefed158 (patch) | |
tree | fcbf5fbb921228f4e0ab24afd70fb32a09721fe9 /webkit | |
parent | 985b6727d8634737e7ffbfb1bec23cd5631f63a9 (diff) | |
download | chromium_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.cc | 96 | ||||
-rw-r--r-- | webkit/media/crypto/ppapi/clear_key_cdm.h | 12 | ||||
-rw-r--r-- | webkit/media/crypto/ppapi/ffmpeg_cdm_video_decoder.cc | 19 |
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. |