Commit 706d5ac2 by manisha_jajoo Committed by GitHub

Merge branch 'main' into rtp-mpeg4

parents e7567d20 4b72335d
Showing with 1362 additions and 343 deletions
...@@ -37,6 +37,7 @@ project.ext { ...@@ -37,6 +37,7 @@ project.ext {
androidxAnnotationExperimentalVersion = '1.2.0' androidxAnnotationExperimentalVersion = '1.2.0'
androidxAppCompatVersion = '1.3.1' androidxAppCompatVersion = '1.3.1'
androidxCollectionVersion = '1.1.0' androidxCollectionVersion = '1.1.0'
androidxConstraintLayoutVersion = '2.0.4'
androidxCoreVersion = '1.7.0' androidxCoreVersion = '1.7.0'
androidxFuturesVersion = '1.1.0' androidxFuturesVersion = '1.1.0'
androidxMediaVersion = '1.4.3' androidxMediaVersion = '1.4.3'
......
...@@ -36,7 +36,7 @@ import androidx.media3.common.MediaItem; ...@@ -36,7 +36,7 @@ import androidx.media3.common.MediaItem;
import androidx.media3.common.util.Assertions; import androidx.media3.common.util.Assertions;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.ui.StyledPlayerView; import androidx.media3.ui.PlayerView;
import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
...@@ -52,7 +52,7 @@ import com.google.android.gms.dynamite.DynamiteModule; ...@@ -52,7 +52,7 @@ import com.google.android.gms.dynamite.DynamiteModule;
public class MainActivity extends AppCompatActivity public class MainActivity extends AppCompatActivity
implements OnClickListener, PlayerManager.Listener { implements OnClickListener, PlayerManager.Listener {
private StyledPlayerView playerView; private PlayerView playerView;
private PlayerManager playerManager; private PlayerManager playerManager;
private RecyclerView mediaQueueList; private RecyclerView mediaQueueList;
private MediaQueueListAdapter mediaQueueListAdapter; private MediaQueueListAdapter mediaQueueListAdapter;
......
...@@ -28,8 +28,8 @@ import androidx.media3.common.Player.TimelineChangeReason; ...@@ -28,8 +28,8 @@ import androidx.media3.common.Player.TimelineChangeReason;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.TracksInfo; import androidx.media3.common.TracksInfo;
import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.ui.StyledPlayerControlView; import androidx.media3.ui.PlayerControlView;
import androidx.media3.ui.StyledPlayerView; import androidx.media3.ui.PlayerView;
import com.google.android.gms.cast.framework.CastContext; import com.google.android.gms.cast.framework.CastContext;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -51,7 +51,7 @@ import java.util.ArrayList; ...@@ -51,7 +51,7 @@ import java.util.ArrayList;
} }
private final Context context; private final Context context;
private final StyledPlayerView playerView; private final PlayerView playerView;
private final Player localPlayer; private final Player localPlayer;
private final CastPlayer castPlayer; private final CastPlayer castPlayer;
private final ArrayList<MediaItem> mediaQueue; private final ArrayList<MediaItem> mediaQueue;
...@@ -66,11 +66,11 @@ import java.util.ArrayList; ...@@ -66,11 +66,11 @@ import java.util.ArrayList;
* *
* @param context A {@link Context}. * @param context A {@link Context}.
* @param listener A {@link Listener} for queue position changes. * @param listener A {@link Listener} for queue position changes.
* @param playerView The {@link StyledPlayerView} for playback. * @param playerView The {@link PlayerView} for playback.
* @param castContext The {@link CastContext}. * @param castContext The {@link CastContext}.
*/ */
public PlayerManager( public PlayerManager(
Context context, Listener listener, StyledPlayerView playerView, CastContext castContext) { Context context, Listener listener, PlayerView playerView, CastContext castContext) {
this.context = context; this.context = context;
this.listener = listener; this.listener = listener;
this.playerView = playerView; this.playerView = playerView;
...@@ -223,10 +223,12 @@ import java.util.ArrayList; ...@@ -223,10 +223,12 @@ import java.util.ArrayList;
if (currentPlayer != localPlayer || tracksInfo == lastSeenTrackGroupInfo) { if (currentPlayer != localPlayer || tracksInfo == lastSeenTrackGroupInfo) {
return; return;
} }
if (!tracksInfo.isTypeSupportedOrEmpty(C.TRACK_TYPE_VIDEO)) { if (tracksInfo.containsType(C.TRACK_TYPE_VIDEO)
&& !tracksInfo.isTypeSupported(C.TRACK_TYPE_VIDEO, /* allowExceedsCapabilities= */ true)) {
listener.onUnsupportedTrack(C.TRACK_TYPE_VIDEO); listener.onUnsupportedTrack(C.TRACK_TYPE_VIDEO);
} }
if (!tracksInfo.isTypeSupportedOrEmpty(C.TRACK_TYPE_AUDIO)) { if (tracksInfo.containsType(C.TRACK_TYPE_AUDIO)
&& !tracksInfo.isTypeSupported(C.TRACK_TYPE_AUDIO, /* allowExceedsCapabilities= */ true)) {
listener.onUnsupportedTrack(C.TRACK_TYPE_AUDIO); listener.onUnsupportedTrack(C.TRACK_TYPE_AUDIO);
} }
lastSeenTrackGroupInfo = tracksInfo; lastSeenTrackGroupInfo = tracksInfo;
...@@ -270,7 +272,7 @@ import java.util.ArrayList; ...@@ -270,7 +272,7 @@ import java.util.ArrayList;
R.drawable.ic_baseline_cast_connected_400, R.drawable.ic_baseline_cast_connected_400,
/* theme= */ null)); /* theme= */ null));
} else { // currentPlayer == localPlayer } else { // currentPlayer == localPlayer
playerView.setControllerShowTimeoutMs(StyledPlayerControlView.DEFAULT_SHOW_TIMEOUT_MS); playerView.setControllerShowTimeoutMs(PlayerControlView.DEFAULT_SHOW_TIMEOUT_MS);
playerView.setDefaultArtwork(null); playerView.setDefaultArtwork(null);
} }
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:keepScreenOn="true"> android:keepScreenOn="true">
<androidx.media3.ui.StyledPlayerView android:id="@+id/player_view" <androidx.media3.ui.PlayerView android:id="@+id/player_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1" android:layout_weight="1"
......
...@@ -15,19 +15,19 @@ ...@@ -15,19 +15,19 @@
#extension GL_OES_EGL_image_external : require #extension GL_OES_EGL_image_external : require
precision mediump float; precision mediump float;
// External texture containing video decoder output. // External texture containing video decoder output.
uniform samplerExternalOES tex_sampler_0; uniform samplerExternalOES uTexSampler0;
// Texture containing the overlap bitmap. // Texture containing the overlap bitmap.
uniform sampler2D tex_sampler_1; uniform sampler2D uTexSampler1;
// Horizontal scaling factor for the overlap bitmap. // Horizontal scaling factor for the overlap bitmap.
uniform float scaleX; uniform float uScaleX;
// Vertical scaling factory for the overlap bitmap. // Vertical scaling factory for the overlap bitmap.
uniform float scaleY; uniform float uScaleY;
varying vec2 v_texcoord; varying vec2 vTexCoords;
void main() { void main() {
vec4 videoColor = texture2D(tex_sampler_0, v_texcoord); vec4 videoColor = texture2D(uTexSampler0, vTexCoords);
vec4 overlayColor = texture2D(tex_sampler_1, vec4 overlayColor = texture2D(uTexSampler1,
vec2(v_texcoord.x * scaleX, vec2(vTexCoords.x * uScaleX,
v_texcoord.y * scaleY)); vTexCoords.y * uScaleY));
// Blend the video decoder output and the overlay bitmap. // Blend the video decoder output and the overlay bitmap.
gl_FragColor = videoColor * (1.0 - overlayColor.a) gl_FragColor = videoColor * (1.0 - overlayColor.a)
+ overlayColor * overlayColor.a; + overlayColor * overlayColor.a;
......
...@@ -11,11 +11,11 @@ ...@@ -11,11 +11,11 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
attribute vec4 a_position; attribute vec4 aFramePosition;
attribute vec4 a_texcoord; attribute vec4 aTexCoords;
uniform mat4 tex_transform; uniform mat4 uTexTransform;
varying vec2 v_texcoord; varying vec2 vTexCoords;
void main() { void main() {
gl_Position = a_position; gl_Position = aFramePosition;
v_texcoord = (tex_transform * a_texcoord).xy; vTexCoords = (uTexTransform * aTexCoords).xy;
} }
...@@ -27,6 +27,7 @@ import android.graphics.drawable.BitmapDrawable; ...@@ -27,6 +27,7 @@ import android.graphics.drawable.BitmapDrawable;
import android.opengl.GLES20; import android.opengl.GLES20;
import android.opengl.GLUtils; import android.opengl.GLUtils;
import androidx.media3.common.C; import androidx.media3.common.C;
import androidx.media3.common.util.GlProgram;
import androidx.media3.common.util.GlUtil; import androidx.media3.common.util.GlUtil;
import java.io.IOException; import java.io.IOException;
import java.util.Locale; import java.util.Locale;
...@@ -50,7 +51,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -50,7 +51,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private final Bitmap logoBitmap; private final Bitmap logoBitmap;
private final Canvas overlayCanvas; private final Canvas overlayCanvas;
private GlUtil.@MonotonicNonNull Program program; private @MonotonicNonNull GlProgram program;
private float bitmapScaleX; private float bitmapScaleX;
private float bitmapScaleY; private float bitmapScaleY;
...@@ -78,7 +79,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -78,7 +79,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
public void initialize() { public void initialize() {
try { try {
program = program =
new GlUtil.Program( new GlProgram(
context, context,
/* vertexShaderFilePath= */ "bitmap_overlay_video_processor_vertex.glsl", /* vertexShaderFilePath= */ "bitmap_overlay_video_processor_vertex.glsl",
/* fragmentShaderFilePath= */ "bitmap_overlay_video_processor_fragment.glsl"); /* fragmentShaderFilePath= */ "bitmap_overlay_video_processor_fragment.glsl");
...@@ -86,23 +87,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -86,23 +87,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
program.setBufferAttribute( program.setBufferAttribute(
"a_position", "aFramePosition", GlUtil.getNormalizedCoordinateBounds(), GlUtil.RECTANGLE_VERTICES_COUNT);
new float[] {
-1, -1, 0, 1,
1, -1, 0, 1,
-1, 1, 0, 1,
1, 1, 0, 1
},
4);
program.setBufferAttribute( program.setBufferAttribute(
"a_texcoord", "aTexCoords", GlUtil.getTextureCoordinateBounds(), GlUtil.RECTANGLE_VERTICES_COUNT);
new float[] {
0, 0, 0, 1,
1, 0, 0, 1,
0, 1, 0, 1,
1, 1, 0, 1
},
4);
GLES20.glGenTextures(1, textures, 0); GLES20.glGenTextures(1, textures, 0);
GLES20.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); GLES20.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
GLES20.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); GLES20.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
...@@ -131,12 +118,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ...@@ -131,12 +118,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
GlUtil.checkGlError(); GlUtil.checkGlError();
// Run the shader program. // Run the shader program.
GlUtil.Program program = checkNotNull(this.program); GlProgram program = checkNotNull(this.program);
program.setSamplerTexIdUniform("tex_sampler_0", frameTexture, /* unit= */ 0); program.setSamplerTexIdUniform("uTexSampler0", frameTexture, /* unit= */ 0);
program.setSamplerTexIdUniform("tex_sampler_1", textures[0], /* unit= */ 1); program.setSamplerTexIdUniform("uTexSampler1", textures[0], /* unit= */ 1);
program.setFloatUniform("scaleX", bitmapScaleX); program.setFloatUniform("uScaleX", bitmapScaleX);
program.setFloatUniform("scaleY", bitmapScaleY); program.setFloatUniform("uScaleY", bitmapScaleY);
program.setFloatsUniform("tex_transform", transformMatrix); program.setFloatsUniform("uTexTransform", transformMatrix);
program.bindAttributesAndUniforms(); program.bindAttributesAndUniforms();
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, /* first= */ 0, /* count= */ 4); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, /* first= */ 0, /* count= */ 4);
......
...@@ -42,7 +42,7 @@ import androidx.media3.exoplayer.drm.HttpMediaDrmCallback; ...@@ -42,7 +42,7 @@ import androidx.media3.exoplayer.drm.HttpMediaDrmCallback;
import androidx.media3.exoplayer.source.MediaSource; import androidx.media3.exoplayer.source.MediaSource;
import androidx.media3.exoplayer.source.ProgressiveMediaSource; import androidx.media3.exoplayer.source.ProgressiveMediaSource;
import androidx.media3.exoplayer.util.EventLogger; import androidx.media3.exoplayer.util.EventLogger;
import androidx.media3.ui.StyledPlayerView; import androidx.media3.ui.PlayerView;
import java.util.UUID; import java.util.UUID;
/** /**
...@@ -61,7 +61,7 @@ public final class MainActivity extends Activity { ...@@ -61,7 +61,7 @@ public final class MainActivity extends Activity {
private static final String DRM_SCHEME_EXTRA = "drm_scheme"; private static final String DRM_SCHEME_EXTRA = "drm_scheme";
private static final String DRM_LICENSE_URL_EXTRA = "drm_license_url"; private static final String DRM_LICENSE_URL_EXTRA = "drm_license_url";
@Nullable private StyledPlayerView playerView; @Nullable private PlayerView playerView;
@Nullable private VideoProcessingGLSurfaceView videoProcessingGLSurfaceView; @Nullable private VideoProcessingGLSurfaceView videoProcessingGLSurfaceView;
@Nullable private ExoPlayer player; @Nullable private ExoPlayer player;
...@@ -181,7 +181,7 @@ public final class MainActivity extends Activity { ...@@ -181,7 +181,7 @@ public final class MainActivity extends Activity {
Assertions.checkNotNull(this.videoProcessingGLSurfaceView); Assertions.checkNotNull(this.videoProcessingGLSurfaceView);
videoProcessingGLSurfaceView.setPlayer(player); videoProcessingGLSurfaceView.setPlayer(player);
Assertions.checkNotNull(playerView).setPlayer(player); Assertions.checkNotNull(playerView).setPlayer(player);
player.addAnalyticsListener(new EventLogger(/* trackSelector= */ null)); player.addAnalyticsListener(new EventLogger());
this.player = player; this.player = player;
} }
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:keepScreenOn="true"> android:keepScreenOn="true">
<androidx.media3.ui.StyledPlayerView <androidx.media3.ui.PlayerView
android:id="@+id/player_view" android:id="@+id/player_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
......
...@@ -76,6 +76,7 @@ ...@@ -76,6 +76,7 @@
<data android:scheme="content"/> <data android:scheme="content"/>
<data android:scheme="asset"/> <data android:scheme="asset"/>
<data android:scheme="file"/> <data android:scheme="file"/>
<data android:scheme="ssai"/>
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
<action android:name="androidx.media3.demo.main.action.VIEW_LIST"/> <action android:name="androidx.media3.demo.main.action.VIEW_LIST"/>
......
...@@ -35,31 +35,31 @@ ...@@ -35,31 +35,31 @@
"name": "HD (cenc)", "name": "HD (cenc)",
"uri": "https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears.mpd", "uri": "https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears.mpd",
"drm_scheme": "widevine", "drm_scheme": "widevine",
"drm_license_uri": "https://proxy.uat.widevine.com/proxy?provider=widevine_test" "drm_license_uri": "https://proxy.uat.widevine.com/proxy?video_id=2015_tears&provider=widevine_test"
}, },
{ {
"name": "UHD (cenc)", "name": "UHD (cenc)",
"uri": "https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears_uhd.mpd", "uri": "https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears_uhd.mpd",
"drm_scheme": "widevine", "drm_scheme": "widevine",
"drm_license_uri": "https://proxy.uat.widevine.com/proxy?provider=widevine_test" "drm_license_uri": "https://proxy.uat.widevine.com/proxy?video_id=2015_tears&provider=widevine_test"
}, },
{ {
"name": "HD (cbcs)", "name": "HD (cbcs)",
"uri": "https://storage.googleapis.com/wvmedia/cbcs/h264/tears/tears_aes_cbcs.mpd", "uri": "https://storage.googleapis.com/wvmedia/cbcs/h264/tears/tears_aes_cbcs.mpd",
"drm_scheme": "widevine", "drm_scheme": "widevine",
"drm_license_uri": "https://proxy.uat.widevine.com/proxy?provider=widevine_test" "drm_license_uri": "https://proxy.uat.widevine.com/proxy?video_id=2015_tears&provider=widevine_test"
}, },
{ {
"name": "UHD (cbcs)", "name": "UHD (cbcs)",
"uri": "https://storage.googleapis.com/wvmedia/cbcs/h264/tears/tears_aes_cbcs_uhd.mpd", "uri": "https://storage.googleapis.com/wvmedia/cbcs/h264/tears/tears_aes_cbcs_uhd.mpd",
"drm_scheme": "widevine", "drm_scheme": "widevine",
"drm_license_uri": "https://proxy.uat.widevine.com/proxy?provider=widevine_test" "drm_license_uri": "https://proxy.uat.widevine.com/proxy?video_id=2015_tears&provider=widevine_test"
}, },
{ {
"name": "Secure -> Clear -> Secure (cenc)", "name": "Secure -> Clear -> Secure (cenc)",
"uri": "https://storage.googleapis.com/exoplayer-test-media-1/widevine/tears_enc_clear_enc.mpd", "uri": "https://storage.googleapis.com/exoplayer-test-media-1/widevine/tears_enc_clear_enc.mpd",
"drm_scheme": "widevine", "drm_scheme": "widevine",
"drm_license_uri": "https://proxy.uat.widevine.com/proxy?provider=widevine_test", "drm_license_uri": "https://proxy.uat.widevine.com/proxy?video_id=2015_tears&provider=widevine_test",
"drm_session_for_clear_content": true "drm_session_for_clear_content": true
} }
] ]
...@@ -71,25 +71,25 @@ ...@@ -71,25 +71,25 @@
"name": "HD (cenc, full-sample)", "name": "HD (cenc, full-sample)",
"uri": "https://storage.googleapis.com/wvmedia/cenc/vp9/tears/tears.mpd", "uri": "https://storage.googleapis.com/wvmedia/cenc/vp9/tears/tears.mpd",
"drm_scheme": "widevine", "drm_scheme": "widevine",
"drm_license_uri": "https://proxy.uat.widevine.com/proxy?provider=widevine_test" "drm_license_uri": "https://proxy.uat.widevine.com/proxy?video_id=2015_tears&provider=widevine_test"
}, },
{ {
"name": "UHD (cenc, full-sample)", "name": "UHD (cenc, full-sample)",
"uri": "https://storage.googleapis.com/wvmedia/cenc/vp9/tears/tears_uhd.mpd", "uri": "https://storage.googleapis.com/wvmedia/cenc/vp9/tears/tears_uhd.mpd",
"drm_scheme": "widevine", "drm_scheme": "widevine",
"drm_license_uri": "https://proxy.uat.widevine.com/proxy?provider=widevine_test" "drm_license_uri": "https://proxy.uat.widevine.com/proxy?video_id=2015_tears&provider=widevine_test"
}, },
{ {
"name": "HD (cenc, sub-sample)", "name": "HD (cenc, sub-sample)",
"uri": "https://storage.googleapis.com/wvmedia/cenc/vp9/subsample/24fps/tears/tears.mpd", "uri": "https://storage.googleapis.com/wvmedia/cenc/vp9/subsample/24fps/tears/tears.mpd",
"drm_scheme": "widevine", "drm_scheme": "widevine",
"drm_license_uri": "https://proxy.uat.widevine.com/proxy?provider=widevine_test" "drm_license_uri": "https://proxy.uat.widevine.com/proxy?video_id=2015_tears&provider=widevine_test"
}, },
{ {
"name": "UHD (cenc, sub-sample)", "name": "UHD (cenc, sub-sample)",
"uri": "https://storage.googleapis.com/wvmedia/cenc/vp9/subsample/24fps/tears/tears_uhd.mpd", "uri": "https://storage.googleapis.com/wvmedia/cenc/vp9/subsample/24fps/tears/tears_uhd.mpd",
"drm_scheme": "widevine", "drm_scheme": "widevine",
"drm_license_uri": "https://proxy.uat.widevine.com/proxy?provider=widevine_test" "drm_license_uri": "https://proxy.uat.widevine.com/proxy?video_id=2015_tears&provider=widevine_test"
} }
] ]
}, },
...@@ -100,13 +100,13 @@ ...@@ -100,13 +100,13 @@
"name": "HD (cenc)", "name": "HD (cenc)",
"uri": "https://storage.googleapis.com/wvmedia/cenc/hevc/tears/tears.mpd", "uri": "https://storage.googleapis.com/wvmedia/cenc/hevc/tears/tears.mpd",
"drm_scheme": "widevine", "drm_scheme": "widevine",
"drm_license_uri": "https://proxy.uat.widevine.com/proxy?provider=widevine_test" "drm_license_uri": "https://proxy.uat.widevine.com/proxy?video_id=2015_tears&provider=widevine_test"
}, },
{ {
"name": "UHD (cenc)", "name": "UHD (cenc)",
"uri": "https://storage.googleapis.com/wvmedia/cenc/hevc/tears/tears_uhd.mpd", "uri": "https://storage.googleapis.com/wvmedia/cenc/hevc/tears/tears_uhd.mpd",
"drm_scheme": "widevine", "drm_scheme": "widevine",
"drm_license_uri": "https://proxy.uat.widevine.com/proxy?provider=widevine_test" "drm_license_uri": "https://proxy.uat.widevine.com/proxy?video_id=2015_tears&provider=widevine_test"
} }
] ]
}, },
...@@ -388,6 +388,98 @@ ...@@ -388,6 +388,98 @@
] ]
}, },
{ {
"name": "IMA DAI streams",
"samples": [
{
"name": "HLS VOD: Demo (skippable pre/post), single ads [30 s]",
"uri": "ssai://dai.google.com/?contentSourceId=2483977&videoId=ima-vod-skippable-test&format=2&adsId=1"
},
{
"name": "HLS VOD: Tears of Steel (pre/mid/mid/mid/post), single ads [10s]",
"uri": "ssai://dai.google.com/?contentSourceId=2528370&videoId=tears-of-steel&format=2&adsId=1"
},
{
"name": "HLS Live: Big Buck Bunny (mid), 3 ads each [10 s]",
"uri": "ssai://dai.google.com/?assetKey=sN_IYUG8STe1ZzhIIE_ksA&format=2&adsId=3"
},
{
"name": "DASH VOD: Tears of Steel (11 periods, pre/mid/post), 2/5/2 ads [5/10s]",
"uri": "ssai://dai.google.com/?contentSourceId=2559737&videoId=tos-dash&format=0&adsId=1"
},
{
"name": "Playlist: No ads - HLS VOD: Demo (skippable pre/post) - No ads",
"playlist": [
{
"uri": "https://html5demos.com/assets/dizzy.mp4"
},
{
"uri": "ssai://dai.google.com/?contentSourceId=2483977&videoId=ima-vod-skippable-test&format=2&adsId=1"
},
{
"uri": "https://html5demos.com/assets/dizzy.mp4"
}
]
},
{
"name": "Playlist: No ads - HLS VOD: Tears of steel (pre/mid/mid/mid/post) - No ads",
"playlist": [
{
"uri": "https://html5demos.com/assets/dizzy.mp4"
},
{
"uri": "ssai://dai.google.com/?contentSourceId=2528370&videoId=tears-of-steel&format=2&adsId=1"
},
{
"uri": "https://html5demos.com/assets/dizzy.mp4"
}
]
},
{
"name": "Playlist: No ads - HLS Live: Big Buck Bunny (mid) - No ads",
"playlist": [
{
"uri": "https://html5demos.com/assets/dizzy.mp4"
},
{
"uri": "ssai://dai.google.com/?assetKey=sN_IYUG8STe1ZzhIIE_ksA&format=2&adsId=3"
},
{
"uri": "https://html5demos.com/assets/dizzy.mp4"
}
]
},
{
"name": "Playlist: No ads - DASH VOD: Tears of Steel (11 periods, pre/mid/post) - No ads",
"playlist": [
{
"uri": "https://html5demos.com/assets/dizzy.mp4"
},
{
"uri": "ssai://dai.google.com/?contentSourceId=2559737&videoId=tos-dash&format=0&adsId=1"
},
{
"uri": "https://html5demos.com/assets/dizzy.mp4"
}
]
},
{
"name": "Playlist: Client-side Ads - DASH VOD: Tears of Steel (11 periods, pre/mid/post) - No ads",
"playlist": [
{
"uri": "https://storage.googleapis.com/exoplayer-test-media-1/mkv/android-screens-lavf-56.36.100-aac-avc-main-1280x720.mkv",
"ad_tag_uri": "https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/124319096/external/ad_rule_samples&ciu_szs=300x250&ad_rule=1&impl=s&gdfp_req=1&env=vp&output=vmap&unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpost&cmsid=496&vid=short_onecue&correlator="
},
{
"uri": "ssai://dai.google.com/?contentSourceId=2559737&videoId=tos-dash&format=0&adsId=1"
},
{
"uri": "https://html5demos.com/assets/dizzy.mp4"
}
]
}
]
},
{
"name": "Playlists", "name": "Playlists",
"samples": [ "samples": [
{ {
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
package androidx.media3.demo.main; package androidx.media3.demo.main;
import android.content.Context; import android.content.Context;
import androidx.media3.common.util.Log;
import androidx.media3.database.DatabaseProvider; import androidx.media3.database.DatabaseProvider;
import androidx.media3.database.StandaloneDatabaseProvider; import androidx.media3.database.StandaloneDatabaseProvider;
import androidx.media3.datasource.DataSource; import androidx.media3.datasource.DataSource;
...@@ -31,12 +30,9 @@ import androidx.media3.datasource.cronet.CronetDataSource; ...@@ -31,12 +30,9 @@ import androidx.media3.datasource.cronet.CronetDataSource;
import androidx.media3.datasource.cronet.CronetUtil; import androidx.media3.datasource.cronet.CronetUtil;
import androidx.media3.exoplayer.DefaultRenderersFactory; import androidx.media3.exoplayer.DefaultRenderersFactory;
import androidx.media3.exoplayer.RenderersFactory; import androidx.media3.exoplayer.RenderersFactory;
import androidx.media3.exoplayer.offline.ActionFileUpgradeUtil;
import androidx.media3.exoplayer.offline.DefaultDownloadIndex;
import androidx.media3.exoplayer.offline.DownloadManager; import androidx.media3.exoplayer.offline.DownloadManager;
import androidx.media3.exoplayer.offline.DownloadNotificationHelper; import androidx.media3.exoplayer.offline.DownloadNotificationHelper;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.net.CookieHandler; import java.net.CookieHandler;
import java.net.CookieManager; import java.net.CookieManager;
import java.net.CookiePolicy; import java.net.CookiePolicy;
...@@ -60,8 +56,6 @@ public final class DemoUtil { ...@@ -60,8 +56,6 @@ public final class DemoUtil {
private static final boolean USE_CRONET_FOR_NETWORKING = true; private static final boolean USE_CRONET_FOR_NETWORKING = true;
private static final String TAG = "DemoUtil"; private static final String TAG = "DemoUtil";
private static final String DOWNLOAD_ACTION_FILE = "actions";
private static final String DOWNLOAD_TRACKER_ACTION_FILE = "tracked_actions";
private static final String DOWNLOAD_CONTENT_DIRECTORY = "downloads"; private static final String DOWNLOAD_CONTENT_DIRECTORY = "downloads";
private static DataSource.@MonotonicNonNull Factory dataSourceFactory; private static DataSource.@MonotonicNonNull Factory dataSourceFactory;
...@@ -155,14 +149,6 @@ public final class DemoUtil { ...@@ -155,14 +149,6 @@ public final class DemoUtil {
private static synchronized void ensureDownloadManagerInitialized(Context context) { private static synchronized void ensureDownloadManagerInitialized(Context context) {
if (downloadManager == null) { if (downloadManager == null) {
DefaultDownloadIndex downloadIndex = new DefaultDownloadIndex(getDatabaseProvider(context));
upgradeActionFile(
context, DOWNLOAD_ACTION_FILE, downloadIndex, /* addNewDownloadsAsCompleted= */ false);
upgradeActionFile(
context,
DOWNLOAD_TRACKER_ACTION_FILE,
downloadIndex,
/* addNewDownloadsAsCompleted= */ true);
downloadManager = downloadManager =
new DownloadManager( new DownloadManager(
context, context,
...@@ -175,23 +161,6 @@ public final class DemoUtil { ...@@ -175,23 +161,6 @@ public final class DemoUtil {
} }
} }
private static synchronized void upgradeActionFile(
Context context,
String fileName,
DefaultDownloadIndex downloadIndex,
boolean addNewDownloadsAsCompleted) {
try {
ActionFileUpgradeUtil.upgradeAndDelete(
new File(getDownloadDirectory(context), fileName),
/* downloadIdProvider= */ null,
downloadIndex,
/* deleteOnFailure= */ true,
addNewDownloadsAsCompleted);
} catch (IOException e) {
Log.e(TAG, "Failed to upgrade action file: " + fileName, e);
}
}
private static synchronized DatabaseProvider getDatabaseProvider(Context context) { private static synchronized DatabaseProvider getDatabaseProvider(Context context) {
if (databaseProvider == null) { if (databaseProvider == null) {
databaseProvider = new StandaloneDatabaseProvider(context); databaseProvider = new StandaloneDatabaseProvider(context);
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:keepScreenOn="true"> android:keepScreenOn="true">
<androidx.media3.ui.StyledPlayerView android:id="@+id/player_view" <androidx.media3.ui.PlayerView android:id="@+id/player_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
app:show_shuffle_button="true" app:show_shuffle_button="true"
......
...@@ -61,9 +61,9 @@ dependencies { ...@@ -61,9 +61,9 @@ dependencies {
implementation 'androidx.appcompat:appcompat:' + androidxAppCompatVersion implementation 'androidx.appcompat:appcompat:' + androidxAppCompatVersion
implementation 'androidx.multidex:multidex:' + androidxMultidexVersion implementation 'androidx.multidex:multidex:' + androidxMultidexVersion
implementation 'com.google.android.material:material:' + androidxMaterialVersion implementation 'com.google.android.material:material:' + androidxMaterialVersion
implementation project(modulePrefix + ':lib-exoplayer') implementation project(modulePrefix + 'lib-exoplayer')
implementation project(modulePrefix + ':lib-exoplayer-dash') implementation project(modulePrefix + 'lib-exoplayer-dash')
implementation project(modulePrefix + ':lib-exoplayer-hls') implementation project(modulePrefix + 'lib-exoplayer-hls')
implementation project(modulePrefix + ':lib-ui') implementation project(modulePrefix + 'lib-ui')
implementation project(modulePrefix + ':lib-session') implementation project(modulePrefix + 'lib-session')
} }
...@@ -21,10 +21,9 @@ ...@@ -21,10 +21,9 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application <application
android:allowBackup="true" android:allowBackup="false"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.Media3Demo"> android:theme="@style/Theme.Media3Demo">
<activity <activity
...@@ -38,13 +37,11 @@ ...@@ -38,13 +37,11 @@
<activity <activity
android:name=".PlayerActivity" android:name=".PlayerActivity"
android:exported="true"> android:exported="true"/>
</activity>
<activity <activity
android:name=".PlayableFolderActivity" android:name=".PlayableFolderActivity"
android:exported="true"> android:exported="true"/>
</activity>
<service <service
android:name=".PlaybackService" android:name=".PlaybackService"
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
"media": [ "media": [
{ {
"id": "video_01", "id": "video_01",
"title": "Future Scenerio", "title": "Future Scenario",
"album": "Mango Open Movie project", "album": "Mango Open Movie project",
"artist": "Blender Foundation", "artist": "Blender Foundation",
"genre": "Video", "genre": "Video",
......
...@@ -34,7 +34,7 @@ import androidx.media3.common.MediaMetadata ...@@ -34,7 +34,7 @@ import androidx.media3.common.MediaMetadata
import androidx.media3.common.Player import androidx.media3.common.Player
import androidx.media3.session.MediaController import androidx.media3.session.MediaController
import androidx.media3.session.SessionToken import androidx.media3.session.SessionToken
import androidx.media3.ui.StyledPlayerView import androidx.media3.ui.PlayerView
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import com.google.common.util.concurrent.MoreExecutors import com.google.common.util.concurrent.MoreExecutors
...@@ -43,7 +43,7 @@ class PlayerActivity : AppCompatActivity() { ...@@ -43,7 +43,7 @@ class PlayerActivity : AppCompatActivity() {
private val controller: MediaController? private val controller: MediaController?
get() = if (controllerFuture.isDone) controllerFuture.get() else null get() = if (controllerFuture.isDone) controllerFuture.get() else null
private lateinit var playerView: StyledPlayerView private lateinit var playerView: PlayerView
private lateinit var mediaList: ListView private lateinit var mediaList: ListView
private lateinit var mediaListAdapter: PlayingMediaItemArrayAdapter private lateinit var mediaListAdapter: PlayingMediaItemArrayAdapter
private val subItemMediaList: MutableList<MediaItem> = mutableListOf() private val subItemMediaList: MutableList<MediaItem> = mutableListOf()
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
android:layout_height="300dp" android:layout_height="300dp"
android:layout_width="match_parent" android:layout_width="match_parent"
> >
<androidx.media3.ui.StyledPlayerView <androidx.media3.ui.PlayerView
android:id="@+id/player_view" android:id="@+id/player_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:id="@+id/add_button" android:id="@+id/add_button"
android:background="@android:drawable/ic_input_add" android:background="@drawable/baseline_playlist_add_white_48"
/> />
</LinearLayout> </LinearLayout>
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:id="@+id/delete_button" android:id="@+id/delete_button"
android:background="@android:drawable/ic_menu_close_clear_cancel" android:background="@drawable/baseline_playlist_remove_white_48"
/> />
</LinearLayout> </LinearLayout>
...@@ -27,7 +27,9 @@ ...@@ -27,7 +27,9 @@
android:label="@string/application_name" android:label="@string/application_name"
android:exported="true"> android:exported="true">
<activity android:name=".MainActivity"> <activity
android:name=".MainActivity"
android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>
......
# Transformer demo
This app demonstrates how to use the [Transformer][] API to modify videos, for
example by removing audio or video.
See the [demos README](../README.md) for instructions on how to build and run
this demo.
[Transformer]: https://exoplayer.dev/transforming-media.html
/*
* Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
apply from: '../../constants.gradle'
apply plugin: 'com.android.application'
android {
compileSdkVersion project.ext.compileSdkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
versionName project.ext.releaseVersion
versionCode project.ext.releaseVersionCode
minSdkVersion 21
targetSdkVersion project.ext.appTargetSdkVersion
multiDexEnabled true
}
buildTypes {
release {
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt')
signingConfig signingConfigs.debug
}
}
lintOptions {
// This demo app isn't indexed and doesn't have translations.
disable 'GoogleAppIndexingWarning','MissingTranslation'
}
}
dependencies {
implementation 'androidx.core:core:' + androidxCoreVersion
compileOnly 'org.checkerframework:checker-qual:' + checkerframeworkVersion
implementation 'androidx.annotation:annotation:' + androidxAnnotationVersion
implementation 'androidx.appcompat:appcompat:' + androidxAppCompatVersion
implementation 'androidx.constraintlayout:constraintlayout:' + androidxConstraintLayoutVersion
implementation 'androidx.multidex:multidex:' + androidxMultidexVersion
implementation 'com.google.android.material:material:' + androidxMaterialVersion
implementation project(modulePrefix + 'lib-exoplayer')
implementation project(modulePrefix + 'lib-transformer')
implementation project(modulePrefix + 'lib-ui')
}
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2021 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="androidx.media3.demo.transformer">
<uses-sdk />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.AppCompat"
android:taskAffinity=""
tools:targetApi="29">
<activity android:name=".ConfigurationActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"
android:launchMode="singleTop"
android:label="@string/app_name"
android:exported="true"
android:theme="@style/Theme.MaterialComponents.DayNight.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="androidx.media3.demo.transformer.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
<data android:scheme="content"/>
<data android:scheme="asset"/>
<data android:scheme="file"/>
</intent-filter>
</activity>
<activity android:name=".TransformerActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"
android:launchMode="singleTop"
android:label="@string/app_name"
android:exported="true"
android:theme="@style/Theme.MaterialComponents.DayNight.NoActionBar"/>
</application>
</manifest>
/*
* Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@NonNullApi
package androidx.media3.demo.transformer;
import androidx.media3.common.util.NonNullApi;
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2021 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConfigurationActivity">
<TextView
android:id="@+id/configuration_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:text="@string/configuration"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/choose_file_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:text="@string/choose_file_title"
app:layout_constraintTop_toBottomOf="@+id/configuration_text_view"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/chosen_file_text_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:paddingLeft="24dp"
android:paddingRight="24dp"
android:textSize="12sp"
android:gravity="center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/choose_file_button" />
<androidx.core.widget.NestedScrollView
android:layout_width="fill_parent"
android:layout_height="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/chosen_file_text_view"
app:layout_constraintBottom_toTopOf="@+id/transform_button">
<TableLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stretchColumns="1"
android:layout_marginTop="32dp"
android:measureWithLargestChild="true"
android:paddingLeft="24dp"
android:paddingRight="12dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<TableRow
android:layout_weight="1"
android:gravity="center_vertical" >
<TextView
android:text="@string/remove_audio" />
<CheckBox
android:id="@+id/remove_audio_checkbox"
android:layout_gravity="right"/>
</TableRow>
<TableRow
android:layout_weight="1"
android:gravity="center_vertical" >
<TextView
android:text="@string/remove_video"/>
<CheckBox
android:id="@+id/remove_video_checkbox"
android:layout_gravity="right" />
</TableRow>
<TableRow
android:layout_weight="1"
android:gravity="center_vertical" >
<TextView
android:text="@string/flatten_for_slow_motion"/>
<CheckBox
android:id="@+id/flatten_for_slow_motion_checkbox"
android:layout_gravity="right" />
</TableRow>
<TableRow
android:layout_weight="1"
android:gravity="center_vertical" >
<TextView
android:id="@+id/audio_mime_text_view"
android:text="@string/audio_mime"/>
<Spinner
android:id="@+id/audio_mime_spinner"
android:layout_gravity="right|center_vertical"
android:gravity="right" />
</TableRow>
<TableRow
android:layout_weight="1"
android:gravity="center_vertical" >
<TextView
android:id="@+id/video_mime_text_view"
android:text="@string/video_mime"/>
<Spinner
android:id="@+id/video_mime_spinner"
android:layout_gravity="right|center_vertical"
android:gravity="right" />
</TableRow>
<TableRow
android:layout_weight="1"
android:gravity="center_vertical" >
<TextView
android:id="@+id/resolution_height_text_view"
android:text="@string/resolution_height"/>
<Spinner
android:id="@+id/resolution_height_spinner"
android:layout_gravity="right|center_vertical"
android:gravity="right" />
</TableRow>
<TableRow
android:layout_weight="1"
android:gravity="center_vertical" >
<TextView
android:id="@+id/translate"
android:text="@string/translate"/>
<Spinner
android:id="@+id/translate_spinner"
android:layout_gravity="right|center_vertical"
android:gravity="right" />
</TableRow>
<TableRow
android:layout_weight="1"
android:gravity="center_vertical" >
<TextView
android:id="@+id/scale"
android:text="@string/scale"/>
<Spinner
android:id="@+id/scale_spinner"
android:layout_gravity="right|center_vertical"
android:gravity="right" />
</TableRow>
<TableRow
android:layout_weight="1"
android:gravity="center_vertical" >
<TextView
android:id="@+id/rotate"
android:text="@string/rotate"/>
<Spinner
android:id="@+id/rotate_spinner"
android:layout_gravity="right|center_vertical"
android:gravity="right" />
</TableRow>
<TableRow
android:layout_weight="1"
android:gravity="center_vertical" >
<TextView
android:text="@string/enable_fallback" />
<CheckBox
android:id="@+id/enable_fallback_checkbox"
android:layout_gravity="right"
android:checked="true"/>
</TableRow>
<TableRow
android:layout_weight="1"
android:gravity="center_vertical" >
<TextView
android:id="@+id/hdr_editing"
android:text="@string/hdr_editing" />
<CheckBox
android:id="@+id/hdr_editing_checkbox"
android:layout_gravity="right" />
</TableRow>
</TableLayout>
</androidx.core.widget.NestedScrollView>
<Button
android:id="@+id/transform_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="28dp"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:text="@string/transform"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- <!--
~ Copyright 2018 The Android Open Source Project ~ Copyright 2021 The Android Open Source Project
~ ~
~ Licensed under the Apache License, Version 2.0 (the "License"); ~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License. ~ you may not use this file except in compliance with the License.
...@@ -14,10 +14,13 @@ ...@@ -14,10 +14,13 @@
~ See the License for the specific language governing permissions and ~ See the License for the specific language governing permissions and
~ limitations under the License. ~ limitations under the License.
--> -->
<TextView
<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> android:layout_width="wrap_content"
<string name="default_notification_channel_name" msgid="7213672915724563695">"এতিয়া প্লে’ হৈ আছে"</string> android:layout_height="32dp"
<string name="play_button_content_description" msgid="963503759453979404">"প্লে’ কৰক"</string> android:gravity="left|center_vertical"
<string name="media3_controls_pause_description" msgid="3510124037191104584">"পজ কৰক"</string> android:paddingLeft="4dp"
</resources> android:paddingRight="4dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:textIsSelectable="false" />
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright 2021 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:keepScreenOn="true"
android:orientation="vertical">
<com.google.android.material.card.MaterialCardView
android:layout_margin="8dp"
android:layout_height="wrap_content"
android:layout_width="match_parent"
app:cardCornerRadius="4dp"
app:cardElevation="2dp"
android:gravity="center_vertical" >
<TextView
android:id="@+id/information_text_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="8dp" />
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_margin="16dp"
app:cardCornerRadius="4dp"
app:cardElevation="2dp">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.media3.ui.PlayerView
android:id="@+id/player_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@+id/debug_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="10sp"
tools:ignore="SmallSp"/>
<LinearLayout
android:id="@+id/progress_view_group"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:padding="8dp"
android:orientation="vertical">
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/progress_indicator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_gravity="center" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="@string/debug_preview" />
<androidx.media3.ui.AspectRatioFrameLayout
android:id="@+id/debug_aspect_ratio_frame_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/debug_preview_not_available" />
</androidx.media3.ui.AspectRatioFrameLayout>
</LinearLayout>
</FrameLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2021 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" translatable="false">Transformer Demo</string>
<string name="configuration" translatable="false">Configuration</string>
<string name="choose_file_title" translatable="false">Choose file</string>
<string name="remove_audio" translatable="false">Remove audio</string>
<string name="remove_video" translatable="false">Remove video</string>
<string name="flatten_for_slow_motion" translatable="false">Flatten for slow motion</string>
<string name="audio_mime" translatable="false">Output audio MIME type</string>
<string name="video_mime" translatable="false">Output video MIME type</string>
<string name="resolution_height" translatable="false">Output video resolution</string>
<string name="translate" translatable="false">Translate video</string>
<string name="scale" translatable="false">Scale video</string>
<string name="rotate" translatable="false">Rotate video (degrees)</string>
<string name="enable_fallback" translatable="false">Enable fallback</string>
<string name="transform" translatable="false">Transform</string>
<string name="hdr_editing" translatable="false">[Experimental] HDR editing</string>
<string name="debug_preview" translatable="false">Debug preview:</string>
<string name="debug_preview_not_available" translatable="false">No debug preview available.</string>
<string name="transformation_started" translatable="false">Transformation started</string>
<string name="transformation_timer" translatable="false">Transformation started %d seconds ago.</string>
<string name="transformation_completed" translatable="false">Transformation completed in %d seconds.</string>
<string name="transformation_error" translatable="false">Transformation error</string>
</resources>
...@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME ...@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https://services.gradle.org/distributions/gradle-7.0.2-all.zip distributionUrl=https://services.gradle.org/distributions/gradle-7.3.3-all.zip
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
apply from: "$gradle.ext.androidxMediaSettingsDir/common_library_config.gradle" apply from: "$gradle.ext.androidxMediaSettingsDir/common_library_config.gradle"
dependencies { dependencies {
api 'com.google.android.gms:play-services-cast-framework:20.1.0' api 'com.google.android.gms:play-services-cast-framework:21.0.1'
implementation 'androidx.annotation:annotation:' + androidxAnnotationVersion implementation 'androidx.annotation:annotation:' + androidxAnnotationVersion
implementation project(modulePrefix + 'lib-common') implementation project(modulePrefix + 'lib-common')
compileOnly 'org.checkerframework:checker-qual:' + checkerframeworkVersion compileOnly 'org.checkerframework:checker-qual:' + checkerframeworkVersion
......
...@@ -137,7 +137,7 @@ public final class CastPlayer extends BasePlayer { ...@@ -137,7 +137,7 @@ public final class CastPlayer extends BasePlayer {
private final SeekResultCallback seekResultCallback; private final SeekResultCallback seekResultCallback;
// Listeners and notification. // Listeners and notification.
private final ListenerSet<Player.EventListener> listeners; private final ListenerSet<Listener> listeners;
@Nullable private SessionAvailabilityListener sessionAvailabilityListener; @Nullable private SessionAvailabilityListener sessionAvailabilityListener;
// Internal state. // Internal state.
...@@ -150,7 +150,7 @@ public final class CastPlayer extends BasePlayer { ...@@ -150,7 +150,7 @@ public final class CastPlayer extends BasePlayer {
private TrackSelectionArray currentTrackSelection; private TrackSelectionArray currentTrackSelection;
private TracksInfo currentTracksInfo; private TracksInfo currentTracksInfo;
private Commands availableCommands; private Commands availableCommands;
@Player.State private int playbackState; private @Player.State int playbackState;
private int currentWindowIndex; private int currentWindowIndex;
private long lastReportedPositionMs; private long lastReportedPositionMs;
private int pendingSeekCount; private int pendingSeekCount;
...@@ -280,41 +280,11 @@ public final class CastPlayer extends BasePlayer { ...@@ -280,41 +280,11 @@ public final class CastPlayer extends BasePlayer {
@Override @Override
public void addListener(Listener listener) { public void addListener(Listener listener) {
EventListener eventListener = listener;
addListener(eventListener);
}
/**
* Registers a listener to receive events from the player.
*
* <p>The listener's methods will be called on the thread associated with {@link
* #getApplicationLooper()}.
*
* @param listener The listener to register.
* @deprecated Use {@link #addListener(Listener)} and {@link #removeListener(Listener)} instead.
*/
@Deprecated
@SuppressWarnings("deprecation")
public void addListener(EventListener listener) {
listeners.add(listener); listeners.add(listener);
} }
@Override @Override
public void removeListener(Listener listener) { public void removeListener(Listener listener) {
EventListener eventListener = listener;
removeListener(eventListener);
}
/**
* Unregister a listener registered through {@link #addListener(EventListener)}. The listener will
* no longer receive events from the player.
*
* @param listener The listener to unregister.
* @deprecated Use {@link #addListener(Listener)} and {@link #removeListener(Listener)} instead.
*/
@Deprecated
@SuppressWarnings("deprecation")
public void removeListener(EventListener listener) {
listeners.remove(listener); listeners.remove(listener);
} }
...@@ -387,14 +357,12 @@ public final class CastPlayer extends BasePlayer { ...@@ -387,14 +357,12 @@ public final class CastPlayer extends BasePlayer {
} }
@Override @Override
@Player.State public @Player.State int getPlaybackState() {
public int getPlaybackState() {
return playbackState; return playbackState;
} }
@Override @Override
@PlaybackSuppressionReason public @PlaybackSuppressionReason int getPlaybackSuppressionReason() {
public int getPlaybackSuppressionReason() {
return Player.PLAYBACK_SUPPRESSION_REASON_NONE; return Player.PLAYBACK_SUPPRESSION_REASON_NONE;
} }
...@@ -475,7 +443,7 @@ public final class CastPlayer extends BasePlayer { ...@@ -475,7 +443,7 @@ public final class CastPlayer extends BasePlayer {
} }
updateAvailableCommandsAndNotifyIfChanged(); updateAvailableCommandsAndNotifyIfChanged();
} else if (pendingSeekCount == 0) { } else if (pendingSeekCount == 0) {
listeners.queueEvent(/* eventFlag= */ C.INDEX_UNSET, EventListener::onSeekProcessed); listeners.queueEvent(/* eventFlag= */ C.INDEX_UNSET, Listener::onSeekProcessed);
} }
listeners.flushEvents(); listeners.flushEvents();
} }
...@@ -559,7 +527,7 @@ public final class CastPlayer extends BasePlayer { ...@@ -559,7 +527,7 @@ public final class CastPlayer extends BasePlayer {
setRepeatModeAndNotifyIfChanged(repeatMode); setRepeatModeAndNotifyIfChanged(repeatMode);
listeners.flushEvents(); listeners.flushEvents();
PendingResult<MediaChannelResult> pendingResult = PendingResult<MediaChannelResult> pendingResult =
remoteMediaClient.queueSetRepeatMode(getCastRepeatMode(repeatMode), /* jsonObject= */ null); remoteMediaClient.queueSetRepeatMode(getCastRepeatMode(repeatMode), /* customData= */ null);
this.repeatMode.pendingResultCallback = this.repeatMode.pendingResultCallback =
new ResultCallback<MediaChannelResult>() { new ResultCallback<MediaChannelResult>() {
@Override @Override
...@@ -574,8 +542,7 @@ public final class CastPlayer extends BasePlayer { ...@@ -574,8 +542,7 @@ public final class CastPlayer extends BasePlayer {
} }
@Override @Override
@RepeatMode public @RepeatMode int getRepeatMode() {
public int getRepeatMode() {
return repeatMode.value; return repeatMode.value;
} }
...@@ -1070,7 +1037,8 @@ public final class CastPlayer extends BasePlayer { ...@@ -1070,7 +1037,8 @@ public final class CastPlayer extends BasePlayer {
int[] trackSupport = new int[] {supported ? C.FORMAT_HANDLED : C.FORMAT_UNSUPPORTED_TYPE}; int[] trackSupport = new int[] {supported ? C.FORMAT_HANDLED : C.FORMAT_UNSUPPORTED_TYPE};
final boolean[] trackSelected = new boolean[] {selected}; final boolean[] trackSelected = new boolean[] {selected};
trackGroupInfos[i] = trackGroupInfos[i] =
new TracksInfo.TrackGroupInfo(trackGroups[i], trackSupport, trackType, trackSelected); new TracksInfo.TrackGroupInfo(
trackGroups[i], /* adaptiveSupported= */ false, trackSupport, trackSelected);
} }
TrackGroupArray newTrackGroups = new TrackGroupArray(trackGroups); TrackGroupArray newTrackGroups = new TrackGroupArray(trackGroups);
TrackSelectionArray newTrackSelections = new TrackSelectionArray(trackSelections); TrackSelectionArray newTrackSelections = new TrackSelectionArray(trackSelections);
...@@ -1292,8 +1260,7 @@ public final class CastPlayer extends BasePlayer { ...@@ -1292,8 +1260,7 @@ public final class CastPlayer extends BasePlayer {
* Retrieves the repeat mode from {@code remoteMediaClient} and maps it into a {@link * Retrieves the repeat mode from {@code remoteMediaClient} and maps it into a {@link
* Player.RepeatMode}. * Player.RepeatMode}.
*/ */
@RepeatMode private static @RepeatMode int fetchRepeatMode(RemoteMediaClient remoteMediaClient) {
private static int fetchRepeatMode(RemoteMediaClient remoteMediaClient) {
MediaStatus mediaStatus = remoteMediaClient.getMediaStatus(); MediaStatus mediaStatus = remoteMediaClient.getMediaStatus();
if (mediaStatus == null) { if (mediaStatus == null) {
// No media session active, yet. // No media session active, yet.
...@@ -1481,7 +1448,7 @@ public final class CastPlayer extends BasePlayer { ...@@ -1481,7 +1448,7 @@ public final class CastPlayer extends BasePlayer {
currentWindowIndex = pendingSeekWindowIndex; currentWindowIndex = pendingSeekWindowIndex;
pendingSeekWindowIndex = C.INDEX_UNSET; pendingSeekWindowIndex = C.INDEX_UNSET;
pendingSeekPositionMs = C.TIME_UNSET; pendingSeekPositionMs = C.TIME_UNSET;
listeners.sendEvent(/* eventFlag= */ C.INDEX_UNSET, EventListener::onSeekProcessed); listeners.sendEvent(/* eventFlag= */ C.INDEX_UNSET, Listener::onSeekProcessed);
} }
} }
} }
......
...@@ -31,7 +31,9 @@ import androidx.media3.common.util.Assertions; ...@@ -31,7 +31,9 @@ import androidx.media3.common.util.Assertions;
private final TrackGroup trackGroup; private final TrackGroup trackGroup;
/** @param trackGroup The {@link TrackGroup} from which the first track will only be selected. */ /**
* @param trackGroup The {@link TrackGroup} from which the first track will only be selected.
*/
public CastTrackSelection(TrackGroup trackGroup) { public CastTrackSelection(TrackGroup trackGroup) {
this.trackGroup = trackGroup; this.trackGroup = trackGroup;
} }
......
...@@ -19,11 +19,13 @@ import android.net.Uri; ...@@ -19,11 +19,13 @@ import android.net.Uri;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.media3.common.C; import androidx.media3.common.C;
import androidx.media3.common.MediaItem; import androidx.media3.common.MediaItem;
import androidx.media3.common.MimeTypes;
import androidx.media3.common.util.Assertions; import androidx.media3.common.util.Assertions;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import com.google.android.gms.cast.MediaInfo; import com.google.android.gms.cast.MediaInfo;
import com.google.android.gms.cast.MediaMetadata; import com.google.android.gms.cast.MediaMetadata;
import com.google.android.gms.cast.MediaQueueItem; import com.google.android.gms.cast.MediaQueueItem;
import com.google.android.gms.common.images.WebImage;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.UUID; import java.util.UUID;
...@@ -47,10 +49,43 @@ public final class DefaultMediaItemConverter implements MediaItemConverter { ...@@ -47,10 +49,43 @@ public final class DefaultMediaItemConverter implements MediaItemConverter {
@Override @Override
public MediaItem toMediaItem(MediaQueueItem mediaQueueItem) { public MediaItem toMediaItem(MediaQueueItem mediaQueueItem) {
// `item` came from `toMediaQueueItem()` so the custom JSON data must be set. @Nullable MediaInfo mediaInfo = mediaQueueItem.getMedia();
MediaInfo mediaInfo = mediaQueueItem.getMedia();
Assertions.checkNotNull(mediaInfo); Assertions.checkNotNull(mediaInfo);
return getMediaItem(Assertions.checkNotNull(mediaInfo.getCustomData())); androidx.media3.common.MediaMetadata.Builder metadataBuilder =
new androidx.media3.common.MediaMetadata.Builder();
@Nullable MediaMetadata metadata = mediaInfo.getMetadata();
if (metadata != null) {
if (metadata.containsKey(MediaMetadata.KEY_TITLE)) {
metadataBuilder.setTitle(metadata.getString(MediaMetadata.KEY_TITLE));
}
if (metadata.containsKey(MediaMetadata.KEY_SUBTITLE)) {
metadataBuilder.setSubtitle(metadata.getString(MediaMetadata.KEY_SUBTITLE));
}
if (metadata.containsKey(MediaMetadata.KEY_ARTIST)) {
metadataBuilder.setArtist(metadata.getString(MediaMetadata.KEY_ARTIST));
}
if (metadata.containsKey(MediaMetadata.KEY_ALBUM_ARTIST)) {
metadataBuilder.setAlbumArtist(metadata.getString(MediaMetadata.KEY_ALBUM_ARTIST));
}
if (metadata.containsKey(MediaMetadata.KEY_ALBUM_TITLE)) {
metadataBuilder.setArtist(metadata.getString(MediaMetadata.KEY_ALBUM_TITLE));
}
if (!metadata.getImages().isEmpty()) {
metadataBuilder.setArtworkUri(metadata.getImages().get(0).getUrl());
}
if (metadata.containsKey(MediaMetadata.KEY_COMPOSER)) {
metadataBuilder.setComposer(metadata.getString(MediaMetadata.KEY_COMPOSER));
}
if (metadata.containsKey(MediaMetadata.KEY_DISC_NUMBER)) {
metadataBuilder.setDiscNumber(metadata.getInt(MediaMetadata.KEY_DISC_NUMBER));
}
if (metadata.containsKey(MediaMetadata.KEY_TRACK_NUMBER)) {
metadataBuilder.setTrackNumber(metadata.getInt(MediaMetadata.KEY_TRACK_NUMBER));
}
}
// `mediaQueueItem` came from `toMediaQueueItem()` so the custom JSON data must be set.
return getMediaItem(
Assertions.checkNotNull(mediaInfo.getCustomData()), metadataBuilder.build());
} }
@Override @Override
...@@ -59,10 +94,41 @@ public final class DefaultMediaItemConverter implements MediaItemConverter { ...@@ -59,10 +94,41 @@ public final class DefaultMediaItemConverter implements MediaItemConverter {
if (mediaItem.localConfiguration.mimeType == null) { if (mediaItem.localConfiguration.mimeType == null) {
throw new IllegalArgumentException("The item must specify its mimeType"); throw new IllegalArgumentException("The item must specify its mimeType");
} }
MediaMetadata metadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE); MediaMetadata metadata =
new MediaMetadata(
MimeTypes.isAudio(mediaItem.localConfiguration.mimeType)
? MediaMetadata.MEDIA_TYPE_MUSIC_TRACK
: MediaMetadata.MEDIA_TYPE_MOVIE);
if (mediaItem.mediaMetadata.title != null) { if (mediaItem.mediaMetadata.title != null) {
metadata.putString(MediaMetadata.KEY_TITLE, mediaItem.mediaMetadata.title.toString()); metadata.putString(MediaMetadata.KEY_TITLE, mediaItem.mediaMetadata.title.toString());
} }
if (mediaItem.mediaMetadata.subtitle != null) {
metadata.putString(MediaMetadata.KEY_SUBTITLE, mediaItem.mediaMetadata.subtitle.toString());
}
if (mediaItem.mediaMetadata.artist != null) {
metadata.putString(MediaMetadata.KEY_ARTIST, mediaItem.mediaMetadata.artist.toString());
}
if (mediaItem.mediaMetadata.albumArtist != null) {
metadata.putString(
MediaMetadata.KEY_ALBUM_ARTIST, mediaItem.mediaMetadata.albumArtist.toString());
}
if (mediaItem.mediaMetadata.albumTitle != null) {
metadata.putString(
MediaMetadata.KEY_ALBUM_TITLE, mediaItem.mediaMetadata.albumTitle.toString());
}
if (mediaItem.mediaMetadata.artworkUri != null) {
metadata.addImage(new WebImage(mediaItem.mediaMetadata.artworkUri));
}
if (mediaItem.mediaMetadata.composer != null) {
metadata.putString(MediaMetadata.KEY_COMPOSER, mediaItem.mediaMetadata.composer.toString());
}
if (mediaItem.mediaMetadata.discNumber != null) {
metadata.putInt(MediaMetadata.KEY_DISC_NUMBER, mediaItem.mediaMetadata.discNumber);
}
if (mediaItem.mediaMetadata.trackNumber != null) {
metadata.putInt(MediaMetadata.KEY_TRACK_NUMBER, mediaItem.mediaMetadata.trackNumber);
}
MediaInfo mediaInfo = MediaInfo mediaInfo =
new MediaInfo.Builder(mediaItem.localConfiguration.uri.toString()) new MediaInfo.Builder(mediaItem.localConfiguration.uri.toString())
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED) .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
...@@ -75,19 +141,15 @@ public final class DefaultMediaItemConverter implements MediaItemConverter { ...@@ -75,19 +141,15 @@ public final class DefaultMediaItemConverter implements MediaItemConverter {
// Deserialization. // Deserialization.
private static MediaItem getMediaItem(JSONObject customData) { private static MediaItem getMediaItem(
JSONObject customData, androidx.media3.common.MediaMetadata mediaMetadata) {
try { try {
JSONObject mediaItemJson = customData.getJSONObject(KEY_MEDIA_ITEM); JSONObject mediaItemJson = customData.getJSONObject(KEY_MEDIA_ITEM);
MediaItem.Builder builder = new MediaItem.Builder(); MediaItem.Builder builder =
builder.setUri(Uri.parse(mediaItemJson.getString(KEY_URI))); new MediaItem.Builder()
builder.setMediaId(mediaItemJson.getString(KEY_MEDIA_ID)); .setUri(Uri.parse(mediaItemJson.getString(KEY_URI)))
if (mediaItemJson.has(KEY_TITLE)) { .setMediaId(mediaItemJson.getString(KEY_MEDIA_ID))
androidx.media3.common.MediaMetadata mediaMetadata = .setMediaMetadata(mediaMetadata);
new androidx.media3.common.MediaMetadata.Builder()
.setTitle(mediaItemJson.getString(KEY_TITLE))
.build();
builder.setMediaMetadata(mediaMetadata);
}
if (mediaItemJson.has(KEY_MIME_TYPE)) { if (mediaItemJson.has(KEY_MIME_TYPE)) {
builder.setMimeType(mediaItemJson.getString(KEY_MIME_TYPE)); builder.setMimeType(mediaItemJson.getString(KEY_MIME_TYPE));
} }
......
...@@ -17,9 +17,10 @@ apply from: "$gradle.ext.androidxMediaSettingsDir/common_library_config.gradle" ...@@ -17,9 +17,10 @@ apply from: "$gradle.ext.androidxMediaSettingsDir/common_library_config.gradle"
// the Gradle properties of each library are populated and we can automatically // the Gradle properties of each library are populated and we can automatically
// check if a 'releaseArtifactId' exists. // check if a 'releaseArtifactId' exists.
rootProject.allprojects.forEach { rootProject.allprojects.forEach {
if ((it.name.contains('lib-') || it.name.contains('test-')) if ((it.name.startsWith(modulePrefix.replace(':', '') + 'lib-')
|| it.name.startsWith(modulePrefix.replace(':', '') + 'test-'))
&& !it.name.endsWith('-common')) { && !it.name.endsWith('-common')) {
evaluationDependsOn(modulePrefix + it.name) evaluationDependsOn(':' + it.name)
} }
} }
// copybara:media3-only // copybara:media3-only
...@@ -36,8 +37,9 @@ dependencies { ...@@ -36,8 +37,9 @@ dependencies {
// List all released targets as constraints. This ensures they are all // List all released targets as constraints. This ensures they are all
// resolved to the same version. // resolved to the same version.
rootProject.allprojects.forEach { rootProject.allprojects.forEach {
if (it.hasProperty('releaseArtifactId')) { if (it.hasProperty('releaseArtifactId')
implementation project(modulePrefix + it.name) && it.releaseArtifactId.startsWith('media3-')) {
implementation project(':' + it.name)
} }
} }
} }
......
...@@ -37,6 +37,8 @@ public final class AdOverlayInfo { ...@@ -37,6 +37,8 @@ public final class AdOverlayInfo {
* The purpose of the overlay. One of {@link #PURPOSE_CONTROLS}, {@link #PURPOSE_CLOSE_AD}, {@link * The purpose of the overlay. One of {@link #PURPOSE_CONTROLS}, {@link #PURPOSE_CLOSE_AD}, {@link
* #PURPOSE_OTHER} or {@link #PURPOSE_NOT_VISIBLE}. * #PURPOSE_OTHER} or {@link #PURPOSE_NOT_VISIBLE}.
*/ */
// @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility
// with Kotlin usages from before TYPE_USE was added.
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE}) @Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE})
...@@ -95,14 +97,18 @@ public final class AdOverlayInfo { ...@@ -95,14 +97,18 @@ public final class AdOverlayInfo {
/** An optional, detailed reason that the overlay view is needed. */ /** An optional, detailed reason that the overlay view is needed. */
@Nullable public final String reasonDetail; @Nullable public final String reasonDetail;
/** @deprecated Use {@link Builder} instead. */ /**
* @deprecated Use {@link Builder} instead.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public AdOverlayInfo(View view, @Purpose int purpose) { public AdOverlayInfo(View view, @Purpose int purpose) {
this(view, purpose, /* detailedReason= */ null); this(view, purpose, /* detailedReason= */ null);
} }
/** @deprecated Use {@link Builder} instead. */ /**
* @deprecated Use {@link Builder} instead.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public AdOverlayInfo(View view, @Purpose int purpose, @Nullable String detailedReason) { public AdOverlayInfo(View view, @Purpose int purpose, @Nullable String detailedReason) {
......
...@@ -18,6 +18,11 @@ package androidx.media3.common; ...@@ -18,6 +18,11 @@ package androidx.media3.common;
import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkArgument;
import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Assertions.checkState;
import static java.lang.Math.max; import static java.lang.Math.max;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
...@@ -30,6 +35,7 @@ import androidx.media3.common.util.Util; ...@@ -30,6 +35,7 @@ import androidx.media3.common.util.Util;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import org.checkerframework.checker.nullness.compatqual.NullableType; import org.checkerframework.checker.nullness.compatqual.NullableType;
...@@ -61,7 +67,7 @@ public final class AdPlaybackState implements Bundleable { ...@@ -61,7 +67,7 @@ public final class AdPlaybackState implements Bundleable {
/** The URI of each ad in the ad group. */ /** The URI of each ad in the ad group. */
public final @NullableType Uri[] uris; public final @NullableType Uri[] uris;
/** The state of each ad in the ad group. */ /** The state of each ad in the ad group. */
@AdState public final int[] states; public final @AdState int[] states;
/** The durations of each ad in the ad group, in microseconds. */ /** The durations of each ad in the ad group, in microseconds. */
public final long[] durationsUs; public final long[] durationsUs;
/** /**
...@@ -343,6 +349,7 @@ public final class AdPlaybackState implements Bundleable { ...@@ -343,6 +349,7 @@ public final class AdPlaybackState implements Bundleable {
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({ @IntDef({
FIELD_TIME_US, FIELD_TIME_US,
FIELD_COUNT, FIELD_COUNT,
...@@ -414,8 +421,11 @@ public final class AdPlaybackState implements Bundleable { ...@@ -414,8 +421,11 @@ public final class AdPlaybackState implements Bundleable {
* #AD_STATE_AVAILABLE}, {@link #AD_STATE_SKIPPED}, {@link #AD_STATE_PLAYED} or {@link * #AD_STATE_AVAILABLE}, {@link #AD_STATE_SKIPPED}, {@link #AD_STATE_PLAYED} or {@link
* #AD_STATE_ERROR}. * #AD_STATE_ERROR}.
*/ */
// @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility
// with Kotlin usages from before TYPE_USE was added.
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE})
@IntDef({ @IntDef({
AD_STATE_UNAVAILABLE, AD_STATE_UNAVAILABLE,
AD_STATE_AVAILABLE, AD_STATE_AVAILABLE,
...@@ -913,6 +923,7 @@ public final class AdPlaybackState implements Bundleable { ...@@ -913,6 +923,7 @@ public final class AdPlaybackState implements Bundleable {
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({ @IntDef({
FIELD_AD_GROUPS, FIELD_AD_GROUPS,
FIELD_AD_RESUME_POSITION_US, FIELD_AD_RESUME_POSITION_US,
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
*/ */
package androidx.media3.common; package androidx.media3.common;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.DoNotInline; import androidx.annotation.DoNotInline;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
...@@ -25,6 +27,7 @@ import androidx.media3.common.util.Util; ...@@ -25,6 +27,7 @@ import androidx.media3.common.util.Util;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method; import java.lang.reflect.Method;
/** /**
...@@ -40,6 +43,11 @@ import java.lang.reflect.Method; ...@@ -40,6 +43,11 @@ import java.lang.reflect.Method;
*/ */
public final class AudioAttributes implements Bundleable { public final class AudioAttributes implements Bundleable {
/**
* The default audio attributes, where the content type is {@link C#CONTENT_TYPE_UNKNOWN}, usage
* is {@link C#USAGE_MEDIA}, capture policy is {@link C#ALLOW_CAPTURE_BY_ALL} and no flags are
* set.
*/
public static final AudioAttributes DEFAULT = new Builder().build(); public static final AudioAttributes DEFAULT = new Builder().build();
/** Builder for {@link AudioAttributes}. */ /** Builder for {@link AudioAttributes}. */
...@@ -65,19 +73,19 @@ public final class AudioAttributes implements Bundleable { ...@@ -65,19 +73,19 @@ public final class AudioAttributes implements Bundleable {
spatializationBehavior = C.SPATIALIZATION_BEHAVIOR_AUTO; spatializationBehavior = C.SPATIALIZATION_BEHAVIOR_AUTO;
} }
/** @see android.media.AudioAttributes.Builder#setContentType(int) */ /** See {@link android.media.AudioAttributes.Builder#setContentType(int)} */
public Builder setContentType(@C.AudioContentType int contentType) { public Builder setContentType(@C.AudioContentType int contentType) {
this.contentType = contentType; this.contentType = contentType;
return this; return this;
} }
/** @see android.media.AudioAttributes.Builder#setFlags(int) */ /** See {@link android.media.AudioAttributes.Builder#setFlags(int)} */
public Builder setFlags(@C.AudioFlags int flags) { public Builder setFlags(@C.AudioFlags int flags) {
this.flags = flags; this.flags = flags;
return this; return this;
} }
/** @see android.media.AudioAttributes.Builder#setUsage(int) */ /** See {@link android.media.AudioAttributes.Builder#setUsage(int)} */
public Builder setUsage(@C.AudioUsage int usage) { public Builder setUsage(@C.AudioUsage int usage) {
this.usage = usage; this.usage = usage;
return this; return this;
...@@ -91,7 +99,7 @@ public final class AudioAttributes implements Bundleable { ...@@ -91,7 +99,7 @@ public final class AudioAttributes implements Bundleable {
// TODO[b/190759307] Update javadoc to link to AudioAttributes.Builder#setSpatializationBehavior // TODO[b/190759307] Update javadoc to link to AudioAttributes.Builder#setSpatializationBehavior
// once compile SDK target is set to 32. // once compile SDK target is set to 32.
/** See AudioAttributes.Builder#setSpatializationBehavior(int). */ /** See {@code android.media.AudioAttributes.Builder.setSpatializationBehavior(int)}. */
public Builder setSpatializationBehavior(@C.SpatializationBehavior int spatializationBehavior) { public Builder setSpatializationBehavior(@C.SpatializationBehavior int spatializationBehavior) {
this.spatializationBehavior = spatializationBehavior; this.spatializationBehavior = spatializationBehavior;
return this; return this;
...@@ -104,10 +112,15 @@ public final class AudioAttributes implements Bundleable { ...@@ -104,10 +112,15 @@ public final class AudioAttributes implements Bundleable {
} }
} }
/** The {@link C.AudioContentType}. */
public final @C.AudioContentType int contentType; public final @C.AudioContentType int contentType;
/** The {@link C.AudioFlags}. */
public final @C.AudioFlags int flags; public final @C.AudioFlags int flags;
/** The {@link C.AudioUsage}. */
public final @C.AudioUsage int usage; public final @C.AudioUsage int usage;
/** The {@link C.AudioAllowedCapturePolicy}. */
public final @C.AudioAllowedCapturePolicy int allowedCapturePolicy; public final @C.AudioAllowedCapturePolicy int allowedCapturePolicy;
/** The {@link C.SpatializationBehavior}. */
public final @C.SpatializationBehavior int spatializationBehavior; public final @C.SpatializationBehavior int spatializationBehavior;
@Nullable private android.media.AudioAttributes audioAttributesV21; @Nullable private android.media.AudioAttributes audioAttributesV21;
...@@ -180,6 +193,7 @@ public final class AudioAttributes implements Bundleable { ...@@ -180,6 +193,7 @@ public final class AudioAttributes implements Bundleable {
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({ @IntDef({
FIELD_CONTENT_TYPE, FIELD_CONTENT_TYPE,
FIELD_FLAGS, FIELD_FLAGS,
......
...@@ -384,8 +384,7 @@ public abstract class BasePlayer implements Player { ...@@ -384,8 +384,7 @@ public abstract class BasePlayer implements Player {
: timeline.getWindow(getCurrentMediaItemIndex(), window).getDurationMs(); : timeline.getWindow(getCurrentMediaItemIndex(), window).getDurationMs();
} }
@RepeatMode private @RepeatMode int getRepeatModeForNavigation() {
private int getRepeatModeForNavigation() {
@RepeatMode int repeatMode = getRepeatMode(); @RepeatMode int repeatMode = getRepeatMode();
return repeatMode == REPEAT_MODE_ONE ? REPEAT_MODE_OFF : repeatMode; return repeatMode == REPEAT_MODE_ONE ? REPEAT_MODE_OFF : repeatMode;
} }
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
*/ */
package androidx.media3.common; package androidx.media3.common;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
...@@ -22,6 +24,7 @@ import androidx.media3.common.util.UnstableApi; ...@@ -22,6 +24,7 @@ import androidx.media3.common.util.UnstableApi;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Arrays; import java.util.Arrays;
import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.Pure;
...@@ -35,8 +38,7 @@ public final class ColorInfo implements Bundleable { ...@@ -35,8 +38,7 @@ public final class ColorInfo implements Bundleable {
* made. * made.
*/ */
@Pure @Pure
@C.ColorSpace public static @C.ColorSpace int isoColorPrimariesToColorSpace(int isoColorPrimaries) {
public static int isoColorPrimariesToColorSpace(int isoColorPrimaries) {
switch (isoColorPrimaries) { switch (isoColorPrimaries) {
case 1: case 1:
return C.COLOR_SPACE_BT709; return C.COLOR_SPACE_BT709;
...@@ -58,8 +60,8 @@ public final class ColorInfo implements Bundleable { ...@@ -58,8 +60,8 @@ public final class ColorInfo implements Bundleable {
* mapping can be made. * mapping can be made.
*/ */
@Pure @Pure
@C.ColorTransfer public static @C.ColorTransfer int isoTransferCharacteristicsToColorTransfer(
public static int isoTransferCharacteristicsToColorTransfer(int isoTransferCharacteristics) { int isoTransferCharacteristics) {
switch (isoTransferCharacteristics) { switch (isoTransferCharacteristics) {
case 1: // BT.709. case 1: // BT.709.
case 6: // SMPTE 170M. case 6: // SMPTE 170M.
...@@ -78,20 +80,20 @@ public final class ColorInfo implements Bundleable { ...@@ -78,20 +80,20 @@ public final class ColorInfo implements Bundleable {
* The color space of the video. Valid values are {@link C#COLOR_SPACE_BT601}, {@link * The color space of the video. Valid values are {@link C#COLOR_SPACE_BT601}, {@link
* C#COLOR_SPACE_BT709}, {@link C#COLOR_SPACE_BT2020} or {@link Format#NO_VALUE} if unknown. * C#COLOR_SPACE_BT709}, {@link C#COLOR_SPACE_BT2020} or {@link Format#NO_VALUE} if unknown.
*/ */
@C.ColorSpace public final int colorSpace; public final @C.ColorSpace int colorSpace;
/** /**
* The color range of the video. Valid values are {@link C#COLOR_RANGE_LIMITED}, {@link * The color range of the video. Valid values are {@link C#COLOR_RANGE_LIMITED}, {@link
* C#COLOR_RANGE_FULL} or {@link Format#NO_VALUE} if unknown. * C#COLOR_RANGE_FULL} or {@link Format#NO_VALUE} if unknown.
*/ */
@C.ColorRange public final int colorRange; public final @C.ColorRange int colorRange;
/** /**
* The color transfer characteristics of the video. Valid values are {@link C#COLOR_TRANSFER_HLG}, * The color transfer characteristics of the video. Valid values are {@link C#COLOR_TRANSFER_HLG},
* {@link C#COLOR_TRANSFER_ST2084}, {@link C#COLOR_TRANSFER_SDR} or {@link Format#NO_VALUE} if * {@link C#COLOR_TRANSFER_ST2084}, {@link C#COLOR_TRANSFER_SDR} or {@link Format#NO_VALUE} if
* unknown. * unknown.
*/ */
@C.ColorTransfer public final int colorTransfer; public final @C.ColorTransfer int colorTransfer;
/** HdrStaticInfo as defined in CTA-861.3, or null if none specified. */ /** HdrStaticInfo as defined in CTA-861.3, or null if none specified. */
@Nullable public final byte[] hdrStaticInfo; @Nullable public final byte[] hdrStaticInfo;
...@@ -163,6 +165,7 @@ public final class ColorInfo implements Bundleable { ...@@ -163,6 +165,7 @@ public final class ColorInfo implements Bundleable {
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({ @IntDef({
FIELD_COLOR_SPACE, FIELD_COLOR_SPACE,
FIELD_COLOR_RANGE, FIELD_COLOR_RANGE,
......
...@@ -15,12 +15,13 @@ ...@@ -15,12 +15,13 @@
*/ */
package androidx.media3.common; package androidx.media3.common;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
...@@ -31,7 +32,7 @@ public final class DeviceInfo implements Bundleable { ...@@ -31,7 +32,7 @@ public final class DeviceInfo implements Bundleable {
/** Types of playback. One of {@link #PLAYBACK_TYPE_LOCAL} or {@link #PLAYBACK_TYPE_REMOTE}. */ /** Types of playback. One of {@link #PLAYBACK_TYPE_LOCAL} or {@link #PLAYBACK_TYPE_REMOTE}. */
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE_USE}) @Target(TYPE_USE)
@IntDef({ @IntDef({
PLAYBACK_TYPE_LOCAL, PLAYBACK_TYPE_LOCAL,
PLAYBACK_TYPE_REMOTE, PLAYBACK_TYPE_REMOTE,
...@@ -88,6 +89,7 @@ public final class DeviceInfo implements Bundleable { ...@@ -88,6 +89,7 @@ public final class DeviceInfo implements Bundleable {
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({FIELD_PLAYBACK_TYPE, FIELD_MIN_VOLUME, FIELD_MAX_VOLUME}) @IntDef({FIELD_PLAYBACK_TYPE, FIELD_MIN_VOLUME, FIELD_MAX_VOLUME})
private @interface FieldNumber {} private @interface FieldNumber {}
......
...@@ -52,7 +52,8 @@ public final class DrmInitData implements Comparator<SchemeData>, Parcelable { ...@@ -52,7 +52,8 @@ public final class DrmInitData implements Comparator<SchemeData>, Parcelable {
* @param mediaData DRM session acquisition data obtained from the media. * @param mediaData DRM session acquisition data obtained from the media.
* @return A {@link DrmInitData} obtained from merging a media manifest and a media stream. * @return A {@link DrmInitData} obtained from merging a media manifest and a media stream.
*/ */
public static @Nullable DrmInitData createSessionCreationData( @Nullable
public static DrmInitData createSessionCreationData(
@Nullable DrmInitData manifestData, @Nullable DrmInitData mediaData) { @Nullable DrmInitData manifestData, @Nullable DrmInitData mediaData) {
ArrayList<SchemeData> result = new ArrayList<>(); ArrayList<SchemeData> result = new ArrayList<>();
String schemeType = null; String schemeType = null;
...@@ -91,7 +92,9 @@ public final class DrmInitData implements Comparator<SchemeData>, Parcelable { ...@@ -91,7 +92,9 @@ public final class DrmInitData implements Comparator<SchemeData>, Parcelable {
/** Number of {@link SchemeData}s. */ /** Number of {@link SchemeData}s. */
public final int schemeDataCount; public final int schemeDataCount;
/** @param schemeDatas Scheme initialization data for possibly multiple DRM schemes. */ /**
* @param schemeDatas Scheme initialization data for possibly multiple DRM schemes.
*/
public DrmInitData(List<SchemeData> schemeDatas) { public DrmInitData(List<SchemeData> schemeDatas) {
this(null, false, schemeDatas.toArray(new SchemeData[0])); this(null, false, schemeDatas.toArray(new SchemeData[0]));
} }
...@@ -104,7 +107,9 @@ public final class DrmInitData implements Comparator<SchemeData>, Parcelable { ...@@ -104,7 +107,9 @@ public final class DrmInitData implements Comparator<SchemeData>, Parcelable {
this(schemeType, false, schemeDatas.toArray(new SchemeData[0])); this(schemeType, false, schemeDatas.toArray(new SchemeData[0]));
} }
/** @param schemeDatas Scheme initialization data for possibly multiple DRM schemes. */ /**
* @param schemeDatas Scheme initialization data for possibly multiple DRM schemes.
*/
public DrmInitData(SchemeData... schemeDatas) { public DrmInitData(SchemeData... schemeDatas) {
this(null, schemeDatas); this(null, schemeDatas);
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package androidx.media3.common; package androidx.media3.common;
import static androidx.media3.common.MimeTypes.normalizeMimeType; import static androidx.media3.common.MimeTypes.normalizeMimeType;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.net.Uri; import android.net.Uri;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
...@@ -25,6 +26,7 @@ import androidx.media3.common.util.UnstableApi; ...@@ -25,6 +26,7 @@ import androidx.media3.common.util.UnstableApi;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -39,6 +41,7 @@ public final class FileTypes { ...@@ -39,6 +41,7 @@ public final class FileTypes {
*/ */
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({ @IntDef({
UNKNOWN, AC3, AC4, ADTS, AMR, FLAC, FLV, MATROSKA, MP3, MP4, OGG, PS, TS, WAV, WEBVTT, JPEG UNKNOWN, AC3, AC4, ADTS, AMR, FLAC, FLV, MATROSKA, MP3, MP4, OGG, PS, TS, WAV, WEBVTT, JPEG
}) })
...@@ -111,8 +114,8 @@ public final class FileTypes { ...@@ -111,8 +114,8 @@ public final class FileTypes {
private FileTypes() {} private FileTypes() {}
/** Returns the {@link Type} corresponding to the response headers provided. */ /** Returns the {@link Type} corresponding to the response headers provided. */
@FileTypes.Type public static @FileTypes.Type int inferFileTypeFromResponseHeaders(
public static int inferFileTypeFromResponseHeaders(Map<String, List<String>> responseHeaders) { Map<String, List<String>> responseHeaders) {
@Nullable List<String> contentTypes = responseHeaders.get(HEADER_CONTENT_TYPE); @Nullable List<String> contentTypes = responseHeaders.get(HEADER_CONTENT_TYPE);
@Nullable @Nullable
String mimeType = contentTypes == null || contentTypes.isEmpty() ? null : contentTypes.get(0); String mimeType = contentTypes == null || contentTypes.isEmpty() ? null : contentTypes.get(0);
...@@ -124,8 +127,7 @@ public final class FileTypes { ...@@ -124,8 +127,7 @@ public final class FileTypes {
* *
* <p>Returns {@link #UNKNOWN} if the mime type is {@code null}. * <p>Returns {@link #UNKNOWN} if the mime type is {@code null}.
*/ */
@FileTypes.Type public static @FileTypes.Type int inferFileTypeFromMimeType(@Nullable String mimeType) {
public static int inferFileTypeFromMimeType(@Nullable String mimeType) {
if (mimeType == null) { if (mimeType == null) {
return FileTypes.UNKNOWN; return FileTypes.UNKNOWN;
} }
...@@ -175,8 +177,7 @@ public final class FileTypes { ...@@ -175,8 +177,7 @@ public final class FileTypes {
} }
/** Returns the {@link Type} corresponding to the {@link Uri} provided. */ /** Returns the {@link Type} corresponding to the {@link Uri} provided. */
@FileTypes.Type public static @FileTypes.Type int inferFileTypeFromUri(Uri uri) {
public static int inferFileTypeFromUri(Uri uri) {
@Nullable String filename = uri.getLastPathSegment(); @Nullable String filename = uri.getLastPathSegment();
if (filename == null) { if (filename == null) {
return FileTypes.UNKNOWN; return FileTypes.UNKNOWN;
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
*/ */
package androidx.media3.common; package androidx.media3.common;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
...@@ -25,6 +27,7 @@ import com.google.common.base.Joiner; ...@@ -25,6 +27,7 @@ import com.google.common.base.Joiner;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
...@@ -153,14 +156,14 @@ public final class Format implements Bundleable { ...@@ -153,14 +156,14 @@ public final class Format implements Bundleable {
private int rotationDegrees; private int rotationDegrees;
private float pixelWidthHeightRatio; private float pixelWidthHeightRatio;
@Nullable private byte[] projectionData; @Nullable private byte[] projectionData;
@C.StereoMode private int stereoMode; private @C.StereoMode int stereoMode;
@Nullable private ColorInfo colorInfo; @Nullable private ColorInfo colorInfo;
// Audio specific. // Audio specific.
private int channelCount; private int channelCount;
private int sampleRate; private int sampleRate;
@C.PcmEncoding private int pcmEncoding; private @C.PcmEncoding int pcmEncoding;
private int encoderDelay; private int encoderDelay;
private int encoderPadding; private int encoderPadding;
...@@ -170,7 +173,7 @@ public final class Format implements Bundleable { ...@@ -170,7 +173,7 @@ public final class Format implements Bundleable {
// Provided by the source. // Provided by the source.
@C.CryptoType private int cryptoType; private @C.CryptoType int cryptoType;
/** Creates a new instance with default values. */ /** Creates a new instance with default values. */
public Builder() { public Builder() {
...@@ -724,7 +727,7 @@ public final class Format implements Bundleable { ...@@ -724,7 +727,7 @@ public final class Format implements Bundleable {
* modes are {@link C#STEREO_MODE_MONO}, {@link C#STEREO_MODE_TOP_BOTTOM}, {@link * modes are {@link C#STEREO_MODE_MONO}, {@link C#STEREO_MODE_TOP_BOTTOM}, {@link
* C#STEREO_MODE_LEFT_RIGHT}, {@link C#STEREO_MODE_STEREO_MESH}. * C#STEREO_MODE_LEFT_RIGHT}, {@link C#STEREO_MODE_STEREO_MESH}.
*/ */
@UnstableApi @C.StereoMode public final int stereoMode; @UnstableApi public final @C.StereoMode int stereoMode;
/** The color metadata associated with the video, or null if not applicable. */ /** The color metadata associated with the video, or null if not applicable. */
@UnstableApi @Nullable public final ColorInfo colorInfo; @UnstableApi @Nullable public final ColorInfo colorInfo;
...@@ -735,7 +738,7 @@ public final class Format implements Bundleable { ...@@ -735,7 +738,7 @@ public final class Format implements Bundleable {
/** The audio sampling rate in Hz, or {@link #NO_VALUE} if unknown or not applicable. */ /** The audio sampling rate in Hz, or {@link #NO_VALUE} if unknown or not applicable. */
public final int sampleRate; public final int sampleRate;
/** The {@link C.PcmEncoding} for PCM audio. Set to {@link #NO_VALUE} for other media types. */ /** The {@link C.PcmEncoding} for PCM audio. Set to {@link #NO_VALUE} for other media types. */
@UnstableApi @C.PcmEncoding public final int pcmEncoding; @UnstableApi public final @C.PcmEncoding int pcmEncoding;
/** /**
* The number of frames to trim from the start of the decoded audio stream, or 0 if not * The number of frames to trim from the start of the decoded audio stream, or 0 if not
* applicable. * applicable.
...@@ -759,14 +762,16 @@ public final class Format implements Bundleable { ...@@ -759,14 +762,16 @@ public final class Format implements Bundleable {
* {@link #drmInitData} is non-null, but may be {@link C#CRYPTO_TYPE_UNSUPPORTED} to indicate that * {@link #drmInitData} is non-null, but may be {@link C#CRYPTO_TYPE_UNSUPPORTED} to indicate that
* the samples are encrypted using an unsupported crypto type. * the samples are encrypted using an unsupported crypto type.
*/ */
@UnstableApi @C.CryptoType public final int cryptoType; @UnstableApi public final @C.CryptoType int cryptoType;
// Lazily initialized hashcode. // Lazily initialized hashcode.
private int hashCode; private int hashCode;
// Video. // Video.
/** @deprecated Use {@link Format.Builder}. */ /**
* @deprecated Use {@link Format.Builder}.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public static Format createVideoSampleFormat( public static Format createVideoSampleFormat(
...@@ -795,7 +800,9 @@ public final class Format implements Bundleable { ...@@ -795,7 +800,9 @@ public final class Format implements Bundleable {
.build(); .build();
} }
/** @deprecated Use {@link Format.Builder}. */ /**
* @deprecated Use {@link Format.Builder}.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public static Format createVideoSampleFormat( public static Format createVideoSampleFormat(
...@@ -830,7 +837,9 @@ public final class Format implements Bundleable { ...@@ -830,7 +837,9 @@ public final class Format implements Bundleable {
// Audio. // Audio.
/** @deprecated Use {@link Format.Builder}. */ /**
* @deprecated Use {@link Format.Builder}.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public static Format createAudioSampleFormat( public static Format createAudioSampleFormat(
...@@ -861,7 +870,9 @@ public final class Format implements Bundleable { ...@@ -861,7 +870,9 @@ public final class Format implements Bundleable {
.build(); .build();
} }
/** @deprecated Use {@link Format.Builder}. */ /**
* @deprecated Use {@link Format.Builder}.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public static Format createAudioSampleFormat( public static Format createAudioSampleFormat(
...@@ -896,7 +907,9 @@ public final class Format implements Bundleable { ...@@ -896,7 +907,9 @@ public final class Format implements Bundleable {
// Generic. // Generic.
/** @deprecated Use {@link Format.Builder}. */ /**
* @deprecated Use {@link Format.Builder}.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public static Format createContainerFormat( public static Format createContainerFormat(
...@@ -923,7 +936,9 @@ public final class Format implements Bundleable { ...@@ -923,7 +936,9 @@ public final class Format implements Bundleable {
.build(); .build();
} }
/** @deprecated Use {@link Format.Builder}. */ /**
* @deprecated Use {@link Format.Builder}.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public static Format createSampleFormat(@Nullable String id, @Nullable String sampleMimeType) { public static Format createSampleFormat(@Nullable String id, @Nullable String sampleMimeType) {
...@@ -983,28 +998,36 @@ public final class Format implements Bundleable { ...@@ -983,28 +998,36 @@ public final class Format implements Bundleable {
return new Builder(this); return new Builder(this);
} }
/** @deprecated Use {@link #buildUpon()} and {@link Builder#setMaxInputSize(int)}. */ /**
* @deprecated Use {@link #buildUpon()} and {@link Builder#setMaxInputSize(int)}.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public Format copyWithMaxInputSize(int maxInputSize) { public Format copyWithMaxInputSize(int maxInputSize) {
return buildUpon().setMaxInputSize(maxInputSize).build(); return buildUpon().setMaxInputSize(maxInputSize).build();
} }
/** @deprecated Use {@link #buildUpon()} and {@link Builder#setSubsampleOffsetUs(long)}. */ /**
* @deprecated Use {@link #buildUpon()} and {@link Builder#setSubsampleOffsetUs(long)}.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public Format copyWithSubsampleOffsetUs(long subsampleOffsetUs) { public Format copyWithSubsampleOffsetUs(long subsampleOffsetUs) {
return buildUpon().setSubsampleOffsetUs(subsampleOffsetUs).build(); return buildUpon().setSubsampleOffsetUs(subsampleOffsetUs).build();
} }
/** @deprecated Use {@link #buildUpon()} and {@link Builder#setLabel(String)} . */ /**
* @deprecated Use {@link #buildUpon()} and {@link Builder#setLabel(String)} .
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public Format copyWithLabel(@Nullable String label) { public Format copyWithLabel(@Nullable String label) {
return buildUpon().setLabel(label).build(); return buildUpon().setLabel(label).build();
} }
/** @deprecated Use {@link #withManifestFormatInfo(Format)}. */ /**
* @deprecated Use {@link #withManifestFormatInfo(Format)}.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public Format copyWithManifestFormatInfo(Format manifestFormat) { public Format copyWithManifestFormatInfo(Format manifestFormat) {
...@@ -1089,21 +1112,27 @@ public final class Format implements Bundleable { ...@@ -1089,21 +1112,27 @@ public final class Format implements Bundleable {
return buildUpon().setEncoderDelay(encoderDelay).setEncoderPadding(encoderPadding).build(); return buildUpon().setEncoderDelay(encoderDelay).setEncoderPadding(encoderPadding).build();
} }
/** @deprecated Use {@link #buildUpon()} and {@link Builder#setFrameRate(float)}. */ /**
* @deprecated Use {@link #buildUpon()} and {@link Builder#setFrameRate(float)}.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public Format copyWithFrameRate(float frameRate) { public Format copyWithFrameRate(float frameRate) {
return buildUpon().setFrameRate(frameRate).build(); return buildUpon().setFrameRate(frameRate).build();
} }
/** @deprecated Use {@link #buildUpon()} and {@link Builder#setDrmInitData(DrmInitData)}. */ /**
* @deprecated Use {@link #buildUpon()} and {@link Builder#setDrmInitData(DrmInitData)}.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public Format copyWithDrmInitData(@Nullable DrmInitData drmInitData) { public Format copyWithDrmInitData(@Nullable DrmInitData drmInitData) {
return buildUpon().setDrmInitData(drmInitData).build(); return buildUpon().setDrmInitData(drmInitData).build();
} }
/** @deprecated Use {@link #buildUpon()} and {@link Builder#setMetadata(Metadata)}. */ /**
* @deprecated Use {@link #buildUpon()} and {@link Builder#setMetadata(Metadata)}.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public Format copyWithMetadata(@Nullable Metadata metadata) { public Format copyWithMetadata(@Nullable Metadata metadata) {
...@@ -1417,6 +1446,7 @@ public final class Format implements Bundleable { ...@@ -1417,6 +1446,7 @@ public final class Format implements Bundleable {
// Bundleable implementation. // Bundleable implementation.
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({ @IntDef({
FIELD_ID, FIELD_ID,
FIELD_LABEL, FIELD_LABEL,
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package androidx.media3.common; package androidx.media3.common;
import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkArgument;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
...@@ -25,6 +26,7 @@ import com.google.common.base.Objects; ...@@ -25,6 +26,7 @@ import com.google.common.base.Objects;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** /**
* A rating expressed as "heart" or "no heart". It can be used to indicate whether the content is a * A rating expressed as "heart" or "no heart". It can be used to indicate whether the content is a
...@@ -77,10 +79,11 @@ public final class HeartRating extends Rating { ...@@ -77,10 +79,11 @@ public final class HeartRating extends Rating {
// Bundleable implementation. // Bundleable implementation.
@RatingType private static final int TYPE = RATING_TYPE_HEART; private static final @RatingType int TYPE = RATING_TYPE_HEART;
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({FIELD_RATING_TYPE, FIELD_RATED, FIELD_IS_HEART}) @IntDef({FIELD_RATING_TYPE, FIELD_RATED, FIELD_IS_HEART})
private @interface FieldNumber {} private @interface FieldNumber {}
...@@ -102,7 +105,7 @@ public final class HeartRating extends Rating { ...@@ -102,7 +105,7 @@ public final class HeartRating extends Rating {
private static HeartRating fromBundle(Bundle bundle) { private static HeartRating fromBundle(Bundle bundle) {
checkArgument( checkArgument(
bundle.getInt(keyForField(FIELD_RATING_TYPE), /* defaultValue= */ RATING_TYPE_DEFAULT) bundle.getInt(keyForField(FIELD_RATING_TYPE), /* defaultValue= */ RATING_TYPE_UNSET)
== TYPE); == TYPE);
boolean isRated = bundle.getBoolean(keyForField(FIELD_RATED), /* defaultValue= */ false); boolean isRated = bundle.getBoolean(keyForField(FIELD_RATED), /* defaultValue= */ false);
return isRated return isRated
......
...@@ -17,6 +17,7 @@ package androidx.media3.common; ...@@ -17,6 +17,7 @@ package androidx.media3.common;
import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Assertions.checkState;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
...@@ -31,6 +32,7 @@ import com.google.common.collect.ImmutableMap; ...@@ -31,6 +32,7 @@ import com.google.common.collect.ImmutableMap;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
...@@ -710,7 +712,9 @@ public final class MediaItem implements Bundleable { ...@@ -710,7 +712,9 @@ public final class MediaItem implements Bundleable {
/** The UUID of the protection scheme. */ /** The UUID of the protection scheme. */
public final UUID scheme; public final UUID scheme;
/** @deprecated Use {@link #scheme} instead. */ /**
* @deprecated Use {@link #scheme} instead.
*/
@UnstableApi @Deprecated public final UUID uuid; @UnstableApi @Deprecated public final UUID uuid;
/** /**
...@@ -719,7 +723,9 @@ public final class MediaItem implements Bundleable { ...@@ -719,7 +723,9 @@ public final class MediaItem implements Bundleable {
*/ */
@Nullable public final Uri licenseUri; @Nullable public final Uri licenseUri;
/** @deprecated Use {@link #licenseRequestHeaders} instead. */ /**
* @deprecated Use {@link #licenseRequestHeaders} instead.
*/
@UnstableApi @Deprecated public final ImmutableMap<String, String> requestHeaders; @UnstableApi @Deprecated public final ImmutableMap<String, String> requestHeaders;
/** The headers to attach to requests sent to the DRM license server. */ /** The headers to attach to requests sent to the DRM license server. */
...@@ -740,7 +746,9 @@ public final class MediaItem implements Bundleable { ...@@ -740,7 +746,9 @@ public final class MediaItem implements Bundleable {
*/ */
public final boolean forceDefaultLicenseUri; public final boolean forceDefaultLicenseUri;
/** @deprecated Use {@link #forcedSessionTrackTypes}. */ /**
* @deprecated Use {@link #forcedSessionTrackTypes}.
*/
@UnstableApi @Deprecated public final ImmutableList<@C.TrackType Integer> sessionForClearTypes; @UnstableApi @Deprecated public final ImmutableList<@C.TrackType Integer> sessionForClearTypes;
/** /**
* The types of tracks for which to always use a DRM session even if the content is unencrypted. * The types of tracks for which to always use a DRM session even if the content is unencrypted.
...@@ -927,7 +935,9 @@ public final class MediaItem implements Bundleable { ...@@ -927,7 +935,9 @@ public final class MediaItem implements Bundleable {
/** Optional subtitles to be sideloaded. */ /** Optional subtitles to be sideloaded. */
public final ImmutableList<SubtitleConfiguration> subtitleConfigurations; public final ImmutableList<SubtitleConfiguration> subtitleConfigurations;
/** @deprecated Use {@link #subtitleConfigurations} instead. */ /**
* @deprecated Use {@link #subtitleConfigurations} instead.
*/
@UnstableApi @Deprecated public final List<Subtitle> subtitles; @UnstableApi @Deprecated public final List<Subtitle> subtitles;
/** /**
...@@ -996,7 +1006,9 @@ public final class MediaItem implements Bundleable { ...@@ -996,7 +1006,9 @@ public final class MediaItem implements Bundleable {
} }
} }
/** @deprecated Use {@link LocalConfiguration}. */ /**
* @deprecated Use {@link LocalConfiguration}.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public static final class PlaybackProperties extends LocalConfiguration { public static final class PlaybackProperties extends LocalConfiguration {
...@@ -1158,7 +1170,9 @@ public final class MediaItem implements Bundleable { ...@@ -1158,7 +1170,9 @@ public final class MediaItem implements Bundleable {
builder.maxPlaybackSpeed); builder.maxPlaybackSpeed);
} }
/** @deprecated Use {@link Builder} instead. */ /**
* @deprecated Use {@link Builder} instead.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public LiveConfiguration( public LiveConfiguration(
...@@ -1210,6 +1224,7 @@ public final class MediaItem implements Bundleable { ...@@ -1210,6 +1224,7 @@ public final class MediaItem implements Bundleable {
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({ @IntDef({
FIELD_TARGET_OFFSET_MS, FIELD_TARGET_OFFSET_MS,
FIELD_MIN_OFFSET_MS, FIELD_MIN_OFFSET_MS,
...@@ -1424,19 +1439,25 @@ public final class MediaItem implements Bundleable { ...@@ -1424,19 +1439,25 @@ public final class MediaItem implements Bundleable {
} }
} }
/** @deprecated Use {@link MediaItem.SubtitleConfiguration} instead */ /**
* @deprecated Use {@link MediaItem.SubtitleConfiguration} instead
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public static final class Subtitle extends SubtitleConfiguration { public static final class Subtitle extends SubtitleConfiguration {
/** @deprecated Use {@link Builder} instead. */ /**
* @deprecated Use {@link Builder} instead.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public Subtitle(Uri uri, String mimeType, @Nullable String language) { public Subtitle(Uri uri, String mimeType, @Nullable String language) {
this(uri, mimeType, language, /* selectionFlags= */ 0); this(uri, mimeType, language, /* selectionFlags= */ 0);
} }
/** @deprecated Use {@link Builder} instead. */ /**
* @deprecated Use {@link Builder} instead.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public Subtitle( public Subtitle(
...@@ -1444,7 +1465,9 @@ public final class MediaItem implements Bundleable { ...@@ -1444,7 +1465,9 @@ public final class MediaItem implements Bundleable {
this(uri, mimeType, language, selectionFlags, /* roleFlags= */ 0, /* label= */ null); this(uri, mimeType, language, selectionFlags, /* roleFlags= */ 0, /* label= */ null);
} }
/** @deprecated Use {@link Builder} instead. */ /**
* @deprecated Use {@link Builder} instead.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public Subtitle( public Subtitle(
...@@ -1547,7 +1570,9 @@ public final class MediaItem implements Bundleable { ...@@ -1547,7 +1570,9 @@ public final class MediaItem implements Bundleable {
return buildClippingProperties(); return buildClippingProperties();
} }
/** @deprecated Use {@link #build()} instead. */ /**
* @deprecated Use {@link #build()} instead.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public ClippingProperties buildClippingProperties() { public ClippingProperties buildClippingProperties() {
...@@ -1625,6 +1650,7 @@ public final class MediaItem implements Bundleable { ...@@ -1625,6 +1650,7 @@ public final class MediaItem implements Bundleable {
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({ @IntDef({
FIELD_START_POSITION_MS, FIELD_START_POSITION_MS,
FIELD_END_POSITION_MS, FIELD_END_POSITION_MS,
...@@ -1676,7 +1702,9 @@ public final class MediaItem implements Bundleable { ...@@ -1676,7 +1702,9 @@ public final class MediaItem implements Bundleable {
} }
} }
/** @deprecated Use {@link ClippingConfiguration} instead. */ /**
* @deprecated Use {@link ClippingConfiguration} instead.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public static final class ClippingProperties extends ClippingConfiguration { public static final class ClippingProperties extends ClippingConfiguration {
...@@ -1705,7 +1733,9 @@ public final class MediaItem implements Bundleable { ...@@ -1705,7 +1733,9 @@ public final class MediaItem implements Bundleable {
* boundaries. * boundaries.
*/ */
@Nullable public final LocalConfiguration localConfiguration; @Nullable public final LocalConfiguration localConfiguration;
/** @deprecated Use {@link #localConfiguration} instead. */ /**
* @deprecated Use {@link #localConfiguration} instead.
*/
@UnstableApi @Deprecated @Nullable public final PlaybackProperties playbackProperties; @UnstableApi @Deprecated @Nullable public final PlaybackProperties playbackProperties;
/** The live playback configuration. */ /** The live playback configuration. */
...@@ -1716,7 +1746,9 @@ public final class MediaItem implements Bundleable { ...@@ -1716,7 +1746,9 @@ public final class MediaItem implements Bundleable {
/** The clipping properties. */ /** The clipping properties. */
public final ClippingConfiguration clippingConfiguration; public final ClippingConfiguration clippingConfiguration;
/** @deprecated Use {@link #clippingConfiguration} instead. */ /**
* @deprecated Use {@link #clippingConfiguration} instead.
*/
@UnstableApi @Deprecated public final ClippingProperties clippingProperties; @UnstableApi @Deprecated public final ClippingProperties clippingProperties;
// Using PlaybackProperties and ClippingProperties until they're deleted. // Using PlaybackProperties and ClippingProperties until they're deleted.
...@@ -1773,6 +1805,7 @@ public final class MediaItem implements Bundleable { ...@@ -1773,6 +1805,7 @@ public final class MediaItem implements Bundleable {
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({ @IntDef({
FIELD_MEDIA_ID, FIELD_MEDIA_ID,
FIELD_LIVE_CONFIGURATION, FIELD_LIVE_CONFIGURATION,
...@@ -1839,7 +1872,7 @@ public final class MediaItem implements Bundleable { ...@@ -1839,7 +1872,7 @@ public final class MediaItem implements Bundleable {
return new MediaItem( return new MediaItem(
mediaId, mediaId,
clippingConfiguration, clippingConfiguration,
/* playbackProperties= */ null, /* localConfiguration= */ null,
liveConfiguration, liveConfiguration,
mediaMetadata); mediaMetadata);
} }
......
...@@ -56,11 +56,11 @@ public final class MediaMetadata implements Bundleable { ...@@ -56,11 +56,11 @@ public final class MediaMetadata implements Bundleable {
@Nullable private Rating userRating; @Nullable private Rating userRating;
@Nullable private Rating overallRating; @Nullable private Rating overallRating;
@Nullable private byte[] artworkData; @Nullable private byte[] artworkData;
@Nullable @PictureType private Integer artworkDataType; @Nullable private @PictureType Integer artworkDataType;
@Nullable private Uri artworkUri; @Nullable private Uri artworkUri;
@Nullable private Integer trackNumber; @Nullable private Integer trackNumber;
@Nullable private Integer totalTrackCount; @Nullable private Integer totalTrackCount;
@Nullable @FolderType private Integer folderType; @Nullable private @FolderType Integer folderType;
@Nullable private Boolean isPlayable; @Nullable private Boolean isPlayable;
@Nullable private Integer recordingYear; @Nullable private Integer recordingYear;
@Nullable private Integer recordingMonth; @Nullable private Integer recordingMonth;
...@@ -248,7 +248,9 @@ public final class MediaMetadata implements Bundleable { ...@@ -248,7 +248,9 @@ public final class MediaMetadata implements Bundleable {
return this; return this;
} }
/** @deprecated Use {@link #setRecordingYear(Integer)} instead. */ /**
* @deprecated Use {@link #setRecordingYear(Integer)} instead.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
public Builder setYear(@Nullable Integer year) { public Builder setYear(@Nullable Integer year) {
...@@ -521,6 +523,8 @@ public final class MediaMetadata implements Bundleable { ...@@ -521,6 +523,8 @@ public final class MediaMetadata implements Bundleable {
* href="https://www.bluetooth.com/specifications/specs/a-v-remote-control-profile-1-6-2/">Bluetooth * href="https://www.bluetooth.com/specifications/specs/a-v-remote-control-profile-1-6-2/">Bluetooth
* AVRCP 1.6.2</a>). * AVRCP 1.6.2</a>).
*/ */
// @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility
// with Kotlin usages from before TYPE_USE was added.
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE}) @Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE})
...@@ -559,6 +563,8 @@ public final class MediaMetadata implements Bundleable { ...@@ -559,6 +563,8 @@ public final class MediaMetadata implements Bundleable {
* <p>Values sourced from the ID3 v2.4 specification (See section 4.14 of * <p>Values sourced from the ID3 v2.4 specification (See section 4.14 of
* https://id3.org/id3v2.4.0-frames). * https://id3.org/id3v2.4.0-frames).
*/ */
// @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility
// with Kotlin usages from before TYPE_USE was added.
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE}) @Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE})
...@@ -650,7 +656,9 @@ public final class MediaMetadata implements Bundleable { ...@@ -650,7 +656,9 @@ public final class MediaMetadata implements Bundleable {
@Nullable public final @FolderType Integer folderType; @Nullable public final @FolderType Integer folderType;
/** Optional boolean for media playability. */ /** Optional boolean for media playability. */
@Nullable public final Boolean isPlayable; @Nullable public final Boolean isPlayable;
/** @deprecated Use {@link #recordingYear} instead. */ /**
* @deprecated Use {@link #recordingYear} instead.
*/
@UnstableApi @Deprecated @Nullable public final Integer year; @UnstableApi @Deprecated @Nullable public final Integer year;
/** Optional year of the recording date. */ /** Optional year of the recording date. */
@Nullable public final Integer recordingYear; @Nullable public final Integer recordingYear;
...@@ -829,6 +837,7 @@ public final class MediaMetadata implements Bundleable { ...@@ -829,6 +837,7 @@ public final class MediaMetadata implements Bundleable {
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({ @IntDef({
FIELD_TITLE, FIELD_TITLE,
FIELD_ARTIST, FIELD_ARTIST,
......
...@@ -62,12 +62,16 @@ public final class Metadata implements Parcelable { ...@@ -62,12 +62,16 @@ public final class Metadata implements Parcelable {
private final Entry[] entries; private final Entry[] entries;
/** @param entries The metadata entries. */ /**
* @param entries The metadata entries.
*/
public Metadata(Entry... entries) { public Metadata(Entry... entries) {
this.entries = entries; this.entries = entries;
} }
/** @param entries The metadata entries. */ /**
* @param entries The metadata entries.
*/
public Metadata(List<? extends Entry> entries) { public Metadata(List<? extends Entry> entries) {
this.entries = entries.toArray(new Entry[0]); this.entries = entries.toArray(new Entry[0]);
} }
......
...@@ -552,8 +552,7 @@ public final class MimeTypes { ...@@ -552,8 +552,7 @@ public final class MimeTypes {
* @return The corresponding {@link C.Encoding}, or {@link C#ENCODING_INVALID}. * @return The corresponding {@link C.Encoding}, or {@link C#ENCODING_INVALID}.
*/ */
@UnstableApi @UnstableApi
@C.Encoding public static @C.Encoding int getEncoding(String mimeType, @Nullable String codec) {
public static int getEncoding(String mimeType, @Nullable String codec) {
switch (mimeType) { switch (mimeType) {
case MimeTypes.AUDIO_MPEG: case MimeTypes.AUDIO_MPEG:
return C.ENCODING_MP3; return C.ENCODING_MP3;
...@@ -728,8 +727,7 @@ public final class MimeTypes { ...@@ -728,8 +727,7 @@ public final class MimeTypes {
} }
/** Returns the encoding for {@link #audioObjectTypeIndication}. */ /** Returns the encoding for {@link #audioObjectTypeIndication}. */
@C.Encoding public @C.Encoding int getEncoding() {
public int getEncoding() {
// See AUDIO_OBJECT_TYPE_AAC_* constants in AacUtil. // See AUDIO_OBJECT_TYPE_AAC_* constants in AacUtil.
switch (audioObjectTypeIndication) { switch (audioObjectTypeIndication) {
case 2: case 2:
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package androidx.media3.common; package androidx.media3.common;
import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkArgument;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.FloatRange; import androidx.annotation.FloatRange;
...@@ -26,6 +27,7 @@ import com.google.common.base.Objects; ...@@ -26,6 +27,7 @@ import com.google.common.base.Objects;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** A rating expressed as a percentage. */ /** A rating expressed as a percentage. */
public final class PercentageRating extends Rating { public final class PercentageRating extends Rating {
...@@ -75,10 +77,11 @@ public final class PercentageRating extends Rating { ...@@ -75,10 +77,11 @@ public final class PercentageRating extends Rating {
// Bundleable implementation. // Bundleable implementation.
@RatingType private static final int TYPE = RATING_TYPE_PERCENTAGE; private static final @RatingType int TYPE = RATING_TYPE_PERCENTAGE;
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({FIELD_RATING_TYPE, FIELD_PERCENT}) @IntDef({FIELD_RATING_TYPE, FIELD_PERCENT})
private @interface FieldNumber {} private @interface FieldNumber {}
...@@ -98,7 +101,7 @@ public final class PercentageRating extends Rating { ...@@ -98,7 +101,7 @@ public final class PercentageRating extends Rating {
private static PercentageRating fromBundle(Bundle bundle) { private static PercentageRating fromBundle(Bundle bundle) {
checkArgument( checkArgument(
bundle.getInt(keyForField(FIELD_RATING_TYPE), /* defaultValue= */ RATING_TYPE_DEFAULT) bundle.getInt(keyForField(FIELD_RATING_TYPE), /* defaultValue= */ RATING_TYPE_UNSET)
== TYPE); == TYPE);
float percent = bundle.getFloat(keyForField(FIELD_PERCENT), /* defaultValue= */ RATING_UNSET); float percent = bundle.getFloat(keyForField(FIELD_PERCENT), /* defaultValue= */ RATING_UNSET);
return percent == RATING_UNSET ? new PercentageRating() : new PercentageRating(percent); return percent == RATING_UNSET ? new PercentageRating() : new PercentageRating(percent);
......
...@@ -46,6 +46,8 @@ public class PlaybackException extends Exception implements Bundleable { ...@@ -46,6 +46,8 @@ public class PlaybackException extends Exception implements Bundleable {
* <p>This list of errors may be extended in future versions, and {@link Player} implementations * <p>This list of errors may be extended in future versions, and {@link Player} implementations
* may define custom error codes. * may define custom error codes.
*/ */
// @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility
// with Kotlin usages from before TYPE_USE was added.
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE}) @Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE})
...@@ -408,6 +410,7 @@ public class PlaybackException extends Exception implements Bundleable { ...@@ -408,6 +410,7 @@ public class PlaybackException extends Exception implements Bundleable {
*/ */
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef( @IntDef(
open = true, open = true,
value = { value = {
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
*/ */
package androidx.media3.common; package androidx.media3.common;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.CheckResult; import androidx.annotation.CheckResult;
import androidx.annotation.FloatRange; import androidx.annotation.FloatRange;
...@@ -26,6 +28,7 @@ import androidx.media3.common.util.Util; ...@@ -26,6 +28,7 @@ import androidx.media3.common.util.Util;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** Parameters that apply to playback, including speed setting. */ /** Parameters that apply to playback, including speed setting. */
public final class PlaybackParameters implements Bundleable { public final class PlaybackParameters implements Bundleable {
...@@ -121,6 +124,7 @@ public final class PlaybackParameters implements Bundleable { ...@@ -121,6 +124,7 @@ public final class PlaybackParameters implements Bundleable {
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({FIELD_SPEED, FIELD_PITCH}) @IntDef({FIELD_SPEED, FIELD_PITCH})
private @interface FieldNumber {} private @interface FieldNumber {}
......
...@@ -15,12 +15,15 @@ ...@@ -15,12 +15,15 @@
*/ */
package androidx.media3.common; package androidx.media3.common;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** /**
* A rating for media content. The style of a rating can be one of {@link HeartRating}, {@link * A rating for media content. The style of a rating can be one of {@link HeartRating}, {@link
...@@ -41,8 +44,9 @@ public abstract class Rating implements Bundleable { ...@@ -41,8 +44,9 @@ public abstract class Rating implements Bundleable {
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({ @IntDef({
RATING_TYPE_DEFAULT, RATING_TYPE_UNSET,
RATING_TYPE_HEART, RATING_TYPE_HEART,
RATING_TYPE_PERCENTAGE, RATING_TYPE_PERCENTAGE,
RATING_TYPE_STAR, RATING_TYPE_STAR,
...@@ -50,7 +54,7 @@ public abstract class Rating implements Bundleable { ...@@ -50,7 +54,7 @@ public abstract class Rating implements Bundleable {
}) })
/* package */ @interface RatingType {} /* package */ @interface RatingType {}
/* package */ static final int RATING_TYPE_DEFAULT = -1; /* package */ static final int RATING_TYPE_UNSET = -1;
/* package */ static final int RATING_TYPE_HEART = 0; /* package */ static final int RATING_TYPE_HEART = 0;
/* package */ static final int RATING_TYPE_PERCENTAGE = 1; /* package */ static final int RATING_TYPE_PERCENTAGE = 1;
/* package */ static final int RATING_TYPE_STAR = 2; /* package */ static final int RATING_TYPE_STAR = 2;
...@@ -58,6 +62,7 @@ public abstract class Rating implements Bundleable { ...@@ -58,6 +62,7 @@ public abstract class Rating implements Bundleable {
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({FIELD_RATING_TYPE}) @IntDef({FIELD_RATING_TYPE})
private @interface FieldNumber {} private @interface FieldNumber {}
...@@ -69,7 +74,7 @@ public abstract class Rating implements Bundleable { ...@@ -69,7 +74,7 @@ public abstract class Rating implements Bundleable {
private static Rating fromBundle(Bundle bundle) { private static Rating fromBundle(Bundle bundle) {
@RatingType @RatingType
int ratingType = int ratingType =
bundle.getInt(keyForField(FIELD_RATING_TYPE), /* defaultValue= */ RATING_TYPE_DEFAULT); bundle.getInt(keyForField(FIELD_RATING_TYPE), /* defaultValue= */ RATING_TYPE_UNSET);
switch (ratingType) { switch (ratingType) {
case RATING_TYPE_HEART: case RATING_TYPE_HEART:
return HeartRating.CREATOR.fromBundle(bundle); return HeartRating.CREATOR.fromBundle(bundle);
...@@ -79,8 +84,9 @@ public abstract class Rating implements Bundleable { ...@@ -79,8 +84,9 @@ public abstract class Rating implements Bundleable {
return StarRating.CREATOR.fromBundle(bundle); return StarRating.CREATOR.fromBundle(bundle);
case RATING_TYPE_THUMB: case RATING_TYPE_THUMB:
return ThumbRating.CREATOR.fromBundle(bundle); return ThumbRating.CREATOR.fromBundle(bundle);
case RATING_TYPE_UNSET:
default: default:
throw new IllegalArgumentException("Encountered unknown rating type: " + ratingType); throw new IllegalArgumentException("Unknown RatingType: " + ratingType);
} }
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package androidx.media3.common; package androidx.media3.common;
import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkArgument;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.FloatRange; import androidx.annotation.FloatRange;
...@@ -27,6 +28,7 @@ import com.google.common.base.Objects; ...@@ -27,6 +28,7 @@ import com.google.common.base.Objects;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** A rating expressed as a fractional number of stars. */ /** A rating expressed as a fractional number of stars. */
public final class StarRating extends Rating { public final class StarRating extends Rating {
...@@ -101,11 +103,12 @@ public final class StarRating extends Rating { ...@@ -101,11 +103,12 @@ public final class StarRating extends Rating {
// Bundleable implementation. // Bundleable implementation.
@RatingType private static final int TYPE = RATING_TYPE_STAR; private static final @RatingType int TYPE = RATING_TYPE_STAR;
private static final int MAX_STARS_DEFAULT = 5; private static final int MAX_STARS_DEFAULT = 5;
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({FIELD_RATING_TYPE, FIELD_MAX_STARS, FIELD_STAR_RATING}) @IntDef({FIELD_RATING_TYPE, FIELD_MAX_STARS, FIELD_STAR_RATING})
private @interface FieldNumber {} private @interface FieldNumber {}
...@@ -127,7 +130,7 @@ public final class StarRating extends Rating { ...@@ -127,7 +130,7 @@ public final class StarRating extends Rating {
private static StarRating fromBundle(Bundle bundle) { private static StarRating fromBundle(Bundle bundle) {
checkArgument( checkArgument(
bundle.getInt(keyForField(FIELD_RATING_TYPE), /* defaultValue= */ RATING_TYPE_DEFAULT) bundle.getInt(keyForField(FIELD_RATING_TYPE), /* defaultValue= */ RATING_TYPE_UNSET)
== TYPE); == TYPE);
int maxStars = int maxStars =
bundle.getInt(keyForField(FIELD_MAX_STARS), /* defaultValue= */ MAX_STARS_DEFAULT); bundle.getInt(keyForField(FIELD_MAX_STARS), /* defaultValue= */ MAX_STARS_DEFAULT);
......
...@@ -44,7 +44,9 @@ public final class StreamKey implements Comparable<StreamKey>, Parcelable { ...@@ -44,7 +44,9 @@ public final class StreamKey implements Comparable<StreamKey>, Parcelable {
/** The stream index. */ /** The stream index. */
public final int streamIndex; public final int streamIndex;
/** @deprecated Use {@link #streamIndex}. */ /**
* @deprecated Use {@link #streamIndex}.
*/
@Deprecated public final int trackIndex; @Deprecated public final int trackIndex;
/** /**
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package androidx.media3.common; package androidx.media3.common;
import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkArgument;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
...@@ -25,6 +26,7 @@ import com.google.common.base.Objects; ...@@ -25,6 +26,7 @@ import com.google.common.base.Objects;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** A rating expressed as "thumbs up" or "thumbs down". */ /** A rating expressed as "thumbs up" or "thumbs down". */
public final class ThumbRating extends Rating { public final class ThumbRating extends Rating {
...@@ -74,10 +76,11 @@ public final class ThumbRating extends Rating { ...@@ -74,10 +76,11 @@ public final class ThumbRating extends Rating {
// Bundleable implementation. // Bundleable implementation.
@RatingType private static final int TYPE = RATING_TYPE_THUMB; private static final @RatingType int TYPE = RATING_TYPE_THUMB;
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({FIELD_RATING_TYPE, FIELD_RATED, FIELD_IS_THUMBS_UP}) @IntDef({FIELD_RATING_TYPE, FIELD_RATED, FIELD_IS_THUMBS_UP})
private @interface FieldNumber {} private @interface FieldNumber {}
...@@ -99,7 +102,7 @@ public final class ThumbRating extends Rating { ...@@ -99,7 +102,7 @@ public final class ThumbRating extends Rating {
private static ThumbRating fromBundle(Bundle bundle) { private static ThumbRating fromBundle(Bundle bundle) {
checkArgument( checkArgument(
bundle.getInt(keyForField(FIELD_RATING_TYPE), /* defaultValue= */ RATING_TYPE_DEFAULT) bundle.getInt(keyForField(FIELD_RATING_TYPE), /* defaultValue= */ RATING_TYPE_UNSET)
== TYPE); == TYPE);
boolean rated = bundle.getBoolean(keyForField(FIELD_RATED), /* defaultValue= */ false); boolean rated = bundle.getBoolean(keyForField(FIELD_RATED), /* defaultValue= */ false);
return rated return rated
......
...@@ -20,6 +20,7 @@ import static androidx.media3.common.util.Assertions.checkArgument; ...@@ -20,6 +20,7 @@ import static androidx.media3.common.util.Assertions.checkArgument;
import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Assertions.checkState;
import static java.lang.Math.max; import static java.lang.Math.max;
import static java.lang.Math.min; import static java.lang.Math.min;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
...@@ -37,6 +38,7 @@ import com.google.errorprone.annotations.InlineMe; ...@@ -37,6 +38,7 @@ import com.google.errorprone.annotations.InlineMe;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -167,7 +169,9 @@ public abstract class Timeline implements Bundleable { ...@@ -167,7 +169,9 @@ public abstract class Timeline implements Bundleable {
*/ */
public Object uid; public Object uid;
/** @deprecated Use {@link #mediaItem} instead. */ /**
* @deprecated Use {@link #mediaItem} instead.
*/
@UnstableApi @Deprecated @Nullable public Object tag; @UnstableApi @Deprecated @Nullable public Object tag;
/** The {@link MediaItem} associated to the window. Not necessarily unique. */ /** The {@link MediaItem} associated to the window. Not necessarily unique. */
...@@ -210,7 +214,9 @@ public abstract class Timeline implements Bundleable { ...@@ -210,7 +214,9 @@ public abstract class Timeline implements Bundleable {
/** Whether this window may change when the timeline is updated. */ /** Whether this window may change when the timeline is updated. */
public boolean isDynamic; public boolean isDynamic;
/** @deprecated Use {@link #isLive()} instead. */ /**
* @deprecated Use {@link #isLive()} instead.
*/
@UnstableApi @Deprecated public boolean isLive; @UnstableApi @Deprecated public boolean isLive;
/** /**
...@@ -414,6 +420,7 @@ public abstract class Timeline implements Bundleable { ...@@ -414,6 +420,7 @@ public abstract class Timeline implements Bundleable {
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({ @IntDef({
FIELD_MEDIA_ITEM, FIELD_MEDIA_ITEM,
FIELD_PRESENTATION_START_TIME_MS, FIELD_PRESENTATION_START_TIME_MS,
...@@ -903,6 +910,7 @@ public abstract class Timeline implements Bundleable { ...@@ -903,6 +910,7 @@ public abstract class Timeline implements Bundleable {
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({ @IntDef({
FIELD_WINDOW_INDEX, FIELD_WINDOW_INDEX,
FIELD_DURATION_US, FIELD_DURATION_US,
...@@ -1174,7 +1182,9 @@ public abstract class Timeline implements Bundleable { ...@@ -1174,7 +1182,9 @@ public abstract class Timeline implements Bundleable {
== C.INDEX_UNSET; == C.INDEX_UNSET;
} }
/** @deprecated Use {@link #getPeriodPositionUs(Window, Period, int, long)} instead. */ /**
* @deprecated Use {@link #getPeriodPositionUs(Window, Period, int, long)} instead.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
@InlineMe(replacement = "this.getPeriodPositionUs(window, period, windowIndex, windowPositionUs)") @InlineMe(replacement = "this.getPeriodPositionUs(window, period, windowIndex, windowPositionUs)")
...@@ -1182,7 +1192,9 @@ public abstract class Timeline implements Bundleable { ...@@ -1182,7 +1192,9 @@ public abstract class Timeline implements Bundleable {
Window window, Period period, int windowIndex, long windowPositionUs) { Window window, Period period, int windowIndex, long windowPositionUs) {
return getPeriodPositionUs(window, period, windowIndex, windowPositionUs); return getPeriodPositionUs(window, period, windowIndex, windowPositionUs);
} }
/** @deprecated Use {@link #getPeriodPositionUs(Window, Period, int, long, long)} instead. */ /**
* @deprecated Use {@link #getPeriodPositionUs(Window, Period, int, long, long)} instead.
*/
@UnstableApi @UnstableApi
@Deprecated @Deprecated
@Nullable @Nullable
...@@ -1362,6 +1374,7 @@ public abstract class Timeline implements Bundleable { ...@@ -1362,6 +1374,7 @@ public abstract class Timeline implements Bundleable {
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({ @IntDef({
FIELD_WINDOWS, FIELD_WINDOWS,
FIELD_PERIODS, FIELD_PERIODS,
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package androidx.media3.common; package androidx.media3.common;
import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkArgument;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.CheckResult; import androidx.annotation.CheckResult;
...@@ -29,6 +30,7 @@ import com.google.common.collect.Lists; ...@@ -29,6 +30,7 @@ import com.google.common.collect.Lists;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
...@@ -41,6 +43,8 @@ public final class TrackGroup implements Bundleable { ...@@ -41,6 +43,8 @@ public final class TrackGroup implements Bundleable {
public final int length; public final int length;
/** An identifier for the track group. */ /** An identifier for the track group. */
public final String id; public final String id;
/** The type of tracks in the group. */
public final @C.TrackType int type;
private final Format[] formats; private final Format[] formats;
...@@ -69,6 +73,11 @@ public final class TrackGroup implements Bundleable { ...@@ -69,6 +73,11 @@ public final class TrackGroup implements Bundleable {
this.id = id; this.id = id;
this.formats = formats; this.formats = formats;
this.length = formats.length; this.length = formats.length;
@C.TrackType int type = MimeTypes.getTrackType(formats[0].sampleMimeType);
if (type == C.TRACK_TYPE_UNKNOWN) {
type = MimeTypes.getTrackType(formats[0].containerMimeType);
}
this.type = type;
verifyCorrectness(); verifyCorrectness();
} }
...@@ -132,13 +141,14 @@ public final class TrackGroup implements Bundleable { ...@@ -132,13 +141,14 @@ public final class TrackGroup implements Bundleable {
return false; return false;
} }
TrackGroup other = (TrackGroup) obj; TrackGroup other = (TrackGroup) obj;
return length == other.length && id.equals(other.id) && Arrays.equals(formats, other.formats); return id.equals(other.id) && Arrays.equals(formats, other.formats);
} }
// Bundleable implementation. // Bundleable implementation.
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({FIELD_FORMATS, FIELD_ID}) @IntDef({FIELD_FORMATS, FIELD_ID})
private @interface FieldNumber {} private @interface FieldNumber {}
...@@ -204,8 +214,7 @@ public final class TrackGroup implements Bundleable { ...@@ -204,8 +214,7 @@ public final class TrackGroup implements Bundleable {
return language == null || language.equals(C.LANGUAGE_UNDETERMINED) ? "" : language; return language == null || language.equals(C.LANGUAGE_UNDETERMINED) ? "" : language;
} }
@C.RoleFlags private static @C.RoleFlags int normalizeRoleFlags(@C.RoleFlags int roleFlags) {
private static int normalizeRoleFlags(@C.RoleFlags int roleFlags) {
// Treat trick-play and non-trick-play formats as compatible. // Treat trick-play and non-trick-play formats as compatible.
return roleFlags | C.ROLE_FLAG_TRICK_PLAY; return roleFlags | C.ROLE_FLAG_TRICK_PLAY;
} }
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
*/ */
package androidx.media3.common; package androidx.media3.common;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
...@@ -25,6 +27,7 @@ import com.google.common.collect.ImmutableList; ...@@ -25,6 +27,7 @@ import com.google.common.collect.ImmutableList;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.List; import java.util.List;
/** An immutable array of {@link TrackGroup}s. */ /** An immutable array of {@link TrackGroup}s. */
...@@ -105,6 +108,7 @@ public final class TrackGroupArray implements Bundleable { ...@@ -105,6 +108,7 @@ public final class TrackGroupArray implements Bundleable {
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({ @IntDef({
FIELD_TRACK_GROUPS, FIELD_TRACK_GROUPS,
}) })
......
...@@ -15,10 +15,11 @@ ...@@ -15,10 +15,11 @@
*/ */
package androidx.media3.common; package androidx.media3.common;
import static java.lang.annotation.ElementType.TYPE_USE;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
...@@ -38,7 +39,7 @@ public interface TrackSelection { ...@@ -38,7 +39,7 @@ public interface TrackSelection {
*/ */
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE_USE}) @Target(TYPE_USE)
@IntDef( @IntDef(
open = true, open = true,
value = {TYPE_UNSET}) value = {TYPE_UNSET})
......
...@@ -32,7 +32,9 @@ public final class TrackSelectionArray { ...@@ -32,7 +32,9 @@ public final class TrackSelectionArray {
// Lazily initialized hashcode. // Lazily initialized hashcode.
private int hashCode; private int hashCode;
/** @param trackSelections The selections. Must not be null, but may contain null elements. */ /**
* @param trackSelections The selections. Must not be null, but may contain null elements.
*/
public TrackSelectionArray(@NullableType TrackSelection... trackSelections) { public TrackSelectionArray(@NullableType TrackSelection... trackSelections) {
this.trackSelections = trackSelections; this.trackSelections = trackSelections;
this.length = trackSelections.length; this.length = trackSelections.length;
......
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.media3.common;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static java.util.Collections.max;
import static java.util.Collections.min;
import android.os.Bundle;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.media3.common.util.UnstableApi;
import com.google.common.collect.ImmutableList;
import com.google.common.primitives.Ints;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
/**
* Forces the selection of {@link #trackIndices} for a {@link TrackGroup}.
*
* <p>If multiple tracks in {@link #trackGroup} are overridden, as many as possible will be selected
* depending on the player capabilities.
*
* <p>If {@link #trackIndices} is empty, no tracks from {@link #trackGroup} will be played. This is
* similar to {@link TrackSelectionParameters#disabledTrackTypes}, except it will only affect the
* playback of the associated {@link TrackGroup}. For example, if the only {@link
* C#TRACK_TYPE_VIDEO} {@link TrackGroup} is associated with no tracks, no video will play until the
* next video starts.
*/
public final class TrackSelectionOverride implements Bundleable {
/** The {@link TrackGroup} whose {@link #trackIndices} are forced to be selected. */
public final TrackGroup trackGroup;
/** The indices of tracks in a {@link TrackGroup} to be selected. */
public final ImmutableList<Integer> trackIndices;
@Documented
@Retention(RetentionPolicy.SOURCE)
@IntDef({
FIELD_TRACK_GROUP,
FIELD_TRACKS,
})
private @interface FieldNumber {}
private static final int FIELD_TRACK_GROUP = 0;
private static final int FIELD_TRACKS = 1;
/** Constructs an instance to force all tracks in {@code trackGroup} to be selected. */
public TrackSelectionOverride(TrackGroup trackGroup) {
this.trackGroup = trackGroup;
ImmutableList.Builder<Integer> builder = new ImmutableList.Builder<>();
for (int i = 0; i < trackGroup.length; i++) {
builder.add(i);
}
this.trackIndices = builder.build();
}
/**
* Constructs an instance to force {@code trackIndices} in {@code trackGroup} to be selected.
*
* @param trackGroup The {@link TrackGroup} for which to override the track selection.
* @param trackIndices The indices of the tracks in the {@link TrackGroup} to select.
*/
public TrackSelectionOverride(TrackGroup trackGroup, List<Integer> trackIndices) {
if (!trackIndices.isEmpty()) {
if (min(trackIndices) < 0 || max(trackIndices) >= trackGroup.length) {
throw new IndexOutOfBoundsException();
}
}
this.trackGroup = trackGroup;
this.trackIndices = ImmutableList.copyOf(trackIndices);
}
/** Returns the {@link C.TrackType} of the overridden track group. */
public @C.TrackType int getTrackType() {
return trackGroup.type;
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
TrackSelectionOverride that = (TrackSelectionOverride) obj;
return trackGroup.equals(that.trackGroup) && trackIndices.equals(that.trackIndices);
}
@Override
public int hashCode() {
return trackGroup.hashCode() + 31 * trackIndices.hashCode();
}
// Bundleable implementation
@UnstableApi
@Override
public Bundle toBundle() {
Bundle bundle = new Bundle();
bundle.putBundle(keyForField(FIELD_TRACK_GROUP), trackGroup.toBundle());
bundle.putIntArray(keyForField(FIELD_TRACKS), Ints.toArray(trackIndices));
return bundle;
}
/** Object that can restore {@code TrackSelectionOverride} from a {@link Bundle}. */
@UnstableApi
public static final Creator<TrackSelectionOverride> CREATOR =
bundle -> {
@Nullable Bundle trackGroupBundle = bundle.getBundle(keyForField(FIELD_TRACK_GROUP));
checkNotNull(trackGroupBundle); // Mandatory as there are no reasonable defaults.
TrackGroup trackGroup = TrackGroup.CREATOR.fromBundle(trackGroupBundle);
@Nullable int[] tracks = bundle.getIntArray(keyForField(FIELD_TRACKS));
if (tracks == null) {
return new TrackSelectionOverride(trackGroup);
}
return new TrackSelectionOverride(trackGroup, Ints.asList(tracks));
};
private static String keyForField(@FieldNumber int field) {
return Integer.toString(field, Character.MAX_RADIX);
}
}
...@@ -16,7 +16,8 @@ ...@@ -16,7 +16,8 @@
package androidx.media3.common; package androidx.media3.common;
import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.BundleableUtil.fromNullableBundle; import static androidx.media3.common.util.BundleableUtil.fromBundleNullableList;
import static androidx.media3.common.util.BundleableUtil.toBundleArrayList;
import static com.google.common.base.MoreObjects.firstNonNull; import static com.google.common.base.MoreObjects.firstNonNull;
import android.content.Context; import android.content.Context;
...@@ -30,11 +31,15 @@ import androidx.annotation.RequiresApi; ...@@ -30,11 +31,15 @@ import androidx.annotation.RequiresApi;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.Ints; import com.google.common.primitives.Ints;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
import org.checkerframework.checker.initialization.qual.UnknownInitialization; import org.checkerframework.checker.initialization.qual.UnknownInitialization;
...@@ -93,7 +98,7 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -93,7 +98,7 @@ public class TrackSelectionParameters implements Bundleable {
// General // General
private boolean forceLowestBitrate; private boolean forceLowestBitrate;
private boolean forceHighestSupportedBitrate; private boolean forceHighestSupportedBitrate;
private TrackSelectionOverrides trackSelectionOverrides; private HashMap<TrackGroup, TrackSelectionOverride> overrides;
private ImmutableSet<@C.TrackType Integer> disabledTrackTypes; private ImmutableSet<@C.TrackType Integer> disabledTrackTypes;
/** /**
...@@ -126,7 +131,7 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -126,7 +131,7 @@ public class TrackSelectionParameters implements Bundleable {
// General // General
forceLowestBitrate = false; forceLowestBitrate = false;
forceHighestSupportedBitrate = false; forceHighestSupportedBitrate = false;
trackSelectionOverrides = TrackSelectionOverrides.EMPTY; overrides = new HashMap<>();
disabledTrackTypes = ImmutableSet.of(); disabledTrackTypes = ImmutableSet.of();
} }
...@@ -234,11 +239,16 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -234,11 +239,16 @@ public class TrackSelectionParameters implements Bundleable {
bundle.getBoolean( bundle.getBoolean(
keyForField(FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE), keyForField(FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE),
DEFAULT_WITHOUT_CONTEXT.forceHighestSupportedBitrate); DEFAULT_WITHOUT_CONTEXT.forceHighestSupportedBitrate);
trackSelectionOverrides = overrides = new HashMap<>();
fromNullableBundle( List<TrackSelectionOverride> overrideList =
TrackSelectionOverrides.CREATOR, fromBundleNullableList(
bundle.getBundle(keyForField(FIELD_SELECTION_OVERRIDE_KEYS)), TrackSelectionOverride.CREATOR,
TrackSelectionOverrides.EMPTY); bundle.getParcelableArrayList(keyForField(FIELD_SELECTION_OVERRIDES)),
ImmutableList.of());
for (int i = 0; i < overrideList.size(); i++) {
TrackSelectionOverride override = overrideList.get(i);
overrides.put(override.trackGroup, override);
}
disabledTrackTypes = disabledTrackTypes =
ImmutableSet.copyOf( ImmutableSet.copyOf(
Ints.asList( Ints.asList(
...@@ -252,7 +262,7 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -252,7 +262,7 @@ public class TrackSelectionParameters implements Bundleable {
"preferredAudioLanguages", "preferredAudioLanguages",
"preferredAudioMimeTypes", "preferredAudioMimeTypes",
"preferredTextLanguages", "preferredTextLanguages",
"trackSelectionOverrides", "overrides",
"disabledTrackTypes", "disabledTrackTypes",
}) })
private void init(@UnknownInitialization Builder this, TrackSelectionParameters parameters) { private void init(@UnknownInitialization Builder this, TrackSelectionParameters parameters) {
...@@ -283,8 +293,8 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -283,8 +293,8 @@ public class TrackSelectionParameters implements Bundleable {
// General // General
forceLowestBitrate = parameters.forceLowestBitrate; forceLowestBitrate = parameters.forceLowestBitrate;
forceHighestSupportedBitrate = parameters.forceHighestSupportedBitrate; forceHighestSupportedBitrate = parameters.forceHighestSupportedBitrate;
trackSelectionOverrides = parameters.trackSelectionOverrides;
disabledTrackTypes = parameters.disabledTrackTypes; disabledTrackTypes = parameters.disabledTrackTypes;
overrides = new HashMap<>(parameters.overrides);
} }
/** Overrides the value of the builder with the value of {@link TrackSelectionParameters}. */ /** Overrides the value of the builder with the value of {@link TrackSelectionParameters}. */
...@@ -644,14 +654,42 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -644,14 +654,42 @@ public class TrackSelectionParameters implements Bundleable {
return this; return this;
} }
/** Adds an override for the provided {@link TrackGroup}. */
public Builder addOverride(TrackSelectionOverride override) {
overrides.put(override.trackGroup, override);
return this;
}
/** Removes the override associated with the provided {@link TrackGroup} if present. */
public Builder clearOverride(TrackGroup trackGroup) {
overrides.remove(trackGroup);
return this;
}
/** Set the override for the type of the provided {@link TrackGroup}. */
public Builder setOverrideForType(TrackSelectionOverride override) {
clearOverridesOfType(override.getTrackType());
overrides.put(override.trackGroup, override);
return this;
}
/** /**
* Sets the selection overrides. * Remove any override associated with {@link TrackGroup TrackGroups} of type {@code trackType}.
*
* @param trackSelectionOverrides The track selection overrides.
* @return This builder.
*/ */
public Builder setTrackSelectionOverrides(TrackSelectionOverrides trackSelectionOverrides) { public Builder clearOverridesOfType(@C.TrackType int trackType) {
this.trackSelectionOverrides = trackSelectionOverrides; Iterator<TrackSelectionOverride> it = overrides.values().iterator();
while (it.hasNext()) {
TrackSelectionOverride override = it.next();
if (override.getTrackType() == trackType) {
it.remove();
}
}
return this;
}
/** Removes all track overrides. */
public Builder clearOverrides() {
overrides.clear();
return this; return this;
} }
...@@ -858,8 +896,9 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -858,8 +896,9 @@ public class TrackSelectionParameters implements Bundleable {
*/ */
public final boolean forceHighestSupportedBitrate; public final boolean forceHighestSupportedBitrate;
/** Overrides to force tracks to be selected. */ /** Overrides to force selection of specific tracks. */
public final TrackSelectionOverrides trackSelectionOverrides; public final ImmutableMap<TrackGroup, TrackSelectionOverride> overrides;
/** /**
* The track types that are disabled. No track of a disabled type will be selected, thus no track * The track types that are disabled. No track of a disabled type will be selected, thus no track
* type contained in the set will be played. The default value is that no track type is disabled * type contained in the set will be played. The default value is that no track type is disabled
...@@ -896,7 +935,7 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -896,7 +935,7 @@ public class TrackSelectionParameters implements Bundleable {
// General // General
this.forceLowestBitrate = builder.forceLowestBitrate; this.forceLowestBitrate = builder.forceLowestBitrate;
this.forceHighestSupportedBitrate = builder.forceHighestSupportedBitrate; this.forceHighestSupportedBitrate = builder.forceHighestSupportedBitrate;
this.trackSelectionOverrides = builder.trackSelectionOverrides; this.overrides = ImmutableMap.copyOf(builder.overrides);
this.disabledTrackTypes = builder.disabledTrackTypes; this.disabledTrackTypes = builder.disabledTrackTypes;
} }
...@@ -941,7 +980,7 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -941,7 +980,7 @@ public class TrackSelectionParameters implements Bundleable {
// General // General
&& forceLowestBitrate == other.forceLowestBitrate && forceLowestBitrate == other.forceLowestBitrate
&& forceHighestSupportedBitrate == other.forceHighestSupportedBitrate && forceHighestSupportedBitrate == other.forceHighestSupportedBitrate
&& trackSelectionOverrides.equals(other.trackSelectionOverrides) && overrides.equals(other.overrides)
&& disabledTrackTypes.equals(other.disabledTrackTypes); && disabledTrackTypes.equals(other.disabledTrackTypes);
} }
...@@ -975,7 +1014,7 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -975,7 +1014,7 @@ public class TrackSelectionParameters implements Bundleable {
// General // General
result = 31 * result + (forceLowestBitrate ? 1 : 0); result = 31 * result + (forceLowestBitrate ? 1 : 0);
result = 31 * result + (forceHighestSupportedBitrate ? 1 : 0); result = 31 * result + (forceHighestSupportedBitrate ? 1 : 0);
result = 31 * result + trackSelectionOverrides.hashCode(); result = 31 * result + overrides.hashCode();
result = 31 * result + disabledTrackTypes.hashCode(); result = 31 * result + disabledTrackTypes.hashCode();
return result; return result;
} }
...@@ -1007,8 +1046,7 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -1007,8 +1046,7 @@ public class TrackSelectionParameters implements Bundleable {
FIELD_PREFERRED_AUDIO_MIME_TYPES, FIELD_PREFERRED_AUDIO_MIME_TYPES,
FIELD_FORCE_LOWEST_BITRATE, FIELD_FORCE_LOWEST_BITRATE,
FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE, FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE,
FIELD_SELECTION_OVERRIDE_KEYS, FIELD_SELECTION_OVERRIDES,
FIELD_SELECTION_OVERRIDE_VALUES,
FIELD_DISABLED_TRACK_TYPE, FIELD_DISABLED_TRACK_TYPE,
FIELD_PREFERRED_VIDEO_ROLE_FLAGS FIELD_PREFERRED_VIDEO_ROLE_FLAGS
}) })
...@@ -1036,10 +1074,9 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -1036,10 +1074,9 @@ public class TrackSelectionParameters implements Bundleable {
private static final int FIELD_PREFERRED_AUDIO_MIME_TYPES = 20; private static final int FIELD_PREFERRED_AUDIO_MIME_TYPES = 20;
private static final int FIELD_FORCE_LOWEST_BITRATE = 21; private static final int FIELD_FORCE_LOWEST_BITRATE = 21;
private static final int FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE = 22; private static final int FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE = 22;
private static final int FIELD_SELECTION_OVERRIDE_KEYS = 23; private static final int FIELD_SELECTION_OVERRIDES = 23;
private static final int FIELD_SELECTION_OVERRIDE_VALUES = 24; private static final int FIELD_DISABLED_TRACK_TYPE = 24;
private static final int FIELD_DISABLED_TRACK_TYPE = 25; private static final int FIELD_PREFERRED_VIDEO_ROLE_FLAGS = 25;
private static final int FIELD_PREFERRED_VIDEO_ROLE_FLAGS = 26;
@UnstableApi @UnstableApi
@Override @Override
...@@ -1083,8 +1120,8 @@ public class TrackSelectionParameters implements Bundleable { ...@@ -1083,8 +1120,8 @@ public class TrackSelectionParameters implements Bundleable {
bundle.putBoolean(keyForField(FIELD_FORCE_LOWEST_BITRATE), forceLowestBitrate); bundle.putBoolean(keyForField(FIELD_FORCE_LOWEST_BITRATE), forceLowestBitrate);
bundle.putBoolean( bundle.putBoolean(
keyForField(FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE), forceHighestSupportedBitrate); keyForField(FIELD_FORCE_HIGHEST_SUPPORTED_BITRATE), forceHighestSupportedBitrate);
bundle.putBundle( bundle.putParcelableArrayList(
keyForField(FIELD_SELECTION_OVERRIDE_KEYS), trackSelectionOverrides.toBundle()); keyForField(FIELD_SELECTION_OVERRIDES), toBundleArrayList(overrides.values()));
bundle.putIntArray(keyForField(FIELD_DISABLED_TRACK_TYPE), Ints.toArray(disabledTrackTypes)); bundle.putIntArray(keyForField(FIELD_DISABLED_TRACK_TYPE), Ints.toArray(disabledTrackTypes));
return bundle; return bundle;
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
*/ */
package androidx.media3.common; package androidx.media3.common;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.FloatRange; import androidx.annotation.FloatRange;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
...@@ -24,6 +26,7 @@ import androidx.media3.common.util.UnstableApi; ...@@ -24,6 +26,7 @@ import androidx.media3.common.util.UnstableApi;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** Represents the video size. */ /** Represents the video size. */
public final class VideoSize implements Bundleable { public final class VideoSize implements Bundleable {
...@@ -131,6 +134,7 @@ public final class VideoSize implements Bundleable { ...@@ -131,6 +134,7 @@ public final class VideoSize implements Bundleable {
// Bundleable implementation. // Bundleable implementation.
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({ @IntDef({
FIELD_WIDTH, FIELD_WIDTH,
FIELD_HEIGHT, FIELD_HEIGHT,
......
...@@ -59,6 +59,8 @@ public final class Cue implements Bundleable { ...@@ -59,6 +59,8 @@ public final class Cue implements Bundleable {
* The type of anchor, which may be unset. One of {@link #TYPE_UNSET}, {@link #ANCHOR_TYPE_START}, * The type of anchor, which may be unset. One of {@link #TYPE_UNSET}, {@link #ANCHOR_TYPE_START},
* {@link #ANCHOR_TYPE_MIDDLE} or {@link #ANCHOR_TYPE_END}. * {@link #ANCHOR_TYPE_MIDDLE} or {@link #ANCHOR_TYPE_END}.
*/ */
// @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility
// with Kotlin usages from before TYPE_USE was added.
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE}) @Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE})
...@@ -87,6 +89,8 @@ public final class Cue implements Bundleable { ...@@ -87,6 +89,8 @@ public final class Cue implements Bundleable {
* The type of line, which may be unset. One of {@link #TYPE_UNSET}, {@link #LINE_TYPE_FRACTION} * The type of line, which may be unset. One of {@link #TYPE_UNSET}, {@link #LINE_TYPE_FRACTION}
* or {@link #LINE_TYPE_NUMBER}. * or {@link #LINE_TYPE_NUMBER}.
*/ */
// @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility
// with Kotlin usages from before TYPE_USE was added.
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE}) @Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE})
...@@ -104,6 +108,8 @@ public final class Cue implements Bundleable { ...@@ -104,6 +108,8 @@ public final class Cue implements Bundleable {
* {@link #TEXT_SIZE_TYPE_FRACTIONAL}, {@link #TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING} or {@link * {@link #TEXT_SIZE_TYPE_FRACTIONAL}, {@link #TEXT_SIZE_TYPE_FRACTIONAL_IGNORE_PADDING} or {@link
* #TEXT_SIZE_TYPE_ABSOLUTE}. * #TEXT_SIZE_TYPE_ABSOLUTE}.
*/ */
// @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility
// with Kotlin usages from before TYPE_USE was added.
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE}) @Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE})
...@@ -128,6 +134,8 @@ public final class Cue implements Bundleable { ...@@ -128,6 +134,8 @@ public final class Cue implements Bundleable {
* The type of vertical layout for this cue, which may be unset (i.e. horizontal). One of {@link * The type of vertical layout for this cue, which may be unset (i.e. horizontal). One of {@link
* #TYPE_UNSET}, {@link #VERTICAL_TYPE_RL} or {@link #VERTICAL_TYPE_LR}. * #TYPE_UNSET}, {@link #VERTICAL_TYPE_RL} or {@link #VERTICAL_TYPE_LR}.
*/ */
// @Target list includes both 'default' targets and TYPE_USE, to ensure backwards compatibility
// with Kotlin usages from before TYPE_USE was added.
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE}) @Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE})
...@@ -561,7 +569,7 @@ public final class Cue implements Bundleable { ...@@ -561,7 +569,7 @@ public final class Cue implements Bundleable {
@Nullable private Alignment textAlignment; @Nullable private Alignment textAlignment;
@Nullable private Alignment multiRowAlignment; @Nullable private Alignment multiRowAlignment;
private float line; private float line;
@LineType private int lineType; private @LineType int lineType;
private @AnchorType int lineAnchor; private @AnchorType int lineAnchor;
private float position; private float position;
private @AnchorType int positionAnchor; private @AnchorType int positionAnchor;
...@@ -722,8 +730,7 @@ public final class Cue implements Bundleable { ...@@ -722,8 +730,7 @@ public final class Cue implements Bundleable {
* @see Cue#lineType * @see Cue#lineType
*/ */
@Pure @Pure
@LineType public @LineType int getLineType() {
public int getLineType() {
return lineType; return lineType;
} }
...@@ -743,8 +750,7 @@ public final class Cue implements Bundleable { ...@@ -743,8 +750,7 @@ public final class Cue implements Bundleable {
* @see Cue#lineAnchor * @see Cue#lineAnchor
*/ */
@Pure @Pure
@AnchorType public @AnchorType int getLineAnchor() {
public int getLineAnchor() {
return lineAnchor; return lineAnchor;
} }
...@@ -786,8 +792,7 @@ public final class Cue implements Bundleable { ...@@ -786,8 +792,7 @@ public final class Cue implements Bundleable {
* @see Cue#positionAnchor * @see Cue#positionAnchor
*/ */
@Pure @Pure
@AnchorType public @AnchorType int getPositionAnchor() {
public int getPositionAnchor() {
return positionAnchor; return positionAnchor;
} }
...@@ -809,8 +814,7 @@ public final class Cue implements Bundleable { ...@@ -809,8 +814,7 @@ public final class Cue implements Bundleable {
* @see Cue#textSizeType * @see Cue#textSizeType
*/ */
@Pure @Pure
@TextSizeType public @TextSizeType int getTextSizeType() {
public int getTextSizeType() {
return textSizeType; return textSizeType;
} }
...@@ -928,8 +932,7 @@ public final class Cue implements Bundleable { ...@@ -928,8 +932,7 @@ public final class Cue implements Bundleable {
* @see Cue#verticalType * @see Cue#verticalType
*/ */
@Pure @Pure
@VerticalType public @VerticalType int getVerticalType() {
public int getVerticalType() {
return verticalType; return verticalType;
} }
...@@ -960,6 +963,7 @@ public final class Cue implements Bundleable { ...@@ -960,6 +963,7 @@ public final class Cue implements Bundleable {
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({ @IntDef({
FIELD_TEXT, FIELD_TEXT,
FIELD_TEXT_ALIGNMENT, FIELD_TEXT_ALIGNMENT,
......
...@@ -39,7 +39,7 @@ public final class RubySpan implements LanguageFeatureSpan { ...@@ -39,7 +39,7 @@ public final class RubySpan implements LanguageFeatureSpan {
public final String rubyText; public final String rubyText;
/** The position of the ruby text relative to the base text. */ /** The position of the ruby text relative to the base text. */
@TextAnnotation.Position public final int position; public final @TextAnnotation.Position int position;
public RubySpan(String rubyText, @TextAnnotation.Position int position) { public RubySpan(String rubyText, @TextAnnotation.Position int position) {
this.rubyText = rubyText; this.rubyText = rubyText;
......
...@@ -15,12 +15,14 @@ ...@@ -15,12 +15,14 @@
*/ */
package androidx.media3.common.text; package androidx.media3.common.text;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.SOURCE; import static java.lang.annotation.RetentionPolicy.SOURCE;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/** Properties of a text annotation (i.e. ruby, text emphasis marks). */ /** Properties of a text annotation (i.e. ruby, text emphasis marks). */
@UnstableApi @UnstableApi
...@@ -57,6 +59,7 @@ public final class TextAnnotation { ...@@ -57,6 +59,7 @@ public final class TextAnnotation {
*/ */
@Documented @Documented
@Retention(SOURCE) @Retention(SOURCE)
@Target(TYPE_USE)
@IntDef({POSITION_UNKNOWN, POSITION_BEFORE, POSITION_AFTER}) @IntDef({POSITION_UNKNOWN, POSITION_BEFORE, POSITION_AFTER})
public @interface Position {} public @interface Position {}
......
...@@ -15,12 +15,14 @@ ...@@ -15,12 +15,14 @@
*/ */
package androidx.media3.common.text; package androidx.media3.common.text;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.SOURCE; import static java.lang.annotation.RetentionPolicy.SOURCE;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/** /**
* A styling span for text emphasis marks. * A styling span for text emphasis marks.
...@@ -50,6 +52,7 @@ public final class TextEmphasisSpan implements LanguageFeatureSpan { ...@@ -50,6 +52,7 @@ public final class TextEmphasisSpan implements LanguageFeatureSpan {
*/ */
@Documented @Documented
@Retention(SOURCE) @Retention(SOURCE)
@Target(TYPE_USE)
@IntDef({MARK_SHAPE_NONE, MARK_SHAPE_CIRCLE, MARK_SHAPE_DOT, MARK_SHAPE_SESAME}) @IntDef({MARK_SHAPE_NONE, MARK_SHAPE_CIRCLE, MARK_SHAPE_DOT, MARK_SHAPE_SESAME})
public @interface MarkShape {} public @interface MarkShape {}
...@@ -71,6 +74,7 @@ public final class TextEmphasisSpan implements LanguageFeatureSpan { ...@@ -71,6 +74,7 @@ public final class TextEmphasisSpan implements LanguageFeatureSpan {
*/ */
@Documented @Documented
@Retention(SOURCE) @Retention(SOURCE)
@Target(TYPE_USE)
@IntDef({MARK_FILL_UNKNOWN, MARK_FILL_FILLED, MARK_FILL_OPEN}) @IntDef({MARK_FILL_UNKNOWN, MARK_FILL_FILLED, MARK_FILL_OPEN})
public @interface MarkFill {} public @interface MarkFill {}
...@@ -79,13 +83,13 @@ public final class TextEmphasisSpan implements LanguageFeatureSpan { ...@@ -79,13 +83,13 @@ public final class TextEmphasisSpan implements LanguageFeatureSpan {
public static final int MARK_FILL_OPEN = 2; public static final int MARK_FILL_OPEN = 2;
/** The mark shape used for text emphasis. */ /** The mark shape used for text emphasis. */
@MarkShape public int markShape; public @MarkShape int markShape;
/** The mark fill for the text emphasis mark. */ /** The mark fill for the text emphasis mark. */
@MarkShape public int markFill; public @MarkShape int markFill;
/** The position of the text emphasis relative to the base text. */ /** The position of the text emphasis relative to the base text. */
@TextAnnotation.Position public final int position; public final @TextAnnotation.Position int position;
public TextEmphasisSpan( public TextEmphasisSpan(
@MarkShape int shape, @MarkFill int fill, @TextAnnotation.Position int position) { @MarkShape int shape, @MarkFill int fill, @TextAnnotation.Position int position) {
......
...@@ -36,10 +36,14 @@ public interface Clock { ...@@ -36,10 +36,14 @@ public interface Clock {
*/ */
long currentTimeMillis(); long currentTimeMillis();
/** @see android.os.SystemClock#elapsedRealtime() */ /**
* @see android.os.SystemClock#elapsedRealtime()
*/
long elapsedRealtime(); long elapsedRealtime();
/** @see android.os.SystemClock#uptimeMillis() */ /**
* @see android.os.SystemClock#uptimeMillis()
*/
long uptimeMillis(); long uptimeMillis();
/** /**
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
*/ */
package androidx.media3.common.util; package androidx.media3.common.util;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.graphics.SurfaceTexture; import android.graphics.SurfaceTexture;
import android.opengl.EGL14; import android.opengl.EGL14;
import android.opengl.EGLConfig; import android.opengl.EGLConfig;
...@@ -29,6 +31,7 @@ import androidx.annotation.RequiresApi; ...@@ -29,6 +31,7 @@ import androidx.annotation.RequiresApi;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** Generates a {@link SurfaceTexture} using EGL/GLES functions. */ /** Generates a {@link SurfaceTexture} using EGL/GLES functions. */
@RequiresApi(17) @RequiresApi(17)
...@@ -47,6 +50,7 @@ public final class EGLSurfaceTexture implements SurfaceTexture.OnFrameAvailableL ...@@ -47,6 +50,7 @@ public final class EGLSurfaceTexture implements SurfaceTexture.OnFrameAvailableL
*/ */
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({SECURE_MODE_NONE, SECURE_MODE_SURFACELESS_CONTEXT, SECURE_MODE_PROTECTED_PBUFFER}) @IntDef({SECURE_MODE_NONE, SECURE_MODE_SURFACELESS_CONTEXT, SECURE_MODE_PROTECTED_PBUFFER})
public @interface SecureMode {} public @interface SecureMode {}
......
...@@ -19,7 +19,7 @@ import java.util.Arrays; ...@@ -19,7 +19,7 @@ import java.util.Arrays;
/** Configurable loader for native libraries. */ /** Configurable loader for native libraries. */
@UnstableApi @UnstableApi
public final class LibraryLoader { public abstract class LibraryLoader {
private static final String TAG = "LibraryLoader"; private static final String TAG = "LibraryLoader";
...@@ -27,7 +27,9 @@ public final class LibraryLoader { ...@@ -27,7 +27,9 @@ public final class LibraryLoader {
private boolean loadAttempted; private boolean loadAttempted;
private boolean isAvailable; private boolean isAvailable;
/** @param libraries The names of the libraries to load. */ /**
* @param libraries The names of the libraries to load.
*/
public LibraryLoader(String... libraries) { public LibraryLoader(String... libraries) {
nativeLibraries = libraries; nativeLibraries = libraries;
} }
...@@ -49,7 +51,7 @@ public final class LibraryLoader { ...@@ -49,7 +51,7 @@ public final class LibraryLoader {
loadAttempted = true; loadAttempted = true;
try { try {
for (String lib : nativeLibraries) { for (String lib : nativeLibraries) {
System.loadLibrary(lib); loadLibrary(lib);
} }
isAvailable = true; isAvailable = true;
} catch (UnsatisfiedLinkError exception) { } catch (UnsatisfiedLinkError exception) {
...@@ -59,4 +61,17 @@ public final class LibraryLoader { ...@@ -59,4 +61,17 @@ public final class LibraryLoader {
} }
return isAvailable; return isAvailable;
} }
/**
* Should be implemented to call {@code System.loadLibrary(name)}.
*
* <p>It's necessary for each subclass to implement this method because {@link
* System#loadLibrary(String)} uses reflection to obtain the calling class, which is then used to
* obtain the class loader to use when loading the native library. If this class were to implement
* the method directly, and if a subclass were to have a different class loader, then loading of
* the native library would fail.
*
* @param name The name of the library to load.
*/
protected abstract void loadLibrary(String name);
} }
...@@ -118,6 +118,21 @@ public final class ListenerSet<T extends @NonNull Object> { ...@@ -118,6 +118,21 @@ public final class ListenerSet<T extends @NonNull Object> {
*/ */
@CheckResult @CheckResult
public ListenerSet<T> copy(Looper looper, IterationFinishedEvent<T> iterationFinishedEvent) { public ListenerSet<T> copy(Looper looper, IterationFinishedEvent<T> iterationFinishedEvent) {
return copy(looper, clock, iterationFinishedEvent);
}
/**
* Copies the listener set.
*
* @param looper The new {@link Looper} for the copied listener set.
* @param clock The new {@link Clock} for the copied listener set.
* @param iterationFinishedEvent The new {@link IterationFinishedEvent} sent when all other events
* sent during one {@link Looper} message queue iteration were handled by the listeners.
* @return The copied listener set.
*/
@CheckResult
public ListenerSet<T> copy(
Looper looper, Clock clock, IterationFinishedEvent<T> iterationFinishedEvent) {
return new ListenerSet<>(listeners, looper, clock, iterationFinishedEvent); return new ListenerSet<>(listeners, looper, clock, iterationFinishedEvent);
} }
...@@ -152,6 +167,11 @@ public final class ListenerSet<T extends @NonNull Object> { ...@@ -152,6 +167,11 @@ public final class ListenerSet<T extends @NonNull Object> {
} }
} }
/** Removes all listeners from the set. */
public void clear() {
listeners.clear();
}
/** Returns the number of added listeners. */ /** Returns the number of added listeners. */
public int size() { public int size() {
return listeners.size(); return listeners.size();
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
*/ */
package androidx.media3.common.util; package androidx.media3.common.util;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
...@@ -22,6 +24,7 @@ import androidx.annotation.Size; ...@@ -22,6 +24,7 @@ import androidx.annotation.Size;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import org.checkerframework.dataflow.qual.Pure; import org.checkerframework.dataflow.qual.Pure;
...@@ -35,8 +38,9 @@ public final class Log { ...@@ -35,8 +38,9 @@ public final class Log {
*/ */
@Documented @Documented
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef({LOG_LEVEL_ALL, LOG_LEVEL_INFO, LOG_LEVEL_WARNING, LOG_LEVEL_ERROR, LOG_LEVEL_OFF}) @IntDef({LOG_LEVEL_ALL, LOG_LEVEL_INFO, LOG_LEVEL_WARNING, LOG_LEVEL_ERROR, LOG_LEVEL_OFF})
@interface LogLevel {} public @interface LogLevel {}
/** Log level to log all messages. */ /** Log level to log all messages. */
public static final int LOG_LEVEL_ALL = 0; public static final int LOG_LEVEL_ALL = 0;
/** Log level to only log informative, warning and error messages. */ /** Log level to only log informative, warning and error messages. */
...@@ -78,7 +82,9 @@ public final class Log { ...@@ -78,7 +82,9 @@ public final class Log {
Log.logStackTraces = logStackTraces; Log.logStackTraces = logStackTraces;
} }
/** @see android.util.Log#d(String, String) */ /**
* @see android.util.Log#d(String, String)
*/
@Pure @Pure
public static void d(@Size(max = 23) String tag, String message) { public static void d(@Size(max = 23) String tag, String message) {
if (logLevel == LOG_LEVEL_ALL) { if (logLevel == LOG_LEVEL_ALL) {
...@@ -86,13 +92,17 @@ public final class Log { ...@@ -86,13 +92,17 @@ public final class Log {
} }
} }
/** @see android.util.Log#d(String, String, Throwable) */ /**
* @see android.util.Log#d(String, String, Throwable)
*/
@Pure @Pure
public static void d(@Size(max = 23) String tag, String message, @Nullable Throwable throwable) { public static void d(@Size(max = 23) String tag, String message, @Nullable Throwable throwable) {
d(tag, appendThrowableString(message, throwable)); d(tag, appendThrowableString(message, throwable));
} }
/** @see android.util.Log#i(String, String) */ /**
* @see android.util.Log#i(String, String)
*/
@Pure @Pure
public static void i(@Size(max = 23) String tag, String message) { public static void i(@Size(max = 23) String tag, String message) {
if (logLevel <= LOG_LEVEL_INFO) { if (logLevel <= LOG_LEVEL_INFO) {
...@@ -100,13 +110,17 @@ public final class Log { ...@@ -100,13 +110,17 @@ public final class Log {
} }
} }
/** @see android.util.Log#i(String, String, Throwable) */ /**
* @see android.util.Log#i(String, String, Throwable)
*/
@Pure @Pure
public static void i(@Size(max = 23) String tag, String message, @Nullable Throwable throwable) { public static void i(@Size(max = 23) String tag, String message, @Nullable Throwable throwable) {
i(tag, appendThrowableString(message, throwable)); i(tag, appendThrowableString(message, throwable));
} }
/** @see android.util.Log#w(String, String) */ /**
* @see android.util.Log#w(String, String)
*/
@Pure @Pure
public static void w(@Size(max = 23) String tag, String message) { public static void w(@Size(max = 23) String tag, String message) {
if (logLevel <= LOG_LEVEL_WARNING) { if (logLevel <= LOG_LEVEL_WARNING) {
...@@ -114,13 +128,17 @@ public final class Log { ...@@ -114,13 +128,17 @@ public final class Log {
} }
} }
/** @see android.util.Log#w(String, String, Throwable) */ /**
* @see android.util.Log#w(String, String, Throwable)
*/
@Pure @Pure
public static void w(@Size(max = 23) String tag, String message, @Nullable Throwable throwable) { public static void w(@Size(max = 23) String tag, String message, @Nullable Throwable throwable) {
w(tag, appendThrowableString(message, throwable)); w(tag, appendThrowableString(message, throwable));
} }
/** @see android.util.Log#e(String, String) */ /**
* @see android.util.Log#e(String, String)
*/
@Pure @Pure
public static void e(@Size(max = 23) String tag, String message) { public static void e(@Size(max = 23) String tag, String message) {
if (logLevel <= LOG_LEVEL_ERROR) { if (logLevel <= LOG_LEVEL_ERROR) {
...@@ -128,7 +146,9 @@ public final class Log { ...@@ -128,7 +146,9 @@ public final class Log {
} }
} }
/** @see android.util.Log#e(String, String, Throwable) */ /**
* @see android.util.Log#e(String, String, Throwable)
*/
@Pure @Pure
public static void e(@Size(max = 23) String tag, String message, @Nullable Throwable throwable) { public static void e(@Size(max = 23) String tag, String message, @Nullable Throwable throwable) {
e(tag, appendThrowableString(message, throwable)); e(tag, appendThrowableString(message, throwable));
......
...@@ -30,7 +30,9 @@ public final class LongArray { ...@@ -30,7 +30,9 @@ public final class LongArray {
this(DEFAULT_INITIAL_CAPACITY); this(DEFAULT_INITIAL_CAPACITY);
} }
/** @param initialCapacity The initial capacity of the array. */ /**
* @param initialCapacity The initial capacity of the array.
*/
public LongArray(int initialCapacity) { public LongArray(int initialCapacity) {
values = new long[initialCapacity]; values = new long[initialCapacity];
} }
......
...@@ -221,6 +221,17 @@ public final class MediaFormatUtil { ...@@ -221,6 +221,17 @@ public final class MediaFormatUtil {
case C.ENCODING_PCM_FLOAT: case C.ENCODING_PCM_FLOAT:
mediaFormatPcmEncoding = AudioFormat.ENCODING_PCM_FLOAT; mediaFormatPcmEncoding = AudioFormat.ENCODING_PCM_FLOAT;
break; break;
case C.ENCODING_PCM_24BIT:
mediaFormatPcmEncoding = AudioFormat.ENCODING_PCM_24BIT_PACKED;
break;
case C.ENCODING_PCM_32BIT:
mediaFormatPcmEncoding = AudioFormat.ENCODING_PCM_32BIT;
break;
case C.ENCODING_INVALID:
mediaFormatPcmEncoding = AudioFormat.ENCODING_INVALID;
break;
case Format.NO_VALUE:
case C.ENCODING_PCM_16BIT_BIG_ENDIAN:
default: default:
// No matching value. Do nothing. // No matching value. Do nothing.
return; return;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment