Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AC-4 Level-4 ISO base media file format support #875

Closed
wants to merge 530 commits into from

Conversation

ybai001
Copy link
Contributor

@ybai001 ybai001 commented Dec 8, 2023

AC-4 Level-4 (Object Based Audio) is a Dolby official audio stream type for Atmos Music. This code update enables Android Media3 support local MP4 and MPEG-DASH AC-4 Level-4 playback.

An independent test asset and test case contribution will be provided later. (We are preparing for a suitable test asset now.)

tonihei and others added 30 commits October 19, 2023 01:03
PiperOrigin-RevId: 574766164
(cherry picked from commit f0cab4d)
If an app rejects the connection of the internal media notification manager
the session should behave like without the the media notification controller.
The legacy System UI controller should not be hidden or even rejected to
connect in such a case.

#minor-release

PiperOrigin-RevId: 574807901
(cherry picked from commit 54d5810)
PiperOrigin-RevId: 574829263
(cherry picked from commit 5f80a47)
Player methods shouldn't be called if they are not available and the
entry point to the playback resumption flow only checks
COMMAND_PLAY_PAUSE.

#minor-release

PiperOrigin-RevId: 574834148
(cherry picked from commit bfd1a27)
The CompositionPlayer is not ready yet.

Issue: androidx#741
PiperOrigin-RevId: 574859927
(cherry picked from commit beb1711)
#minor-release

PiperOrigin-RevId: 575161190
(cherry picked from commit a8ab9e2)
This change moves the handling of any media button event into
`MediaSessionImpl.onMediaButtonEvent(intent)`. This includes
the double click handling from `MediaSessionLegacyStub`.

The advantage is that everything is in one place which allows
to offer `MediaSession.Callback.onMediaButtonEvent` with which
an app can override the default implementation and handle media
buttons in a custom way.

Media button events can originate from various places:

- Delivered to `MediaSessionService.onStartCommand(Intent)`
  - A `PendingIntent` from the notification below API 33
  - An `Intent` sent to the `MediaButtonReceiver` by the system dispatched
    to the service
- Delivered to `MediaSessionCompat.Callback.onMediaButtonEvent(Intent)`
  implemented by `MediaSessionLegacyStub` during the session is active
  - Bluetooth (headset/remote control)
  - Apps/system using `AudioManager.dispatchKeyEvent(KeyEvent)`
  - Apps/system using `MediaControllerCompat.dispatchKeyEvent(keyEvent)`

Issue: androidx#12
Issue: androidx#159
Issue: androidx#216
Issue: androidx#249

#minor-release

PiperOrigin-RevId: 575231251
(cherry picked from commit a79d44e)
This currently only applies to subtitles muxed into mp4 segments, and
not standalone text files linked directly from the manifest.

Issue: androidx#288

#minor-release

PiperOrigin-RevId: 572263764
(cherry picked from commit 66fa591)
This allows to disable periodic position updates when building
the session.

#minor-release

PiperOrigin-RevId: 572531837
(cherry picked from commit 4dc3db4)
#minor-release

PiperOrigin-RevId: 572556101
(cherry picked from commit c7a091a)
Issue: androidx#721
PiperOrigin-RevId: 572565009
(cherry picked from commit cef85be)
When the controller of the `MediaNotificationManager` is disconnected,
the session is removed from the service without checking whether the
session hasn't already been removed. This caused flakiness in `MediaSessionServiceTest.addSession()`.

Because there is a public API `MediaSessionService.removeSession()`,
the controller can't make an assumption whether the session is still
contained in the service when being disconnected.

#minor-release

PiperOrigin-RevId: 572568350
(cherry picked from commit 7fdc5b2)
A few methods in PlayerInfo and related classes combine filtering
information with bundling in one method. This makes it impossible
to use just the filtering for example and it's also easier to reason
about than two dedicated methods. This change splits these methods
into two parts accordingly.

