Skip to content

Commit 121c650

Browse files
committed
- add communication path between player and decoder/renderer
- add application example for xHE-AAC
1 parent 9a3c247 commit 121c650

File tree

11 files changed

+663
-3
lines changed

11 files changed

+663
-3
lines changed

demos/main/src/main/assets/media.exolist.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,10 @@
787787
{
788788
"name": "MPEG-H HD (MP4, H265)",
789789
"uri": "https://media.githubusercontent.com/media/Fraunhofer-IIS/mpegh-test-content/main/TRI_Fileset_17_514H_D1_D2_D3_O1_24bit1080p50.mp4"
790+
},
791+
{
792+
"name": "xHE-AAC Test (MP4)",
793+
"uri": "https://www2.iis.fraunhofer.de/AAC/Test_PRL-20.mp4"
790794
}
791795
]
792796
},

demos/main/src/main/java/androidx/media3/demo/main/PlayerActivity.java

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,16 @@
3434
import androidx.appcompat.app.AppCompatActivity;
3535
import androidx.media3.common.AudioAttributes;
3636
import androidx.media3.common.C;
37+
import androidx.media3.common.CodecParameter;
38+
import androidx.media3.common.CodecParameters;
39+
import androidx.media3.common.CodecParametersChangeListener;
3740
import androidx.media3.common.ErrorMessageProvider;
3841
import androidx.media3.common.MediaItem;
3942
import androidx.media3.common.PlaybackException;
4043
import androidx.media3.common.Player;
4144
import androidx.media3.common.TrackSelectionParameters;
4245
import androidx.media3.common.Tracks;
46+
import androidx.media3.common.util.Log;
4347
import androidx.media3.common.util.UnstableApi;
4448
import androidx.media3.common.util.Util;
4549
import androidx.media3.datasource.DataSchemeDataSource;
@@ -61,6 +65,7 @@
6165
import androidx.media3.ui.PlayerView;
6266
import java.util.ArrayList;
6367
import java.util.Collections;
68+
import java.util.HashMap;
6469
import java.util.List;
6570
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
6671

