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