AudioTrack、MediaCodec、および MediaExtractor の組み合わせを使用して、音楽をデコードおよび再生しています。
ドキュメントによると、
以前に送信されたデータに隣接していないデータのデコードを開始するには (つまり、シーク後)、デコーダーを flush() する必要があります。フラッシュの時点でクライアントが所有している可能性のある入力または出力バッファーは、すぐに取り消されます。つまり、flush() の呼び出し後、クライアントはバッファーを所有しなくなります。
mAudioTrack.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);