Merge changes I93364c74,I5ca831b8

* changes:
  Exclude MTP implementation from simulator build
  Fixes for simulator build on lucid
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 962b38b..232583a 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -52,6 +52,7 @@
     void endBox();
     uint32_t interleaveDuration() const { return mInterleaveDurationUs; }
     status_t setInterleaveDuration(uint32_t duration);
+    int32_t getTimeScale() const { return mTimeScale; }
 
 protected:
     virtual ~MPEG4Writer();
@@ -72,6 +73,7 @@
     bool mStreamableFile;
     off_t mEstimatedMoovBoxSize;
     uint32_t mInterleaveDurationUs;
+    int32_t mTimeScale;
     int64_t mStartTimestampUs;
     Mutex mLock;
 
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 73f5547..cdbf483 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -68,6 +68,7 @@
     kKeyDiscNumber        = 'dnum',  // cstring
     kKeyDate              = 'date',  // cstring
     kKeyWriter            = 'writ',  // cstring
+    kKeyTimeScale         = 'tmsl',  // int32_t
 
     // video profile and level
     kKeyVideoProfile      = 'vprf',  // int32_t
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 3beae7f..24b0e7b 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -381,12 +381,12 @@
     return OK;
 }
 
-// If interval <  0, only the first frame is I frame, and rest are all P frames
-// If interval == 0, all frames are encoded as I frames. No P frames
-// If interval >  0, it is the time spacing (seconds) between 2 neighboring I frames
-status_t StagefrightRecorder::setParamVideoIFramesInterval(int32_t interval) {
-    LOGV("setParamVideoIFramesInterval: %d seconds", interval);
-    mIFramesInterval = interval;
+// If seconds <  0, only the first frame is I frame, and rest are all P frames
+// If seconds == 0, all frames are encoded as I frames. No P frames
+// If seconds >  0, it is the time spacing (seconds) between 2 neighboring I frames
+status_t StagefrightRecorder::setParamVideoIFramesInterval(int32_t seconds) {
+    LOGV("setParamVideoIFramesInterval: %d seconds", seconds);
+    mIFramesIntervalSec = seconds;
     return OK;
 }
 
@@ -444,6 +444,44 @@
     return OK;
 }
 
