Skip to content

Final output render can be black if default framebuffer draw buffer remains GL_NONE #3320

Description

@shihhsinliNV

Version

Media3 pre-release (alpha, beta or RC not in this list)

More version details

Observed with AndroidX Media3 1.6.0-alpha01 prebuilts in AOSP CTS. The same code path exists on the current androidx/media release branch in:
libraries/effect/src/main/java/androidx/media3/effect/FinalShaderProgramWrapper.java

Devices that reproduce the issue

NVIDIA Tegra Android TV

Devices that do not reproduce the issue

No response

Reproducible in the demo app?

No

Reproduction steps

  1. Run this CTS test on an affected GLES implementation:

    CtsMediaEditingTestCases
    android.media.mediaediting.cts.TranscodeQualityTest#transcodeTest[2_transcode_avc_To_avc_320x240_30fps_ForceEncoding_ssim]
    
    1. The test transcodes AVC to AVC at 320x240 and validates output quality with SSIM.

    2. Internally, Media3 renders through its intermediate GL/FBO pipeline, then FinalShaderProgramWrapper.renderFrameToOutputSurface() focuses the encoder/output EGLSurface and renders to framebuffer 0:

      java
      GlUtil.focusEglSurface(
      eglDisplay,
      eglContext,
      outputEglSurface,
      outputSurfaceInfo.width,
      outputSurfaceInfo.height);
      GlUtil.clearFocusedBuffers();
      defaultShaderProgram.drawFrame(inputTexture.texId, presentationTimeUs);
      EGL14.eglSwapBuffers(eglDisplay, outputEglSurface);

    3. On the affected implementation, framebuffer 0 draw/read buffer state remains GL_NONE after an earlier no-surface/FBO transition. Binding framebuffer 0 after focusing the output surface does not restore GL_DRAW_BUFFER0 / GL_READ_BUFFER to GL_BACK.

    4. The final clear/draw into the output surface is discarded, causing black encoded output.

Expected result

Media3 should render the final transformed frame into the output/encoder EGLSurface, and the CTS SSIM check should pass.

The final output-surface render path should be robust if default-framebuffer draw/read buffer state is still GL_NONE after earlier no-surface/FBO transitions.

Actual result

The encoded output contains black frames, and the CTS SSIM check fails.

Observed SSIM:

text
expected: > 0.9
actual:   ~0.1027


Instrumentation showed:

* Media3 intermediate/effect FBO content was non-black.
* The final output EGLSurface was focused at 320x240.
* Framebuffer 0 was complete.
* Program/texture bindings and color mask looked valid.
* No GL error was reported.
* The active default-framebuffer draw state was still GL_NONE.

Representative state:

text
haveFront=0 haveBack=1
drawFb=0 readFb=0
GL_DRAW_BUFFER0 / derived draw state = GL_NONE
read buffer = GL_BACK


Additional instrumentation confirmed the app did not explicitly call glDrawBuffers(... GL_NONE ...); the stale state came from internal/default-framebuffer state carried across the prior no-surface/FBO transition.

The EGL/GLES specs define default framebuffer draw/read state for contexts with and without an associated default framebuffer, but do not clearly require a later eglMakeCurrent transition from no default framebuffer / surfaceless rendering to a real EGLSurface to reset default framebuffer draw/read buffer state. This appears similar to the robustness issue previously handled in HWUI by resetting default-FB draw/read buffers after transitioning from no surface to a real surface.

Media

Not applicable.

The issue does not appear to depend on the specific media content. The failure is caused by final output-surface GL state: Media3 has valid non-black intermediate/effect FBO content, but the final render to the output EGLSurface is discarded because the default framebuffer draw buffer remains GL_NONE.

Bug Report

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions