Implement mp4 box read/write.
The box may be optimized if necessary during writing. Change-Id: I7a46e72a0bcbeacb23085a87e1f0df3a826e4da7
This commit is contained in:
parent
0f3bc4b6b4
commit
57474b31d6
File diff suppressed because it is too large
Load Diff
|
@ -9,10 +9,14 @@
|
|||
#include <vector>
|
||||
|
||||
#include "media/mp4/aac.h"
|
||||
#include "media/mp4/box_reader.h"
|
||||
#include "media/mp4/box.h"
|
||||
#include "media/mp4/es_descriptor.h"
|
||||
#include "media/mp4/fourccs.h"
|
||||
|
||||
namespace media {
|
||||
|
||||
class BufferReader;
|
||||
|
||||
namespace mp4 {
|
||||
|
||||
enum TrackType {
|
||||
|
@ -22,33 +26,42 @@ enum TrackType {
|
|||
kHint
|
||||
};
|
||||
|
||||
#define DECLARE_BOX_METHODS(T) \
|
||||
T(); \
|
||||
virtual ~T(); \
|
||||
virtual bool Parse(BoxReader* reader) OVERRIDE; \
|
||||
virtual FourCC BoxType() const OVERRIDE; \
|
||||
class BoxBuffer;
|
||||
|
||||
#define DECLARE_BOX_METHODS(T) \
|
||||
T(); \
|
||||
virtual ~T(); \
|
||||
virtual bool ReadWrite(BoxBuffer* buffer) OVERRIDE; \
|
||||
virtual FourCC BoxType() const OVERRIDE; \
|
||||
virtual uint32 ComputeSize() OVERRIDE;
|
||||
|
||||
struct FileType : Box {
|
||||
DECLARE_BOX_METHODS(FileType);
|
||||
|
||||
FourCC major_brand;
|
||||
uint32 minor_version;
|
||||
std::vector<FourCC> compatible_brands;
|
||||
};
|
||||
|
||||
struct ProtectionSystemSpecificHeader : Box {
|
||||
struct SegmentType : FileType {
|
||||
DECLARE_BOX_METHODS(SegmentType);
|
||||
};
|
||||
|
||||
struct ProtectionSystemSpecificHeader : FullBox {
|
||||
DECLARE_BOX_METHODS(ProtectionSystemSpecificHeader);
|
||||
|
||||
std::vector<uint8> system_id;
|
||||
std::vector<uint8> data;
|
||||
std::vector<uint8> raw_box;
|
||||
};
|
||||
|
||||
struct SampleAuxiliaryInformationOffset : Box {
|
||||
struct SampleAuxiliaryInformationOffset : FullBox {
|
||||
DECLARE_BOX_METHODS(SampleAuxiliaryInformationOffset);
|
||||
|
||||
std::vector<uint64> offsets;
|
||||
};
|
||||
|
||||
struct SampleAuxiliaryInformationSize : Box {
|
||||
struct SampleAuxiliaryInformationSize : FullBox {
|
||||
DECLARE_BOX_METHODS(SampleAuxiliaryInformationSize);
|
||||
|
||||
uint8 default_sample_info_size;
|
||||
|
@ -62,14 +75,14 @@ struct OriginalFormat : Box {
|
|||
FourCC format;
|
||||
};
|
||||
|
||||
struct SchemeType : Box {
|
||||
struct SchemeType : FullBox {
|
||||
DECLARE_BOX_METHODS(SchemeType);
|
||||
|
||||
FourCC type;
|
||||
uint32 version;
|
||||
};
|
||||
|
||||
struct TrackEncryption : Box {
|
||||
struct TrackEncryption : FullBox {
|
||||
DECLARE_BOX_METHODS(TrackEncryption);
|
||||
|
||||
// Note: this definition is specific to the CENC protection type.
|
||||
|
@ -92,7 +105,7 @@ struct ProtectionSchemeInfo : Box {
|
|||
SchemeInfo info;
|
||||
};
|
||||
|
||||
struct MovieHeader : Box {
|
||||
struct MovieHeader : FullBox {
|
||||
DECLARE_BOX_METHODS(MovieHeader);
|
||||
|
||||
uint64 creation_time;
|
||||
|
@ -104,7 +117,13 @@ struct MovieHeader : Box {
|
|||
uint32 next_track_id;
|
||||
};
|
||||
|
||||
struct TrackHeader : Box {
|
||||
struct TrackHeader : FullBox {
|
||||
enum TrackHeaderFlags {
|
||||
kTrackEnabled = 0x000001,
|
||||
kTrackInMovie = 0x000002,
|
||||
kTrackInPreview = 0x000004,
|
||||
};
|
||||
|
||||
DECLARE_BOX_METHODS(TrackHeader);
|
||||
|
||||
uint64 creation_time;
|
||||
|
@ -125,7 +144,7 @@ struct EditListEntry {
|
|||
int16 media_rate_fraction;
|
||||
};
|
||||
|
||||
struct EditList : Box {
|
||||
struct EditList : FullBox {
|
||||
DECLARE_BOX_METHODS(EditList);
|
||||
|
||||
std::vector<EditListEntry> edits;
|
||||
|
@ -137,7 +156,7 @@ struct Edit : Box {
|
|||
EditList list;
|
||||
};
|
||||
|
||||
struct HandlerReference : Box {
|
||||
struct HandlerReference : FullBox {
|
||||
DECLARE_BOX_METHODS(HandlerReference);
|
||||
|
||||
TrackType type;
|
||||
|
@ -188,11 +207,11 @@ struct VideoSampleEntry : Box {
|
|||
AVCDecoderConfigurationRecord avcc;
|
||||
};
|
||||
|
||||
struct ElementaryStreamDescriptor : Box {
|
||||
struct ElementaryStreamDescriptor : FullBox {
|
||||
DECLARE_BOX_METHODS(ElementaryStreamDescriptor);
|
||||
|
||||
uint8 object_type;
|
||||
AAC aac;
|
||||
ESDescriptor es_descriptor;
|
||||
};
|
||||
|
||||
struct AudioSampleEntry : Box {
|
||||
|
@ -208,7 +227,7 @@ struct AudioSampleEntry : Box {
|
|||
ElementaryStreamDescriptor esds;
|
||||
};
|
||||
|
||||
struct SampleDescription : Box {
|
||||
struct SampleDescription : FullBox {
|
||||
DECLARE_BOX_METHODS(SampleDescription);
|
||||
|
||||
TrackType type;
|
||||
|
@ -222,7 +241,7 @@ struct DecodingTime {
|
|||
};
|
||||
|
||||
// stts.
|
||||
struct DecodingTimeToSample : Box {
|
||||
struct DecodingTimeToSample : FullBox {
|
||||
DECLARE_BOX_METHODS(DecodingTimeToSample);
|
||||
|
||||
std::vector<DecodingTime> decoding_time;
|
||||
|
@ -232,13 +251,13 @@ struct CompositionOffset {
|
|||
uint32 sample_count;
|
||||
// If version == 0, sample_offset is uint32;
|
||||
// If version == 1, sample_offset is int32.
|
||||
// Let us always use signed version, which should work unless the offset
|
||||
// Always use signed version, which should work unless the offset
|
||||
// exceeds 31 bits, which shouldn't happen.
|
||||
int32 sample_offset;
|
||||
};
|
||||
|
||||
// ctts. Optional.
|
||||
struct CompositionTimeToSample : Box {
|
||||
struct CompositionTimeToSample : FullBox {
|
||||
DECLARE_BOX_METHODS(CompositionTimeToSample);
|
||||
|
||||
std::vector<CompositionOffset> composition_offset;
|
||||
|
@ -251,14 +270,14 @@ struct ChunkInfo {
|
|||
};
|
||||
|
||||
// stsc.
|
||||
struct SampleToChunk : Box {
|
||||
struct SampleToChunk : FullBox {
|
||||
DECLARE_BOX_METHODS(SampleToChunk);
|
||||
|
||||
std::vector<ChunkInfo> chunk_info;
|
||||
};
|
||||
|
||||
// stsz.
|
||||
struct SampleSize : Box {
|
||||
struct SampleSize : FullBox {
|
||||
DECLARE_BOX_METHODS(SampleSize);
|
||||
|
||||
uint32 sample_size;
|
||||
|
@ -267,27 +286,27 @@ struct SampleSize : Box {
|
|||
};
|
||||
|
||||
// stz2.
|
||||
struct CompactSampleSize : SampleSize {
|
||||
struct CompactSampleSize : FullBox {
|
||||
DECLARE_BOX_METHODS(CompactSampleSize);
|
||||
};
|
||||
|
||||
// stco.
|
||||
struct ChunkOffset : Box {
|
||||
DECLARE_BOX_METHODS(ChunkOffset);
|
||||
|
||||
// Chunk byte offsets into mdat relative to the beginning of the file.
|
||||
// Use 64 bits instead of 32 bits so it is large enough to hold
|
||||
// ChunkLargeOffset data.
|
||||
std::vector<uint64> offsets;
|
||||
uint8 field_size;
|
||||
std::vector<uint32> sizes;
|
||||
};
|
||||
|
||||
// co64.
|
||||
struct ChunkLargeOffset : ChunkOffset {
|
||||
struct ChunkLargeOffset : FullBox {
|
||||
DECLARE_BOX_METHODS(ChunkLargeOffset);
|
||||
|
||||
std::vector<uint64> offsets;
|
||||
};
|
||||
|
||||
// stco.
|
||||
struct ChunkOffset : ChunkLargeOffset {
|
||||
DECLARE_BOX_METHODS(ChunkOffset);
|
||||
};
|
||||
|
||||
// stss. Optional.
|
||||
struct SyncSample : Box {
|
||||
struct SyncSample : FullBox {
|
||||
DECLARE_BOX_METHODS(SyncSample);
|
||||
|
||||
std::vector<uint32> sample_number;
|
||||
|
@ -302,12 +321,13 @@ struct SampleTable : Box {
|
|||
SampleToChunk sample_to_chunk;
|
||||
// Either SampleSize or CompactSampleSize must present. Store in SampleSize.
|
||||
SampleSize sample_size;
|
||||
// Either ChunkOffset or ChunkLargeOffset must present. Store in ChunkOffset.
|
||||
ChunkOffset chunk_offset;
|
||||
// Either ChunkOffset or ChunkLargeOffset must present. Store in
|
||||
// ChunkLargeOffset.
|
||||
ChunkLargeOffset chunk_large_offset;
|
||||
SyncSample sync_sample;
|
||||
};
|
||||
|
||||
struct MediaHeader : Box {
|
||||
struct MediaHeader : FullBox {
|
||||
DECLARE_BOX_METHODS(MediaHeader);
|
||||
|
||||
uint64 creation_time;
|
||||
|
@ -318,10 +338,48 @@ struct MediaHeader : Box {
|
|||
char language[4];
|
||||
};
|
||||
|
||||
struct VideoMediaHeader : FullBox {
|
||||
DECLARE_BOX_METHODS(VideoMediaHeader);
|
||||
|
||||
uint16 graphicsmode;
|
||||
uint16 opcolor_red;
|
||||
uint16 opcolor_green;
|
||||
uint16 opcolor_blue;
|
||||
};
|
||||
|
||||
struct SoundMediaHeader : FullBox {
|
||||
DECLARE_BOX_METHODS(SoundMediaHeader);
|
||||
|
||||
uint16 balance;
|
||||
};
|
||||
|
||||
struct DataEntryUrl : FullBox {
|
||||
DECLARE_BOX_METHODS(DataEntryUrl);
|
||||
|
||||
std::vector<uint8> location;
|
||||
};
|
||||
|
||||
struct DataReference : FullBox {
|
||||
DECLARE_BOX_METHODS(DataReference);
|
||||
|
||||
// data entry can be either url or urn box. Fix to url box for now.
|
||||
std::vector<DataEntryUrl> data_entry;
|
||||
};
|
||||
|
||||
struct DataInformation : Box {
|
||||
DECLARE_BOX_METHODS(DataInformation);
|
||||
|
||||
DataReference dref;
|
||||
};
|
||||
|
||||
struct MediaInformation : Box {
|
||||
DECLARE_BOX_METHODS(MediaInformation);
|
||||
|
||||
DataInformation dinf;
|
||||
SampleTable sample_table;
|
||||
// Exactly one specific meida header shall be present, vmhd, smhd, hmhd, nmhd.
|
||||
VideoMediaHeader vmhd;
|
||||
SoundMediaHeader smhd;
|
||||
};
|
||||
|
||||
struct Media : Box {
|
||||
|
@ -340,13 +398,13 @@ struct Track : Box {
|
|||
Edit edit;
|
||||
};
|
||||
|
||||
struct MovieExtendsHeader : Box {
|
||||
struct MovieExtendsHeader : FullBox {
|
||||
DECLARE_BOX_METHODS(MovieExtendsHeader);
|
||||
|
||||
uint64 fragment_duration;
|
||||
};
|
||||
|
||||
struct TrackExtends : Box {
|
||||
struct TrackExtends : FullBox {
|
||||
DECLARE_BOX_METHODS(TrackExtends);
|
||||
|
||||
uint32 track_id;
|
||||
|
@ -366,41 +424,64 @@ struct MovieExtends : Box {
|
|||
struct Movie : Box {
|
||||
DECLARE_BOX_METHODS(Movie);
|
||||
|
||||
bool fragmented;
|
||||
MovieHeader header;
|
||||
MovieExtends extends;
|
||||
std::vector<Track> tracks;
|
||||
std::vector<ProtectionSystemSpecificHeader> pssh;
|
||||
};
|
||||
|
||||
struct TrackFragmentDecodeTime : Box {
|
||||
struct TrackFragmentDecodeTime : FullBox {
|
||||
DECLARE_BOX_METHODS(TrackFragmentDecodeTime);
|
||||
|
||||
uint64 decode_time;
|
||||
};
|
||||
|
||||
struct MovieFragmentHeader : Box {
|
||||
struct MovieFragmentHeader : FullBox {
|
||||
DECLARE_BOX_METHODS(MovieFragmentHeader);
|
||||
|
||||
uint32 sequence_number;
|
||||
};
|
||||
|
||||
struct TrackFragmentHeader : Box {
|
||||
struct TrackFragmentHeader : FullBox {
|
||||
enum TrackFragmentFlagsMasks {
|
||||
kDataOffsetPresentMask = 0x000001,
|
||||
kSampleDescriptionIndexPresentMask = 0x000002,
|
||||
kDefaultSampleDurationPresentMask = 0x000008,
|
||||
kDefaultSampleSizePresentMask = 0x000010,
|
||||
kDefaultSampleFlagsPresentMask = 0x000020,
|
||||
kDurationIsEmptyMask = 0x010000,
|
||||
kDefaultBaseIsMoofMask = 0x020000,
|
||||
};
|
||||
|
||||
enum SampleFlagsMasks {
|
||||
kReservedMask = 0xFC000000,
|
||||
kSampleDependsOnMask = 0x03000000,
|
||||
kSampleIsDependedOnMask = 0x00C00000,
|
||||
kSampleHasRedundancyMask = 0x00300000,
|
||||
kSamplePaddingValueMask = 0x000E0000,
|
||||
kNonKeySampleMask = 0x00010000,
|
||||
kSampleDegradationPriorityMask = 0x0000FFFF,
|
||||
};
|
||||
|
||||
DECLARE_BOX_METHODS(TrackFragmentHeader);
|
||||
|
||||
uint32 track_id;
|
||||
|
||||
uint32 sample_description_index;
|
||||
uint32 default_sample_duration;
|
||||
uint32 default_sample_size;
|
||||
uint32 default_sample_flags;
|
||||
|
||||
// As 'flags' might be all zero, we cannot use zeroness alone to identify
|
||||
// when default_sample_flags wasn't specified, unlike the other values.
|
||||
bool has_default_sample_flags;
|
||||
};
|
||||
|
||||
struct TrackFragmentRun : Box {
|
||||
struct TrackFragmentRun : FullBox {
|
||||
enum TrackFragmentFlagsMasks {
|
||||
kDataOffsetPresentMask = 0x000001,
|
||||
kFirstSampleFlagsPresentMask = 0x000004,
|
||||
kSampleDurationPresentMask = 0x000100,
|
||||
kSampleSizePresentMask = 0x000200,
|
||||
kSampleFlagsPresentMask = 0x000400,
|
||||
kSampleCompTimeOffsetsPresentMask = 0x000800,
|
||||
};
|
||||
|
||||
DECLARE_BOX_METHODS(TrackFragmentRun);
|
||||
|
||||
uint32 sample_count;
|
||||
|
@ -429,6 +510,50 @@ struct MovieFragment : Box {
|
|||
std::vector<ProtectionSystemSpecificHeader> pssh;
|
||||
};
|
||||
|
||||
struct SegmentReference {
|
||||
enum SAPType {
|
||||
TypeUnknown = 0,
|
||||
Type1 = 1, // T(ept) = T(dec) = T(sap) = T(ptf)
|
||||
Type2 = 2, // T(ept) = T(dec) = T(sap) < T(ptf)
|
||||
Type3 = 3, // T(ept) < T(dec) = T(sap) <= T(ptf)
|
||||
Type4 = 4, // T(ept) <= T(ptf) < T(dec) = T(sap)
|
||||
Type5 = 5, // T(ept) = T(dec) < T(sap)
|
||||
Type6 = 6, // T(ept) < T(dec) < T(sap)
|
||||
};
|
||||
|
||||
bool reference_type;
|
||||
uint32 referenced_size;
|
||||
uint32 subsegment_duration;
|
||||
bool starts_with_sap;
|
||||
SAPType sap_type;
|
||||
uint32 sap_delta_time;
|
||||
// We add this field to keep track of earliest_presentation_time in this
|
||||
// subsegment. It is not part of SegmentReference.
|
||||
uint64 earliest_presentation_time;
|
||||
};
|
||||
|
||||
struct SegmentIndex : FullBox {
|
||||
DECLARE_BOX_METHODS(SegmentIndex);
|
||||
|
||||
uint32 reference_id;
|
||||
uint32 timescale;
|
||||
uint64 earliest_presentation_time;
|
||||
uint64 first_offset;
|
||||
std::vector<SegmentReference> references;
|
||||
};
|
||||
|
||||
// The actual data is parsed and written separately, so we do not inherit it
|
||||
// from Box.
|
||||
struct MediaData {
|
||||
MediaData();
|
||||
~MediaData();
|
||||
void Write(BufferWriter* buffer_writer);
|
||||
uint32 ComputeSize();
|
||||
FourCC BoxType() const;
|
||||
|
||||
uint32 data_size;
|
||||
};
|
||||
|
||||
#undef DECLARE_BOX
|
||||
|
||||
} // namespace mp4
|
||||
|
|
|
@ -18,7 +18,9 @@ enum FourCC {
|
|||
FOURCC_CENC = 0x63656e63,
|
||||
FOURCC_CO64 = 0x636f3634,
|
||||
FOURCC_CTTS = 0x63747473,
|
||||
FOURCC_DASH = 0x64617368,
|
||||
FOURCC_DINF = 0x64696e66,
|
||||
FOURCC_DREF = 0x64726566,
|
||||
FOURCC_EAC3 = 0x65632d33,
|
||||
FOURCC_EDTS = 0x65647473,
|
||||
FOURCC_ELST = 0x656c7374,
|
||||
|
@ -30,6 +32,7 @@ enum FourCC {
|
|||
FOURCC_FTYP = 0x66747970,
|
||||
FOURCC_HDLR = 0x68646c72,
|
||||
FOURCC_HINT = 0x68696e74,
|
||||
FOURCC_ISO6 = 0x69736f36,
|
||||
FOURCC_IODS = 0x696f6473,
|
||||
FOURCC_MDAT = 0x6d646174,
|
||||
FOURCC_MDHD = 0x6d646864,
|
||||
|
@ -42,6 +45,7 @@ enum FourCC {
|
|||
FOURCC_MINF = 0x6d696e66,
|
||||
FOURCC_MOOF = 0x6d6f6f66,
|
||||
FOURCC_MOOV = 0x6d6f6f76,
|
||||
FOURCC_MP41 = 0x6d703431,
|
||||
FOURCC_MP4A = 0x6d703461,
|
||||
FOURCC_MP4V = 0x6d703476,
|
||||
FOURCC_MVEX = 0x6d766578,
|
||||
|
@ -79,6 +83,8 @@ enum FourCC {
|
|||
FOURCC_TREX = 0x74726578,
|
||||
FOURCC_TRUN = 0x7472756e,
|
||||
FOURCC_UDTA = 0x75647461,
|
||||
FOURCC_URL = 0x75726c20,
|
||||
FOURCC_URN = 0x75726e20,
|
||||
FOURCC_UUID = 0x75756964,
|
||||
FOURCC_VIDE = 0x76696465,
|
||||
FOURCC_VMHD = 0x766d6864,
|
||||
|
|
Loading…
Reference in New Issue