+status_t StagefrightRecorder::setParamMovieTimeScale(int32_t timeScale) {
+    LOGV("setParamMovieTimeScale: %d", timeScale);
+
+    // The range is set to be the same as the audio's time scale range
+    // since audio's time scale has a wider range.
+    if (timeScale < 600 || timeScale > 96000) {
+        LOGE("Time scale (%d) for movie is out of range [600, 96000]", timeScale);
+        return BAD_VALUE;
+    }
+    mMovieTimeScale = timeScale;
+    return OK;
+}
+
+status_t StagefrightRecorder::setParamVideoTimeScale(int32_t timeScale) {
+    LOGV("setParamVideoTimeScale: %d", timeScale);
+
+    // 60000 is chosen to make sure that each video frame from a 60-fps
+    // video has 1000 ticks.
+    if (timeScale < 600 || timeScale > 60000) {
+        LOGE("Time scale (%d) for video is out of range [600, 60000]", timeScale);
+        return BAD_VALUE;
+    }
+    mVideoTimeScale = timeScale;
+    return OK;
+}
+
+status_t StagefrightRecorder::setParamAudioTimeScale(int32_t timeScale) {
+    LOGV("setParamAudioTimeScale: %d", timeScale);
+
+    // 96000 Hz is the highest sampling rate support in AAC.
+    if (timeScale < 600 || timeScale > 96000) {
+        LOGE("Time scale (%d) for audio is out of range [600, 96000]", timeScale);
+        return BAD_VALUE;
+    }
+    mAudioTimeScale = timeScale;
+    return OK;
+}
+
 status_t StagefrightRecorder::setParameter(
         const String8 &key, const String8 &value) {
     LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
@@ -462,6 +500,11 @@
         if (safe_strtoi32(value.string(), &durationUs)) {
             return setParamInterleaveDuration(durationUs);
         }
+    } else if (key == "param-movie-time-scale") {
+        int32_t timeScale;
+        if (safe_strtoi32(value.string(), &timeScale)) {
+            return setParamMovieTimeScale(timeScale);
+        }
     } else if (key == "param-use-64bit-offset") {
         int32_t use64BitOffset;
         if (safe_strtoi32(value.string(), &use64BitOffset)) {
@@ -492,15 +535,20 @@
         if (safe_strtoi32(value.string(), &audio_bitrate)) {
             return setParamAudioEncodingBitRate(audio_bitrate);
         }
+    } else if (key == "audio-param-time-scale") {
+        int32_t timeScale;
+        if (safe_strtoi32(value.string(), &timeScale)) {
+            return setParamAudioTimeScale(timeScale);
+        }
     } else if (key == "video-param-encoding-bitrate") {
         int32_t video_bitrate;
         if (safe_strtoi32(value.string(), &video_bitrate)) {
             return setParamVideoEncodingBitRate(video_bitrate);
         }
     } else if (key == "video-param-i-frames-interval") {
-        int32_t interval;
-        if (safe_strtoi32(value.string(), &interval)) {
-            return setParamVideoIFramesInterval(interval);
+        int32_t seconds;
+        if (safe_strtoi32(value.string(), &seconds)) {
+            return setParamVideoIFramesInterval(seconds);
         }
     } else if (key == "video-param-encoder-profile") {
         int32_t profile;
@@ -517,6 +565,11 @@
         if (safe_strtoi32(value.string(), &cameraId)) {
             return setParamVideoCameraId(cameraId);
         }
+    } else if (key == "video-param-time-scale") {
+        int32_t timeScale;
+        if (safe_strtoi32(value.string(), &timeScale)) {
+            return setParamVideoTimeScale(timeScale);
+        }
     } else {
         LOGE("setParameter: failed to find key %s", key.string());
     }
@@ -637,6 +690,7 @@
     encMeta->setInt32(kKeyChannelCount, mAudioChannels);
     encMeta->setInt32(kKeySampleRate, mSampleRate);
     encMeta->setInt32(kKeyBitRate, mAudioBitRate);
+    encMeta->setInt32(kKeyTimeScale, mAudioTimeScale);
 
     OMXClient client;
     CHECK_EQ(client.connect(), OK);
@@ -880,10 +934,11 @@
 
     enc_meta->setInt32(kKeyWidth, width);
     enc_meta->setInt32(kKeyHeight, height);
-    enc_meta->setInt32(kKeyIFramesInterval, mIFramesInterval);
+    enc_meta->setInt32(kKeyIFramesInterval, mIFramesIntervalSec);
     enc_meta->setInt32(kKeyStride, stride);
     enc_meta->setInt32(kKeySliceHeight, sliceHeight);
     enc_meta->setInt32(kKeyColorFormat, colorFormat);
+    enc_meta->setInt32(kKeyTimeScale, mVideoTimeScale);
     if (mVideoEncoderProfile != -1) {
         enc_meta->setInt32(kKeyVideoProfile, mVideoEncoderProfile);
     }
@@ -921,6 +976,7 @@
     if (audioEncoder == NULL) {
         return UNKNOWN_ERROR;
     }
+
     writer->addSource(audioEncoder);
     return OK;
 }
@@ -957,6 +1013,7 @@
     meta->setInt32(kKeyFileType, mOutputFormat);
     meta->setInt32(kKeyBitRate, totalBitRate);
     meta->setInt32(kKey64BitFileOffset, mUse64BitFileOffset);
+    meta->setInt32(kKeyTimeScale, mMovieTimeScale);
     if (mTrackEveryNumberOfFrames > 0) {
         meta->setInt32(kKeyTrackFrameStatus, mTrackEveryNumberOfFrames);
     }
@@ -1027,9 +1084,12 @@
     mAudioChannels = 1;
     mAudioBitRate  = 12200;
     mInterleaveDurationUs = 0;
-    mIFramesInterval = 1;
+    mIFramesIntervalSec = 1;
     mAudioSourceNode = 0;
     mUse64BitFileOffset = false;
+    mMovieTimeScale  = 1000;
+    mAudioTimeScale  = 1000;
+    mVideoTimeScale  = 1000;
     mCameraId        = 0;
     mVideoEncoderProfile = -1;
     mVideoEncoderLevel   = -1;
@@ -1112,7 +1172,7 @@
     result.append(buffer);
     snprintf(buffer, SIZE, "     Encoder level: %d\n", mVideoEncoderLevel);
     result.append(buffer);
-    snprintf(buffer, SIZE, "     I frames interval (s): %d\n", mIFramesInterval);
+    snprintf(buffer, SIZE, "     I frames interval (s): %d\n", mIFramesIntervalSec);
     result.append(buffer);
     snprintf(buffer, SIZE, "     Frame size (pixels): %dx%d\n", mVideoWidth, mVideoHeight);
     result.append(buffer);
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 58f0031..f51d7f8 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -81,10 +81,13 @@
     int32_t mAudioChannels;
     int32_t mSampleRate;
     int32_t mInterleaveDurationUs;
-    int32_t mIFramesInterval;
+    int32_t mIFramesIntervalSec;
     int32_t mCameraId;
     int32_t mVideoEncoderProfile;
     int32_t mVideoEncoderLevel;
+    int32_t mMovieTimeScale;
+    int32_t mVideoTimeScale;
+    int32_t mAudioTimeScale;
     int64_t mMaxFileSizeBytes;
     int64_t mMaxFileDurationUs;
     int32_t mTrackEveryNumberOfFrames;
@@ -111,17 +114,20 @@
     status_t setParamAudioEncodingBitRate(int32_t bitRate);
     status_t setParamAudioNumberOfChannels(int32_t channles);
     status_t setParamAudioSamplingRate(int32_t sampleRate);
+    status_t setParamAudioTimeScale(int32_t timeScale);
     status_t setParamVideoEncodingBitRate(int32_t bitRate);
-    status_t setParamVideoIFramesInterval(int32_t interval);
+    status_t setParamVideoIFramesInterval(int32_t seconds);
     status_t setParamVideoEncoderProfile(int32_t profile);
     status_t setParamVideoEncoderLevel(int32_t level);
     status_t setParamVideoCameraId(int32_t cameraId);
+    status_t setParamVideoTimeScale(int32_t timeScale);
     status_t setParamTrackTimeStatus(int64_t timeDurationUs);
     status_t setParamTrackFrameStatus(int32_t nFrames);
     status_t setParamInterleaveDuration(int32_t durationUs);
     status_t setParam64BitFileOffset(bool use64BitFileOffset);
     status_t setParamMaxFileDurationUs(int64_t timeUs);
     status_t setParamMaxFileSizeBytes(int64_t bytes);
+    status_t setParamMovieTimeScale(int32_t timeScale);
     void clipVideoBitRate();
     void clipVideoFrameRate();
     void clipVideoFrameWidth();
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 6a4a131..b7388bb 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -41,6 +41,7 @@
 class MPEG4Writer::Track {
 public:
     Track(MPEG4Writer *owner, const sp<MediaSource> &source);
+
     ~Track();
 
     status_t start(MetaData *params);
@@ -61,12 +62,13 @@
     volatile bool mResumed;
     int64_t mMaxTimeStampUs;
     int64_t mEstimatedTrackSizeBytes;
+    int32_t mTimeScale;
 
     pthread_t mThread;
 
     struct SampleInfo {
         size_t size;
-        int64_t timestamp;
+        int64_t timestampUs;
     };
     List<SampleInfo>    mSampleInfos;
     bool                mSamplesHaveSameSize;
@@ -92,11 +94,11 @@
 
     struct SttsTableEntry {
 
-        SttsTableEntry(uint32_t count, uint32_t duration)
-            : sampleCount(count), sampleDuration(duration) {}
+        SttsTableEntry(uint32_t count, uint32_t durationUs)
+            : sampleCount(count), sampleDurationUs(durationUs) {}
 
         uint32_t sampleCount;
-        uint32_t sampleDuration;
+        uint32_t sampleDurationUs;
     };
     List<SttsTableEntry> mSttsTableEntries;
 
@@ -270,6 +272,13 @@
         return OK;
     }
 
+    if (!param ||
+        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
+        mTimeScale = 1000;
+    }
+    CHECK(mTimeScale > 0);
+    LOGV("movie time scale: %d", mTimeScale);
+
     mStreamableFile = true;
     mWriteMoovBoxToMemory = false;
     mMoovBoxBuffer = NULL;
@@ -336,14 +345,14 @@
         return;
     }
 
