Merge "MediaFormat owns its strings"
diff --git a/cmds/stagefright/audioloop.cpp b/cmds/stagefright/audioloop.cpp
index ed7d6cb..96073f1 100644
--- a/cmds/stagefright/audioloop.cpp
+++ b/cmds/stagefright/audioloop.cpp
@@ -1,4 +1,18 @@
-#include "SineSource.h"
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include <binder/ProcessState.h>
 #include <media/mediarecorder.h>
@@ -10,41 +24,79 @@
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/OMXClient.h>
 #include <media/stagefright/OMXCodec.h>
-
-#include <system/audio.h>
+#include "SineSource.h"
 
 using namespace android;
 
-int main() {
-    // We only have an AMR-WB encoder on sholes...
-    static bool outputWBAMR = false;
-    static const int32_t kSampleRate = outputWBAMR ? 16000 : 8000;
-    static const int32_t kNumChannels = 1;
+static void usage(const char* name)
+{
+    fprintf(stderr, "Usage: %s [-d duration] [-m] [-w] [<output-file>]\n", name);
+    fprintf(stderr, "Encodes either a sine wave or microphone input to AMR format\n");
+    fprintf(stderr, "    -d    duration in seconds, default 5 seconds\n");
+    fprintf(stderr, "    -m    use microphone for input, default sine source\n");
+    fprintf(stderr, "    -w    use AMR wideband (default narrowband)\n");
+    fprintf(stderr, "    <output-file> output file for AMR encoding,"
+            " if unspecified, decode to speaker.\n");
+}
+
+int main(int argc, char* argv[])
+{
+    static const int channels = 1; // not permitted to be stereo now
+    unsigned duration = 5;
+    bool useMic = false;
+    bool outputWBAMR = false;
+    bool playToSpeaker = true;
+    const char* fileOut = NULL;
+    int ch;
+    while ((ch = getopt(argc, argv, "d:mw")) != -1) {
+        switch (ch) {
+        case 'd':
+            duration = atoi(optarg);
+            break;
+        case 'm':
+            useMic = true;
+            break;
+        case 'w':
+            outputWBAMR = true;
+            break;
+        default:
+            usage(argv[0]);
+            return -1;
+        }
+    }
+    argc -= optind;
+    argv += optind;
+    if (argc == 1) {
+        fileOut = argv[0];
+    }
+    const int32_t kSampleRate = outputWBAMR ? 16000 : 8000;
+    const int32_t kBitRate = outputWBAMR ? 16000 : 8000;
 
     android::ProcessState::self()->startThreadPool();
-
     OMXClient client;
     CHECK_EQ(client.connect(), (status_t)OK);
+    sp<MediaSource> source;
 
-#if 0
-    sp<MediaSource> source = new SineSource(kSampleRate, kNumChannels);
-#else
-    sp<MediaSource> source = new AudioSource(
-            AUDIO_SOURCE_DEFAULT,
-            kSampleRate,
-            audio_channel_in_mask_from_count(kNumChannels));
-#endif
+    if (useMic) {
+        // talk into the appropriate microphone for the duration
+        source = new AudioSource(
+                AUDIO_SOURCE_MIC,
+                kSampleRate,
+                channels);
+    } else {
+        // use a sine source at 500 hz.
+        source = new SineSource(kSampleRate, channels);
+    }
 
     sp<MetaData> meta = new MetaData;
-
     meta->setCString(
             kKeyMIMEType,
             outputWBAMR ? MEDIA_MIMETYPE_AUDIO_AMR_WB
-                        : MEDIA_MIMETYPE_AUDIO_AMR_NB);
+                    : MEDIA_MIMETYPE_AUDIO_AMR_NB);
 
-    meta->setInt32(kKeyChannelCount, kNumChannels);
+    meta->setInt32(kKeyChannelCount, channels);
     meta->setInt32(kKeySampleRate, kSampleRate);
-
+    meta->setInt32(kKeyBitRate, kBitRate);
     int32_t maxInputSize;
     if (source->getFormat()->findInt32(kKeyMaxInputSize, &maxInputSize)) {
         meta->setInt32(kKeyMaxInputSize, maxInputSize);
@@ -55,47 +107,41 @@
             meta, true /* createEncoder */,
             source);
 
-#if 1
-    sp<AMRWriter> writer = new AMRWriter("/sdcard/out.amr");
-    writer->addSource(encoder);
-    writer->start();
-    sleep(10);
-    writer->stop();
-#else
-    sp<MediaSource> decoder = OMXCodec::Create(
-            client.interface(),
-            meta, false /* createEncoder */,
-            encoder);
+    if (fileOut != NULL) {
+        // target file specified, write encoded AMR output
+        sp<AMRWriter> writer = new AMRWriter(fileOut);
+        writer->addSource(encoder);
+        writer->start();
+        sleep(duration);
+        writer->stop();
+    } else {
+        // otherwise decode to speaker
+        sp<MediaSource> decoder = OMXCodec::Create(
+                client.interface(),
+                meta, false /* createEncoder */,
+                encoder);
 
-#if 0
-    AudioPlayer *player = new AudioPlayer(NULL);
-    player->setSource(decoder);
-
-    player->start();
-
-    sleep(10);
-
-    player->stop();
-
-    delete player;
-    player = NULL;
-#elif 0
-    CHECK_EQ(decoder->start(), (status_t)OK);
-
-    MediaBuffer *buffer;
-    while (decoder->read(&buffer) == OK) {
-        // do something with buffer
-
-        putchar('.');
-        fflush(stdout);
-
-        buffer->release();
-        buffer = NULL;
+        if (playToSpeaker) {
+            AudioPlayer *player = new AudioPlayer(NULL);
+            player->setSource(decoder);
+            player->start();
+            sleep(duration);
+            source->stop(); // must stop source otherwise delete player will hang
+            delete player; // there is no player->stop()...
+        } else {
+            CHECK_EQ(decoder->start(), (status_t)OK);
+            MediaBuffer* buffer;
+            while (decoder->read(&buffer) == OK) {
+                // do something with buffer (save it eventually?)
+                // need to stop after some count though...
+                putchar('.');
+                fflush(stdout);
+                buffer->release();
+                buffer = NULL;
+            }
+            CHECK_EQ(decoder->stop(), (status_t)OK);
+        }
     }
 
-    CHECK_EQ(decoder->stop(), (status_t)OK);
-#endif
-#endif
-
     return 0;
 }
diff --git a/cmds/stagefright/recordvideo.cpp b/cmds/stagefright/recordvideo.cpp
index 1d267f9..9f547c7 100644
--- a/cmds/stagefright/recordvideo.cpp
+++ b/cmds/stagefright/recordvideo.cpp
@@ -73,7 +73,7 @@
         return meta;
     }
 
