Some work to make audio encoding work.
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index ef67611..51a0649 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -24,6 +24,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=         \
+        SineSource.cpp    \
         record.cpp
 
 LOCAL_SHARED_LIBRARIES := \
diff --git a/cmds/stagefright/JPEGSource.cpp b/cmds/stagefright/JPEGSource.cpp
index a7994ed..4e9ca4e 100644
--- a/cmds/stagefright/JPEGSource.cpp
+++ b/cmds/stagefright/JPEGSource.cpp
@@ -102,7 +102,7 @@
     meta->setCString(kKeyMIMEType, "image/jpeg");
     meta->setInt32(kKeyWidth, mWidth);
     meta->setInt32(kKeyHeight, mHeight);
-    meta->setInt32(kKeyCompressedSize, mSize);
+    meta->setInt32(kKeyMaxInputSize, mSize);
 
     return meta;
 }
diff --git a/cmds/stagefright/SineSource.cpp b/cmds/stagefright/SineSource.cpp
new file mode 100644
index 0000000..3c25a7f
--- /dev/null
+++ b/cmds/stagefright/SineSource.cpp
@@ -0,0 +1,100 @@
+#include "SineSource.h"
+
+#include <math.h>
+
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+SineSource::SineSource(int32_t sampleRate, int32_t numChannels)
+    : mStarted(false),
+      mSampleRate(sampleRate),
+      mNumChannels(numChannels),
+      mPhase(0),
+      mGroup(NULL) {
+    CHECK(numChannels == 1 || numChannels == 2);
+}
+
+SineSource::~SineSource() {
+    if (mStarted) {
+        stop();
+    }
+}
+
+status_t SineSource::start(MetaData *params) {
+    CHECK(!mStarted);
+
+    mGroup = new MediaBufferGroup;
+    mGroup->add_buffer(new MediaBuffer(kBufferSize));
+
+    mPhase = 0;
+    mStarted = true;
+
+    return OK;
+}
+
+status_t SineSource::stop() {
+    CHECK(mStarted);
+
+    delete mGroup;
+    mGroup = NULL;
+
+    mStarted = false;
+
+    return OK;
+}
+
+sp<MetaData> SineSource::getFormat() {
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, "audio/raw");
+    meta->setInt32(kKeyChannelCount, mNumChannels);
+    meta->setInt32(kKeySampleRate, mSampleRate);
+
+    return meta;
+}
+
+status_t SineSource::read(
+        MediaBuffer **out, const ReadOptions *options) {
+    *out = NULL;
+
+    MediaBuffer *buffer;
+    status_t err = mGroup->acquire_buffer(&buffer);
+
+    if (err != OK) {
+        return err;
+    }
+
+    size_t frameSize = mNumChannels * sizeof(int16_t);
+    size_t numFramesPerBuffer = buffer->size() / frameSize;
+
+    int16_t *ptr = (int16_t *)buffer->data();
+
+    const double k = kFrequency / mSampleRate * (2.0 * M_PI);
+
+    double x = mPhase * k;
+    for (size_t i = 0; i < numFramesPerBuffer; ++i) {
+        int16_t amplitude = (int16_t)(32767.0 * sin(x));
+        
+        *ptr++ = amplitude;
+        if (mNumChannels == 2) {
+            *ptr++ = amplitude;
+        }
+
+        x += k;
+    }
+
+    buffer->meta_data()->setInt32(kKeyTimeUnits, mPhase);
+    buffer->meta_data()->setInt32(kKeyTimeScale, mSampleRate);
+
+    mPhase += numFramesPerBuffer;
+
+    buffer->set_range(0, numFramesPerBuffer * frameSize);
+
+    *out = buffer;
+
+    return OK;
+}
+
+}  // namespace android
diff --git a/cmds/stagefright/SineSource.h b/cmds/stagefright/SineSource.h
new file mode 100644
index 0000000..76ab669
--- /dev/null
+++ b/cmds/stagefright/SineSource.h
@@ -0,0 +1,39 @@
+#ifndef SINE_SOURCE_H_
+
+#define SINE_SOURCE_H_
+
+#include <media/stagefright/MediaSource.h>
+
+namespace android {
+
+struct MediaBufferGroup;
+
+struct SineSource : public MediaSource {
+    SineSource(int32_t sampleRate, int32_t numChannels);
+
+    virtual status_t start(MetaData *params);
+    virtual status_t stop();
+
+    virtual sp<MetaData> getFormat();
+
+    virtual status_t read(
+            MediaBuffer **out, const ReadOptions *options = NULL);
+
+protected:
+    virtual ~SineSource();
+
+private:
+    enum { kBufferSize = 8192 };
+    static const double kFrequency = 500.0;
+
+    bool mStarted;
+    int32_t mSampleRate;
+    int32_t mNumChannels;
+    size_t mPhase;
+
+    MediaBufferGroup *mGroup;
+};
+
+}  // namespace android
+
+#endif // SINE_SOURCE_H_
diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp
index 4b44761..c049594 100644
--- a/cmds/stagefright/record.cpp
+++ b/cmds/stagefright/record.cpp
@@ -14,7 +14,10 @@
  * limitations under the License.
  */
 
