Bug 1041384 - Update GMP APIs for decrypt without decoding and reporting capabilities. r=jesup

This commit is contained in:
Chris Pearce 2014-07-24 09:35:02 +12:00
Родитель 7b82110ed9
Коммит 499998ccd9
7 изменённых файлов: 136 добавлений и 76 удалений

Просмотреть файл

@ -51,7 +51,7 @@ GMPVideoEncodedFrameImpl::~GMPVideoEncodedFrameImpl()
} }
} }
const GMPEncryptedBufferData* const GMPEncryptedBufferMetadata*
GMPVideoEncodedFrameImpl::GetDecryptionData() const GMPVideoEncodedFrameImpl::GetDecryptionData() const
{ {
return nullptr; return nullptr;

Просмотреть файл

@ -91,7 +91,7 @@ public:
virtual uint8_t* Buffer() MOZ_OVERRIDE; virtual uint8_t* Buffer() MOZ_OVERRIDE;
virtual GMPBufferType BufferType() const MOZ_OVERRIDE; virtual GMPBufferType BufferType() const MOZ_OVERRIDE;
virtual void SetBufferType(GMPBufferType aBufferType) MOZ_OVERRIDE; virtual void SetBufferType(GMPBufferType aBufferType) MOZ_OVERRIDE;
virtual const GMPEncryptedBufferData* GetDecryptionData() const MOZ_OVERRIDE; virtual const GMPEncryptedBufferMetadata* GetDecryptionData() const MOZ_OVERRIDE;
private: private:
void DestroyBuffer(); void DestroyBuffer();

Просмотреть файл

@ -49,9 +49,9 @@ public:
virtual const uint8_t* Buffer() const = 0; virtual const uint8_t* Buffer() const = 0;
virtual uint8_t* Buffer() = 0; virtual uint8_t* Buffer() = 0;
// Get data describing how this frame is encrypted, or nullptr if the // Get metadata describing how this frame is encrypted, or nullptr if the
// buffer is not encrypted. // buffer is not encrypted.
virtual const GMPEncryptedBufferData* GetDecryptionData() const = 0; virtual const GMPEncryptedBufferMetadata* GetDecryptionData() const = 0;
}; };
#endif // GMP_AUDIO_FRAME_h_ #endif // GMP_AUDIO_FRAME_h_

Просмотреть файл

