blob: 0ec18a101a02303b230dc5ad58f8b571f1d69805 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_CDM_PPAPI_CLEAR_KEY_CDM_H_
#define MEDIA_CDM_PPAPI_CLEAR_KEY_CDM_H_
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
#include "media/cdm/aes_decryptor.h"
#include "media/cdm/ppapi/clear_key_cdm_common.h"
// Enable this to use the fake decoder for testing.
// TODO(tomfinegan): Move fake audio decoder into a separate class.
#if 0
#define CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
#endif
namespace media {
class CdmVideoDecoder;
class DecoderBuffer;
class FFmpegCdmAudioDecoder;
// Clear key implementation of the cdm::ContentDecryptionModule interface.
class ClearKeyCdm : public ClearKeyCdmInterface {
public:
explicit ClearKeyCdm(Host* host, bool is_decrypt_only);
virtual ~ClearKeyCdm();
// ContentDecryptionModule implementation.
virtual cdm::Status GenerateKeyRequest(
const char* type, uint32_t type_size,
const uint8_t* init_data, uint32_t init_data_size) OVERRIDE;
virtual cdm::Status AddKey(const char* session_id,
uint32_t session_id_size,
const uint8_t* key,
uint32_t key_size,
const uint8_t* key_id,
uint32_t key_id_size) OVERRIDE;
virtual cdm::Status CancelKeyRequest(const char* session_id,
uint32_t session_id_size) OVERRIDE;
virtual void TimerExpired(void* context) OVERRIDE;
virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer,
cdm::DecryptedBlock* decrypted_block) OVERRIDE;
virtual cdm::Status InitializeAudioDecoder(
const cdm::AudioDecoderConfig& audio_decoder_config) OVERRIDE;
virtual cdm::Status InitializeVideoDecoder(
const cdm::VideoDecoderConfig& video_decoder_config) OVERRIDE;
virtual void DeinitializeDecoder(cdm::StreamType decoder_type) OVERRIDE;
virtual void ResetDecoder(cdm::StreamType decoder_type) OVERRIDE;
virtual cdm::Status DecryptAndDecodeFrame(
const cdm::InputBuffer& encrypted_buffer,
cdm::VideoFrame* video_frame) OVERRIDE;
virtual cdm::Status DecryptAndDecodeSamples(
const cdm::InputBuffer& encrypted_buffer,
cdm::AudioFrames* audio_frames) OVERRIDE;
virtual void Destroy() OVERRIDE;
virtual void OnPlatformChallengeResponse(
const cdm::PlatformChallengeResponse& response) OVERRIDE;
virtual void OnQueryOutputProtectionStatus(
uint32_t link_mask, uint32_t output_protection_mask) OVERRIDE;
private:
// TODO(xhwang): After we removed DecryptorClient. We probably can also remove
// this Client class as well. Investigate this possibility.
class Client {
public:
// TODO(jrummell): Remove bitmask and rename kNone to kInvalid once CDM
// interface supports session_id passing completely.
enum Status {
kNone = 0,
kCreated = 1 << 0,
kMessage = 1 << 1,
kReady = 1 << 2,
kClosed = 1 << 3,
kError = 1 << 4
};
Client();
virtual ~Client();
Status status() { return status_; }
const std::string& web_session_id() { return web_session_id_; }
const std::vector<uint8>& message() { return message_; }
const std::string& destination_url() { return destination_url_; }
MediaKeys::KeyError error_code() { return error_code_; }
int system_code() { return system_code_; }
// Resets the Client to a clean state.
void Reset();
void OnSessionCreated(uint32 session_id, const std::string& web_session_id);
void OnSessionMessage(uint32 session_id,
const std::vector<uint8>& message,
const std::string& destination_url);
void OnSessionReady(uint32 session_id);
void OnSessionClosed(uint32 session_id);
void OnSessionError(uint32 session_id,
MediaKeys::KeyError error_code,
int system_code);
private:
Status status_;
std::string web_session_id_;
std::vector<uint8> message_;
std::string destination_url_;
MediaKeys::KeyError error_code_;
int system_code_;
};
// Prepares next heartbeat message and sets a timer for it.
void ScheduleNextHeartBeat();
// 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<DecoderBuffer>* decrypted_buffer);
#if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
int64 CurrentTimeStampInMicroseconds() const;
// Generates fake video frames with |duration_in_microseconds|.
// Returns the number of samples generated in the |audio_frames|.
int GenerateFakeAudioFramesFromDuration(int64 duration_in_microseconds,
cdm::AudioFrames* audio_frames) const;
// Generates fake video frames given |input_timestamp|.
// Returns cdm::kSuccess if any audio frame is successfully generated.
cdm::Status GenerateFakeAudioFrames(int64 timestamp_in_microseconds,
cdm::AudioFrames* audio_frames);
#endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
Client client_;
AesDecryptor decryptor_;
// Protects the |client_| from being accessed by the |decryptor_|
// simultaneously.
base::Lock client_lock_;
ClearKeyCdmHost* host_;
const bool is_decrypt_only_;
std::string heartbeat_session_id_;
std::string next_heartbeat_message_;
// Timer delay in milliseconds for the next host_->SetTimer() call.
int64 timer_delay_ms_;
// Indicates whether a timer has been set to prevent multiple timers from
// running.
bool timer_set_;
#if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER)
int channel_count_;
int bits_per_channel_;
int samples_per_second_;
int64 output_timestamp_base_in_microseconds_;
int total_samples_generated_;
#endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER
#if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER)
scoped_ptr<FFmpegCdmAudioDecoder> audio_decoder_;
#endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER
scoped_ptr<CdmVideoDecoder> video_decoder_;
DISALLOW_COPY_AND_ASSIGN(ClearKeyCdm);
};
} // namespace media
#endif // MEDIA_CDM_PPAPI_CLEAR_KEY_CDM_H_