【发布时间】:2014-03-13 13:38:29
【问题描述】:
我正在编写一个可以通过摄像头输入编码视频并通过解码-编辑-编码步骤处理视频的应用程序。对于相机,我使用Camera类而不是Intent来配置相机的细节设置。然后我将相机帧提供给编码器(API 16 中的 MediaCodec)和复用器(我使用 ffmpeg 复用器,因为我想在 4.1 设备上工作)。
我通过系统纳秒时间测量相机帧的时间码,并选择一个帧子集以适应所需的 FPS(当前为 15)。时间值中有一些小的“噪音”,例如(以毫秒为单位):0, 60718, 135246, 201049, ... 而不是 0, 66000, 133000, 200000, ...。
在尝试正确配置复用器(如this question)后,我可以制作一个视频(使用 AVC 编解码器),该视频可由设备上的视频播放器播放。播放速度是正确的,所以我认为视频应该有正确的帧时间信息。
但是,当我尝试解码视频以执行视频编辑过程时遇到了问题。我使用标准视频提取/解码步骤为these samples,如下所示:
int decode_input_index = decoder.dequeueInputBuffer(TIMEOUT_USEC);
if (decode_input_index >= 0)
{
ByteBuffer decoder_input_buffer = decode_input_buffers[decode_input_index];
int sample_size = extractor.readSampleData(decoder_input_buffer, 0);
if (sample_size < 0)
{
decoder.queueInputBuffer(decode_input_index, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
is_decode_input_done = true;
}
else
{
long sample_time = extractor.getSampleTime();
decoder.queueInputBuffer(decode_input_index, 0, sample_size, sample_time, 0);
extractor.advance();
}
}
else
{
Log.v(TAG, "Decoder dequeueInputBuffer timed out! Try again later");
}
当我对视频进行编码时,getSampleTime() 的采样时间值正确。 (例如,它们在我们身上正好是 0、60718、135246、201049、...)。它也是decoder.queueInputBuffer() 的输入中的呈现时间。当解码器继续解码此帧时,我通过以下方式获得帧时间:
int decode_output_index = decoder.dequeueOutputBuffer(decode_buffer_info, TIMEOUT_USEC);
switch (decode_output_index)
{
....
(some negative-value flags in MediaCodec)
....
default:
{
ByteBuffer decode_output_buffer = decode_output_buffers[decode_output_index];
long ptime_us = decode_buffer_info.presentationTimeUs;
boolean is_decode_EOS = ((decode_buffer_info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0);
....
}
}
我希望设置与解码器输入中的时间序列相同的时间序列,但我从解码器输出的 BufferInfo 中得到很多 0。解码后的帧内容似乎是正确的,但是大部分的呈现时间值都是0。只有最后几帧有正确的呈现时间。
我在装有 Android 4.3 的设备上测试了整个相同的过程(即使使用相同的 ffmpeg muxer 而不是 API 18 中的 MediaMuxer),一切看起来都很好。在4.1/4.2设备上,如果我通过设备内置的摄像头APP采集视频,然后解码视频,那么呈现时间也是正确的,虽然时间值也会因为摄像头延迟而产生噪音。
视频或解码过程有什么问题,视频可以正常播放和解码,但采样时间正确且演示时间错误?我可能不得不使用一种解决方法来通过采样时间来衡量演示时间(使用队列很容易),但我想弄清楚我的工作中是否有任何遗漏的部分。
【问题讨论】:
标签: android decode encode android-mediacodec mediaextractor