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;
+}