blob: 919f9ca06bc326e7278cd01217770a03f7220ebe [file] [log] [blame]
// 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