1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "media/cdm/ppapi/clear_key_cdm.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm> 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sstream> 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/decoder_buffer.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/decrypt_config.h" 18ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "media/cdm/ppapi/cdm_video_decoder.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int64 kNoTimestamp = kint64min; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/at_exit.h" 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/media.h" 30ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "media/cdm/ppapi/ffmpeg_cdm_audio_decoder.h" 31ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "media/cdm/ppapi/ffmpeg_cdm_video_decoder.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Include FFmpeg avformat.h for av_register_all(). 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Temporarily disable possible loss of data warning. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MSVC_PUSH_DISABLE_WARNING(4244); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libavformat/avformat.h> 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MSVC_POP_WARNING(); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // extern "C" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(tomfinegan): When COMPONENT_BUILD is not defined an AtExitManager must 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// exist before the call to InitializeFFmpegLibraries(). This should no longer 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be required after http://crbug.com/91970 because we'll be able to get rid of 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// InitializeFFmpegLibraries(). 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined COMPONENT_BUILD 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static base::AtExitManager g_at_exit_manager; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(tomfinegan): InitializeFFmpegLibraries() and |g_cdm_module_initialized| 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are required for running in the sandbox, and should no longer be required 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// after http://crbug.com/91970 is fixed. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool InitializeFFmpegLibraries() { 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath file_path; 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(PathService::Get(base::DIR_MODULE, &file_path)); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(media::InitializeMediaLibrary(file_path)); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static bool g_ffmpeg_lib_initialized = InitializeFFmpegLibraries(); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kClearKeyCdmVersion[] = "0.1.0.1"; 634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey"; 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const char kExternalClearKeyDecryptOnlyKeySystem[] = 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) "org.chromium.externalclearkey.decryptonly"; 6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int64 kSecondsPerMinute = 60; 6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int64 kMsPerSecond = 1000; 6868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int64 kInitialTimerDelayMs = 200; 6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const int64 kMaxTimerDelayMs = 1 * kSecondsPerMinute * kMsPerSecond; 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Heart beat message header. If a key message starts with |kHeartBeatHeader|, 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// it's a heart beat message. Otherwise, it's a key request. 7268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const char kHeartBeatHeader[] = "HEARTBEAT"; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copies |input_buffer| into a media::DecoderBuffer. If the |input_buffer| is 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// empty, an empty (end-of-stream) media::DecoderBuffer is returned. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static scoped_refptr<media::DecoderBuffer> CopyDecoderBufferFrom( 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const cdm::InputBuffer& input_buffer) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!input_buffer.data) { 791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK(!input_buffer.data_size); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return media::DecoderBuffer::CreateEOSBuffer(); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(tomfinegan): Get rid of this copy. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<media::DecoderBuffer> output_buffer = 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::DecoderBuffer::CopyFrom(input_buffer.data, input_buffer.data_size); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<media::SubsampleEntry> subsamples; 881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) for (uint32_t i = 0; i < input_buffer.num_subsamples; ++i) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::SubsampleEntry subsample; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subsample.clear_bytes = input_buffer.subsamples[i].clear_bytes; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subsample.cypher_bytes = input_buffer.subsamples[i].cipher_bytes; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subsamples.push_back(subsample); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<media::DecryptConfig> decrypt_config(new media::DecryptConfig( 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string(reinterpret_cast<const char*>(input_buffer.key_id), 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_buffer.key_id_size), 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string(reinterpret_cast<const char*>(input_buffer.iv), 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_buffer.iv_size), 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_buffer.data_offset, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subsamples)); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 103ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch output_buffer->set_decrypt_config(decrypt_config.Pass()); 104ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch output_buffer->set_timestamp( 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMicroseconds(input_buffer.timestamp)); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return output_buffer; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Type> 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ScopedResetter { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit ScopedResetter(Type* object) : object_(object) {} 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~ScopedResetter() { object_->Reset(); } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Type* const object_; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void INITIALIZE_CDM_MODULE() { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(2) << "FFmpeg libraries initialized: " << g_ffmpeg_lib_initialized; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) av_register_all(); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DeinitializeCdmModule() { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void* CreateCdmInstance(int cdm_interface_version, 131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const char* key_system, uint32_t key_system_size, 132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) GetCdmHostFunc get_cdm_host_func, 133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) void* user_data) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "CreateCdmInstance()"; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string key_system_string(key_system, key_system_size); 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (key_system_string != kExternalClearKeyKeySystem && 138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) key_system_string != kExternalClearKeyDecryptOnlyKeySystem) { 139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DVLOG(1) << "Unsupported key system:" << key_system_string; 1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return NULL; 1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (cdm_interface_version != media::ClearKeyCdmInterface::kVersion) 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) media::ClearKeyCdmHost* host = static_cast<media::ClearKeyCdmHost*>( 147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) get_cdm_host_func(media::ClearKeyCdmHost::kVersion, user_data)); 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!host) 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return new media::ClearKeyCdm( 152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) host, key_system_string == kExternalClearKeyDecryptOnlyKeySystem); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* GetCdmVersion() { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kClearKeyCdmVersion; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 159ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace media { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Since all the calls to AesDecryptor are synchronous, pass a dummy value for 162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// session_id that is never exposed outside this class. 163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// TODO(jrummell): Remove usage of this when the CDM interface is updated 164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// to use session_id. 165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ClearKeyCdm::Client::Client() 167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) : status_(kNone), error_code_(MediaKeys::kUnknownError), system_code_(0) {} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ClearKeyCdm::Client::~Client() {} 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClearKeyCdm::Client::Reset() { 172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) status_ = kNone; 173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) web_session_id_.clear(); 174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) message_.clear(); 175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) destination_url_.clear(); 176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) error_code_ = MediaKeys::kUnknownError; 177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) system_code_ = 0; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ClearKeyCdm::Client::OnSessionCreated(uint32 session_id, 181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& web_session_id) { 182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) status_ = static_cast<Status>(status_ | kCreated); 183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) web_session_id_ = web_session_id; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ClearKeyCdm::Client::OnSessionMessage(uint32 session_id, 187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::vector<uint8>& message, 188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& destination_url) { 189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) status_ = static_cast<Status>(status_ | kMessage); 190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) message_ = message; 191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) destination_url_ = destination_url; 192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ClearKeyCdm::Client::OnSessionReady(uint32 session_id) { 195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) status_ = static_cast<Status>(status_ | kReady); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ClearKeyCdm::Client::OnSessionClosed(uint32 session_id) { 199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) status_ = static_cast<Status>(status_ | kClosed); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ClearKeyCdm::Client::OnSessionError(uint32 session_id, 203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) media::MediaKeys::KeyError error_code, 204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int system_code) { 205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) status_ = static_cast<Status>(status_ | kError); 206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) error_code_ = error_code; 207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) system_code_ = system_code; 208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ClearKeyCdm::ClearKeyCdm(ClearKeyCdmHost* host, bool is_decrypt_only) 211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : decryptor_( 212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&Client::OnSessionCreated, base::Unretained(&client_)), 213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&Client::OnSessionMessage, base::Unretained(&client_)), 214a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&Client::OnSessionReady, base::Unretained(&client_)), 215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&Client::OnSessionClosed, base::Unretained(&client_)), 216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&Client::OnSessionError, base::Unretained(&client_))), 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) host_(host), 218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) is_decrypt_only_(is_decrypt_only), 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) timer_delay_ms_(kInitialTimerDelayMs), 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) timer_set_(false) { 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_count_ = 0; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bits_per_channel_ = 0; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) samples_per_second_ = 0; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_timestamp_base_in_microseconds_ = kNoTimestamp; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_samples_generated_ = 0; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ClearKeyCdm::~ClearKeyCdm() {} 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)cdm::Status ClearKeyCdm::GenerateKeyRequest(const char* type, 2331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) uint32_t type_size, 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8_t* init_data, 2351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) uint32_t init_data_size) { 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "GenerateKeyRequest()"; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(client_lock_); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedResetter<Client> auto_resetter(&client_); 239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) decryptor_.CreateSession(MediaKeys::kInvalidSessionId, 240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string(type, type_size), 241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) init_data, init_data_size); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (client_.status() != (Client::kMessage | Client::kCreated)) { 244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Use values returned to client if possible. 245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) host_->SendKeyError(client_.web_session_id().data(), 246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_.web_session_id().size(), 247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static_cast<cdm::MediaKeyError>(client_.error_code()), 248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) client_.system_code()); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cdm::kSessionError; 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) host_->SendKeyMessage( 253a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_.web_session_id().data(), client_.web_session_id().size(), 254a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) reinterpret_cast<const char*>(&client_.message()[0]), 255a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_.message().size(), 256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) client_.destination_url().data(), client_.destination_url().size()); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Only save the latest session ID for heartbeat messages. 259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) heartbeat_session_id_ = client_.web_session_id(); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cdm::kSuccess; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cdm::Status ClearKeyCdm::AddKey(const char* session_id, 2651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) uint32_t session_id_size, 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8_t* key, 2671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) uint32_t key_size, 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8_t* key_id, 2691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) uint32_t key_id_size) { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "AddKey()"; 271a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(!key_id && !key_id_size); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(client_lock_); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedResetter<Client> auto_resetter(&client_); 274a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) decryptor_.UpdateSession(MediaKeys::kInvalidSessionId, key, key_size); 275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 276a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (client_.status() != Client::kReady) { 277f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) host_->SendKeyError(session_id, session_id_size, 278f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static_cast<cdm::MediaKeyError>(client_.error_code()), 279f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) client_.system_code()); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cdm::kSessionError; 281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!timer_set_) { 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScheduleNextHeartBeat(); 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) timer_set_ = true; 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cdm::kSuccess; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cdm::Status ClearKeyCdm::CancelKeyRequest(const char* session_id, 2921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) uint32_t session_id_size) { 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "CancelKeyRequest()"; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(client_lock_); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedResetter<Client> auto_resetter(&client_); 296a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) decryptor_.ReleaseSession(MediaKeys::kInvalidSessionId); 297f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 298a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // No message normally sent by Release(), but if an error occurred, 299f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // report it as a failure. 300a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (client_.status() == Client::kError) { 301f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) host_->SendKeyError(session_id, session_id_size, 302f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static_cast<cdm::MediaKeyError>(client_.error_code()), 303f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) client_.system_code()); 304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return cdm::kSessionError; 305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cdm::kSuccess; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ClearKeyCdm::TimerExpired(void* context) { 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string heartbeat_message; 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!next_heartbeat_message_.empty() && 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) context == &next_heartbeat_message_[0]) { 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) heartbeat_message = next_heartbeat_message_; 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) heartbeat_message = "ERROR: Invalid timer context found!"; 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This URL is only used for testing the code path for defaultURL. 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // There is no service at this URL, so applications should ignore it. 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char url[] = "http://test.externalclearkey.chromium.org"; 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) host_->SendKeyMessage( 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) heartbeat_session_id_.data(), heartbeat_session_id_.size(), 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) heartbeat_message.data(), heartbeat_message.size(), 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) url, arraysize(url) - 1); 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScheduleNextHeartBeat(); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void CopyDecryptResults( 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::Decryptor::Status* status_copy, 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<media::DecoderBuffer>* buffer_copy, 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::Decryptor::Status status, 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const scoped_refptr<media::DecoderBuffer>& buffer) { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *status_copy = status; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *buffer_copy = buffer; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cdm::Status ClearKeyCdm::Decrypt( 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const cdm::InputBuffer& encrypted_buffer, 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cdm::DecryptedBlock* decrypted_block) { 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Decrypt()"; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(encrypted_buffer.data); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<media::DecoderBuffer> buffer; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status != cdm::kSuccess) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 352ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(buffer->data()); 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) decrypted_block->SetDecryptedBuffer( 354ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch host_->Allocate(buffer->data_size())); 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(reinterpret_cast<void*>(decrypted_block->DecryptedBuffer()->Data()), 356ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch buffer->data(), 357ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch buffer->data_size()); 358ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch decrypted_block->DecryptedBuffer()->SetSize(buffer->data_size()); 359ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch decrypted_block->SetTimestamp(buffer->timestamp().InMicroseconds()); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cdm::kSuccess; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cdm::Status ClearKeyCdm::InitializeAudioDecoder( 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const cdm::AudioDecoderConfig& audio_decoder_config) { 366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (is_decrypt_only_) 367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return cdm::kSessionError; 368f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_decoder_) 371ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch audio_decoder_.reset(new media::FFmpegCdmAudioDecoder(host_)); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_decoder_->Initialize(audio_decoder_config)) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cdm::kSessionError; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cdm::kSuccess; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_count_ = audio_decoder_config.channel_count; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bits_per_channel_ = audio_decoder_config.bits_per_channel; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) samples_per_second_ = audio_decoder_config.samples_per_second; 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cdm::kSuccess; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIMPLEMENTED(); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cdm::kSessionError; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cdm::Status ClearKeyCdm::InitializeVideoDecoder( 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const cdm::VideoDecoderConfig& video_decoder_config) { 390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (is_decrypt_only_) 391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return cdm::kSessionError; 392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (video_decoder_ && video_decoder_->is_initialized()) { 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!video_decoder_->is_initialized()); 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return cdm::kSessionError; 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Any uninitialized decoder will be replaced. 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) video_decoder_ = CreateVideoDecoder(host_, video_decoder_config); 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!video_decoder_) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cdm::kSessionError; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cdm::kSuccess; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClearKeyCdm::ResetDecoder(cdm::StreamType decoder_type) { 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "ResetDecoder()"; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (decoder_type) { 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case cdm::kStreamTypeVideo: 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) video_decoder_->Reset(); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case cdm::kStreamTypeAudio: 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_decoder_->Reset(); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "ResetDecoder(): invalid cdm::StreamType"; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (decoder_type == cdm::kStreamTypeAudio) { 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_timestamp_base_in_microseconds_ = kNoTimestamp; 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_samples_generated_ = 0; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // CLEAR_KEY_CDM_USE_FFMPEG_DECODER 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClearKeyCdm::DeinitializeDecoder(cdm::StreamType decoder_type) { 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "DeinitializeDecoder()"; 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (decoder_type) { 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case cdm::kStreamTypeVideo: 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) video_decoder_->Deinitialize(); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case cdm::kStreamTypeAudio: 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_decoder_->Deinitialize(); 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) output_timestamp_base_in_microseconds_ = kNoTimestamp; 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) total_samples_generated_ = 0; 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "DeinitializeDecoder(): invalid cdm::StreamType"; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cdm::Status ClearKeyCdm::DecryptAndDecodeFrame( 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const cdm::InputBuffer& encrypted_buffer, 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cdm::VideoFrame* decoded_frame) { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "DecryptAndDecodeFrame()"; 450f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TRACE_EVENT0("media", "ClearKeyCdm::DecryptAndDecodeFrame"); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<media::DecoderBuffer> buffer; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status != cdm::kSuccess) 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const uint8_t* data = NULL; 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32_t size = 0; 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64_t timestamp = 0; 461ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!buffer->end_of_stream()) { 462ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data = buffer->data(); 463ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch size = buffer->data_size(); 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) timestamp = encrypted_buffer.timestamp; 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return video_decoder_->DecodeFrame(data, size, timestamp, decoded_frame); 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cdm::Status ClearKeyCdm::DecryptAndDecodeSamples( 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const cdm::InputBuffer& encrypted_buffer, 4721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) cdm::AudioFrames* audio_frames) { 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "DecryptAndDecodeSamples()"; 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<media::DecoderBuffer> buffer; 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cdm::Status status = DecryptToMediaDecoderBuffer(encrypted_buffer, &buffer); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status != cdm::kSuccess) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return status; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(CLEAR_KEY_CDM_USE_FFMPEG_DECODER) 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const uint8_t* data = NULL; 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32_t size = 0; 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64_t timestamp = 0; 485ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!buffer->end_of_stream()) { 486ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data = buffer->data(); 487ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch size = buffer->data_size(); 4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) timestamp = encrypted_buffer.timestamp; 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return audio_decoder_->DecodeBuffer(data, size, timestamp, audio_frames); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 timestamp_in_microseconds = kNoTimestamp; 494ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!buffer->end_of_stream()) { 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timestamp_in_microseconds = buffer->GetTimestamp().InMicroseconds(); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(timestamp_in_microseconds != kNoTimestamp); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GenerateFakeAudioFrames(timestamp_in_microseconds, audio_frames); 4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return cdm::kSuccess; 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ClearKeyCdm::Destroy() { 5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(1) << "Destroy()"; 5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete this; 5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ClearKeyCdm::ScheduleNextHeartBeat() { 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Prepare the next heartbeat message and set timer. 5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::ostringstream msg_stream; 5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) msg_stream << kHeartBeatHeader << " from ClearKey CDM set at time " 5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << host_->GetCurrentWallTimeInSeconds() << "."; 5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_heartbeat_message_ = msg_stream.str(); 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) host_->SetTimer(timer_delay_ms_, &next_heartbeat_message_[0]); 5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Use a smaller timer delay at start-up to facilitate testing. Increase the 5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // timer delay up to a limit to avoid message spam. 5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (timer_delay_ms_ < kMaxTimerDelayMs) 5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) timer_delay_ms_ = std::min(2 * timer_delay_ms_, kMaxTimerDelayMs); 5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cdm::Status ClearKeyCdm::DecryptToMediaDecoderBuffer( 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const cdm::InputBuffer& encrypted_buffer, 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<media::DecoderBuffer>* decrypted_buffer) { 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(decrypted_buffer); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<media::DecoderBuffer> buffer = 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CopyDecoderBufferFrom(encrypted_buffer); 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 531ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (buffer->end_of_stream()) { 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *decrypted_buffer = buffer; 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cdm::kSuccess; 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Callback is called synchronously, so we can use variables on the stack. 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::Decryptor::Status status = media::Decryptor::kError; 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The AesDecryptor does not care what the stream type is. Pass kVideo 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for both audio and video decryption. 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decryptor_.Decrypt( 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::Decryptor::kVideo, 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer, 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CopyDecryptResults, &status, decrypted_buffer)); 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status == media::Decryptor::kError) 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cdm::kDecryptError; 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status == media::Decryptor::kNoKey) 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cdm::kNoKey; 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(status, media::Decryptor::kSuccess); 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cdm::kSuccess; 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ClearKeyCdm::OnPlatformChallengeResponse( 5561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const cdm::PlatformChallengeResponse& response) { 5571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) NOTIMPLEMENTED(); 5581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 5591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 5601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ClearKeyCdm::OnQueryOutputProtectionStatus( 5611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) uint32_t link_mask, uint32_t output_protection_mask) { 5621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) NOTIMPLEMENTED(); 5631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}; 5641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER) 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 ClearKeyCdm::CurrentTimeStampInMicroseconds() const { 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return output_timestamp_base_in_microseconds_ + 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time::kMicrosecondsPerSecond * 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_samples_generated_ / samples_per_second_; 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ClearKeyCdm::GenerateFakeAudioFramesFromDuration( 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 duration_in_microseconds, 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cdm::AudioFrames* audio_frames) const { 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 samples_to_generate = static_cast<double>(samples_per_second_) * 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) duration_in_microseconds / base::Time::kMicrosecondsPerSecond + 0.5; 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (samples_to_generate <= 0) 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 bytes_per_sample = channel_count_ * bits_per_channel_ / 8; 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |frame_size| must be a multiple of |bytes_per_sample|. 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 frame_size = bytes_per_sample * samples_to_generate; 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 timestamp = CurrentTimeStampInMicroseconds(); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kHeaderSize = sizeof(timestamp) + sizeof(frame_size); 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_frames->SetFrameBuffer(host_->Allocate(kHeaderSize + frame_size)); 5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8_t* data = audio_frames->FrameBuffer()->Data(); 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(data, ×tamp, sizeof(timestamp)); 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += sizeof(timestamp); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(data, &frame_size, sizeof(frame_size)); 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += sizeof(frame_size); 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // You won't hear anything because we have all zeros here. But the video 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should play just fine! 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(data, 0, frame_size); 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) audio_frames->FrameBuffer()->SetSize(kHeaderSize + frame_size); 5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return samples_to_generate; 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cdm::Status ClearKeyCdm::GenerateFakeAudioFrames( 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 timestamp_in_microseconds, 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cdm::AudioFrames* audio_frames) { 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (timestamp_in_microseconds == kNoTimestamp) 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cdm::kNeedMoreData; 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return kNeedMoreData for the first frame because duration is unknown. 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (output_timestamp_base_in_microseconds_ == kNoTimestamp) { 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_timestamp_base_in_microseconds_ = timestamp_in_microseconds; 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cdm::kNeedMoreData; 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int samples_generated = GenerateFakeAudioFramesFromDuration( 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timestamp_in_microseconds - CurrentTimeStampInMicroseconds(), 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_frames); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_samples_generated_ += samples_generated; 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return samples_generated == 0 ? cdm::kNeedMoreData : cdm::kSuccess; 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // CLEAR_KEY_CDM_USE_FAKE_AUDIO_DECODER 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 624ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} // namespace media 625