Second part of speeding up video recording frame rate

1. Avoid copying the input recording frames to the encoder via OMX interface
   for TI video encoder
   This is a missing change for part one which help reduces the CPU load.

2. Release output buffers as early as possible. This is a little bit helpful, but not critical.

TODO:
We should save the underlying pointers allocated by the OMX component before we replace them
and restore them before we call OMX_FreeBuffer()!

Change-Id: Ib3a88978f4c3b1153808872eaa7ac4c265a811ff
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index f836c55..aceeab8 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -98,6 +98,7 @@
         kDecoderLiesAboutNumberOfChannels     = 256,
         kInputBufferSizesAreBogus             = 512,
         kSupportsMultipleFramesPerInputBuffer = 1024,
+        kAvoidMemcopyInputRecordingFrames     = 2048,
     };
 
     struct BufferInfo {
@@ -165,7 +166,8 @@
             OMX_COLOR_FORMATTYPE colorFormat);
 
     void setVideoInputFormat(
-            const char *mime, OMX_U32 width, OMX_U32 height);
+            const char *mime, OMX_U32 width, OMX_U32 height,
+            OMX_U32 frameRate, OMX_U32 bitRate);
 
     status_t setupMPEG4EncoderParameters();
     status_t setupAVCEncoderParameters();
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index e0f8f9e..6fa11e0 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -705,6 +705,7 @@
     int64_t lastDuration = 0;   // Time spacing between the previous two samples
     int32_t sampleCount = 1;    // Sample count in the current stts table entry
     uint32_t previousSampleSize = 0;  // Size of the previous sample
+    sp<MetaData> meta_data;
 
     MediaBuffer *buffer;
     while (!mDone && mSource->read(&buffer) == OK) {
@@ -825,35 +826,46 @@
             continue;
         }
 
-        if (is_avc) StripStartcode(buffer);
+        // Make a deep copy of the MediaBuffer and Metadata and release
+        // the original as soon as we can
+        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
+        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
+                buffer->range_length());
+        copy->set_range(0, buffer->range_length());
+        meta_data = new MetaData(*buffer->meta_data().get());
+        buffer->release();
+        buffer = NULL;
+
+        if (is_avc) StripStartcode(copy);
 
         SampleInfo info;
         info.size = is_avc
 #if USE_NALLEN_FOUR
-                ? buffer->range_length() + 4
+                ? copy->range_length() + 4
 #else
-                ? buffer->range_length() + 2
+                ? copy->range_length() + 2
 #endif
-                : buffer->range_length();
+                : copy->range_length();
 
         // Max file size or duration handling
         mEstimatedTrackSizeBytes += info.size;
         if (mOwner->exceedsFileSizeLimit()) {
-            buffer->release();
-            buffer = NULL;
             mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
             break;
         }
         if (mOwner->exceedsFileDurationLimit()) {
-            buffer->release();
-            buffer = NULL;
             mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
             break;
         }
 
 
+        int32_t isSync = false;
+        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
+
         int64_t timestampUs;
-        CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
+        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
+
+////////////////////////////////////////////////////////////////////////////////
         if (mSampleInfos.empty()) {
             mOwner->setStartTimestamp(timestampUs);
             mStartTimestampUs = (timestampUs - mOwner->getStartTimestamp());
@@ -884,12 +896,10 @@
         lastDuration = info.timestamp - lastTimestamp;
         lastTimestamp = info.timestamp;
 
-////////////////////////////////////////////////////////////////////////////////
-        // Make a deep copy of the MediaBuffer less Metadata
-        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
-        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
-                buffer->range_length());
-        copy->set_range(0, buffer->range_length());
+        if (isSync != 0) {
+            mStssTableEntries.push_back(mSampleInfos.size());
+        }
+
 
         mChunkSamples.push_back(copy);
         if (interleaveDurationUs == 0) {
@@ -915,14 +925,6 @@
             }
         }
 