PiperOrigin-RevId: 572592458
(cherry picked from commit 4ebe630)
PlayerInfo bundling is costly and we can add a shortcut for
in-process binder calls where we store the direct object
reference in a live Binder object that can be written to the
Bundle instead of the individual data fields.

#minor-release

PiperOrigin-RevId: 572816784
(cherry picked from commit d1fc15f)
All the production code is already calling these new incremental
methods, migrating the tests allows us to remove the old
`List`-returning methods in a follow-up change.

#minor-release

PiperOrigin-RevId: 572822828
(cherry picked from commit a12bde4)
…flow-fix

PiperOrigin-RevId: 572864175
(cherry picked from commit 2421ba4)
If the `Subtitle` has 'active' cues at `OutputOptions.startTimeUs`, this
change ensures these are emitted in a `CuesWithTiming` with
`CuesWithTiming.startTimeUs = OutputOptions.startTimeUs`. If
`OutputOptions.outputAllCues` is also set, then another `CuesWithTiming`
is emitted at the end that covers the 'first part' of the active cues,
and  ends at `OutputOptions.startTimeUs`.

As well as adding some more tests to `LegacySubtitleUtilWebvttTest`,
this change also adds more tests for `TtmlParser` handling of
`OutputOptions`, which transitively tests the behaviour of
`LegacySubtitleUtil`.

#minor-release

PiperOrigin-RevId: 573151016
(cherry picked from commit f9ece88)
This content is no longer available, the manifest is returning a 404.

Issue: google/ExoPlayer#11309

#minor-release

PiperOrigin-RevId: 573202175
(cherry picked from commit a19f577)
All production and test callers of the non-incremental methods are
already migrated, so we can remove them in this change too.

#minor-release

PiperOrigin-RevId: 573207318
(cherry picked from commit ecd2464)
PiperOrigin-RevId: 573220915
(cherry picked from commit 40459f7)
Use a non deprecated method that takes a `notMetRequirements` parameter
instead.

PiperOrigin-RevId: 573252909
(cherry picked from commit 8b7ebc7)
Previously, we calculated the next playlist reload time by adding the target duration (or half of it, depending on whether there is a real update in the new playlist snapshot) from the last load completion time, which makes the reload interval as long as `targetDuration(or half of it) + lastLoadDuration`. While still complying to the standard that "the client MUST wait for at least the target duration before attempting to reload the Playlist file again", this could cause buffering when the playback position is close to the end of live window. This change is to calculate the reload interval accurately by not adding the term `lastLoadDuration`.

Issue: androidx#663

#minor-release

PiperOrigin-RevId: 573300009
(cherry picked from commit 58a63c8)
When MediaItems are added from the controller, we currently completely
replace the item with the one from our database, overriding any
potential additional information the controller may have set.

Also forward the onAddMediaItems/onSetMediaItems callbacks to common
helper methods instead of redirecting them through super methods

#minor-release
Issue: androidx#706
PiperOrigin-RevId: 573799351
(cherry picked from commit 00425db)
Android Auto shows a queue button when the queue is not empty.
Apps were able to remove this queue button with the legacy API
by not setting the queue of the session.

After this change, removing `COMMAND_GET_TIMELINE` from the commands
of the media notification controller or the session player sets the
queue in the platform session to null.

#minor-release
Issue: androidx#339
PiperOrigin-RevId: 573813558
(cherry picked from commit f53e1bc)
#minor-release

PiperOrigin-RevId: 573849858
(cherry picked from commit d5f093f)
Media button event coming from the `MediaSessionService` are delegated
to the `MediaSessionImpl` and then sent to the session by using the
`MediaSessionStub` directly instead of using the `MediaController`
API.

Splitting the `MediaController.Listener` and `Player.Listener` in
`MediaNotificationManager` got reverted, and both listener are set to the
controller as before. This reverts the change that introduced a
different timing behaviour. It still holds, that a listener
registered on a `MediaController` that calls a method like `play()` is
called immediately and before the call has arrived at the player. This
change works around this behaviour from the library side by calling
`MediaSessionStub` directly with a `ControllerInfo`.

