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, &timestamp, 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