1.AudioTrack:: write ()

Frameworks/base/media/java/android/media/AudioTrack.java

public intwrite(byte[] audioData, int offsetInBytes, int sizeInBytes) {

if (mState == STATE_UNINITIALIZED) {

return ERROR_INVALID_OPERATION;

}

if ( (audioData == null) ||(offsetInBytes < 0 ) || (sizeInBytes < 0)

|| (offsetInBytes + sizeInBytes< 0) // detect integer overflow

|| (offsetInBytes + sizeInBytes >audioData.length)) {

return ERROR_BAD_VALUE;

}

int ret =native_write_byte(audioData, offsetInBytes, sizeInBytes, mAudioFormat);

if ((mDataLoadMode == MODE_STATIC)

&& (mState ==STATE_NO_STATIC_DATA)

&& (ret > 0)) {

// benign race with respect toother APIs that read mState

mState = STATE_INITIALIZED;

}

return ret;

}

public int write(short[] audioData, intoffsetInShorts, int sizeInShorts) {

if (mState == STATE_UNINITIALIZED) {

return ERROR_INVALID_OPERATION;

}

if ( (audioData == null) ||(offsetInShorts < 0 ) || (sizeInShorts < 0)

|| (offsetInShorts +sizeInShorts < 0) // detect integeroverflow

|| (offsetInShorts +sizeInShorts > audioData.length)) {

return ERROR_BAD_VALUE;

}

int ret =native_write_short(audioData, offsetInShorts, sizeInShorts, mAudioFormat);

if ((mDataLoadMode == MODE_STATIC)

&& (mState ==STATE_NO_STATIC_DATA)

&& (ret > 0)) {

// benign race with respect toother APIs that read mState

mState = STATE_INITIALIZED;

}

return ret;

}

2.android_media_AudioTrack_native_write_short ()

frameworks/base/core/jni/android_media_AudioTrack.cpp

static jintandroid_media_AudioTrack_native_write_byte(JNIEnv *env, jobject thiz,

jbyteArrayjavaAudioData,

jint offsetInBytes, jint sizeInBytes,

jint javaAudioFormat) {

//ALOGV("android_media_AudioTrack_native_write_byte(offset=%d,sizeInBytes=%d) called",

//offsetInBytes, sizeInBytes);

sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);

// JAVA 环境中得到本地 AudioTrack对象

if (lpTrack == NULL) {

jniThrowException(env,"java/lang/IllegalStateException",

"Unable to retrieve AudioTrackpointer for write()");

return 0;

}

// get the pointer for the audio data fromthe java array

// NOTE: We may useGetPrimitiveArrayCritical() when the JNI implementation changes in such

// a way that it becomes much moreefficient. When doing so, we will have to prevent the

// AudioSystem callback to be called whilein critical section (in case of media server

// process crash for instance)

jbyte* cAudioData = NULL;

if (javaAudioData) {

cAudioData = (jbyte*)env->GetByteArrayElements(javaAudioData, NULL);

if (cAudioData == NULL) {

ALOGE("Error retrieving sourceof audio data to play, can't play");

return 0; // out of memory or no datato load

}

} else {

ALOGE("NULL java array of audiodata to play, can't play");

return 0;

}

jint written =writeToTrack(lpTrack, javaAudioFormat, cAudioData, offsetInBytes, sizeInBytes);

env->ReleaseByteArrayElements(javaAudioData,cAudioData, 0);

//ALOGV("write wrote %d (tried %d)bytes in the native AudioTrack with offset %d",

//(int)written, (int)(sizeInBytes), (int)offsetInBytes);

return written;

}

static jintandroid_media_AudioTrack_native_write_short(JNIEnv *env, jobject thiz,

jshortArray javaAudioData,

jint offsetInShorts, jint sizeInShorts,

jintjavaAudioFormat) {

return(android_media_AudioTrack_native_write_byte(env, thiz,

(jbyteArray) javaAudioData,

offsetInShorts*2, sizeInShorts*2,

javaAudioFormat)

/ 2);

}

3.writeToTrack ()

frameworks/base/core/jni/android_media_AudioTrack.cpp