-    int64_t max_duration = 0;
+    int64_t maxDurationUs = 0;
     for (List<Track *>::iterator it = mTracks.begin();
          it != mTracks.end(); ++it) {
         (*it)->stop();
 
-        int64_t duration = (*it)->getDurationUs();
-        if (duration > max_duration) {
-            max_duration = duration;
+        int64_t durationUs = (*it)->getDurationUs();
+        if (durationUs > maxDurationUs) {
+            maxDurationUs = durationUs;
         }
     }
 
@@ -367,8 +376,7 @@
     mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
     mMoovBoxBufferOffset = 0;
     CHECK(mMoovBoxBuffer != NULL);
-    int32_t timeScale = 1000;
-    int32_t duration = max_duration / timeScale;
+    int32_t duration = (maxDurationUs * mTimeScale) / 1E6;
 
     beginBox("moov");
 
@@ -376,7 +384,7 @@
         writeInt32(0);             // version=0, flags=0
         writeInt32(now);           // creation time
         writeInt32(now);           // modification time
-        writeInt32(timeScale);          // timescale
+        writeInt32(mTimeScale);    // mvhd timescale
         writeInt32(duration);
         writeInt32(0x10000);       // rate: 1.0
         writeInt16(0x100);         // volume
@@ -655,7 +663,6 @@
 }
 
 int64_t MPEG4Writer::getStartTimestampUs() {
-    LOGI("getStartTimestampUs: %lld", mStartTimestampUs);
     Mutex::Autolock autoLock(mLock);
     return mStartTimestampUs;
 }
