| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef MEDIA_FORMATS_MP4_WRITABLE_BOX_DEFINITIONS_H_ |
| #define MEDIA_FORMATS_MP4_WRITABLE_BOX_DEFINITIONS_H_ |
| |
| #include <string> |
| #include <vector> |
| |
| #include "base/containers/span.h" |
| #include "base/time/time.h" |
| #include "media/base/media_export.h" |
| #include "media/formats/mp4/box_definitions.h" |
| #include "media/formats/mp4/fourccs.h" |
| #include "media/media_buildflags.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| #include "ui/gfx/geometry/size.h" |
| |
| namespace media::mp4::writable_boxes { |
| |
| enum class TrackHeaderFlags : uint16_t { |
| kTrackEnabled = 0x0001, |
| kTrackInMovie = 0x0002, |
| kTrackInPreview = 0x0004, |
| }; |
| |
| enum class TrackFragmentHeaderFlags : uint32_t { |
| kBaseDataOffsetPresent = 0x0001, |
| kSampleDescriptionIndexPresent = 0x0002, |
| kDefaultSampleDurationPresent = 0x0008, |
| kDefaultSampleSizePresent = 0x0010, |
| kkDefaultSampleFlagsPresent = 0x0020, |
| |
| // This is `iso5` brand by spec on 14496-12, so can't be used |
| // with brand of `isom`, `avc1`, `iso2`. |
| |
| // https://www.w3.org/TR/mse-byte-stream-format-isobmff/ said that |
| // it should have `kDefaultBaseIsMoof', but not `kBaseDataOffsetPresent`. |
| kDefaultBaseIsMoof = 0x020000, |
| }; |
| |
| enum class TrackFragmentRunFlags : uint16_t { |
| kDataOffsetPresent = 0x0001, |
| kFirstSampleFlagsPresent = 0x0004, |
| kSampleDurationPresent = 0x0100, |
| kSampleSizePresent = 0x0200, |
| kSampleFlagsPresent = 0x0400, |
| }; |
| |
| enum class FragmentSampleFlags : uint32_t { |
| kSampleFlagIsNonSync = 0x00010000, |
| kSampleFlagDependsYes = 0x01000000, |
| kSampleFlagDependsNo = 0x02000000, |
| }; |
| |
| // Box header without version. |
| struct MEDIA_EXPORT Box {}; |
| |
| // Box header with version and flags. |
| struct MEDIA_EXPORT FullBox : Box { |
| // version 1 is 64 bits where applicable, 0 is 32 bits. |
| uint8_t version; |
| uint32_t flags : 24; |
| }; |
| |
| // Pixel Aspect Ratio Box (`pasp`) box. |
| struct MEDIA_EXPORT PixelAspectRatioBox : Box { |
| // It has relative width and height of a pixel. |
| // We use default value of 1 for both of these values. |
| }; |
| |
| // Bit Rate Box (`btrt`) box. |
| struct MEDIA_EXPORT BitRate : Box { |
| uint32_t max_bit_rate; |
| uint32_t avg_bit_rate; |
| }; |
| |
| #if BUILDFLAG(USE_PROPRIETARY_CODECS) |
| // Elementary Stream Descriptor (`esds`) box. |
| struct MEDIA_EXPORT ElementaryStreamDescriptor : FullBox { |
| ElementaryStreamDescriptor(); |
| ~ElementaryStreamDescriptor(); |
| ElementaryStreamDescriptor(const ElementaryStreamDescriptor&); |
| ElementaryStreamDescriptor& operator=(const ElementaryStreamDescriptor&); |
| |
| // ES descriptor 14496-1 |
| // DecoderConfigDescriptor (14496-1). |
| // AAC AudioSpecificConfig (14496-3). |
| std::vector<uint8_t> aac_codec_description; |
| }; |
| |
| // MP4A Audio Sample Entry (`mp4a`) box. |
| struct MEDIA_EXPORT AudioSampleEntry : Box { |
| uint32_t sample_rate; // AudioSampleEntry. |
| |
| ElementaryStreamDescriptor elementary_stream_descriptor; |
| BitRate bit_rate; |
| }; |
| |
| // AVC DecoderConfiguration Record (`avcc`) box. |
| struct MEDIA_EXPORT AVCDecoderConfiguration : Box { |
| // Refer AVCDecoderConfigurationRecord of box_definitions.h |
| // because it provides Serialize method and the format |
| // is hard to be correct. |
| AVCDecoderConfigurationRecord avc_config_record; |
| }; |
| |
| // VisualSampleEtnry (`avc1`) box. |
| struct MEDIA_EXPORT VisualSampleEntry : Box { |
| gfx::Size coded_size; |
| // It is formatted in a fixed 32-byte field, with the first |
| // byte set to the number of bytes to be displayed, followed |
| // by that number of bytes of displayable data, and then padding |
| // to complete 32 bytes total (including the size byte). |
| // The field may be set to 0. |
| |
| // It will have browser brand name. |
| std::string compressor_name; // char compressor_name[32]; |
| AVCDecoderConfiguration avc_decoder_configuration; |
| PixelAspectRatioBox pixel_aspect_ratio; |
| }; |
| #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) |
| |
| // Media sample table (`stsd`) box. |
| struct MEDIA_EXPORT SampleDescription : FullBox { |
| SampleDescription(); |
| ~SampleDescription(); |
| SampleDescription(const SampleDescription&); |
| SampleDescription& operator=(const SampleDescription&); |
| |
| uint32_t entry_count = 0; |
| |
| #if BUILDFLAG(USE_PROPRIETARY_CODECS) |
| absl::optional<VisualSampleEntry> visual_sample_entry; |
| absl::optional<AudioSampleEntry> audio_sample_entry; |
| #endif |
| }; |
| |
| // `stco`, `stsz`, `stts`, `stsc`' are mandatory boxes. |
| // They have 0 child entries in the fragment MP4. |
| |
| // Media sample table (`stco`) box. |
| struct MEDIA_EXPORT SampleChunkOffset : FullBox {}; |
| |
| // Media sample table (`stsz`) box. |
| struct MEDIA_EXPORT SampleSize : FullBox {}; |
| |
| // Decoding Time to Sample (`stts`) box. |
| struct MEDIA_EXPORT DecodingTimeToSample : FullBox {}; |
| |
| // Media sample table (`stsc`) box. |
| struct MEDIA_EXPORT SampleToChunk : FullBox {}; |
| |
| // Media sample table (`stbl`) box. |
| struct MEDIA_EXPORT SampleTable : Box { |
| SampleToChunk sample_to_chunk; |
| DecodingTimeToSample decoding_time_to_sample; |
| SampleSize sample_size; |
| SampleChunkOffset sample_chunk_offset; |
| SampleDescription sample_description; |
| }; |
| |
| // Data Url Entry (`url`) box. |
| struct MEDIA_EXPORT DataUrlEntry : FullBox {}; |
| |
| // Data Reference (`dref`) box. |
| struct MEDIA_EXPORT DataReference : FullBox { |
| DataReference(); |
| ~DataReference(); |
| DataReference(const DataReference&); |
| DataReference& operator=(const DataReference&); |
| |
| std::vector<DataUrlEntry> entries; |
| }; |
| |
| // Data Information (`dinf`) box. |
| struct MEDIA_EXPORT DataInformation : Box { |
| DataReference data_reference; |
| }; |
| |
| // Sound Media Information Header (`smdh`) box. |
| struct MEDIA_EXPORT SoundMediaHeader : FullBox { |
| // It has `balance` and `reserved` fields that |
| // has `0` as a default value. |
| }; |
| |
| // Video Media Information Header (`vmhd`) box. |
| struct MEDIA_EXPORT VideoMediaHeader : FullBox { |
| // It has `graphics_mode` and `op_color[3]` that |
| // has `0` as a default value. |
| }; |
| |
| // Media information (`minf`) box. |
| struct MEDIA_EXPORT MediaInformation : Box { |
| absl::optional<VideoMediaHeader> video_header; |
| absl::optional<SoundMediaHeader> sound_header; |
| DataInformation data_information; |
| SampleTable sample_table; |
| }; |
| |
| // Media Handler (`hdlr`) box. |
| struct MEDIA_EXPORT MediaHandler : FullBox { |
| mp4::FourCC handler_type; |
| std::string name; |
| }; |
| |
| // Media header (`mdhd`) box. |
| struct MEDIA_EXPORT MediaHeader : FullBox { |
| base::Time creation_time; |
| base::Time modification_time; |
| uint32_t timescale = 0; |
| base::TimeDelta duration; |
| std::string language; // 3 letters code ISO-639-2/T language. |
| }; |
| |
| // Media (`mdia`) box. |
| struct MEDIA_EXPORT Media : Box { |
| MediaHeader header; |
| MediaHandler handler; |
| MediaInformation information; |
| }; |
| |
| // Track header (`tkhd`) box. |
| struct MEDIA_EXPORT TrackHeader : FullBox { |
| uint32_t track_id; |
| base::Time creation_time; |
| base::Time modification_time; |
| base::TimeDelta duration; |
| bool is_audio; |
| gfx::Size natural_size; |
| }; |
| |
| // Track (`trak`) box. |
| struct MEDIA_EXPORT Track : Box { |
| TrackHeader header; |
| Media media; |
| }; |
| |
| // Track Extends (`trex`) box. |
| struct MEDIA_EXPORT TrackExtends : FullBox { |
| uint32_t track_id = 0; |
| uint32_t default_sample_description_index = 0; |
| base::TimeDelta default_sample_duration; |
| uint32_t default_sample_size = 0; |
| |
| // The sample flags field in sample fragments is coded as a 32-bit value. |
| // bit(4) reserved=0; |
| // unsigned int(2) is_leading; |
| // unsigned int(2) sample_depends_on; |
| // unsigned int(2) sample_is_depended_on; |
| // unsigned int(2) sample_has_redundancy; |
| // bit(3) sample_padding_value; |
| // bit(1) sample_is_non_sync_sample; |
| // unsigned int(16) sample_degradation_priority; |
| uint32_t default_sample_flags = 0; |
| }; |
| |
| // Movie Extends (`mvex`) box. |
| struct MEDIA_EXPORT MovieExtends : Box { |
| MovieExtends(); |
| ~MovieExtends(); |
| std::vector<TrackExtends> track_extends; |
| }; |
| |
| // Movie Header (`mvhd`) box. |
| struct MEDIA_EXPORT MovieHeader : FullBox { |
| MovieHeader(); |
| ~MovieHeader(); |
| |
| // It is Windows epoch time so it should be converted to Jan. 1, 1904 UTC |
| // before writing. Dates before Jan 1, 1904 UTC will fail / are unsupported. |
| base::Time creation_time; |
| base::Time modification_time; |
| |
| // This is the number of time units that pass in one second. |
| uint32_t timescale = 0; |
| base::TimeDelta duration; |
| uint32_t next_track_id = 0; |
| }; |
| |
| // Movie (`moov`) box. |
| struct MEDIA_EXPORT Movie : Box { |
| Movie(); |
| ~Movie(); |
| MovieHeader header; |
| std::vector<Track> tracks; |
| MovieExtends extends; |
| }; |
| |
| // Track Fragment Run (`trun`) box. |
| struct MEDIA_EXPORT TrackFragmentRun : FullBox { |
| TrackFragmentRun(); |
| ~TrackFragmentRun(); |
| TrackFragmentRun(const TrackFragmentRun&); |
| TrackFragmentRun& operator=(const TrackFragmentRun&); |
| |
| uint32_t sample_count; |
| uint32_t first_sample_flags; |
| |
| // Optional fields, presence is indicated in `flags`. If not present, the |
| // default value established in the `TrackFragmentHeader` is used. |
| std::vector<base::TimeTicks> sample_timestamps; |
| std::vector<uint32_t> sample_sizes; |
| std::vector<uint32_t> sample_flags; |
| // We don't support sample_composition_time_offsets as we don't know |
| // how to get it on given data. |
| }; |
| |
| // Track Fragment Decode Time (`tfdt`) box. |
| struct MEDIA_EXPORT TrackFragmentDecodeTime : Box { |
| uint32_t track_id; |
| base::TimeDelta base_media_decode_time; |
| }; |
| |
| // Track Fragment Header(`tfhd`) box. |
| struct MEDIA_EXPORT TrackFragmentHeader : FullBox { |
| uint32_t track_id; |
| |
| // `base_data_offset` will be calculated during fragment write. |
| // uint64_t base_data_offset; |
| base::TimeDelta default_sample_duration; |
| uint32_t default_sample_size; |
| uint32_t default_sample_flags; |
| }; |
| |
| // Track Fragment Header(`traf`) box. |
| struct MEDIA_EXPORT TrackFragment : Box { |
| TrackFragmentHeader header; |
| TrackFragmentDecodeTime decode_time; |
| TrackFragmentRun run; |
| }; |
| |
| // Movie Fragment Header(`mfhd`) box. |
| struct MEDIA_EXPORT MovieFragmentHeader : FullBox { |
| uint32_t sequence_number; |
| }; |
| |
| // Movie Fragment (`moof`) box. |
| struct MEDIA_EXPORT MovieFragment : Box { |
| MovieFragment(); |
| ~MovieFragment(); |
| MovieFragment(const MovieFragment&); |
| MovieFragment& operator=(const MovieFragment&); |
| |
| MovieFragmentHeader header; |
| std::vector<TrackFragment> track_fragments; |
| }; |
| |
| // Media Data (`mdat`) box. |
| struct MEDIA_EXPORT MediaData : Box { |
| MediaData(); |
| ~MediaData(); |
| MediaData(const MediaData&); |
| MediaData& operator=(const MediaData&); |
| std::vector<std::vector<uint8_t>> track_data; |
| }; |
| |
| // File Type (`ftyp`) box. |
| struct MEDIA_EXPORT FileType : Box { |
| FileType(); |
| ~FileType(); |
| uint32_t major_brand; |
| uint32_t minor_version; |
| std::vector<uint32_t> compatible_brands; |
| }; |
| |
| // Movie Track Fragment Random Access Box Entry. |
| struct TrackFragmentRandomAccessEntry { |
| base::TimeDelta time; |
| uint64_t moof_offset = 0; |
| uint32_t traf_number = 0; |
| uint32_t trun_number = 0; |
| uint32_t sample_number = 0; |
| }; |
| |
| // Movie Track Fragment Random Access Box (`tfra`) box. |
| struct MEDIA_EXPORT TrackFragmentRandomAccess : FullBox { |
| TrackFragmentRandomAccess(); |
| ~TrackFragmentRandomAccess(); |
| TrackFragmentRandomAccess(const TrackFragmentRandomAccess&); |
| TrackFragmentRandomAccess& operator=(const TrackFragmentRandomAccess&); |
| |
| uint32_t track_id; |
| std::vector<TrackFragmentRandomAccessEntry> entries; |
| }; |
| |
| // Movie Fragment Random Access Offset Box (`mfro`) box. |
| struct MEDIA_EXPORT FragmentRandomAccessOffset : Box { |
| // It is `mfra` box size and should be located at the last of |
| // enclosing `mfra` box. |
| }; |
| |
| // Movie Fragment Random Access Box (`mfra`) box. |
| struct MEDIA_EXPORT FragmentRandomAccess : Box { |
| FragmentRandomAccess(); |
| ~FragmentRandomAccess(); |
| |
| std::vector<TrackFragmentRandomAccess> tracks; |
| FragmentRandomAccessOffset offset; |
| }; |
| |
| } // namespace media::mp4::writable_boxes |
| |
| #endif // MEDIA_FORMATS_MP4_WRITABLE_BOX_DEFINITIONS_H_ |