#minor-release

PiperOrigin-RevId: 573918850
(cherry picked from commit 64bd3bc)
#minor-release

PiperOrigin-RevId: 574090381
(cherry picked from commit df19097)
PiperOrigin-RevId: 574129451
(cherry picked from commit 009d48a)
Issue: androidx#734

#minor-release

PiperOrigin-RevId: 574182702
(cherry picked from commit 61770f8)
PiperOrigin-RevId: 574290408
(cherry picked from commit 1a43aa3)
microkatz and others added 12 commits April 2, 2024 18:30
Some devices supporting Performance Points for decoder coverage are missing coverage over the CDD requirements for H264. For these cases ExoPlayer should fall back to legacy resolution and frame rate support checks. If there is a stream evaluated as a PerformancePointCoverageResult of COVERAGE_RESULT_NO, then ExoPlayer checks for coverage of the 720p H264 CDD requirement.

Issue: google/ExoPlayer#10898

Issue: androidx#693

Issue: androidx#966
PiperOrigin-RevId: 609740128
(cherry picked from commit 23a301f)
This change aims to prioritise tracks that have a 'smooth enough for
video' frame rate, without always selecting the track with the highest
frame rate.

In particular MP4 files extracted from motion photos sometimes have two
HEVC tracks, with the higher-res one having a very low frame rate (not
intended for use in video playback). Before this change
`DefaultTrackSelector` would pick the low-fps, high-res track.

This change adds a somewhat arbitrary 10fps threshold for "smooth video
playback", meaning any tracks above this threshold are selected in
preference to tracks below it. Within the tracks above the threshold
other attributes are used to select the preferred track. We deliberately
don't pick the highest-fps track (over pixel count and bitrate), because
most users would prefer to see a 30fps 4k track over a 60fps 720p track.

