之前我们看过get position,今天来看看set position。
*****************************************源码*************************************************
//Test case 3: setPlaybackHeadPosition() on paused track
@LargeTest
public void testSetPlaybackHeadPositionPaused() throws Exception {
// constants for test
final String TEST_NAME = "testSetPlaybackHeadPositionPaused";
final int TEST_SR = 22050;
final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
final int TEST_MODE = AudioTrack.MODE_STREAM;
final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
//-------- initialization --------------
int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT,
2*minBuffSize, TEST_MODE);
byte data[] = new byte[minBuffSize];
//-------- test --------------
assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
track.write(data, 0, data.length);
track.write(data, 0, data.length);
track.play();
track.pause();
assumeTrue(TEST_NAME, track.getPlayState() == AudioTrack.PLAYSTATE_PAUSED);
assertTrue(TEST_NAME, track.setPlaybackHeadPosition(10) == AudioTrack.SUCCESS);
//-------- tear down --------------
track.release();
}
**********************************************************************************************
源码路径:
frameworks\base\media\tests\mediaframeworktest\src\com\android\mediaframeworktest\functional\MediaAudioTrackTest.java
#######################说明################################
//Test case 3: setPlaybackHeadPosition() on paused track
@LargeTest
public void testSetPlaybackHeadPositionPaused() throws Exception {
// constants for test
final String TEST_NAME = "testSetPlaybackHeadPositionPaused";
final int TEST_SR = 22050;
final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
final int TEST_MODE = AudioTrack.MODE_STREAM;
final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
//-------- initialization --------------
int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT,
2*minBuffSize, TEST_MODE);
byte data[] = new byte[minBuffSize];
//-------- test --------------
assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
track.write(data, 0, data.length);
track.write(data, 0, data.length);
track.play();
track.pause();
assumeTrue(TEST_NAME, track.getPlayState() == AudioTrack.PLAYSTATE_PAUSED);
assertTrue(TEST_NAME, track.setPlaybackHeadPosition(10) == AudioTrack.SUCCESS);
+++++++++++++++++++++++++++++setPlaybackHeadPosition+++++++++++++++++++++++++++++++++++
/**
* Sets the playback head position. The track must be stopped for the position to be changed.
* @param positionInFrames playback head position expressed in frames
* @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
* {@link #ERROR_INVALID_OPERATION}
*/
public int setPlaybackHeadPosition(int positionInFrames) {
synchronized(mPlayStateLock) {
if ((mPlayState == PLAYSTATE_STOPPED) || (mPlayState == PLAYSTATE_PAUSED)) {
return native_set_position(positionInFrames);
++++++++++++++++++++++++++++android_media_AudioTrack_set_position++++++++++++++++++++++++++++++++++++
static jint android_media_AudioTrack_set_position(JNIEnv *env, jobject thiz,
jint position) {
AudioTrack *lpTrack = (AudioTrack *)env->GetIntField(
thiz, javaAudioTrackFields.nativeTrackInJavaObj);
if (lpTrack) {
return android_media_translateErrorCode( lpTrack->setPosition(position) );
++++++++++++++++++++++++++++AudioTrack::setPosition++++++++++++++++++++++++++++++++++++
status_t AudioTrack::setPosition(uint32_t position)
{
Mutex::Autolock _l(mCblk->lock);
if (!stopped()) return INVALID_OPERATION;
if (position > mCblk->user) return BAD_VALUE;
mCblk->server = position;
mCblk->flags |= CBLK_FORCEREADY_ON;
return NO_ERROR;
}
----------------------------AudioTrack::setPosition------------------------------------
} else {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioTrack pointer for setPosition()");
return AUDIOTRACK_ERROR;
}
}
----------------------------android_media_AudioTrack_set_position------------------------------------
} else {
return ERROR_INVALID_OPERATION;
}
}
}
-----------------------------setPlaybackHeadPosition-----------------------------------
//-------- tear down --------------
track.release();
}
###########################################################
&&&&&&&&&&&&&&&&&&&&&&&总结&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
set position改变的其实是audio_track_cblk_t结构体中的server成员。
也就是AudioMixer中从audio_track_cblk_t中copy数据时的起始地址。
这儿设置position有个限制,就是不能跑到user前面去,
即不能让取数据的其实地址超出已写数据的范围。
在播放器中,大幅度拖动进度条,改变的应该是读取文件时的地址,
*****************************************源码*************************************************
//Test case 3: setPlaybackHeadPosition() on paused track
@LargeTest
public void testSetPlaybackHeadPositionPaused() throws Exception {
// constants for test
final String TEST_NAME = "testSetPlaybackHeadPositionPaused";
final int TEST_SR = 22050;
final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
final int TEST_MODE = AudioTrack.MODE_STREAM;
final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
//-------- initialization --------------
int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT,
2*minBuffSize, TEST_MODE);
byte data[] = new byte[minBuffSize];
//-------- test --------------
assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
track.write(data, 0, data.length);
track.write(data, 0, data.length);
track.play();
track.pause();
assumeTrue(TEST_NAME, track.getPlayState() == AudioTrack.PLAYSTATE_PAUSED);
assertTrue(TEST_NAME, track.setPlaybackHeadPosition(10) == AudioTrack.SUCCESS);
//-------- tear down --------------
track.release();
}
**********************************************************************************************
源码路径:
frameworks\base\media\tests\mediaframeworktest\src\com\android\mediaframeworktest\functional\MediaAudioTrackTest.java
#######################说明################################
//Test case 3: setPlaybackHeadPosition() on paused track
@LargeTest
public void testSetPlaybackHeadPositionPaused() throws Exception {
// constants for test
final String TEST_NAME = "testSetPlaybackHeadPositionPaused";
final int TEST_SR = 22050;
final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
final int TEST_MODE = AudioTrack.MODE_STREAM;
final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
//-------- initialization --------------
int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT,
2*minBuffSize, TEST_MODE);
byte data[] = new byte[minBuffSize];
//-------- test --------------
assumeTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
track.write(data, 0, data.length);
track.write(data, 0, data.length);
track.play();
track.pause();
assumeTrue(TEST_NAME, track.getPlayState() == AudioTrack.PLAYSTATE_PAUSED);
assertTrue(TEST_NAME, track.setPlaybackHeadPosition(10) == AudioTrack.SUCCESS);
+++++++++++++++++++++++++++++setPlaybackHeadPosition+++++++++++++++++++++++++++++++++++
/**
* Sets the playback head position. The track must be stopped for the position to be changed.
* @param positionInFrames playback head position expressed in frames
* @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
* {@link #ERROR_INVALID_OPERATION}
*/
public int setPlaybackHeadPosition(int positionInFrames) {
synchronized(mPlayStateLock) {
if ((mPlayState == PLAYSTATE_STOPPED) || (mPlayState == PLAYSTATE_PAUSED)) {
return native_set_position(positionInFrames);
++++++++++++++++++++++++++++android_media_AudioTrack_set_position++++++++++++++++++++++++++++++++++++
static jint android_media_AudioTrack_set_position(JNIEnv *env, jobject thiz,
jint position) {
AudioTrack *lpTrack = (AudioTrack *)env->GetIntField(
thiz, javaAudioTrackFields.nativeTrackInJavaObj);
if (lpTrack) {
return android_media_translateErrorCode( lpTrack->setPosition(position) );
++++++++++++++++++++++++++++AudioTrack::setPosition++++++++++++++++++++++++++++++++++++
status_t AudioTrack::setPosition(uint32_t position)
{
Mutex::Autolock _l(mCblk->lock);
if (!stopped()) return INVALID_OPERATION;
if (position > mCblk->user) return BAD_VALUE;
mCblk->server = position;
mCblk->flags |= CBLK_FORCEREADY_ON;
return NO_ERROR;
}
----------------------------AudioTrack::setPosition------------------------------------
} else {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioTrack pointer for setPosition()");
return AUDIOTRACK_ERROR;
}
}
----------------------------android_media_AudioTrack_set_position------------------------------------
} else {
return ERROR_INVALID_OPERATION;
}
}
}
-----------------------------setPlaybackHeadPosition-----------------------------------
//-------- tear down --------------
track.release();
}
###########################################################
&&&&&&&&&&&&&&&&&&&&&&&总结&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
set position改变的其实是audio_track_cblk_t结构体中的server成员。
也就是AudioMixer中从audio_track_cblk_t中copy数据时的起始地址。
这儿设置position有个限制,就是不能跑到user前面去,
即不能让取数据的其实地址超出已写数据的范围。
在播放器中,大幅度拖动进度条,改变的应该是读取文件时的地址,
而不是audio_track_cblk_t对象中的地址。
另外,只能在stop的状态下才能改变position。