GLEffectsFrameProcessor, MatrixShaderProgram and FinalMatrixShaderProgramWrapper are currently setup to handle the input frames coming from an external input (i.e. a video decoder). Image input is loaded into Bitmap objects at the start of the pipeline, so they are not produced externally. The changes provide a way for the frame processing pipeline to handle this "internal" (i.e. non-external) input.
PiperOrigin-RevId: 508645244
Based on [this conversation thread](https://chat.google.com/room/AAAA--f88ao/76Rem_cRCK8), I've opted to update the existing FrameProcessor.create() rather than deprecate it, as it is unlikely to be in use by apps outside google3.
PiperOrigin-RevId: 506920930
Flushing resets all the texture processors within the `FrameProcessor`. This
includes:
- At the back, the FinalMatrixTextureProcessorWrapper, and its MatrixTextureProcessor
- At the front, the ExternalTextureManager
- All the texture processors in between
- All the ChainingGlTextureProcessorListeners in between texture processors
- All the internal states in the aforementioned components
The flush process follows the order, from `GlEffectsFrameProcessor.flush()`
1. Flush the `FrameProcessingTaskExecutor`, so that after it returns, all tasks queued before calling `flush()` completes
2. Post to `FrameProcessingTaskExecutor`, to flush the `FinalMatrixTextureProcessorWrapper`
3. Flushing the `FinalMatrixTextureProcessorWrapper` will propagate flushing through, via the `ChainingGlTextureProcessorListener`
Startblock:
has LGTM from christosts
and then
add reviewer andrewlewis
PiperOrigin-RevId: 506296469
This is confusing, since the effect is used not only when applying an effect, but also when preparing an effect (ex. in a texture processor's constructor), so we should also mention that case.
PiperOrigin-RevId: 504843598
This makes it implicitly clear that if the value of a getter changes due
to a change in command availability then the listener will be invoked,
without needing to explicitly document every command on every listener
method.
#minor-release
PiperOrigin-RevId: 503178383
We currently only document it for the getCurrentMediaItem(), but
the command was always meant to cover all information about the
current media item and the position therein.
To correctly hide information for controllers, we need to filter
the Timeline when bundling the PlayerInfo class if only this
command is available.
PiperOrigin-RevId: 503098124
When bundling PlayerInfo, we need to remove information if the
controller is not allowed to access it. This was only partially
done at the moment.
PiperOrigin-RevId: 502852798
When bundling PlayerInfo, we remove data when the controller is not
allowed to access this data via getters. We also remove data for
performance reasons. In the toBundle() method, it's currently hard to
make the connection between allowed commands and filtering, because
the values are checked at a different place. This can be made more
readable by forwarding the applicable Commands directly.
The only functional fix is to filter the Timeline when sending the
first PlayerInfo after a connecting a controller if the command to
get the Timeline is not available. This also allows us to remove a
path to filter MediaItems from Timelines as it isn't used.
PiperOrigin-RevId: 502607391
This CL includes following changes:
1. Remove GCA related terms/links from java docs and comments.
2. Make class final where ever possible.
3. Append /* package */ for default classes.
4. Change java docs to recommended format.
5. Replace term "packet" with "sample" to avoid confusion.
6. Correct TODO format.
7. Delete MediaFormatUtil.java from muxer module and add its methods into MediaFormatUtil.java in common module.
Note: The java doc on various boxes has the limited description which was already present. In future I am planning to add proper small description for each box (from MP4 spec).
Not included in this CL:
1. Order of element correction as it will show lot of changes and might create confusion with other minor changes.
2. Correction in test cases (Only some renaming).
PiperOrigin-RevId: 502414139
This is needed for constrained multi-asset to shift the timestamps of
the media items that are not the first in the sequence.
PiperOrigin-RevId: 502409923
This should make debugging much easier as values will be more human-readable.
Before this CL, one needed to reference MediaFormatUtil to check the
colorSpace/colorTransfer/colorRange values and make sure values were as
expected.
PiperOrigin-RevId: 502367147
The migration strategy is to deprecate `androidx.media3.session.BitmapLoader` and copy the file into common since BitmapLoader is a public interface that apps could be relying on.
PiperOrigin-RevId: 501266521
The FrameProcessor is created on the GL thread, but:
- setInputFrameInfo() is currently called from the playback thread.
- release() is currently called from the transformer internal thread.
PiperOrigin-RevId: 501035719
Initialising the fields as Integer and then getting a String on compute time is slow. Instead we directly initialise these fields as String. Improves the time taken in bundling PlayerInfo further to less than 200ms from ~300ms.
Also modified a test to improve productive coverage.
PiperOrigin-RevId: 500003935
Improves the time taken to construct playerInfo from its bundle from ~400 ms to ~300 ms.
Also made `Timeline.Window.toBundle(boolean excludeMediaItem)` public as it was required to assert a condition in tests.
PiperOrigin-RevId: 499512353
Added another check in each of these tests to make sure we don't add keys to bundle for fields with default values.
Also fixed comments of similar changes in `AdPlaybackStateTest` and `MediaMetadataTest`.
PiperOrigin-RevId: 499463581
Did not do this optimisation for `AdPlaybackState.AdGroup` as its length is zero for `AdPlaybackState` with no ads.
No need to pass default values while fetching keys, which we always set in `AdPlaybackState.AdGroup.toBundle()`.
PiperOrigin-RevId: 496995048
Users of this class may run into these assertions when creating the
State and they need to check the source code to understand why
the State is invalid. Adding error messages to all our correctness
assertions helps to understand the root cause more easily.
PiperOrigin-RevId: 496875109
These are the remaining setter operations. They all share the same
logic that handles playlist and/or position changes. The logic to
create the placeholder state is mostly copied from ExoPlayerImpl's
maskTimelineAndPosition and getPeriodPositonUsAfterTimelineChanged.
PiperOrigin-RevId: 496364712
FrameProcessor already support using different transfer function for input and
output color. This CL has two major changes:
- Create an eglSurface that recognizes BT.2020 PQ
- This requires a separate extension that works only after 33
- So we current throw, if input is HDR, and this extension doesn't work
- Create FrameProcessor with PQ output transfer function
PiperOrigin-RevId: 496023758
Some Player methods operate relative to existing indices in the
playlist (add,remove,move,seek). As these operations may be issued
from a place with a stale playlist (e.g. a controller that sends
a command while the playlist is changing), we have to handle out-
of-bounds indices gracefully. In most cases this is already
documented and implemented correctly. However, some cases are not
documented and the existing player implementations don't handle
these cases consistently (or in some cases not even correctly).
PiperOrigin-RevId: 495856295
The `MediaItem` instances in the following cases are not actually empty but acts as a placeholder. `EMPTY_MEDIA_ITEM` can also be confused with `MediaItem.EMPTY`.
PiperOrigin-RevId: 495843012
Improves the time taken to construct `playerInfo` from its bundle from ~450 ms to ~400 ms. Each `MediaItem` inside `Timeline.Window` contains `MediaMetadata` and hence is a good candidate for bundling optimisations. There already exists a test to check all parameters for null values when unset.
PiperOrigin-RevId: 495614719
This simplifies some position tracking needs for an app implementing
SimpleBasePlayer.
- The period index can always be derived from the media item index
and the position. So there is no need to set it separately.
- The media item index can be left unset in the State in case the app
doesn't care about the value or wants to set it the default start
index (e.g. while the playlist is still empty where UNSET is
different from zero).
- Similarly, we should allow to set the content position (and buffered
position) to C.TIME_UNSET to let the app ignore it or indicate the
default position explictly.
PiperOrigin-RevId: 495352633
isLoading is not allowed to be true when IDLE, so we have to set to
false when stopping in case it was set to true before.
PiperOrigin-RevId: 494975405
BasePlayer simplifies implementations by handling all the various
seek methods and forwarding to a single method that can then be
implemented by subclasses. However, this loses the information about
the concrete entry point used for seeking, which is relevant when
the subclass wants to verify or filter by Player.Command. This
can be improved by adding the command as a new parameter. Since
we have to change the method anyway, we can also incorporate the
boolean flag about whether the current item is repeated to avoid
the separate method.
PiperOrigin-RevId: 494948094
- Use a single `VideoSize` instance instead of four primitive fields.
- Clarify that the reported size is the decoded size, that is the encoded video
size.
PiperOrigin-RevId: 494148190
Some Player methods like getting the Looper and adding listeners
were always allowed to be called from any thread, but this is
undocumented. This change makes the threading rules of these
methods more explicit.
Removing listeners was never meant to be called from another thread
and we also don't support it safely because final callbacks may
be triggered from the wrong thread. To find potential issues, we
can assert the correct thread when releasing listeners.
Finally, there is a potential race condition when calling addListener
from a different thread at the same time as release, which may lead to
a registered listener that could receive callbacks after the player is
released.
PiperOrigin-RevId: 493843981
The folder type has a mix of information about the item. It shows
whether the item is browsable (type != FOLDER_TYPE_NONE) and
which Bluetooth folder type to set for legacy session information.
It's a lot clearer to split this into a boolean isBrowsable and
use the existing mediaType to map back to the bluetooth folder type
where required.
folderType is not marked as deprecated yet as this would be an API
change, which will be done later.
PiperOrigin-RevId: 493544589
This adds support for the release handling. To align with the
established behavior in ExoPlayer, the player can only call
listeners from within the release methods (and not afterwards)
and automatically enforces an IDLE state (without listener call)
in case getters of the player are used after release.
PiperOrigin-RevId: 493543958
Modify FrameProcessor and MatrixTextureProcessor interfaces to support
different input and output color transfers. Does not implement conversion between
color ranges (ex. HDR and SDR), but should allow for conversion between color
transfers of the same color range (ex. HLG and PQ).
This supports in-app tone mapping, where we need a single FrameProcessor to
input HDR color transfers (ex. HLG/PQ) and output SDR (ex. gamma2.2). This also
supports previewing, where we need a single FrameProcessor to be able to input HLG
and output PQ.
Manually tested by confirming colors still look right on SDR and HDR videos
with a rotation and color affect applied.
PiperOrigin-RevId: 493108678
From this CL on, FrameProcessor listeners will be invoked from an Executor that
is passed in when creating the FrameProcessor.
GlTextureProcessor needs to invoke the ErrorListener on the said Executor too.
PiperOrigin-RevId: 493018583
These have the same value (`-1`), and basically the same meaning (offset
in an array/list/file/byte stream/etc), but 'position' is an overloaded
term in a media playback library, and there's a risk people assume that
methods like `Player.getCurrentPosition()` may return
`C.POSITION_UNSET`, when in fact unset media times (whether duration or
position) are always represented by `C.TIME_UNSET` which is a) a `long`
(not `int`) and b) a different underlying value. (aside:
`getCurrentPosition()` never returns an unset value, but it's a good
example of the ambiguity of the word 'position' between 'byte offset'
and 'media timestamp'.)
PiperOrigin-RevId: 492493102
In some cases we split a test method, and in other cases we just add
line breaks to make the separation between arrange/act/assert more
clear.
PiperOrigin-RevId: 492182769
This adds the forwarding logic for most setters in SimpleExoPlayer
in the same style as the existing logic for setPlayWhenReady.
This change doesn't implement the setters for modifying media items,
seeking and releasing yet as they require additional handling that
goes beyond the repeated implementation pattern in this change.
PiperOrigin-RevId: 492124399
This better matches the terminology we use elsewhere in the Player
interface, where items inside the playlist are referred to as
"media item" and only the entire list is called "playlist".
PiperOrigin-RevId: 491882849
To support OPUS offload, we need to provide a few configuration values
that are currently not set due to the lack of devices supporting
OPUS offload.
PiperOrigin-RevId: 491613716
This is more clear than using Format.NO_VALUE, when we do actually intend for an
output value.
Also, fix @see formatting by using summary fragments instead, and add an error
output for OETF and EOTF transfer functions.
PiperOrigin-RevId: 490910229
This change includes a change in the `IMediaController.aidl` file and needs
to provide backwards compatibility for when a client connects that is of an older or
newer version of the current service implementation.
This CL proposes to create a new AIDL method `onPlayerInfoChangedWithExtensions`
that is easier to extend in the future because it does use an `Bundle` rather than
primitives. A `Bundle` can be changed in a backward/forwards compatible way
in case we need further changes.
The compatibility handling is provided in `MediaSessionStub` and `MediaControllerStub`. The approach is not based on specific AIDL/Binder features but implemented fully in application code.
Issue: androidx/media#102
#minor-release
PiperOrigin-RevId: 490483068
If there is output data available (outputBuffer.hasRemaining()), then
there is no need to move other data between the underlying processors.
It will not change the buffer being returned by that call to getOutput.
If there is no output data readily available, it's necessary to go to
the AudioProcessors and pass buffers between them, as this may produce
data for output.
PiperOrigin-RevId: 490482653
Previously, FrameProcessor never had the usecase in which the output surface
is replaced, while previewing introduced this usecase.
When switching output surfaces, we need to destroy the EGL Surface linked to the
surface that is being swapped out, because an EGL surface is linked to the EGL
display (which is not destroyed even when releasing FrameProcessor).
A GL exception will be thrown in the following scenario if we don't destroy the
EGL surface:
1. Creates a Surface, the surface is identified by address 0x11
2. Sets Surface(0x11) on FrameProcessor. Eventually an EGL surface is created
to wrap Surface(0x11)
3. Release FrameProcess, this releases the EGL context
4. Instantiate a new FrameProcessor, sets Surface(0x11) as the output
5. When FrameProcessor creates an EGL surface to wrap Surface(0x11), GL throws
an exception, becasue Surface(0x11) has previouly been connected to an EGL
surface.
PiperOrigin-RevId: 489590072
This adds the full Builders and State representation needed to
implement all Player getter methods and listener invocations.
PiperOrigin-RevId: 489503319
Util.getAudioTrackChannelConfig() maps a channel count to a
channel mask that is passed to AudioTrack. The method expected that
playback of 8-channel audio is possible from Android 5.1 and playback of
12-channel audio is only possible from Android 12L. However, there is no
restriction on the upper number of channels that can be passed to the
AudioTrack. google/ExoPlayer#10701 is an example where the audio decoder
outputs 12 channels on an Android 10.
This change removes the restrictions for 8 and 12 channels. Note, we still
do not support playback of arbitrary number of channels as it would require
further changes to DefaultAudioSink.
#minor-release
Issue: google/ExoPlayer#10701
PiperOrigin-RevId: 488659831
When we currently trigger the iteration finished event during the
release, we don't mark the event as triggered. This means that
someone can trigger another release from within the callback,
which then tries to resend the event.
Issue: google/ExoPlayer#10758
#minor-release
PiperOrigin-RevId: 488645089
Split inner interface into separate file, which will go in common
module. The old interface will be deprecated and extends the new.
#cleanup
PiperOrigin-RevId: 483732226
Make it easier to support use of RGBA_101012 rather than RGBA_8888 for EGL
contexts, displays, and surfaces.
This tangentially supports adding HDR tests, by slightly simplifying the color
selection logic we'd have to add in HDR tests.
PiperOrigin-RevId: 482219428
Currently, repeating the same item (via seekNext/Previous) implicitly
results in a seek to the default position of the current item, which
looks exactly the same as a direct seek. As a result, we don't send
onMediaItemTransition as we would for every other seekNext/Previous
call.
This can be fixed by explicitly marking the repeat case in the internal
BasePlayer/ExoPlayerImpl methods, so that the callback can be triggered.
Issue: google/ExoPlayer#10667
PiperOrigin-RevId: 481951788
Currently, a frame is dropped if it's requested release time is in the past.
This mode was added to support previewing. However, in normal ExoPlayer
playback, slightly late frames (<30ms late) are also rendered. On MediaCodec
side, this means calling `releaseOutputBuffer` with a release time in the
past.
PiperOrigin-RevId: 479615291
This mode is supported by using `C.TIME_UNSET` (which is a negative value). The
new logic decouples the value of `C.TIME_UNSET` and the frame dropping
behaviour.
PiperOrigin-RevId: 479368880
Currently `FrameProcessor.releaseOutputFrame()` method supports
Release at a specific system time
Drops the frame
This API is not that convenient to use when the caller wants to release a frame, now, regardless of the release time. A use case is to release (present) a frame when no frame is shown for a while, and it's thus better to just release the frame, now.
Currently if MCVR wants a frame to be rendered now, MCVR calls release frame with a set offset like 10us: `releaseOutputFrame(System.nanoTime() + 10_000)`. The 10us offset is to prevent the frame processor dropping the frame, due to thread hopping delays.
To make the API better usable, consider adding a mode for releasing the frame now, like (bold marks the new mode)
- Use C.TIME_UNSET to drop
- **Use -1 to release the frame immediately, or**
- Use an actual release time.
PiperOrigin-RevId: 479044215
A follow up to stopping speaker playback with a Player decorator from
https://github.com/androidx/media/issues/15.
It looks like we will need to change to using playback suppression to avoid
errors like https://github.com/androidx/media/issues/167, when we don't start
a foreground service.
We may not have this implemented by 1.0, but would like it in the API and it seems to be appropriate.
PiperOrigin-RevId: 478835686
"Final" was likely added to reference the FinalMatrixTextureProcessorWrapper,
which is a package-private class. However, I think more clear to express that
this is the input size, which then has all effects applied, to get the output
size.
PiperOrigin-RevId: 477975358
* Before this CL, the texture was stored during the construction of the LUT processor. This failed since if one creates a list of GlEffects on the application thread, the texture will get stored in the application thread during the effect creation and not on the GL thread, which executes the FrameProcessors.
* This is an issue since the executing thread then can't index from the texture stored on a different thread.
PiperOrigin-RevId: 476388021
The stream offset is used to calculate the presentation time of
a metadata object when reading and later when playing, to calculate
the current presentation time to decide whether to send the metadata
to the output.
Accordingly, the presentation time of a pending metadata that has been
calculated with a given offset needs to be recalculated when the
stream offset changes.
#minor-release
PiperOrigin-RevId: 472499943
In particular, make it a bit more clear that "rendering" and "releasing" frames are
related concepts, and how they differ from one another in conjunction with frame
dropping.
PiperOrigin-RevId: 471037733
Use the PQ OETF and EOTF to ensure that intermediate fragment shader operations
using PQ are in linear BT.2020 rather than PQ and HLG-1 BT.2020.
Also, swap the OETF and EOTF in shaders, as they were used incorrectly before
Manually tested by verifying transformer demo HLG and PQ videos look the same with and without this CL, including with a BitmapOverlayProcessor enabled to test flows both with one MatrixTransformationProcessor that skips HDR TFs, and with one that doesn't.
PiperOrigin-RevId: 469736067
Adds a method to FrameProcessor.Listener to be called when an
output frame is available and a method releaseOutputFrame in
FrameProcessor allowing the caller to trigger release of the
oldest available output frame at a given timestamp. Late frames
or frames with unset release times are dropped in the
FinalMatrixTransformationProcessorWrapper.
More than one output frame can become available before they are
released if the penultimate GlTextureProcessor is capable of producing
multiple output frames. Processing continues while waiting for
releaseOutputFrame to be called. Frame release tasks are prioritized
over other tasks.
PiperOrigin-RevId: 468473072
We create an empty CueGroup in many places as default or
where none is needed. Instead, we can define a constant
for this purpose and reuse it.
PiperOrigin-RevId: 467944841
This base class will simplify the implementation of custom
Player classes. The current version only supports
available commands and playWhenReady handling.
PiperOrigin-RevId: 467618021
While HDR is most closely tied to the color transfer (ex.
COLOR_TRANSFER_SDR is the only one explicitly mentioning dynamic
range), technically color spaces may be associated with HDR as well,
like BT.2020 commonly being used for HDR rather than BT.709 for SDR.
Therefore, it's more specific to mention just that the transfer is HDR.
PiperOrigin-RevId: 466316960
This allows the GlEffectsFrameProcessor to later handle HLG and PQ
differently, or limited and full color range differently.
No functional change intended in this CL.
PiperOrigin-RevId: 466070764
Format.NO_VALUE is a placeholder value for an invalid @C.ColorTransfer, used
for example when the decoder doesn't support this transfer function.
When encountering this invalid value, interpret this as COLOR_TRANSFER_SDR.
Confirmed locally that an exception is thrown when transcoding on p4head, and no exception is thrown when transcoding with this CL.
PiperOrigin-RevId: 464135080
This will allow effects preview in ExoPlayer to use the
Effect and FrameProcessor interface (and the interfaces
they depend on) without depending on transformer or the
future effects module.
PiperOrigin-RevId: 464060047
* Sets KEY_HDR_STATIC_INFO from MediaFormat in the DefaultCodec.
* Adds checks in mediaparser to ensure color space, range, and transfer are valid
values.
PiperOrigin-RevId: 463921325
This adds two methods that are helpful when working with Futures.
One is a version of postOrRun that can indicate completion by a
Future and the other is a simplified version of Guava's
Futures.transformAsync (which can't be used as it's in Beta).
PiperOrigin-RevId: 461896598
This will help developers self-diagnose issues like Issue: google/ExoPlayer#10392
where the NPE occurs far from the original null value because a field
gets assigned to null.
This change aims to ensure that every stable method on Player,
ExoPlayer and ExoPlayer.Builder that takes a non-null type will fail
with an NPE before returning.
#minor-release
PiperOrigin-RevId: 461846580
* Introduced `useHdr` for `GlEffect#toGlTextureProcessor`, so
`TextureProcessor` implementations can decide how to handle HDR.
* Creating FP16 color textures for HDR input.
Tested via manual testing, adding a no-op GlEffectWrapper to the transformation to
force use of intermediate textures, adding a linear ramp to the fragment shader,
and trying to ascertain that there's a real reduction in posterization when
switching from 4-bit to 8-bit unsigned bytes, and again from 8-bit unsigned bytes
to 16-bit floating point.
PiperOrigin-RevId: 461613117
I don't think it's useful to keep these in numerical order, it makes
more sense to keep them grouped into a 'logical' ordering.
#minor-release
PiperOrigin-RevId: 460453464
This extension is needed for editing HDR input with OpenGL, as the
ExternalTextureProcessor samples raw YUV values from the
external texture for HDR and converts them to RGB itself rather than
relying on the OpenGL driver to do this automatically as for SDR.
PiperOrigin-RevId: 460424154
The SDR constant also specified a color space and range, in addition to
C.COLOR_TRANSFER_SDR. However, it turns out that SDR videos may use different color
space and range values, so following prior ExoPlayer conventions to have `null`
mean "generic SDR" is preferable here.
PiperOrigin-RevId: 459296746
If the input is HDR (HLG), check encoder capabilities for HDR support
and request tone-mapping to SDR during decoder configuration otherwise.
Capabilities are only checked for API 31 and above, as HDR editing is
not supported before.
As the encoder capabilities check needs to happen before selecting the
encoder to use (as this may depend on the resolution output by the
effects chain), the EncoderWrapper checks all candidate encoders
for the MIME type for HDR capabilities and only requests fallback to
SDR if none of them support it.
When the actual encoder is selected, the wrapper checks that it matches
one of the encoders is checked capabilities for.
PiperOrigin-RevId: 458511599
Configure the GL shaders and encoder to take in HDR metadata.
This mostly just consists of passing the Format.colorInfo through
the VideoTranscodingSamplePipeline down to the encoder, rather than passing
the PQ-ness down to the GL step.
Due to b/237674316, this will remove HDR10+ support temporarily to introduce
support for HLG10.
Manually tested to confirm that HLG10 operations that don't affect color display
correctly after this CL with "HDR editing" in the demo checked, and continue to display incorrectly (as before this CL) without the option unchecked.
PiperOrigin-RevId: 458490810
Previously two timelines that differed only in shuffle order were
considered equal, which resulted in no call to
Player.Listener.onTimelineChanged when calling
ExoPlayer.setShuffleOrder. This in turn resulted in no call to
MediaControllerCompat.Callback.onQueueChanged.
Also make a small fix inside ExoPlayerImpl.setShuffleOrder, to ensure
that the new shuffle order is used when constructing the masked
timeline.
Issue: google/ExoPlayer#9889
#minor-release
PiperOrigin-RevId: 457703727
The native GL errors are in an arbitrary order according to
https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glGetError.xml
This means any of them could contain the most useful message
so it's better to use all for the GlException's message rather than
picking the last message and logging all others.
PiperOrigin-RevId: 454130460
Transformer always enabled glAssertionsEnabled, so there should
be no functional change.
ExoPlayer previously disabled glAssertionsEnabled, so GlUtil logged
GlExceptions instead of throwing them. The GlExceptions are now
caught and logged by the callers so that there should also be no
functional change overall.
This change also replaces EGLSurfaceTexture#GlException with
GlUtil#GlException.
PiperOrigin-RevId: 453963741
Some Player implementations have no playlist capability but can still
set a MediaItem for playback. Examples are a MediaController connected
to a legacy MediaSession, ExoPlayer up to 2.12 or MediaPlayer.
To indicate this capability, we need an allowed command in addition
to COMMAND_CHANGE_MEDIA_ITEMS that just allows to set a single item
that replaces everything that is currently played.
#minor-release
PiperOrigin-RevId: 453879626
SingleFrameGlTextureProcessor is now an abstract class containing a
default implementation of the more flexible GlTextureProcessor interface
while still exposing the same simple abstract methods for single frame
processing it previously did.
FrameProcessorChain and GlEffect will be changed to use
GlTextureProcessor in follow-ups.
PiperOrigin-RevId: 453633000
The current setup with distinct, private `keyForField` implementations,
leaves open the (theoretical) possibility of a clash in the `Bundle`
keys used by the superclass and subclass. This change brings
consistency with our only other extensible `Bundleable` type
(`PlaybackException`).
#minor-release
PiperOrigin-RevId: 453385875
We generally nest the `Builder` for `Foo` inside `Foo`. In this case,
there's already a `DefaultTrackSelector.Parameters.Builder` type visible
to a developer, it just happens to be the 'common'
`TrackSelectorParameters.Builder`, so using it is a bit weird. For
example this code snippet doesn't compile because
`DefaultTrackSelector.Parameters.Builder#build()` returns
`TrackSelectionParameters`. This CL fixes that problem and the code
snippet now compiles.
```java
DefaultTrackSelector.Parameters params =
new DefaultTrackSelector.Parameters.Builder(context).build()
```
#minor-release
PiperOrigin-RevId: 453215702
This is done by removing the `@FieldNumber` IntDef completely. It's not
really adding much value anyway, because it's `open` so there's no real
enforcement to prevent passing 'incorrect' values.
#minor-release
PiperOrigin-RevId: 452108972
This value only existed to allow setting media URLs from external sources
(e.g. in a MediaController) so that a player can start playing this item.
Now that we have MediaItem.RequestMetadata.mediaUrl we can remove this value
from MediaMetadata because it's request metadata, not media metadata.
PiperOrigin-RevId: 451857413
These fields can be used to transport additional request properties
when the requester doesn't know the details needed for the actual
playback (i.e. the LocalConfiguration).
PiperOrigin-RevId: 451857093
* Rename (via deprecation)
`MediaItem.DrmConfiguration.Builder#forceSessionsForAudioAndVideoTracks`
to `setForceSessionsForAudioAndVideoTracks`. This is more consistent
with existing 'force' method names both in this class and in
`TrackSelectionParameters.Builder`.
* Add missing `@Nullable` annotation to the parameter for
`MediaItem.SubtitleConfiguration.Builder#setMimeType`. This annotation
is already present on the `MediaItem.SubtitleConfiguration#mimeType`
field that this setter corresponds to.
PiperOrigin-RevId: 450941336
This value is only needed by subclasses of `Rating`, all of which are
in this package (the `Rating` constructor is already package-private to
ensure this).
PiperOrigin-RevId: 450886872
This detection relies on an unsupported workaround and may trigger
permission warnings in tools analyzing permission usage although
no permission is needed or requested by app code.
Given the majority of 5G-NSA playbacks are on API 31+ by now,
we can remove this path to avoid the permission confusion and the
unsupported detection workaround.
PiperOrigin-RevId: 450382586
We need to pass timestamp for the list of cues so we are defining a new class CueGroup which will store both cues and timestamp.
PiperOrigin-RevId: 449212054
The MMWAVE constant was deprecated in favour of a new constant
with a better name. Thus, we need to check for both constants now.
PiperOrigin-RevId: 449018959
This is an individual language (ISO 639-3) part of the Arabic
macrolanguage ("ar" in ISO 639-1). Add this mapping to our
existing list similar to other individual to macrolanguage
mappings we have already.
Issue: Issue: google/ExoPlayer#10255
PiperOrigin-RevId: 448911950
When using a MatrixTransformationFrameProcessor per transformation
matrix, each frame processor's shader applies the matrix to the
vertices and clips the result to the NDC range when drawing the
output frame.
This change combines consecutive MatrixTransformations into a single
MatrixTransformationFrameProcessor by multiplying the individual
matrices while updating and clipping the visible polygon after
each matrix and mapping the resulting visible polygon back to the
input space so that its vertices and the combined transformation
matrix can be used in the shader.
PiperOrigin-RevId: 448521068
This listener replaces
FrameProcessorChain#getAndRethrowBackgroundExceptions.
The listener uses a new exception type FrameProcessingException
separate from TransformationException as the frame processing
components will be made reusable outside of transformer soon.
PiperOrigin-RevId: 447455746
This constant is used for https://docs.gl/es2/glVertexAttribPointer
which takes the number of components per generic vertex attribute
(meaning the size of the individual coordinate vectors here) not the
number of attributes (the number of vertices that the old constant
name referred to).
PiperOrigin-RevId: 447427241
Some APIs from Android 12L were used either via reflection or
constants values were hard-coded. We can now use these APIs directly
since we upgraded the compile SDK version to 32.
PiperOrigin-RevId: 446167543
This is consistent with the IntDef name, and frees up the CONTENT_TYPE_
prefix for the @ContentType values (which are currently just TYPE_*,
and therefore ambiguous with lots of other 'type' values in C).
PiperOrigin-RevId: 445356476
This method was introduced in e414f0d2ac
as a replacement for Util.inferContentType(String) but it incorrectly
didn't return TYPE_SS when passed "ism" or "isml".
PiperOrigin-RevId: 445217167
This fixes some small niggles:
1. `inferContentType(String)` is documented to take a path, but in the
tests we're passing full URIs.
2. A `String` parameter is usually a path, but also a MIME type or an
extension. In the new methods, the meaning of a `String` parameter
is always clear from the name of the method.
3. `inferContentType(String)` is always passed an extension in
'production' code (which has to be manually prefixed with a dot).
4. `inferContentType(Uri, @Nullable String)` always ignores the Uri if
the String is non-null. IMO this logic is clearer to a reader if it's
just in-lined at the call-site.
These methods are used from the demo apps, so will be part of the stable
API.
PiperOrigin-RevId: 444826053
The DefaultMediaNotificationProvider checks if a command is available
before putting the respective action in the notification.
PiperOrigin-RevId: 440114422
PeriodicDimmingFrameProcessor is an example of how a custom fragment
shader can be used to apply color changes that change over time.
PiperOrigin-RevId: 439840609
App code should get all of this information from TrackGroupInfo,
and should only need TrackGroup as a key to use for overrides.
PiperOrigin-RevId: 438840925
This provides better compatibility with MediaExtractor, which does read these fields; we also need them for being able to mux file contents into another mp4 file.
Also, there is a minor refactor included so that we have an actual type for esds box contents instead of a pair.
PiperOrigin-RevId: 438673825
The placeholder surface is either EGL_NO_SURFACE or a 1x1 pbuffer
depending on whether the device supports EGL_KHR_surfaceless_context.
PiperOrigin-RevId: 438541846
This is basically 'container' and 'subtitle' MIME types
I previously avoided stabilising any 'custom' MIME types (those
containing '/x-') but it certainly seems reasonable to expect
developers to use APPLICATION_M3U8 and so then it also makes sense
to stabilise other 'similar' custom MIME types too.
PiperOrigin-RevId: 438501642
This requires an additional nanos to micros conversion because
the SurfaceTexture uses nanos. But as the timestamps from the
MediaCodec decoder (propagated in DefaultCodec#releaseOutputBuffer) are
in microseconds no precision is lost here.
Also add test that checks output video duration.
PiperOrigin-RevId: 438010490
* The AdvancedFrameProcessor calls use() in updateProgramAndDraw().
* The AdvancedFrameProcessor has the same input and output dimensions.
PiperOrigin-RevId: 437231350
The FrameProcessorChain manages a List<GlFrameProcessor>.
FrameProcessorChainDataProcessingTest now tests chaining ScaleToFit-
and AdvancedFrameProcessors.
PiperOrigin-RevId: 436468037
ExternalCopyFrameProcessor's output dimensions match the input
size not the output size. So the intermediate texture size
should match the input size.
Also rename configureOutputDimensions to configureOutputSize.
PiperOrigin-RevId: 435058789
More info: go/lsc-assertthrows and go/assertthrows
NOTE: if the source of truth for this code is _NOT_ `//third_party/`, please ask for this CL to be reverted.
Tested:
TAP --sample ran all affected tests and none failed
http://test/OCL:434925976:BASE:434869111:1647399186064:de338189
PiperOrigin-RevId: 435047509
* Move auto-adjustments for transformation matrices from the
VideoTranscodingSamplePipeline constructor to the new
ScaleToFitFrameProcessor.
* Add GlFrameProcessor#getOutputDimensions() to allow for GlFrameProcessors with
different input and output dimensions. This is a prerequisite for
Presentation.
* Tested with unit tests (and manually just in case).
* A follow up CL will implement change the FrameProcessor input to be scale and
rotate values as requested by the user. This was kept out of this CL to
reduce CL review size. Presentation will also be implemented in a follow up
CL.
PiperOrigin-RevId: 434774854
This fixes an exception thrown when parceling becasue the type can not be found
(expects the AdsPlaybackState to be Serializable). Transforming the map and the
ad playback states to a Bundle fixes the problem.
#minor-release
PiperOrigin-RevId: 433491993
This constructor always does the wrong thing for non-adaptive groups
containing more than 1 track, because it'll incorrectly generate an
adaptive selection. Replace it with a constructor for specifying a
single track within the group instead.
PiperOrigin-RevId: 431673458
Only log GL exceptions in GlUtil if they aren't thrown. Otherwise,
it's up to the caller whether or not to log them to avoid logging them
twice.
PiperOrigin-RevId: 431657397
As evidenced by the somewhat awkward logic in PlayerControlView, the
previous design wasn't very friendly to expected usage. There will be
more usage when the track selection dialog components are migrated,
which would be similarly awkward without this change.
PiperOrigin-RevId: 431407675
getCurrentTrackGroups and getCurrentTrackSelections are
retained for now, but moved from Player to ExoPlayer, to
ease the transition for some application code that currently
uses these methods.
PiperOrigin-RevId: 430036355
isTypeSupportedOrEmpty is very specific and a little hard to
understand unless you know the one thing it's useful for. This
commit replaces it with isTypeSupported, which can be used in
conjunction with the recently added containsType method.
PiperOrigin-RevId: 429312712
The track type is derived solely from the content. It does
not depend on any runtime properties such as the player's
capabilities of user track selection. Hence it belongs in
TrackGroup rather than TrackGroupInfo.
Note that this avoids TrackSelectionOverride from having to
re-derive the track type internally.
PiperOrigin-RevId: 429303312
We need TracksInfo.hasTracksOfType to determine which tabs to
display in TrackSelectionDialog.
We need TrackGroupInfo.isAdaptiveSupported to determine whether
to allow multiple selection (check boxes) or not (radio buttons).
PiperOrigin-RevId: 428793739
Ignorable ad periods are skipped to resolve the media period id with the
ad playback state of the resulting period. In case of a change in the period
position un-played ad periods are rolled forward to be played.
PiperOrigin-RevId: 428011116
And also add a test that all Player.Listener events are forwarded
to AnalyticsListener.
The AnalyticsCollector also needlessly implemented
Video/AudioRendererEventListener, which is not needed because all of
the equivalent methods are called directly and never through the
interface.
#minor-release
PiperOrigin-RevId: 427478000
There are two sets of listeners in ExoPlayerImpl at the moment,
which can be merged together to use a single ListenerSet. This has
the added advantage that the events that were previously sent
through the ArraySet get additional guarantees provided by ListenerSet
(e.g. correct event ordering and onEvents triggered).
Also add missing constants for onEvents to ensure all Player.Listener
methods have an corresponding constant.
#minor-release
PiperOrigin-RevId: 427415349
This ensures Kotlin usages of these IntDef annotations in the 'old'
position will continue to compile.
'Frequently used' is a subjective judgement. I have a parallel change
that marks all the other public IntDefs in the library as TYPE_USE
(those that I've judged to be 'rarely used' by apps).
A follow-up change will fix the positions of existing usages to be as if
they're only TYPE_USE.
#minor-release
PiperOrigin-RevId: 426427334
This is a breaking change if the annotation itself is in use in Kotlin
code. It's judged that the IntDefs in this commit are unlikely to be
referred to often in Kotlin code. This is because they're either:
- Related to esoteric parts of the library, or
- In a common part of the library but only returned from methods (and
never passed to callback methods).
A follow-up change will fix the positions of existing usages to match
this new config.
#minor-release
PiperOrigin-RevId: 426410237
This is not backwards compatible if the @SelectionReason annotation is
used in Kotlin code, but before this change there aren't many library
surfaces that return a value annotated with @SelectionReason, so it
seems relatively unlikely that it is in use in any/many apps.
A follow-up change will fix the positions of existing usages to match
this new config.
#minor-release
PiperOrigin-RevId: 426409877
This is only used inside AudioFocusManager, it doesn't need to public.
Also mark it TYPE_USE and update the position to match.
#minor-release
PiperOrigin-RevId: 426407790
This is only used in DefaultAudioSink, so we could move it there and
make it private - but at that point we might as well refer to the
underlying AudioManager constants instead.
#minor-release
PiperOrigin-RevId: 426407661
This only changes IntDefs that cannot be used by apps because they're
either private or package-private.
A follow-up change will fix the positions of existing usages to match
this new config.
#minor-release
PiperOrigin-RevId: 426372273
This makes the delegation model more explicit, and prevents the javadoc
compiler from just pulling in the Player javadoc automatically - which
can lead to some confusion when some method definitions in Player depend
on other methods (e.g. seekForward() is defined in terms of
getSeekForwardIncrement()).
Issue: google/ExoPlayer#9897
#minor-release
PiperOrigin-RevId: 426359004
These were messed up in 74c6ef9ba0
Also suppress deprecation warnings when we're just forwarding a
deprecated method to the delegate.
#minor-release
PiperOrigin-RevId: 426351791
This change makes GlUtil.Program an outer class named GlProgram,
and also moves private static helpers as well as the inner classes
Attribute and Uniform which were only used by GlUtil.Program to
GlProgram. Other static utility methods remain in GlUtil.
No functional changes intended.
PiperOrigin-RevId: 426119299
The longer list of targets is only necessary for backwards
compatibility with existing Kotlin code that will stop compiling
if the position of the annotation becomes 'wrong' by marking it only
TYPE_USE. Since none of these IntDefs have been released (except in
media3 alpha1) we don't need to maintain this compatibility.
Also add a comment to all the places that *do* need the longer list of
targets, in order to explain why it's there and discourage copy-pasting
when defining new IntDefs in future.
Also fix some single-element arrays to remove the array notation.
#minor-release
PiperOrigin-RevId: 426108537
- Add a checkbox in the demo app to enable experimental HDR editing.
- Add an `experimental_` method to `TransformationRequest` to enable HDR editing.
- Add fragment/vertex shaders for the experimental HDR pipeline. The main difference compared to the existing shaders is that we sample from the decoder in YUV rather than RGB (because the YUV -> RGB conversion in the graphics driver is not precisely defined, so we need to do this to get consistent results), which requires the use of ES 3, and then do a crude YUV -> RGB conversion in the shader (ignoring the input color primaries for now).
- When HDR editing is enabled, we force using `FrameEditor` (no passthrough) to avoid the need to select another edit operation, and use the new shaders. The `EGLContext` and `EGLSurface` also need to be set up differently for this path.
PiperOrigin-RevId: 425570639
When the media3 modules are referred from an external project and
gradle.ext.androidxMediaModulePrefix is specified, build error occurs
like the following.
> gradle.ext.androidxMediaModulePrefix = "media-"
> A problem occurred evaluating project ':media-lib-common'.
> > Project with path ':media-media-lib-cast' could not be found in project ':media-lib-common'.
As you can see, the build script of the common module is trying to
use an incorrect named project which has duplicated prefixes.
To avoid the `MediaPeriodQueue`to discard the reading period, we can set the next ad of an ad group early and then (possibly) only change it's duration once we receive the actual duration. This way we avoid a rebuffering as a result of the reading period being discarded.
The change also takes care to properly set ad break and their durations when we join the live stream at the moment when an ad is playing.
PiperOrigin-RevId: 423163467
Simplifying and clarifying variables, and adding comments.
Tested by confirming demo-gl and demo-transformer both
correctly display videos
PiperOrigin-RevId: 421792079
The existing wording would be correct if prefixed with
"Returns false if [...]", but it seems confusing to a document a boolean
method in terms the condition it returns false - so I reworded it in
terms of when it returns true.
#minor-release
PiperOrigin-RevId: 421682584
The common module now defines all other released targets as constraints,
which ensures they must have matching versions. As all other libraries
indirectly depend on the common module, this declaration is only needed
in here.
PiperOrigin-RevId: 419776578
This involves stabilising AdsLoader and ImaAdsLoader, as well
as (Default)MediaSourceFactory and the following methods on
ExoPlayer.Builder:
* setMediaSourceFactory
* setAdsLoaderProvider
* setAdViewProvider
Most of ImaAdsLoader.Builder and (Default)MediaSourceFactory remain
unstable for now.
PiperOrigin-RevId: 417814106
For the media3 codebase the timeline images need to be under the common module.
Verified results in an empty commit for ExoPlayer GitHub.
PiperOrigin-RevId: 416850853
UnsupportedEglVersionException() is only used once, and seems a bit too
specific for Transformer. Also, it's possible for eglCreateContext to fail for
other reasons besides lack of support, so it wasn't always accurate when
thrown.
It is possible for devices not to support EGL version 2.0 though, per
https://source.android.com/devices/graphics/implement-opengl-es, which doesn't
specify the EGL version that must be supported.
PiperOrigin-RevId: 415489396
*** Original commit ***
Make audio track min buffer size configurable.
Move the code in its own class as DefaultAudioTrack
is getting very big. It also help for testability.
The new class is easily configurable and highly tested.
Manual test was used to catch any regression.
https://github.com/google/ExoPlayer/issues/8891
***
PiperOrigin-RevId: 415469179
Refactor GlUtil.java to be a bit more readable. Also, reorder, inline, and
rename a few things. Refactoring change only. No functional changes intended.
PiperOrigin-RevId: 415283874
Move the code in its own class as DefaultAudioTrack
is getting very big. It also help for testability.
The new class is easily configurable and highly tested.
Manual test was used to catch any regression.
https://github.com/google/ExoPlayer/issues/8891
PiperOrigin-RevId: 415268938
The new field matches the platform's
AudioAttributes.getSpatializationBehavior() API added in Sv2. At the
moment, the platform API is called via reflection, until Sv2 is released
and the compile SDK target can be increased to 32.
PiperOrigin-RevId: 414406126
When calling Android's Log class directly, there's a LongLogTag
lint check that detects tags over the 23 char limit, however it
cannot detect long log tags in ExoPlayer due to the way that we
log via our own Log class. This commit adds @Size annotations to
enforce the same rule.
PiperOrigin-RevId: 413976364
Allowing duplicate groups caused some other code working with the
array to use reference equality comparison. This is error-prone,
easily forgotten (e.g. when using the TrackGroups in a map) and
causes bugs when TrackGroups are serialized to disk or to another
process.
All TrackGroups created by ExoPlayer are already unique and custom
code creating TrackGroupArrays with identical groups can easily
distringuish them by adding an id to each group.
Issue: google/ExoPlayer#9718
PiperOrigin-RevId: 413617005
This allows to give TrackGroups an identifier. The underlying goal is
to provide a way to make otherwise identical TrackGroups
distinguishable.
Also set this id in all internal sources that may produce identical
TrackGroups in certain edge cases.
Issue: google/ExoPlayer#9718
PiperOrigin-RevId: 413430719
This is already called in GlUtil.Program().
Tested by confirming that the demo-gl target still runs as expected.
Refactoring change only. No intended functional changes.
PiperOrigin-RevId: 412308564
And also tweak existing role flag logic to strictly prefer perfect
matches over partial matches.
Caveat: Video role flags only supported for fixed track selections
(same issue as Issue: google/ExoPlayer#9519).
Issue: google/ExoPlayer#9402
PiperOrigin-RevId: 412292835
This inheritance is really confusing because ExoPlayerImpl is not
a full Player interface implementation. It also claims to be an
ExoPlayer implementation in the Javadoc which isn't true in its
current state.
Removing the inheritance also allows to clean up some unused methods.
PiperOrigin-RevId: 411756963
Before this change ExpPlayerImplInternal dropped a change of the playing period when a change in the timeline occurred that actually changed the playing period but we don't want to update the period queue. This logic also dropped the update of a skipped server side inserted preroll ad for which we want the periodQueue to 'seek' to the stream position after the preroll ad and trigger a SKIP discontinuity.
This change now introduces an exception so that a skipped SSI ad is still causing an update in the period queue which leads to a 'seek' and a discontinuity of type SKIP.
PiperOrigin-RevId: 411607299
Document that apps should retain `GlUtil.Program` while the program is in use,
and keep a reference to attributes/uniforms within the program to make sure
they don't get GC'd causing any allocated buffers passed to GL to become
invalid.
Tested manually by running gldemo and transformer.
PiperOrigin-RevId: 411516894
The player will not play ads in final states (played, skipped, error)
again. To allow ads loader customizations to play ads again, we can
add a method that resets the state back to available or unavailable
(depending on whether we have the URI for the ad).
Issue: google/ExoPlayer#9615
PiperOrigin-RevId: 411042842
Populate ICY headers into MediaMetadata so that they can
propagate to the app via AnalyticsListener#onMediaMetadataChanged().
This change copies IcyHeaders.name into MediaMetadata.description
and IcyHeaders.genre into MediaMetadata.genre.
Note: MediaItem.metadata maintain their precedence and overwrite any
ICY headers parsed.
Issue: google/ExoPlayer#9677
#minor-release
PiperOrigin-RevId: 410495676
The main point of the IDLE state is that the player is not holding
resources. Clarify this in the documentation of STATE_IDLE, prepare and
stop.
PiperOrigin-RevId: 409950785
This method is helpful when iterating the list of track overrides
to figure out which type the override applies to.
Issue: google/ExoPlayer#9665
PiperOrigin-RevId: 409108977
And in a couple of related places.
This is for consistency with the rest of the codebase where
we exclusively use indices.
#minor-release
PiperOrigin-RevId: 408273372
* Remove GlUtil.Program String[] constructor to unify and just use the
String constructor.
* Add getAttributeArrayLocationAndEnable() to simplify things a tiny bit.
* Increase usage of constant values.
PiperOrigin-RevId: 407570340
Where this introduced an inconsistency (e.g. assigning to something
called `windowIndex`), I generally renamed the transitive closure of
identifiers to maintain consistency (meaning this change is quite
large). The exception is code that interacts with Timeline and Window
directly, where sometimes I kept the 'window' nomenclature.
#minor-release
PiperOrigin-RevId: 407040052
The video scaling mode and stream type defines a default constant
that needs to be added to the IntDef definition to be assignable.
PiperOrigin-RevId: 406835696
This allows the use of the intdef in parameterized types,
e.g. List<@MyIntDef Integer>
For IntDefs that are already released in ExoPlayer 2.15.1 we add
TYPE_USE in addition to all other reasonable targets, to maintain
backwards compatibility with Kotlin code (where an incorrectly
positioned annotation is a compilation failure). 'reasonable targets'
includes FIELD, METHOD, PARAMETER and LOCAL_VARIABLE but not TYPE,
CONSTRUCTOR, ANNOTATION_TYPE, PACKAGE or MODULE. TYPE_PARAMETER is
implied by TYPE_USE.
For not-yet-released IntDefs we just add TYPE_USE.
#minor-release
PiperOrigin-RevId: 406793413
Only deprecated references remain.
Usages of the deprecated methods will be migrated in a follow-up change.
#minor-release
PiperOrigin-RevId: 405927141
Our package-info.java files are annotated with @NonNullApi which results
in everything being non-null by default, so this annotation is never
needed.
#minor-release
PiperOrigin-RevId: 405864737