This change also includes a test MP4 file, extracted from the existing
`jpeg/pixel-motion-photo-2-hevc-tracks.jpg` file by logging
`mp4StartPosition` in
[`MotionPhotoDescription.getMotionPhotoMetadata`](https://github.com/androidx/media/blob/b930b40a16c06318e43c81771fa2b1024bdb3f29/libraries/extractor/src/main/java/androidx/media3/extractor/jpeg/MotionPhotoDescription.java#L123)
and then using `dd`:

```
mp4StartPosition=2603594

$ dd if=jpeg/pixel-motion-photo-2-hevc-tracks.jpg \
    of=mp4/pixel-motion-photo-2-hevc-tracks.mp4 \
    bs=1 \
    skip=2603594
```

----

This solution is in addition to the `JpegMotionPhotoExtractor` change
made specifically for these two-track motion photos in
androidx@5266c71.
We will keep both changes, even though that change is not strictly
needed after this one, because adding the role flags helps to
communicate more clearly the intended usage of these tracks. This
change to consider FPS seems like a generally useful improvement to
`DefaultTrackSelector`, since it seems unlikely we would prefer a 5fps
video track over a 30fps one.

Issue: androidx#1051
PiperOrigin-RevId: 611015459
(cherry picked from commit c7e00b1)
When the controller replaces the current item, the masking position will be changed to the default position of the new item for a short while, before the correct position comes from the session. This will interrupt the current position fetched from the controller when the playback doesn't interrupted by the item replacing.

Issue: androidx#951

PiperOrigin-RevId: 611417539
(cherry picked from commit 1bdc58d)
PiperOrigin-RevId: 612485043
(cherry picked from commit bbdaf2b)
The removed check searched for a player command inside a list of
session commands, which is not allowed by the IntDef definition
and only worked because both types map to a Java int.

PiperOrigin-RevId: 612758442
(cherry picked from commit c79ac5b)
PiperOrigin-RevId: 612808322
(cherry picked from commit 3a43bd7)
PiperOrigin-RevId: 613156951
(cherry picked from commit a90a704)
#minor-release

PiperOrigin-RevId: 621828038
(cherry picked from commit d57229a)
Renderers may be enabled for subsequent media items as soon as the current media item's renderer's isEnded() returns true. When a renderer is being enabled and the player is 'playing', that renderer is also started. When playing a mixed playlist of images and content with audio & video, the player may skip some image items because the early-starting of the audio renderer causes a clock update.

A solution is to only start the "early-enabled" renderers at the point of media transition and add a condition on DefaultMediaClock to use the standalone clock when reading-ahead and the renderer clock source is not in a started state.

Issue: androidx#1017
PiperOrigin-RevId: 613231227
(cherry picked from commit 638b2a3)
Issue: androidx#1051
PiperOrigin-RevId: 613516802
(cherry picked from commit afacf2c)
PiperOrigin-RevId: 622189733
(cherry picked from commit 5fc35a6)
PiperOrigin-RevId: 622211426
(cherry picked from commit 2a5b9af)
@rohitjoins
Copy link
Contributor

Hi @ybai001,

I'm running into an error when trying to import the PR: Cannot find a merge reference for Pull Request 875. It might have a conflict with head.

Could you please try rebasing the PR with the latest changes in the main branch? And I'll try importing it again.

If that doesn't work, I'm happy to manually copy the changes to avoid further delays in case you're fine with it.

@ybai001
Copy link
Contributor Author

ybai001 commented Apr 11, 2024

Hi, @rohitjoins,
When I try to do it as you said, the CLA check failed due to to many commits on my branch. Do you know how to solve it?

@rohitjoins
Copy link
Contributor

rohitjoins commented Apr 11, 2024

Hi @ybai001,

The PR currently shows many commits, you should rebase it against the main branch, so that your commits for this PR are only there.

@ybai001
Copy link
Contributor Author

ybai001 commented Apr 11, 2024

Hi @ybai001,

The PR currently shows many commits, you should rebase it against the main branch, so that your commits for this PR are only there.

Could you guide me how to do it? I have never done it on GitHub. And I can't find "rebase" button on WebUI. Thanks.

@rohitjoins
Copy link
Contributor

May be try the solution suggested here.

Basically you want to get all changes from the upstream branch main in your forked repository.

@ybai001
Copy link
Contributor Author

ybai001 commented Apr 11, 2024

It seems that there are already too many commits on this pull request. The first step should be roll un-related commits back. Do you know how to do it?

@ybai001
Copy link
Contributor Author

ybai001 commented Apr 11, 2024

May be try the solution suggested here.

Basically you want to get all changes from the upstream branch main in your forked repository.

I can't make it work but make things worse. Please manually copy the changes to avoid further delays, thanks.

@rohitjoins
Copy link
Contributor

From what I can see, the PR is against the main branch and not release, so may be try rebasing it against the main branch.

@ybai001
Copy link
Contributor Author

ybai001 commented Apr 11, 2024

From what I can see, the PR is against the main branch and not release, so may be try rebasing it against the main branch.

I tried it but the commit numbers of this pull request is already too much. Seems that I have no way to make it reduced.

@rohitjoins
Copy link
Contributor

rohitjoins commented Apr 11, 2024

You can try this:

  1. Setup GitHub CLI (https://cli.github.com/) and run below commands on a local clone of the media3 git project
  2. gh pr checkout 875
  3. git checkout main && git pull && git checkout - && git rebase main
  4. You may get some conflicts, resolve them and continue rebasing.
  5. Once done push force the changes, git push --force.

I could resolve doing the same on my end, but don't have access to push to this PR.

@ybai001
Copy link
Contributor Author

ybai001 commented Apr 11, 2024

I can't solve the problem in this pull request so that I created the new one: #1265
Please let me know whether it is OK to you. If there is no problem, I'll close this pull request and focus on the new one.

@rohitjoins
Copy link
Contributor

Hi @ybai001,

I was able to import #1265 internally. Closing this as a duplicate.

@rohitjoins rohitjoins closed this Apr 11, 2024
@androidx androidx locked and limited conversation to collaborators Jun 11, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.