• 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 "MPEG2TSWriter"
19 #include <media/stagefright/foundation/ADebug.h>
20 
21 #include <media/stagefright/foundation/hexdump.h>
22 #include <media/stagefright/foundation/ABuffer.h>
23 #include <media/stagefright/foundation/AMessage.h>
24 #include <media/stagefright/MPEG2TSWriter.h>
25 #include <media/stagefright/MediaBuffer.h>
26 #include <media/stagefright/MediaDefs.h>
27 #include <media/stagefright/MediaErrors.h>
28 #include <media/stagefright/MediaSource.h>
29 #include <media/stagefright/MetaData.h>
30 #include <media/stagefright/Utils.h>
31 #include <arpa/inet.h>
32 
33 #include "include/ESDS.h"
34 
35 namespace android {
36 
37 struct MPEG2TSWriter::SourceInfo : public AHandler {
38     SourceInfo(const sp<IMediaSource> &source);
39 
40     void start(const sp<AMessage> &notify);
41     void stop();
42 
43     unsigned streamType() const;
44     unsigned incrementContinuityCounter();
45 
46     void readMore();
47 
48     enum {
49         kNotifyStartFailed,
50         kNotifyBuffer,
51         kNotifyReachedEOS,
52     };
53 
54     sp<ABuffer> lastAccessUnit();
55     int64_t lastAccessUnitTimeUs();
56     void setLastAccessUnit(const sp<ABuffer> &accessUnit);
57 
58     void setEOSReceived();
59     bool eosReceived() const;
60 
61 protected:
62     virtual void onMessageReceived(const sp<AMessage> &msg);
63 
64     virtual ~SourceInfo();
65 
66 private:
67     enum {
68         kWhatStart = 'strt',
69         kWhatRead  = 'read',
70     };
71 
72     sp<IMediaSource> mSource;
73     sp<ALooper> mLooper;
74     sp<AMessage> mNotify;
75 
76     sp<ABuffer> mAACCodecSpecificData;
77 
78     sp<ABuffer> mAACBuffer;
79 
80     sp<ABuffer> mLastAccessUnit;
81     bool mEOSReceived;
82 
83     unsigned mStreamType;
84     unsigned mContinuityCounter;
85 
86     void extractCodecSpecificData();
87 
88     bool appendAACFrames(MediaBuffer *buffer);
89     bool flushAACFrames();
90 
91     void postAVCFrame(MediaBuffer *buffer);
92 
93     DISALLOW_EVIL_CONSTRUCTORS(SourceInfo);
94 };
95 
SourceInfo(const sp<IMediaSource> & source)96 MPEG2TSWriter::SourceInfo::SourceInfo(const sp<IMediaSource> &source)
97     : mSource(source),
98       mLooper(new ALooper),
99       mEOSReceived(false),
100       mStreamType(0),
101       mContinuityCounter(0) {
102     mLooper->setName("MPEG2TSWriter source");
103 
104     sp<MetaData> meta = mSource->getFormat();
105     const char *mime;
106     CHECK(meta->findCString(kKeyMIMEType, &mime));
107 
108     if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
109         mStreamType = 0x0f;
110     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
111         mStreamType = 0x1b;
112     } else {
113         TRESPASS();
114     }
115 }
116 
~SourceInfo()117 MPEG2TSWriter::SourceInfo::~SourceInfo() {
118 }
119 
streamType() const120 unsigned MPEG2TSWriter::SourceInfo::streamType() const {
121     return mStreamType;
122 }
123 
incrementContinuityCounter()124 unsigned MPEG2TSWriter::SourceInfo::incrementContinuityCounter() {
125     if (++mContinuityCounter == 16) {
126         mContinuityCounter = 0;
127     }
128 
129     return mContinuityCounter;
130 }
131 
start(const sp<AMessage> & notify)132 void MPEG2TSWriter::SourceInfo::start(const sp<AMessage> &notify) {
133     mLooper->registerHandler(this);
134     mLooper->start();
135 
136     mNotify = notify;
137 
138     (new AMessage(kWhatStart, this))->post();
139 }
140 
stop()141 void MPEG2TSWriter::SourceInfo::stop() {
142     mLooper->unregisterHandler(id());
143     mLooper->stop();
144 
145     mSource->stop();
146 }
147 
extractCodecSpecificData()148 void MPEG2TSWriter::SourceInfo::extractCodecSpecificData() {
149     sp<MetaData> meta = mSource->getFormat();
150 
151     const char *mime;
152     CHECK(meta->findCString(kKeyMIMEType, &mime));
153 
154     if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
155         uint32_t type;
156         const void *data;
157         size_t size;
158         if (!meta->findData(kKeyESDS, &type, &data, &size)) {
159             // Codec specific data better be in the first data buffer.
160             return;
161         }
162 
163         ESDS esds((const char *)data, size);
164         CHECK_EQ(esds.InitCheck(), (status_t)OK);
165 
166         const uint8_t *codec_specific_data;
167         size_t codec_specific_data_size;
168         esds.getCodecSpecificInfo(
169                 (const void **)&codec_specific_data, &codec_specific_data_size);
170 
171         CHECK_GE(codec_specific_data_size, 2u);
172 
173         mAACCodecSpecificData = new ABuffer(codec_specific_data_size);
174 
175         memcpy(mAACCodecSpecificData->data(), codec_specific_data,
176                codec_specific_data_size);
177 
178         return;
179     }
180 
181     if (strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
182         return;
183     }
184 
185     uint32_t type;
186     const void *data;
187     size_t size;
188     if (!meta->findData(kKeyAVCC, &type, &data, &size)) {
189         // Codec specific data better be part of the data stream then.
190         return;
191     }
192 
193     sp<ABuffer> out = new ABuffer(1024);
194     out->setRange(0, 0);
195 
196     const uint8_t *ptr = (const uint8_t *)data;
197 
198     size_t numSeqParameterSets = ptr[5] & 31;
199 
200     ptr += 6;
201     size -= 6;
202 
203     for (size_t i = 0; i < numSeqParameterSets; ++i) {
204         CHECK(size >= 2);
205         size_t length = U16_AT(ptr);
206 
207         ptr += 2;
208         size -= 2;
209 
210         CHECK(size >= length);
211 
212         CHECK_LE(out->size() + 4 + length, out->capacity());
213         memcpy(out->data() + out->size(), "\x00\x00\x00\x01", 4);
214         memcpy(out->data() + out->size() + 4, ptr, length);
215         out->setRange(0, out->size() + length + 4);
216 
217         ptr += length;
218         size -= length;
219     }
220 
221     CHECK(size >= 1);
222     size_t numPictureParameterSets = *ptr;
223     ++ptr;
224     --size;
225 
226     for (size_t i = 0; i < numPictureParameterSets; ++i) {
227         CHECK(size >= 2);
228         size_t length = U16_AT(ptr);
229 
230         ptr += 2;
231         size -= 2;
232 
233         CHECK(size >= length);
234 
235         CHECK_LE(out->size() + 4 + length, out->capacity());
236         memcpy(out->data() + out->size(), "\x00\x00\x00\x01", 4);
237         memcpy(out->data() + out->size() + 4, ptr, length);
238         out->setRange(0, out->size() + length + 4);
239 
240         ptr += length;
241         size -= length;
242     }
243 
244     out->meta()->setInt64("timeUs", 0ll);
245 
246     sp<AMessage> notify = mNotify->dup();
247     notify->setInt32("what", kNotifyBuffer);
248     notify->setBuffer("buffer", out);
249     notify->setInt32("oob", true);
250     notify->post();
251 }
252 
postAVCFrame(MediaBuffer * buffer)253 void MPEG2TSWriter::SourceInfo::postAVCFrame(MediaBuffer *buffer) {
254     sp<AMessage> notify = mNotify->dup();
255     notify->setInt32("what", kNotifyBuffer);
256 
257     sp<ABuffer> copy =
258         new ABuffer(buffer->range_length());
259     memcpy(copy->data(),
260            (const uint8_t *)buffer->data()
261             + buffer->range_offset(),
262            buffer->range_length());
263 
264     int64_t timeUs;
265     CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
266     copy->meta()->setInt64("timeUs", timeUs);
267 
268     int32_t isSync;
269     if (buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)
270             && isSync != 0) {
271         copy->meta()->setInt32("isSync", true);
272     }
273 
274     notify->setBuffer("buffer", copy);
275     notify->post();
276 }
277 
appendAACFrames(MediaBuffer * buffer)278 bool MPEG2TSWriter::SourceInfo::appendAACFrames(MediaBuffer *buffer) {
279     bool accessUnitPosted = false;
280 
281     if (mAACBuffer != NULL
282             && mAACBuffer->size() + 7 + buffer->range_length()
283                     > mAACBuffer->capacity()) {
284         accessUnitPosted = flushAACFrames();
285     }
286 
287     if (mAACBuffer == NULL) {
288         size_t alloc = 4096;
289         if (buffer->range_length() + 7 > alloc) {
290             alloc = 7 + buffer->range_length();
291         }
292 
293         mAACBuffer = new ABuffer(alloc);
294 
295         int64_t timeUs;
296         CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
297 
298         mAACBuffer->meta()->setInt64("timeUs", timeUs);
299         mAACBuffer->meta()->setInt32("isSync", true);
300 
301         mAACBuffer->setRange(0, 0);
302     }
303 
304     const uint8_t *codec_specific_data = mAACCodecSpecificData->data();
305 
306     unsigned profile = (codec_specific_data[0] >> 3) - 1;
307 
308     unsigned sampling_freq_index =
309         ((codec_specific_data[0] & 7) << 1)
310         | (codec_specific_data[1] >> 7);
311 
312     unsigned channel_configuration =
313         (codec_specific_data[1] >> 3) & 0x0f;
314 
315     uint8_t *ptr = mAACBuffer->data() + mAACBuffer->size();
316 
317     const uint32_t aac_frame_length = buffer->range_length() + 7;
318 
319     *ptr++ = 0xff;
320     *ptr++ = 0xf1;  // b11110001, ID=0, layer=0, protection_absent=1
321 
322     *ptr++ =
323         profile << 6
324         | sampling_freq_index << 2
325         | ((channel_configuration >> 2) & 1);  // private_bit=0
326 
327     // original_copy=0, home=0, copyright_id_bit=0, copyright_id_start=0
328     *ptr++ =
329         (channel_configuration & 3) << 6
330         | aac_frame_length >> 11;
331     *ptr++ = (aac_frame_length >> 3) & 0xff;
332     *ptr++ = (aac_frame_length & 7) << 5;
333 
334     // adts_buffer_fullness=0, number_of_raw_data_blocks_in_frame=0
335     *ptr++ = 0;
336 
337     memcpy(ptr,
338            (const uint8_t *)buffer->data() + buffer->range_offset(),
339            buffer->range_length());
340 
341     ptr += buffer->range_length();
342 
343     mAACBuffer->setRange(0, ptr - mAACBuffer->data());
344 
345     return accessUnitPosted;
346 }
347 
flushAACFrames()348 bool MPEG2TSWriter::SourceInfo::flushAACFrames() {
349     if (mAACBuffer == NULL) {
350         return false;
351     }
352 
353     sp<AMessage> notify = mNotify->dup();
354     notify->setInt32("what", kNotifyBuffer);
355     notify->setBuffer("buffer", mAACBuffer);
356     notify->post();
357 
358     mAACBuffer.clear();
359 
360     return true;
361 }
362 
readMore()363 void MPEG2TSWriter::SourceInfo::readMore() {
364     (new AMessage(kWhatRead, this))->post();
365 }
366 
onMessageReceived(const sp<AMessage> & msg)367 void MPEG2TSWriter::SourceInfo::onMessageReceived(const sp<AMessage> &msg) {
368     switch (msg->what()) {
369         case kWhatStart:
370         {
371             status_t err = mSource->start();
372             if (err != OK) {
373                 sp<AMessage> notify = mNotify->dup();
374                 notify->setInt32("what", kNotifyStartFailed);
375                 notify->post();
376                 break;
377             }
378 
379             extractCodecSpecificData();
380 
381             readMore();
382             break;
383         }
384 
385         case kWhatRead:
386         {
387             MediaBuffer *buffer;
388             status_t err = mSource->read(&buffer);
389 
390             if (err != OK && err != INFO_FORMAT_CHANGED) {
391                 if (mStreamType == 0x0f) {
392                     flushAACFrames();
393                 }
394 
395                 sp<AMessage> notify = mNotify->dup();
396                 notify->setInt32("what", kNotifyReachedEOS);
397                 notify->setInt32("status", err);
398                 notify->post();
399                 break;
400             }
401 
402             if (err == OK) {
403                 if (mStreamType == 0x0f && mAACCodecSpecificData == NULL) {
404                     // The first buffer contains codec specific data.
405 
406                     CHECK_GE(buffer->range_length(), 2u);
407 
408                     mAACCodecSpecificData = new ABuffer(buffer->range_length());
409 
410                     memcpy(mAACCodecSpecificData->data(),
411                            (const uint8_t *)buffer->data()
412                             + buffer->range_offset(),
413                            buffer->range_length());
414                 } else if (buffer->range_length() > 0) {
415                     if (mStreamType == 0x0f) {
416                         if (!appendAACFrames(buffer)) {
417                             msg->post();
418                         }
419                     } else {
420                         postAVCFrame(buffer);
421                     }
422                 } else {
423                     readMore();
424                 }
425 
426                 buffer->release();
427                 buffer = NULL;
428             }
429 
430             // Do not read more data until told to.
431             break;
432         }
433 
434         default:
435             TRESPASS();
436     }
437 }
438 
lastAccessUnit()439 sp<ABuffer> MPEG2TSWriter::SourceInfo::lastAccessUnit() {
440     return mLastAccessUnit;
441 }
442 
setLastAccessUnit(const sp<ABuffer> & accessUnit)443 void MPEG2TSWriter::SourceInfo::setLastAccessUnit(
444         const sp<ABuffer> &accessUnit) {
445     mLastAccessUnit = accessUnit;
446 }
447 
lastAccessUnitTimeUs()448 int64_t MPEG2TSWriter::SourceInfo::lastAccessUnitTimeUs() {
449     if (mLastAccessUnit == NULL) {
450         return -1;
451     }
452 
453     int64_t timeUs;
454     CHECK(mLastAccessUnit->meta()->findInt64("timeUs", &timeUs));
455 
456     return timeUs;
457 }
458 
setEOSReceived()459 void MPEG2TSWriter::SourceInfo::setEOSReceived() {
460     CHECK(!mEOSReceived);
461     mEOSReceived = true;
462 }
463 
eosReceived() const464 bool MPEG2TSWriter::SourceInfo::eosReceived() const {
465     return mEOSReceived;
466 }
467 
468 ////////////////////////////////////////////////////////////////////////////////
469 
MPEG2TSWriter(int fd)470 MPEG2TSWriter::MPEG2TSWriter(int fd)
471     : mFile(fdopen(dup(fd), "wb")),
472       mWriteCookie(NULL),
473       mWriteFunc(NULL),
474       mStarted(false),
475       mNumSourcesDone(0),
476       mNumTSPacketsWritten(0),
477       mNumTSPacketsBeforeMeta(0),
478       mPATContinuityCounter(0),
479       mPMTContinuityCounter(0) {
480     init();
481 }
482 
MPEG2TSWriter(void * cookie,ssize_t (* write)(void * cookie,const void * data,size_t size))483 MPEG2TSWriter::MPEG2TSWriter(
484         void *cookie,
485         ssize_t (*write)(void *cookie, const void *data, size_t size))
486     : mFile(NULL),
487       mWriteCookie(cookie),
488       mWriteFunc(write),
489       mStarted(false),
490       mNumSourcesDone(0),
491       mNumTSPacketsWritten(0),
492       mNumTSPacketsBeforeMeta(0),
493       mPATContinuityCounter(0),
494       mPMTContinuityCounter(0) {
495     init();
496 }
497 
init()498 void MPEG2TSWriter::init() {
499     CHECK(mFile != NULL || mWriteFunc != NULL);
500 
501     initCrcTable();
502 
503     mLooper = new ALooper;
504     mLooper->setName("MPEG2TSWriter");
505 
506     mReflector = new AHandlerReflector<MPEG2TSWriter>(this);
507 
508     mLooper->registerHandler(mReflector);
509     mLooper->start();
510 }
511 
~MPEG2TSWriter()512 MPEG2TSWriter::~MPEG2TSWriter() {
513     if (mStarted) {
514         reset();
515     }
516 
517     mLooper->unregisterHandler(mReflector->id());
518     mLooper->stop();
519 
520     if (mFile != NULL) {
521         fclose(mFile);
522         mFile = NULL;
523     }
524 }
525 
addSource(const sp<IMediaSource> & source)526 status_t MPEG2TSWriter::addSource(const sp<IMediaSource> &source) {
527     CHECK(!mStarted);
528 
529     sp<MetaData> meta = source->getFormat();
530     const char *mime;
531     CHECK(meta->findCString(kKeyMIMEType, &mime));
532 
533     if (strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
534             && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
535         return ERROR_UNSUPPORTED;
536     }
537 
538     sp<SourceInfo> info = new SourceInfo(source);
539 
540     mSources.push(info);
541 
542     return OK;
543 }
544 
start(MetaData *)545 status_t MPEG2TSWriter::start(MetaData * /* param */) {
546     CHECK(!mStarted);
547 
548     mStarted = true;
549     mNumSourcesDone = 0;
550     mNumTSPacketsWritten = 0;
551     mNumTSPacketsBeforeMeta = 0;
552 
553     for (size_t i = 0; i < mSources.size(); ++i) {
554         sp<AMessage> notify =
555             new AMessage(kWhatSourceNotify, mReflector);
556 
557         notify->setInt32("source-index", i);
558 
559         mSources.editItemAt(i)->start(notify);
560     }
561 
562     return OK;
563 }
564 
reset()565 status_t MPEG2TSWriter::reset() {
566     CHECK(mStarted);
567 
568     for (size_t i = 0; i < mSources.size(); ++i) {
569         mSources.editItemAt(i)->stop();
570     }
571     mStarted = false;
572 
573     return OK;
574 }
575 
pause()576 status_t MPEG2TSWriter::pause() {
577     CHECK(mStarted);
578 
579     return OK;
580 }
581 
reachedEOS()582 bool MPEG2TSWriter::reachedEOS() {
583     return !mStarted || (mNumSourcesDone == mSources.size() ? true : false);
584 }
585 
dump(int,const Vector<String16> &)586 status_t MPEG2TSWriter::dump(
587         int /* fd */, const Vector<String16> & /* args */) {
588     return OK;
589 }
590 
onMessageReceived(const sp<AMessage> & msg)591 void MPEG2TSWriter::onMessageReceived(const sp<AMessage> &msg) {
592     switch (msg->what()) {
593         case kWhatSourceNotify:
594         {
595             int32_t sourceIndex;
596             CHECK(msg->findInt32("source-index", &sourceIndex));
597 
598             int32_t what;
599             CHECK(msg->findInt32("what", &what));
600 
601             if (what == SourceInfo::kNotifyReachedEOS
602                     || what == SourceInfo::kNotifyStartFailed) {
603                 sp<SourceInfo> source = mSources.editItemAt(sourceIndex);
604                 source->setEOSReceived();
605 
606                 sp<ABuffer> buffer = source->lastAccessUnit();
607                 source->setLastAccessUnit(NULL);
608 
609                 if (buffer != NULL) {
610                     writeTS();
611                     writeAccessUnit(sourceIndex, buffer);
612                 }
613 
614                 ++mNumSourcesDone;
615             } else if (what == SourceInfo::kNotifyBuffer) {
616                 sp<ABuffer> buffer;
617                 CHECK(msg->findBuffer("buffer", &buffer));
618 
619                 int32_t oob;
620                 if (msg->findInt32("oob", &oob) && oob) {
621                     // This is codec specific data delivered out of band.
622                     // It can be written out immediately.
623                     writeTS();
624                     writeAccessUnit(sourceIndex, buffer);
625                     break;
626                 }
627 
628                 // We don't just write out data as we receive it from
629                 // the various sources. That would essentially write them
630                 // out in random order (as the thread scheduler determines
631                 // how the messages are dispatched).
632                 // Instead we gather an access unit for all tracks and
633                 // write out the one with the smallest timestamp, then
634                 // request more data for the written out track.
635                 // Rinse, repeat.
636                 // If we don't have data on any track we don't write
637                 // anything just yet.
638 
639                 sp<SourceInfo> source = mSources.editItemAt(sourceIndex);
640 
641                 CHECK(source->lastAccessUnit() == NULL);
642                 source->setLastAccessUnit(buffer);
643 
644                 ALOGV("lastAccessUnitTimeUs[%d] = %.2f secs",
645                      sourceIndex, source->lastAccessUnitTimeUs() / 1E6);
646 
647                 int64_t minTimeUs = -1;
648                 size_t minIndex = 0;
649 
650                 for (size_t i = 0; i < mSources.size(); ++i) {
651                     const sp<SourceInfo> &source = mSources.editItemAt(i);
652 
653                     if (source->eosReceived()) {
654                         continue;
655                     }
656 
657                     int64_t timeUs = source->lastAccessUnitTimeUs();
658                     if (timeUs < 0) {
659                         minTimeUs = -1;
660                         break;
661                     } else if (minTimeUs < 0 || timeUs < minTimeUs) {
662                         minTimeUs = timeUs;
663                         minIndex = i;
664                     }
665                 }
666 
667                 if (minTimeUs < 0) {
668                     ALOGV("not a all tracks have valid data.");
669                     break;
670                 }
671 
672                 ALOGV("writing access unit at time %.2f secs (index %zu)",
673                      minTimeUs / 1E6, minIndex);
674 
675                 source = mSources.editItemAt(minIndex);
676 
677                 buffer = source->lastAccessUnit();
678                 source->setLastAccessUnit(NULL);
679 
680                 writeTS();
681                 writeAccessUnit(minIndex, buffer);
682 
683                 source->readMore();
684             }
685             break;
686         }
687 
688         default:
689             TRESPASS();
690     }
691 }
692 
writeProgramAssociationTable()693 void MPEG2TSWriter::writeProgramAssociationTable() {
694     // 0x47
695     // transport_error_indicator = b0
696     // payload_unit_start_indicator = b1
697     // transport_priority = b0
698     // PID = b0000000000000 (13 bits)
699     // transport_scrambling_control = b00
700     // adaptation_field_control = b01 (no adaptation field, payload only)
701     // continuity_counter = b????
702     // skip = 0x00
703     // --- payload follows
704     // table_id = 0x00
705     // section_syntax_indicator = b1
706     // must_be_zero = b0
707     // reserved = b11
708     // section_length = 0x00d
709     // transport_stream_id = 0x0000
710     // reserved = b11
711     // version_number = b00001
712     // current_next_indicator = b1
713     // section_number = 0x00
714     // last_section_number = 0x00
715     //   one program follows:
716     //   program_number = 0x0001
717     //   reserved = b111
718     //   program_map_PID = 0x01e0 (13 bits!)
719     // CRC = 0x????????
720 
721     static const uint8_t kData[] = {
722         0x47,
723         0x40, 0x00, 0x10, 0x00,  // b0100 0000 0000 0000 0001 ???? 0000 0000
724         0x00, 0xb0, 0x0d, 0x00,  // b0000 0000 1011 0000 0000 1101 0000 0000
725         0x00, 0xc3, 0x00, 0x00,  // b0000 0000 1100 0011 0000 0000 0000 0000
726         0x00, 0x01, 0xe1, 0xe0,  // b0000 0000 0000 0001 1110 0001 1110 0000
727         0x00, 0x00, 0x00, 0x00   // b???? ???? ???? ???? ???? ???? ???? ????
728     };
729 
730     sp<ABuffer> buffer = new ABuffer(188);
731     memset(buffer->data(), 0xff, buffer->size());
732     memcpy(buffer->data(), kData, sizeof(kData));
733 
734     if (++mPATContinuityCounter == 16) {
735         mPATContinuityCounter = 0;
736     }
737     buffer->data()[3] |= mPATContinuityCounter;
738 
739     uint32_t crc = htonl(crc32(&buffer->data()[5], 12));
740     memcpy(&buffer->data()[17], &crc, sizeof(crc));
741 
742     CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
743 }
744 
writeProgramMap()745 void MPEG2TSWriter::writeProgramMap() {
746     // 0x47
747     // transport_error_indicator = b0
748     // payload_unit_start_indicator = b1
749     // transport_priority = b0
750     // PID = b0 0001 1110 0000 (13 bits) [0x1e0]
751     // transport_scrambling_control = b00
752     // adaptation_field_control = b01 (no adaptation field, payload only)
753     // continuity_counter = b????
754     // skip = 0x00
755     // -- payload follows
756     // table_id = 0x02
757     // section_syntax_indicator = b1
758     // must_be_zero = b0
759     // reserved = b11
760     // section_length = 0x???
761     // program_number = 0x0001
762     // reserved = b11
763     // version_number = b00001
764     // current_next_indicator = b1
765     // section_number = 0x00
766     // last_section_number = 0x00
767     // reserved = b111
768     // PCR_PID = b? ???? ???? ???? (13 bits)
769     // reserved = b1111
770     // program_info_length = 0x000
771     //   one or more elementary stream descriptions follow:
772     //   stream_type = 0x??
773     //   reserved = b111
774     //   elementary_PID = b? ???? ???? ???? (13 bits)
775     //   reserved = b1111
776     //   ES_info_length = 0x000
777     // CRC = 0x????????
778 
779     static const uint8_t kData[] = {
780         0x47,
781         0x41, 0xe0, 0x10, 0x00,  // b0100 0001 1110 0000 0001 ???? 0000 0000
782         0x02, 0xb0, 0x00, 0x00,  // b0000 0010 1011 ???? ???? ???? 0000 0000
783         0x01, 0xc3, 0x00, 0x00,  // b0000 0001 1100 0011 0000 0000 0000 0000
784         0xe0, 0x00, 0xf0, 0x00   // b111? ???? ???? ???? 1111 0000 0000 0000
785     };
786 
787     sp<ABuffer> buffer = new ABuffer(188);
788     memset(buffer->data(), 0xff, buffer->size());
789     memcpy(buffer->data(), kData, sizeof(kData));
790 
791     if (++mPMTContinuityCounter == 16) {
792         mPMTContinuityCounter = 0;
793     }
794     buffer->data()[3] |= mPMTContinuityCounter;
795 
796     size_t section_length = 5 * mSources.size() + 4 + 9;
797     buffer->data()[6] |= section_length >> 8;
798     buffer->data()[7] = section_length & 0xff;
799 
800     static const unsigned kPCR_PID = 0x1e1;
801     buffer->data()[13] |= (kPCR_PID >> 8) & 0x1f;
802     buffer->data()[14] = kPCR_PID & 0xff;
803 
804     uint8_t *ptr = &buffer->data()[sizeof(kData)];
805     for (size_t i = 0; i < mSources.size(); ++i) {
806         *ptr++ = mSources.editItemAt(i)->streamType();
807 
808         const unsigned ES_PID = 0x1e0 + i + 1;
809         *ptr++ = 0xe0 | (ES_PID >> 8);
810         *ptr++ = ES_PID & 0xff;
811         *ptr++ = 0xf0;
812         *ptr++ = 0x00;
813     }
814 
815     uint32_t crc = htonl(crc32(&buffer->data()[5], 12+mSources.size()*5));
816     memcpy(&buffer->data()[17+mSources.size()*5], &crc, sizeof(crc));
817 
818     CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
819 }
820 
writeAccessUnit(int32_t sourceIndex,const sp<ABuffer> & accessUnit)821 void MPEG2TSWriter::writeAccessUnit(
822         int32_t sourceIndex, const sp<ABuffer> &accessUnit) {
823     // 0x47
824     // transport_error_indicator = b0
825     // payload_unit_start_indicator = b1
826     // transport_priority = b0
827     // PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex]
828     // transport_scrambling_control = b00
829     // adaptation_field_control = b??
830     // continuity_counter = b????
831     // -- payload follows
832     // packet_startcode_prefix = 0x000001
833     // stream_id = 0x?? (0xe0 for avc video, 0xc0 for aac audio)
834     // PES_packet_length = 0x????
835     // reserved = b10
836     // PES_scrambling_control = b00
837     // PES_priority = b0
838     // data_alignment_indicator = b1
839     // copyright = b0
840     // original_or_copy = b0
841     // PTS_DTS_flags = b10  (PTS only)
842     // ESCR_flag = b0
843     // ES_rate_flag = b0
844     // DSM_trick_mode_flag = b0
845     // additional_copy_info_flag = b0
846     // PES_CRC_flag = b0
847     // PES_extension_flag = b0
848     // PES_header_data_length = 0x05
849     // reserved = b0010 (PTS)
850     // PTS[32..30] = b???
851     // reserved = b1
852     // PTS[29..15] = b??? ???? ???? ???? (15 bits)
853     // reserved = b1
854     // PTS[14..0] = b??? ???? ???? ???? (15 bits)
855     // reserved = b1
856     // the first fragment of "buffer" follows
857 
858     sp<ABuffer> buffer = new ABuffer(188);
859     memset(buffer->data(), 0xff, buffer->size());
860 
861     const unsigned PID = 0x1e0 + sourceIndex + 1;
862 
863     const unsigned continuity_counter =
864         mSources.editItemAt(sourceIndex)->incrementContinuityCounter();
865 
866     // XXX if there are multiple streams of a kind (more than 1 audio or
867     // more than 1 video) they need distinct stream_ids.
868     const unsigned stream_id =
869         mSources.editItemAt(sourceIndex)->streamType() == 0x0f ? 0xc0 : 0xe0;
870 
871     int64_t timeUs;
872     CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
873 
874     uint32_t PTS = (timeUs * 9ll) / 100ll;
875 
876     size_t PES_packet_length = accessUnit->size() + 8;
877     bool padding = (accessUnit->size() < (188 - 18));
878 
879     if (PES_packet_length >= 65536) {
880         // This really should only happen for video.
881         CHECK_EQ(stream_id, 0xe0u);
882 
883         // It's valid to set this to 0 for video according to the specs.
884         PES_packet_length = 0;
885     }
886 
887     uint8_t *ptr = buffer->data();
888     *ptr++ = 0x47;
889     *ptr++ = 0x40 | (PID >> 8);
890     *ptr++ = PID & 0xff;
891     *ptr++ = (padding ? 0x30 : 0x10) | continuity_counter;
892     if (padding) {
893         int paddingSize = 188 - accessUnit->size() - 18;
894         *ptr++ = paddingSize - 1;
895         if (paddingSize >= 2) {
896             *ptr++ = 0x00;
897             ptr += paddingSize - 2;
898         }
899     }
900     *ptr++ = 0x00;
901     *ptr++ = 0x00;
902     *ptr++ = 0x01;
903     *ptr++ = stream_id;
904     *ptr++ = PES_packet_length >> 8;
905     *ptr++ = PES_packet_length & 0xff;
906     *ptr++ = 0x84;
907     *ptr++ = 0x80;
908     *ptr++ = 0x05;
909     *ptr++ = 0x20 | (((PTS >> 30) & 7) << 1) | 1;
910     *ptr++ = (PTS >> 22) & 0xff;
911     *ptr++ = (((PTS >> 15) & 0x7f) << 1) | 1;
912     *ptr++ = (PTS >> 7) & 0xff;
913     *ptr++ = ((PTS & 0x7f) << 1) | 1;
914 
915     size_t sizeLeft = buffer->data() + buffer->size() - ptr;
916     size_t copy = accessUnit->size();
917     if (copy > sizeLeft) {
918         copy = sizeLeft;
919     }
920 
921     memcpy(ptr, accessUnit->data(), copy);
922 
923     CHECK_EQ(internalWrite(buffer->data(), buffer->size()), buffer->size());
924 
925     size_t offset = copy;
926     while (offset < accessUnit->size()) {
927         bool lastAccessUnit = ((accessUnit->size() - offset) < 184);
928         // for subsequent fragments of "buffer":
929         // 0x47
930         // transport_error_indicator = b0
931         // payload_unit_start_indicator = b0
932         // transport_priority = b0
933         // PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex]
934         // transport_scrambling_control = b00
935         // adaptation_field_control = b??
936         // continuity_counter = b????
937         // the fragment of "buffer" follows.
938 
939         memset(buffer->data(), 0xff, buffer->size());
940 
941         const unsigned continuity_counter =
942             mSources.editItemAt(sourceIndex)->incrementContinuityCounter();
943 
944         ptr = buffer->data();
945         *ptr++ = 0x47;
946         *ptr++ = 0x00 | (PID >> 8);
947         *ptr++ = PID & 0xff;
948         *ptr++ = (lastAccessUnit ? 0x30 : 0x10) | continuity_counter;
949 
950         if (lastAccessUnit) {
951             // Pad packet using an adaptation field
952             // Adaptation header all to 0 execpt size
953             uint8_t paddingSize = (uint8_t)184 - (accessUnit->size() - offset);
954             *ptr++ = paddingSize - 1;
955             if (paddingSize >= 2) {
956                 *ptr++ = 0x00;
957                 ptr += paddingSize - 2;
958             }
959         }
960 
961         size_t sizeLeft = buffer->data() + buffer->size() - ptr;
962         size_t copy = accessUnit->size() - offset;
963         if (copy > sizeLeft) {
964             copy = sizeLeft;
965         }
966 
967         memcpy(ptr, accessUnit->data() + offset, copy);
968         CHECK_EQ(internalWrite(buffer->data(), buffer->size()),
969                  buffer->size());
970 
971         offset += copy;
972     }
973 }
974 
writeTS()975 void MPEG2TSWriter::writeTS() {
976     if (mNumTSPacketsWritten >= mNumTSPacketsBeforeMeta) {
977         writeProgramAssociationTable();
978         writeProgramMap();
979 
980         mNumTSPacketsBeforeMeta = mNumTSPacketsWritten + 2500;
981     }
982 }
983 
initCrcTable()984 void MPEG2TSWriter::initCrcTable() {
985     uint32_t poly = 0x04C11DB7;
986 
987     for (int i = 0; i < 256; i++) {
988         uint32_t crc = i << 24;
989         for (int j = 0; j < 8; j++) {
990             crc = (crc << 1) ^ ((crc & 0x80000000) ? (poly) : 0);
991         }
992         mCrcTable[i] = crc;
993     }
994 }
995 
996 /**
997  * Compute CRC32 checksum for buffer starting at offset start and for length
998  * bytes.
999  */
crc32(const uint8_t * p_start,size_t length)1000 uint32_t MPEG2TSWriter::crc32(const uint8_t *p_start, size_t length) {
1001     uint32_t crc = 0xFFFFFFFF;
1002     const uint8_t *p;
1003 
1004     for (p = p_start; p < p_start + length; p++) {
1005         crc = (crc << 8) ^ mCrcTable[((crc >> 24) ^ *p) & 0xFF];
1006     }
1007 
1008     return crc;
1009 }
1010 
internalWrite(const void * data,size_t size)1011 ssize_t MPEG2TSWriter::internalWrite(const void *data, size_t size) {
1012     if (mFile != NULL) {
1013         return fwrite(data, 1, size, mFile);
1014     }
1015 
1016     return (*mWriteFunc)(mWriteCookie, data, size);
1017 }
1018 
1019 }  // namespace android
1020 
1021