@@ -683,6 +690,11 @@
       mGotAllCodecSpecificData(false),
       mReachedEOS(false) {
     getCodecSpecificDataFromInputFormatIfPossible();
+
+    if (!mMeta->findInt32(kKeyTimeScale, &mTimeScale)) {
+        mTimeScale = 1000;
+    }
+    CHECK(mTimeScale > 0);
 }
 
 void MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
@@ -927,9 +939,9 @@
     int64_t chunkTimestampUs = 0;
     int32_t nChunks = 0;
     int32_t nZeroLengthFrames = 0;
-    int64_t lastTimestamp = 0;  // Timestamp of the previous sample
-    int64_t lastDuration = 0;   // Time spacing between the previous two samples
-    int32_t sampleCount = 1;    // Sample count in the current stts table entry
+    int64_t lastTimestampUs = 0;  // Previous sample time stamp in ms
+    int64_t lastDurationUs = 0;   // Between the previous two samples in ms
+    int32_t sampleCount = 1;      // Sample count in the current stts table entry
     uint32_t previousSampleSize = 0;  // Size of the previous sample
     int64_t previousPausedDurationUs = 0;
     sp<MetaData> meta_data;
@@ -1113,7 +1125,7 @@
         }
 
         if (mResumed) {
-            previousPausedDurationUs += (timestampUs - mMaxTimeStampUs - 1000 * lastDuration);
+            previousPausedDurationUs += (timestampUs - mMaxTimeStampUs - lastDurationUs);
             mResumed = false;
         }
 
@@ -1124,12 +1136,11 @@
             mMaxTimeStampUs = timestampUs;
         }
 
