// 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. #ifndef MEDIA_BASE_DECODER_BUFFER_H_ #define MEDIA_BASE_DECODER_BUFFER_H_ #include #include #include #include #include #include "base/check.h" #include "base/macros.h" #include "base/memory/read_only_shared_memory_region.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "build/build_config.h" #include "media/base/decrypt_config.h" #include "media/base/media_export.h" #include "media/base/timestamp_constants.h" #include "media/base/unaligned_shared_memory.h" namespace media { // A specialized buffer for interfacing with audio / video decoders. // // Also includes decoder specific functionality for decryption. // // NOTE: It is illegal to call any method when end_of_stream() is true. class MEDIA_EXPORT DecoderBuffer : public base::RefCountedThreadSafe { public: enum { kPaddingSize = 64, #if defined(ARCH_CPU_ARM_FAMILY) kAlignmentSize = 16 #else kAlignmentSize = 32 #endif }; // Allocates buffer with |size| >= 0. |is_key_frame_| will default to false. explicit DecoderBuffer(size_t size); // Create a DecoderBuffer whose |data_| is copied from |data|. |data| must not // be NULL and |size| >= 0. The buffer's |is_key_frame_| will default to // false. static scoped_refptr CopyFrom(const uint8_t* data, size_t size); // Create a DecoderBuffer whose |data_| is copied from |data| and |side_data_| // is copied from |side_data|. Data pointers must not be NULL and sizes must // be >= 0. The buffer's |is_key_frame_| will default to false. static scoped_refptr CopyFrom(const uint8_t* data, size_t size, const uint8_t* side_data, size_t side_data_size); // Create a DecoderBuffer where data() of |size| bytes resides within the heap // as byte array. The buffer's |is_key_frame_| will default to false. // // Ownership of |data| is transferred to the buffer. static scoped_refptr FromArray(std::unique_ptr data, size_t size); // Create a DecoderBuffer where data() of |size| bytes resides within the // memory referred to by |region| at non-negative offset |offset|. The // buffer's |is_key_frame_| will default to false. // // The shared memory will be mapped read-only. // // If mapping fails, nullptr will be returned. static scoped_refptr FromSharedMemoryRegion( base::subtle::PlatformSharedMemoryRegion region, off_t offset, size_t size); // Create a DecoderBuffer where data() of |size| bytes resides within the // ReadOnlySharedMemoryRegion referred to by |mapping| at non-negative offset // |offset|. The buffer's |is_key_frame_| will default to false. // // Ownership of |region| is transferred to the buffer. static scoped_refptr FromSharedMemoryRegion( base::ReadOnlySharedMemoryRegion region, off_t offset, size_t size); // Create a DecoderBuffer indicating we've reached end of stream. // // Calling any method other than end_of_stream() on the resulting buffer // is disallowed. static scoped_refptr CreateEOSBuffer(); base::TimeDelta timestamp() const { DCHECK(!end_of_stream()); return timestamp_; } // TODO(dalecurtis): This should be renamed at some point, but to avoid a yak // shave keep as a virtual with hacker_style() for now. virtual void set_timestamp(base::TimeDelta timestamp); base::TimeDelta duration() const { DCHECK(!end_of_stream()); return duration_; } void set_duration(base::TimeDelta duration) { DCHECK(!end_of_stream()); DCHECK(duration == kNoTimestamp || (duration >= base::TimeDelta() && duration != kInfiniteDuration)) << duration.InSecondsF(); duration_ = duration; } const uint8_t* data() const { DCHECK(!end_of_stream()); if (shared_mem_mapping_ && shared_mem_mapping_->IsValid()) return static_cast(shared_mem_mapping_->memory()); if (shm_) return static_cast(shm_->memory()); return data_.get(); } // TODO(sandersd): Remove writable_data(). https://crbug.com/834088 uint8_t* writable_data() const { DCHECK(!end_of_stream()); DCHECK(!shm_); DCHECK(!shared_mem_mapping_); return data_.get(); } size_t data_size() const { DCHECK(!end_of_stream()); return size_; } const uint8_t* side_data() const { DCHECK(!end_of_stream()); return side_data_.get(); } size_t side_data_size() const { DCHECK(!end_of_stream()); return side_data_size_; } typedef std::pair DiscardPadding; const DiscardPadding& discard_padding() const { DCHECK(!end_of_stream()); return discard_padding_; } void set_discard_padding(const DiscardPadding& discard_padding) { DCHECK(!end_of_stream()); discard_padding_ = discard_padding; } // Returns DecryptConfig associated with |this|. Returns null iff |this| is // not encrypted. const DecryptConfig* decrypt_config() const { DCHECK(!end_of_stream()); return decrypt_config_.get(); } void set_decrypt_config(std::unique_ptr decrypt_config) { DCHECK(!end_of_stream()); decrypt_config_ = std::move(decrypt_config); } // If there's no data in this buffer, it represents end of stream. bool end_of_stream() const { return !shared_mem_mapping_ && !shm_ && !data_; } bool is_key_frame() const { DCHECK(!end_of_stream()); return is_key_frame_; } void set_is_key_frame(bool is_key_frame) { DCHECK(!end_of_stream()); is_key_frame_ = is_key_frame; } // Returns true if all fields in |buffer| matches this buffer // including |data_| and |side_data_|. bool MatchesForTesting(const DecoderBuffer& buffer) const; // Returns a human-readable string describing |*this|. std::string AsHumanReadableString(bool verbose = false) const; // Replaces any existing side data with data copied from |side_data|. void CopySideDataFrom(const uint8_t* side_data, size_t side_data_size); protected: friend class base::RefCountedThreadSafe; // Allocates a buffer of size |size| >= 0 and copies |data| into it. If |data| // is NULL then |data_| is set to NULL and |buffer_size_| to 0. // |is_key_frame_| will default to false. DecoderBuffer(const uint8_t* data, size_t size, const uint8_t* side_data, size_t side_data_size); DecoderBuffer(std::unique_ptr data, size_t size); DecoderBuffer(std::unique_ptr shm, size_t size); DecoderBuffer(std::unique_ptr shared_mem_mapping, size_t size); virtual ~DecoderBuffer(); // Encoded data, if it is stored on the heap. std::unique_ptr data_; private: // Presentation time of the frame. base::TimeDelta timestamp_; // Presentation duration of the frame. base::TimeDelta duration_; // Size of the encoded data. size_t size_; // Side data. Used for alpha channel in VPx, and for text cues. size_t side_data_size_; std::unique_ptr side_data_; // Encoded data, if it is stored in a shared memory mapping. std::unique_ptr shared_mem_mapping_; // Encoded data, if it is stored in SHM. std::unique_ptr shm_; // Encryption parameters for the encoded data. std::unique_ptr decrypt_config_; // Duration of (audio) samples from the beginning and end of this frame which // should be discarded after decoding. A value of kInfiniteDuration for the // first value indicates the entire frame should be discarded; the second // value must be base::TimeDelta() in this case. DiscardPadding discard_padding_; // Whether the frame was marked as a keyframe in the container. bool is_key_frame_; // Constructor helper method for memory allocations. void Initialize(); DISALLOW_COPY_AND_ASSIGN(DecoderBuffer); }; } // namespace media #endif // MEDIA_BASE_DECODER_BUFFER_H_