Я пытаюсь использовать MediaCodec для кодирования кадров (с помощью камеры или декодера) в видео. При обработке вывода кодировщика с помощью dequeueOutputBuffer() я ожидаю получить возвращаемый индекс = MediaCodec.INFO_OUTPUT_FORMAT_CHANGED, поэтому я могу вызвать getOutputFormat(), чтобы получить формат вывода кодировщика в качестве входных данных используемого в настоящее время мультиплексора ffmpeg.
Я протестировал некоторые планшеты/телефоны с Android версии 4.1~4.3. Все они имеют как минимум один аппаратный кодировщик видео AVC и используются в тесте. На устройствах с версией 4.3 кодировщик выдает MediaCodec.INFO_OUTPUT_FORMAT_CHANGED перед записью закодированных данных, как ожидается, и выходной формат, возвращаемый функцией getOutputFormat(), может правильно использоваться мультиплексором. На устройствах с версией 4.2.2 или ниже кодировщик никогда не выдает MediaCodec.INFO_OUTPUT_FORMAT_CHANGED, пока он все еще может выводить закодированный элементарный поток, но мультиплексор не может знать точный выходной формат.
Я хочу задать следующие вопросы:
- Зависит ли поведение кодировщика (дает MediaCodec.INFO_OUTPUT_FORMAT_CHANGED или нет перед выводом закодированных данных) от уровня Android API или чипов на отдельных устройствах?
- Если кодировщик записывает данные до появления MediaCodec.INFO_OUTPUT_FORMAT_CHANGED, есть ли способ получить выходной формат закодированных данных?
- Кодер по-прежнему выводит данные конфигурации кодека (с флагом MediaCodec.BUFFER_FLAG_CODEC_CONFIG) на устройства перед закодированными данными. В основном он используется для настройки декодера, но могу ли я получить выходной формат по данным конфигурации кодека?
Я пробовал эти решения, чтобы получить формат вывода, но не удалось:
- Часто вызывайте getOutputFormat() в течение всего процесса кодирования. Однако все они выдают IllegalStateException без появления MediaCodec.INFO_OUTPUT_FORMAT_CHANGED.
Используйте первоначальное использование MediaFormat для настройки кодировщика в начале, как в примере:
m_init_encode_format = MediaFormat.createVideoFormat(m_encode_video_mime, m_frame_width, m_frame_height); int encode_bit_rate = 3000000; int encode_frame_rate = 15; int encode_iframe_interval = 2; m_init_encode_format.setInteger(MediaFormat.KEY_COLOR_FORMAT, m_encode_color_format); m_init_encode_format.setInteger(MediaFormat.KEY_BIT_RATE, encode_bit_rate); m_init_encode_format.setInteger(MediaFormat.KEY_FRAME_RATE, encode_frame_rate); m_init_encode_format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, encode_iframe_interval); m_encoder = MediaCodec.createByCodecName(m_video_encoder_codec_info.getName()); m_encoder.configure(m_init_encode_format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); // Assume m_init_encode_format is the output format of the encoder
Однако это не удается, поскольку выходной формат кодировщика все еще «изменен» по сравнению с исходным.
Пожалуйста, помогите мне понять поведение кодировщика и есть ли какое-либо решение для запроса выходного формата, если отсутствует требуемый MediaCodec.INFO_OUTPUT_FORMAT_CHANGED.
При сравнении выходного формата и данных конфигурации кодека отсутствуют поля csd-0, csd-1 и поле "что" со значением = 1869968451. (Я не понимаю поле "что". Кажется, это константа и не требуется.Может ли кто-нибудь сказать мне о ее значении?)
Если я проанализирую данные конфигурации кодека как поле csd-1 (последние 8 байтов) и поле csd-0 (оставшиеся байты), кажется, что мультиплексор может работать правильно и выводить видео, воспроизводимое на всех тестируемых устройствах. (Но я хочу спросить: правильно ли это 8-байтовое предположение, или есть более надежный способ парсить данные?)
Однако у меня возникла еще одна проблема: если я снова декодирую видео с помощью Android MediaCodec, значение BufferInfo.presentationTimeUs, полученное с помощью dequeueOutputBuffer(), равно 0 для большинства декодированных кадров. Только последние несколько кадров имеют правильное время. Время выборки, полученное с помощью MediaExtractor.getSampleTime(), является правильным и точно соответствует значению, которое я установил для кодировщика/мультиплексора, но время декодированного кадра — нет. Эта проблема возникает только на устройстве 4.2.2 или более ранней версии.
Странно, что время кадра неправильное, но видео может воспроизводиться с правильной скоростью на устройстве. (Большинство протестированных мною устройств с версией 4.2.2 или ниже имеют только 1 декодер Video AVC.) Нужно ли задавать другие поля, которые могут повлиять на время презентации?