Android 使用 MediaSync 的应用在播放视频时冻结
Android app that uses MediaSync freezes while playing video
我正在尝试使用新的 MediaSync API 同步播放视频和音频。 https://developer.android.com/reference/android/media/MediaSync.html
我有使用 MediaSync 的纯音频播放器,但对于纯视频播放器,我在显示 5-6 帧后立即在 logcat 中得到这个
I/MediaSync﹕ still waiting to release a buffer before acquire
我的视频播放器如下
public class VideoDecoderTask implements Runnable {
......
@Override
public void run() {
mediaSync = new MediaSync();
mediaSync.setSurface(surface);
Surface inputSurface = mediaSync.createInputSurface();
mediaExtractor = new MediaExtractor();
try {
mediaExtractor.setDataSource(this.clipPath);
} catch (IOException e1) {
e1.printStackTrace();
}
for (int i = 0; i < mediaExtractor.getTrackCount(); i++) {
MediaFormat format = mediaExtractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("video/")) {
Log.d(LOG_TAG, format.toString());
mediaExtractor.selectTrack(i);
try {
videoDecoder = MediaCodec.createDecoderByType(mime);
} catch (IOException e) {
e.printStackTrace();
}
videoDecoder.configure(format, inputSurface, null, 0);
Log.d(LOG_TAG, "Found a video track.");
break;
}
}
SyncParams syncParams = new SyncParams();
syncParams.setSyncSource(SyncParams.SYNC_SOURCE_VSYNC);
mediaSync.setPlaybackParams(new PlaybackParams().setSpeed(1.f));
mediaSync.setSyncParams(syncParams);
videoDecoder.setCallback(decoderCallback, null);
videoDecoder.start();
}
MediaCodec.Callback decoderCallback = new MediaCodec.Callback() {
@Override
public void onInputBufferAvailable(MediaCodec codec, int index) {
if (index >= 0) {
ByteBuffer byteBuffer = codec.getInputBuffer(index);
int sampleSize = mediaExtractor.readSampleData(byteBuffer, 0);
Log.d(LOG_TAG, "SampleSize: " + sampleSize);
if (sampleSize < 0) {
//we're at end of file so submit EOS to the decoder input
Log.d(LOG_TAG, "Video Decoder input EOS reached");
codec.queueInputBuffer(index, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
} else {
long sampleTime = mediaExtractor.getSampleTime();
codec.queueInputBuffer(index, 0, sampleSize, sampleTime, 0);
mediaExtractor.advance();
}
}
}
@Override
public void onOutputBufferAvailable(MediaCodec codec, int index, MediaCodec.BufferInfo info) {
Log.d(LOG_TAG, "Rendering with preso time: " + info.presentationTimeUs);
codec.releaseOutputBuffer(index, info.presentationTimeUs);
}
};
}
以上任务使用
从主线程启动
VideoDecoderTask decoderTask = new VideoDecoderTask(clipPath, new Surface(surface));
Thread thread = new Thread(decoderTask);
thread.start();
其中表面来自 TextureView
根据 mediasync 生成的消息,我有根据的猜测是由于某种原因,onOutputBufferAvailable 中返回的缓冲区未释放回来。我需要什么来解决这个问题?
顺便说一句,我 运行 在 Nexus9 运行 开发版本 M 来自 https://developer.android.com/preview/download.html#images
如果我用 SurfaceView 替换输出的 TextureView,视频播放似乎工作正常。
虽然这解决了我的问题,但我不明白为什么使用 SurfaceTexture 创建的表面与从 SurfaceHolder.Per http://developer.android.com/reference/android/graphics/SurfaceTexture.html 获得的表面之间存在差异
"A Surface created from a SurfaceTexture can be used as an output destination for the android.hardware.camera2, MediaCodec, MediaPlayer"。这几乎就是我在上面的示例中所做的,该示例使用 MediaSync/MEdiaCodec 和 TextureView 作为输出表面
我发现了一个问题。
codec.releaseOutputBuffer(index, info.presentationTimeUs);
codec.releaseOutputBuffer(指数, 1000 * info.presentationTimeUs);
请参考下面的 MediaSync 示例。
我正在尝试使用新的 MediaSync API 同步播放视频和音频。 https://developer.android.com/reference/android/media/MediaSync.html
我有使用 MediaSync 的纯音频播放器,但对于纯视频播放器,我在显示 5-6 帧后立即在 logcat 中得到这个
I/MediaSync﹕ still waiting to release a buffer before acquire
我的视频播放器如下
public class VideoDecoderTask implements Runnable {
......
@Override
public void run() {
mediaSync = new MediaSync();
mediaSync.setSurface(surface);
Surface inputSurface = mediaSync.createInputSurface();
mediaExtractor = new MediaExtractor();
try {
mediaExtractor.setDataSource(this.clipPath);
} catch (IOException e1) {
e1.printStackTrace();
}
for (int i = 0; i < mediaExtractor.getTrackCount(); i++) {
MediaFormat format = mediaExtractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("video/")) {
Log.d(LOG_TAG, format.toString());
mediaExtractor.selectTrack(i);
try {
videoDecoder = MediaCodec.createDecoderByType(mime);
} catch (IOException e) {
e.printStackTrace();
}
videoDecoder.configure(format, inputSurface, null, 0);
Log.d(LOG_TAG, "Found a video track.");
break;
}
}
SyncParams syncParams = new SyncParams();
syncParams.setSyncSource(SyncParams.SYNC_SOURCE_VSYNC);
mediaSync.setPlaybackParams(new PlaybackParams().setSpeed(1.f));
mediaSync.setSyncParams(syncParams);
videoDecoder.setCallback(decoderCallback, null);
videoDecoder.start();
}
MediaCodec.Callback decoderCallback = new MediaCodec.Callback() {
@Override
public void onInputBufferAvailable(MediaCodec codec, int index) {
if (index >= 0) {
ByteBuffer byteBuffer = codec.getInputBuffer(index);
int sampleSize = mediaExtractor.readSampleData(byteBuffer, 0);
Log.d(LOG_TAG, "SampleSize: " + sampleSize);
if (sampleSize < 0) {
//we're at end of file so submit EOS to the decoder input
Log.d(LOG_TAG, "Video Decoder input EOS reached");
codec.queueInputBuffer(index, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
} else {
long sampleTime = mediaExtractor.getSampleTime();
codec.queueInputBuffer(index, 0, sampleSize, sampleTime, 0);
mediaExtractor.advance();
}
}
}
@Override
public void onOutputBufferAvailable(MediaCodec codec, int index, MediaCodec.BufferInfo info) {
Log.d(LOG_TAG, "Rendering with preso time: " + info.presentationTimeUs);
codec.releaseOutputBuffer(index, info.presentationTimeUs);
}
};
}
以上任务使用
从主线程启动VideoDecoderTask decoderTask = new VideoDecoderTask(clipPath, new Surface(surface));
Thread thread = new Thread(decoderTask);
thread.start();
其中表面来自 TextureView
根据 mediasync 生成的消息,我有根据的猜测是由于某种原因,onOutputBufferAvailable 中返回的缓冲区未释放回来。我需要什么来解决这个问题?
顺便说一句,我 运行 在 Nexus9 运行 开发版本 M 来自 https://developer.android.com/preview/download.html#images
如果我用 SurfaceView 替换输出的 TextureView,视频播放似乎工作正常。
虽然这解决了我的问题,但我不明白为什么使用 SurfaceTexture 创建的表面与从 SurfaceHolder.Per http://developer.android.com/reference/android/graphics/SurfaceTexture.html 获得的表面之间存在差异 "A Surface created from a SurfaceTexture can be used as an output destination for the android.hardware.camera2, MediaCodec, MediaPlayer"。这几乎就是我在上面的示例中所做的,该示例使用 MediaSync/MEdiaCodec 和 TextureView 作为输出表面
我发现了一个问题。
codec.releaseOutputBuffer(index, info.presentationTimeUs);
codec.releaseOutputBuffer(指数, 1000 * info.presentationTimeUs);
请参考下面的 MediaSync 示例。