// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cobalt/media/base/decoder_buffer.h"

#include "cobalt/build/build_config.h"
#include "starboard/memory.h"

namespace cobalt {
namespace media {

DecoderBuffer::ScopedAllocatorPtr::ScopedAllocatorPtr(Allocator* allocator,
                                                      Type type, size_t size)
    : allocator_(allocator), type_(type) {
  if (size > 0) {
    DCHECK(allocator_);
    allocations_ = allocator_->Allocate(size + COBALT_MEDIA_BUFFER_PADDING,
                                        COBALT_MEDIA_BUFFER_ALIGNMENT,
                                        static_cast<intptr_t>(type));
#if COBALT_MEDIA_BUFFER_PADDING > 0
    if (allocations_.number_of_buffers() > 0) {
      char zeros[COBALT_MEDIA_BUFFER_PADDING + 1] = {0};
      allocations_.Write(size, zeros, COBALT_MEDIA_BUFFER_PADDING);
      allocations_.ShrinkTo(size);
    }
#endif  // COBALT_MEDIA_BUFFER_PADDING > 0
  }
}

DecoderBuffer::ScopedAllocatorPtr::~ScopedAllocatorPtr() {
  // |allocator_| can be NULL for EOS buffer.
  if (allocator_) {
    allocator_->Free(allocations_);
  }
}

DecoderBuffer::DecoderBuffer()
    : data_(NULL, DemuxerStream::UNKNOWN, 0),
      splice_timestamp_(kNoTimestamp),
      is_key_frame_(false) {}

DecoderBuffer::DecoderBuffer(Allocator* allocator, Type type, size_t size)
    : data_(allocator, type, size),
      splice_timestamp_(kNoTimestamp),
      is_key_frame_(false) {}

DecoderBuffer::DecoderBuffer(Allocator* allocator, Type type,
                             const uint8_t* data, size_t size)
    : data_(allocator, type, size),
      splice_timestamp_(kNoTimestamp),
      is_key_frame_(false) {
  if (!data) {
    CHECK_EQ(size, 0u);
    return;
  }

  allocations().Write(0, data, size);
}

DecoderBuffer::DecoderBuffer(Allocator* allocator, Type type,
                             Allocator::Allocations allocations)
    : data_(allocator, type, allocations.size()),
      splice_timestamp_(kNoTimestamp),
      is_key_frame_(false) {
  int offset = 0;
  for (int i = 0; i < allocations.number_of_buffers(); ++i) {
    this->allocations().Write(offset, allocations.buffers()[i],
                              allocations.buffer_sizes()[i]);
    offset += allocations.buffer_sizes()[i];
  }
}

DecoderBuffer::~DecoderBuffer() {}

// static
scoped_refptr<DecoderBuffer> DecoderBuffer::Create(Allocator* allocator,
                                                   Type type, size_t size) {
  DCHECK_GT(size, 0);
  scoped_refptr<DecoderBuffer> decoder_buffer =
      new DecoderBuffer(allocator, type, size);
  if (decoder_buffer->has_data()) {
    return decoder_buffer;
  }
  return NULL;
}

// static
scoped_refptr<DecoderBuffer> DecoderBuffer::CopyFrom(Allocator* allocator,
                                                     Type type,
                                                     const uint8_t* data,
                                                     size_t data_size) {
  // If you hit this CHECK you likely have a bug in a demuxer. Go fix it.
  CHECK(data);
  scoped_refptr<DecoderBuffer> decoder_buffer =
      new DecoderBuffer(allocator, type, data, data_size);
  if (decoder_buffer->has_data()) {
    return decoder_buffer;
  }
  return NULL;
}

// static
scoped_refptr<DecoderBuffer> DecoderBuffer::CreateEOSBuffer() {
  return make_scoped_refptr(new DecoderBuffer);
}

const char* DecoderBuffer::GetTypeName() const {
  switch (type()) {
    case DemuxerStream::AUDIO:
      return "audio";
    case DemuxerStream::VIDEO:
      return "video";
    case DemuxerStream::TEXT:
      return "text";
    case DemuxerStream::UNKNOWN:
      return "unknown";
    case DemuxerStream::NUM_TYPES:
      // Fall-through to NOTREACHED().
      break;
  }
  NOTREACHED();
  return "";
}

std::string DecoderBuffer::AsHumanReadableString() {
  if (end_of_stream()) {
    return "end of stream";
  }

  std::ostringstream s;
  s << "type: " << GetTypeName()
    << " timestamp: " << timestamp_.InMicroseconds()
    << " duration: " << duration_.InMicroseconds() << " size: " << data_size()
    << " is_key_frame: " << is_key_frame_
    << " encrypted: " << (decrypt_config_ != NULL) << " discard_padding (ms): ("
    << discard_padding_.first.InMilliseconds() << ", "
    << discard_padding_.second.InMilliseconds() << ")";

  if (decrypt_config_) s << " decrypt:" << (*decrypt_config_);

  return s.str();
}

void DecoderBuffer::set_timestamp(base::TimeDelta timestamp) {
  DCHECK(!end_of_stream());
  timestamp_ = timestamp;
}

}  // namespace media
}  // namespace cobalt
