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