我正在使用AudioTrack,MediaCodec和MediaExtractor的组合来解码和播放音乐。
根据the document,
为了开始解码与先前提交的数据不相邻的数据(即,在搜索之后),必须刷新()解码器。客户端可以在刷新点处拥有的任何输入或输出缓冲区立即被撤销,即在调用flush()之后,客户端不再拥有任何缓冲区。
我在搜索后调用flush,所以我也应该调用mAudioTrack.flush();
虽然调用了flush,但是audioTrack会播放以前写入数据的某些部分,并从新写入的数据继续播放。
不调用decoder.flush,可能会在音频播放中听到明显的故障。那么如何实现瞬时刷新并继续播放新写入的数据?
代码段:
更新了代码
do {
int codedbufferIndex = decoder.dequeueInputBuffer(1000);
if (codedbufferIndex >= 0) {
ByteBuffer codecInput = inputBuffers[codedbufferIndex];
synchronized (playerState) {
if (seek) {
extractor.seekTo(seekTo,
MediaExtractor.SEEK_TO_CLOSEST_SYNC);
// audioTrack.pause();
// audioTrack.stop();
// audioTrack.flush();
decoder.flush();
seek = false;
// audioTrack.play();
continue;
}
}
read = extractor.readSampleData(codecInput, offset);
if (read < 0) {
if (extractor.hasCacheReachedEndOfStream())
Log.e(TAG, "extractor.hasCacheReachedEndOfStream()");
break;
}
presentationTimeUs = extractor.getSampleTime();
decoder.queueInputBuffer(codedbufferIndex, offset, read,
presentationTimeUs, (read > 0) ? 0
: MediaCodec.BUFFER_FLAG_END_OF_STREAM);
int decodedDataBufIndex = decoder.dequeueOutputBuffer(info,
2000);
if (decodedDataBufIndex >= 0) {
ByteBuffer codecOutput = outputBuffers[decodedDataBufIndex];
byte[] atInput = new byte[info.size];
codecOutput.get(atInput);
codecOutput.clear();
decoder.releaseOutputBuffer(decodedDataBufIndex, false);
if(info.offset != 0){
Log.e(TAG,"info.offset = "+String.valueOf(info.offset));
}
audioTrack.write(atInput, /*0*/info.offset, info.size);
extractor.advance();
} else if (decodedDataBufIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
MediaFormat newFormat = decoder.getOutputFormat();
Log.e(TAG,
"newFormat: "
+ newFormat
.getString(MediaFormat.KEY_MIME));
Log.e(TAG,
"newFormat: "
+ String.valueOf(newFormat
.getInteger(MediaFormat.KEY_SAMPLE_RATE)));
Log.e(TAG, "Inside INFO_OUTPUT_FORMAT_CHANGED");
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
sampleRate, AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT, 32768,
AudioTrack.MODE_STREAM);
audioTrack.play();
}
} else {
Log.e(TAG,"codedbufferIndex is "+String.valueOf(codedbufferIndex));
}
} while (read >= 0);
答案 0 :(得分:0)
AudioTrack.flush()如果没有暂停或停止,则为无操作。
如果没有停止或暂停,或者轨道的创建模式不是,则为无操作 MODE_STREAM。
一种解决方案是降低AudioTrack的缓冲区,因此先前提交的字节的播放是不可察觉的。在我的应用程序中,我使用了相当大的32K大小,这并不麻烦。