// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "starboard/shared/win32/decrypting_decoder.h"

#include <stdlib.h>

#include <algorithm>
#include <numeric>

#include "starboard/common/log.h"
#include "starboard/common/memory.h"
#include "starboard/common/ref_counted.h"
#include "starboard/shared/win32/error_utils.h"
#include "starboard/shared/win32/media_foundation_utils.h"

namespace starboard {
namespace shared {
namespace win32 {

namespace {

ComPtr<IMFSample> CreateSample(const void* data,
                               int size,
                               int64_t win32_timestamp) {
  ComPtr<IMFMediaBuffer> buffer;
  HRESULT hr = MFCreateMemoryBuffer(size, &buffer);
  CheckResult(hr);

  BYTE* buffer_ptr;
  hr = buffer->Lock(&buffer_ptr, 0, 0);
  CheckResult(hr);

  memcpy(buffer_ptr, data, size);

  hr = buffer->Unlock();
  CheckResult(hr);

  hr = buffer->SetCurrentLength(size);
  CheckResult(hr);

  ComPtr<IMFSample> input;
  hr = MFCreateSample(&input);
  CheckResult(hr);

  hr = input->AddBuffer(buffer.Get());
  CheckResult(hr);

  // sample time is in 100 nanoseconds.
  input->SetSampleTime(win32_timestamp);
  return input;
}

void AttachDrmDataToSample(ComPtr<IMFSample> sample,
                           int sample_size,
                           const uint8_t* key_id,
                           int key_id_size,
                           const uint8_t* iv,
                           int iv_size,
                           const SbDrmSubSampleMapping* subsample_mapping,
                           int subsample_count) {
  if (iv_size == 16 && ::starboard::common::MemoryIsZero(iv + 8, 8)) {
    // For iv that is 16 bytes long but the the last 8 bytes is 0, we treat
    // it as an 8 bytes iv.
    iv_size = 8;
  }
  sample->SetBlob(MFSampleExtension_Encryption_SampleID,
                  reinterpret_cast<const UINT8*>(iv),
                  static_cast<UINT32>(iv_size));
  SB_DCHECK(key_id_size == sizeof(GUID));
  GUID guid = *reinterpret_cast<const GUID*>(key_id);

  guid.Data1 = _byteswap_ulong(guid.Data1);
  guid.Data2 = _byteswap_ushort(guid.Data2);
  guid.Data3 = _byteswap_ushort(guid.Data3);

  sample->SetGUID(MFSampleExtension_Content_KeyID, guid);

  SB_DCHECK(sizeof(DWORD) * 2 == sizeof(SbDrmSubSampleMapping));

  SbDrmSubSampleMapping default_subsample = {0, sample_size};
  if (subsample_count == 0) {
    subsample_mapping = &default_subsample;
    subsample_count = 1;
  }
  sample->SetBlob(
      MFSampleExtension_Encryption_SubSampleMappingSplit,
      reinterpret_cast<const UINT8*>(subsample_mapping),
      static_cast<UINT32>(subsample_count * sizeof(SbDrmSubSampleMapping)));
}

}  // namespace

DecryptingDecoder::DecryptingDecoder(const std::string& type,
                                     scoped_ptr<MediaTransform> decoder,
                                     SbDrmSystem drm_system)
    : type_(type), decoder_(decoder.Pass()) {
  SB_DCHECK(decoder_.get());
  drm_system_ = static_cast<DrmSystemPlayready*>(drm_system);
}

DecryptingDecoder::~DecryptingDecoder() {
  Reset();
}

bool DecryptingDecoder::TryWriteInputBuffer(
    const scoped_refptr<InputBuffer>& input_buffer,
    int bytes_to_skip_in_sample) {
  SB_DCHECK(input_buffer);
  SB_DCHECK(bytes_to_skip_in_sample >= 0);

  ComPtr<IMFSample> input_sample;

  const SbDrmSampleInfo* drm_info = input_buffer->drm_info();
  const uint8_t* key_id = NULL;
  int key_id_size = 0;
  bool encrypted = false;

  if (drm_info != NULL && drm_info->identifier_size == 16 &&
      (drm_info->initialization_vector_size == 8 ||
       drm_info->initialization_vector_size == 16)) {
    key_id = drm_info->identifier;
    key_id_size = drm_info->identifier_size;
    encrypted = true;
  }

  if (input_buffer == last_input_buffer_) {
    SB_DCHECK(last_input_sample_);
    input_sample = last_input_sample_;
  } else {
    if (input_buffer->size() < bytes_to_skip_in_sample) {
      SB_NOTREACHED();
      return false;
    }

    const void* data = input_buffer->data() + bytes_to_skip_in_sample;
    int size = input_buffer->size() - bytes_to_skip_in_sample;

    std::int64_t win32_timestamp =
        ConvertUsecToWin32Time(input_buffer->timestamp());
    const uint8_t* iv = NULL;
    int iv_size = 0;
    const SbDrmSubSampleMapping* subsample_mapping = NULL;
    int subsample_count = 0;

    if (drm_info != NULL && drm_info->initialization_vector_size != 0) {
      if (bytes_to_skip_in_sample != 0) {
        if (drm_info->subsample_count != 0 && drm_info->subsample_count != 1) {
          return false;
        }
        if (drm_info->subsample_count == 1) {
          if (drm_info->subsample_mapping[0].clear_byte_count !=
              bytes_to_skip_in_sample) {
            return false;
          }
        }
      } else {
        subsample_mapping = drm_info->subsample_mapping;
        subsample_count = drm_info->subsample_count;
      }

      iv = drm_info->initialization_vector;
      iv_size = drm_info->initialization_vector_size;
    }

    // MFSampleExtension_CleanPoint is a key-frame for the video + audio. It is
    // not set here because the win32 system is smart enough to figure this out.
    // It will probably be totally ok to not set this at all. Resolution: If
    // there are problems with win32 video decoding, come back to this and see
    // if setting this will fix it. THis will be used if
    // SbMediaVideoSampleInfo::is_key_frame is true inside of the this function
    // (which will receive an InputBuffer).
    input_sample = CreateSample(data, size, win32_timestamp);

    if (encrypted) {
      AttachDrmDataToSample(input_sample, size, key_id, key_id_size, iv,
                            iv_size, subsample_mapping, subsample_count);
    }
    last_input_buffer_ = input_buffer;
    last_input_sample_ = input_sample;
  }

  if (encrypted) {
    if (!decryptor_) {
      if (decoder_->draining()) {
        return false;
      }
      if (!decoder_->drained()) {
        decoder_->Drain();
        return false;
      }
      decoder_->ResetFromDrained();
      scoped_refptr<DrmSystemPlayready::License> license =
          drm_system_->GetLicense(key_id, key_id_size);
      if (license && license->usable()) {
        decryptor_.reset(new MediaTransform(license->decryptor()));
        bool success = ActivateDecryptor();
        if (!success) {
          decryptor_.reset();
          return false;
        }
      }
    }
    if (!decryptor_) {
      SB_NOTREACHED();
      return false;
    }
  }

  if (encrypted) {
    return decryptor_->TryWrite(input_sample);
  }
  return decoder_->TryWrite(input_sample);
}

bool DecryptingDecoder::ProcessAndRead(ComPtr<IMFSample>* output,
                                       ComPtr<IMFMediaType>* new_type,
                                       bool* has_error) {
  bool did_something = false;

  *output = decoder_->TryRead(new_type);
  did_something |= *output != NULL;
  *has_error = decoder_->HasError();

  if (decryptor_) {
    if (!pending_decryptor_output_) {
      ComPtr<IMFMediaType> ignored_type;
      pending_decryptor_output_ = decryptor_->TryRead(&ignored_type);
      did_something |= pending_decryptor_output_ != NULL;
    }

    if (pending_decryptor_output_) {
      if (decoder_->TryWrite(pending_decryptor_output_)) {
        pending_decryptor_output_.Reset();
        did_something = true;
      }
    }

    if (decryptor_->drained() && !decoder_->draining() &&
        !decoder_->drained()) {
      decoder_->Drain();
      did_something = true;
    }
  }

  return did_something;
}

void DecryptingDecoder::Drain() {
  if (decryptor_) {
    decryptor_->Drain();
  } else {
    decoder_->Drain();
  }
}

bool DecryptingDecoder::ActivateDecryptor() {
  SB_DCHECK(decryptor_);

  ComPtr<IMFMediaType> decoder_output_type = decoder_->GetCurrentOutputType();
  decryptor_->SetInputType(decoder_->GetCurrentInputType());

  GUID original_sub_type;
  decoder_output_type->GetGUID(MF_MT_SUBTYPE, &original_sub_type);

  // Ensure that the decryptor and the decoder agrees on the protection of
  // samples transferred between them.
  ComPtr<IMFSampleProtection> decryption_sample_protection =
      decryptor_->GetSampleProtection();
  SB_DCHECK(decryption_sample_protection);

  DWORD decryption_protection_version;
  HRESULT hr = decryption_sample_protection->GetOutputProtectionVersion(
      &decryption_protection_version);
  CheckResult(hr);

  ComPtr<IMFSampleProtection> decoder_sample_protection =
      decoder_->GetSampleProtection();
  SB_DCHECK(decoder_sample_protection);

  DWORD decoder_protection_version;
  hr = decoder_sample_protection->GetInputProtectionVersion(
      &decoder_protection_version);
  CheckResult(hr);

  DWORD protection_version =
      std::min(decoder_protection_version, decryption_protection_version);
  if (protection_version < SAMPLE_PROTECTION_VERSION_RC4) {
    SB_NOTREACHED();
    return true;
  }

  BYTE* cert_data = NULL;
  DWORD cert_data_size = 0;

  hr = decoder_sample_protection->GetProtectionCertificate(
      protection_version, &cert_data, &cert_data_size);
  CheckResult(hr);

  BYTE* crypt_seed = NULL;
  DWORD crypt_seed_size = 0;
  hr = decryption_sample_protection->InitOutputProtection(
      protection_version, 0, cert_data, cert_data_size, &crypt_seed,
      &crypt_seed_size);
  if (FAILED(hr)) {
    // This can happen if we call InitOutputProtection while processing
    // a UWP resume event or shortly after.
    return false;
  }
  CheckResult(hr);

  hr = decoder_sample_protection->InitInputProtection(
      protection_version, 0, crypt_seed, crypt_seed_size);
  CheckResult(hr);

  CoTaskMemFree(cert_data);
  CoTaskMemFree(crypt_seed);

  // Ensure that the input type of the decoder is the output type of the
  // decryptor.
  ComPtr<IMFMediaType> decoder_input_type;
  std::vector<ComPtr<IMFMediaType>> decryptor_output_types =
      decryptor_->GetAvailableOutputTypes();
  SB_DCHECK(!decryptor_output_types.empty());

  decryptor_->SetOutputType(decryptor_output_types[0]);
  decoder_->SetInputType(decryptor_output_types[0]);

  std::vector<ComPtr<IMFMediaType>> decoder_output_types =
      decoder_->GetAvailableOutputTypes();
  for (auto output_type : decoder_output_types) {
    GUID sub_type;
    output_type->GetGUID(MF_MT_SUBTYPE, &sub_type);
    if (IsEqualGUID(sub_type, original_sub_type)) {
      decoder_->SetOutputType(output_type);
      return true;
    }
  }
  return true;
}

void DecryptingDecoder::Reset() {
  if (decryptor_) {
    decryptor_->Reset();
  }
  decoder_->Reset();

  last_input_buffer_ = nullptr;
  last_input_sample_ = nullptr;
}

}  // namespace win32
}  // namespace shared
}  // namespace starboard