+#include "SineSource.h"
+
 #include <binder/ProcessState.h>
+#include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/CameraSource.h>
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDebug.h>
@@ -24,9 +27,11 @@
 #include <media/stagefright/MmapSource.h>
 #include <media/stagefright/OMXClient.h>
 #include <media/stagefright/OMXCodec.h>
+#include <media/MediaPlayerInterface.h>
 
 using namespace android;
 
+#if 0
 class DummySource : public MediaSource {
 public:
     DummySource(int width, int height)
@@ -158,7 +163,7 @@
         OMXCodec::Create(
                 client.interface(), enc_meta, true /* createEncoder */, decoder);
 
-#if 1
+#if 0
     sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/output.mp4");
     writer->addSource(enc_meta, encoder);
     writer->start();
@@ -204,4 +209,60 @@
 
     return 0;
 }
+#endif
+
+int main(int argc, char **argv) {
+    android::ProcessState::self()->startThreadPool();
+
+    OMXClient client;
+    CHECK_EQ(client.connect(), OK);
+
+    const int32_t kSampleRate = 22050;
+    const int32_t kNumChannels = 2;
+    sp<MediaSource> audioSource = new SineSource(kSampleRate, kNumChannels);
+
+#if 0
+    sp<MediaPlayerBase::AudioSink> audioSink;
+    AudioPlayer *player = new AudioPlayer(audioSink);
+    player->setSource(audioSource);
+    player->start();
+
+    sleep(10);
+
+    player->stop();
+#endif
+
+    sp<MetaData> encMeta = new MetaData;
+    encMeta->setCString(kKeyMIMEType, 1 ? "audio/3gpp" : "audio/mp4a-latm");
+    encMeta->setInt32(kKeySampleRate, kSampleRate);
+    encMeta->setInt32(kKeyChannelCount, kNumChannels);
+    encMeta->setInt32(kKeyMaxInputSize, 8192);
+
+    sp<MediaSource> encoder =
+        OMXCodec::Create(client.interface(), encMeta, true, audioSource);
+
+    encoder->start();
+
+    int32_t n = 0;
+    status_t err;
+    MediaBuffer *buffer;
+    while ((err = encoder->read(&buffer)) == OK) {
+        printf(".");
+        fflush(stdout);
+
+        buffer->release();
+        buffer = NULL;
+
+        if (++n == 10000) {
+            break;
+        }
+    }
+    printf("$\n");
+
+    encoder->stop();
+
+    client.disconnect();
+
+    return 0;
+}
 
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index be60565..abb45a9 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -45,7 +45,7 @@
     kKeyPlatformPrivate   = 'priv',
     kKeyDecoderComponent  = 'decC',
     kKeyBufferID          = 'bfID',
-    kKeyCompressedSize    = 'cmpS',
+    kKeyMaxInputSize      = 'inpS',
 };
 
 enum {
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 5b0e0b4..6ddf2fe 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -155,6 +155,11 @@
     void setJPEGInputFormat(
             OMX_U32 width, OMX_U32 height, OMX_U32 compressedSize);
 
+    void setMinBufferSize(OMX_U32 portIndex, OMX_U32 size);
+
+    void setRawAudioFormat(
+            OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels);
+
     status_t allocateBuffers();
     status_t allocateBuffersOnPort(OMX_U32 portIndex);
 
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 7c8defc..a132c66 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -301,7 +301,7 @@
     if (!strcasecmp("audio/3gpp", mime)) {
         codec->setAMRFormat();
     }
-    if (!createEncoder && !strcasecmp("audio/mp4a-latm", mime)) {
+    if (!strcasecmp("audio/mp4a-latm", mime)) {
         int32_t numChannels, sampleRate;
         CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
         CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
@@ -334,7 +334,7 @@
 
         int32_t compressedSize;
         success = success && meta->findInt32(
-                kKeyCompressedSize, &compressedSize);
+                kKeyMaxInputSize, &compressedSize);
 
         CHECK(success);
         CHECK(compressedSize > 0);
@@ -343,11 +343,42 @@
         codec->setJPEGInputFormat(width, height, (OMX_U32)compressedSize);
     }
 
+    int32_t maxInputSize;
+    if (createEncoder && meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
+        codec->setMinBufferSize(kPortIndexInput, (OMX_U32)maxInputSize);
+    }
+
+    if (!strcmp(componentName, "OMX.TI.AMR.encode")
+        || !strcmp(componentName, "OMX.TI.WBAMR.encode")) {
+        codec->setMinBufferSize(kPortIndexOutput, 8192);  // XXX
+    }
+
     codec->initOutputFormat(meta);
 
     return codec;
 }
 
