Несовместимое время выборки / время представления во время декодирования видео
Я пишу приложение, которое может кодировать видео по входу камеры и обрабатывать видео с помощью шагов декодирования-редактирования-кодирования. Для камеры я использую класс Camera, а не Intent для настройки параметров камеры. Затем я передаю кадры камеры кодеру (MediaCodec в API 16) и мультиплексору (я использую мультиплексор ffmpeg, поскольку хочу работать на устройствах 4.1).
Я измеряю временной код кадров камеры по системному нано-времени и выбираю подмножество кадров, чтобы соответствовать желаемому FPS (в настоящее время 15). Есть некоторые небольшие «шумы» в значениях времени, например (в мс): 0, 60718, 135246, 201049, ... вместо 0, 66000, 133000, 200000, ....
После некоторых попыток правильно настроить мультиплексор (какэтот вопрос), Я могу создать видео (с кодеком AVC), которое может воспроизводиться видеопроигрывателем на устройствах. Скорость воспроизведения правильная, поэтому я думаю, что видео должно иметь правильную информацию о времени кадров.
Однако у меня возникла проблема при попытке декодировать видео для выполнения процесса редактирования видео. Я использую стандартные шаги извлечения / декодирования видео какэти образцы, как это:
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. Только последние несколько кадров имеют правильное время представления.
Я тестирую весь тот же процесс на устройстве с Android 4.3 (даже с тем же мультиплексором ffmpeg, а не MediaMuxer в API 18), и все выглядит хорошо. На устройствах 4.1 / 4.2, если я снимаю видео встроенным приложением камеры на устройстве, а затем декодирую видео, тогда время представления также является правильным, хотя значения времени также имеют шумы из-за задержки камеры.
Что не так с видео или процессом декодирования, когда видео можно воспроизводить и декодировать нормально, но с правильным временем выборки и плохим временем представления? Возможно, мне придется использовать обходной путь, чтобы измерить время представления по времени выборки (это легко с помощью очереди), но я хочу выяснить, есть ли какая-либо пропущенная часть в моей работе.