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 <binder/ProcessState.h>
18#include <media/mediarecorder.h>
19#include <media/stagefright/foundation/ADebug.h>
20#include <media/stagefright/AMRWriter.h>
21#include <media/stagefright/AudioPlayer.h>
22#include <media/stagefright/AudioSource.h>
23#include <media/stagefright/MediaDefs.h>
24#include <media/stagefright/MetaData.h>
25#include <media/stagefright/OMXClient.h>
26#include <media/stagefright/OMXCodec.h>
27#include "SineSource.h"
28
29using namespace android;
30
31static void usage(const char* name)
32{
33    fprintf(stderr, "Usage: %s [-d duration] [-m] [-w] [<output-file>]\n", name);
34    fprintf(stderr, "Encodes either a sine wave or microphone input to AMR format\n");
35    fprintf(stderr, "    -d    duration in seconds, default 5 seconds\n");
36    fprintf(stderr, "    -m    use microphone for input, default sine source\n");
37    fprintf(stderr, "    -w    use AMR wideband (default narrowband)\n");
38    fprintf(stderr, "    <output-file> output file for AMR encoding,"
39            " if unspecified, decode to speaker.\n");
40}
41
42int main(int argc, char* argv[])
43{
44    static const int channels = 1; // not permitted to be stereo now
45    unsigned duration = 5;
46    bool useMic = false;
47    bool outputWBAMR = false;
48    bool playToSpeaker = true;
49    const char* fileOut = NULL;
50    int ch;
51    while ((ch = getopt(argc, argv, "d:mw")) != -1) {
52        switch (ch) {
53        case 'd':
54            duration = atoi(optarg);
55            break;
56        case 'm':
57            useMic = true;
58            break;
59        case 'w':
60            outputWBAMR = true;
61            break;
62        default:
63            usage(argv[0]);
64            return -1;
65        }
66    }
67    argc -= optind;
68    argv += optind;
69    if (argc == 1) {
70        fileOut = argv[0];
71    }
72    const int32_t kSampleRate = outputWBAMR ? 16000 : 8000;
73    const int32_t kBitRate = outputWBAMR ? 16000 : 8000;
74
75    android::ProcessState::self()->startThreadPool();
76    OMXClient client;
77    CHECK_EQ(client.connect(), (status_t)OK);
78    sp<MediaSource> source;
79
80    if (useMic) {
81        // talk into the appropriate microphone for the duration
82        source = new AudioSource(
83                AUDIO_SOURCE_MIC,
84                kSampleRate,
85                channels);
86    } else {
87        // use a sine source at 500 hz.
88        source = new SineSource(kSampleRate, channels);
89    }
90
91    sp<MetaData> meta = new MetaData;
92    meta->setCString(
93            kKeyMIMEType,
94            outputWBAMR ? MEDIA_MIMETYPE_AUDIO_AMR_WB
95                    : MEDIA_MIMETYPE_AUDIO_AMR_NB);
96
97    meta->setInt32(kKeyChannelCount, channels);
98    meta->setInt32(kKeySampleRate, kSampleRate);
99    meta->setInt32(kKeyBitRate, kBitRate);
100    int32_t maxInputSize;
101    if (source->getFormat()->findInt32(kKeyMaxInputSize, &maxInputSize)) {
102        meta->setInt32(kKeyMaxInputSize, maxInputSize);
103    }
104
105    sp<MediaSource> encoder = OMXCodec::Create(
106            client.interface(),
107            meta, true /* createEncoder */,
108            source);
109
110    if (fileOut != NULL) {
111        // target file specified, write encoded AMR output
112        sp<AMRWriter> writer = new AMRWriter(fileOut);
113        writer->addSource(encoder);
114        writer->start();
115        sleep(duration);
116        writer->stop();
117    } else {
118        // otherwise decode to speaker
119        sp<MediaSource> decoder = OMXCodec::Create(
120                client.interface(),
121                meta, false /* createEncoder */,
122                encoder);
123
124        if (playToSpeaker) {
125            AudioPlayer *player = new AudioPlayer(NULL);
126            player->setSource(decoder);
127            player->start();
128            sleep(duration);
129            source->stop(); // must stop source otherwise delete player will hang
130            delete player; // there is no player->stop()...
131        } else {
132            CHECK_EQ(decoder->start(), (status_t)OK);
133            MediaBuffer* buffer;
134            while (decoder->read(&buffer) == OK) {
135                // do something with buffer (save it eventually?)
136                // need to stop after some count though...
137                putchar('.');
138                fflush(stdout);
139                buffer->release();
140                buffer = NULL;
141            }
142            CHECK_EQ(decoder->stop(), (status_t)OK);
143        }
144    }
145
146    return 0;
147}
148