MainActivity
имеет кнопки SurfaceView
и Воспроизведение, Пауза и Стоп.Он создает и запускает потоки во время воспроизведения.Я изучал столько, сколько смог, и я сделал это из-за ссылки на код, но проблема в том, что когда я играю, я получаю:
'Нормальный вывод видео, аудио +очень быстрый звук '
Это наложенное состояние воспроизведения.Я не думаю, что есть причина для двойного воспроизведения звука, потому что аудио буфер равен releasedOutput
, рендерит его false
, и только скопированный буфер равен queuedAudio
.Пожалуйста, помогите мне с проблемой.
И я не знаю, почему я должен пройти процесс копирования.Если я не пройду процесс копирования, он не будет работать.
И в конце воспроизведения, когда повторение закончится,
Log.i ("mintest", "first end");
Log.i ("mintest", "second end");
Log.i ("mintest", "third end");
Этот журнал должен бытьвключен, но только первый.Это не вызывает никаких других проблем, но, пожалуйста, дайте мне знать, если у вас есть еще причины!
Мой код
public class VideoDecoderThread extends Thread {
private static final String VIDEO = "video/";
private static final String AUDIO = "audio/";
private static final String TAG = "VideoDecoder";
private MediaExtractor mExtractor, mAudioExtractor;
private MediaCodec mDecoder, mAudioDecoder;
private boolean eosReceived;
private boolean isPaused;
private BufferInfo info, audioInfo;
private ByteBuffer[] inputBuffers, audioInputBuffers;
private boolean isInput, isAudioInput;
private int mSampleRate;
private MediaSync mMediaSync;
@RequiresApi(api = Build.VERSION_CODES.N)
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;
}
@RequiresApi(api = Build.VERSION_CODES.M)
@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 {
Log.d(TAG, "InputBuffer BUFFER_FLAG_END_OF_STREAM");
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:
Log.d(TAG, "INFO_OUTPUT_BUFFERS_CHANGED");
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
Log.d(TAG, "INFO_OUTPUT_FORMAT_CHANGED format : " + mDecoder.getOutputFormat());
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
Log.d(TAG, "INFO_TRY_AGAIN_LATER");
break;
default:
mDecoder.releaseOutputBuffer(outIndex, true);
Log.d(TAG, "INFO_OUTPUT_RELEASED");
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) {
Log.d(TAG, "OutputBuffer BUFFER_FLAG_END_OF_STREAM");
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");
mAudioDecoder.stop();
mAudioDecoder.release();
mAudioExtractor.release();
mMediaSync = null;
mDecoder = null;
mExtractor = null;
mAudioDecoder = null;
mAudioExtractor = null;
MainActivity.isfirstPlay = true;
Log.i("mintest", "third end");
}
public void close() {
eosReceived = true;
}
public void pause() {
isPaused = true;
}
public void play() {
isPaused = false;
}
}