1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef MPEG4_EXTRACTOR_H_
18 
19 #define MPEG4_EXTRACTOR_H_
20 
21 #include <arpa/inet.h>
22 
23 #include <media/MediaExtractorPluginApi.h>
24 #include <media/MediaExtractorPluginHelper.h>
25 #include <media/NdkMediaFormat.h>
26 #include <media/stagefright/foundation/AString.h>
27 #include <utils/KeyedVector.h>
28 #include <utils/List.h>
29 #include <utils/String8.h>
30 #include <utils/Vector.h>
31 
32 namespace android {
33 struct AMessage;
34 struct CDataSource;
35 class DataSourceHelper;
36 class SampleTable;
37 class String8;
38 namespace heif {
39 class ItemTable;
40 }
41 using heif::ItemTable;
42 
43 struct SidxEntry {
44     size_t mSize;
45     uint32_t mDurationUs;
46 };
47 
48 struct Trex {
49     uint32_t track_ID;
50     uint32_t default_sample_description_index;
51     uint32_t default_sample_duration;
52     uint32_t default_sample_size;
53     uint32_t default_sample_flags;
54 };
55 
56 class MPEG4Extractor : public MediaExtractorPluginHelper {
57 public:
58     explicit MPEG4Extractor(DataSourceHelper *source, const char *mime = NULL);
59 
60     virtual size_t countTracks();
61     virtual MediaTrackHelper *getTrack(size_t index);
62     virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
63 
64     virtual media_status_t getMetaData(AMediaFormat *meta);
65     virtual uint32_t flags() const;
name()66     virtual const char * name() { return "MPEG4Extractor"; }
67 
68 protected:
69     virtual ~MPEG4Extractor();
70 
71 private:
72 
73     struct PsshInfo {
74         uint8_t uuid[16];
75         uint32_t datalen;
76         uint8_t *data;
77     };
78     struct Track {
79         Track *next;
80         AMediaFormat *meta;
81         uint32_t timescale;
82         sp<SampleTable> sampleTable;
83         bool includes_expensive_metadata;
84         bool skipTrack;
85         bool elst_needs_processing;
86         /* signed int, ISO Spec allows media_time = -1 for other use cases.
87          * but we don't support empty edits for now.
88          */
89         int64_t elst_media_time;
90         uint64_t elst_segment_duration;
91         // Shift start offset (move to earlier time) when media_time > 0.
92         uint64_t elst_shift_start_ticks;
93         // Initial start offset (move to later time), from empty edit list entry.
94         uint64_t elst_initial_empty_edit_ticks;
95         bool subsample_encryption;
96 
97         uint8_t *mTx3gBuffer;
98         size_t mTx3gSize, mTx3gFilled;
99 
100 
TrackTrack101         Track() {
102             next = NULL;
103             meta = NULL;
104             timescale = 0;
105             includes_expensive_metadata = false;
106             skipTrack = false;
107             elst_needs_processing = false;
108             elst_media_time = 0;
109             elst_segment_duration = 0;
110             elst_shift_start_ticks = 0;
111             elst_initial_empty_edit_ticks = 0;
112             subsample_encryption = false;
113             mTx3gBuffer = NULL;
114             mTx3gSize = mTx3gFilled = 0;
115         }
~TrackTrack116         ~Track() {
117             if (meta) {
118                 AMediaFormat_delete(meta);
119                 meta = NULL;
120             }
121             free (mTx3gBuffer);
122             mTx3gBuffer = NULL;
123         }
124 
125       private:
126         DISALLOW_EVIL_CONSTRUCTORS(Track);
127     };
128 
129     static const int kTx3gGrowth = 16 * 1024;
130 
131     Vector<SidxEntry> mSidxEntries;
132     off64_t mMoofOffset;
133     bool mMoofFound;
134     bool mMdatFound;
135 
136     Vector<PsshInfo> mPssh;
137 
138     Vector<Trex> mTrex;
139 
140     DataSourceHelper *mDataSource;
141     status_t mInitCheck;
142     uint32_t mHeaderTimescale;
143     bool mIsQT;
144     bool mIsHeif;
145     bool mHasMoovBox;
146     bool mPreferHeif;
147     bool mIsAvif;
148 
149     Track *mFirstTrack, *mLastTrack;
150 
151     AMediaFormat *mFileMetaData;
152 
153     Vector<uint32_t> mPath;
154     String8 mLastCommentMean;
155     String8 mLastCommentName;
156     String8 mLastCommentData;
157 
158     KeyedVector<uint32_t, AString> mMetaKeyMap;
159 
160     status_t readMetaData();
161     status_t parseChunk(off64_t *offset, int depth);
162     status_t parseITunesMetaData(off64_t offset, size_t size);
163     status_t parseColorInfo(off64_t offset, size_t size);
164     status_t parsePaspBox(off64_t offset, size_t size);
165     status_t parse3GPPMetaData(off64_t offset, size_t size, int depth);
166     void parseID3v2MetaData(off64_t offset, uint64_t size);
167     status_t parseQTMetaKey(off64_t data_offset, size_t data_size);
168     status_t parseQTMetaVal(int32_t keyId, off64_t data_offset, size_t data_size);
169 
170     status_t updateAudioTrackInfoFromESDS_MPEG4Audio(
171             const void *esds_data, size_t esds_size);
172 
173     static status_t verifyTrack(Track *track);
174 
175     sp<ItemTable> mItemTable;
176 
177     status_t parseTrackHeader(off64_t data_offset, off64_t data_size);
178 
179     status_t parseSegmentIndex(off64_t data_offset, size_t data_size);
180 
181     Track *findTrackByMimePrefix(const char *mimePrefix);
182 
183     status_t parseChannelCountSampleRate(
184             off64_t *offset, uint16_t *channelCount, uint16_t *sampleRate);
185     status_t parseAC3SpecificBox(off64_t offset);
186     status_t parseEAC3SpecificBox(off64_t offset);
187     status_t parseAC4SpecificBox(off64_t offset);
188     status_t parseALACSampleEntry(off64_t *offset);
189     void adjustRawDefaultFrameSize();
190 
191     MPEG4Extractor(const MPEG4Extractor &);
192     MPEG4Extractor &operator=(const MPEG4Extractor &);
193 };
194 
195 }  // namespace android
196 
197 #endif  // MPEG4_EXTRACTOR_H_
198