-    virtual status_t start(MetaData *params) {
+    virtual status_t start(MetaData *params __unused) {
         mNumFramesOutput = 0;
         return OK;
     }
@@ -83,7 +83,7 @@
     }
 
     virtual status_t read(
-            MediaBuffer **buffer, const MediaSource::ReadOptions *options) {
+            MediaBuffer **buffer, const MediaSource::ReadOptions *options __unused) {
 
         if (mNumFramesOutput % 10 == 0) {
             fprintf(stderr, ".");
@@ -100,8 +100,12 @@
         // We don't care about the contents. we just test video encoder
         // Also, by skipping the content generation, we can return from
         // read() much faster.
-        //char x = (char)((double)rand() / RAND_MAX * 255);
-        //memset((*buffer)->data(), x, mSize);
+#if 0
+        // iterate through solid planes of color.
+        static unsigned char x = 0x60;
+        memset((*buffer)->data(), x, mSize);
+        x = x >= 0xa0 ? 0x60 : x + 1;
+#endif
         (*buffer)->set_range(0, mSize);
         (*buffer)->meta_data()->clear();
         (*buffer)->meta_data()->setInt64(
@@ -163,7 +167,7 @@
     int level = -1;        // Encoder specific default
     int profile = -1;      // Encoder specific default
     int codec = 0;
-    char *fileName = "/sdcard/output.mp4";
+    const char *fileName = "/sdcard/output.mp4";
     bool preferSoftwareCodec = false;
 
     android::ProcessState::self()->startThreadPool();
diff --git a/services/audiopolicy/AudioPolicyService.cpp b/services/audiopolicy/AudioPolicyService.cpp
index 4a708a0..918c25c 100644
--- a/services/audiopolicy/AudioPolicyService.cpp
+++ b/services/audiopolicy/AudioPolicyService.cpp
@@ -270,6 +270,10 @@
     if (!mAudioCommands.isEmpty()) {
         release_wake_lock(mName.string());
     }
+    for (size_t k=0; k < mAudioCommands.size(); k++) {
+        delete mAudioCommands[k]->mParam;
+        delete mAudioCommands[k];
+    }
     mAudioCommands.clear();
     delete mpToneGenerator;
 }
@@ -441,7 +445,7 @@
     ToneData *data = new ToneData();
     data->mType = type;
     data->mStream = stream;
-    command->mParam = (void *)data;
+    command->mParam = data;
     Mutex::Autolock _l(mLock);
     insertCommand_l(command);
     ALOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
@@ -542,7 +546,7 @@
     data->mIO = output;
     data->mStream = stream;
     data->mSession = session;
-    command->mParam = (void *)data;
+    command->mParam = data;
     Mutex::Autolock _l(mLock);
     insertCommand_l(command);
     ALOGV("AudioCommandThread() adding stop output %d", output);
@@ -555,7 +559,7 @@
     command->mCommand = RELEASE_OUTPUT;
     ReleaseOutputData *data = new ReleaseOutputData();
     data->mIO = output;
-    command->mParam = (void *)data;
+    command->mParam = data;
     Mutex::Autolock _l(mLock);
     insertCommand_l(command);
     ALOGV("AudioCommandThread() adding release output %d", output);
@@ -644,6 +648,10 @@
         for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
             if (mAudioCommands[k] == removedCommands[j]) {
                 ALOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
+                // for commands that are not filtered,
+                // command->mParam is deleted in threadLoop
+                delete mAudioCommands[k]->mParam;
+                delete mAudioCommands[k];
                 mAudioCommands.removeAt(k);
                 break;
             }
diff --git a/services/audiopolicy/AudioPolicyService.h b/services/audiopolicy/AudioPolicyService.h
index cdc90d0..28e3a4b 100644
--- a/services/audiopolicy/AudioPolicyService.h
+++ b/services/audiopolicy/AudioPolicyService.h
@@ -198,6 +198,8 @@
                     void        insertCommand_l(AudioCommand *command, int delayMs = 0);
 
     private:
+        class AudioCommandData;
+
         // descriptor for requested tone playback event
         class AudioCommand {
 
@@ -212,41 +214,48 @@
             Condition mCond; // condition for status return
             status_t mStatus; // command status
             bool mWaitStatus; // true if caller is waiting for status
-            void *mParam;     // command parameter (ToneData, VolumeData, ParametersData)
+            AudioCommandData *mParam;     // command specific parameter data
         };
 
-        class ToneData {
+        class AudioCommandData {
+        public:
+            virtual ~AudioCommandData() {}
+        protected:
+            AudioCommandData() {}
+        };
+
+        class ToneData : public AudioCommandData {
         public:
             ToneGenerator::tone_type mType; // tone type (START_TONE only)
             audio_stream_type_t mStream;    // stream type (START_TONE only)
         };
 
-        class VolumeData {
+        class VolumeData : public AudioCommandData {
         public:
             audio_stream_type_t mStream;
             float mVolume;
             audio_io_handle_t mIO;
         };
 
-        class ParametersData {
+        class ParametersData : public AudioCommandData {
         public:
             audio_io_handle_t mIO;
             String8 mKeyValuePairs;
         };
 
-        class VoiceVolumeData {
+        class VoiceVolumeData : public AudioCommandData {
         public:
             float mVolume;
         };
 
-        class StopOutputData {
+        class StopOutputData : public AudioCommandData {
         public:
             audio_io_handle_t mIO;
             audio_stream_type_t mStream;
             int mSession;
         };
 
-        class ReleaseOutputData {
+        class ReleaseOutputData : public AudioCommandData {
         public:
             audio_io_handle_t mIO;
         };
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index abfb602..7645a2a 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -397,7 +397,7 @@
                     "must be set to NULL in camera3_device::ops", __FUNCTION__);
             return INVALID_OPERATION;
         } else {
-            ALOGD("%s: Skipping NULL check for deprecated register_stream_buffers");
+            ALOGD("%s: Skipping NULL check for deprecated register_stream_buffers", __FUNCTION__);
         }
 
         return OK;