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