Взаимодействие Android MediaCodec/NdkMediaCodec GLES2

мы пытаемся декодировать битовые потоки AVC/h264, используя новый API NdkMediaCodec. Хотя декодирование теперь работает нормально, мы пытаемся преобразовать содержимое декодированного видеокадра в GLES2 для рендеринга. API позволяет передавать ANativeWindow во время настройки, но мы хотим контролировать планирование рендеринга видео и, в конечном счете, просто предоставить N текстур, которые заполняются данными декодированного кадра.

Все попытки сопоставить память, возвращаемую getOutputBuffer(), с GLES через eglCreateImageKHR/external image не увенчались успехом. NdkMediaCodec, похоже, использует libstagefright/OMX для внутреннего использования. Таким образом, выходные буферы, скорее всего, выделены с помощью gralloc, не так ли? Есть ли способ получить дескриптор gralloc/GraphicsBuffer для привязки кадра к EGL/GLES2?

Поскольку существует множество форматов пикселей для медиа-фрейма без какой-либо дополнительной документации по их расположению в памяти, трудно надежно использовать NdkMediaCodec.

Большое спасибо за любые подсказки!


person youaresoomean    schedule 03.04.2015    source источник


Ответы (1)


Для общего MediaCodec в java создайте SurfaceTexture для текстуры GL ES, в которой вы хотите иметь данные, затем создайте Surface из этого SurfaceTexture и используйте его в качестве цели для декодера MediaCodec. См. http://bigflake.com/mediacodec/ (например, EncodeDecodeTest) для примера, как это сделать.

Однако классы SurfaceTexture и Surface сейчас недоступны непосредственно в NDK (насколько я знаю), поэтому вам нужно будет вызывать их через JNI. Затем вы можете создать ANativeWindow из Surface, используя ANativeWindow_fromSurface.

Вы правы в том, что буферы вывода — это буферы gralloc, но, поскольку для этого существуют общедоступные API, безопаснее полагаться на них, чем пытаться использовать ярлыки.

person mstorsjo    schedule 03.04.2015
comment
Ndk Api просто принимает одно окно ANativeWindow во время настройки. Что мне нужно, так это способ декодировать каждый новый кадр в другую (ну N текстур в кольцевом буфере) текстуру. Идеальным решением, даже если это означает использование частного API, был бы способ получить дескриптор gralloc для ptr, возвращаемый функцией get output buffer. - person youaresoomean; 04.04.2015
comment
Вам явно нужно иметь доступ более чем к одному декодированному кадру одновременно, или достаточно иметь точный контроль над тем, какой из кадров вы используете? При использовании SurfaceTexture вы получаете обратный вызов, когда доступен новый кадр, затем вы можете по своему усмотрению вызвать updateTexImage(), чтобы подкачать этот новый кадр в текстуру (и вызвать getTimestamp(), чтобы узнать, какой это кадр). Таким образом, вы можете точно контролировать, какие кадры используются, когда и где, но вы можете использовать только один за раз и только последовательно. - person mstorsjo; 04.04.2015
comment
Да, мне нужно больше одного кадра. Аппаратное декодирование на других поддерживаемых нами платформах (iOS, Intel MFX) работает таким образом. Насколько я понял, текстура не сразу доступна для GLES2 при вызове updateTexImage, не так ли? Планировщик видео вычисляет текущую задержку рендеринга для потокового видео и определяет отметку времени отображения. Поэтому очень важно, чтобы рама была доступна в это время. Можно ли выделить хранилище для N кадров в одной SurfaceTexture и изменить привязку GL tex obj после сохранения кадра? - person youaresoomean; 07.04.2015
comment
Внутри SurfaceTexture на самом деле содержит несколько буферов (есть флаг, если вы хотите явно отключить это); как только вы получите обратный вызов, говорящий о том, что доступен новый кадр, он должен быть доступен для использования сразу после вызова updateTexImage. Единственное предостережение заключается в том, что вы не знаете временную метку следующего доступного кадра, пока не вызовете updateTexImage. - person mstorsjo; 07.04.2015
comment
Ясно спасибо. Таким образом, одним из решений было бы прикрепить новые идентификаторы GL Obj-Tex к SurfaceTexture и надеяться, что внутренний буфер достаточно велик, или, возможно, забыть об API NdkMediaCodec и просто перейти непосредственно к OMX (или напрямую использовать libstagefright). Почему-то Android/NDK — это настоящий кошмар — по крайней мере, для наших случаев использования :( - person youaresoomean; 07.04.2015
comment
Проверил код Android Frameworks-Base, отсоединение также удаляет текстуру GL. Таким образом, нет возможности использовать несколько текстур с SurfaceTexture. - person youaresoomean; 07.04.2015