Skip to content

Commit 713b9cd

Browse files
committed
Refactored and added Javadoc
1 parent 0d3227c commit 713b9cd

23 files changed

+1604
-18421
lines changed

RELEASENOTES.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
variable bitrate metadata when falling back to constant bitrate seeking
1212
due to `FLAG_ENABLE_CONSTANT_BITRATE_SEEKING(_ALWAYS)`
1313
([#2194](https://github.com/androidx/media/issues/2194)).
14-
* Fix seek on fragmented mp4 with multiple sidx atoms.
15-
([#9373](https://github.com/google/ExoPlayer/issues/9373))
14+
* Add support for seeking in fragmented MP4 with multiple `sidx` atoms
15+
([#9373](https://github.com/google/ExoPlayer/issues/9373)).
1616
* DataSource:
1717
* Audio:
1818
* Allow constant power upmixing/downmixing in DefaultAudioMixer.

libraries/common/src/main/java/androidx/media3/common/util/Util.java

+48
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,54 @@ public static <T> void nullSafeListToArray(List<T> list, T[] array) {
703703
list.toArray(array);
704704
}
705705

706+
/**
707+
* Creates a new array containing the concatenation of multiple non-null {@code int[]} arrays.
708+
*
709+
* @param arrays A list of non-null {@code int[]} arrays to concatenate.
710+
* @return The concatenated result.
711+
*/
712+
@UnstableApi
713+
public static int[] nullSafeIntArraysConcatenation(List<int[]> arrays) {
714+
int totalLength = 0;
715+
for (int[] array : arrays) {
716+
totalLength += array.length;
717+
}
718+
719+
int[] concatenation = new int[totalLength];
720+
721+
int offset = 0;
722+
for (int[] array : arrays) {
723+
System.arraycopy(array, 0, concatenation, offset, array.length);
724+
offset += array.length;
725+
}
726+
727+
return concatenation;
728+
}
729+
730+
/**
731+
* Creates a new array containing the concatenation of multiple non-null {@code long[]} arrays.
732+
*
733+
* @param arrays A list of non-null {@code long[]} arrays to concatenate.
734+
* @return The concatenated result.
735+
*/
736+
@UnstableApi
737+
public static long[] nullSafeLongArraysConcatenation(List<long[]> arrays) {
738+
int totalLength = 0;
739+
for (long[] array : arrays) {
740+
totalLength += array.length;
741+
}
742+
743+
long[] res = new long[totalLength];
744+
745+
int offset = 0;
746+
for (long[] array : arrays) {
747+
System.arraycopy(array, 0, res, offset, array.length);
748+
offset += array.length;
749+
}
750+
751+
return res;
752+
}
753+
706754
/**
707755
* Creates a {@link Handler} on the current {@link Looper} thread.
708756
*

libraries/extractor/src/main/java/androidx/media3/extractor/ChunkIndicesWrapper.java

-85
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Copyright 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package androidx.media3.extractor;
17+
18+
import androidx.media3.common.util.UnstableApi;
19+
import androidx.media3.common.util.Util;
20+
import java.util.ArrayList;
21+
import java.util.HashSet;
22+
import java.util.List;
23+
import java.util.Set;
24+
25+
/**
26+
* A utility class for merging multiple {@link ChunkIndex} instances into a single {@link
27+
* ChunkIndex}.
28+
*
29+
* <p>This is useful in scenarios where media is split across multiple segments or sources, and a
30+
* unified index is needed for seeking or playback.
31+
*/
32+
@UnstableApi
33+
public class MergedChunkIndex {
34+
35+
/** The individual {@link ChunkIndex} entries being merged. */
36+
private final List<ChunkIndex> chunks;
37+
38+
/** The set of first start times seen so far across added {@link ChunkIndex} instances. */
39+
private final Set<Long> uniqueStartTimes;
40+
41+
/** Creates an instance. */
42+
public MergedChunkIndex() {
43+
this.chunks = new ArrayList<>();
44+
this.uniqueStartTimes = new HashSet<>();
45+
}
46+
47+
/**
48+
* Adds a {@link ChunkIndex} to be merged.
49+
*
50+
* <p>Chunk indices with duplicate starting timestamps are ignored to avoid redundant data.
51+
*
52+
* @param chunk The {@link ChunkIndex} to add.
53+
*/
54+
public void merge(ChunkIndex chunk) {
55+
if (chunk.timesUs.length > 0 && !uniqueStartTimes.contains(chunk.timesUs[0])) {
56+
chunks.add(chunk);
57+
uniqueStartTimes.add(chunk.timesUs[0]);
58+
}
59+
}
60+
61+
/** Returns a single {@link ChunkIndex} that combines all added chunk indices. */
62+
public ChunkIndex toChunkIndex() {
63+
List<int[]> sizesList = new ArrayList<>();
64+
List<long[]> offsetsList = new ArrayList<>();
65+
List<long[]> durationsList = new ArrayList<>();
66+
List<long[]> timesList = new ArrayList<>();
67+
68+
for (ChunkIndex chunk : chunks) {
69+
sizesList.add(chunk.sizes);
70+
offsetsList.add(chunk.offsets);
71+
durationsList.add(chunk.durationsUs);
72+
timesList.add(chunk.timesUs);
73+
}
74+
75+
return new ChunkIndex(
76+
Util.nullSafeIntArraysConcatenation(sizesList),
77+
Util.nullSafeLongArraysConcatenation(offsetsList),
78+
Util.nullSafeLongArraysConcatenation(durationsList),
79+
Util.nullSafeLongArraysConcatenation(timesList));
80+
}
81+
82+
/** Clears all added chunk indices and internal state. */
83+
public void clear() {
84+
chunks.clear();
85+
uniqueStartTimes.clear();
86+
}
87+
88+
/** Returns the number of chunk indices added so far. */
89+
public int size() {
90+
return chunks.size();
91+
}
92+
}

0 commit comments

Comments
 (0)