1 /*
2 * AudioRecord.cpp
3 *
4 * Copyright (C) 2009-2012 Belledonne Communications, Grenoble, France
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 #include "mediastreamer2/mscommon.h"
22 #include "AudioRecord.h"
23 #include "AudioTrack.h"
24
25 namespace fake_android{
26
27
AudioRecord(audio_source_t inputSource,uint32_t sampleRate,audio_format_t format,uint32_t channelMask,int frameCount,callback_t cbf,void * user,int notificationFrames,int sessionId,transfer_type transferType,audio_input_flags_t flags)28 AudioRecord::AudioRecord(audio_source_t inputSource,
29 uint32_t sampleRate,
30 audio_format_t format,
31 uint32_t channelMask,
32 int frameCount,
33 callback_t cbf,
34 void* user ,
35 int notificationFrames,
36 int sessionId,
37 transfer_type transferType,
38 audio_input_flags_t flags){
39 mThis=new uint8_t[AudioRecordImpl::sObjSize];
40 memset(mThis,0,AudioRecordImpl::sObjSize);
41 mImpl=AudioRecordImpl::get();
42 mSessionId=-1;
43
44 if (mImpl->mCtorBeforeAPI17.isFound()) {
45 mImpl->mCtorBeforeAPI17.invoke(mThis,inputSource,sampleRate,format,channelMask,frameCount,(record_flags)0,cbf,user,notificationFrames,sessionId);
46 } else {
47 /* The flags parameter was removed in Android 4.2 (API level 17). */
48 if (AudioTrackImpl::get()->mSdkVersion>=19 && sessionId==0){
49 sessionId=AudioSystem::newAudioSessionId(); /*we allocate a sessionID by ourselves because otherwise it is not accessible
50 because the method is inlined*/
51 if (sessionId==-1){
52 sessionId=0;
53 }else mSessionId=sessionId;
54 }
55 mImpl->mCtor.invoke(mThis,inputSource,sampleRate,format,channelMask,frameCount,cbf,user,notificationFrames,sessionId,transferType,flags);
56 }
57 //dumpMemory(mThis,AudioRecordImpl::sObjSize);
58 }
59
AudioRecord()60 AudioRecord::AudioRecord(){
61 mThis=new uint8_t[AudioRecordImpl::sObjSize];
62 memset(mThis,0,AudioRecordImpl::sObjSize);
63 mImpl=AudioRecordImpl::get();
64 mImpl->mDefaultCtor.invoke(mThis);
65 }
66
67
68 /* Terminates the AudioRecord and unregisters it from AudioFlinger.
69 * Also destroys all resources assotiated with the AudioRecord.
70 */
~AudioRecord()71 AudioRecord::~AudioRecord(){
72 }
73
74
start(AudioSystem::sync_event_t event,int triggerSession)75 status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession){
76 ms_message("starting audio record on [%p]",mThis);
77 return mImpl->mStart.invoke(mThis,event,triggerSession);
78 }
79
stop()80 status_t AudioRecord::stop(){
81 return mImpl->mStop.invoke(mThis);
82 }
83
initCheck() const84 status_t AudioRecord::initCheck()const{
85 return mImpl->mInitCheck.invoke(mThis);
86 }
87
getMinFrameCount(int * frameCount,uint32_t sampleRate,audio_format_t format,int channelCount)88 status_t AudioRecord::getMinFrameCount(int* frameCount,
89 uint32_t sampleRate,
90 audio_format_t format,
91 int channelCount)
92 {
93 if (AudioRecordImpl::get()->mGetMinFrameCount.isFound()){
94 return AudioRecordImpl::get()->mGetMinFrameCount.invoke(frameCount,sampleRate,format,channelCount);
95 }else{
96 //this method didn't existed in 2.2
97 //Use hardcoded values instead (1024 frames at 8khz)
98 *frameCount=(1024*channelCount*sampleRate)/8000;
99 return 0;
100 }
101 }
102
getInput() const103 audio_io_handle_t AudioRecord::getInput() const{
104 //return mImpl->mGetInput.invoke(mThis);
105 ms_error("AudioRecord::getInput() not implemented.");
106 return 0;
107 }
108
getSessionId() const109 int AudioRecord::getSessionId() const{
110 if (mImpl->mGetSessionId.isFound()){
111 return mImpl->mGetSessionId.invoke(mThis);
112 }else if (mSessionId!=-1)
113 return mSessionId;
114 ms_warning("AudioRecord::getSessionId() not available");
115 return -1;
116 }
117
readBuffer(const void * p_info,Buffer * buffer)118 void AudioRecord::readBuffer(const void *p_info, Buffer *buffer){
119 if (AudioSystemImpl::get()->mApi18){
120 *buffer=*(const Buffer*)p_info;
121 }else{
122 const OldBuffer *oldbuf=(const OldBuffer*)p_info;
123 buffer->frameCount=oldbuf->frameCount;
124 buffer->size=oldbuf->size;
125 buffer->raw=oldbuf->raw;
126 }
127 }
128
isRefCounted() const129 bool AudioRecord::isRefCounted()const{
130 return mImpl->mUseRefcount;
131 }
132
destroy() const133 void AudioRecord::destroy()const{
134 mImpl->mDtor.invoke(mThis);
135 delete []mThis;
136 }
137
getRealThis() const138 void *AudioRecord::getRealThis()const{
139 void *ret= mThis + mImpl->mRefBaseOffset;
140 return ret;
141 }
142
init(Library * lib)143 bool AudioRecordImpl::init(Library *lib){
144 bool fail=false;
145
146 if (!sImpl){
147 AudioRecordImpl *impl=new AudioRecordImpl(lib);
148 if (!impl->mCtorBeforeAPI17.isFound() && !impl->mCtor.isFound()) {
149 fail=true;
150 ms_error("AudioRecord::AudioRecord(...) not found.");
151 }
152 if (!impl->mDtor.isFound()) {
153 fail=true;
154 ms_error("AudioRecord::~AudioRecord() dtor not found.");
155 }
156 if (!impl->mInitCheck.isFound()) {
157 ms_warning("AudioRecord::initCheck() not found (normal on Android 4.4)");
158 }
159 if (!impl->mStop.isFound()) {
160 fail=true;
161 ms_error("AudioRecord::stop() not found.");
162 }
163 if (!impl->mStart.isFound()) {
164 fail=true;
165 ms_error("AudioRecord::start() not found.");
166 }
167 if (impl->mApiVersion>=19 && !impl->mDefaultCtor.isFound()){
168 fail=true;
169 ms_error("AudioRecord::AudioRecord() not found.");
170 }
171 if (fail){
172 delete impl;
173 return false;
174 }
175 sImpl=impl;
176 if (impl->mApiVersion>=19){
177 AudioRecord *test=new AudioRecord();
178 //dumpMemory(test->getRealThis(),AudioRecordImpl::sObjSize);
179 if (findRefbaseOffset(test->getRealThis(),AudioRecordImpl::sObjSize)>(ptrdiff_t)sizeof(void*)){
180 ms_message("AudioRecord does not need refcounting despite it is 4.4");
181 impl->mUseRefcount=false;
182 }else{
183 ms_message("AudioRecord needs refcounting.");
184 impl->mUseRefcount=true;
185 }
186 sp<AudioRecord> st(test);
187 }
188 }
189 return true;
190 }
191
192 AudioRecordImpl *AudioRecordImpl::sImpl=NULL;
193
AudioRecordImpl(Library * lib)194 AudioRecordImpl::AudioRecordImpl(Library *lib) :
195 // By default, try to load Android 2.3 symbols
196 mCtorBeforeAPI17(lib,"_ZN7android11AudioRecordC1EijijijPFviPvS1_ES1_ii"),
197 mCtor(lib, "_ZN7android11AudioRecordC1E14audio_source_tj14audio_format_tjiPFviPvS3_ES3_iiNS0_13transfer_typeE19audio_input_flags_t"), // 4.4 symbol
198 mDtor(lib,"_ZN7android11AudioRecordD1Ev"),
199 mDefaultCtor(lib,"_ZN7android11AudioRecordC1Ev"),
200 mInitCheck(lib,"_ZNK7android11AudioRecord9initCheckEv"),
201 mStop(lib,"_ZN7android11AudioRecord4stopEv"),
202 mStart(lib,"_ZN7android11AudioRecord5startEv"),
203 mGetMinFrameCount(lib,"_ZN7android11AudioRecord16getMinFrameCountEPijii"),
204 mGetSessionId(lib,"_ZNK7android11AudioRecord12getSessionIdEv")
205 {
206 mApiVersion=0;
207 mUseRefcount=false;
208 mRefBaseOffset=0;
209 if (!mCtor.isFound()){
210 // Try some Android 2.2 symbols if not found
211 if (!mCtorBeforeAPI17.isFound()) {
212 mCtorBeforeAPI17.load(lib,"_ZN7android11AudioRecordC1EijijijPFviPvS1_ES1_i");
213 }
214 // Then try some Android 4.1 symbols if still not found
215 if (!mCtorBeforeAPI17.isFound()) {
216 mCtorBeforeAPI17.load(lib,"_ZN7android11AudioRecordC1E14audio_source_tj14audio_format_tjiNS0_12record_flagsEPFviPvS4_ES4_ii");
217 }
218 // Try to load Android 4.2 constructor
219 if (!mCtorBeforeAPI17.isFound()) {
220 mCtor.load(lib,"_ZN7android11AudioRecordC1E14audio_source_tj14audio_format_tjiPFviPvS3_ES3_ii");
221 }
222 // 5.0 constructor
223 if (!mCtor.isFound()){
224 mCtor.load(lib,"_ZN7android11AudioRecordC1E14audio_source_tj14audio_format_tjjPFviPvS3_ES3_jiNS0_13transfer_typeE19audio_input_flags_t");
225 mApiVersion=21;
226 }
227 }else {
228 mApiVersion=19;
229 }
230
231 if (!mStart.isFound()) {
232 mStart.load(lib,"_ZN7android11AudioRecord5startENS_11AudioSystem12sync_event_tEi");
233 }
234 if (!mGetMinFrameCount.isFound()) {
235 mGetMinFrameCount.load(lib, "_ZN7android11AudioRecord16getMinFrameCountEPij14audio_format_ti");
236 }
237
238 // Then try some Android 4.2 symbols if still not found
239 if (!mGetMinFrameCount.isFound()) {
240 mGetMinFrameCount.load(lib, "_ZN7android11AudioRecord16getMinFrameCountEPij14audio_format_tj");
241 }
242 }
243
244
245 }//end of namespace
246