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