@ -19,7 +19,7 @@
#include "gmp-platform.h" #include "gmp-platform.h"
class GMPEncryptedBufferData { class GMPEncryptedBufferMetadata {
public: public:
// Key ID to identify the decryption key. // Key ID to identify the decryption key.
virtual const uint8_t* KeyId() const = 0; virtual const uint8_t* KeyId() const = 0;
@ -33,14 +33,23 @@ public:
// Size (in bytes) of |IV|. // Size (in bytes) of |IV|.
virtual uint32_t IVSize() const = 0; virtual uint32_t IVSize() const = 0;
// Number of enties returned by ClearBytes and CipherBytes(). // Number of entries returned by ClearBytes() and CipherBytes().
virtual uint32_t NumSubsamples() const = 0; virtual uint32_t NumSubsamples() const = 0;
virtual const uint32_t* ClearBytes() const = 0; virtual const uint16_t* ClearBytes() const = 0;
virtual const uint32_t* CipherBytes() const = 0; virtual const uint32_t* CipherBytes() const = 0;
}; };
class GMPBuffer {
public:
virtual uint32_t Id() const = 0;
virtual uint8_t* Data() = 0;
virtual uint32_t Size() const = 0;
virtual void Resize(uint32_t aSize) = 0;
virtual ~GMPBuffer() {}
};
// These match to the DOMException codes as per: // These match to the DOMException codes as per:
// http://www.w3.org/TR/dom/#domexception // http://www.w3.org/TR/dom/#domexception
enum GMPDOMException { enum GMPDOMException {
@ -60,71 +69,106 @@ enum GMPDOMException {
// Time in milliseconds, as offset from epoch, 1 Jan 1970. // Time in milliseconds, as offset from epoch, 1 Jan 1970.
typedef int64_t GMPTimestamp; typedef int64_t GMPTimestamp;
// Capability definitions. The capabilities of the EME GMP are reported
// to Gecko by calling the GMPDecryptorCallback::SetCapabilities()
// callback and specifying the logical OR of the GMP_EME_CAP_* flags below.
//
// Note the DECRYPT and the DECRYPT_AND_DECODE are mutually exclusive;
// only one mode should be reported for each stream type, but different
// modes can be reported for different stream types.
//
// Note: Gecko does not currently support the caps changing at runtime.
// Set them once per plugin initialization, during the startup of
// the GMPdecryptor.
// Capability; CDM can decrypt encrypted buffers and return still
// compressed buffers back to Gecko for decompression there.
#define GMP_EME_CAP_DECRYPT_AUDIO (uint64_t(1) << 0)
#define GMP_EME_CAP_DECRYPT_VIDEO (uint64_t(1) << 1)
// Capability; CDM can decrypt and then decode encrypted buffers,
// and return decompressed samples to Gecko for playback.
#define GMP_EME_CAP_DECRYPT_AND_DECODE_AUDIO (uint64_t(1) << 2)
#define GMP_EME_CAP_DECRYPT_AND_DECODE_VIDEO (uint64_t(1) << 3)
class GMPDecryptorCallback { class GMPDecryptorCallback {
public: public:
// Resolves a promise for a session created or loaded. // Resolves a promise for a session created or loaded.
// Passes the session id to be exposed to JavaScript. // Passes the session id to be exposed to JavaScript.
// Must be called before OnSessionMessage(). // Must be called before SessionMessage().
// aSessionId must be null terminated. // aSessionId must be null terminated.
virtual void OnResolveNewSessionPromise(uint32_t aPromiseId, virtual void ResolveNewSessionPromise(uint32_t aPromiseId,
const char* aSessionId, const char* aSessionId,
uint32_t aSessionIdLength) = 0; uint32_t aSessionIdLength) = 0;
// Called to resolve a specified promise with "undefined". // Called to resolve a specified promise with "undefined".
virtual void OnResolvePromise(uint32_t aPromiseId) = 0; virtual void ResolvePromise(uint32_t aPromiseId) = 0;
// Called to reject a promise with a DOMException. // Called to reject a promise with a DOMException.
// aMessage is logged to the WebConsole. // aMessage is logged to the WebConsole.
// aMessage is optional, but if present must be null terminated. // aMessage is optional, but if present must be null terminated.
virtual void OnRejectPromise(uint32_t aPromiseId, virtual void RejectPromise(uint32_t aPromiseId,
GMPDOMException aException, GMPDOMException aException,
const char* aMessage, const char* aMessage,
uint32_t aMessageLength) = 0; uint32_t aMessageLength) = 0;
// Called by the CDM when it has a message for session |session_id|. // Called by the CDM when it has a message for session |session_id|.
// Length parameters should not include null termination. // Length parameters should not include null termination.
// aSessionId must be null terminated. // aSessionId must be null terminated.
virtual void OnSessionMessage(const char* aSessionId, virtual void SessionMessage(const char* aSessionId,
uint32_t aSessionIdLength, uint32_t aSessionIdLength,
const uint8_t* aMessage, const uint8_t* aMessage,
uint32_t aMessageLength, uint32_t aMessageLength,
const char* aDestinationURL, const char* aDestinationURL,
uint32_t aDestinationURLLength) = 0; uint32_t aDestinationURLLength) = 0;
// aSessionId must be null terminated. // aSessionId must be null terminated.
virtual void OnExpirationChange(const char* aSessionId, virtual void ExpirationChange(const char* aSessionId,
uint32_t aSessionIdLength, uint32_t aSessionIdLength,
GMPTimestamp aExpiryTime) = 0; GMPTimestamp aExpiryTime) = 0;
// Called by the GMP when a session is closed. All file IO // Called by the GMP when a session is closed. All file IO
// that a session requires should be complete before calling this. // that a session requires should be complete before calling this.
// aSessionId must be null terminated. // aSessionId must be null terminated.
virtual void OnSessionClosed(const char* aSessionId, virtual void SessionClosed(const char* aSessionId,
uint32_t aSessionIdLength) = 0; uint32_t aSessionIdLength) = 0;
// Called by the GMP when an error occurs in a session. // Called by the GMP when an error occurs in a session.
// aSessionId must be null terminated. // aSessionId must be null terminated.
// aMessage is logged to the WebConsole. // aMessage is logged to the WebConsole.
// aMessage is optional, but if present must be null terminated. // aMessage is optional, but if present must be null terminated.
virtual void OnSessionError(const char* aSessionId, virtual void SessionError(const char* aSessionId,
uint32_t aSessionIdLength, uint32_t aSessionIdLength,
GMPDOMException aException, GMPDOMException aException,
uint32_t aSystemCode, uint32_t aSystemCode,
const char* aMessage, const char* aMessage,
uint32_t aMessageLength) = 0; uint32_t aMessageLength) = 0;
virtual void OnKeyIdUsable(const char* aSessionId, // Marks a key as usable. Gecko will not call into the CDM to decrypt
uint32_t aSessionIdLength, // or decode content encrypted with a key unless the CDM has marked it
const uint8_t* aKeyId, // usable first. So a CDM *MUST* mark its usable keys as usable!
uint32_t aKeyIdLength) = 0; virtual void KeyIdUsable(const char* aSessionId,
uint32_t aSessionIdLength,
const uint8_t* aKeyId,
uint32_t aKeyIdLength) = 0;
// Marks a key as no longer usable. // Marks a key as no longer usable.
// Note: Keys are assumed to be not usable when a session is closed or removed. // Note: Keys are assumed to be not usable when a session is closed or removed.
virtual void OnKeyIdNotUsable(const char* aSessionId, virtual void KeyIdNotUsable(const char* aSessionId,
uint32_t aSessionIdLength, uint32_t aSessionIdLength,
const uint8_t* aKeyId, const uint8_t* aKeyId,
uint32_t aKeyIdLength) = 0; uint32_t aKeyIdLength) = 0;
// The CDM must report its capabilites of this CDM. aCaps should be a
// logical OR of the GMP_EME_CAP_* flags. The CDM *MUST* call this
// function and report whether it can decrypt and/or decode. Without
// this, Gecko does not know how to use the CDM and will not send
// samples to the CDM to decrypt or decrypt-and-decode mode. Note a
// CDM cannot change modes once playback has begun.
virtual void SetCapabilities(uint64_t aCaps) = 0;
// Returns decrypted buffer to Gecko, or reports failure.
virtual void Decrypted(GMPBuffer* aBuffer, GMPErr aResult) = 0;
}; };
// Host interface, passed to GetAPIFunc(), with "decrypt". // Host interface, passed to GetAPIFunc(), with "decrypt".
@ -166,10 +210,14 @@ public:
virtual void Init(GMPDecryptorCallback* aCallback) = 0; virtual void Init(GMPDecryptorCallback* aCallback) = 0;
// Requests the creation of a session given |aType| and |aInitData|. // Requests the creation of a session given |aType| and |aInitData|.
// Decryptor should callback GMPDecryptorCallback::OnSessionCreated() // Decryptor should callback GMPDecryptorCallback::SessionCreated()
// with the web session ID on success, or OnSessionError() on failure, // with the web session ID on success, or SessionError() on failure,
// and then call OnSessionReady() once all keys for that session are // and then call KeyIdUsable() as keys for that session become
// available. // usable.
//
// The CDM must also call GMPDecryptorCallback::SetCapabilities()
// exactly once during start up, to inform Gecko whether to use the CDM
// in decrypt or decrypt-and-decode mode.
virtual void CreateSession(uint32_t aPromiseId, virtual void CreateSession(uint32_t aPromiseId,
const char* aInitDataType, const char* aInitDataType,
uint32_t aInitDataTypeSize, uint32_t aInitDataTypeSize,
@ -203,6 +251,15 @@ public:
virtual void SetServerCertificate(uint32_t aPromiseId, virtual void SetServerCertificate(uint32_t aPromiseId,
const uint8_t* aServerCert, const uint8_t* aServerCert,
uint32_t aServerCertSize) = 0; uint32_t aServerCertSize) = 0;
// Asynchronously decrypts aBuffer in place. When the decryption is
// complete, GMPDecryptor should write the decrypted data back into the
// same GMPBuffer object and return it to Gecko by calling Decrypted(),
// with the GMPNoErr successcode. If decryption fails, call Decrypted()
// with a failure code, and an error event will fire on the media element.
virtual void Decrypt(GMPBuffer* aBuffer,
GMPEncryptedBufferMetadata* aMetadata) = 0;
}; };
#endif // GMP_DECRYPTION_h_ #endif // GMP_DECRYPTION_h_

Просмотреть файл

@ -39,7 +39,7 @@ typedef enum {
GMPClosedErr = 2, GMPClosedErr = 2,
GMPAllocErr = 3, GMPAllocErr = 3,
GMPNotImplementedErr = 4, GMPNotImplementedErr = 4,
GMPNotClosedErr = 5, GMPRecordInUse = 5,
GMPQuotaExceededErr = 6, GMPQuotaExceededErr = 6,
GMPDecodeErr = 7, GMPDecodeErr = 7,
GMPEncodeErr = 8, GMPEncodeErr = 8,

Просмотреть файл

@ -21,30 +21,31 @@
#include <stdint.h> #include <stdint.h>
// Provides basic per-origin storage for CDMs. GMPRecord instances can be // Provides basic per-origin storage for CDMs. GMPRecord instances can be
// retrieved by calling GMPPlatformAPI->openstorage. Multiple GMPRecord // retrieved by calling GMPPlatformAPI->openstorage. Multiple GMPRecords
// can be open at once. This interface is asynchronous, with results // with different names can be open at once, but a single record can only
// being returned via callbacks to the GMPRecordClient pointer provided // be opened by one client at a time. This interface is asynchronous, with
// to the GMPPlatformAPI->openstorage call, on the main thread. // results being returned via callbacks to the GMPRecordClient pointer
// provided to the GMPPlatformAPI->openstorage call, on the main thread.
class GMPRecord { class GMPRecord {
public: public:
// Opens the record. Calls OnOpenComplete() once the record is open. // Opens the record. Calls OpenComplete() once the record is open.
// Note: OnReadComplete() is only called if this returns GMPNoErr. // Note: OpenComplete() is only called if this returns GMPNoErr.
virtual GMPErr Open() = 0; virtual GMPErr Open() = 0;
// Reads the entire contents of the file, and calls // Reads the entire contents of the record, and calls
// GMPRecordClient::OnReadComplete() once the operation is complete. // GMPRecordClient::ReadComplete() once the operation is complete.
// Note: OnReadComplete() is only called if this returns GMPNoErr. // Note: ReadComplete() is only called if this returns GMPNoErr.
virtual GMPErr Read() = 0; virtual GMPErr Read() = 0;
// Writes aDataSize bytes of aData into the file, overwritting the contents // Writes aDataSize bytes of aData into the record, overwriting the
// of the file. Overwriting with 0 bytes "deletes" the file. // contents of the record. Overwriting with 0 bytes "deletes" the file.
// Write 0 bytes to "delete" a file. // Note: WriteComplete is only called if this returns GMPNoErr.
// Note: OnWriteComplete is only called if this returns GMPNoErr.
virtual GMPErr Write(const uint8_t* aData, uint32_t aDataSize) = 0; virtual GMPErr Write(const uint8_t* aData, uint32_t aDataSize) = 0;
// Closes a file. File must not be used after this is called. Cancels all // Closes a record. GMPRecord object must not be used after this is
// callbacks. // called, request a new one with GMPPlatformAPI->openstorage to re-open
// this record. Cancels all callbacks.
virtual GMPErr Close() = 0; virtual GMPErr Close() = 0;
virtual ~GMPRecord() {} virtual ~GMPRecord() {}
@ -57,32 +58,34 @@ class GMPRecordClient {
// Response to a GMPRecord::Open() call with the open |status|. // Response to a GMPRecord::Open() call with the open |status|.
// aStatus values: // aStatus values:
// - GMPNoErr - File opened successfully. File may be empty. // - GMPNoErr - Record opened successfully. Record may be empty.
// - GMPFileInUse - There file is in use by another client. // - GMPRecordInUse - This record is in use by another client.
// - GMPGenericErr - Unspecified error. // - GMPGenericErr - Unspecified error.
// Do not use the GMPRecord if aStatus is not GMPNoErr. // Do not use the GMPRecord if aStatus is not GMPNoErr.
virtual void OnOpenComplete(GMPErr aStatus) = 0; virtual void OpenComplete(GMPErr aStatus) = 0;
// Response to a GMPRecord::Read() call, where aData is the file contents, // Response to a GMPRecord::Read() call, where aData is the record contents,
// of length aDataSize. // of length aDataSize.
// aData is only valid for the duration of the call to OnReadComplete. // aData is only valid for the duration of the call to ReadComplete.
// Copy it if you want to hang onto it! // Copy it if you want to hang onto it!
// aStatus values: // aStatus values:
// - GMPNoErr - File contents read successfully, aDataSize 0 means file // - GMPNoErr - Record contents read successfully, aDataSize 0 means record
// is empty. // is empty.
// - GMPFileInUse - There are other operations or clients in use on this file. // - GMPRecordInUse - There are other operations or clients in use on
// this record.
// - GMPGenericErr - Unspecified error. // - GMPGenericErr - Unspecified error.
// Do not continue to use the GMPRecord if aStatus is not GMPNoErr. // Do not continue to use the GMPRecord if aStatus is not GMPNoErr.
virtual void OnReadComplete(GMPErr aStatus, virtual void ReadComplete(GMPErr aStatus,
const uint8_t* aData, const uint8_t* aData,
uint32_t aDataSize) = 0; uint32_t aDataSize) = 0;
// Response to a GMPRecord::Write() call. // Response to a GMPRecord::Write() call.
// - GMPNoErr - File contents written successfully. // - GMPNoErr - File contents written successfully.
// - GMPFileInUse - There are other operations or clients in use on this file. // - GMPRecordInUse - There are other operations or clients in use on
// - GMPGenericErr - Unspecified error. File should be regarded as corrupt. // this record.
// - GMPGenericErr - Unspecified error.
// Do not continue to use the GMPRecord if aStatus is not GMPNoErr. // Do not continue to use the GMPRecord if aStatus is not GMPNoErr.
virtual void OnWriteComplete(GMPErr aStatus) = 0; virtual void WriteComplete(GMPErr aStatus) = 0;
virtual ~GMPRecordClient() {} virtual ~GMPRecordClient() {}
}; };

Просмотреть файл

@ -90,9 +90,9 @@ public:
virtual GMPBufferType BufferType() const = 0; virtual GMPBufferType BufferType() const = 0;
virtual void SetBufferType(GMPBufferType aBufferType) = 0; virtual void SetBufferType(GMPBufferType aBufferType) = 0;
// Get data describing how this frame is encrypted, or nullptr if the // Get metadata describing how this frame is encrypted, or nullptr if the
// frame is not encrypted. // frame is not encrypted.
virtual const GMPEncryptedBufferData* GetDecryptionData() const = 0; virtual const GMPEncryptedBufferMetadata* GetDecryptionData() const = 0;
}; };
#endif // GMP_VIDEO_FRAME_ENCODED_h_ #endif // GMP_VIDEO_FRAME_ENCODED_h_