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 #define LOG_NDEBUG 0
18 #define LOG_TAG "audioloop"
19 #include <utils/Log.h>
20
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24
25 #include <utils/String16.h>
26
27 #include <android/content/AttributionSourceState.h>
28 #include <binder/ProcessState.h>
29 #include <media/mediarecorder.h>
30 #include <media/stagefright/foundation/ADebug.h>
31 #include <media/stagefright/foundation/AMessage.h>
32 #include <media/stagefright/AMRWriter.h>
33 #include <media/stagefright/AudioSource.h>
34 #include <media/stagefright/MediaCodecSource.h>
35 #include <media/stagefright/MediaDefs.h>
36 #include <media/stagefright/SimpleDecodingSource.h>
37 #include "AudioPlayer.h"
38 #include "SineSource.h"
39
40 using namespace android;
41
42 using content::AttributionSourceState;
43
usage(const char * name)44 static void usage(const char* name)
45 {
46 fprintf(stderr, "Usage: %s [-d du.ration] [-m] [-w] [-N name] [<output-file>]\n", name);
47 fprintf(stderr, "Encodes either a sine wave or microphone input to AMR format\n");
48 fprintf(stderr, " -d duration in seconds, default 5 seconds\n");
49 fprintf(stderr, " -m use microphone for input, default sine source\n");
50 fprintf(stderr, " -w use AMR wideband (default narrowband)\n");
51 fprintf(stderr, " -N name of the encoder; must be set with -M\n");
52 fprintf(stderr, " -M media type of the encoder; must be set with -N\n");
53 fprintf(stderr, " <output-file> output file for AMR encoding,"
54 " if unspecified, decode to speaker.\n");
55 }
56
main(int argc,char * argv[])57 int main(int argc, char* argv[])
58 {
59 static const int channels = 1; // not permitted to be stereo now
60 unsigned duration = 5;
61 bool useMic = false;
62 bool outputWBAMR = false;
63 bool playToSpeaker = true;
64 const char* fileOut = NULL;
65 AString name;
66 AString mediaType;
67 int ch;
68 while ((ch = getopt(argc, argv, "d:mwN:M:")) != -1) {
69 switch (ch) {
70 case 'd':
71 duration = atoi(optarg);
72 break;
73 case 'm':
74 useMic = true;
75 break;
76 case 'w':
77 outputWBAMR = true;
78 break;
79 case 'N':
80 name.setTo(optarg);
81 break;
82 case 'M':
83 mediaType.setTo(optarg);
84 break;
85 default:
86 usage(argv[0]);
87 return -1;
88 }
89 }
90 argc -= optind;
91 argv += optind;
92 if (argc == 1) {
93 fileOut = argv[0];
94 }
95 if ((name.empty() && !mediaType.empty()) || (!name.empty() && mediaType.empty())) {
96 fprintf(stderr, "-N and -M must be set together\n");
97 usage(argv[0]);
98 return -1;
99 }
100 if (!name.empty() && fileOut != NULL) {
101 fprintf(stderr, "-N and -M cannot be used with <output file>\n");
102 usage(argv[0]);
103 return -1;
104 }
105 int32_t sampleRate = !name.empty() ? 44100 : outputWBAMR ? 16000 : 8000;
106 int32_t bitRate = sampleRate;
107
108 android::ProcessState::self()->startThreadPool();
109 sp<MediaSource> source;
110
111 if (useMic) {
112 // talk into the appropriate microphone for the duration
113 audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
114 attr.source = AUDIO_SOURCE_MIC;
115
116 // TODO b/182392769: use attribution source util
117 source = new AudioSource(
118 &attr,
119 AttributionSourceState(),
120 sampleRate,
121 channels);
122 } else {
123 // use a sine source at 500 hz.
124 source = new SineSource(sampleRate, channels);
125 }
126
127 sp<AMessage> meta = new AMessage;
128 if (name.empty()) {
129 meta->setString(
130 "mime",
131 outputWBAMR ? MEDIA_MIMETYPE_AUDIO_AMR_WB
132 : MEDIA_MIMETYPE_AUDIO_AMR_NB);
133 } else {
134 meta->setString("mime", mediaType);
135 meta->setString("testing-name", name);
136 }
137
138 meta->setInt32("channel-count", channels);
139 meta->setInt32("sample-rate", sampleRate);
140 meta->setInt32("bitrate", bitRate);
141 int32_t maxInputSize;
142 if (source->getFormat()->findInt32(kKeyMaxInputSize, &maxInputSize)) {
143 meta->setInt32("max-input-size", maxInputSize);
144 }
145
146 sp<ALooper> looper = new ALooper;
147 looper->setName("audioloop");
148 looper->start();
149
150 sp<MediaSource> encoder = MediaCodecSource::Create(looper, meta, source);
151
152 if (fileOut != NULL) {
153 // target file specified, write encoded AMR output
154 int fd = open(fileOut, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
155 if (fd < 0) {
156 return 1;
157 }
158 sp<AMRWriter> writer = new AMRWriter(fd);
159 close(fd);
160 writer->addSource(encoder);
161 writer->start();
162 sleep(duration);
163 writer->stop();
164 } else {
165 // otherwise decode to speaker
166 sp<MediaSource> decoder = SimpleDecodingSource::Create(encoder);
167
168 if (playToSpeaker) {
169 AudioPlayer player(NULL);
170 player.setSource(decoder);
171 player.start();
172 sleep(duration);
173
174 ALOGI("Line: %d", __LINE__);
175 decoder.clear(); // must clear |decoder| otherwise delete player will hang.
176 ALOGI("Line: %d", __LINE__);
177 } else {
178 CHECK_EQ(decoder->start(), (status_t)OK);
179 MediaBufferBase* buffer;
180 while (decoder->read(&buffer) == OK) {
181 // do something with buffer (save it eventually?)
182 // need to stop after some count though...
183 putchar('.');
184 fflush(stdout);
185 buffer->release();
186 buffer = NULL;
187 }
188 CHECK_EQ(decoder->stop(), (status_t)OK);
189 }
190 ALOGI("Line: %d", __LINE__);
191 }
192
193 return 0;
194 }
195