У меня есть старое устройство с Android 4.2, на котором я пытаюсь воспроизвести видеопоток.Я использую MediaCodec и MediaExtractor, но последовательное декодирование видео и аудио кажется довольно медленным.Воспроизведение звука замедляет его почти до 20 кадров в секунду с 30, а звук заикается, но если я уберу аудиодекодер, он будет очень плавным.Есть ли способ сделать это асинхронным, чтобы при рендеринге видео не приходилось ждать аудио?Также в моем коде «extractor.getSampleTrackIndex ()», кажется, занимает большую часть времени обработки, поскольку он пытается выяснить, является ли блок данных аудио или видео дорожкой, и это, кажется, замедляет все.
extractor.setDataSource(uri);
for (int i = 0; i < extractor.getTrackCount(); i++) {
MediaFormat format = extractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("video/")) {
Log.d(TAG, "Found video track with format " + mime);
mVideoTrackIndex = i;
extractor.selectTrack(mVideoTrackIndex);
format_h264 = format;
videoDecoder = MediaCodec.createDecoderByType(mime);
videoDecoder.configure(format, surface, null, 0);
Log.d(TAG, "Found a videoDecoder for " + mime);
} else if (mime.startsWith("audio/") && audioDecoder == null) {
Log.d(TAG, "Found audio track with format " + mime);
audio_mime = mime;
audio_format = extractor.getTrackFormat(i);
try {
audioDecoder = MediaCodec.createDecoderByType(audio_mime);
if (audioDecoder != null) {
audioDecoder.configure(audio_format, null, null, 0);
mAudioTrackIndex = i;
extractor.selectTrack(mAudioTrackIndex);
MediaFormat extractorTrackFormat = extractor.getTrackFormat(mAudioTrackIndex);
mAudioSampleRate = extractorTrackFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
Log.d(TAG, "Found an audioDecoder for " + mime);
}
} catch (Exception e) {
Log.w(TAG, "no audioDecoder found for" + mime);
e.printStackTrace();
}
} else {
Log.d(TAG, "Unknown mime type: " + mime + " on format: " + format.toString());
}
}
videoDecoder.start();
VideoDecoderThread videoDecoderThread = new VideoDecoderThread();
videoDecoderThread.start();
ByteBuffer[] videoInputBuffers = videoDecoder.getInputBuffers();
AudioDecoderThread audioDecoderThread = null;
if (audioDecoder != null) {
audioDecoder.start();
audioInputBuffers = audioDecoder.getInputBuffers();
audioDecoderThread = new AudioDecoderThread();
audioDecoderThread.start();
}
while (!Thread.interrupted()) {
if (!isEOS) {
render(extractor, videoInputBuffers, audioInputBuffers);
extractor.advance();
} else {Thread.sleep(1);}
}
void render(MediaExtractor extractor, ByteBuffer[] videoInputBuffers, ByteBuffer[] audioInputBuffers) {
int videoInIndex;
int audioinIndex;
ByteBuffer buffer;
int trackIndex = extractor.getSampleTrackIndex();
if (trackIndex == mVideoTrackIndex) {
videoInIndex = videoDecoder.dequeueInputBuffer(0);
if (videoInIndex < 0) return;
buffer = videoInputBuffers[videoInIndex];
videoDecoder.queueInputBuffer(videoInIndex, 0, extractor.readSampleData(buffer, 0), extractor.getSampleTime(), 0);
} else {
if (audioDecoder != null) {
audioinIndex = audioDecoder.dequeueInputBuffer(0);
if (audioinIndex < 0) return;
buffer = audioInputBuffers[audioinIndex];
audioDecoder.queueInputBuffer(audioinIndex, 0, extractor.readSampleData(buffer, 0), extractor.getSampleTime(), 0);
}
}
}