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