• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "Utils"
19 #include <utils/Log.h>
20 
21 #include "include/ESDS.h"
22 
23 #include <arpa/inet.h>
24 #include <cutils/properties.h>
25 #include <media/stagefright/foundation/ABuffer.h>
26 #include <media/stagefright/foundation/ADebug.h>
27 #include <media/stagefright/foundation/AMessage.h>
28 #include <media/stagefright/MetaData.h>
29 #include <media/stagefright/Utils.h>
30 
31 namespace android {
32 
U16_AT(const uint8_t * ptr)33 uint16_t U16_AT(const uint8_t *ptr) {
34     return ptr[0] << 8 | ptr[1];
35 }
36 
U32_AT(const uint8_t * ptr)37 uint32_t U32_AT(const uint8_t *ptr) {
38     return ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3];
39 }
40 
U64_AT(const uint8_t * ptr)41 uint64_t U64_AT(const uint8_t *ptr) {
42     return ((uint64_t)U32_AT(ptr)) << 32 | U32_AT(ptr + 4);
43 }
44 
U16LE_AT(const uint8_t * ptr)45 uint16_t U16LE_AT(const uint8_t *ptr) {
46     return ptr[0] | (ptr[1] << 8);
47 }
48 
U32LE_AT(const uint8_t * ptr)49 uint32_t U32LE_AT(const uint8_t *ptr) {
50     return ptr[3] << 24 | ptr[2] << 16 | ptr[1] << 8 | ptr[0];
51 }
52 
U64LE_AT(const uint8_t * ptr)53 uint64_t U64LE_AT(const uint8_t *ptr) {
54     return ((uint64_t)U32LE_AT(ptr + 4)) << 32 | U32LE_AT(ptr);
55 }
56 
57 // XXX warning: these won't work on big-endian host.
ntoh64(uint64_t x)58 uint64_t ntoh64(uint64_t x) {
59     return ((uint64_t)ntohl(x & 0xffffffff) << 32) | ntohl(x >> 32);
60 }
61 
hton64(uint64_t x)62 uint64_t hton64(uint64_t x) {
63     return ((uint64_t)htonl(x & 0xffffffff) << 32) | htonl(x >> 32);
64 }
65 
convertMetaDataToMessage(const sp<MetaData> & meta,sp<AMessage> * format)66 status_t convertMetaDataToMessage(
67         const sp<MetaData> &meta, sp<AMessage> *format) {
68     format->clear();
69 
70     const char *mime;
71     CHECK(meta->findCString(kKeyMIMEType, &mime));
72 
73     sp<AMessage> msg = new AMessage;
74     msg->setString("mime", mime);
75 
76     int64_t durationUs;
77     if (meta->findInt64(kKeyDuration, &durationUs)) {
78         msg->setInt64("durationUs", durationUs);
79     }
80 
81     int32_t isSync;
82     if (meta->findInt32(kKeyIsSyncFrame, &isSync) && isSync != 0) {
83         msg->setInt32("is-sync-frame", 1);
84     }
85 
86     if (!strncasecmp("video/", mime, 6)) {
87         int32_t width, height;
88         CHECK(meta->findInt32(kKeyWidth, &width));
89         CHECK(meta->findInt32(kKeyHeight, &height));
90 
91         msg->setInt32("width", width);
92         msg->setInt32("height", height);
93 
94         int32_t sarWidth, sarHeight;
95         if (meta->findInt32(kKeySARWidth, &sarWidth)
96                 && meta->findInt32(kKeySARHeight, &sarHeight)) {
97             msg->setInt32("sar-width", sarWidth);
98             msg->setInt32("sar-height", sarHeight);
99         }
100     } else if (!strncasecmp("audio/", mime, 6)) {
101         int32_t numChannels, sampleRate;
102         CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
103         CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
104 
105         msg->setInt32("channel-count", numChannels);
106         msg->setInt32("sample-rate", sampleRate);
107 
108         int32_t channelMask;
109         if (meta->findInt32(kKeyChannelMask, &channelMask)) {
110             msg->setInt32("channel-mask", channelMask);
111         }
112 
113         int32_t delay = 0;
114         if (meta->findInt32(kKeyEncoderDelay, &delay)) {
115             msg->setInt32("encoder-delay", delay);
116         }
117         int32_t padding = 0;
118         if (meta->findInt32(kKeyEncoderPadding, &padding)) {
119             msg->setInt32("encoder-padding", padding);
120         }
121 
122         int32_t isADTS;
123         if (meta->findInt32(kKeyIsADTS, &isADTS)) {
124             msg->setInt32("is-adts", true);
125         }
126     }
127 
128     int32_t maxInputSize;
129     if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
130         msg->setInt32("max-input-size", maxInputSize);
131     }
132 
133     uint32_t type;
134     const void *data;
135     size_t size;
136     if (meta->findData(kKeyAVCC, &type, &data, &size)) {
137         // Parse the AVCDecoderConfigurationRecord
138 
139         const uint8_t *ptr = (const uint8_t *)data;
140 
141         CHECK(size >= 7);
142         CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
143         uint8_t profile = ptr[1];
144         uint8_t level = ptr[3];
145 
146         // There is decodable content out there that fails the following
147         // assertion, let's be lenient for now...
148         // CHECK((ptr[4] >> 2) == 0x3f);  // reserved
149 
150         size_t lengthSize = 1 + (ptr[4] & 3);
151 
152         // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
153         // violates it...
154         // CHECK((ptr[5] >> 5) == 7);  // reserved
155 
156         size_t numSeqParameterSets = ptr[5] & 31;
157 
158         ptr += 6;
159         size -= 6;
160 
161         sp<ABuffer> buffer = new ABuffer(1024);
162         buffer->setRange(0, 0);
163 
164         for (size_t i = 0; i < numSeqParameterSets; ++i) {
165             CHECK(size >= 2);
166             size_t length = U16_AT(ptr);
167 
168             ptr += 2;
169             size -= 2;
170 
171             CHECK(size >= length);
172 
173             memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4);
174             memcpy(buffer->data() + buffer->size() + 4, ptr, length);
175             buffer->setRange(0, buffer->size() + 4 + length);
176 
177             ptr += length;
178             size -= length;
179         }
180 
181         buffer->meta()->setInt32("csd", true);
182         buffer->meta()->setInt64("timeUs", 0);
183 
184         msg->setBuffer("csd-0", buffer);
185 
186         buffer = new ABuffer(1024);
187         buffer->setRange(0, 0);
188 
189         CHECK(size >= 1);
190         size_t numPictureParameterSets = *ptr;
191         ++ptr;
192         --size;
193 
194         for (size_t i = 0; i < numPictureParameterSets; ++i) {
195             CHECK(size >= 2);
196             size_t length = U16_AT(ptr);
197 
198             ptr += 2;
199             size -= 2;
200 
201             CHECK(size >= length);
202 
203             memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4);
204             memcpy(buffer->data() + buffer->size() + 4, ptr, length);
205             buffer->setRange(0, buffer->size() + 4 + length);
206 
207             ptr += length;
208             size -= length;
209         }
210 
211         buffer->meta()->setInt32("csd", true);
212         buffer->meta()->setInt64("timeUs", 0);
213         msg->setBuffer("csd-1", buffer);
214     } else if (meta->findData(kKeyESDS, &type, &data, &size)) {
215         ESDS esds((const char *)data, size);
216         CHECK_EQ(esds.InitCheck(), (status_t)OK);
217 
218         const void *codec_specific_data;
219         size_t codec_specific_data_size;
220         esds.getCodecSpecificInfo(
221                 &codec_specific_data, &codec_specific_data_size);
222 
223         sp<ABuffer> buffer = new ABuffer(codec_specific_data_size);
224 
225         memcpy(buffer->data(), codec_specific_data,
226                codec_specific_data_size);
227 
228         buffer->meta()->setInt32("csd", true);
229         buffer->meta()->setInt64("timeUs", 0);
230         msg->setBuffer("csd-0", buffer);
231     } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) {
232         sp<ABuffer> buffer = new ABuffer(size);
233         memcpy(buffer->data(), data, size);
234 
235         buffer->meta()->setInt32("csd", true);
236         buffer->meta()->setInt64("timeUs", 0);
237         msg->setBuffer("csd-0", buffer);
238 
239         if (!meta->findData(kKeyVorbisBooks, &type, &data, &size)) {
240             return -EINVAL;
241         }
242 
243         buffer = new ABuffer(size);
244         memcpy(buffer->data(), data, size);
245 
246         buffer->meta()->setInt32("csd", true);
247         buffer->meta()->setInt64("timeUs", 0);
248         msg->setBuffer("csd-1", buffer);
249     }
250 
251     *format = msg;
252 
253     return OK;
254 }
255 
reassembleAVCC(const sp<ABuffer> & csd0,const sp<ABuffer> csd1,char * avcc)256 static size_t reassembleAVCC(const sp<ABuffer> &csd0, const sp<ABuffer> csd1, char *avcc) {
257 
258     avcc[0] = 1;        // version
259     avcc[1] = 0x64;     // profile
260     avcc[2] = 0;        // unused (?)
261     avcc[3] = 0xd;      // level
262     avcc[4] = 0xff;     // reserved+size
263 
264     size_t i = 0;
265     int numparams = 0;
266     int lastparamoffset = 0;
267     int avccidx = 6;
268     do {
269         if (i >= csd0->size() - 4 ||
270                 memcmp(csd0->data() + i, "\x00\x00\x00\x01", 4) == 0) {
271             if (i >= csd0->size() - 4) {
272                 // there can't be another param here, so use all the rest
273                 i = csd0->size();
274             }
275             ALOGV("block at %d, last was %d", i, lastparamoffset);
276             if (lastparamoffset > 0) {
277                 int size = i - lastparamoffset;
278                 avcc[avccidx++] = size >> 8;
279                 avcc[avccidx++] = size & 0xff;
280                 memcpy(avcc+avccidx, csd0->data() + lastparamoffset, size);
281                 avccidx += size;
282                 numparams++;
283             }
284             i += 4;
285             lastparamoffset = i;
286         } else {
287             i++;
288         }
289     } while(i < csd0->size());
290     ALOGV("csd0 contains %d params", numparams);
291 
292     avcc[5] = 0xe0 | numparams;
293     //and now csd-1
294     i = 0;
295     numparams = 0;
296     lastparamoffset = 0;
297     int numpicparamsoffset = avccidx;
298     avccidx++;
299     do {
300         if (i >= csd1->size() - 4 ||
301                 memcmp(csd1->data() + i, "\x00\x00\x00\x01", 4) == 0) {
302             if (i >= csd1->size() - 4) {
303                 // there can't be another param here, so use all the rest
304                 i = csd1->size();
305             }
306             ALOGV("block at %d, last was %d", i, lastparamoffset);
307             if (lastparamoffset > 0) {
308                 int size = i - lastparamoffset;
309                 avcc[avccidx++] = size >> 8;
310                 avcc[avccidx++] = size & 0xff;
311                 memcpy(avcc+avccidx, csd1->data() + lastparamoffset, size);
312                 avccidx += size;
313                 numparams++;
314             }
315             i += 4;
316             lastparamoffset = i;
317         } else {
318             i++;
319         }
320     } while(i < csd1->size());
321     avcc[numpicparamsoffset] = numparams;
322     return avccidx;
323 }
324 
reassembleESDS(const sp<ABuffer> & csd0,char * esds)325 static void reassembleESDS(const sp<ABuffer> &csd0, char *esds) {
326     int csd0size = csd0->size();
327     esds[0] = 3; // kTag_ESDescriptor;
328     int esdescriptorsize = 26 + csd0size;
329     CHECK(esdescriptorsize < 268435456); // 7 bits per byte, so max is 2^28-1
330     esds[1] = 0x80 | (esdescriptorsize >> 21);
331     esds[2] = 0x80 | ((esdescriptorsize >> 14) & 0x7f);
332     esds[3] = 0x80 | ((esdescriptorsize >> 7) & 0x7f);
333     esds[4] = (esdescriptorsize & 0x7f);
334     esds[5] = esds[6] = 0; // es id
335     esds[7] = 0; // flags
336     esds[8] = 4; // kTag_DecoderConfigDescriptor
337     int configdescriptorsize = 18 + csd0size;
338     esds[9] = 0x80 | (configdescriptorsize >> 21);
339     esds[10] = 0x80 | ((configdescriptorsize >> 14) & 0x7f);
340     esds[11] = 0x80 | ((configdescriptorsize >> 7) & 0x7f);
341     esds[12] = (configdescriptorsize & 0x7f);
342     esds[13] = 0x40; // objectTypeIndication
343     esds[14] = 0x15; // not sure what 14-25 mean, they are ignored by ESDS.cpp,
344     esds[15] = 0x00; // but the actual values here were taken from a real file.
345     esds[16] = 0x18;
346     esds[17] = 0x00;
347     esds[18] = 0x00;
348     esds[19] = 0x00;
349     esds[20] = 0xfa;
350     esds[21] = 0x00;
351     esds[22] = 0x00;
352     esds[23] = 0x00;
353     esds[24] = 0xfa;
354     esds[25] = 0x00;
355     esds[26] = 5; // kTag_DecoderSpecificInfo;
356     esds[27] = 0x80 | (csd0size >> 21);
357     esds[28] = 0x80 | ((csd0size >> 14) & 0x7f);
358     esds[29] = 0x80 | ((csd0size >> 7) & 0x7f);
359     esds[30] = (csd0size & 0x7f);
360     memcpy((void*)&esds[31], csd0->data(), csd0size);
361     // data following this is ignored, so don't bother appending it
362 
363 }
364 
convertMessageToMetaData(const sp<AMessage> & msg,sp<MetaData> & meta)365 void convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) {
366     AString mime;
367     if (msg->findString("mime", &mime)) {
368         meta->setCString(kKeyMIMEType, mime.c_str());
369     } else {
370         ALOGW("did not find mime type");
371     }
372 
373     int64_t durationUs;
374     if (msg->findInt64("durationUs", &durationUs)) {
375         meta->setInt64(kKeyDuration, durationUs);
376     }
377 
378     int32_t isSync;
379     if (msg->findInt32("is-sync-frame", &isSync) && isSync != 0) {
380         meta->setInt32(kKeyIsSyncFrame, 1);
381     }
382 
383     if (mime.startsWith("video/")) {
384         int32_t width;
385         int32_t height;
386         if (msg->findInt32("width", &width) && msg->findInt32("height", &height)) {
387             meta->setInt32(kKeyWidth, width);
388             meta->setInt32(kKeyHeight, height);
389         } else {
390             ALOGW("did not find width and/or height");
391         }
392 
393         int32_t sarWidth, sarHeight;
394         if (msg->findInt32("sar-width", &sarWidth)
395                 && msg->findInt32("sar-height", &sarHeight)) {
396             meta->setInt32(kKeySARWidth, sarWidth);
397             meta->setInt32(kKeySARHeight, sarHeight);
398         }
399     } else if (mime.startsWith("audio/")) {
400         int32_t numChannels;
401         if (msg->findInt32("channel-count", &numChannels)) {
402             meta->setInt32(kKeyChannelCount, numChannels);
403         }
404         int32_t sampleRate;
405         if (msg->findInt32("sample-rate", &sampleRate)) {
406             meta->setInt32(kKeySampleRate, sampleRate);
407         }
408         int32_t channelMask;
409         if (msg->findInt32("channel-mask", &channelMask)) {
410             meta->setInt32(kKeyChannelMask, channelMask);
411         }
412         int32_t delay = 0;
413         if (msg->findInt32("encoder-delay", &delay)) {
414             meta->setInt32(kKeyEncoderDelay, delay);
415         }
416         int32_t padding = 0;
417         if (msg->findInt32("encoder-padding", &padding)) {
418             meta->setInt32(kKeyEncoderPadding, padding);
419         }
420 
421         int32_t isADTS;
422         if (msg->findInt32("is-adts", &isADTS)) {
423             meta->setInt32(kKeyIsADTS, isADTS);
424         }
425     }
426 
427     int32_t maxInputSize;
428     if (msg->findInt32("max-input-size", &maxInputSize)) {
429         meta->setInt32(kKeyMaxInputSize, maxInputSize);
430     }
431 
432     // reassemble the csd data into its original form
433     sp<ABuffer> csd0;
434     if (msg->findBuffer("csd-0", &csd0)) {
435         if (mime.startsWith("video/")) { // do we need to be stricter than this?
436             sp<ABuffer> csd1;
437             if (msg->findBuffer("csd-1", &csd1)) {
438                 char avcc[1024]; // that oughta be enough, right?
439                 size_t outsize = reassembleAVCC(csd0, csd1, avcc);
440                 meta->setData(kKeyAVCC, kKeyAVCC, avcc, outsize);
441             }
442         } else if (mime.startsWith("audio/")) {
443             int csd0size = csd0->size();
444             char esds[csd0size + 31];
445             reassembleESDS(csd0, esds);
446             meta->setData(kKeyESDS, kKeyESDS, esds, sizeof(esds));
447         }
448     }
449 
450     // XXX TODO add whatever other keys there are
451 
452 #if 0
453     ALOGI("converted %s to:", msg->debugString(0).c_str());
454     meta->dumpToLog();
455 #endif
456 }
457 
MakeUserAgent()458 AString MakeUserAgent() {
459     AString ua;
460     ua.append("stagefright/1.2 (Linux;Android ");
461 
462 #if (PROPERTY_VALUE_MAX < 8)
463 #error "PROPERTY_VALUE_MAX must be at least 8"
464 #endif
465 
466     char value[PROPERTY_VALUE_MAX];
467     property_get("ro.build.version.release", value, "Unknown");
468     ua.append(value);
469     ua.append(")");
470 
471     return ua;
472 }
473 
474 }  // namespace android
475 
476