+void OMXCodec::setMinBufferSize(OMX_U32 portIndex, OMX_U32 size) {
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    def.nSize = sizeof(def);
+    def.nVersion.s.nVersionMajor = 1;
+    def.nVersion.s.nVersionMinor = 1;
+    def.nPortIndex = portIndex;
+
+    status_t err = mOMX->get_parameter(
+            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    CHECK_EQ(err, OK);
+
+    if (def.nBufferSize < size) {
+        def.nBufferSize = size;
+
+    }
+
+    err = mOMX->set_parameter(
+            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    CHECK_EQ(err, OK);
+}
+
 status_t OMXCodec::setVideoPortFormatType(
         OMX_U32 portIndex,
         OMX_VIDEO_CODINGTYPE compressionFormat,
@@ -689,7 +720,6 @@
     if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
         err = mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
         CHECK_EQ(err, OK);
-
         setState(LOADED_TO_IDLE);
     }
 
@@ -1430,6 +1460,41 @@
     mBufferFilled.signal();
 }
 
+void OMXCodec::setRawAudioFormat(
+        OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
+    OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
+    pcmParams.nSize = sizeof(pcmParams);
+    pcmParams.nVersion.s.nVersionMajor = 1;
+    pcmParams.nVersion.s.nVersionMinor = 1;
+    pcmParams.nPortIndex = portIndex;
+
+    status_t err = mOMX->get_parameter(
+            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
+
+    CHECK_EQ(err, OK);
+
+    pcmParams.nChannels = numChannels;
+    pcmParams.eNumData = OMX_NumericalDataSigned;
+    pcmParams.bInterleaved = OMX_TRUE;
+    pcmParams.nBitPerSample = 16;
+    pcmParams.nSamplingRate = sampleRate;
+    pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
+
+    if (numChannels == 1) {
+        pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
+    } else {
+        CHECK_EQ(numChannels, 2);
+
+        pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
+        pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+    }
+
+    err = mOMX->set_parameter(
+            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
+
+    CHECK_EQ(err, OK);
+}
+
 void OMXCodec::setAMRFormat() {
     if (!mIsEncoder) {
         OMX_AUDIO_PARAM_AMRTYPE def;
@@ -1459,57 +1524,32 @@
         CHECK(format->findInt32(kKeySampleRate, &sampleRate));
         CHECK(format->findInt32(kKeyChannelCount, &numChannels));
 
-        OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
-        pcmParams.nSize = sizeof(pcmParams);
-        pcmParams.nVersion.s.nVersionMajor = 1;
-        pcmParams.nVersion.s.nVersionMinor = 1;
-        pcmParams.nPortIndex = kPortIndexInput;
-
-        status_t err = mOMX->get_parameter(
-                mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
-
-        CHECK_EQ(err, OK);
-
-        pcmParams.nChannels = numChannels;
-        pcmParams.eNumData = OMX_NumericalDataSigned;
-        pcmParams.bInterleaved = OMX_TRUE;
-        pcmParams.nBitPerSample = 16;
-        pcmParams.nSamplingRate = sampleRate;
-        pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
-
-        if (numChannels == 1) {
-            pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
-        } else {
-            CHECK_EQ(numChannels, 2);
-
-            pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
-            pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
-        }
-
-        err = mOMX->set_parameter(
-                mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
-
-        CHECK_EQ(err, OK);
+        setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
     }
 }
 
 void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate) {
-    OMX_AUDIO_PARAM_AACPROFILETYPE profile;
-    profile.nSize = sizeof(profile);
-    profile.nVersion.s.nVersionMajor = 1;
-    profile.nVersion.s.nVersionMinor = 1;
-    profile.nPortIndex = kPortIndexInput;
+    if (mIsEncoder) {
+        setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
+    } else {
+        OMX_AUDIO_PARAM_AACPROFILETYPE profile;
+        profile.nSize = sizeof(profile);
+        profile.nVersion.s.nVersionMajor = 1;
+        profile.nVersion.s.nVersionMinor = 1;
+        profile.nPortIndex = kPortIndexInput;
 
-    status_t err =
-        mOMX->get_parameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
-    CHECK_EQ(err, OK);
+        status_t err = mOMX->get_parameter(
+                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
+        CHECK_EQ(err, OK);
 
-    profile.nChannels = numChannels;
-    profile.nSampleRate = sampleRate;
-    profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
+        profile.nChannels = numChannels;
+        profile.nSampleRate = sampleRate;
+        profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
 
-    err = mOMX->set_parameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
-    CHECK_EQ(err, OK);
+        err = mOMX->set_parameter(
+                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
+        CHECK_EQ(err, OK);
+    }
 }
 
 void OMXCodec::setImageOutputFormat(
@@ -2102,40 +2142,46 @@
         {
             OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio;
 
-            CHECK_EQ(audio_def->eEncoding, OMX_AUDIO_CodingPCM);
+            if (audio_def->eEncoding == OMX_AUDIO_CodingPCM) {
+                OMX_AUDIO_PARAM_PCMMODETYPE params;
+                params.nSize = sizeof(params);
+                params.nVersion.s.nVersionMajor = 1;
+                params.nVersion.s.nVersionMinor = 1;
+                params.nPortIndex = kPortIndexOutput;
 
-            OMX_AUDIO_PARAM_PCMMODETYPE params;
-            params.nSize = sizeof(params);
-            params.nVersion.s.nVersionMajor = 1;
-            params.nVersion.s.nVersionMinor = 1;
-            params.nPortIndex = kPortIndexOutput;
+                err = mOMX->get_parameter(
+                        mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
+                CHECK_EQ(err, OK);
 
-            err = mOMX->get_parameter(
-                    mNode, OMX_IndexParamAudioPcm, &params, sizeof(params));
-            CHECK_EQ(err, OK);
+                CHECK_EQ(params.eNumData, OMX_NumericalDataSigned);
+                CHECK_EQ(params.nBitPerSample, 16);
+                CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear);
 
-            CHECK_EQ(params.eNumData, OMX_NumericalDataSigned);
-            CHECK_EQ(params.nBitPerSample, 16);
-            CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear);
+                int32_t numChannels, sampleRate;
+                inputFormat->findInt32(kKeyChannelCount, &numChannels);
+                inputFormat->findInt32(kKeySampleRate, &sampleRate);
 
-            int32_t numChannels, sampleRate;
-            inputFormat->findInt32(kKeyChannelCount, &numChannels);
-            inputFormat->findInt32(kKeySampleRate, &sampleRate);
+                if ((OMX_U32)numChannels != params.nChannels) {
+                    LOGW("Codec outputs a different number of channels than "
+                         "the input stream contains.");
+                }
 
-            if ((OMX_U32)numChannels != params.nChannels) {
-                LOGW("Codec outputs a different number of channels than "
-                     "the input stream contains.");
+                mOutputFormat->setCString(kKeyMIMEType, "audio/raw");
+
+                // Use the codec-advertised number of channels, as some
+                // codecs appear to output stereo even if the input data is
+                // mono.
+                mOutputFormat->setInt32(kKeyChannelCount, params.nChannels);
+
+                // The codec-reported sampleRate is not reliable...
+                mOutputFormat->setInt32(kKeySampleRate, sampleRate);
+            } else if (audio_def->eEncoding == OMX_AUDIO_CodingAMR) {
+                mOutputFormat->setCString(kKeyMIMEType, "audio/3gpp");
+            } else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) {
+                mOutputFormat->setCString(kKeyMIMEType, "audio/mp4a-latm");
+            } else {
+                CHECK(!"Should not be here. Unknown audio encoding.");
             }
-
-            mOutputFormat->setCString(kKeyMIMEType, "audio/raw");
-
-            // Use the codec-advertised number of channels, as some
-            // codecs appear to output stereo even if the input data is
-            // mono.
-            mOutputFormat->setInt32(kKeyChannelCount, params.nChannels);
-
-            // The codec-reported sampleRate is not reliable...
-            mOutputFormat->setInt32(kKeySampleRate, sampleRate);
             break;
         }