#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "media/formats/mp4/mp4_stream_parser.h"
#include <stddef.h>
#include <limits>
#include <memory>
#include <utility>
#include <vector>
#include "base/functional/callback_helpers.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/encryption_pattern.h"
#include "media/base/encryption_scheme.h"
#include "media/base/media_client.h"
#include "media/base/media_tracks.h"
#include "media/base/media_util.h"
#include "media/base/stream_parser.h"
#include "media/base/stream_parser_buffer.h"
#include "media/base/timestamp_constants.h"
#include "media/base/video_codecs.h"
#include "media/base/video_decoder_config.h"
#include "media/base/video_util.h"
#include "media/formats/mp4/box_definitions.h"
#include "media/formats/mp4/box_reader.h"
#include "media/formats/mp4/es_descriptor.h"
#include "media/formats/mp4/rcheck.h"
#include "media/formats/mpeg/adts_constants.h"
namespace media::mp4 {
namespace {
const int kMaxEmptySampleLogs = …;
const int kMaxInvalidConversionLogs = …;
const int kMaxVideoKeyframeMismatchLogs = …;
EncryptionScheme GetEncryptionScheme(const ProtectionSchemeInfo& sinf) { … }
class ExternalMemoryAdapter : public DecoderBuffer::ExternalMemory { … };
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
base::HeapArray<uint8_t> PrepareAACBuffer(
const AAC& aac_config,
base::span<const uint8_t> frame_buf,
std::vector<SubsampleEntry>* subsamples) {
base::HeapArray<uint8_t> output_buffer;
int adts_header_size = 0;
if (aac_config.GetProfile() != AudioCodecProfile::kXHE_AAC) {
output_buffer = aac_config.CreateAdtsFromEsds(frame_buf, &adts_header_size);
} else {
output_buffer = base::HeapArray<uint8_t>::CopiedFrom(frame_buf);
}
if (output_buffer.empty()) {
return output_buffer;
}
if (subsamples->empty()) {
subsamples->emplace_back(adts_header_size, frame_buf.size());
} else {
(*subsamples)[0].clear_bytes += adts_header_size;
}
return output_buffer;
}
#endif
#if BUILDFLAG(ENABLE_PLATFORM_IAMF_AUDIO)
base::HeapArray<uint8_t> PrependIADescriptors(
const IamfSpecificBox& iacb,
base::span<const uint8_t> frame_buf,
std::vector<SubsampleEntry>* subsamples) {
const size_t descriptors_size = iacb.ia_descriptors.size();
const size_t total_size = frame_buf.size() + descriptors_size;
auto output_buffer = base::HeapArray<uint8_t>::Uninit(total_size);
output_buffer.copy_from(iacb.ia_descriptors);
output_buffer.last(frame_buf.size()).copy_from(frame_buf);
if (subsamples->empty()) {
subsamples->emplace_back(descriptors_size, frame_buf.size());
} else {
(*subsamples)[0].clear_bytes += descriptors_size;
}
return output_buffer;
}
#endif
}
MP4StreamParser::MP4StreamParser(
std::optional<base::flat_set<int>> strict_audio_object_types,
bool has_sbr,
bool has_flac,
bool has_iamf,
bool has_dv)
: … { … }
MP4StreamParser::~MP4StreamParser() = default;
void MP4StreamParser::Init(
InitCB init_cb,
NewConfigCB config_cb,
NewBuffersCB new_buffers_cb,
EncryptedMediaInitDataCB encrypted_media_init_data_cb,
NewMediaSegmentCB new_segment_cb,
EndMediaSegmentCB end_of_segment_cb,
MediaLog* media_log) { … }
void MP4StreamParser::Reset() { … }
void MP4StreamParser::Flush() { … }
bool MP4StreamParser::GetGenerateTimestampsFlag() const { … }
bool MP4StreamParser::AppendToParseBuffer(base::span<const uint8_t> buf) { … }
StreamParser::ParseStatus MP4StreamParser::Parse(
int max_pending_bytes_to_inspect) { … }
void MP4StreamParser::ModulatedPeek(const uint8_t** buf, int* size) { … }
void MP4StreamParser::ModulatedPeekAt(int64_t offset,
const uint8_t** buf,
int* size) { … }
bool MP4StreamParser::ModulatedTrim(int64_t max_offset) { … }
ParseResult MP4StreamParser::ParseBox() { … }
VideoTransformation MP4StreamParser::CalculateRotation(
const TrackHeader& track,
const MovieHeader& movie) { … }
bool MP4StreamParser::ParseMoov(BoxReader* reader) { … }
bool MP4StreamParser::ParseMoof(BoxReader* reader) { … }
void MP4StreamParser::OnEncryptedMediaInitData(
const std::vector<ProtectionSystemSpecificHeader>& headers) { … }
ParseResult MP4StreamParser::EnqueueSample(BufferQueueMap* buffers) { … }
bool MP4StreamParser::SendAndFlushSamples(BufferQueueMap* buffers) { … }
bool MP4StreamParser::ReadAndDiscardMDATsUntil(int64_t max_clear_offset) { … }
void MP4StreamParser::ChangeState(State new_state) { … }
bool MP4StreamParser::HaveEnoughDataToEnqueueSamples() { … }
bool MP4StreamParser::ComputeHighestEndOffset(const MovieFragment& moof) { … }
}