jintwriteToTrack(const sp<AudioTrack>& track, jint audioFormat, jbyte*data,

jint offsetInBytes, jintsizeInBytes) {

// give the data to the native AudioTrackobject (the data starts at the offset)

ssize_t written = 0;

// regular write() or copy the data to theAudioTrack's shared memory?

if (track->sharedBuffer() == 0) {

// stream mode

// 调用本地的write方法

written =track->write(data + offsetInBytes, sizeInBytes);

} else {// static mode

if (audioFormat ==javaAudioTrackFields.PCM16) {

// writing to shared memory, checkfor capacity

if ((size_t)sizeInBytes >track->sharedBuffer()->size()) {

sizeInBytes =track->sharedBuffer()->size();

}

memcpy(track->sharedBuffer()->pointer(), data + offsetInBytes,sizeInBytes);

written = sizeInBytes;

} else if (audioFormat ==javaAudioTrackFields.PCM8) {

// data contains 8bit data we needto expand to 16bit before copying

// to the shared memory

// writing to shared memory, checkfor capacity,

// note that input data will occupy2X the input space due to 8 to 16bit conversion

if (((size_t)sizeInBytes)*2 >track->sharedBuffer()->size()) {

sizeInBytes =track->sharedBuffer()->size() / 2;

}

int count = sizeInBytes;

int16_t *dst = (int16_t*)track->sharedBuffer()->pointer();

const int8_t *src = (const int8_t*)(data + offsetInBytes);

while (count--) {

*dst++ = (int16_t)(*src++^0x80)<< 8;

}

// even though we wrote2*sizeInBytes, we only report sizeInBytes as written to hide

// the 8bit mixer restriction fromthe user of this function

written = sizeInBytes;

}

}

return written;

}

4.说明

一块共享内存

一个控制结构

通过共享内存传递数据

通过控制结构协调生产者和消费者线程

5.AudioTrack::write()

Frameworks/av/media/libmedia/AudioTrack.cpp

ssize_t AudioTrack::write(const void* buffer, size_t userSize)

{

if (mSharedBuffer != 0 ||mIsTimed) {

returnINVALID_OPERATION;

}

if (ssize_t(userSize) <0) {

// Sanity-check: useris most-likely passing an error code, and it would

// make the returnvalue ambiguous (actualSize vs error).

ALOGE("AudioTrack::write(buffer=%p, size=%u (%d)",

buffer,userSize, userSize);

return BAD_VALUE;

}

ALOGV("write %p: %dbytes, mActive=%d", this, userSize, mActive);

if (userSize == 0) {

return 0;

}

// acquire a strongreference on the IMemory and IAudioTrack so that they cannot be destroyed

// while we are accessing the cblk

mLock.lock();

sp<IAudioTrack> audioTrack = mAudioTrack;

sp<IMemory> iMem = mCblkMemory;

mLock.unlock();

// since mLock is unlockedthe IAudioTrack and shared memory may be re-created,

// so all cblk referencesmight still refer to old shared memory, but that should be benign

ssize_t written = 0;

const int8_t *src = (constint8_t *)buffer;

Buffer audioBuffer;

size_t frameSz =frameSize();

do {

audioBuffer.frameCount= userSize/frameSz;

status_t err = obtainBuffer(&audioBuffer, -1);

if (err < 0) {

// out of buffers,return #bytes written

if (err ==status_t(NO_MORE_BUFFERS)) {

break;

}

returnssize_t(err);

}

size_t toWrite;

if (mFormat ==AUDIO_FORMAT_PCM_8_BIT && !(mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) {

// Divide capacityby 2 to take expansion into account

toWrite =audioBuffer.size>>1;

memcpy_to_i16_from_u8(audioBuffer.i16, (const uint8_t *) src, toWrite);

} else {

toWrite =audioBuffer.size;

memcpy(audioBuffer.i8, src, toWrite);

}

src += toWrite;

userSize -= toWrite;

written += toWrite;

releaseBuffer(&audioBuffer);

} while (userSize >=frameSz);

return written;

}

更多相关文章

  1. android系统信息,cpu、内存、电池等
  2. Android 开发 Eclipse 内存调整
  3. android: MapView加载多个 overlay 内存溢出
  4. Android Studio之内存分析
  5. android 自带的contacts2.db数据库表结构脚本
  6. Android安全模型之Android安全机制(内存管理)
  7. Android内存泄漏查找

随机推荐

  1. Android 如何利用proc有上层想kernel写文
  2. Java中的ClassLoader 动态加载机制
  3. Android:自定义滚动边缘(EdgeEffect)效果
  4. Android四大布局及属性
  5. android使用traceView进行性能测试
  6. android:如果手机安装了app则打开一个acti
  7. Android 内存泄漏的检测和解决
  8. 石家庄android培训哪家实力强、就业率高?
  9. MIUI 系统 BUG,Android 调用相机崩溃?将拍
  10. Android硬件编解码与软件编解码