`BlankFrameProducer` was originally internal to
`DefaultVideoFrameProcessorVideoFrameRenderingTest`. We later copied it in
c221958889. This CL converges the usages.
PiperOrigin-RevId: 555953620
This effect can scale Alpha values.
This is needed for testing Compositor, and coincidentally was requested
by a partner in the past. This also will generally be more useful in
full multi-asset, where we may want to have one input have different alpha
values than another
Also, update fragment_shader_copy_es2.glsl to not throw away alpha values.
This means ThumbnailStripShaderProgram (the only place this glsl is used) will
consider input alpha and output alpha appropriately
PiperOrigin-RevId: 555915092
This adds an effect to change the speed of the video track. The speed
of the audio track can already be changed using a SonicAudioProcessor.
Issue: androidx/media#559
PiperOrigin-RevId: 555155418
When implementing pause and resume, overlay appears as black frame on resume, suggesting the texture isn't being remade properly due to lack of proper deletion.
PiperOrigin-RevId: 554832580
The test file decompresses to about 48 MB, which can cause an
`OutOfMemoryError` on lower end devices.
Also, a test appears to apply a rotation to this bitmap without downscaling
first, leading to exceeding a maximum texture width/height of 4096 on some
devices.
Replace the test file with one that has a quarter of the original's
width/height so that these tests can pass reliably even on lower end
devices.
PiperOrigin-RevId: 554507185
This means we now require 2+ input frames per input, and compare the primary
stream timestamp with secondary stream timestamps in order to select the
correct output timestamp. We also must release frames and back-pressure as
soon as possible to avoid blocking upstream VFPs.
Also, improve signalling of VFP onReadyToAcceptInputFrame
PiperOrigin-RevId: 553448965
This allows for custom implementations of this interface, like
a TestVideoCompositor or partner-implemented implementation
PiperOrigin-RevId: 552541631
After this change, every queued bitmap is treated as an individual input stream
(like a new MediaItems).
This change merges the FrameDropTest and FrameDropPixelTest into one (while maintaining all the test cases)
- This is accomplished by generating bitmaps with timestamps on it in FrameDropTest and compare them with goldens (one may call this a pixel test, please lmk if you want this to be renamed)
- The most part of the change comes from DefaultVideoFrameProcessorVideoFrameRenderingTest. The overall working is
- We bypass the input manager
- The TestFrameGenerator generates frames based on timestamps. In this case, we generate frames with timestamps on it
- The generated frame is sent to texture output and in turn saved to bitmaps
- We then compare the generated bitmap with the goldens
PiperOrigin-RevId: 551795770
For each event, the timestamp and presentation time is logged. The trace can
then be dumped to a tsv file and easily imported in a spreadsheet.
PiperOrigin-RevId: 550839156
signalEndOfInputStream is needed for when streams have different amounts of
frames, so that if the primary stream finishes after a secondary stream, it
can end without waiting indefinitely for the secondary stream's matching
timestamps.
onEnded mirrors this API on the output side, which will be necessary to
know when to call signalEndOfInput on downstream components (ex. on downstream)
VideoFrameProcessors
PiperOrigin-RevId: 549969933
The VideoFrameProcessingTaskExecutor already handles wrapping
GlUtil.GlException errors into VideoFrameProcessingExceptions.
Therefore, stop wrapping this ourselves, so that errors are
attributed to the correct line number with less indirection.
PiperOrigin-RevId: 549959258
Alters the OverlayShaderProgram implementation to support rotations, however we need to apply the transformations separately in order for them to work as expected so the matrix is removed from the interface in favour of explicit methods.
Adds a rotation test to ensure this ability doesn't regress
PiperOrigin-RevId: 549890847
For now, just identical timestamps. A follow-up CL will allow for different
framerates. Prior tests already send identical timestamp frames, so no new
tests were added
PiperOrigin-RevId: 548676759
Before this CL, the text with a scale span would wrap text, with because the scale wasn't taken into account when measuring the width of the overlay.
PiperOrigin-RevId: 548123626
* Allow more than one input bitmap at a time.
* Allow Compositor to take in and set up an Executor. Otherwise,
Compositor resources may be created on one thread and accessed on another.
* Add a Compositor TestRunner to reuse test code more.
* Update VideoFrameProcessingTaskExecutor to use a new onError listener, so
that it's more reusable in non-DVFP contexts, like for Compositor.
PiperOrigin-RevId: 547206053
Frame buffers are focused, not current. EGL Contexts may be current but this
is a prerequisite for focusing a framebuffer, and this alone isn't
sufficient to make a bitmap.
Clear this up as it can make some complex tests harder to understand, if the
methods needed don't match up in naming.
PiperOrigin-RevId: 546305118
BaseGlShaderProgram and SingleFrameGlShaderProgram are technically color space agnostic. useHdr is passed to the TexturePool, which only uses the value to choose between high/regular precision. useHdr is therefore a bit misleading and should be generalized to "useHighPrecisionColorComponents."
PiperOrigin-RevId: 545726629
This allows us to simplify and reduce thread initialization, hops and the
synchronization cost associated with them, especially when more and more VFPs
are used.
PiperOrigin-RevId: 545622169
Providing the sync token in the api allows the client to decide which waiting method they would like to use depending on the use case, allowing them to optimise if possible.
PiperOrigin-RevId: 543997311
MP4 edit lists sometimes ask to start playback between two samples.
If this happens, we currently change the timestamp of the first
sample to zero to trim it (e.g. to display the first frame for a
slightly shorter period of time). However, we can't do this to audio
samples are they have an inherent duration and trimming them this
way is not possible.
#minor-release
PiperOrigin-RevId: 543420218
By passing this class where it's needed, implementations don't need to store it
in a field (reducing boilerplate) and it's clearer that it can't be unset when
needed.
PiperOrigin-RevId: 542823522
To more accurately describe what they do, especially as Compositor will
starts to use more contexts or threads, and it's important to know what
needs to be reset/recreated/focused before what methods.
PiperOrigin-RevId: 541010135
Previously, TextureMangers have a method to signal ending of a current input
stream, and a method to end the **entire input**. The responsibility of both
methods are not easy to document, understand and read.
With the new design,
- Only `TextureManager.signalEndOfCurrentInputStream()` is kept
- It's called for every MediaItem in the sequence, include the final one
- FinalWrapper now takes explicit signal that frame processing is ending,
rather than relying on the return value of `onCurrentInputStreamProcessed()`
- On DVFP receiving EOS from the pipeline, it signals FinalWrapper the stream
is ending, **before** signaling the input switcher, so that FinalWrapper is
able to end the stream when the onCurrentInputStreamEnded signal eventually
reaches FinalWrapper
PiperOrigin-RevId: 540856680
This helps debug bitmap tests. Without this CL, I typically
need to go into the file to find the test name and absolute
path. With this CL, I can just adb pull the printed file path,
which is much simpler.
PiperOrigin-RevId: 540539042
The existing NullableType has been deprecated 5 years ago and causes
crashes in Kotlin apps because Kotlin doesn't recognize this annotation
as a nullable type annotation.
While we can't align on a single @Nullable annotation yet, we can at
least replace this one by JSR305's @Nonnull(MAYBE) as it fulfils all
requirements, including full Kotlin compatiblity. To avoid the
cumbersome name, we can redefine it as our own @NullableType
annotation. (We can't use @Nullable to avoid name clashes with the main
@Nullable annotation from AndroidX)
Issue: google/ExoPlayer#6792
PiperOrigin-RevId: 540497469
Partially roll forward of 5c29abbbf4, and adds some extra logic
Changes to the original CL
The original logic (a66f08ba97) fails in the following case:
> This is only seem on emulators.
- EOS is sent to ExtTexMgr
- The timer starts
- One frame arrives on SurfaceTexture, reset the timer
- The frame is sent for processing, now `availablFrames == 0`
- One frame arrives on Surface, reset the timer
- The frame is kept on SurfaceTexture for the downstream shader doesn't have
capacity, `availablFrames == 1`
- Timer times out as the downstream processor doesn't report being able to take
another frame.
- Although there's a frame available on the SurfaceTexture
This is solved by having the force EOS logic clear all the frames that the
SurfaceTexture holds. This also ensures the first frame dequeued from the next
stream isn't from the previous stream.
PiperOrigin-RevId: 540023359
This methods currently registers and queues the bitmaps Will need to have a method that just queues bitmaps in future CLs.
#minor-release
PiperOrigin-RevId: 539605628
*** Original commit ***
Add a timer to end a video stream prematurely in ExtTexMgr
***
This has been submitting for more than 1.5hrs. "This presubmit is running slowly because you have been throttled by Build Queue due to using too much of your Product Area's quota."
adding NO_SQ as this is a pure rollback
PiperOrigin-RevId: 539135970
To ensure no regressions for the potentially confusing pipeline of:
* HDR electrical -> SDR linear EOTF+OOTF, and
* SDR linear -> SDR electrical OETF
PiperOrigin-RevId: 538741079
`outputSurfaceInfoChanged` is not reset when `defaultShaderProgram` is null.
That is, on the first time `ensureConfigured()` is called with output size
changed, `outputSurfaceInfoChanged` is not set to false after creating the
`defaultShaderProgram`, and `defaultShaderProgram` will be created again on the
second time `ensureConfigured()` is called.
PiperOrigin-RevId: 537870404
This future.get() duplicates the wait done in
singleThreadExecutorService.awaitTermination(). If awaitTermination times out, this future.get() would also result in unnecessary blocking.
PiperOrigin-RevId: 536442153
Also, document that texture output disables manual frame release.
In the past, texture output would lead to surface output methods throwing. Now,
they're simply no-ops instead.
PiperOrigin-RevId: 534894168
This is blocking the upgrade to AGP 8.0.1. The Android Studio Upgrade
Assistant refuses to run with the error:
> Modules have the same package for their `main` and `androidTest`
> artifacts
>
> The package specifications in `AndroidManifest.xml` files define the
> same package for the `main` and `androidTest` artifacts, in the
> following modules: `effect`, `muxer`, `transformer`,
`test_exoplayer_abr`, `test_exoplayer_performance`, and `container`.
This change also adds the `.test` suffix to `test/AndroidManifest.xml`
files where it's missing, because although it's not mentioned in the
Upgrade Assistant error it does cause problems later.
```
> Incorrect package="androidx.media3.database" found in source AndroidManifest.xml: libraries/database/src/test/AndroidManifest.xml.
Setting the namespace via the package attribute in the source AndroidManifest.xml is no longer supported.
Recommendation: remove package="androidx.media3.database" from the source AndroidManifest.xml: libraries/database/src/test/AndroidManifest.xml.
```
Issue: androidx/media#409
PiperOrigin-RevId: 533460180
This allows us to avoid needing a reference to the VideoFrameProcessor, which
can be especially difficult if an App only has a reference to the
VideoFrameProcessor.Factory it passes into Transformer/ExoPlayer.
PiperOrigin-RevId: 533205983
Have the FinalShaderProgramWrapper / VideoFrameProcessor texture
output access textures provided through a texture pool, that
recycles used textures.
Also, add the TexturePool interface to generally re-use textures.
PiperOrigin-RevId: 532754377
Propagate the "end of current stream" signal directly after queueing the
last frame, instead of waiting for the next onReadyToAcceptInputFrame()
call.
PiperOrigin-RevId: 532739462
Allow the VideoFrameProcessor to output multiple textures at a time, so that
lifetime of textures is up to the consumer calling VFP.releaseOutputFrame.
The FinalShaderProgramWrapper also has a new maxCapacity limit added, to ensure
the a reasonable amount of textures is used and avoid using up memory.
PiperOrigin-RevId: 532094256
When exporting compositions with multiple images in a row, transformation could
get stuck if a shader was ready to accept input when end-of-stream was already
signaled and queued from upstream. Fix accounting for the downstream capacity.
Manually tested on concatenations with several images and several videos in a
row, by adding logging and verifying the capacity updates as expected across
edited media item transitions.
PiperOrigin-RevId: 532088793
The output end-of-stream notification from the last shader could theoretically
arrive before the latch for detecting it is created, which might cause waiting
on the latch indefinitely. Create the latch before signaling end of stream so
that it's guaranteed to be set before the end-of-stream signal arrives.
PiperOrigin-RevId: 532056472
For DefaultVideoFrameProcessorVideoFrameRenderingTest: `registerInputStream` sets the textureManager, so reordering makes sure the textureManager is set before you set the frame info. This is important for texture input, where the frame info provides the width and height.
PiperOrigin-RevId: 529753404
Also make FinalShaderProgramWrapper always receive internal texture.
This means it does not sample from a input texture, and its input color is
always linear, hence the input type does not matter.
PiperOrigin-RevId: 527869045
*** Original commit ***
Effect: glFlush instead of glFinish on tex output
This is much faster (~2-3x) than glFlush. While there's a risk that GL commands
queued to the GL server may not be complete by the time non-GL commands access
the texture, this should be unlikely as we only access the texture from GL.
If we see stability issues in the future, we can reconsider and move this back
to glFinish (or GL synchronization mechanisms like fences, which are more
complex)
***
PiperOrigin-RevId: 527848094
renderOutputFrame actually renders frames to an output surface. We'll soon have
a releaseOutputFrame method, that would release resources associated with an
output time, so rename this to disambiguate the two methods.
Also rename onOutputFrameAvailable to onOutputFrameAvailableForRendering, to
make it clear this is not available for "release"
This change should be a renaming-only change and have no functional differences.
PiperOrigin-RevId: 527844947
This is much faster (~2-3x) than glFlush. While there's a risk that GL commands
queued to the GL server may not be complete by the time non-GL commands access
the texture, this should be unlikely as we only access the texture from GL.
PiperOrigin-RevId: 527641520
Add `VideoFrameProcessor.registerInputStream()` to signal a new type of input.
And `InputHandler.signalEndOfCurrentInputStream()` to signal to `InputHandler`
partial input stream completion.
Fully processed means after FinalShaderProgramWrapper releases the last frame.
PiperOrigin-RevId: 527356646
Allow the VideoFrameProcessor to output to a texture without an output surface.
Tested by updating texture output tests to no longer output to a surface.
PiperOrigin-RevId: 527244605
The production code changes are in transformer, but the tests in effect have also been updated to confirm the is no color regression `inputColorInfo.colorTransfer=C.COLOR_TRANSFER_SRGB`
PiperOrigin-RevId: 526950435
Previously, I assumed that SDR contents must be BT709, and HDR contents must be
BT2020. Turns out BT2020 is just wide-gamut, and SDR contents / transfers may be
represented in BT2020 color spaces.
Relax the check, so that we don't throw when valid BT2020 SMPTE 170M contents
are input into effects.
PiperOrigin-RevId: 526668347
Whenever a frame is queued to the shader, it's guaranteed that there will be a
subsequent `onInputFrameProcessed` callback, so we can pass on the
end-of-stream signal there.
PiperOrigin-RevId: 525850141
Creates a way for apps to provide their EGLContext to DefaultVideoFrameProcessor, so that we can attach their context to the one we create. See [the EGL docs for more information about how contexts are shared in GL](https://registry.khronos.org/EGL/sdk/docs/man/html/eglCreateContext.xhtml)
PiperOrigin-RevId: 525708652
Removes glObjectsProvider from `VideoFrameProcessor` and `Effects`. Apps will set the glObjectsProvider on the DefaultVideoFrameProcessor.Factory.Builder when providing a custom DefaultVideoFrameProcessor.Factory, rather than in `Effects`.
PiperOrigin-RevId: 525169059
A new texture manager will be created for input by texture ID so this texture manager won't be the only one to handle internal (i.e. non-external) textures.
PiperOrigin-RevId: 525116460
In `ExternalTextureManager` in seemingly rare cases end of stream is signaled
at the point where a frame is currently pending processing. In that case the
video end of stream signal was lost. If the muxer timeout was enabled this
case would result in throwing an exception, but otherwise the operation would
get stuck
Add code to signal end of stream in `onInputFrameProcessed` as well, so that we
signal end of stream when the pending frame is handled.
Tested by running
`TransformerEndToEndTest.loopingTranscodedVideo_producesExpectedResult` several
times.
PiperOrigin-RevId: 524361069
In addition to the changes in 3a5c4277a7
This change essentially reverts 30e5bc9837 (Merged Jul 2022).
From this CL on, `VideoFrameProcessor` takes in non-offset, monotonically
increasing timestamps. For example, with one 5s and one 10s video,
- `VideoFrameProcessor`'s input should start from 0
- On switching to the second video (10s), the timestamp of the first frame in
the second video should be at 5s.
In ExoPlayer however, `streamOffset` is managed differently and thus needs
correction before sending the frames to `VideoFrameProcessor`:
- The timestamp of the first video is offset by a large int, so the first frame
of the first media item has timestamp (assuming) 10000000000000000
- The last frame of the first media item has 10000005000000000
- At this point the stream off set is updated to 10000005000000000
- The pts of the first frame of the second video starts from 0 again.
PiperOrigin-RevId: 523444236
Before this CL, SurfaceTexture.onFrameAvailable was used to tell whether a frame
was available in the VideoFrameProcessor's output texture. This was incorrect, as
it would rely on having the texture be written to before the
SurfaceTexture.onFrameAvailableListener is invoked, leading to null-pointer-
exceptions on timeouts.
Instead of using DefaultVideoFrameProcessor different interfaces to set that we
want to output to a texture, and get that output texture, use one interface that
sets a listener, and renders to a texture iff that listener is set. As this
listener is executed on the GL thread, this also allows us to no longer need to
expand visibility for the GL task executor and tasks.
PiperOrigin-RevId: 522362101
NPE in toneMap_hlgFrame_matchesGoldenFile and toneMap_pqFrame_matchesGoldenFile was created because a uEnableColorTransfer uniform was being created on the HDR path, when HDR shader files don't have this uniform. (they don't support disable color transfers right now)
Fix: only create the uniform when input is SDR.
manually tested on failing tests
PiperOrigin-RevId: 522002603
By having a single base class for GL shader programs we simplify the customization
of new shader programs. The concrete cases include
- Allow frame dropping in shader program
- Creating a FrameCache that selectively (based on timestamp) replays and clears
the cached content
PiperOrigin-RevId: 520322060
Previously, we always used ImageReader to read from the output of DefaultVideoFrameProcessor, for pixel tests. This has a limitation of not being
able to read HDR contents, so that we couldn't support HDR pixel tests.
Reading from a texture allows us to use glReadPixels to read from
DefaultVideoFrameProcessor, and build upon this to implement HDR pixel tests. We do
still want tests for surface output though, because real use-cases only will output
to Surfaces.
Also, add some tests for outputting to textures, since this test infrastructure is
a bit complex.
PiperOrigin-RevId: 519786535
Since the composite matrix is ultimately rewritten to, we need to ensure it's cleared (to identity) before update.
Test plan: use an effect as a time based approach and see that the effect no longer clips
PiperOrigin-RevId: 518886623
Reduce nesting by using an early return. Also, rename
`outputSizeOrRotationChanged` to `outputChanged`, because this also applies to when the output surface changes.
Also, update local variable initialization, add some javadoc, and remove unneeded
local variable
PiperOrigin-RevId: 518241708
d288891c77 added clearing depth buffers to GLUtil, so there is no need to have allow apps to have a custom clearOutputFrame.
Also removes default implementations in GLObjectsProvider know that these methods have been implemented.
PiperOrigin-RevId: 517156304
Instead of using a long frameDurationUs with Math.floor, use a double
frameDurationUs with Math.round,
Before, playing an image with 30 fps over 1 second would result in the final
timestamp not being aligned to the expected 1 second timestamp. Over long
periods of time, this can lead to significant timestamp drift. Additionally,
for TimestampWrapper and constrained multi-asset, where TimestampWrapper
begins the 2nd effect on the 2nd asset's startTimeUs, this floor() behavior
can lead to the first few frames of the 2nd asset using the first asset's
effects, due to timestamps being mismatched.
PiperOrigin-RevId: 516529240