blob: 88b1f94421424b6711585e3c75523e79ac210ea8 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/base/stream_parser_buffer.h"
#include <algorithm>
#include "base/check_op.h"
#include "base/compiler_specific.h"
#include "base/containers/span.h"
#include "base/memory/scoped_refptr.h"
#include "base/numerics/safe_conversions.h"
#include "base/types/pass_key.h"
#include "media/base/media_client.h"
#include "media/base/timestamp_constants.h"
namespace media {
static_assert(StreamParserBuffer::Type::TYPE_MAX < 4,
"StreamParserBuffer::type_ has a max storage size of two bits.");
scoped_refptr<StreamParserBuffer> StreamParserBuffer::CreateEOSBuffer(
std::optional<ConfigVariant> next_config) {
return base::MakeRefCounted<StreamParserBuffer>(
base::PassKey<StreamParserBuffer>(), DecoderBufferType::kEndOfStream,
std::move(next_config));
}
scoped_refptr<StreamParserBuffer> StreamParserBuffer::CopyFrom(
const uint8_t* data,
int data_size,
bool is_key_frame,
Type type,
TrackId track_id) {
if (auto* media_client = GetMediaClient()) {
if (auto* alloc = media_client->GetMediaAllocator()) {
auto data_span =
UNSAFE_TODO(base::span(data, base::checked_cast<size_t>(data_size)));
return StreamParserBuffer::FromExternalMemory(
alloc->CopyFrom(data_span), is_key_frame, type, track_id);
}
}
return base::MakeRefCounted<StreamParserBuffer>(
base::PassKey<StreamParserBuffer>(), data, data_size, is_key_frame, type,
track_id);
}
scoped_refptr<StreamParserBuffer> StreamParserBuffer::FromExternalMemory(
std::unique_ptr<ExternalMemory> external_memory,
bool is_key_frame,
Type type,
TrackId track_id) {
return base::MakeRefCounted<StreamParserBuffer>(
base::PassKey<StreamParserBuffer>(), std::move(external_memory),
is_key_frame, type, track_id);
}
scoped_refptr<StreamParserBuffer> StreamParserBuffer::FromArray(
base::HeapArray<uint8_t> heap_array,
bool is_key_frame,
Type type,
TrackId track_id) {
return base::MakeRefCounted<StreamParserBuffer>(
base::PassKey<StreamParserBuffer>(), std::move(heap_array), is_key_frame,
type, track_id);
}
DecodeTimestamp StreamParserBuffer::GetDecodeTimestamp() const {
if (decode_timestamp_ == kNoDecodeTimestamp)
return DecodeTimestamp::FromPresentationTime(timestamp());
return decode_timestamp_;
}
void StreamParserBuffer::SetDecodeTimestamp(DecodeTimestamp timestamp) {
decode_timestamp_ = timestamp;
if (preroll_buffer_)
preroll_buffer_->SetDecodeTimestamp(timestamp);
}
StreamParserBuffer::StreamParserBuffer(
base::PassKey<StreamParserBuffer>,
std::unique_ptr<ExternalMemory> external_memory,
bool is_key_frame,
Type type,
TrackId track_id)
: DecoderBuffer(std::move(external_memory)),
type_(type),
track_id_(track_id) {
set_duration(kNoTimestamp);
set_is_key_frame(is_key_frame);
}
StreamParserBuffer::StreamParserBuffer(base::PassKey<StreamParserBuffer>,
base::HeapArray<uint8_t> heap_array,
bool is_key_frame,
Type type,
TrackId track_id)
: DecoderBuffer(std::move(heap_array)), type_(type), track_id_(track_id) {
set_duration(kNoTimestamp);
set_is_key_frame(is_key_frame);
}
StreamParserBuffer::StreamParserBuffer(base::PassKey<StreamParserBuffer>,
const uint8_t* data,
int data_size,
bool is_key_frame,
Type type,
TrackId track_id)
: DecoderBuffer(
// TODO(crbug.com/40284755): Convert `StreamBufferParser` to
// `size_t` and `base::span`.
UNSAFE_TODO(base::span(data, base::checked_cast<size_t>(data_size)))),
type_(type),
track_id_(track_id) {
// TODO(scherkus): Should DataBuffer constructor accept a timestamp and
// duration to force clients to set them? Today they end up being zero which
// is both a common and valid value and could lead to bugs.
if (data) {
set_duration(kNoTimestamp);
}
if (is_key_frame)
set_is_key_frame(true);
}
StreamParserBuffer::StreamParserBuffer(base::PassKey<StreamParserBuffer>,
DecoderBufferType decoder_buffer_type,
std::optional<ConfigVariant> next_config)
: DecoderBuffer(decoder_buffer_type, next_config),
type_(Type::UNKNOWN),
track_id_(-1) {}
StreamParserBuffer::~StreamParserBuffer() = default;
int StreamParserBuffer::GetConfigId() const {
return config_id_;
}
void StreamParserBuffer::SetConfigId(int config_id) {
config_id_ = config_id;
if (preroll_buffer_)
preroll_buffer_->SetConfigId(config_id);
}
const char* StreamParserBuffer::GetTypeName() const {
return DemuxerStream::GetTypeName(type());
}
void StreamParserBuffer::SetPrerollBuffer(
scoped_refptr<StreamParserBuffer> preroll_buffer) {
DCHECK(!preroll_buffer_);
DCHECK(!end_of_stream());
DCHECK(!preroll_buffer->end_of_stream());
DCHECK(!preroll_buffer->preroll_buffer_);
DCHECK(preroll_buffer->timestamp() <= timestamp());
DCHECK(preroll_buffer->discard_padding() == DecoderBuffer::DiscardPadding());
DCHECK_EQ(preroll_buffer->type(), type());
DCHECK_EQ(preroll_buffer->track_id(), track_id());
preroll_buffer_ = std::move(preroll_buffer);
preroll_buffer_->set_timestamp(timestamp());
preroll_buffer_->SetConfigId(GetConfigId());
preroll_buffer_->SetDecodeTimestamp(GetDecodeTimestamp());
// Mark the entire buffer for discard.
preroll_buffer_->set_discard_padding(
std::make_pair(kInfiniteDuration, base::TimeDelta()));
}
void StreamParserBuffer::set_timestamp(base::TimeDelta timestamp) {
DecoderBuffer::set_timestamp(timestamp);
if (preroll_buffer_)
preroll_buffer_->set_timestamp(timestamp);
}
size_t StreamParserBuffer::GetMemoryUsage() const {
size_t memory_usage = DecoderBuffer::GetMemoryUsage() -
sizeof(DecoderBuffer) + sizeof(StreamParserBuffer);
if (preroll_buffer_) {
memory_usage += preroll_buffer_->GetMemoryUsage();
}
return memory_usage;
}
} // namespace media