| // 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 "media/base/decoder_buffer.h" |
| |
| |
| namespace media { |
| |
| // Allocates a block of memory which is padded for use with the SIMD |
| // optimizations used by FFmpeg. |
| static uint8* AllocateFFmpegSafeBlock(int size) { |
| uint8* const block = reinterpret_cast<uint8*>(base::AlignedAlloc( |
| size + DecoderBuffer::kPaddingSize, DecoderBuffer::kAlignmentSize)); |
| memset(block + size, 0, DecoderBuffer::kPaddingSize); |
| return block; |
| } |
| |
| DecoderBuffer::DecoderBuffer(int size) |
| : size_(size), |
| side_data_size_(0), |
| is_key_frame_(false) { |
| Initialize(); |
| } |
| |
| DecoderBuffer::DecoderBuffer(const uint8* data, |
| int size, |
| const uint8* side_data, |
| int side_data_size) |
| : size_(size), |
| side_data_size_(side_data_size), |
| is_key_frame_(false) { |
| if (!data) { |
| CHECK_EQ(size_, 0); |
| CHECK(!side_data); |
| return; |
| } |
| |
| Initialize(); |
| |
| DCHECK_GE(size_, 0); |
| memcpy(data_.get(), data, size_); |
| |
| if (!side_data) { |
| CHECK_EQ(side_data_size, 0); |
| return; |
| } |
| |
| DCHECK_GT(side_data_size_, 0); |
| memcpy(side_data_.get(), side_data, side_data_size_); |
| } |
| |
| DecoderBuffer::~DecoderBuffer() {} |
| |
| void DecoderBuffer::Initialize() { |
| CHECK_GE(size_, 0); |
| data_.reset(AllocateFFmpegSafeBlock(size_)); |
| if (side_data_size_ > 0) |
| side_data_.reset(AllocateFFmpegSafeBlock(side_data_size_)); |
| splice_timestamp_ = kNoTimestamp(); |
| } |
| |
| // static |
| scoped_refptr<DecoderBuffer> DecoderBuffer::CopyFrom(const uint8* data, |
| int data_size) { |
| // If you hit this CHECK you likely have a bug in a demuxer. Go fix it. |
| CHECK(data); |
| return make_scoped_refptr(new DecoderBuffer(data, data_size, NULL, 0)); |
| } |
| |
| // static |
| scoped_refptr<DecoderBuffer> DecoderBuffer::CopyFrom(const uint8* data, |
| int data_size, |
| const uint8* side_data, |
| int side_data_size) { |
| // If you hit this CHECK you likely have a bug in a demuxer. Go fix it. |
| CHECK(data); |
| CHECK(side_data); |
| return make_scoped_refptr(new DecoderBuffer(data, data_size, |
| side_data, side_data_size)); |
| } |
| |
| // static |
| scoped_refptr<DecoderBuffer> DecoderBuffer::CreateEOSBuffer() { |
| return make_scoped_refptr(new DecoderBuffer(NULL, 0, NULL, 0)); |
| } |
| |
| std::string DecoderBuffer::AsHumanReadableString() { |
| if (end_of_stream()) { |
| return "end of stream"; |
| } |
| |
| std::ostringstream s; |
| s << "timestamp: " << timestamp_.InMicroseconds() |
| << " duration: " << duration_.InMicroseconds() |
| << " size: " << size_ |
| << " side_data_size: " << side_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; |
| } |
| |
| void DecoderBuffer::CopySideDataFrom(const uint8* side_data, |
| int side_data_size) { |
| if (side_data_size > 0) { |
| side_data_size_ = side_data_size; |
| side_data_.reset(AllocateFFmpegSafeBlock(side_data_size_)); |
| memcpy(side_data_.get(), side_data, side_data_size_); |
| } else { |
| side_data_.reset(); |
| side_data_size_ = 0; |
| } |
| } |
| |
| } // namespace media |