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