我的代码运行后,画面会重复而且还是没有声音,我想知道问题出在哪儿,我需要怎么修改
package com.example.mediacodectest;
import android.annotation.SuppressLint;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaSync;
import android.media.PlaybackParams;
import android.os.Build;
import android.util.Log;
import android.view.Surface;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import java.io.IOException;
import java.nio.ByteBuffer;
public class MediaThread3 extends Thread {
private Surface surface;
private Surface inputSurface;
private MediaExtractor extractor;
private MediaCodec mediaCodec;
private MediaFormat mformat;
private String mime = null;
private int width = 0;
private int heghit = 0;
private long startMs = -1;
private MediaSync sync;
private AudioTrack audio;
public MediaThread3(Surface surface) {
this.surface = surface;
}
@SuppressLint("NewApi")
public void run() {
int bufsize = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);
audio = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT, bufsize, AudioTrack.MODE_STREAM);
sync = new MediaSync();
sync.setSurface(surface);
inputSurface = sync.createInputSurface();
sync.setAudioTrack(audio);
sync.setCallback(new syncCallback(), null);
//设置播放速度
sync.setPlaybackParams(new PlaybackParams().setSpeed(1.f));
try {
//根据视频源获取MediaFormat
extractor = new MediaExtractor();
extractor.setDataSource("sdcard/qqq/test2.mp4");
int numTracks = extractor.getTrackCount();
Log.d("numTracks", String.valueOf(numTracks));
for (int i = 0; i < numTracks; i++) {
mformat = extractor.getTrackFormat(i);
String mime = mformat.getString(MediaFormat.KEY_MIME);
Log.d("mime", mime);
if (mime.startsWith("video/")) {
extractor.selectTrack(i);
try {
mediaCodec = MediaCodec.createDecoderByType(mime);
mediaCodec.setCallback(new CodecCallback());
} catch (IOException e) {
e.printStackTrace();
}
//这样配置之后,解码之后的数据就会 直接显示在mSurface 上边 这里是核心点
mediaCodec.configure(mformat, inputSurface, null, 0);
break;
}
}
mediaCodec.start();
} catch (IOException e) {
e.printStackTrace();
}
}
@RequiresApi(api = Build.VERSION_CODES.M)
public class syncCallback extends MediaSync.Callback {
@Override
public void onAudioBufferConsumed(@NonNull MediaSync sync, @NonNull ByteBuffer audioBuffer, int bufferId) {
mediaCodec.releaseOutputBuffer(bufferId, true);
}
}
//异步处理解码播放
public class CodecCallback extends MediaCodec.Callback {
@SuppressLint("NewApi")
@Override
public void onInputBufferAvailable(@NonNull MediaCodec codec, int index) {
ByteBuffer inputBuffer = codec.getInputBuffer(index);
int sampleSize = extractor.readSampleData(inputBuffer, 0);
if (sampleSize > 0) {
codec.queueInputBuffer(index, 0, sampleSize, extractor.getSampleTime(), 0);
extractor.advance(); //下一帧数据
} else {
codec.queueInputBuffer(index, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
}
}
@SuppressLint("NewApi")
@Override
public void onOutputBufferAvailable(@NonNull MediaCodec codec, int index, @NonNull MediaCodec.BufferInfo info) {
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
codec.stop();
codec.release();// 释放组件
extractor.release();
return;
}
if (index > 0) {
if (startMs == -1) {
startMs = System.currentTimeMillis();
} else {
//保持播放的速度与实际帧率相同
while (info.presentationTimeUs / 1000 > System.currentTimeMillis() - startMs) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
if (codec == mediaCodec) {
// surface timestamp must contain media presentation time in nanoseconds.
codec.releaseOutputBuffer(index, 1000 * info.presentationTimeUs);
} else {
ByteBuffer audioByteBuffer = codec.getOutputBuffer(index);
sync.queueAudio(audioByteBuffer, index, info.presentationTimeUs);
}
//
}
@Override
public void onError(@NonNull MediaCodec codec, @NonNull MediaCodec.CodecException e) {
codec.stop();
codec.release();
extractor.release();
}
@Override
public void onOutputFormatChanged(@NonNull MediaCodec codec, @NonNull MediaFormat format) {
mformat = format; // option B
}
}
}