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