// Copyright 2016 Google Inc. 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/starboard/player/input_buffer_internal.h"

#include <vector>

#include "starboard/atomic.h"
#include "starboard/log.h"
#include "starboard/memory.h"

namespace starboard {
namespace shared {
namespace starboard {
namespace player {

class InputBuffer::ReferenceCountedBuffer {
 public:
  ReferenceCountedBuffer(SbPlayerDeallocateSampleFunc deallocate_sample_func,
                         SbPlayer player,
                         void* context,
                         const void* sample_buffer,
                         int sample_buffer_size,
                         SbMediaTime sample_pts,
                         const SbMediaVideoSampleInfo* video_sample_info,
                         const SbDrmSampleInfo* sample_drm_info)
      : ref_count_(0),
        deallocate_sample_func_(deallocate_sample_func),
        player_(player),
        context_(context),
        data_(reinterpret_cast<const uint8_t*>(sample_buffer)),
        size_(sample_buffer_size),
        pts_(sample_pts),
        has_video_sample_info_(video_sample_info != NULL),
        has_drm_info_(sample_drm_info != NULL) {
    SB_DCHECK(deallocate_sample_func);
    if (has_video_sample_info_) {
      video_sample_info_ = *video_sample_info;
    }
    if (has_drm_info_) {
      drm_info_ = *sample_drm_info;
    }
  }

  void AddRef() const { SbAtomicBarrier_Increment(&ref_count_, 1); }
  void Release() const {
    if (SbAtomicBarrier_Increment(&ref_count_, -1) == 0) {
      delete this;
    }
  }

  const uint8_t* data() const { return data_; }
  int size() const { return size_; }
  SbMediaTime pts() const { return pts_; }
  const SbMediaVideoSampleInfo* video_sample_info() const {
    return has_video_sample_info_ ? &video_sample_info_ : NULL;
  }
  const SbDrmSampleInfo* drm_info() const {
    return has_drm_info_ ? &drm_info_ : NULL;
  }
  void SetDecryptedContent(const void* buffer, int size) {
    SB_DCHECK(size == size_);
    SB_DCHECK(deallocate_sample_func_);
    DeallocateSampleBuffer();

    if (size > 0) {
      decrypted_data_.resize(size);
      SbMemoryCopy(&decrypted_data_[0], buffer, size);
      data_ = &decrypted_data_[0];
    } else {
      data_ = NULL;
    }
    size_ = size;
    has_drm_info_ = false;
  }

 private:
  ~ReferenceCountedBuffer() { DeallocateSampleBuffer(); }

  void DeallocateSampleBuffer() {
    if (deallocate_sample_func_) {
      deallocate_sample_func_(player_, context_, const_cast<uint8_t*>(data_));
      deallocate_sample_func_ = NULL;
    }
  }

  mutable SbAtomic32 ref_count_;
  SbPlayerDeallocateSampleFunc deallocate_sample_func_;
  SbPlayer player_;
  void* context_;
  const uint8_t* data_;
  int size_;
  SbMediaTime pts_;
  bool has_video_sample_info_;
  SbMediaVideoSampleInfo video_sample_info_;
  bool has_drm_info_;
  SbDrmSampleInfo drm_info_;
  std::vector<uint8_t> decrypted_data_;

  SB_DISALLOW_COPY_AND_ASSIGN(ReferenceCountedBuffer);
};

InputBuffer::InputBuffer() : buffer_(NULL) {}

InputBuffer::InputBuffer(SbPlayerDeallocateSampleFunc deallocate_sample_func,
                         SbPlayer player,
                         void* context,
                         const void* sample_buffer,
                         int sample_buffer_size,
                         SbMediaTime sample_pts,
                         const SbMediaVideoSampleInfo* video_sample_info,
                         const SbDrmSampleInfo* sample_drm_info) {
  buffer_ = new ReferenceCountedBuffer(
      deallocate_sample_func, player, context, sample_buffer,
      sample_buffer_size, sample_pts, video_sample_info, sample_drm_info);
  buffer_->AddRef();
}

InputBuffer::InputBuffer(const InputBuffer& that) {
  buffer_ = that.buffer_;
  if (buffer_) {
    buffer_->AddRef();
  }
}

InputBuffer::~InputBuffer() {
  if (buffer_) {
    buffer_->Release();
  }
}

InputBuffer& InputBuffer::operator=(const InputBuffer& that) {
  if (that.buffer_) {
    that.buffer_->AddRef();
  }
  if (buffer_) {
    buffer_->Release();
  }
  buffer_ = that.buffer_;

  return *this;
}

const uint8_t* InputBuffer::data() const {
  SB_DCHECK(buffer_);
  return buffer_->data();
}

int InputBuffer::size() const {
  SB_DCHECK(buffer_);
  return buffer_->size();
}

SbMediaTime InputBuffer::pts() const {
  SB_DCHECK(buffer_);
  return buffer_->pts();
}

const SbMediaVideoSampleInfo* InputBuffer::video_sample_info() const {
  SB_DCHECK(buffer_);
  return buffer_->video_sample_info();
}

const SbDrmSampleInfo* InputBuffer::drm_info() const {
  SB_DCHECK(buffer_);
  return buffer_->drm_info();
}

void InputBuffer::SetDecryptedContent(const void* buffer, int size) {
  SB_DCHECK(buffer_);
  buffer_->SetDecryptedContent(buffer, size);
}

}  // namespace player
}  // namespace starboard
}  // namespace shared
}  // namespace starboard
