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