mirror of
https://github.com/samsonjs/media.git
synced 2026-03-28 09:55:48 +00:00
282 lines
9.9 KiB
Java
282 lines
9.9 KiB
Java
/*
|
|
* Copyright 2017 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 java.lang.annotation.ElementType.TYPE_USE;
|
|
|
|
import android.os.Bundle;
|
|
import androidx.annotation.DoNotInline;
|
|
import androidx.annotation.IntDef;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.annotation.RequiresApi;
|
|
import androidx.media3.common.util.UnstableApi;
|
|
import androidx.media3.common.util.Util;
|
|
import java.lang.annotation.Documented;
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
import java.lang.annotation.Target;
|
|
import java.lang.reflect.Method;
|
|
|
|
/**
|
|
* Attributes for audio playback, which configure the underlying platform {@link
|
|
* android.media.AudioTrack}.
|
|
*
|
|
* <p>To set the audio attributes, create an instance using the {@link Builder} and either pass it
|
|
* to the player or send a message of type {@code Renderer#MSG_SET_AUDIO_ATTRIBUTES} to the audio
|
|
* renderers.
|
|
*
|
|
* <p>This class is based on {@link android.media.AudioAttributes}, but can be used on all supported
|
|
* API versions.
|
|
*/
|
|
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();
|
|
|
|
/** Builder for {@link AudioAttributes}. */
|
|
public static final class Builder {
|
|
|
|
private @C.AudioContentType int contentType;
|
|
private @C.AudioFlags int flags;
|
|
private @C.AudioUsage int usage;
|
|
private @C.AudioAllowedCapturePolicy int allowedCapturePolicy;
|
|
private @C.SpatializationBehavior int spatializationBehavior;
|
|
|
|
/**
|
|
* Creates a new builder for {@link AudioAttributes}.
|
|
*
|
|
* <p>By default 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 Builder() {
|
|
contentType = C.CONTENT_TYPE_UNKNOWN;
|
|
flags = 0;
|
|
usage = C.USAGE_MEDIA;
|
|
allowedCapturePolicy = C.ALLOW_CAPTURE_BY_ALL;
|
|
spatializationBehavior = C.SPATIALIZATION_BEHAVIOR_AUTO;
|
|
}
|
|
|
|
/** See {@link android.media.AudioAttributes.Builder#setContentType(int)} */
|
|
public Builder setContentType(@C.AudioContentType int contentType) {
|
|
this.contentType = contentType;
|
|
return this;
|
|
}
|
|
|
|
/** See {@link android.media.AudioAttributes.Builder#setFlags(int)} */
|
|
public Builder setFlags(@C.AudioFlags int flags) {
|
|
this.flags = flags;
|
|
return this;
|
|
}
|
|
|
|
/** See {@link android.media.AudioAttributes.Builder#setUsage(int)} */
|
|
public Builder setUsage(@C.AudioUsage int usage) {
|
|
this.usage = usage;
|
|
return this;
|
|
}
|
|
|
|
/** See {@link android.media.AudioAttributes.Builder#setAllowedCapturePolicy(int)}. */
|
|
public Builder setAllowedCapturePolicy(@C.AudioAllowedCapturePolicy int allowedCapturePolicy) {
|
|
this.allowedCapturePolicy = allowedCapturePolicy;
|
|
return this;
|
|
}
|
|
|
|
// TODO[b/190759307] Update javadoc to link to AudioAttributes.Builder#setSpatializationBehavior
|
|
// once compile SDK target is set to 32.
|
|
/** See {@code android.media.AudioAttributes.Builder.setSpatializationBehavior(int)}. */
|
|
public Builder setSpatializationBehavior(@C.SpatializationBehavior int spatializationBehavior) {
|
|
this.spatializationBehavior = spatializationBehavior;
|
|
return this;
|
|
}
|
|
|
|
/** Creates an {@link AudioAttributes} instance from this builder. */
|
|
public AudioAttributes build() {
|
|
return new AudioAttributes(
|
|
contentType, flags, usage, allowedCapturePolicy, spatializationBehavior);
|
|
}
|
|
}
|
|
|
|
/** The {@link C.AudioContentType}. */
|
|
public final @C.AudioContentType int contentType;
|
|
/** The {@link C.AudioFlags}. */
|
|
public final @C.AudioFlags int flags;
|
|
/** The {@link C.AudioUsage}. */
|
|
public final @C.AudioUsage int usage;
|
|
/** The {@link C.AudioAllowedCapturePolicy}. */
|
|
public final @C.AudioAllowedCapturePolicy int allowedCapturePolicy;
|
|
/** The {@link C.SpatializationBehavior}. */
|
|
public final @C.SpatializationBehavior int spatializationBehavior;
|
|
|
|
@Nullable private android.media.AudioAttributes audioAttributesV21;
|
|
|
|
private AudioAttributes(
|
|
@C.AudioContentType int contentType,
|
|
@C.AudioFlags int flags,
|
|
@C.AudioUsage int usage,
|
|
@C.AudioAllowedCapturePolicy int allowedCapturePolicy,
|
|
@C.SpatializationBehavior int spatializationBehavior) {
|
|
this.contentType = contentType;
|
|
this.flags = flags;
|
|
this.usage = usage;
|
|
this.allowedCapturePolicy = allowedCapturePolicy;
|
|
this.spatializationBehavior = spatializationBehavior;
|
|
}
|
|
|
|
/**
|
|
* Returns a {@link android.media.AudioAttributes} from this instance.
|
|
*
|
|
* <p>Field {@link AudioAttributes#allowedCapturePolicy} is ignored for API levels prior to 29.
|
|
*/
|
|
@RequiresApi(21)
|
|
public android.media.AudioAttributes getAudioAttributesV21() {
|
|
if (audioAttributesV21 == null) {
|
|
android.media.AudioAttributes.Builder builder =
|
|
new android.media.AudioAttributes.Builder()
|
|
.setContentType(contentType)
|
|
.setFlags(flags)
|
|
.setUsage(usage);
|
|
if (Util.SDK_INT >= 29) {
|
|
Api29.setAllowedCapturePolicy(builder, allowedCapturePolicy);
|
|
}
|
|
if (Util.SDK_INT >= 32) {
|
|
Api32.setSpatializationBehavior(builder, spatializationBehavior);
|
|
}
|
|
audioAttributesV21 = builder.build();
|
|
}
|
|
return audioAttributesV21;
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(@Nullable Object obj) {
|
|
if (this == obj) {
|
|
return true;
|
|
}
|
|
if (obj == null || getClass() != obj.getClass()) {
|
|
return false;
|
|
}
|
|
AudioAttributes other = (AudioAttributes) obj;
|
|
return this.contentType == other.contentType
|
|
&& this.flags == other.flags
|
|
&& this.usage == other.usage
|
|
&& this.allowedCapturePolicy == other.allowedCapturePolicy
|
|
&& this.spatializationBehavior == other.spatializationBehavior;
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
int result = 17;
|
|
result = 31 * result + contentType;
|
|
result = 31 * result + flags;
|
|
result = 31 * result + usage;
|
|
result = 31 * result + allowedCapturePolicy;
|
|
result = 31 * result + spatializationBehavior;
|
|
return result;
|
|
}
|
|
|
|
// Bundleable implementation.
|
|
|
|
@Documented
|
|
@Retention(RetentionPolicy.SOURCE)
|
|
@Target(TYPE_USE)
|
|
@IntDef({
|
|
FIELD_CONTENT_TYPE,
|
|
FIELD_FLAGS,
|
|
FIELD_USAGE,
|
|
FIELD_ALLOWED_CAPTURE_POLICY,
|
|
FIELD_SPATIALIZATION_BEHAVIOR
|
|
})
|
|
private @interface FieldNumber {}
|
|
|
|
private static final int FIELD_CONTENT_TYPE = 0;
|
|
private static final int FIELD_FLAGS = 1;
|
|
private static final int FIELD_USAGE = 2;
|
|
private static final int FIELD_ALLOWED_CAPTURE_POLICY = 3;
|
|
private static final int FIELD_SPATIALIZATION_BEHAVIOR = 4;
|
|
|
|
@UnstableApi
|
|
@Override
|
|
public Bundle toBundle() {
|
|
Bundle bundle = new Bundle();
|
|
bundle.putInt(keyForField(FIELD_CONTENT_TYPE), contentType);
|
|
bundle.putInt(keyForField(FIELD_FLAGS), flags);
|
|
bundle.putInt(keyForField(FIELD_USAGE), usage);
|
|
bundle.putInt(keyForField(FIELD_ALLOWED_CAPTURE_POLICY), allowedCapturePolicy);
|
|
bundle.putInt(keyForField(FIELD_SPATIALIZATION_BEHAVIOR), spatializationBehavior);
|
|
return bundle;
|
|
}
|
|
|
|
/** Object that can restore {@link AudioAttributes} from a {@link Bundle}. */
|
|
@UnstableApi
|
|
public static final Creator<AudioAttributes> CREATOR =
|
|
bundle -> {
|
|
Builder builder = new Builder();
|
|
if (bundle.containsKey(keyForField(FIELD_CONTENT_TYPE))) {
|
|
builder.setContentType(bundle.getInt(keyForField(FIELD_CONTENT_TYPE)));
|
|
}
|
|
if (bundle.containsKey(keyForField(FIELD_FLAGS))) {
|
|
builder.setFlags(bundle.getInt(keyForField(FIELD_FLAGS)));
|
|
}
|
|
if (bundle.containsKey(keyForField(FIELD_USAGE))) {
|
|
builder.setUsage(bundle.getInt(keyForField(FIELD_USAGE)));
|
|
}
|
|
if (bundle.containsKey(keyForField(FIELD_ALLOWED_CAPTURE_POLICY))) {
|
|
builder.setAllowedCapturePolicy(bundle.getInt(keyForField(FIELD_ALLOWED_CAPTURE_POLICY)));
|
|
}
|
|
if (bundle.containsKey(keyForField(FIELD_SPATIALIZATION_BEHAVIOR))) {
|
|
builder.setSpatializationBehavior(
|
|
bundle.getInt(keyForField(FIELD_SPATIALIZATION_BEHAVIOR)));
|
|
}
|
|
return builder.build();
|
|
};
|
|
|
|
private static String keyForField(@FieldNumber int field) {
|
|
return Integer.toString(field, Character.MAX_RADIX);
|
|
}
|
|
|
|
@RequiresApi(29)
|
|
private static final class Api29 {
|
|
private Api29() {}
|
|
|
|
@DoNotInline
|
|
public static void setAllowedCapturePolicy(
|
|
android.media.AudioAttributes.Builder builder,
|
|
@C.AudioAllowedCapturePolicy int allowedCapturePolicy) {
|
|
builder.setAllowedCapturePolicy(allowedCapturePolicy);
|
|
}
|
|
}
|
|
|
|
@RequiresApi(32)
|
|
private static final class Api32 {
|
|
private Api32() {}
|
|
|
|
@DoNotInline
|
|
public static void setSpatializationBehavior(
|
|
android.media.AudioAttributes.Builder builder,
|
|
@C.SpatializationBehavior int spatializationBehavior) {
|
|
try {
|
|
// TODO[b/190759307]: Remove reflection once compile SDK target is set to 32.
|
|
Method setSpatializationBehavior =
|
|
builder.getClass().getMethod("setSpatializationBehavior", Integer.TYPE);
|
|
setSpatializationBehavior.invoke(builder, spatializationBehavior);
|
|
} catch (Exception e) {
|
|
// Do nothing if reflection fails.
|
|
}
|
|
}
|
|
}
|
|
}
|