Android — декодировать поток H.264 с помощью MediaCodec API JNI

Я занимаюсь разработкой декодера H.264 с использованием MediaCodec API. Я пытаюсь вызвать MediaCodec Java API в слое JNI внутри функции, как:

void Decompress(const unsigned char *encodedInputdata, unsigned int inputLength, unsigned char **outputDecodedData, int &width, int &height) {
// encodedInputdata is encoded H.264 remote stream
// .....
// outputDecodedData = call JNI function of MediaCodec Java API to decode
// .....
}

Позже я пришлю outputDecodedData в мой существующий конвейер рендеринга видео и рендеринга на Surface,

Я надеюсь, что смогу написать функцию Java для декодирования входного потока, но это будет проблемой —

  1. это ресурс говорится, что —

…Вы ничего не можете сделать с декодированным видеокадром, но визуализировать их
на поверхность

Здесь Surface был пройден decoder.configure(format, surface, null, 0) сделать вывод ByteBuffer на поверхности и утверждал We can't use this buffer but render it due to the API limit,

Итак, смогу ли я отправить вывод ByteBuffer на родной слой, чтобы бросить как unsigned char* и перейти к моему конвейеру рендеринга вместо прохождения Surface Ветхий Завет configure()?

1

Решение

Я вижу две фундаментальные проблемы с вашим предложенным определением функции.

Во-первых, MediaCodec работает с блоками доступа (блоками NAL для H.264), а не с произвольными порциями данных из потока, поэтому вам нужно одновременно передавать по одному блоку NAL. Как только блок получен, кодек может захотеть дождаться поступления дополнительных кадров, прежде чем производить какие-либо выходные данные. Обычно вы не можете передать один кадр ввода и ждать получения одного кадра вывода.

Во-вторых, как вы заметили, выход ByteBuffer кодируется YUV в одном из нескольких цветовых форматов. Формат варьируется от устройства к устройству; Устройства Qualcomm используют свой собственный формат. (Тем не менее, он был переработан, поэтому, если вы будете искать вокруг, вы можете найти какой-то код, чтобы распутать его.)

Обычный обходной путь заключается в отправке видеокадров в SurfaceTexture, которая преобразует их в «внешние» текстуры GLES. Этим можно манипулировать различными способами или передавать в pbuffer и извлекать с помощью glReadPixels(),

1

Другие решения


По вопросам рекламы [email protected]