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