메인액티비티에는 SurfaceView와 재생, 일시중지, 정지버튼이 있고, 재생시 스레드를 생성, 시작시킵니다. 여기저기서 최대한 공부하고 작성된 코드들 참고해서 만들긴 했는데 문제는 재생시,
' 정상 출력 비디오, 오디오 + 싱크가 맞지 않는 매우 빠른 속도의 오디오 '
이렇게 겹쳐서 재생이 되는 상태입니다. 오디오 버퍼를 releaseOutput 하면서 렌더 여부를 false로 하고 복사한 버퍼만 queueAudio 하기 때문에 오디오가 이중으로 재생될 이유가 없을 것 같은데.. 무엇이 문제인지 도움 좀 부탁드립니다..
그리고 사실 복사 과정을 거쳐야 하는 이유도 잘 모르겠습니다.. 복사 과정을 거치지 않으면 싱크가 맞지 않던데..
그리고 재생이 끝났을 때, 반복문이 끝나면서
Log.i("mintest", "first end");
Log.i("mintest", "second end");
Log.i("mintest", "third end");
이 로그가 실행 되어야 하는데, 첫번째만 실행이 됩니다. 이는 다른 문제를 일으키지는 않지만, 추가적으로 이유를 아신다면 가르쳐주시길 바랍니다!
public boolean init(Surface surface, AssetFileDescriptor filePath) {
eosReceived = false;
isPaused = false;
try {
mExtractor = new MediaExtractor();
mExtractor.setDataSource(filePath);
mAudioExtractor = new MediaExtractor();
mAudioExtractor.setDataSource(filePath);
mMediaSync = new MediaSync();
mMediaSync.setSurface(surface);
Surface surface1 = mMediaSync.createInputSurface();
for (int i = 0; i < mExtractor.getTrackCount(); i++) {
MediaFormat format = mExtractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith(VIDEO)) {
mExtractor.selectTrack(i);
mDecoder = MediaCodec.createDecoderByType(mime);
mDecoder.configure(format, surface1, null, 0);
mDecoder.start();
break;
}
}
for (int i = 0; i < mAudioExtractor.getTrackCount(); i++) {
MediaFormat format = mAudioExtractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith(AUDIO)) {
mAudioExtractor.selectTrack(i);
mAudioDecoder = MediaCodec.createDecoderByType(mime);
mSampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
mAudioDecoder.configure(format, null, null, 0);
mAudioDecoder.start();
int buffsize = AudioTrack.getMinBufferSize(mSampleRate, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, mSampleRate,
AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT,
buffsize,
AudioTrack.MODE_STREAM);
mMediaSync.setAudioTrack(audioTrack);
break;
}
}
info = new BufferInfo();
audioInfo = new BufferInfo();
inputBuffers = mDecoder.getInputBuffers();
audioInputBuffers = mAudioDecoder.getInputBuffers();
isInput = true;
isAudioInput = true;
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
@Override
public void run() {
while (!eosReceived) {
if (!isPaused) {
if (isInput) {
int inputIndex = mDecoder.dequeueInputBuffer(10000);
if (inputIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputIndex];
int sampleSize = mExtractor.readSampleData(inputBuffer, 0);
if (mExtractor.advance() && sampleSize > 0) {
mDecoder.queueInputBuffer(inputIndex, 0, sampleSize, mExtractor.getSampleTime(), 0);
} else {
mDecoder.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
isInput = false;
}
}
}
int outIndex = mDecoder.dequeueOutputBuffer(info, 10000);
switch (outIndex) {
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
break;
default:
mDecoder.releaseOutputBuffer(outIndex, true );
break;
}
if (isAudioInput) {
int audioInputIndex = mAudioDecoder.dequeueInputBuffer(10000);
if (audioInputIndex >= 0) {
ByteBuffer audioInputBuffer = audioInputBuffers[audioInputIndex];
int audioSampleSize = mAudioExtractor.readSampleData(audioInputBuffer, 0);
if (mAudioExtractor.advance() && audioSampleSize > 0) {
mAudioDecoder.queueInputBuffer(audioInputIndex, 0, audioSampleSize, mAudioExtractor.getSampleTime(), 0);
} else {
mAudioDecoder.queueInputBuffer(audioInputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
isAudioInput = false;
}
}
}
int audioOutIndex = mAudioDecoder.dequeueOutputBuffer(audioInfo, 10000);
switch (audioOutIndex) {
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
mAudioDecoder.getOutputBuffers();
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
break;
default:
ByteBuffer decoderBuffer = mAudioDecoder.getOutputBuffer(audioOutIndex);
ByteBuffer copyBuffer = ByteBuffer.allocate(decoderBuffer.remaining());
copyBuffer.put(decoderBuffer);
copyBuffer.flip();
mAudioDecoder.releaseOutputBuffer(audioOutIndex, false);
mMediaSync.queueAudio(copyBuffer, audioOutIndex, audioInfo.presentationTimeUs);
break;
}
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
break;
}
mMediaSync.setPlaybackParams(new PlaybackParams().setSpeed(0.5f));
} else {
mMediaSync.setPlaybackParams(new PlaybackParams().setSpeed(0.f));
}
}
Log.i("mintest", "first end");
mMediaSync.setPlaybackParams(new PlaybackParams().setSpeed(0.f));
mMediaSync.release();
mDecoder.stop();
mDecoder.release();
mExtractor.release();
Log.i("mintest", "second end");
...
Log.i("mintest", "third end");
}
...
}