diff options
author | xhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-06 12:35:21 +0000 |
---|---|---|
committer | xhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-06 12:35:21 +0000 |
commit | 19e3c28a7d524d5719bbe87c0de4fd7ff76e3e51 (patch) | |
tree | ed52c99809caee3a6b13522d55c6329b67ab1380 /webkit/media | |
parent | 2a6f6898365f74ccdd7a9d14c1e2ee8022025c0b (diff) | |
download | chromium_src-19e3c28a7d524d5719bbe87c0de4fd7ff76e3e51.zip chromium_src-19e3c28a7d524d5719bbe87c0de4fd7ff76e3e51.tar.gz chromium_src-19e3c28a7d524d5719bbe87c0de4fd7ff76e3e51.tar.bz2 |
Add video decoding support in the CDM interface.
BUG=none
TEST=none
Review URL: https://chromiumcodereview.appspot.com/10900007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@155174 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/media')
-rw-r--r-- | webkit/media/crypto/ppapi/cdm_wrapper.cc | 2 | ||||
-rw-r--r-- | webkit/media/crypto/ppapi/clear_key_cdm.cc | 29 | ||||
-rw-r--r-- | webkit/media/crypto/ppapi/clear_key_cdm.h | 10 | ||||
-rw-r--r-- | webkit/media/crypto/ppapi/content_decryption_module.h | 149 |
4 files changed, 171 insertions, 19 deletions
diff --git a/webkit/media/crypto/ppapi/cdm_wrapper.cc b/webkit/media/crypto/ppapi/cdm_wrapper.cc index 6abe3e9..6307856 100644 --- a/webkit/media/crypto/ppapi/cdm_wrapper.cc +++ b/webkit/media/crypto/ppapi/cdm_wrapper.cc @@ -302,7 +302,7 @@ void CdmWrapper::DeliverBlock(int32_t result, case cdm::kSuccess: decrypted_block_info.result = PP_DECRYPTRESULT_SUCCESS; break; - case cdm::kErrorNoKey: + case cdm::kNoKey: decrypted_block_info.result = PP_DECRYPTRESULT_DECRYPT_NOKEY; break; default: diff --git a/webkit/media/crypto/ppapi/clear_key_cdm.cc b/webkit/media/crypto/ppapi/clear_key_cdm.cc index 835d062..94addb4 100644 --- a/webkit/media/crypto/ppapi/clear_key_cdm.cc +++ b/webkit/media/crypto/ppapi/clear_key_cdm.cc @@ -137,7 +137,7 @@ cdm::Status ClearKeyCdm::GenerateKeyRequest(const uint8_t* init_data, decryptor_.GenerateKeyRequest("", init_data, init_data_size); if (client_.status() != Client::kKeyMessage) - return cdm::kErrorUnknown; + return cdm::kError; DCHECK(key_request); key_request->session_id = AllocateAndCopy(client_.session_id().data(), @@ -165,7 +165,7 @@ cdm::Status ClearKeyCdm::AddKey(const char* session_id, std::string(session_id, session_id_size)); if (client_.status() != Client::kKeyAdded) - return cdm::kErrorUnknown; + return cdm::kError; return cdm::kSuccess; } @@ -203,10 +203,10 @@ cdm::Status ClearKeyCdm::Decrypt( base::Bind(&CopyDecryptResults, &status, &buffer)); if (status == media::Decryptor::kError) - return cdm::kErrorUnknown; + return cdm::kError; if (status == media::Decryptor::kNoKey) - return cdm::kErrorNoKey; + return cdm::kNoKey; DCHECK(buffer); int data_size = buffer->GetDataSize(); @@ -216,4 +216,25 @@ cdm::Status ClearKeyCdm::Decrypt( return cdm::kSuccess; } +cdm::Status ClearKeyCdm::InitializeVideoDecoder( + const cdm::VideoDecoderConfig& video_decoder_config) { + NOTIMPLEMENTED(); + return cdm::kError; +} + +cdm::Status ClearKeyCdm::DecryptAndDecodeVideo( + const cdm::InputBuffer& encrypted_buffer, + cdm::VideoFrame* video_frame) { + NOTIMPLEMENTED(); + return cdm::kError; +} + +void ClearKeyCdm::ResetVideoDecoder() { + NOTIMPLEMENTED(); +} + +void ClearKeyCdm::StopVideoDecoder() { + NOTIMPLEMENTED(); +} + } // namespace webkit_media diff --git a/webkit/media/crypto/ppapi/clear_key_cdm.h b/webkit/media/crypto/ppapi/clear_key_cdm.h index eaad45d..44b3110 100644 --- a/webkit/media/crypto/ppapi/clear_key_cdm.h +++ b/webkit/media/crypto/ppapi/clear_key_cdm.h @@ -31,19 +31,23 @@ class ClearKeyCdm : public cdm::ContentDecryptionModule { virtual cdm::Status GenerateKeyRequest(const uint8_t* init_data, int init_data_size, cdm::KeyMessage* key_request) OVERRIDE; - virtual cdm::Status AddKey(const char* session_id, int session_id_size, const uint8_t* key, int key_size, const uint8_t* key_id, int key_id_size) OVERRIDE; - virtual cdm::Status CancelKeyRequest(const char* session_id, int session_id_size) OVERRIDE; - virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer, cdm::OutputBuffer* decrypted_buffer) OVERRIDE; + virtual cdm::Status InitializeVideoDecoder( + const cdm::VideoDecoderConfig& video_decoder_config) OVERRIDE; + virtual cdm::Status DecryptAndDecodeVideo( + const cdm::InputBuffer& encrypted_buffer, + cdm::VideoFrame* video_frame) OVERRIDE; + virtual void ResetVideoDecoder() OVERRIDE; + virtual void StopVideoDecoder() OVERRIDE; private: class Client : public media::DecryptorClient { diff --git a/webkit/media/crypto/ppapi/content_decryption_module.h b/webkit/media/crypto/ppapi/content_decryption_module.h index cb21258..0f2244a 100644 --- a/webkit/media/crypto/ppapi/content_decryption_module.h +++ b/webkit/media/crypto/ppapi/content_decryption_module.h @@ -8,6 +8,7 @@ #if defined(_MSC_VER) typedef unsigned char uint8_t; typedef unsigned int uint32_t; +typedef int int32_t; typedef __int64 int64_t; #else #include <stdint.h> @@ -29,10 +30,13 @@ namespace cdm { enum Status { kSuccess = 0, - kErrorUnknown, - kErrorNoKey + kNeedMoreData, // Decoder needs more data to produce a decoded frame/sample. + kNoKey, // The required decryption key is not available. + kError }; +// Represents a key message sent by the CDM. It does not own any pointers in +// this struct. // TODO(xhwang): Use int32_t instead of uint32_t for sizes here and below and // update checks to include <0. struct KeyMessage { @@ -82,6 +86,8 @@ struct SubsampleEntry { uint32_t cipher_bytes; }; +// Represents an input buffer to be decrypted (and possibly decoded). It does +// own any pointers in this struct. struct InputBuffer { InputBuffer() : data(NULL), @@ -117,6 +123,7 @@ struct InputBuffer { int64_t timestamp; // Presentation timestamp in microseconds. }; +// Represents an output decrypted buffer. It does not own |data|. struct OutputBuffer { OutputBuffer() : data(NULL), @@ -129,15 +136,87 @@ struct OutputBuffer { int64_t timestamp; // Presentation timestamp in microseconds. }; +// Surface formats based on FOURCC labels, see: +// http://www.fourcc.org/yuv.php +enum VideoFormat { + kUnknownVideoFormat = 0, // Unknown format value. Used for error reporting. + kEmptyVideoFrame, // An empty frame. + kYv12, // 12bpp YVU planar 1x1 Y, 2x2 VU samples. + kI420 // 12bpp YVU planar 1x1 Y, 2x2 UV samples. +}; + +struct Size { + Size() : width(0), height(0) {} + Size(int32_t width, int32_t height) : width(width), height(height) {} + + int32_t width; + int32_t height; +}; + +struct VideoFrame { + static const int32_t kMaxPlanes = 3; + + VideoFrame() + : timestamp(0) { + for (int i = 0; i < kMaxPlanes; ++i) { + strides[i] = 0; + data[i] = NULL; + } + } + + // Array of strides for each plane, typically greater or equal to the width + // of the surface divided by the horizontal sampling period. Note that + // strides can be negative. + int32_t strides[kMaxPlanes]; + + // Array of data pointers to each plane. + uint8_t* data[kMaxPlanes]; + + int64_t timestamp; // Presentation timestamp in microseconds. +}; + +struct VideoDecoderConfig { + enum VideoCodec { + kUnknownVideoCodec = 0, + kCodecVP8 + }; + + enum VideoCodecProfile { + kUnknownVideoCodecProfile = 0, + kVp8ProfileMain + }; + + VideoDecoderConfig() + : codec(kUnknownVideoCodec), + profile(kUnknownVideoCodecProfile), + format(kUnknownVideoFormat), + extra_data(NULL), + extra_data_size() {} + + VideoCodec codec; + VideoCodecProfile profile; + VideoFormat format; + + // Width and height of video frame immediately post-decode. Not all pixels + // in this region are valid. + Size coded_size; + + // Optional byte data required to initialize video decoders, such as H.264 + // AAVC data. + uint8_t* extra_data; + int32_t extra_data_size; +}; + class ContentDecryptionModule { public: // Generates a |key_request| given the |init_data|. + // // Returns kSuccess if the key request was successfully generated, // in which case the callee should have allocated memory for the output // parameters (e.g |session_id| in |key_request|) and passed the ownership // to the caller. - // Returns kErrorUnknown otherwise, in which case the output parameters should - // not be used by the caller. + // Returns kError if any error happened, in which case the |key_request| + // should not be used by the caller. // // TODO(xhwang): It's not safe to pass the ownership of the dynamically // allocated memory over library boundaries. Fix it after related PPAPI change @@ -147,8 +226,8 @@ class ContentDecryptionModule { KeyMessage* key_request) = 0; // Adds the |key| to the CDM to be associated with |key_id|. - // Returns kSuccess if the key was successfully added. - // Returns kErrorUnknown otherwise. + // + // Returns kSuccess if the key was successfully added, kError otherwise. virtual Status AddKey(const char* session_id, int session_id_size, const uint8_t* key, @@ -157,20 +236,23 @@ class ContentDecryptionModule { int key_id_size) = 0; // Cancels any pending key request made to the CDM for |session_id|. + // // Returns kSuccess if all pending key requests for |session_id| were - // successfully canceled or there was no key request to be canceled. - // Returns kErrorUnknown otherwise. + // successfully canceled or there was no key request to be canceled, kError + // otherwise. virtual Status CancelKeyRequest(const char* session_id, int session_id_size) = 0; // Decrypts the |encrypted_buffer|. + // // Returns kSuccess if decryption succeeded, in which case the callee // should have filled the |decrypted_buffer| and passed the ownership of // |data| in |decrypted_buffer| to the caller. - // Returns kErrorNoKey if the CDM did not have the necessary decryption key + // Returns kNoKey if the CDM did not have the necessary decryption key // to decrypt. - // Returns kErrorUnknown if any other error happened. - // In these two cases, |decrypted_buffer| should not be used by the caller. + // Returns kError if any other error happened. + // If the return value is not kSuccess, |decrypted_buffer| should be ignored + // by the caller. // // TODO(xhwang): It's not safe to pass the ownership of the dynamically // allocated memory over library boundaries. Fix it after related PPAPI change @@ -178,6 +260,51 @@ class ContentDecryptionModule { virtual Status Decrypt(const InputBuffer& encrypted_buffer, OutputBuffer* decrypted_buffer) = 0; + // Initializes the CDM video decoder with |video_decoder_config|. This + // function must be called before DecryptAndDecodeVideo() is called. + // + // Returns kSuccess if the |video_decoder_config| is supported and the CDM + // video decoder is successfully initialized. + // Returns kError if |video_decoder_config| is not supported. The CDM may + // still be able to do Decrypt(). + // + // TODO(xhwang): Add stream ID here and in the following video decoder + // functions when we need to support multiple video streams in one CDM. + virtual Status InitializeVideoDecoder( + const VideoDecoderConfig& video_decoder_config) = 0; + + // Decrypts the |encrypted_buffer| and decodes the decrypted buffer into a + // |video_frame|. Upon end-of-stream, the caller should call this function + // repeatedly with empty |encrypted_buffer| (|data| == NULL) until only empty + // |video_frame| (|format| == kEmptyVideoFrame) is produced. + // + // Returns kSuccess if decryption and decoding both succeeded, in which case + // the callee should have filled the |video_frame| and passed the ownership of + // |data| in |video_frame| to the caller. + // Returns kNoKey if the CDM did not have the necessary decryption key + // to decrypt. + // Returns kNeedMoreData if more data was needed by the decoder to generate + // a decoded frame (e.g. during initialization). + // Returns kError if any other (decryption or decoding) error happened. + // If the return value is not kSuccess, |video_frame| should be ignored by + // the caller. + // + // TODO(xhwang): It's not safe to pass the ownership of the dynamically + // allocated memory over library boundaries. Fix it after related PPAPI change + // and sample CDM are landed. + virtual Status DecryptAndDecodeVideo(const InputBuffer& encrypted_buffer, + VideoFrame* video_frame) = 0; + + // Resets the CDM video decoder to an initialized clean state. All internal + // buffers will be flushed. + virtual void ResetVideoDecoder() = 0; + + // Stops the CDM video decoder and sets it to an uninitialized state. The + // caller can call InitializeVideoDecoder() again after this call to + // re-initialize the video decoder. This can be used to reconfigure the + // video decoder if the config changes. + virtual void StopVideoDecoder() = 0; + virtual ~ContentDecryptionModule() {} }; |