-        // Our timestamp is in ms.
-        info.timestamp = (timestampUs + 500) / 1000;
+        info.timestampUs = timestampUs;
         mSampleInfos.push_back(info);
         if (mSampleInfos.size() > 2) {
-            if (lastDuration != info.timestamp - lastTimestamp) {
-                SttsTableEntry sttsEntry(sampleCount, lastDuration);
+            if (lastDurationUs != info.timestampUs - lastTimestampUs) {
+                SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
                 mSttsTableEntries.push_back(sttsEntry);
                 sampleCount = 1;
             } else {
@@ -1142,8 +1153,8 @@
             }
             previousSampleSize = info.size;
         }
-        lastDuration = info.timestamp - lastTimestamp;
-        lastTimestamp = info.timestamp;
+        lastDurationUs = info.timestampUs - lastTimestampUs;
+        lastTimestampUs = info.timestampUs;
 
         if (isSync != 0) {
             mStssTableEntries.push_back(mSampleInfos.size());
@@ -1213,11 +1224,11 @@
     // there is no frame time after it, just repeat the previous
     // frame's duration.
     if (mSampleInfos.size() == 1) {
-        lastDuration = 0;  // A single sample's duration
+        lastDurationUs = 0;  // A single sample's duration
     } else {
         ++sampleCount;  // Count for the last sample
     }
-    SttsTableEntry sttsEntry(sampleCount, lastDuration);
+    SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
     mSttsTableEntries.push_back(sttsEntry);
     mReachedEOS = true;
     LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames - %s",
@@ -1249,12 +1260,13 @@
 void MPEG4Writer::Track::findMinAvgMaxSampleDurationMs(
         int32_t *min, int32_t *avg, int32_t *max) {
     CHECK(!mSampleInfos.empty());
-    int32_t avgSampleDurationMs = mMaxTimeStampUs / 1000/ mSampleInfos.size();
+    int32_t avgSampleDurationMs = mMaxTimeStampUs / 1000 / mSampleInfos.size();
     int32_t minSampleDurationMs = 0x7FFFFFFF;
     int32_t maxSampleDurationMs = 0;
     for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
         it != mSttsTableEntries.end(); ++it) {
-        int32_t sampleDurationMs = static_cast<int32_t>(it->sampleDuration);
+        int32_t sampleDurationMs =
+            (static_cast<int32_t>(it->sampleDurationUs) + 500) / 1000;
         if (sampleDurationMs > maxSampleDurationMs) {
             maxSampleDurationMs = sampleDurationMs;
         } else if (sampleDurationMs < minSampleDurationMs) {
@@ -1370,10 +1382,13 @@
     CHECK(success);
 
     bool is_audio = !strncasecmp(mime, "audio/", 6);
-    int32_t timeScale = 1000;
-    int32_t duration = getDurationUs() / timeScale;
+    LOGV("%s track time scale: %d",
+        is_audio? "Audio": "Video", mTimeScale);
+
 
     time_t now = time(NULL);
+    int32_t mvhdTimeScale = mOwner->getTimeScale();
+    int64_t trakDurationUs = getDurationUs();
 
     mOwner->beginBox("trak");
 
@@ -1385,7 +1400,9 @@
         mOwner->writeInt32(now);           // modification time
         mOwner->writeInt32(trackID);
         mOwner->writeInt32(0);             // reserved
-        mOwner->writeInt32(duration);
+        int32_t tkhdDuration =
+            (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
+        mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
         mOwner->writeInt32(0);             // reserved
         mOwner->writeInt32(0);             // reserved
         mOwner->writeInt16(0);             // layer
@@ -1423,12 +1440,17 @@
           mOwner->beginBox("elst");
             mOwner->writeInt32(0);           // version=0, flags=0: 32-bit time
             mOwner->writeInt32(2);           // never ends with an empty list
-            int64_t durationMs =
-                (mStartTimestampUs - moovStartTimeUs) / 1000;
-            mOwner->writeInt32(durationMs);  // edit duration
-            mOwner->writeInt32(-1);          // empty edit box to signal starting time offset
-            mOwner->writeInt32(1 << 16);     // x1 rate
-            mOwner->writeInt32(duration);
+
+            // First elst entry: specify the starting time offset
+            int64_t offsetUs = mStartTimestampUs - moovStartTimeUs;
+            int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6;
+            mOwner->writeInt32(seg);         // in mvhd timecale
+            mOwner->writeInt32(-1);          // starting time offset
+            mOwner->writeInt32(1 << 16);     // rate = 1.0
+
+            // Second elst entry: specify the track duration
+            seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
+            mOwner->writeInt32(seg);         // in mvhd timescale
             mOwner->writeInt32(0);
             mOwner->writeInt32(1 << 16);
           mOwner->endBox();
@@ -1441,8 +1463,9 @@
           mOwner->writeInt32(0);             // version=0, flags=0
           mOwner->writeInt32(now);           // creation time
           mOwner->writeInt32(now);           // modification time
-          mOwner->writeInt32(timeScale);     // timescale
-          mOwner->writeInt32(duration);      // duration
+          mOwner->writeInt32(mTimeScale);    // media timescale
+          int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
+          mOwner->writeInt32(mdhdDuration);  // use media timescale
           // Language follows the three letter standard ISO-639-2/T
           // 'e', 'n', 'g' for "English", for instance.
           // Each character is packed as the difference between its ASCII value and 0x60.
@@ -1664,7 +1687,8 @@
             for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
                  it != mSttsTableEntries.end(); ++it) {
                 mOwner->writeInt32(it->sampleCount);
-                mOwner->writeInt32(it->sampleDuration);
+                int32_t dur = (it->sampleDurationUs * mTimeScale + 5E5) / 1E6;
+                mOwner->writeInt32(dur);
             }
           mOwner->endBox();  // stts
 
@@ -1717,7 +1741,7 @@
                     mOwner->writeInt64((*it));
                 }
             }
-          mOwner->endBox();  // co64
+          mOwner->endBox();  // stco or co64
 
         mOwner->endBox();  // stbl
        mOwner->endBox();  // minf
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 077e123..157897b 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -3212,6 +3212,12 @@
 void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
     mOutputFormat = new MetaData;
     mOutputFormat->setCString(kKeyDecoderComponent, mComponentName);
+    if (mIsEncoder) {
+        int32_t timeScale;
+        if (inputFormat->findInt32(kKeyTimeScale, &timeScale)) {
+            mOutputFormat->setInt32(kKeyTimeScale, timeScale);
+        }
+    }
 
     OMX_PARAM_PORTDEFINITIONTYPE def;
     InitOMXParams(&def);