1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <sys/types.h> 18 #include <sys/stat.h> 19 #include <fcntl.h> 20 21 #include <utils/String16.h> 22 23 #include <binder/ProcessState.h> 24 #include <media/mediarecorder.h> 25 #include <media/stagefright/foundation/ADebug.h> 26 #include <media/stagefright/foundation/AMessage.h> 27 #include <media/stagefright/AMRWriter.h> 28 #include <media/stagefright/AudioPlayer.h> 29 #include <media/stagefright/AudioSource.h> 30 #include <media/stagefright/MediaCodecSource.h> 31 #include <media/stagefright/MediaDefs.h> 32 #include <media/stagefright/MetaData.h> 33 #include <media/stagefright/SimpleDecodingSource.h> 34 #include "SineSource.h" 35 36 using namespace android; 37 38 static void usage(const char* name) 39 { 40 fprintf(stderr, "Usage: %s [-d du.ration] [-m] [-w] [<output-file>]\n", name); 41 fprintf(stderr, "Encodes either a sine wave or microphone input to AMR format\n"); 42 fprintf(stderr, " -d duration in seconds, default 5 seconds\n"); 43 fprintf(stderr, " -m use microphone for input, default sine source\n"); 44 fprintf(stderr, " -w use AMR wideband (default narrowband)\n"); 45 fprintf(stderr, " <output-file> output file for AMR encoding," 46 " if unspecified, decode to speaker.\n"); 47 } 48 49 int main(int argc, char* argv[]) 50 { 51 static const int channels = 1; // not permitted to be stereo now 52 unsigned duration = 5; 53 bool useMic = false; 54 bool outputWBAMR = false; 55 bool playToSpeaker = true; 56 const char* fileOut = NULL; 57 int ch; 58 while ((ch = getopt(argc, argv, "d:mw")) != -1) { 59 switch (ch) { 60 case 'd': 61 duration = atoi(optarg); 62 break; 63 case 'm': 64 useMic = true; 65 break; 66 case 'w': 67 outputWBAMR = true; 68 break; 69 default: 70 usage(argv[0]); 71 return -1; 72 } 73 } 74 argc -= optind; 75 argv += optind; 76 if (argc == 1) { 77 fileOut = argv[0]; 78 } 79 const int32_t kSampleRate = outputWBAMR ? 16000 : 8000; 80 const int32_t kBitRate = outputWBAMR ? 16000 : 8000; 81 82 android::ProcessState::self()->startThreadPool(); 83 sp<MediaSource> source; 84 85 if (useMic) { 86 // talk into the appropriate microphone for the duration 87 source = new AudioSource( 88 AUDIO_SOURCE_MIC, 89 String16(), 90 kSampleRate, 91 channels); 92 } else { 93 // use a sine source at 500 hz. 94 source = new SineSource(kSampleRate, channels); 95 } 96 97 sp<AMessage> meta = new AMessage; 98 meta->setString( 99 "mime", 100 outputWBAMR ? MEDIA_MIMETYPE_AUDIO_AMR_WB 101 : MEDIA_MIMETYPE_AUDIO_AMR_NB); 102 103 meta->setInt32("channel-count", channels); 104 meta->setInt32("sample-rate", kSampleRate); 105 meta->setInt32("bitrate", kBitRate); 106 int32_t maxInputSize; 107 if (source->getFormat()->findInt32(kKeyMaxInputSize, &maxInputSize)) { 108 meta->setInt32("max-input-size", maxInputSize); 109 } 110 111 sp<ALooper> looper = new ALooper; 112 looper->setName("audioloop"); 113 looper->start(); 114 115 sp<IMediaSource> encoder = MediaCodecSource::Create(looper, meta, source); 116 117 if (fileOut != NULL) { 118 // target file specified, write encoded AMR output 119 int fd = open(fileOut, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR); 120 if (fd < 0) { 121 return 1; 122 } 123 sp<AMRWriter> writer = new AMRWriter(fd); 124 close(fd); 125 writer->addSource(encoder); 126 writer->start(); 127 sleep(duration); 128 writer->stop(); 129 } else { 130 // otherwise decode to speaker 131 sp<IMediaSource> decoder = SimpleDecodingSource::Create(encoder); 132 133 if (playToSpeaker) { 134 AudioPlayer *player = new AudioPlayer(NULL); 135 player->setSource(decoder); 136 player->start(); 137 sleep(duration); 138 139 decoder.clear(); // must clear |decoder| otherwise delete player will hang. 140 delete player; // there is no player->stop()... 141 } else { 142 CHECK_EQ(decoder->start(), (status_t)OK); 143 MediaBuffer* buffer; 144 while (decoder->read(&buffer) == OK) { 145 // do something with buffer (save it eventually?) 146 // need to stop after some count though... 147 putchar('.'); 148 fflush(stdout); 149 buffer->release(); 150 buffer = NULL; 151 } 152 CHECK_EQ(decoder->stop(), (status_t)OK); 153 } 154 } 155 156 return 0; 157 } 158