• 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 <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