@@ -261,6 +266,7 @@ protected void setContentView() {
261266
/**
262267
* @return Whether initialization was successful.
263268
*/
269+
@OptIn(markerClass = UnstableApi.class)
264270
protected boolean initializePlayer() {
265271
Intent intent = getIntent();
266272
if (player == null) {
@@ -277,6 +283,56 @@ protected boolean initializePlayer() {
277283
setRenderersFactory(
278284
playerBuilder, intent.getBooleanExtra(IntentUtil.PREFER_EXTENSION_DECODERS_EXTRA, false));
279285
player = playerBuilder.build();
286+
287+
// --------------------------- TESTING CODE ONLY -- REMOVE AGAIN ----------------------------
288+
player.setCodecParametersChangeListener(new CodecParametersChangeListener() {
289+
@Override
290+
public void onCodecParametersChanged(CodecParameters codecParameters) {
291+
HashMap<String, CodecParameter> parameters = codecParameters.get();
292+
for (String key : parameters.keySet()) {
293+
Log.e("PlayerActivity", "key = " + key + " value = " + parameters.get(key));
294+
}
295+
}
296+
297+
@Override
298+
public ArrayList<String> getFilterKeys() {
299+
ArrayList<String> filterKeys = new ArrayList<>();
300+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
301+
filterKeys.add(CodecParameter.KEY_AAC_DRC_OUTPUT_LOUDNESS);
302+
}
303+
return filterKeys;
304+
}
305+
});
306+
307+
CodecParameter codecParameter;
308+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
309+
// For testing set initial targetLoudness to -16 LUFS
310+
codecParameter = new CodecParameter(CodecParameter.KEY_AAC_DRC_TARGET_REFERENCE_LEVEL, 64,
311+
CodecParameter.VALUETYPE_INT);
312+
player.setCodecParameter(codecParameter);
313+
// For testing set initial BoostFactor to 32
314+
codecParameter = new CodecParameter(CodecParameter.KEY_AAC_DRC_BOOST_FACTOR, 32,
315+
CodecParameter.VALUETYPE_INT);
316+
player.setCodecParameter(codecParameter);
317+
// For testing set initial AttenuationFactor to 16
318+
codecParameter = new CodecParameter(CodecParameter.KEY_AAC_DRC_ATTENUATION_FACTOR, 16,
319+
CodecParameter.VALUETYPE_INT);
320+
player.setCodecParameter(codecParameter);
321+
}
322+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
323+
// For testing set initial EffectType to NOISY_ENVIRONMENT
324+
codecParameter = new CodecParameter(CodecParameter.KEY_AAC_DRC_EFFECT_TYPE, 2,
325+
CodecParameter.VALUETYPE_INT);
326+
player.setCodecParameter(codecParameter);
327+
}
328+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
329+
// For testing set initial AlbumMode to ENABLED
330+
codecParameter = new CodecParameter(CodecParameter.KEY_AAC_DRC_ALBUM_MODE, 1,
331+
CodecParameter.VALUETYPE_INT);
332+
player.setCodecParameter(codecParameter);
333+
}
334+
// --------------------------- TESTING CODE ONLY -- REMOVE AGAIN ----------------------------
335+
280336
player.setTrackSelectionParameters(trackSelectionParameters);
281337
player.addListener(new PlayerEventListener());
282338
player.addAnalyticsListener(new EventLogger());
@@ -298,6 +354,44 @@ protected boolean initializePlayer() {
298354
player.setRepeatMode(IntentUtil.parseRepeatModeExtra(repeatModeExtra));
299355
}
300356
updateButtonVisibility();
357+
358+
// --------------------------- TESTING CODE ONLY -- REMOVE AGAIN ----------------------------
359+
// Simulate sleep so the MPEG-D DRC can change during runtime
360+
try {
361+
Thread.sleep(2000);
362+
} catch (InterruptedException e) {
363+
e.printStackTrace();
364+
}
365+
366+
CodecParameter codecParameter;
367+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
368+
// Testing a change to the targetLoudness during codec runtime (set to -24 LUFS)
369+
codecParameter = new CodecParameter(CodecParameter.KEY_AAC_DRC_TARGET_REFERENCE_LEVEL, 96,
370+
CodecParameter.VALUETYPE_INT);
371+
player.setCodecParameter(codecParameter);
372+
// Testing a change to the boost factor during codec runtime (set to 96)
373+
codecParameter = new CodecParameter(CodecParameter.KEY_AAC_DRC_BOOST_FACTOR, 96,
374+
CodecParameter.VALUETYPE_INT);
375+
player.setCodecParameter(codecParameter);
376+
// Testing a change to the attenuation factor during codec runtime (set to 64)
377+
codecParameter = new CodecParameter(CodecParameter.KEY_AAC_DRC_ATTENUATION_FACTOR, 64,
378+
CodecParameter.VALUETYPE_INT);
379+
player.setCodecParameter(codecParameter);
380+
}
381+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
382+
// Testing a change to the EffectType during codec runtime (set to OFF)
383+
codecParameter = new CodecParameter(CodecParameter.KEY_AAC_DRC_EFFECT_TYPE, -1,
384+
CodecParameter.VALUETYPE_INT);
385+
player.setCodecParameter(codecParameter);
386+
}
387+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
388+
// Testing a change to the album mode during codec runtime (set to DISABLED)
389+
codecParameter = new CodecParameter(CodecParameter.KEY_AAC_DRC_ALBUM_MODE, 0,
390+
CodecParameter.VALUETYPE_INT);
391+
player.setCodecParameter(codecParameter);
392+
}
393+
// --------------------------- TESTING CODE ONLY -- REMOVE AGAIN ----------------------------
394+
301395
return true;
302396
}
303397

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
package androidx.media3.common;
2+
3+
import static java.lang.annotation.ElementType.TYPE_USE;
4+
5+
import android.media.MediaFormat;
6+
import android.os.Build;
7+
8+
import androidx.annotation.IntDef;
9+
import androidx.annotation.Nullable;
10+
import androidx.annotation.RequiresApi;
11+
12+
import java.lang.annotation.Documented;
13+
import java.lang.annotation.Retention;
14+
import java.lang.annotation.RetentionPolicy;
15+
import java.lang.annotation.Target;
16+
17+
/**
18+
* A {@link CodecParameter} holds the key, value and the value type for signalling a parameter change to a
19+
* decoder. The key can be an arbitrary string which must be known by the decoder instance.
20+
*/
21+
public class CodecParameter {
22+
23+
private static final String TAG = "CodecParameter";
24+
25+
/**
26+
* @see MediaFormat#KEY_AAC_DRC_ALBUM_MODE
27+
*/
28+
@RequiresApi(api = Build.VERSION_CODES.R)
29+
public final static String KEY_AAC_DRC_ALBUM_MODE = MediaFormat.KEY_AAC_DRC_ALBUM_MODE;
30+
31+
/**
32+
* @see MediaFormat#KEY_AAC_DRC_ATTENUATION_FACTOR
33+
*/
34+
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
35+
public final static String KEY_AAC_DRC_ATTENUATION_FACTOR = MediaFormat.KEY_AAC_DRC_ATTENUATION_FACTOR;
36+
37+
/**
38+
* @see MediaFormat#KEY_AAC_DRC_BOOST_FACTOR
39+
*/
40+
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
41+
public final static String KEY_AAC_DRC_BOOST_FACTOR = MediaFormat.KEY_AAC_DRC_BOOST_FACTOR;
42+
43+
/**
44+
* @see MediaFormat#KEY_AAC_DRC_EFFECT_TYPE
45+
*/
46+
@RequiresApi(api = Build.VERSION_CODES.P)
47+
public final static String KEY_AAC_DRC_EFFECT_TYPE = MediaFormat.KEY_AAC_DRC_EFFECT_TYPE;
48+
49+
/**
50+
* @see MediaFormat#KEY_AAC_DRC_TARGET_REFERENCE_LEVEL
51+
*/
52+
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
53+
public final static String KEY_AAC_DRC_TARGET_REFERENCE_LEVEL = MediaFormat.KEY_AAC_DRC_TARGET_REFERENCE_LEVEL;
54+
55+
/**
56+
* @see MediaFormat#KEY_AAC_DRC_OUTPUT_LOUDNESS
57+
*/
58+
@RequiresApi(api = Build.VERSION_CODES.R)
59+
public final static String KEY_AAC_DRC_OUTPUT_LOUDNESS = MediaFormat.KEY_AAC_DRC_OUTPUT_LOUDNESS;
60+
61+
62+
/**
63+
* Key to set the MPEG-H output mode.
64+
* The corresponding value must be of value type {@link ValueType#VALUETYPE_INT}.
65+
* Possible values are:
66+
* 0 for PCM output (decoding the MPEG-H bitstream with a certain MPEG-H target layout CICP index)
67+
* 1 for MPEG-H bitstream bypass (using IEC61937-13 with a sample rate factor of 4)
68+
* 2 for MPEG-H bitstream bypass (using IEC61937-13 with a sample rate factor of 16)
69+
*/
70+
public final static String KEY_MPEGH_OUTPUT_MODE = "mpegh-output-mode";
71+
72+
/**
73+
* Key to set the MPEG-H target layout CICP index.
74+
* The corresponding value must be of value type {@link ValueType#VALUETYPE_INT}.
75+
* It must be set before decoder initialization. A change during runtime does not have any effect.
76+
* Supported values are: 0, 1, 2, 6, 8, 10, 12
77+
* A value of 0 tells the decoder to create binauralized output.
78+
*/
79+
public final static String KEY_MPEGH_TARGET_LAYOUT = "mpegh-target-layout";
80+
81+
/**
82+
* Key to set the MPEG-H UI configuration.
83+
* The corresponding value must be of value type {@link ValueType#VALUETYPE_STRING}.
84+
* This key is returned from the MPEG-H UI manager.
85+
*/
86+
public final static String KEY_MPEGH_UI_CONFIG = "mpegh-ui-config";
87+
88+
/**
89+
* Key to set the MPEG-H UI command.
90+
* The corresponding value must be of value type {@link ValueType#VALUETYPE_STRING}.
91+
* This key is passed to the MPEG-H UI manager.
92+
*/
93+
public final static String KEY_MPEGH_UI_COMMAND = "mpegh-ui-command";
94+
95+
/**
96+
* Key to set the MPEG-H UI persistence storage path.
97+
* The corresponding value must be of value type {@link ValueType#VALUETYPE_STRING}.
98+
* This key is passed to the MPEG-H UI manager.
99+
*/
100+
public final static String KEY_MPEGH_UI_PERSISTENCESTORAGE_PATH = "mpegh-ui-persistencestorage-path";
101+
102+
/**
103+
* @see MediaFormat#TYPE_NULL
104+
*/
105+
public static final int VALUETYPE_NULL = 0; // MediaFormat.TYPE_NULL;
106+
/**
107+
* @see MediaFormat#TYPE_INTEGER
108+
*/
109+
public static final int VALUETYPE_INT = 1; // MediaFormat.TYPE_INTEGER;
110+
/**
111+
* @see MediaFormat#TYPE_LONG
112+
*/
113+
public static final int VALUETYPE_LONG = 2; // MediaFormat.TYPE_LONG;
114+
/**
115+
* @see MediaFormat#TYPE_FLOAT
116+
*/
117+
public static final int VALUETYPE_FLOAT = 3; // MediaFormat.TYPE_FLOAT;
118+
/**
119+
* @see MediaFormat#TYPE_STRING
120+
*/
121+
public static final int VALUETYPE_STRING = 4; // MediaFormat.TYPE_STRING;
122+
/**
123+
* @see MediaFormat#TYPE_BYTE_BUFFER
124+
*/
125+
public static final int VALUETYPE_BYTE_BUFFER = 5; // MediaFormat.TYPE_BYTE_BUFFER;
126+
127+
/**
128+
* Value types for a {@link CodecParameter}.
129+
* One of {@link #VALUETYPE_NULL}, {@link #VALUETYPE_INT}, {@link #VALUETYPE_LONG},
130+
* {@link #VALUETYPE_FLOAT}, {@link #VALUETYPE_STRING} or {@link #VALUETYPE_BYTE_BUFFER}.
131+
*/
132+
@Documented
133+
@Retention(RetentionPolicy.SOURCE)
134+
@Target(TYPE_USE)
135+
@IntDef({
136+
VALUETYPE_NULL,
137+
VALUETYPE_INT,
138+
VALUETYPE_LONG,
139+
VALUETYPE_FLOAT,
140+
VALUETYPE_STRING,
141+
VALUETYPE_BYTE_BUFFER
142+
})
143+
public @interface ValueType {
144+
145+
}
146+
147+
148+
public String key;
149+
public @Nullable Object value;
150+
public @ValueType int valueType;
151+
152+
153+
/**
154+
* Creates a new codec parameter.
155+
*
156+
* @param key A string holding the key of the codec parameter.
157+
* @param value An object representing the value of the codec parameter.
158+
* @param valueType The value type of the value object.
159+
*/
160+
public CodecParameter(String key, @Nullable Object value, @ValueType int valueType) {
161+
this.key = key;
162+
this.value = value;
163+
this.valueType = valueType;
164+
}
165+
}

0 commit comments

Comments
 (0)