-        int32_t isSync = false;
-        if (buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync) &&
-            isSync != 0) {
-            mStssTableEntries.push_back(mSampleInfos.size());
-        }
-
-        buffer->release();
-        buffer = NULL;
     }
 
     if (mSampleInfos.empty()) {
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 66011ca..7c3df31 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -347,6 +347,9 @@
 
         quirks |= kRequiresAllocateBufferOnInputPorts;
         quirks |= kRequiresAllocateBufferOnOutputPorts;
+        if (!strncmp(componentName, "OMX.TI.video.encoder", 20)) {
+            quirks |= kAvoidMemcopyInputRecordingFrames;
+        }
     }
 
     if (!strcmp(componentName, "OMX.TI.Video.Decoder")) {
@@ -574,7 +577,10 @@
         CHECK(success);
 
         if (mIsEncoder) {
-            setVideoInputFormat(mMIME, width, height);
+            int32_t frameRate = 25;  // XXX
+            int32_t bitRate = 3000000;  // bit rate
+            //success = success && meta->findInt32(kKeySampleRate, &frameRate);
+            setVideoInputFormat(mMIME, width, height, frameRate, bitRate);
         } else {
             status_t err = setVideoOutputFormat(
                     mMIME, width, height);
@@ -739,7 +745,8 @@
 }
 
 void OMXCodec::setVideoInputFormat(
-        const char *mime, OMX_U32 width, OMX_U32 height) {
+        const char *mime, OMX_U32 width, OMX_U32 height,
+        OMX_U32 frameRate, OMX_U32 bitRate) {
     CODEC_LOGV("setVideoInputFormat width=%ld, height=%ld", width, height);
 
     OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
@@ -769,6 +776,7 @@
     CHECK_EQ(setVideoPortFormatType(
             kPortIndexInput, OMX_VIDEO_CodingUnused,
             colorFormat), OK);
+
     InitOMXParams(&def);
     def.nPortIndex = kPortIndexInput;
 
@@ -782,11 +790,10 @@
 
     video_def->nFrameWidth = width;
     video_def->nFrameHeight = height;
+    video_def->xFramerate = (frameRate << 16);  // Q16 format
     video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
     video_def->eColorFormat = colorFormat;
 
-    video_def->xFramerate = (24 << 16);  // Q16 format
-
     err = mOMX->setParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
@@ -806,7 +813,8 @@
 
     video_def->nFrameWidth = width;
     video_def->nFrameHeight = height;
-
+    video_def->xFramerate = (frameRate << 16);  // Q16 format
+    video_def->nBitrate = bitRate;  // Q16 format
     video_def->eCompressionFormat = compressionFormat;
     video_def->eColorFormat = OMX_COLOR_FormatUnused;
 
@@ -928,6 +936,7 @@
 
     h264type.nSliceHeaderSpacing = 0;
     h264type.nBFrames = 0;
+    h264type.nPFrames = 24;  // XXX
     h264type.bUseHadamard = OMX_TRUE;
     h264type.nRefFrames = 1;
     h264type.nRefIdx10ActiveMinus1 = 0;
@@ -960,7 +969,7 @@
     CHECK_EQ(err, OK);
 
     bitrateType.eControlRate = OMX_Video_ControlRateVariable;
-    bitrateType.nTargetBitrate = 3000000;
+    bitrateType.nTargetBitrate = 3000000;  // XXX
 
     err = mOMX->setParameter(
             mNode, OMX_IndexParamVideoBitrate,
@@ -2049,9 +2058,15 @@
             break;
         }
 
-        memcpy((uint8_t *)info->mData + offset,
-               (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
-               srcBuffer->range_length());
+        if (mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames)) {
+            CHECK(mOMXLivesLocally && offset == 0);
+            OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *) info->mBuffer;
+            header->pBuffer = (OMX_U8 *) srcBuffer->data() + srcBuffer->range_offset();
+        } else {
+            memcpy((uint8_t *)info->mData + offset,
+                    (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
+                    srcBuffer->range_length());
+        }
 
         int64_t lastBufferTimeUs;
         CHECK(srcBuffer->meta_data()->findInt64(kKeyTime, &lastBufferTimeUs));