• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "MetaDataUtils"
19 #include <utils/Log.h>
20 
21 #include <media/stagefright/foundation/avc_utils.h>
22 #include <media/stagefright/foundation/base64.h>
23 #include <media/stagefright/foundation/ABitReader.h>
24 #include <media/stagefright/foundation/ABuffer.h>
25 #include <media/stagefright/foundation/ByteUtils.h>
26 #include <media/stagefright/MediaDefs.h>
27 #include <media/stagefright/MetaDataUtils.h>
28 #include <media/NdkMediaFormat.h>
29 
30 namespace android {
31 
MakeAVCCodecSpecificData(MetaDataBase & meta,const uint8_t * data,size_t size)32 bool MakeAVCCodecSpecificData(MetaDataBase &meta, const uint8_t *data, size_t size) {
33     if (data == nullptr || size == 0) {
34         return false;
35     }
36 
37     int32_t width;
38     int32_t height;
39     int32_t sarWidth;
40     int32_t sarHeight;
41     sp<ABuffer> accessUnit = new ABuffer((void*)data,  size);
42     sp<ABuffer> csd = MakeAVCCodecSpecificData(accessUnit, &width, &height, &sarWidth, &sarHeight);
43     if (csd == nullptr) {
44         return false;
45     }
46     meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
47 
48     meta.setData(kKeyAVCC, kTypeAVCC, csd->data(), csd->size());
49     meta.setInt32(kKeyWidth, width);
50     meta.setInt32(kKeyHeight, height);
51     if (sarWidth > 0 && sarHeight > 0) {
52         meta.setInt32(kKeySARWidth, sarWidth);
53         meta.setInt32(kKeySARHeight, sarHeight);
54     }
55     return true;
56 }
57 
MakeAVCCodecSpecificData(AMediaFormat * meta,const uint8_t * data,size_t size)58 bool MakeAVCCodecSpecificData(AMediaFormat *meta, const uint8_t *data, size_t size) {
59     if (meta == nullptr || data == nullptr || size == 0) {
60         return false;
61     }
62 
63     int32_t width;
64     int32_t height;
65     int32_t sarWidth;
66     int32_t sarHeight;
67     sp<ABuffer> accessUnit = new ABuffer((void*)data,  size);
68     sp<ABuffer> csd = MakeAVCCodecSpecificData(accessUnit, &width, &height, &sarWidth, &sarHeight);
69     if (csd == nullptr) {
70         return false;
71     }
72     AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_AVC);
73 
74     AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CSD_AVC, csd->data(), csd->size());
75     AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_WIDTH, width);
76     AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_HEIGHT, height);
77     if (sarWidth > 0 && sarHeight > 0) {
78         AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_SAR_WIDTH, sarWidth);
79         AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_SAR_HEIGHT, sarHeight);
80     }
81     return true;
82 }
83 
MakeAACCodecSpecificData(MetaDataBase & meta,const uint8_t * data,size_t size)84 bool MakeAACCodecSpecificData(MetaDataBase &meta, const uint8_t *data, size_t size) {
85     if (data == nullptr || size < 7) {
86         return false;
87     }
88 
89     ABitReader bits(data, size);
90 
91     // adts_fixed_header
92 
93     if (bits.getBits(12) != 0xfffu) {
94         ALOGE("Wrong atds_fixed_header");
95         return false;
96     }
97 
98     bits.skipBits(4);  // ID, layer, protection_absent
99 
100     unsigned profile = bits.getBits(2);
101     if (profile == 3u) {
102         ALOGE("profile should not be 3");
103         return false;
104     }
105     unsigned sampling_freq_index = bits.getBits(4);
106     bits.getBits(1);  // private_bit
107     unsigned channel_configuration = bits.getBits(3);
108     if (channel_configuration == 0u) {
109         ALOGE("channel_config should not be 0");
110         return false;
111     }
112 
113     if (!MakeAACCodecSpecificData(
114             meta, profile, sampling_freq_index, channel_configuration)) {
115         return false;
116     }
117 
118     meta.setInt32(kKeyIsADTS, true);
119     return true;
120 }
121 
MakeAACCodecSpecificData(uint8_t * csd,size_t * esds_size,unsigned profile,unsigned sampling_freq_index,unsigned channel_configuration,int32_t * sampling_rate)122 bool MakeAACCodecSpecificData(
123         uint8_t *csd, /* out */
124         size_t *esds_size, /* in/out */
125         unsigned profile, /* in */
126         unsigned sampling_freq_index, /* in */
127         unsigned channel_configuration, /* in */
128         int32_t *sampling_rate /* out */
129 ) {
130     if(sampling_freq_index > 11u) {
131         return false;
132     }
133     static const int32_t kSamplingFreq[] = {
134         96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
135         16000, 12000, 11025, 8000
136     };
137     *sampling_rate = kSamplingFreq[sampling_freq_index];
138 
139     static const uint8_t kStaticESDS[] = {
140         0x03, 22,
141         0x00, 0x00,     // ES_ID
142         0x00,           // streamDependenceFlag, URL_Flag, OCRstreamFlag
143 
144         0x04, 17,
145         0x40,                       // Audio ISO/IEC 14496-3
146         0x00, 0x00, 0x00, 0x00,
147         0x00, 0x00, 0x00, 0x00,
148         0x00, 0x00, 0x00, 0x00,
149 
150         0x05, 2,
151         // AudioSpecificInfo follows
152 
153         // oooo offf fccc c000
154         // o - audioObjectType
155         // f - samplingFreqIndex
156         // c - channelConfig
157     };
158 
159     size_t csdSize = sizeof(kStaticESDS) + 2;
160     if (csdSize > *esds_size) {
161         return false;
162     }
163     memcpy(csd, kStaticESDS, sizeof(kStaticESDS));
164 
165     csd[sizeof(kStaticESDS)] =
166         ((profile + 1) << 3) | (sampling_freq_index >> 1);
167 
168     csd[sizeof(kStaticESDS) + 1] =
169         ((sampling_freq_index << 7) & 0x80) | (channel_configuration << 3);
170 
171     *esds_size = csdSize;
172     return true;
173 }
174 
MakeAACCodecSpecificData(AMediaFormat * meta,unsigned profile,unsigned sampling_freq_index,unsigned channel_configuration)175 bool MakeAACCodecSpecificData(AMediaFormat *meta, unsigned profile, unsigned sampling_freq_index,
176         unsigned channel_configuration) {
177 
178     if(sampling_freq_index > 11u) {
179         return false;
180     }
181 
182     uint8_t csd[2];
183     csd[0] = ((profile + 1) << 3) | (sampling_freq_index >> 1);
184     csd[1] = ((sampling_freq_index << 7) & 0x80) | (channel_configuration << 3);
185 
186     static const int32_t kSamplingFreq[] = {
187         96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
188         16000, 12000, 11025, 8000
189     };
190     int32_t sampleRate = kSamplingFreq[sampling_freq_index];
191 
192     AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CSD_0, csd, sizeof(csd));
193     AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_AAC);
194     AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, sampleRate);
195     AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, channel_configuration);
196 
197     return true;
198 }
199 
MakeAACCodecSpecificData(MetaDataBase & meta,unsigned profile,unsigned sampling_freq_index,unsigned channel_configuration)200 bool MakeAACCodecSpecificData(
201         MetaDataBase &meta,
202         unsigned profile, unsigned sampling_freq_index,
203         unsigned channel_configuration) {
204 
205     uint8_t csd[24];
206     size_t csdSize = sizeof(csd);
207     int32_t sampleRate;
208 
209     if (!MakeAACCodecSpecificData(csd, &csdSize, profile, sampling_freq_index,
210             channel_configuration, &sampleRate)) {
211         return false;
212     }
213 
214     meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
215 
216     meta.setInt32(kKeySampleRate, sampleRate);
217     meta.setInt32(kKeyChannelCount, channel_configuration);
218     meta.setData(kKeyESDS, 0, csd, csdSize);
219     return true;
220 }
221 
222 
extractAlbumArt(AMediaFormat * fileMeta,const void * data,size_t size)223 static void extractAlbumArt(
224         AMediaFormat *fileMeta, const void *data, size_t size) {
225     ALOGV("extractAlbumArt from '%s'", (const char *)data);
226 
227     size_t inLen = strnlen((const char *)data, size);
228     size_t flacSize = inLen / 4 * 3;
229     uint8_t *flac = new uint8_t[flacSize];
230     if (!decodeBase64(flac, &flacSize, (const char*)data)) {
231         ALOGE("malformed base64 encoded data.");
232         delete[] flac;
233         return;
234     }
235 
236     ALOGV("got flac of size %zu", flacSize);
237 
238     uint32_t picType;
239     uint32_t typeLen;
240     uint32_t descLen;
241     uint32_t dataLen;
242     char type[128];
243 
244     if (flacSize < 8) {
245         delete[] flac;
246         return;
247     }
248 
249     picType = U32_AT(flac);
250 
251     if (picType != 3) {
252         // This is not a front cover.
253         delete[] flac;
254         return;
255     }
256 
257     typeLen = U32_AT(&flac[4]);
258     if (typeLen > sizeof(type) - 1) {
259         delete[] flac;
260         return;
261     }
262 
263     // we've already checked above that flacSize >= 8
264     if (flacSize - 8 < typeLen) {
265         delete[] flac;
266         return;
267     }
268 
269     memcpy(type, &flac[8], typeLen);
270     type[typeLen] = '\0';
271 
272     ALOGV("picType = %d, type = '%s'", picType, type);
273 
274     if (!strcmp(type, "-->")) {
275         // This is not inline cover art, but an external url instead.
276         delete[] flac;
277         return;
278     }
279 
280     if (flacSize < 32 || flacSize - 32 < typeLen) {
281         delete[] flac;
282         return;
283     }
284 
285     descLen = U32_AT(&flac[8 + typeLen]);
286     if (flacSize - 32 - typeLen < descLen) {
287         delete[] flac;
288         return;
289     }
290 
291     dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
292 
293     // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0
294     if (flacSize - 32 - typeLen - descLen < dataLen) {
295         delete[] flac;
296         return;
297     }
298 
299     ALOGV("got image data, %zu trailing bytes",
300          flacSize - 32 - typeLen - descLen - dataLen);
301 
302     AMediaFormat_setBuffer(fileMeta, AMEDIAFORMAT_KEY_ALBUMART,
303             &flac[8 + typeLen + 4 + descLen + 20], dataLen);
304 
305     delete[] flac;
306 }
307 
parseVorbisComment(AMediaFormat * fileMeta,const char * comment,size_t commentLength)308 void parseVorbisComment(
309         AMediaFormat *fileMeta, const char *comment, size_t commentLength) {
310     // Haptic tag is only kept here as it will only be used in extractor to generate channel mask.
311     struct {
312         const char *const mTag;
313         const char *mKey;
314     } kMap[] = {
315         { "TITLE", AMEDIAFORMAT_KEY_TITLE },
316         { "ARTIST", AMEDIAFORMAT_KEY_ARTIST },
317         { "ALBUMARTIST", AMEDIAFORMAT_KEY_ALBUMARTIST },
318         { "ALBUM ARTIST", AMEDIAFORMAT_KEY_ALBUMARTIST },
319         { "COMPILATION", AMEDIAFORMAT_KEY_COMPILATION },
320         { "ALBUM", AMEDIAFORMAT_KEY_ALBUM },
321         { "COMPOSER", AMEDIAFORMAT_KEY_COMPOSER },
322         { "GENRE", AMEDIAFORMAT_KEY_GENRE },
323         { "AUTHOR", AMEDIAFORMAT_KEY_AUTHOR },
324         { "TRACKNUMBER", AMEDIAFORMAT_KEY_CDTRACKNUMBER },
325         { "DISCNUMBER", AMEDIAFORMAT_KEY_DISCNUMBER },
326         { "DATE", AMEDIAFORMAT_KEY_DATE },
327         { "YEAR", AMEDIAFORMAT_KEY_YEAR },
328         { "LYRICIST", AMEDIAFORMAT_KEY_LYRICIST },
329         { "METADATA_BLOCK_PICTURE", AMEDIAFORMAT_KEY_ALBUMART },
330         { "ANDROID_LOOP", AMEDIAFORMAT_KEY_LOOP },
331         { "ANDROID_HAPTIC", AMEDIAFORMAT_KEY_HAPTIC_CHANNEL_COUNT },
332     };
333 
334         for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
335             size_t tagLen = strlen(kMap[j].mTag);
336             if (!strncasecmp(kMap[j].mTag, comment, tagLen)
337                     && comment[tagLen] == '=') {
338                 if (kMap[j].mKey == AMEDIAFORMAT_KEY_ALBUMART) {
339                     extractAlbumArt(
340                             fileMeta,
341                             &comment[tagLen + 1],
342                             commentLength - tagLen - 1);
343                 } else if (kMap[j].mKey == AMEDIAFORMAT_KEY_LOOP) {
344                     if (!strcasecmp(&comment[tagLen + 1], "true")) {
345                         AMediaFormat_setInt32(fileMeta, AMEDIAFORMAT_KEY_LOOP, 1);
346                     }
347                 } else if (kMap[j].mKey == AMEDIAFORMAT_KEY_HAPTIC_CHANNEL_COUNT) {
348                     char *end;
349                     errno = 0;
350                     const int hapticChannelCount = strtol(&comment[tagLen + 1], &end, 10);
351                     if (errno == 0) {
352                         AMediaFormat_setInt32(fileMeta, kMap[j].mKey, hapticChannelCount);
353                     } else {
354                         ALOGE("Error(%d) when parsing haptic channel count", errno);
355                     }
356                 } else {
357                     AMediaFormat_setString(fileMeta, kMap[j].mKey, &comment[tagLen + 1]);
358                 }
359             }
360         }
361 
362 }
363 
364 }  // namespace android
365