Я занимаюсь разработкой декодера 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 для декодирования входного потока, но это будет проблемой —
…Вы ничего не можете сделать с декодированным видеокадром, но визуализировать их
на поверхность
Здесь 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()
?
Я вижу две фундаментальные проблемы с вашим предложенным определением функции.
Во-первых, MediaCodec работает с блоками доступа (блоками NAL для H.264), а не с произвольными порциями данных из потока, поэтому вам нужно одновременно передавать по одному блоку NAL. Как только блок получен, кодек может захотеть дождаться поступления дополнительных кадров, прежде чем производить какие-либо выходные данные. Обычно вы не можете передать один кадр ввода и ждать получения одного кадра вывода.
Во-вторых, как вы заметили, выход ByteBuffer кодируется YUV в одном из нескольких цветовых форматов. Формат варьируется от устройства к устройству; Устройства Qualcomm используют свой собственный формат. (Тем не менее, он был переработан, поэтому, если вы будете искать вокруг, вы можете найти какой-то код, чтобы распутать его.)
Обычный обходной путь заключается в отправке видеокадров в SurfaceTexture, которая преобразует их в «внешние» текстуры GLES. Этим можно манипулировать различными способами или передавать в pbuffer и извлекать с помощью glReadPixels()
,