MPEG4Writer.cpp revision be83c9e8c71ce16c0d0e9ed9df525510a49a541b
1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "MPEG4Writer"
19#include <utils/Log.h>
20
21#include <arpa/inet.h>
22
23#include <ctype.h>
24#include <pthread.h>
25
26#include <media/stagefright/MPEG4Writer.h>
27#include <media/stagefright/MediaBuffer.h>
28#include <media/stagefright/MetaData.h>
29#include <media/stagefright/MediaDebug.h>
30#include <media/stagefright/MediaDefs.h>
31#include <media/stagefright/MediaErrors.h>
32#include <media/stagefright/MediaSource.h>
33#include <media/stagefright/Utils.h>
34
35namespace android {
36
37class MPEG4Writer::Track {
38public:
39    Track(MPEG4Writer *owner, const sp<MediaSource> &source);
40    ~Track();
41
42    status_t start();
43    void stop();
44    bool reachedEOS();
45
46    int64_t getDurationUs() const;
47    void writeTrackHeader(int32_t trackID);
48
49private:
50    MPEG4Writer *mOwner;
51    sp<MetaData> mMeta;
52    sp<MediaSource> mSource;
53    volatile bool mDone;
54    int64_t mMaxTimeStampUs;
55
56    pthread_t mThread;
57
58    struct SampleInfo {
59        size_t size;
60        int64_t timestamp;
61    };
62    List<SampleInfo>    mSampleInfos;
63    bool                mSamplesHaveSameSize;
64
65    List<MediaBuffer *> mChunkSamples;
66    List<off_t>         mChunkOffsets;
67
68    struct StscTableEntry {
69
70        StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id)
71            : firstChunk(chunk),
72              samplesPerChunk(samples),
73              sampleDescriptionId(id) {}
74
75        uint32_t firstChunk;
76        uint32_t samplesPerChunk;
77        uint32_t sampleDescriptionId;
78    };
79    List<StscTableEntry> mStscTableEntries;
80
81    List<int32_t> mStssTableEntries;
82
83    struct SttsTableEntry {
84
85        SttsTableEntry(uint32_t count, uint32_t duration)
86            : sampleCount(count), sampleDuration(duration) {}
87
88        uint32_t sampleCount;
89        uint32_t sampleDuration;
90    };
91    List<SttsTableEntry> mSttsTableEntries;
92
93    void *mCodecSpecificData;
94    size_t mCodecSpecificDataSize;
95    bool mGotAllCodecSpecificData;
96
97    bool mReachedEOS;
98
99    static void *ThreadWrapper(void *me);
100    void threadEntry();
101
102    status_t makeAVCCodecSpecificData(
103            const uint8_t *data, size_t size);
104    void writeOneChunk(bool isAvc);
105
106    Track(const Track &);
107    Track &operator=(const Track &);
108};
109
110#define USE_NALLEN_FOUR         1
111
112MPEG4Writer::MPEG4Writer(const char *filename)
113    : mFile(fopen(filename, "wb")),
114      mOffset(0),
115      mMdatOffset(0),
116      mInterleaveDurationUs(500000) {
117    CHECK(mFile != NULL);
118}
119
120MPEG4Writer::MPEG4Writer(int fd)
121    : mFile(fdopen(fd, "wb")),
122      mOffset(0),
123      mMdatOffset(0),
124      mInterleaveDurationUs(500000) {
125    CHECK(mFile != NULL);
126}
127
128MPEG4Writer::~MPEG4Writer() {
129    stop();
130
131    for (List<Track *>::iterator it = mTracks.begin();
132         it != mTracks.end(); ++it) {
133        delete *it;
134    }
135    mTracks.clear();
136}
137
138status_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
139    Track *track = new Track(this, source);
140    mTracks.push_back(track);
141
142    return OK;
143}
144
145status_t MPEG4Writer::start() {
146    if (mFile == NULL) {
147        return UNKNOWN_ERROR;
148    }
149
150    beginBox("ftyp");
151      writeFourcc("isom");
152      writeInt32(0);
153      writeFourcc("isom");
154    endBox();
155
156    mMdatOffset = mOffset;
157    write("\x00\x00\x00\x01mdat????????", 16);
158
159    for (List<Track *>::iterator it = mTracks.begin();
160         it != mTracks.end(); ++it) {
161        status_t err = (*it)->start();
162
163        if (err != OK) {
164            for (List<Track *>::iterator it2 = mTracks.begin();
165                 it2 != it; ++it2) {
166                (*it2)->stop();
167            }
168
169            return err;
170        }
171    }
172
173    return OK;
174}
175
176void MPEG4Writer::stop() {
177    if (mFile == NULL) {
178        return;
179    }
180
181    int64_t max_duration = 0;
182    for (List<Track *>::iterator it = mTracks.begin();
183         it != mTracks.end(); ++it) {
184        (*it)->stop();
185
186        int64_t duration = (*it)->getDurationUs();
187        if (duration > max_duration) {
188            max_duration = duration;
189        }
190    }
191
192    // Fix up the size of the 'mdat' chunk.
193    fseek(mFile, mMdatOffset + 8, SEEK_SET);
194    int64_t size = mOffset - mMdatOffset;
195    size = hton64(size);
196    fwrite(&size, 1, 8, mFile);
197    fseek(mFile, mOffset, SEEK_SET);
198
199    time_t now = time(NULL);
200
201    beginBox("moov");
202
203      beginBox("mvhd");
204        writeInt32(0);             // version=0, flags=0
205        writeInt32(now);           // creation time
206        writeInt32(now);           // modification time
207        writeInt32(1000);          // timescale
208        writeInt32(max_duration / 1000);
209        writeInt32(0x10000);       // rate
210        writeInt16(0x100);         // volume
211        writeInt16(0);             // reserved
212        writeInt32(0);             // reserved
213        writeInt32(0);             // reserved
214        writeInt32(0x10000);       // matrix
215        writeInt32(0);
216        writeInt32(0);
217        writeInt32(0);
218        writeInt32(0x10000);
219        writeInt32(0);
220        writeInt32(0);
221        writeInt32(0);
222        writeInt32(0x40000000);
223        writeInt32(0);             // predefined
224        writeInt32(0);             // predefined
225        writeInt32(0);             // predefined
226        writeInt32(0);             // predefined
227        writeInt32(0);             // predefined
228        writeInt32(0);             // predefined
229        writeInt32(mTracks.size() + 1);  // nextTrackID
230      endBox();  // mvhd
231
232      int32_t id = 1;
233      for (List<Track *>::iterator it = mTracks.begin();
234           it != mTracks.end(); ++it, ++id) {
235          (*it)->writeTrackHeader(id);
236      }
237    endBox();  // moov
238
239    CHECK(mBoxes.empty());
240
241    fclose(mFile);
242    mFile = NULL;
243}
244
245status_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
246    mInterleaveDurationUs = durationUs;
247    return OK;
248}
249
250void MPEG4Writer::lock() {
251    mLock.lock();
252}
253
254void MPEG4Writer::unlock() {
255    mLock.unlock();
256}
257
258off_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
259    off_t old_offset = mOffset;
260
261    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
262           1, buffer->range_length(), mFile);
263
264    mOffset += buffer->range_length();
265
266    return old_offset;
267}
268
269static void StripStartcode(MediaBuffer *buffer) {
270    if (buffer->range_length() < 4) {
271        return;
272    }
273
274    const uint8_t *ptr =
275        (const uint8_t *)buffer->data() + buffer->range_offset();
276
277    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
278        buffer->set_range(
279                buffer->range_offset() + 4, buffer->range_length() - 4);
280    }
281}
282
283off_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
284    StripStartcode(buffer);
285
286    off_t old_offset = mOffset;
287
288    size_t length = buffer->range_length();
289
290#if USE_NALLEN_FOUR
291    uint8_t x = length >> 24;
292    fwrite(&x, 1, 1, mFile);
293    x = (length >> 16) & 0xff;
294    fwrite(&x, 1, 1, mFile);
295    x = (length >> 8) & 0xff;
296    fwrite(&x, 1, 1, mFile);
297    x = length & 0xff;
298    fwrite(&x, 1, 1, mFile);
299#else
300    CHECK(length < 65536);
301
302    uint8_t x = length >> 8;
303    fwrite(&x, 1, 1, mFile);
304    x = length & 0xff;
305    fwrite(&x, 1, 1, mFile);
306#endif
307
308    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
309           1, length, mFile);
310
311#if USE_NALLEN_FOUR
312    mOffset += length + 4;
313#else
314    mOffset += length + 2;
315#endif
316
317    return old_offset;
318}
319
320void MPEG4Writer::beginBox(const char *fourcc) {
321    CHECK_EQ(strlen(fourcc), 4);
322
323    mBoxes.push_back(mOffset);
324
325    writeInt32(0);
326    writeFourcc(fourcc);
327}
328
329void MPEG4Writer::endBox() {
330    CHECK(!mBoxes.empty());
331
332    off_t offset = *--mBoxes.end();
333    mBoxes.erase(--mBoxes.end());
334
335    fseek(mFile, offset, SEEK_SET);
336    writeInt32(mOffset - offset);
337    mOffset -= 4;
338    fseek(mFile, mOffset, SEEK_SET);
339}
340
341void MPEG4Writer::writeInt8(int8_t x) {
342    fwrite(&x, 1, 1, mFile);
343    ++mOffset;
344}
345
346void MPEG4Writer::writeInt16(int16_t x) {
347    x = htons(x);
348    fwrite(&x, 1, 2, mFile);
349    mOffset += 2;
350}
351
352void MPEG4Writer::writeInt32(int32_t x) {
353    x = htonl(x);
354    fwrite(&x, 1, 4, mFile);
355    mOffset += 4;
356}
357
358void MPEG4Writer::writeInt64(int64_t x) {
359    x = hton64(x);
360    fwrite(&x, 1, 8, mFile);
361    mOffset += 8;
362}
363
364void MPEG4Writer::writeCString(const char *s) {
365    size_t n = strlen(s);
366
367    fwrite(s, 1, n + 1, mFile);
368    mOffset += n + 1;
369}
370
371void MPEG4Writer::writeFourcc(const char *s) {
372    CHECK_EQ(strlen(s), 4);
373    fwrite(s, 1, 4, mFile);
374    mOffset += 4;
375}
376
377void MPEG4Writer::write(const void *data, size_t size) {
378    fwrite(data, 1, size, mFile);
379    mOffset += size;
380}
381
382bool MPEG4Writer::reachedEOS() {
383    bool allDone = true;
384    for (List<Track *>::iterator it = mTracks.begin();
385         it != mTracks.end(); ++it) {
386        if (!(*it)->reachedEOS()) {
387            allDone = false;
388            break;
389        }
390    }
391
392    return allDone;
393}
394
395////////////////////////////////////////////////////////////////////////////////
396
397MPEG4Writer::Track::Track(
398        MPEG4Writer *owner, const sp<MediaSource> &source)
399    : mOwner(owner),
400      mMeta(source->getFormat()),
401      mSource(source),
402      mDone(false),
403      mMaxTimeStampUs(0),
404      mSamplesHaveSameSize(true),
405      mCodecSpecificData(NULL),
406      mCodecSpecificDataSize(0),
407      mGotAllCodecSpecificData(false),
408      mReachedEOS(false) {
409}
410
411MPEG4Writer::Track::~Track() {
412    stop();
413
414    if (mCodecSpecificData != NULL) {
415        free(mCodecSpecificData);
416        mCodecSpecificData = NULL;
417    }
418}
419
420status_t MPEG4Writer::Track::start() {
421    status_t err = mSource->start();
422
423    if (err != OK) {
424        mDone = mReachedEOS = true;
425        return err;
426    }
427
428    pthread_attr_t attr;
429    pthread_attr_init(&attr);
430    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
431
432    mDone = false;
433    mMaxTimeStampUs = 0;
434    mReachedEOS = false;
435
436    pthread_create(&mThread, &attr, ThreadWrapper, this);
437    pthread_attr_destroy(&attr);
438
439    return OK;
440}
441
442void MPEG4Writer::Track::stop() {
443    if (mDone) {
444        return;
445    }
446
447    mDone = true;
448
449    void *dummy;
450    pthread_join(mThread, &dummy);
451
452    mSource->stop();
453}
454
455bool MPEG4Writer::Track::reachedEOS() {
456    return mReachedEOS;
457}
458
459// static
460void *MPEG4Writer::Track::ThreadWrapper(void *me) {
461    Track *track = static_cast<Track *>(me);
462
463    track->threadEntry();
464
465    return NULL;
466}
467
468#include <ctype.h>
469static void hexdump(const void *_data, size_t size) {
470    const uint8_t *data = (const uint8_t *)_data;
471    size_t offset = 0;
472    while (offset < size) {
473        printf("0x%04x  ", offset);
474
475        size_t n = size - offset;
476        if (n > 16) {
477            n = 16;
478        }
479
480        for (size_t i = 0; i < 16; ++i) {
481            if (i == 8) {
482                printf(" ");
483            }
484
485            if (offset + i < size) {
486                printf("%02x ", data[offset + i]);
487            } else {
488                printf("   ");
489            }
490        }
491
492        printf(" ");
493
494        for (size_t i = 0; i < n; ++i) {
495            if (isprint(data[offset + i])) {
496                printf("%c", data[offset + i]);
497            } else {
498                printf(".");
499            }
500        }
501
502        printf("\n");
503
504        offset += 16;
505    }
506}
507
508
509status_t MPEG4Writer::Track::makeAVCCodecSpecificData(
510        const uint8_t *data, size_t size) {
511    // hexdump(data, size);
512
513    if (mCodecSpecificData != NULL) {
514        LOGE("Already have codec specific data");
515        return ERROR_MALFORMED;
516    }
517
518    if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) {
519        LOGE("Must start with a start code");
520        return ERROR_MALFORMED;
521    }
522
523    size_t picParamOffset = 4;
524    while (picParamOffset + 3 < size
525            && memcmp("\x00\x00\x00\x01", &data[picParamOffset], 4)) {
526        ++picParamOffset;
527    }
528
529    if (picParamOffset + 3 >= size) {
530        LOGE("Could not find start-code for pictureParameterSet");
531        return ERROR_MALFORMED;
532    }
533
534    size_t seqParamSetLength = picParamOffset - 4;
535    size_t picParamSetLength = size - picParamOffset - 4;
536
537    mCodecSpecificDataSize =
538        6 + 1 + seqParamSetLength + 2 + picParamSetLength + 2;
539
540    mCodecSpecificData = malloc(mCodecSpecificDataSize);
541    uint8_t *header = (uint8_t *)mCodecSpecificData;
542    header[0] = 1;
543    header[1] = 0x42;  // profile
544    header[2] = 0x80;
545    header[3] = 0x1e;  // level
546
547#if USE_NALLEN_FOUR
548    header[4] = 0xfc | 3;  // length size == 4 bytes
549#else
550    header[4] = 0xfc | 1;  // length size == 2 bytes
551#endif
552
553    header[5] = 0xe0 | 1;
554    header[6] = seqParamSetLength >> 8;
555    header[7] = seqParamSetLength & 0xff;
556    memcpy(&header[8], &data[4], seqParamSetLength);
557    header += 8 + seqParamSetLength;
558    header[0] = 1;
559    header[1] = picParamSetLength >> 8;
560    header[2] = picParamSetLength & 0xff;
561    memcpy(&header[3], &data[picParamOffset + 4], picParamSetLength);
562
563    return OK;
564}
565
566void MPEG4Writer::Track::threadEntry() {
567    sp<MetaData> meta = mSource->getFormat();
568    const char *mime;
569    meta->findCString(kKeyMIMEType, &mime);
570    bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
571                    !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
572    bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
573    int32_t count = 0;
574    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
575    int64_t chunkTimestampUs = 0;
576    int32_t nChunks = 0;
577    int32_t nZeroLengthFrames = 0;
578    int64_t lastTimestamp = 0;  // Timestamp of the previous sample
579    int64_t lastDuration = 0;   // Time spacing between the previous two samples
580    int32_t sampleCount = 1;    // Sample count in the current stts table entry
581    uint32_t previousSampleSize = 0;  // Size of the previous sample
582
583    MediaBuffer *buffer;
584    while (!mDone && mSource->read(&buffer) == OK) {
585        if (buffer->range_length() == 0) {
586            buffer->release();
587            buffer = NULL;
588            ++nZeroLengthFrames;
589            continue;
590        }
591
592        ++count;
593
594        int32_t isCodecConfig;
595        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
596                && isCodecConfig) {
597            CHECK(!mGotAllCodecSpecificData);
598
599            if (is_avc) {
600                status_t err = makeAVCCodecSpecificData(
601                        (const uint8_t *)buffer->data()
602                            + buffer->range_offset(),
603                        buffer->range_length());
604                CHECK_EQ(OK, err);
605            } else if (is_mpeg4) {
606                mCodecSpecificDataSize = buffer->range_length();
607                mCodecSpecificData = malloc(mCodecSpecificDataSize);
608                memcpy(mCodecSpecificData,
609                        (const uint8_t *)buffer->data()
610                            + buffer->range_offset(),
611                       buffer->range_length());
612            }
613
614            buffer->release();
615            buffer = NULL;
616
617            mGotAllCodecSpecificData = true;
618            continue;
619        } else if (!mGotAllCodecSpecificData &&
620                count == 1 && is_mpeg4 && mCodecSpecificData == NULL) {
621            // The TI mpeg4 encoder does not properly set the
622            // codec-specific-data flag.
623
624            const uint8_t *data =
625                (const uint8_t *)buffer->data() + buffer->range_offset();
626
627            const size_t size = buffer->range_length();
628
629            size_t offset = 0;
630            while (offset + 3 < size) {
631                if (data[offset] == 0x00 && data[offset + 1] == 0x00
632                    && data[offset + 2] == 0x01 && data[offset + 3] == 0xb6) {
633                    break;
634                }
635
636                ++offset;
637            }
638
639            // CHECK(offset + 3 < size);
640            if (offset + 3 >= size) {
641                // XXX assume the entire first chunk of data is the codec specific
642                // data.
643                offset = size;
644            }
645
646            mCodecSpecificDataSize = offset;
647            mCodecSpecificData = malloc(offset);
648            memcpy(mCodecSpecificData, data, offset);
649
650            buffer->set_range(buffer->range_offset() + offset, size - offset);
651
652            if (size == offset) {
653                buffer->release();
654                buffer = NULL;
655
656                continue;
657            }
658
659            mGotAllCodecSpecificData = true;
660        } else if (!mGotAllCodecSpecificData && is_avc && count < 3) {
661            // The TI video encoder does not flag codec specific data
662            // as such and also splits up SPS and PPS across two buffers.
663
664            const uint8_t *data =
665                (const uint8_t *)buffer->data() + buffer->range_offset();
666
667            size_t size = buffer->range_length();
668
669            CHECK(count == 2 || mCodecSpecificData == NULL);
670
671            size_t offset = mCodecSpecificDataSize;
672            mCodecSpecificDataSize += size + 4;
673            mCodecSpecificData =
674                realloc(mCodecSpecificData, mCodecSpecificDataSize);
675
676            memcpy((uint8_t *)mCodecSpecificData + offset,
677                   "\x00\x00\x00\x01", 4);
678
679            memcpy((uint8_t *)mCodecSpecificData + offset + 4, data, size);
680
681            buffer->release();
682            buffer = NULL;
683
684            if (count == 2) {
685                void *tmp = mCodecSpecificData;
686                size = mCodecSpecificDataSize;
687                mCodecSpecificData = NULL;
688                mCodecSpecificDataSize = 0;
689
690                status_t err = makeAVCCodecSpecificData(
691                        (const uint8_t *)tmp, size);
692                free(tmp);
693                tmp = NULL;
694                CHECK_EQ(OK, err);
695
696                mGotAllCodecSpecificData = true;
697            }
698
699            continue;
700        }
701
702        SampleInfo info;
703        info.size = is_avc
704#if USE_NALLEN_FOUR
705                ? buffer->range_length() + 4
706#else
707                ? buffer->range_length() + 2
708#endif
709                : buffer->range_length();
710
711        bool is_audio = !strncasecmp(mime, "audio/", 6);
712
713        int64_t timestampUs;
714        CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
715
716        if (timestampUs > mMaxTimeStampUs) {
717            mMaxTimeStampUs = timestampUs;
718        }
719
720        // Our timestamp is in ms.
721        info.timestamp = (timestampUs + 500) / 1000;
722        mSampleInfos.push_back(info);
723        if (mSampleInfos.size() > 2) {
724            if (lastDuration != info.timestamp - lastTimestamp) {
725                SttsTableEntry sttsEntry(sampleCount, lastDuration);
726                mSttsTableEntries.push_back(sttsEntry);
727                sampleCount = 1;
728            } else {
729                ++sampleCount;
730            }
731        }
732        if (mSamplesHaveSameSize) {
733            if (mSampleInfos.size() >= 2 && previousSampleSize != info.size) {
734                mSamplesHaveSameSize = false;
735            }
736            previousSampleSize = info.size;
737        }
738        lastDuration = info.timestamp - lastTimestamp;
739        lastTimestamp = info.timestamp;
740
741////////////////////////////////////////////////////////////////////////////////
742        // Make a deep copy of the MediaBuffer less Metadata
743        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
744        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
745                buffer->range_length());
746        copy->set_range(0, buffer->range_length());
747
748        mChunkSamples.push_back(copy);
749        if (interleaveDurationUs == 0) {
750            StscTableEntry stscEntry(++nChunks, 1, 1);
751            mStscTableEntries.push_back(stscEntry);
752            writeOneChunk(is_avc);
753        } else {
754            if (chunkTimestampUs == 0) {
755                chunkTimestampUs = timestampUs;
756            } else {
757                if (timestampUs - chunkTimestampUs > interleaveDurationUs) {
758                    ++nChunks;
759                    if (nChunks == 1 ||  // First chunk
760                        (--(mStscTableEntries.end()))->samplesPerChunk !=
761                         mChunkSamples.size()) {
762                        StscTableEntry stscEntry(nChunks,
763                                mChunkSamples.size(), 1);
764                        mStscTableEntries.push_back(stscEntry);
765                    }
766                    writeOneChunk(is_avc);
767                    chunkTimestampUs = timestampUs;
768                }
769            }
770        }
771
772        int32_t isSync = false;
773        if (buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync) &&
774            isSync != 0) {
775            mStssTableEntries.push_back(mSampleInfos.size());
776        }
777
778        buffer->release();
779        buffer = NULL;
780    }
781
782    CHECK(!mSampleInfos.empty());
783
784    // Last chunk
785    if (!mChunkSamples.empty()) {
786        ++nChunks;
787        StscTableEntry stscEntry(nChunks, mChunkSamples.size(), 1);
788        mStscTableEntries.push_back(stscEntry);
789        writeOneChunk(is_avc);
790    }
791
792    // We don't really know how long the last frame lasts, since
793    // there is no frame time after it, just repeat the previous
794    // frame's duration.
795    if (mSampleInfos.size() == 1) {
796        lastDuration = 0;  // A single sample's duration
797    } else {
798        ++sampleCount;  // Count for the last sample
799    }
800    SttsTableEntry sttsEntry(sampleCount, lastDuration);
801    mSttsTableEntries.push_back(sttsEntry);
802    mReachedEOS = true;
803    LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames",
804            count, nZeroLengthFrames, mSampleInfos.size());
805}
806
807void MPEG4Writer::Track::writeOneChunk(bool isAvc) {
808    mOwner->lock();
809    for (List<MediaBuffer *>::iterator it = mChunkSamples.begin();
810         it != mChunkSamples.end(); ++it) {
811        off_t offset = isAvc? mOwner->addLengthPrefixedSample_l(*it)
812                            : mOwner->addSample_l(*it);
813        if (it == mChunkSamples.begin()) {
814            mChunkOffsets.push_back(offset);
815        }
816    }
817    mOwner->unlock();
818    while (!mChunkSamples.empty()) {
819        List<MediaBuffer *>::iterator it = mChunkSamples.begin();
820        (*it)->release();
821        (*it) = NULL;
822        mChunkSamples.erase(it);
823    }
824    mChunkSamples.clear();
825}
826
827int64_t MPEG4Writer::Track::getDurationUs() const {
828    return mMaxTimeStampUs;
829}
830
831void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
832    const char *mime;
833    bool success = mMeta->findCString(kKeyMIMEType, &mime);
834    CHECK(success);
835
836    bool is_audio = !strncasecmp(mime, "audio/", 6);
837
838    time_t now = time(NULL);
839
840    mOwner->beginBox("trak");
841
842      mOwner->beginBox("tkhd");
843        mOwner->writeInt32(0);             // version=0, flags=0
844        mOwner->writeInt32(now);           // creation time
845        mOwner->writeInt32(now);           // modification time
846        mOwner->writeInt32(trackID);
847        mOwner->writeInt32(0);             // reserved
848        mOwner->writeInt32(getDurationUs() / 1000);
849        mOwner->writeInt32(0);             // reserved
850        mOwner->writeInt32(0);             // reserved
851        mOwner->writeInt16(0);             // layer
852        mOwner->writeInt16(0);             // alternate group
853        mOwner->writeInt16(is_audio ? 0x100 : 0);  // volume
854        mOwner->writeInt16(0);             // reserved
855
856        mOwner->writeInt32(0x10000);       // matrix
857        mOwner->writeInt32(0);
858        mOwner->writeInt32(0);
859        mOwner->writeInt32(0);
860        mOwner->writeInt32(0x10000);
861        mOwner->writeInt32(0);
862        mOwner->writeInt32(0);
863        mOwner->writeInt32(0);
864        mOwner->writeInt32(0x40000000);
865
866        if (is_audio) {
867            mOwner->writeInt32(0);
868            mOwner->writeInt32(0);
869        } else {
870            int32_t width, height;
871            bool success = mMeta->findInt32(kKeyWidth, &width);
872            success = success && mMeta->findInt32(kKeyHeight, &height);
873            CHECK(success);
874
875            mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
876            mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
877        }
878      mOwner->endBox();  // tkhd
879
880      mOwner->beginBox("mdia");
881
882        mOwner->beginBox("mdhd");
883          mOwner->writeInt32(0);             // version=0, flags=0
884          mOwner->writeInt32(now);           // creation time
885          mOwner->writeInt32(now);           // modification time
886          mOwner->writeInt32(1000);          // timescale
887          mOwner->writeInt32(getDurationUs() / 1000);
888          mOwner->writeInt16(0);             // language code XXX
889          mOwner->writeInt16(0);             // predefined
890        mOwner->endBox();
891
892        mOwner->beginBox("hdlr");
893          mOwner->writeInt32(0);             // version=0, flags=0
894          mOwner->writeInt32(0);             // component type: should be mhlr
895          mOwner->writeFourcc(is_audio ? "soun" : "vide");  // component subtype
896          mOwner->writeInt32(0);             // reserved
897          mOwner->writeInt32(0);             // reserved
898          mOwner->writeInt32(0);             // reserved
899          mOwner->writeCString("SoundHandler");          // name
900        mOwner->endBox();
901
902        mOwner->beginBox("minf");
903          if (is_audio) {
904              mOwner->beginBox("smhd");
905              mOwner->writeInt32(0);           // version=0, flags=0
906              mOwner->writeInt16(0);           // balance
907              mOwner->writeInt16(0);           // reserved
908              mOwner->endBox();
909          } else {
910              mOwner->beginBox("vmhd");
911              mOwner->writeInt32(0x00000001);  // version=0, flags=1
912              mOwner->writeInt16(0);           // graphics mode
913              mOwner->writeInt16(0);           // opcolor
914              mOwner->writeInt16(0);
915              mOwner->writeInt16(0);
916              mOwner->endBox();
917          }
918
919          mOwner->beginBox("dinf");
920            mOwner->beginBox("dref");
921              mOwner->writeInt32(0);  // version=0, flags=0
922              mOwner->writeInt32(1);
923              mOwner->beginBox("url ");
924                mOwner->writeInt32(1);  // version=0, flags=1
925              mOwner->endBox();  // url
926            mOwner->endBox();  // dref
927          mOwner->endBox();  // dinf
928
929       mOwner->endBox();  // minf
930
931        mOwner->beginBox("stbl");
932
933          mOwner->beginBox("stsd");
934            mOwner->writeInt32(0);               // version=0, flags=0
935            mOwner->writeInt32(1);               // entry count
936            if (is_audio) {
937                const char *fourcc = NULL;
938                if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime)) {
939                    fourcc = "samr";
940                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
941                    fourcc = "sawb";
942                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
943                    fourcc = "mp4a";
944                } else {
945                    LOGE("Unknown mime type '%s'.", mime);
946                    CHECK(!"should not be here, unknown mime type.");
947                }
948
949                mOwner->beginBox(fourcc);          // audio format
950                  mOwner->writeInt32(0);           // reserved
951                  mOwner->writeInt16(0);           // reserved
952                  mOwner->writeInt16(0x1);         // data ref index
953                  mOwner->writeInt32(0);           // reserved
954                  mOwner->writeInt32(0);           // reserved
955                  int32_t nChannels;
956                  CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
957                  mOwner->writeInt16(nChannels);   // channel count
958                  mOwner->writeInt16(16);          // sample size
959                  mOwner->writeInt16(0);           // predefined
960                  mOwner->writeInt16(0);           // reserved
961
962                  int32_t samplerate;
963                  bool success = mMeta->findInt32(kKeySampleRate, &samplerate);
964                  CHECK(success);
965
966                  mOwner->writeInt32(samplerate << 16);
967                  if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
968                    mOwner->beginBox("esds");
969
970                        mOwner->writeInt32(0);     // version=0, flags=0
971                        mOwner->writeInt8(0x03);   // ES_DescrTag
972                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
973                        mOwner->writeInt16(0x0000);// ES_ID
974                        mOwner->writeInt8(0x00);
975
976                        mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
977                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
978                        mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
979                        mOwner->writeInt8(0x15);   // streamType AudioStream
980
981                        mOwner->writeInt16(0x03);  // XXX
982                        mOwner->writeInt8(0x00);   // buffer size 24-bit
983                        mOwner->writeInt32(96000); // max bit rate
984                        mOwner->writeInt32(96000); // avg bit rate
985
986                        mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
987                        mOwner->writeInt8(mCodecSpecificDataSize);
988                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
989
990                        static const uint8_t kData2[] = {
991                            0x06,  // SLConfigDescriptorTag
992                            0x01,
993                            0x02
994                        };
995                        mOwner->write(kData2, sizeof(kData2));
996
997                    mOwner->endBox();  // esds
998                  }
999                mOwner->endBox();
1000            } else {
1001                if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
1002                    mOwner->beginBox("mp4v");
1003                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
1004                    mOwner->beginBox("s263");
1005                } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
1006                    mOwner->beginBox("avc1");
1007                } else {
1008                    LOGE("Unknown mime type '%s'.", mime);
1009                    CHECK(!"should not be here, unknown mime type.");
1010                }
1011
1012                  mOwner->writeInt32(0);           // reserved
1013                  mOwner->writeInt16(0);           // reserved
1014                  mOwner->writeInt16(0);           // data ref index
1015                  mOwner->writeInt16(0);           // predefined
1016                  mOwner->writeInt16(0);           // reserved
1017                  mOwner->writeInt32(0);           // predefined
1018                  mOwner->writeInt32(0);           // predefined
1019                  mOwner->writeInt32(0);           // predefined
1020
1021                  int32_t width, height;
1022                  bool success = mMeta->findInt32(kKeyWidth, &width);
1023                  success = success && mMeta->findInt32(kKeyHeight, &height);
1024                  CHECK(success);
1025
1026                  mOwner->writeInt16(width);
1027                  mOwner->writeInt16(height);
1028                  mOwner->writeInt32(0x480000);    // horiz resolution
1029                  mOwner->writeInt32(0x480000);    // vert resolution
1030                  mOwner->writeInt32(0);           // reserved
1031                  mOwner->writeInt16(1);           // frame count
1032                  mOwner->write("                                ", 32);
1033                  mOwner->writeInt16(0x18);        // depth
1034                  mOwner->writeInt16(-1);          // predefined
1035
1036                  CHECK(23 + mCodecSpecificDataSize < 128);
1037
1038                  if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
1039                      mOwner->beginBox("esds");
1040
1041                        mOwner->writeInt32(0);           // version=0, flags=0
1042
1043                        mOwner->writeInt8(0x03);  // ES_DescrTag
1044                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
1045                        mOwner->writeInt16(0x0000);  // ES_ID
1046                        mOwner->writeInt8(0x1f);
1047
1048                        mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
1049                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
1050                        mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
1051                        mOwner->writeInt8(0x11);  // streamType VisualStream
1052
1053                        static const uint8_t kData[] = {
1054                            0x01, 0x77, 0x00,
1055                            0x00, 0x03, 0xe8, 0x00,
1056                            0x00, 0x03, 0xe8, 0x00
1057                        };
1058                        mOwner->write(kData, sizeof(kData));
1059
1060                        mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
1061
1062                        mOwner->writeInt8(mCodecSpecificDataSize);
1063                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
1064
1065                        static const uint8_t kData2[] = {
1066                            0x06,  // SLConfigDescriptorTag
1067                            0x01,
1068                            0x02
1069                        };
1070                        mOwner->write(kData2, sizeof(kData2));
1071
1072                      mOwner->endBox();  // esds
1073                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
1074                      mOwner->beginBox("d263");
1075
1076                          mOwner->writeInt32(0);  // vendor
1077                          mOwner->writeInt8(0);   // decoder version
1078                          mOwner->writeInt8(10);  // level: 10
1079                          mOwner->writeInt8(0);   // profile: 0
1080
1081                      mOwner->endBox();  // d263
1082                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
1083                      mOwner->beginBox("avcC");
1084                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
1085                      mOwner->endBox();  // avcC
1086                  }
1087
1088                mOwner->endBox();  // mp4v, s263 or avc1
1089            }
1090          mOwner->endBox();  // stsd
1091
1092          mOwner->beginBox("stts");
1093            mOwner->writeInt32(0);  // version=0, flags=0
1094            mOwner->writeInt32(mSttsTableEntries.size());
1095            for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
1096                 it != mSttsTableEntries.end(); ++it) {
1097                mOwner->writeInt32(it->sampleCount);
1098                mOwner->writeInt32(it->sampleDuration);
1099            }
1100          mOwner->endBox();  // stts
1101
1102          if (!is_audio) {
1103            mOwner->beginBox("stss");
1104              mOwner->writeInt32(0);  // version=0, flags=0
1105              mOwner->writeInt32(mStssTableEntries.size());  // number of sync frames
1106              for (List<int32_t>::iterator it = mStssTableEntries.begin();
1107                   it != mStssTableEntries.end(); ++it) {
1108                  mOwner->writeInt32(*it);
1109              }
1110            mOwner->endBox();  // stss
1111          }
1112
1113          mOwner->beginBox("stsz");
1114            mOwner->writeInt32(0);  // version=0, flags=0
1115            if (mSamplesHaveSameSize) {
1116                List<SampleInfo>::iterator it = mSampleInfos.begin();
1117                mOwner->writeInt32(it->size);  // default sample size
1118            } else {
1119                mOwner->writeInt32(0);
1120            }
1121            mOwner->writeInt32(mSampleInfos.size());
1122            if (!mSamplesHaveSameSize) {
1123                for (List<SampleInfo>::iterator it = mSampleInfos.begin();
1124                     it != mSampleInfos.end(); ++it) {
1125                    mOwner->writeInt32((*it).size);
1126                }
1127            }
1128          mOwner->endBox();  // stsz
1129
1130          mOwner->beginBox("stsc");
1131            mOwner->writeInt32(0);  // version=0, flags=0
1132            mOwner->writeInt32(mStscTableEntries.size());
1133            for (List<StscTableEntry>::iterator it = mStscTableEntries.begin();
1134                 it != mStscTableEntries.end(); ++it) {
1135                mOwner->writeInt32(it->firstChunk);
1136                mOwner->writeInt32(it->samplesPerChunk);
1137                mOwner->writeInt32(it->sampleDescriptionId);
1138            }
1139          mOwner->endBox();  // stsc
1140
1141          mOwner->beginBox("co64");
1142            mOwner->writeInt32(0);  // version=0, flags=0
1143            mOwner->writeInt32(mChunkOffsets.size());
1144            for (List<off_t>::iterator it = mChunkOffsets.begin();
1145                 it != mChunkOffsets.end(); ++it) {
1146                mOwner->writeInt64((*it));
1147            }
1148          mOwner->endBox();  // co64
1149
1150        mOwner->endBox();  // stbl
1151      mOwner->endBox();  // mdia
1152    mOwner->endBox();  // trak
1153}
1154
1155}  // namespace android
1156