/* * 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. */ #define LOG_NDEBUG 0 #define LOG_TAG "audioloop" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "SineSource.h" using namespace android; static void usage(const char* name) { fprintf(stderr, "Usage: %s [-d du.ration] [-m] [-w] [-N name] []\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, " -N name of the encoder; must be set with -M\n"); fprintf(stderr, " -M media type of the encoder; must be set with -N\n"); fprintf(stderr, " 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; AString name; AString mediaType; int ch; while ((ch = getopt(argc, argv, "d:mwN:M:")) != -1) { switch (ch) { case 'd': duration = atoi(optarg); break; case 'm': useMic = true; break; case 'w': outputWBAMR = true; break; case 'N': name.setTo(optarg); break; case 'M': mediaType.setTo(optarg); break; default: usage(argv[0]); return -1; } } argc -= optind; argv += optind; if (argc == 1) { fileOut = argv[0]; } if ((name.empty() && !mediaType.empty()) || (!name.empty() && mediaType.empty())) { fprintf(stderr, "-N and -M must be set together\n"); usage(argv[0]); return -1; } if (!name.empty() && fileOut != NULL) { fprintf(stderr, "-N and -M cannot be used with \n"); usage(argv[0]); return -1; } int32_t sampleRate = !name.empty() ? 44100 : outputWBAMR ? 16000 : 8000; int32_t bitRate = sampleRate; android::ProcessState::self()->startThreadPool(); sp source; if (useMic) { // talk into the appropriate microphone for the duration source = new AudioSource( AUDIO_SOURCE_MIC, String16(), sampleRate, channels); } else { // use a sine source at 500 hz. source = new SineSource(sampleRate, channels); } sp meta = new AMessage; if (name.empty()) { meta->setString( "mime", outputWBAMR ? MEDIA_MIMETYPE_AUDIO_AMR_WB : MEDIA_MIMETYPE_AUDIO_AMR_NB); } else { meta->setString("mime", mediaType); meta->setString("testing-name", name); } meta->setInt32("channel-count", channels); meta->setInt32("sample-rate", sampleRate); meta->setInt32("bitrate", bitRate); int32_t maxInputSize; if (source->getFormat()->findInt32(kKeyMaxInputSize, &maxInputSize)) { meta->setInt32("max-input-size", maxInputSize); } sp looper = new ALooper; looper->setName("audioloop"); looper->start(); sp encoder = MediaCodecSource::Create(looper, meta, source); if (fileOut != NULL) { // target file specified, write encoded AMR output int fd = open(fileOut, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR); if (fd < 0) { return 1; } sp writer = new AMRWriter(fd); close(fd); writer->addSource(encoder); writer->start(); sleep(duration); writer->stop(); } else { // otherwise decode to speaker sp decoder = SimpleDecodingSource::Create(encoder); if (playToSpeaker) { AudioPlayer player(NULL); player.setSource(decoder); player.start(); sleep(duration); ALOGI("Line: %d", __LINE__); decoder.clear(); // must clear |decoder| otherwise delete player will hang. ALOGI("Line: %d", __LINE__); } else { CHECK_EQ(decoder->start(), (status_t)OK); MediaBufferBase* 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); } ALOGI("Line: %d", __LINE__); } return 0; }