| /* |
| * 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 <utils/Log.h> |
| |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <fcntl.h> |
| |
| #include <utils/String16.h> |
| |
| #include <android/content/AttributionSourceState.h> |
| #include <binder/ProcessState.h> |
| #include <media/mediarecorder.h> |
| #include <media/stagefright/foundation/ADebug.h> |
| #include <media/stagefright/foundation/AMessage.h> |
| #include <media/stagefright/AMRWriter.h> |
| #include <media/stagefright/AudioSource.h> |
| #include <media/stagefright/MediaCodecSource.h> |
| #include <media/stagefright/MediaDefs.h> |
| #include <media/stagefright/SimpleDecodingSource.h> |
| #include "AudioPlayer.h" |
| #include "SineSource.h" |
| |
| using namespace android; |
| |
| using content::AttributionSourceState; |
| |
| static void usage(const char* name) |
| { |
| fprintf(stderr, "Usage: %s [-d du.ration] [-m] [-w] [-N name] [<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, " -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> 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 <output file>\n"); |
| usage(argv[0]); |
| return -1; |
| } |
| int32_t sampleRate = !name.empty() ? 44100 : outputWBAMR ? 16000 : 8000; |
| int32_t bitRate = sampleRate; |
| |
| android::ProcessState::self()->startThreadPool(); |
| sp<MediaSource> source; |
| |
| if (useMic) { |
| // talk into the appropriate microphone for the duration |
| audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER; |
| attr.source = AUDIO_SOURCE_MIC; |
| |
| // TODO b/182392769: use attribution source util |
| source = new AudioSource( |
| &attr, |
| AttributionSourceState(), |
| sampleRate, |
| channels); |
| } else { |
| // use a sine source at 500 hz. |
| source = new SineSource(sampleRate, channels); |
| } |
| |
| sp<AMessage> 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<ALooper> looper = new ALooper; |
| looper->setName("audioloop"); |
| looper->start(); |
| |
| sp<MediaSource> 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<AMRWriter> writer = new AMRWriter(fd); |
| close(fd); |
| writer->addSource(encoder); |
| writer->start(); |
| sleep(duration); |
| writer->stop(); |
| } else { |
| // otherwise decode to speaker |
| sp<MediaSource> 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; |
| } |