1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #include "mp4_demuxer/Adts.h"
6 #include "mp4_demuxer/AnnexB.h"
7 #include "mp4_demuxer/ByteReader.h"
8 #include "mp4_demuxer/DecoderData.h"
9 #include <media/stagefright/foundation/ABitReader.h>
10 #include "media/stagefright/MetaData.h"
11 #include "media/stagefright/MediaDefs.h"
12 #include "media/stagefright/Utils.h"
13 #include "mozilla/ArrayUtils.h"
14 #include "include/ESDS.h"
15
16 #ifdef MOZ_RUST_MP4PARSE
17 #include "mp4parse.h"
18 #endif
19
20 using namespace stagefright;
21
22 namespace mp4_demuxer
23 {
24
25 static int32_t
FindInt32(const MetaData * mMetaData,uint32_t mKey)26 FindInt32(const MetaData* mMetaData, uint32_t mKey)
27 {
28 int32_t value;
29 if (!mMetaData->findInt32(mKey, &value))
30 return 0;
31 return value;
32 }
33
34 static int64_t
FindInt64(const MetaData * mMetaData,uint32_t mKey)35 FindInt64(const MetaData* mMetaData, uint32_t mKey)
36 {
37 int64_t value;
38 if (!mMetaData->findInt64(mKey, &value))
39 return 0;
40 return value;
41 }
42
43 template <typename T, size_t N>
44 static bool
FindData(const MetaData * aMetaData,uint32_t aKey,mozilla::Vector<T,N> * aDest)45 FindData(const MetaData* aMetaData, uint32_t aKey, mozilla::Vector<T, N>* aDest)
46 {
47 const void* data;
48 size_t size;
49 uint32_t type;
50
51 aDest->clear();
52 // There's no point in checking that the type matches anything because it
53 // isn't set consistently in the MPEG4Extractor.
54 if (!aMetaData->findData(aKey, &type, &data, &size) || size % sizeof(T)) {
55 return false;
56 }
57
58 aDest->append(reinterpret_cast<const T*>(data), size / sizeof(T));
59 return true;
60 }
61
62 template <typename T>
63 static bool
FindData(const MetaData * aMetaData,uint32_t aKey,nsTArray<T> * aDest)64 FindData(const MetaData* aMetaData, uint32_t aKey, nsTArray<T>* aDest)
65 {
66 const void* data;
67 size_t size;
68 uint32_t type;
69
70 aDest->Clear();
71 // There's no point in checking that the type matches anything because it
72 // isn't set consistently in the MPEG4Extractor.
73 if (!aMetaData->findData(aKey, &type, &data, &size) || size % sizeof(T)) {
74 return false;
75 }
76
77 aDest->AppendElements(reinterpret_cast<const T*>(data), size / sizeof(T));
78 return true;
79 }
80
81 static bool
FindData(const MetaData * aMetaData,uint32_t aKey,mozilla::MediaByteBuffer * aDest)82 FindData(const MetaData* aMetaData, uint32_t aKey, mozilla::MediaByteBuffer* aDest)
83 {
84 return FindData(aMetaData, aKey, static_cast<nsTArray<uint8_t>*>(aDest));
85 }
86
87 bool
DoUpdate(const uint8_t * aData,size_t aLength)88 CryptoFile::DoUpdate(const uint8_t* aData, size_t aLength)
89 {
90 ByteReader reader(aData, aLength);
91 while (reader.Remaining()) {
92 PsshInfo psshInfo;
93 if (!reader.ReadArray(psshInfo.uuid, 16)) {
94 return false;
95 }
96
97 if (!reader.CanReadType<uint32_t>()) {
98 return false;
99 }
100 auto length = reader.ReadType<uint32_t>();
101
102 if (!reader.ReadArray(psshInfo.data, length)) {
103 return false;
104 }
105 pssh.AppendElement(psshInfo);
106 }
107 return true;
108 }
109
110 static void
UpdateTrackInfo(mozilla::TrackInfo & aConfig,const MetaData * aMetaData,const char * aMimeType)111 UpdateTrackInfo(mozilla::TrackInfo& aConfig,
112 const MetaData* aMetaData,
113 const char* aMimeType)
114 {
115 mozilla::CryptoTrack& crypto = aConfig.mCrypto;
116 aConfig.mMimeType = aMimeType;
117 aConfig.mDuration = FindInt64(aMetaData, kKeyDuration);
118 aConfig.mMediaTime = FindInt64(aMetaData, kKeyMediaTime);
119 aConfig.mTrackId = FindInt32(aMetaData, kKeyTrackID);
120 aConfig.mCrypto.mValid = aMetaData->findInt32(kKeyCryptoMode, &crypto.mMode) &&
121 aMetaData->findInt32(kKeyCryptoDefaultIVSize, &crypto.mIVSize) &&
122 FindData(aMetaData, kKeyCryptoKey, &crypto.mKeyId);
123 }
124
125 void
Update(const MetaData * aMetaData,const char * aMimeType)126 MP4AudioInfo::Update(const MetaData* aMetaData,
127 const char* aMimeType)
128 {
129 UpdateTrackInfo(*this, aMetaData, aMimeType);
130 mChannels = FindInt32(aMetaData, kKeyChannelCount);
131 mBitDepth = FindInt32(aMetaData, kKeySampleSize);
132 mRate = FindInt32(aMetaData, kKeySampleRate);
133 mProfile = FindInt32(aMetaData, kKeyAACProfile);
134
135 if (FindData(aMetaData, kKeyESDS, mExtraData)) {
136 ESDS esds(mExtraData->Elements(), mExtraData->Length());
137
138 const void* data;
139 size_t size;
140 if (esds.getCodecSpecificInfo(&data, &size) == OK) {
141 const uint8_t* cdata = reinterpret_cast<const uint8_t*>(data);
142 mCodecSpecificConfig->AppendElements(cdata, size);
143 if (size > 1) {
144 ABitReader br(cdata, size);
145 mExtendedProfile = br.getBits(5);
146
147 if (mExtendedProfile == 31) { // AAC-ELD => additional 6 bits
148 mExtendedProfile = 32 + br.getBits(6);
149 }
150 }
151 }
152 }
153 }
154
155 bool
IsValid() const156 MP4AudioInfo::IsValid() const
157 {
158 return mChannels > 0 && mRate > 0 &&
159 // Accept any mime type here, but if it's aac, validate the profile.
160 (!mMimeType.Equals(MEDIA_MIMETYPE_AUDIO_AAC) ||
161 mProfile > 0 || mExtendedProfile > 0);
162 }
163
164 void
Update(const MetaData * aMetaData,const char * aMimeType)165 MP4VideoInfo::Update(const MetaData* aMetaData, const char* aMimeType)
166 {
167 UpdateTrackInfo(*this, aMetaData, aMimeType);
168 mDisplay.width = FindInt32(aMetaData, kKeyDisplayWidth);
169 mDisplay.height = FindInt32(aMetaData, kKeyDisplayHeight);
170 mImage.width = FindInt32(aMetaData, kKeyWidth);
171 mImage.height = FindInt32(aMetaData, kKeyHeight);
172 mRotation = VideoInfo::ToSupportedRotation(FindInt32(aMetaData, kKeyRotation));
173
174 FindData(aMetaData, kKeyAVCC, mExtraData);
175 if (!mExtraData->Length()) {
176 if (FindData(aMetaData, kKeyESDS, mExtraData)) {
177 ESDS esds(mExtraData->Elements(), mExtraData->Length());
178
179 const void* data;
180 size_t size;
181 if (esds.getCodecSpecificInfo(&data, &size) == OK) {
182 const uint8_t* cdata = reinterpret_cast<const uint8_t*>(data);
183 mCodecSpecificConfig->AppendElements(cdata, size);
184 }
185 }
186 }
187
188 }
189
190 #ifdef MOZ_RUST_MP4PARSE
191 void
Update(const mp4parse_track_info * track,const mp4parse_track_video_info * video)192 MP4VideoInfo::Update(const mp4parse_track_info* track,
193 const mp4parse_track_video_info* video)
194 {
195 if (track->codec == MP4PARSE_CODEC_AVC) {
196 mMimeType = MEDIA_MIMETYPE_VIDEO_AVC;
197 } else if (track->codec == MP4PARSE_CODEC_VP9) {
198 mMimeType = NS_LITERAL_CSTRING("video/vp9");
199 }
200 mTrackId = track->track_id;
201 mDuration = track->duration;
202 mMediaTime = track->media_time;
203 mDisplay.width = video->display_width;
204 mDisplay.height = video->display_height;
205 mImage.width = video->image_width;
206 mImage.height = video->image_height;
207 }
208 #endif
209
210 bool
IsValid() const211 MP4VideoInfo::IsValid() const
212 {
213 return (mDisplay.width > 0 && mDisplay.height > 0) ||
214 (mImage.width > 0 && mImage.height > 0);
215 }
216
217 }
218