Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3a29ea87 authored by ztenghui's avatar ztenghui Committed by Android (Google) Code Review
Browse files

Merge "Add the presentation rotation support" into jb-mr2-dev

parents aab193b1 11287471
Loading
Loading
Loading
Loading
+12 −3
Original line number Original line Diff line number Diff line
@@ -55,7 +55,8 @@ static int muxing(
        const char *outputFileName,
        const char *outputFileName,
        bool enableTrim,
        bool enableTrim,
        int trimStartTimeMs,
        int trimStartTimeMs,
        int trimEndTimeMs) {
        int trimEndTimeMs,
        int rotationDegrees) {
    sp<NuMediaExtractor> extractor = new NuMediaExtractor;
    sp<NuMediaExtractor> extractor = new NuMediaExtractor;
    if (extractor->setDataSource(path) != OK) {
    if (extractor->setDataSource(path) != OK) {
        fprintf(stderr, "unable to instantiate extractor. %s\n", path);
        fprintf(stderr, "unable to instantiate extractor. %s\n", path);
@@ -141,6 +142,7 @@ static int muxing(
    size_t trackIndex = -1;
    size_t trackIndex = -1;
    sp<ABuffer> newBuffer = new ABuffer(bufferSize);
    sp<ABuffer> newBuffer = new ABuffer(bufferSize);


    muxer->setOrientationHint(rotationDegrees);
    muxer->start();
    muxer->start();


    while (!sawInputEOS) {
    while (!sawInputEOS) {
@@ -210,12 +212,13 @@ int main(int argc, char **argv) {
    char *outputFileName = NULL;
    char *outputFileName = NULL;
    int trimStartTimeMs = -1;
    int trimStartTimeMs = -1;
    int trimEndTimeMs = -1;
    int trimEndTimeMs = -1;
    int rotationDegrees = 0;
    // When trimStartTimeMs and trimEndTimeMs seems valid, we turn this switch
    // When trimStartTimeMs and trimEndTimeMs seems valid, we turn this switch
    // to true.
    // to true.
    bool enableTrim = false;
    bool enableTrim = false;


    int res;
    int res;
    while ((res = getopt(argc, argv, "h?avo:s:e:")) >= 0) {
    while ((res = getopt(argc, argv, "h?avo:s:e:r:")) >= 0) {
        switch (res) {
        switch (res) {
            case 'a':
            case 'a':
            {
            {
@@ -247,6 +250,12 @@ int main(int argc, char **argv) {
                break;
                break;
            }
            }


            case 'r':
            {
                rotationDegrees = atoi(optarg);
                break;
            }

            case '?':
            case '?':
            case 'h':
            case 'h':
            default:
            default:
@@ -288,7 +297,7 @@ int main(int argc, char **argv) {
    looper->start();
    looper->start();


    int result = muxing(looper, argv[0], useAudio, useVideo, outputFileName,
    int result = muxing(looper, argv[0], useAudio, useVideo, outputFileName,
                        enableTrim, trimStartTimeMs, trimEndTimeMs);
                        enableTrim, trimStartTimeMs, trimEndTimeMs, rotationDegrees);


    looper->stop();
    looper->stop();


+12 −2
Original line number Original line Diff line number Diff line
@@ -76,12 +76,21 @@ public:
     */
     */
    status_t start();
    status_t start();


    /**
     * Set the orientation hint.
     * @param degrees The rotation degrees. It has to be either 0,
     *                90, 180 or 270.
     * @return OK if no error.
     */
    status_t setOrientationHint(int degrees);

    /**
    /**
     * Stop muxing.
     * Stop muxing.
     * This method is a blocking call. Depending on how
     * This method is a blocking call. Depending on how
     * much data is bufferred internally, the time needed for stopping
     * much data is bufferred internally, the time needed for stopping
     * the muxer may be time consuming. UI thread is
     * the muxer may be time consuming. UI thread is
     * not recommended for launching this call.
     * not recommended for launching this call.
     * @return OK if no error.
     */
     */
    status_t stop();
    status_t stop();


@@ -104,12 +113,13 @@ public:
private:
private:
    sp<MPEG4Writer> mWriter;
    sp<MPEG4Writer> mWriter;
    Vector< sp<MediaAdapter> > mTrackList;  // Each track has its MediaAdapter.
    Vector< sp<MediaAdapter> > mTrackList;  // Each track has its MediaAdapter.
    sp<MetaData> mFileMeta;  // Metadata for the whole file.


    Mutex mMuxerLock;
    Mutex mMuxerLock;


    enum State {
    enum State {
        UNINITED,
        UNINITIALIZED,
        INITED,
        INITIALIZED,
        STARTED,
        STARTED,
        STOPPED
        STOPPED
    };
    };
+34 −14
Original line number Original line Diff line number Diff line
@@ -36,18 +36,21 @@
namespace android {
namespace android {


MediaMuxer::MediaMuxer(const char *path, OutputFormat format)
MediaMuxer::MediaMuxer(const char *path, OutputFormat format)
    : mState(UNINITED) {
    : mState(UNINITIALIZED) {
    if (format == OUTPUT_FORMAT_MPEG_4) {
    if (format == OUTPUT_FORMAT_MPEG_4) {
        mWriter = new MPEG4Writer(path);
        mWriter = new MPEG4Writer(path);
        mState = INITED;
        mFileMeta = new MetaData;
        mState = INITIALIZED;
    }
    }

}
}


MediaMuxer::MediaMuxer(int fd, OutputFormat format)
MediaMuxer::MediaMuxer(int fd, OutputFormat format)
    : mState(UNINITED) {
    : mState(UNINITIALIZED) {
    if (format == OUTPUT_FORMAT_MPEG_4) {
    if (format == OUTPUT_FORMAT_MPEG_4) {
        mWriter = new MPEG4Writer(fd);
        mWriter = new MPEG4Writer(fd);
        mState = INITED;
        mFileMeta = new MetaData;
        mState = INITIALIZED;
    }
    }
}
}


@@ -55,6 +58,7 @@ MediaMuxer::~MediaMuxer() {
    Mutex::Autolock autoLock(mMuxerLock);
    Mutex::Autolock autoLock(mMuxerLock);


    // Clean up all the internal resources.
    // Clean up all the internal resources.
    mFileMeta.clear();
    mWriter.clear();
    mWriter.clear();
    mTrackList.clear();
    mTrackList.clear();
}
}
@@ -67,15 +71,15 @@ ssize_t MediaMuxer::addTrack(const sp<AMessage> &format) {
        return -EINVAL;
        return -EINVAL;
    }
    }


    if (mState != INITED) {
    if (mState != INITIALIZED) {
        ALOGE("addTrack() must be called after constructor and before start().");
        ALOGE("addTrack() must be called after constructor and before start().");
        return INVALID_OPERATION;
        return INVALID_OPERATION;
    }
    }


    sp<MetaData> meta = new MetaData;
    sp<MetaData> trackMeta = new MetaData;
    convertMessageToMetaData(format, meta);
    convertMessageToMetaData(format, trackMeta);


    sp<MediaAdapter> newTrack = new MediaAdapter(meta);
    sp<MediaAdapter> newTrack = new MediaAdapter(trackMeta);
    status_t result = mWriter->addSource(newTrack);
    status_t result = mWriter->addSource(newTrack);
    if (result == OK) {
    if (result == OK) {
        return mTrackList.add(newTrack);
        return mTrackList.add(newTrack);
@@ -83,11 +87,27 @@ ssize_t MediaMuxer::addTrack(const sp<AMessage> &format) {
    return -1;
    return -1;
}
}


status_t MediaMuxer::setOrientationHint(int degrees) {
    Mutex::Autolock autoLock(mMuxerLock);
    if (mState != INITIALIZED) {
        ALOGE("setOrientationHint() must be called before start().");
        return INVALID_OPERATION;
    }

    if (degrees != 0 && degrees != 90 && degrees != 180 && degrees != 270) {
        ALOGE("setOrientationHint() get invalid degrees");
        return -EINVAL;
    }

    mFileMeta->setInt32(kKeyRotation, degrees);
    return OK;
}

status_t MediaMuxer::start() {
status_t MediaMuxer::start() {
    Mutex::Autolock autoLock(mMuxerLock);
    Mutex::Autolock autoLock(mMuxerLock);
    if (mState == INITED) {
    if (mState == INITIALIZED) {
        mState = STARTED;
        mState = STARTED;
        return mWriter->start();
        return mWriter->start(mFileMeta.get());
    } else {
    } else {
        ALOGE("start() is called in invalid state %d", mState);
        ALOGE("start() is called in invalid state %d", mState);
        return INVALID_OPERATION;
        return INVALID_OPERATION;
@@ -135,13 +155,13 @@ status_t MediaMuxer::writeSampleData(const sp<ABuffer> &buffer, size_t trackInde
    mediaBuffer->add_ref(); // Released in MediaAdapter::signalBufferReturned().
    mediaBuffer->add_ref(); // Released in MediaAdapter::signalBufferReturned().
    mediaBuffer->set_range(buffer->offset(), buffer->size());
    mediaBuffer->set_range(buffer->offset(), buffer->size());


    sp<MetaData> metaData = mediaBuffer->meta_data();
    sp<MetaData> sampleMetaData = mediaBuffer->meta_data();
    metaData->setInt64(kKeyTime, timeUs);
    sampleMetaData->setInt64(kKeyTime, timeUs);
    // Just set the kKeyDecodingTime as the presentation time for now.
    // Just set the kKeyDecodingTime as the presentation time for now.
    metaData->setInt64(kKeyDecodingTime, timeUs);
    sampleMetaData->setInt64(kKeyDecodingTime, timeUs);


    if (flags & SAMPLE_FLAG_SYNC) {
    if (flags & SAMPLE_FLAG_SYNC) {
        metaData->setInt32(kKeyIsSyncFrame, true);
        sampleMetaData->setInt32(kKeyIsSyncFrame, true);
    }
    }


    sp<MediaAdapter> currentTrack = mTrackList[trackIndex];
    sp<MediaAdapter> currentTrack = mTrackList[trackIndex];