• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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 "ESQueue"
19 #include <media/stagefright/foundation/ADebug.h>
20 
21 #include "ESQueue.h"
22 
23 #include <media/stagefright/foundation/hexdump.h>
24 #include <media/stagefright/foundation/ABitReader.h>
25 #include <media/stagefright/foundation/ABuffer.h>
26 #include <media/stagefright/foundation/AMessage.h>
27 #include <media/stagefright/MediaErrors.h>
28 #include <media/stagefright/MediaDefs.h>
29 #include <media/stagefright/MetaData.h>
30 #include <media/stagefright/Utils.h>
31 
32 #include "include/avc_utils.h"
33 
34 #include <netinet/in.h>
35 
36 namespace android {
37 
ElementaryStreamQueue(Mode mode,uint32_t flags)38 ElementaryStreamQueue::ElementaryStreamQueue(Mode mode, uint32_t flags)
39     : mMode(mode),
40       mFlags(flags) {
41 }
42 
getFormat()43 sp<MetaData> ElementaryStreamQueue::getFormat() {
44     return mFormat;
45 }
46 
clear(bool clearFormat)47 void ElementaryStreamQueue::clear(bool clearFormat) {
48     if (mBuffer != NULL) {
49         mBuffer->setRange(0, 0);
50     }
51 
52     mRangeInfos.clear();
53 
54     if (clearFormat) {
55         mFormat.clear();
56     }
57 }
58 
IsSeeminglyValidADTSHeader(const uint8_t * ptr,size_t size)59 static bool IsSeeminglyValidADTSHeader(const uint8_t *ptr, size_t size) {
60     if (size < 3) {
61         // Not enough data to verify header.
62         return false;
63     }
64 
65     if (ptr[0] != 0xff || (ptr[1] >> 4) != 0x0f) {
66         return false;
67     }
68 
69     unsigned layer = (ptr[1] >> 1) & 3;
70 
71     if (layer != 0) {
72         return false;
73     }
74 
75     unsigned ID = (ptr[1] >> 3) & 1;
76     unsigned profile_ObjectType = ptr[2] >> 6;
77 
78     if (ID == 1 && profile_ObjectType == 3) {
79         // MPEG-2 profile 3 is reserved.
80         return false;
81     }
82 
83     return true;
84 }
85 
IsSeeminglyValidMPEGAudioHeader(const uint8_t * ptr,size_t size)86 static bool IsSeeminglyValidMPEGAudioHeader(const uint8_t *ptr, size_t size) {
87     if (size < 3) {
88         // Not enough data to verify header.
89         return false;
90     }
91 
92     if (ptr[0] != 0xff || (ptr[1] >> 5) != 0x07) {
93         return false;
94     }
95 
96     unsigned ID = (ptr[1] >> 3) & 3;
97 
98     if (ID == 1) {
99         return false;  // reserved
100     }
101 
102     unsigned layer = (ptr[1] >> 1) & 3;
103 
104     if (layer == 0) {
105         return false;  // reserved
106     }
107 
108     unsigned bitrateIndex = (ptr[2] >> 4);
109 
110     if (bitrateIndex == 0x0f) {
111         return false;  // reserved
112     }
113 
114     unsigned samplingRateIndex = (ptr[2] >> 2) & 3;
115 
116     if (samplingRateIndex == 3) {
117         return false;  // reserved
118     }
119 
120     return true;
121 }
122 
appendData(const void * data,size_t size,int64_t timeUs)123 status_t ElementaryStreamQueue::appendData(
124         const void *data, size_t size, int64_t timeUs) {
125     if (mBuffer == NULL || mBuffer->size() == 0) {
126         switch (mMode) {
127             case H264:
128             case MPEG_VIDEO:
129             {
130 #if 0
131                 if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) {
132                     return ERROR_MALFORMED;
133                 }
134 #else
135                 uint8_t *ptr = (uint8_t *)data;
136 
137                 ssize_t startOffset = -1;
138                 for (size_t i = 0; i + 3 < size; ++i) {
139                     if (!memcmp("\x00\x00\x00\x01", &ptr[i], 4)) {
140                         startOffset = i;
141                         break;
142                     }
143                 }
144 
145                 if (startOffset < 0) {
146                     return ERROR_MALFORMED;
147                 }
148 
149                 if (startOffset > 0) {
150                     ALOGI("found something resembling an H.264/MPEG syncword "
151                           "at offset %d",
152                           startOffset);
153                 }
154 
155                 data = &ptr[startOffset];
156                 size -= startOffset;
157 #endif
158                 break;
159             }
160 
161             case MPEG4_VIDEO:
162             {
163 #if 0
164                 if (size < 3 || memcmp("\x00\x00\x01", data, 3)) {
165                     return ERROR_MALFORMED;
166                 }
167 #else
168                 uint8_t *ptr = (uint8_t *)data;
169 
170                 ssize_t startOffset = -1;
171                 for (size_t i = 0; i + 2 < size; ++i) {
172                     if (!memcmp("\x00\x00\x01", &ptr[i], 3)) {
173                         startOffset = i;
174                         break;
175                     }
176                 }
177 
178                 if (startOffset < 0) {
179                     return ERROR_MALFORMED;
180                 }
181 
182                 if (startOffset > 0) {
183                     ALOGI("found something resembling an H.264/MPEG syncword "
184                           "at offset %d",
185                           startOffset);
186                 }
187 
188                 data = &ptr[startOffset];
189                 size -= startOffset;
190 #endif
191                 break;
192             }
193 
194             case AAC:
195             {
196                 uint8_t *ptr = (uint8_t *)data;
197 
198 #if 0
199                 if (size < 2 || ptr[0] != 0xff || (ptr[1] >> 4) != 0x0f) {
200                     return ERROR_MALFORMED;
201                 }
202 #else
203                 ssize_t startOffset = -1;
204                 for (size_t i = 0; i < size; ++i) {
205                     if (IsSeeminglyValidADTSHeader(&ptr[i], size - i)) {
206                         startOffset = i;
207                         break;
208                     }
209                 }
210 
211                 if (startOffset < 0) {
212                     return ERROR_MALFORMED;
213                 }
214 
215                 if (startOffset > 0) {
216                     ALOGI("found something resembling an AAC syncword at "
217                           "offset %d",
218                           startOffset);
219                 }
220 
221                 data = &ptr[startOffset];
222                 size -= startOffset;
223 #endif
224                 break;
225             }
226 
227             case MPEG_AUDIO:
228             {
229                 uint8_t *ptr = (uint8_t *)data;
230 
231                 ssize_t startOffset = -1;
232                 for (size_t i = 0; i < size; ++i) {
233                     if (IsSeeminglyValidMPEGAudioHeader(&ptr[i], size - i)) {
234                         startOffset = i;
235                         break;
236                     }
237                 }
238 
239                 if (startOffset < 0) {
240                     return ERROR_MALFORMED;
241                 }
242 
243                 if (startOffset > 0) {
244                     ALOGI("found something resembling an MPEG audio "
245                           "syncword at offset %d",
246                           startOffset);
247                 }
248 
249                 data = &ptr[startOffset];
250                 size -= startOffset;
251                 break;
252             }
253 
254             case PCM_AUDIO:
255             {
256                 break;
257             }
258 
259             default:
260                 TRESPASS();
261                 break;
262         }
263     }
264 
265     size_t neededSize = (mBuffer == NULL ? 0 : mBuffer->size()) + size;
266     if (mBuffer == NULL || neededSize > mBuffer->capacity()) {
267         neededSize = (neededSize + 65535) & ~65535;
268 
269         ALOGV("resizing buffer to size %d", neededSize);
270 
271         sp<ABuffer> buffer = new ABuffer(neededSize);
272         if (mBuffer != NULL) {
273             memcpy(buffer->data(), mBuffer->data(), mBuffer->size());
274             buffer->setRange(0, mBuffer->size());
275         } else {
276             buffer->setRange(0, 0);
277         }
278 
279         mBuffer = buffer;
280     }
281 
282     memcpy(mBuffer->data() + mBuffer->size(), data, size);
283     mBuffer->setRange(0, mBuffer->size() + size);
284 
285     RangeInfo info;
286     info.mLength = size;
287     info.mTimestampUs = timeUs;
288     mRangeInfos.push_back(info);
289 
290 #if 0
291     if (mMode == AAC) {
292         ALOGI("size = %d, timeUs = %.2f secs", size, timeUs / 1E6);
293         hexdump(data, size);
294     }
295 #endif
296 
297     return OK;
298 }
299 
dequeueAccessUnit()300 sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnit() {
301     if ((mFlags & kFlag_AlignedData) && mMode == H264) {
302         if (mRangeInfos.empty()) {
303             return NULL;
304         }
305 
306         RangeInfo info = *mRangeInfos.begin();
307         mRangeInfos.erase(mRangeInfos.begin());
308 
309         sp<ABuffer> accessUnit = new ABuffer(info.mLength);
310         memcpy(accessUnit->data(), mBuffer->data(), info.mLength);
311         accessUnit->meta()->setInt64("timeUs", info.mTimestampUs);
312 
313         memmove(mBuffer->data(),
314                 mBuffer->data() + info.mLength,
315                 mBuffer->size() - info.mLength);
316 
317         mBuffer->setRange(0, mBuffer->size() - info.mLength);
318 
319         if (mFormat == NULL) {
320             mFormat = MakeAVCCodecSpecificData(accessUnit);
321         }
322 
323         return accessUnit;
324     }
325 
326     switch (mMode) {
327         case H264:
328             return dequeueAccessUnitH264();
329         case AAC:
330             return dequeueAccessUnitAAC();
331         case MPEG_VIDEO:
332             return dequeueAccessUnitMPEGVideo();
333         case MPEG4_VIDEO:
334             return dequeueAccessUnitMPEG4Video();
335         case PCM_AUDIO:
336             return dequeueAccessUnitPCMAudio();
337         default:
338             CHECK_EQ((unsigned)mMode, (unsigned)MPEG_AUDIO);
339             return dequeueAccessUnitMPEGAudio();
340     }
341 }
342 
dequeueAccessUnitPCMAudio()343 sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitPCMAudio() {
344     if (mBuffer->size() < 4) {
345         return NULL;
346     }
347 
348     ABitReader bits(mBuffer->data(), 4);
349     CHECK_EQ(bits.getBits(8), 0xa0);
350     unsigned numAUs = bits.getBits(8);
351     bits.skipBits(8);
352     unsigned quantization_word_length = bits.getBits(2);
353     unsigned audio_sampling_frequency = bits.getBits(3);
354     unsigned num_channels = bits.getBits(3);
355 
356     CHECK_EQ(audio_sampling_frequency, 2);  // 48kHz
357     CHECK_EQ(num_channels, 1u);  // stereo!
358 
359     if (mFormat == NULL) {
360         mFormat = new MetaData;
361         mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
362         mFormat->setInt32(kKeyChannelCount, 2);
363         mFormat->setInt32(kKeySampleRate, 48000);
364     }
365 
366     static const size_t kFramesPerAU = 80;
367     size_t frameSize = 2 /* numChannels */ * sizeof(int16_t);
368 
369     size_t payloadSize = numAUs * frameSize * kFramesPerAU;
370 
371     if (mBuffer->size() < 4 + payloadSize) {
372         return NULL;
373     }
374 
375     sp<ABuffer> accessUnit = new ABuffer(payloadSize);
376     memcpy(accessUnit->data(), mBuffer->data() + 4, payloadSize);
377 
378     int64_t timeUs = fetchTimestamp(payloadSize + 4);
379     CHECK_GE(timeUs, 0ll);
380     accessUnit->meta()->setInt64("timeUs", timeUs);
381 
382     int16_t *ptr = (int16_t *)accessUnit->data();
383     for (size_t i = 0; i < payloadSize / sizeof(int16_t); ++i) {
384         ptr[i] = ntohs(ptr[i]);
385     }
386 
387     memmove(
388             mBuffer->data(),
389             mBuffer->data() + 4 + payloadSize,
390             mBuffer->size() - 4 - payloadSize);
391 
392     mBuffer->setRange(0, mBuffer->size() - 4 - payloadSize);
393 
394     return accessUnit;
395 }
396 
dequeueAccessUnitAAC()397 sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitAAC() {
398     if (mBuffer->size() == 0) {
399         return NULL;
400     }
401 
402     CHECK(!mRangeInfos.empty());
403 
404     const RangeInfo &info = *mRangeInfos.begin();
405     if (mBuffer->size() < info.mLength) {
406         return NULL;
407     }
408 
409     CHECK_GE(info.mTimestampUs, 0ll);
410 
411     // The idea here is consume all AAC frames starting at offsets before
412     // info.mLength so we can assign a meaningful timestamp without
413     // having to interpolate.
414     // The final AAC frame may well extend into the next RangeInfo but
415     // that's ok.
416     size_t offset = 0;
417     while (offset < info.mLength) {
418         if (offset + 7 > mBuffer->size()) {
419             return NULL;
420         }
421 
422         ABitReader bits(mBuffer->data() + offset, mBuffer->size() - offset);
423 
424         // adts_fixed_header
425 
426         CHECK_EQ(bits.getBits(12), 0xfffu);
427         bits.skipBits(3);  // ID, layer
428         bool protection_absent = bits.getBits(1) != 0;
429 
430         if (mFormat == NULL) {
431             unsigned profile = bits.getBits(2);
432             CHECK_NE(profile, 3u);
433             unsigned sampling_freq_index = bits.getBits(4);
434             bits.getBits(1);  // private_bit
435             unsigned channel_configuration = bits.getBits(3);
436             CHECK_NE(channel_configuration, 0u);
437             bits.skipBits(2);  // original_copy, home
438 
439             mFormat = MakeAACCodecSpecificData(
440                     profile, sampling_freq_index, channel_configuration);
441 
442             mFormat->setInt32(kKeyIsADTS, true);
443 
444             int32_t sampleRate;
445             int32_t numChannels;
446             CHECK(mFormat->findInt32(kKeySampleRate, &sampleRate));
447             CHECK(mFormat->findInt32(kKeyChannelCount, &numChannels));
448 
449             ALOGI("found AAC codec config (%d Hz, %d channels)",
450                  sampleRate, numChannels);
451         } else {
452             // profile_ObjectType, sampling_frequency_index, private_bits,
453             // channel_configuration, original_copy, home
454             bits.skipBits(12);
455         }
456 
457         // adts_variable_header
458 
459         // copyright_identification_bit, copyright_identification_start
460         bits.skipBits(2);
461 
462         unsigned aac_frame_length = bits.getBits(13);
463 
464         bits.skipBits(11);  // adts_buffer_fullness
465 
466         unsigned number_of_raw_data_blocks_in_frame = bits.getBits(2);
467 
468         if (number_of_raw_data_blocks_in_frame != 0) {
469             // To be implemented.
470             TRESPASS();
471         }
472 
473         if (offset + aac_frame_length > mBuffer->size()) {
474             return NULL;
475         }
476 
477         size_t headerSize = protection_absent ? 7 : 9;
478 
479         offset += aac_frame_length;
480     }
481 
482     int64_t timeUs = fetchTimestamp(offset);
483 
484     sp<ABuffer> accessUnit = new ABuffer(offset);
485     memcpy(accessUnit->data(), mBuffer->data(), offset);
486 
487     memmove(mBuffer->data(), mBuffer->data() + offset,
488             mBuffer->size() - offset);
489     mBuffer->setRange(0, mBuffer->size() - offset);
490 
491     accessUnit->meta()->setInt64("timeUs", timeUs);
492 
493     return accessUnit;
494 }
495 
fetchTimestamp(size_t size)496 int64_t ElementaryStreamQueue::fetchTimestamp(size_t size) {
497     int64_t timeUs = -1;
498     bool first = true;
499 
500     while (size > 0) {
501         CHECK(!mRangeInfos.empty());
502 
503         RangeInfo *info = &*mRangeInfos.begin();
504 
505         if (first) {
506             timeUs = info->mTimestampUs;
507         }
508 
509         if (info->mLength > size) {
510             info->mLength -= size;
511 
512             if (first) {
513                 info->mTimestampUs = -1;
514             }
515 
516             size = 0;
517         } else {
518             size -= info->mLength;
519 
520             mRangeInfos.erase(mRangeInfos.begin());
521             info = NULL;
522         }
523 
524         first = false;
525     }
526 
527     if (timeUs == 0ll) {
528         ALOGV("Returning 0 timestamp");
529     }
530 
531     return timeUs;
532 }
533 
534 struct NALPosition {
535     size_t nalOffset;
536     size_t nalSize;
537 };
538 
dequeueAccessUnitH264()539 sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitH264() {
540     const uint8_t *data = mBuffer->data();
541 
542     size_t size = mBuffer->size();
543     Vector<NALPosition> nals;
544 
545     size_t totalSize = 0;
546 
547     status_t err;
548     const uint8_t *nalStart;
549     size_t nalSize;
550     bool foundSlice = false;
551     while ((err = getNextNALUnit(&data, &size, &nalStart, &nalSize)) == OK) {
552         if (nalSize == 0) continue;
553 
554         unsigned nalType = nalStart[0] & 0x1f;
555         bool flush = false;
556 
557         if (nalType == 1 || nalType == 5) {
558             if (foundSlice) {
559                 ABitReader br(nalStart + 1, nalSize);
560                 unsigned first_mb_in_slice = parseUE(&br);
561 
562                 if (first_mb_in_slice == 0) {
563                     // This slice starts a new frame.
564 
565                     flush = true;
566                 }
567             }
568 
569             foundSlice = true;
570         } else if ((nalType == 9 || nalType == 7) && foundSlice) {
571             // Access unit delimiter and SPS will be associated with the
572             // next frame.
573 
574             flush = true;
575         }
576 
577         if (flush) {
578             // The access unit will contain all nal units up to, but excluding
579             // the current one, separated by 0x00 0x00 0x00 0x01 startcodes.
580 
581             size_t auSize = 4 * nals.size() + totalSize;
582             sp<ABuffer> accessUnit = new ABuffer(auSize);
583 
584 #if !LOG_NDEBUG
585             AString out;
586 #endif
587 
588             size_t dstOffset = 0;
589             for (size_t i = 0; i < nals.size(); ++i) {
590                 const NALPosition &pos = nals.itemAt(i);
591 
592                 unsigned nalType = mBuffer->data()[pos.nalOffset] & 0x1f;
593 
594 #if !LOG_NDEBUG
595                 char tmp[128];
596                 sprintf(tmp, "0x%02x", nalType);
597                 if (i > 0) {
598                     out.append(", ");
599                 }
600                 out.append(tmp);
601 #endif
602 
603                 memcpy(accessUnit->data() + dstOffset, "\x00\x00\x00\x01", 4);
604 
605                 memcpy(accessUnit->data() + dstOffset + 4,
606                        mBuffer->data() + pos.nalOffset,
607                        pos.nalSize);
608 
609                 dstOffset += pos.nalSize + 4;
610             }
611 
612             ALOGV("accessUnit contains nal types %s", out.c_str());
613 
614             const NALPosition &pos = nals.itemAt(nals.size() - 1);
615             size_t nextScan = pos.nalOffset + pos.nalSize;
616 
617             memmove(mBuffer->data(),
618                     mBuffer->data() + nextScan,
619                     mBuffer->size() - nextScan);
620 
621             mBuffer->setRange(0, mBuffer->size() - nextScan);
622 
623             int64_t timeUs = fetchTimestamp(nextScan);
624             CHECK_GE(timeUs, 0ll);
625 
626             accessUnit->meta()->setInt64("timeUs", timeUs);
627 
628             if (mFormat == NULL) {
629                 mFormat = MakeAVCCodecSpecificData(accessUnit);
630             }
631 
632             return accessUnit;
633         }
634 
635         NALPosition pos;
636         pos.nalOffset = nalStart - mBuffer->data();
637         pos.nalSize = nalSize;
638 
639         nals.push(pos);
640 
641         totalSize += nalSize;
642     }
643     CHECK_EQ(err, (status_t)-EAGAIN);
644 
645     return NULL;
646 }
647 
dequeueAccessUnitMPEGAudio()648 sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitMPEGAudio() {
649     const uint8_t *data = mBuffer->data();
650     size_t size = mBuffer->size();
651 
652     if (size < 4) {
653         return NULL;
654     }
655 
656     uint32_t header = U32_AT(data);
657 
658     size_t frameSize;
659     int samplingRate, numChannels, bitrate, numSamples;
660     CHECK(GetMPEGAudioFrameSize(
661                 header, &frameSize, &samplingRate, &numChannels,
662                 &bitrate, &numSamples));
663 
664     if (size < frameSize) {
665         return NULL;
666     }
667 
668     unsigned layer = 4 - ((header >> 17) & 3);
669 
670     sp<ABuffer> accessUnit = new ABuffer(frameSize);
671     memcpy(accessUnit->data(), data, frameSize);
672 
673     memmove(mBuffer->data(),
674             mBuffer->data() + frameSize,
675             mBuffer->size() - frameSize);
676 
677     mBuffer->setRange(0, mBuffer->size() - frameSize);
678 
679     int64_t timeUs = fetchTimestamp(frameSize);
680     CHECK_GE(timeUs, 0ll);
681 
682     accessUnit->meta()->setInt64("timeUs", timeUs);
683 
684     if (mFormat == NULL) {
685         mFormat = new MetaData;
686 
687         switch (layer) {
688             case 1:
689                 mFormat->setCString(
690                         kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I);
691                 break;
692             case 2:
693                 mFormat->setCString(
694                         kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II);
695                 break;
696             case 3:
697                 mFormat->setCString(
698                         kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
699                 break;
700             default:
701                 TRESPASS();
702         }
703 
704         mFormat->setInt32(kKeySampleRate, samplingRate);
705         mFormat->setInt32(kKeyChannelCount, numChannels);
706     }
707 
708     return accessUnit;
709 }
710 
EncodeSize14(uint8_t ** _ptr,size_t size)711 static void EncodeSize14(uint8_t **_ptr, size_t size) {
712     CHECK_LE(size, 0x3fff);
713 
714     uint8_t *ptr = *_ptr;
715 
716     *ptr++ = 0x80 | (size >> 7);
717     *ptr++ = size & 0x7f;
718 
719     *_ptr = ptr;
720 }
721 
MakeMPEGVideoESDS(const sp<ABuffer> & csd)722 static sp<ABuffer> MakeMPEGVideoESDS(const sp<ABuffer> &csd) {
723     sp<ABuffer> esds = new ABuffer(csd->size() + 25);
724 
725     uint8_t *ptr = esds->data();
726     *ptr++ = 0x03;
727     EncodeSize14(&ptr, 22 + csd->size());
728 
729     *ptr++ = 0x00;  // ES_ID
730     *ptr++ = 0x00;
731 
732     *ptr++ = 0x00;  // streamDependenceFlag, URL_Flag, OCRstreamFlag
733 
734     *ptr++ = 0x04;
735     EncodeSize14(&ptr, 16 + csd->size());
736 
737     *ptr++ = 0x40;  // Audio ISO/IEC 14496-3
738 
739     for (size_t i = 0; i < 12; ++i) {
740         *ptr++ = 0x00;
741     }
742 
743     *ptr++ = 0x05;
744     EncodeSize14(&ptr, csd->size());
745 
746     memcpy(ptr, csd->data(), csd->size());
747 
748     return esds;
749 }
750 
dequeueAccessUnitMPEGVideo()751 sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitMPEGVideo() {
752     const uint8_t *data = mBuffer->data();
753     size_t size = mBuffer->size();
754 
755     bool sawPictureStart = false;
756     int pprevStartCode = -1;
757     int prevStartCode = -1;
758     int currentStartCode = -1;
759 
760     size_t offset = 0;
761     while (offset + 3 < size) {
762         if (memcmp(&data[offset], "\x00\x00\x01", 3)) {
763             ++offset;
764             continue;
765         }
766 
767         pprevStartCode = prevStartCode;
768         prevStartCode = currentStartCode;
769         currentStartCode = data[offset + 3];
770 
771         if (currentStartCode == 0xb3 && mFormat == NULL) {
772             memmove(mBuffer->data(), mBuffer->data() + offset, size - offset);
773             size -= offset;
774             (void)fetchTimestamp(offset);
775             offset = 0;
776             mBuffer->setRange(0, size);
777         }
778 
779         if ((prevStartCode == 0xb3 && currentStartCode != 0xb5)
780                 || (pprevStartCode == 0xb3 && prevStartCode == 0xb5)) {
781             // seqHeader without/with extension
782 
783             if (mFormat == NULL) {
784                 CHECK_GE(size, 7u);
785 
786                 unsigned width =
787                     (data[4] << 4) | data[5] >> 4;
788 
789                 unsigned height =
790                     ((data[5] & 0x0f) << 8) | data[6];
791 
792                 mFormat = new MetaData;
793                 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG2);
794                 mFormat->setInt32(kKeyWidth, width);
795                 mFormat->setInt32(kKeyHeight, height);
796 
797                 ALOGI("found MPEG2 video codec config (%d x %d)", width, height);
798 
799                 sp<ABuffer> csd = new ABuffer(offset);
800                 memcpy(csd->data(), data, offset);
801 
802                 memmove(mBuffer->data(),
803                         mBuffer->data() + offset,
804                         mBuffer->size() - offset);
805 
806                 mBuffer->setRange(0, mBuffer->size() - offset);
807                 size -= offset;
808                 (void)fetchTimestamp(offset);
809                 offset = 0;
810 
811                 // hexdump(csd->data(), csd->size());
812 
813                 sp<ABuffer> esds = MakeMPEGVideoESDS(csd);
814                 mFormat->setData(
815                         kKeyESDS, kTypeESDS, esds->data(), esds->size());
816 
817                 return NULL;
818             }
819         }
820 
821         if (mFormat != NULL && currentStartCode == 0x00) {
822             // Picture start
823 
824             if (!sawPictureStart) {
825                 sawPictureStart = true;
826             } else {
827                 sp<ABuffer> accessUnit = new ABuffer(offset);
828                 memcpy(accessUnit->data(), data, offset);
829 
830                 memmove(mBuffer->data(),
831                         mBuffer->data() + offset,
832                         mBuffer->size() - offset);
833 
834                 mBuffer->setRange(0, mBuffer->size() - offset);
835 
836                 int64_t timeUs = fetchTimestamp(offset);
837                 CHECK_GE(timeUs, 0ll);
838 
839                 offset = 0;
840 
841                 accessUnit->meta()->setInt64("timeUs", timeUs);
842 
843                 ALOGV("returning MPEG video access unit at time %lld us",
844                       timeUs);
845 
846                 // hexdump(accessUnit->data(), accessUnit->size());
847 
848                 return accessUnit;
849             }
850         }
851 
852         ++offset;
853     }
854 
855     return NULL;
856 }
857 
getNextChunkSize(const uint8_t * data,size_t size)858 static ssize_t getNextChunkSize(
859         const uint8_t *data, size_t size) {
860     static const char kStartCode[] = "\x00\x00\x01";
861 
862     if (size < 3) {
863         return -EAGAIN;
864     }
865 
866     if (memcmp(kStartCode, data, 3)) {
867         TRESPASS();
868     }
869 
870     size_t offset = 3;
871     while (offset + 2 < size) {
872         if (!memcmp(&data[offset], kStartCode, 3)) {
873             return offset;
874         }
875 
876         ++offset;
877     }
878 
879     return -EAGAIN;
880 }
881 
dequeueAccessUnitMPEG4Video()882 sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitMPEG4Video() {
883     uint8_t *data = mBuffer->data();
884     size_t size = mBuffer->size();
885 
886     enum {
887         SKIP_TO_VISUAL_OBJECT_SEQ_START,
888         EXPECT_VISUAL_OBJECT_START,
889         EXPECT_VO_START,
890         EXPECT_VOL_START,
891         WAIT_FOR_VOP_START,
892         SKIP_TO_VOP_START,
893 
894     } state;
895 
896     if (mFormat == NULL) {
897         state = SKIP_TO_VISUAL_OBJECT_SEQ_START;
898     } else {
899         state = SKIP_TO_VOP_START;
900     }
901 
902     int32_t width = -1, height = -1;
903 
904     size_t offset = 0;
905     ssize_t chunkSize;
906     while ((chunkSize = getNextChunkSize(
907                     &data[offset], size - offset)) > 0) {
908         bool discard = false;
909 
910         unsigned chunkType = data[offset + 3];
911 
912         switch (state) {
913             case SKIP_TO_VISUAL_OBJECT_SEQ_START:
914             {
915                 if (chunkType == 0xb0) {
916                     // Discard anything before this marker.
917 
918                     state = EXPECT_VISUAL_OBJECT_START;
919                 } else {
920                     discard = true;
921                 }
922                 break;
923             }
924 
925             case EXPECT_VISUAL_OBJECT_START:
926             {
927                 CHECK_EQ(chunkType, 0xb5);
928                 state = EXPECT_VO_START;
929                 break;
930             }
931 
932             case EXPECT_VO_START:
933             {
934                 CHECK_LE(chunkType, 0x1f);
935                 state = EXPECT_VOL_START;
936                 break;
937             }
938 
939             case EXPECT_VOL_START:
940             {
941                 CHECK((chunkType & 0xf0) == 0x20);
942 
943                 CHECK(ExtractDimensionsFromVOLHeader(
944                             &data[offset], chunkSize,
945                             &width, &height));
946 
947                 state = WAIT_FOR_VOP_START;
948                 break;
949             }
950 
951             case WAIT_FOR_VOP_START:
952             {
953                 if (chunkType == 0xb3 || chunkType == 0xb6) {
954                     // group of VOP or VOP start.
955 
956                     mFormat = new MetaData;
957                     mFormat->setCString(
958                             kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
959 
960                     mFormat->setInt32(kKeyWidth, width);
961                     mFormat->setInt32(kKeyHeight, height);
962 
963                     ALOGI("found MPEG4 video codec config (%d x %d)",
964                          width, height);
965 
966                     sp<ABuffer> csd = new ABuffer(offset);
967                     memcpy(csd->data(), data, offset);
968 
969                     // hexdump(csd->data(), csd->size());
970 
971                     sp<ABuffer> esds = MakeMPEGVideoESDS(csd);
972                     mFormat->setData(
973                             kKeyESDS, kTypeESDS,
974                             esds->data(), esds->size());
975 
976                     discard = true;
977                     state = SKIP_TO_VOP_START;
978                 }
979 
980                 break;
981             }
982 
983             case SKIP_TO_VOP_START:
984             {
985                 if (chunkType == 0xb6) {
986                     offset += chunkSize;
987 
988                     sp<ABuffer> accessUnit = new ABuffer(offset);
989                     memcpy(accessUnit->data(), data, offset);
990 
991                     memmove(data, &data[offset], size - offset);
992                     size -= offset;
993                     mBuffer->setRange(0, size);
994 
995                     int64_t timeUs = fetchTimestamp(offset);
996                     CHECK_GE(timeUs, 0ll);
997 
998                     offset = 0;
999 
1000                     accessUnit->meta()->setInt64("timeUs", timeUs);
1001 
1002                     ALOGV("returning MPEG4 video access unit at time %lld us",
1003                          timeUs);
1004 
1005                     // hexdump(accessUnit->data(), accessUnit->size());
1006 
1007                     return accessUnit;
1008                 } else if (chunkType != 0xb3) {
1009                     offset += chunkSize;
1010                     discard = true;
1011                 }
1012 
1013                 break;
1014             }
1015 
1016             default:
1017                 TRESPASS();
1018         }
1019 
1020         if (discard) {
1021             (void)fetchTimestamp(offset);
1022             memmove(data, &data[offset], size - offset);
1023             size -= offset;
1024             offset = 0;
1025             mBuffer->setRange(0, size);
1026         } else {
1027             offset += chunkSize;
1028         }
1029     }
1030 
1031     return NULL;
1032 }
1033 
1034 }  // namespace android
1035