Merge "Add the presentation rotation support" into jb-mr2-dev
diff --git a/cmds/stagefright/muxer.cpp b/cmds/stagefright/muxer.cpp
index fac2acc..cca33e0 100644
--- a/cmds/stagefright/muxer.cpp
+++ b/cmds/stagefright/muxer.cpp
@@ -55,7 +55,8 @@
         const char *outputFileName,
         bool enableTrim,
         int trimStartTimeMs,
-        int trimEndTimeMs) {
+        int trimEndTimeMs,
+        int rotationDegrees) {
     sp<NuMediaExtractor> extractor = new NuMediaExtractor;
     if (extractor->setDataSource(path) != OK) {
         fprintf(stderr, "unable to instantiate extractor. %s\n", path);
@@ -141,6 +142,7 @@
     size_t trackIndex = -1;
     sp<ABuffer> newBuffer = new ABuffer(bufferSize);
 
+    muxer->setOrientationHint(rotationDegrees);
     muxer->start();
 
     while (!sawInputEOS) {
@@ -210,12 +212,13 @@
     char *outputFileName = NULL;
     int trimStartTimeMs = -1;
     int trimEndTimeMs = -1;
+    int rotationDegrees = 0;
     // When trimStartTimeMs and trimEndTimeMs seems valid, we turn this switch
     // to true.
     bool enableTrim = false;
 
     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) {
             case 'a':
             {
@@ -247,6 +250,12 @@
                 break;
             }
 
+            case 'r':
+            {
+                rotationDegrees = atoi(optarg);
+                break;
+            }
+
             case '?':
             case 'h':
             default:
@@ -288,7 +297,7 @@
     looper->start();
 
     int result = muxing(looper, argv[0], useAudio, useVideo, outputFileName,
-                        enableTrim, trimStartTimeMs, trimEndTimeMs);
+                        enableTrim, trimStartTimeMs, trimEndTimeMs, rotationDegrees);
 
     looper->stop();
 
diff --git a/include/media/stagefright/MediaMuxer.h b/include/media/stagefright/MediaMuxer.h
index 167d0d9..fad319f 100644
--- a/include/media/stagefright/MediaMuxer.h
+++ b/include/media/stagefright/MediaMuxer.h
@@ -77,11 +77,20 @@
     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.
      * This method is a blocking call. Depending on how
      * much data is bufferred internally, the time needed for stopping
      * the muxer may be time consuming. UI thread is
      * not recommended for launching this call.
+     * @return OK if no error.
      */
     status_t stop();
 
@@ -104,12 +113,13 @@
 private:
     sp<MPEG4Writer> mWriter;
     Vector< sp<MediaAdapter> > mTrackList;  // Each track has its MediaAdapter.
+    sp<MetaData> mFileMeta;  // Metadata for the whole file.
 
     Mutex mMuxerLock;
 
     enum State {
-        UNINITED,
-        INITED,
+        UNINITIALIZED,
+        INITIALIZED,
         STARTED,
         STOPPED
     };
diff --git a/media/libstagefright/MediaMuxer.cpp b/media/libstagefright/MediaMuxer.cpp
index 21841b3..b948fe2 100644
--- a/media/libstagefright/MediaMuxer.cpp
+++ b/media/libstagefright/MediaMuxer.cpp
@@ -36,18 +36,21 @@
 namespace android {
 
 MediaMuxer::MediaMuxer(const char *path, OutputFormat format)
-    : mState(UNINITED) {
+    : mState(UNINITIALIZED) {
     if (format == OUTPUT_FORMAT_MPEG_4) {
         mWriter = new MPEG4Writer(path);
-        mState = INITED;
+        mFileMeta = new MetaData;
+        mState = INITIALIZED;
     }
+
 }
 
 MediaMuxer::MediaMuxer(int fd, OutputFormat format)
-    : mState(UNINITED) {
+    : mState(UNINITIALIZED) {
     if (format == OUTPUT_FORMAT_MPEG_4) {
         mWriter = new MPEG4Writer(fd);
-        mState = INITED;
+        mFileMeta = new MetaData;
+        mState = INITIALIZED;
     }
 }
 
@@ -55,6 +58,7 @@
     Mutex::Autolock autoLock(mMuxerLock);
 
     // Clean up all the internal resources.
+    mFileMeta.clear();
     mWriter.clear();
     mTrackList.clear();
 }
@@ -67,15 +71,15 @@
         return -EINVAL;
     }
 
-    if (mState != INITED) {
+    if (mState != INITIALIZED) {
         ALOGE("addTrack() must be called after constructor and before start().");
         return INVALID_OPERATION;
     }
 
-    sp<MetaData> meta = new MetaData;
-    convertMessageToMetaData(format, meta);
+    sp<MetaData> trackMeta = new MetaData;
+    convertMessageToMetaData(format, trackMeta);
 
-    sp<MediaAdapter> newTrack = new MediaAdapter(meta);
+    sp<MediaAdapter> newTrack = new MediaAdapter(trackMeta);
     status_t result = mWriter->addSource(newTrack);
     if (result == OK) {
         return mTrackList.add(newTrack);
@@ -83,11 +87,27 @@
     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() {
     Mutex::Autolock autoLock(mMuxerLock);
-    if (mState == INITED) {
+    if (mState == INITIALIZED) {
         mState = STARTED;
-        return mWriter->start();
+        return mWriter->start(mFileMeta.get());
     } else {
         ALOGE("start() is called in invalid state %d", mState);
         return INVALID_OPERATION;
@@ -135,13 +155,13 @@
     mediaBuffer->add_ref(); // Released in MediaAdapter::signalBufferReturned().
     mediaBuffer->set_range(buffer->offset(), buffer->size());
 
-    sp<MetaData> metaData = mediaBuffer->meta_data();
-    metaData->setInt64(kKeyTime, timeUs);
+    sp<MetaData> sampleMetaData = mediaBuffer->meta_data();
+    sampleMetaData->setInt64(kKeyTime, timeUs);
     // Just set the kKeyDecodingTime as the presentation time for now.
-    metaData->setInt64(kKeyDecodingTime, timeUs);
+    sampleMetaData->setInt64(kKeyDecodingTime, timeUs);
 
     if (flags & SAMPLE_FLAG_SYNC) {
-        metaData->setInt32(kKeyIsSyncFrame, true);
+        sampleMetaData->setInt32(kKeyIsSyncFrame, true);
     }
 
     sp<MediaAdapter> currentTrack = mTrackList[trackIndex];