Compare commits

..

No commits in common. "142496fa166a76246a2177f09c14c61a0a055a04" and "a7c897003c35e8db816c470131f548081fc9b02e" have entirely different histories.

4 changed files with 13 additions and 63 deletions

View File

@ -11,9 +11,6 @@
`ExoPlayer.Builder`.
* Fix bug where prepare errors in the content of `AdsMediaSource` may be
never reported ([#2337](https://github.com/androidx/media/issues/2337)).
* Fix memory leak in `MergingMediaSource`, for example used when
sideloading subtitles
([#2338](https://github.com/androidx/media/issues/2338)).
* Transformer:
* Filling an initial gap (added via `addGap()`) with silent audio now
requires explicitly setting `experimentalSetForceAudioTrack(true)` in

View File

@ -245,9 +245,8 @@ public final class MergingMediaSource extends CompositeMediaSource<Integer> {
MergingMediaPeriod mergingPeriod = (MergingMediaPeriod) mediaPeriod;
for (int i = 0; i < mediaSources.length; i++) {
List<MediaPeriodAndId> mediaPeriodsForSource = mediaPeriods.get(i);
MediaPeriod childPeriod = mergingPeriod.getChildPeriod(i);
for (int j = 0; j < mediaPeriodsForSource.size(); j++) {
if (mediaPeriodsForSource.get(j).mediaPeriod.equals(childPeriod)) {
if (mediaPeriodsForSource.get(j).mediaPeriod.equals(mediaPeriod)) {
mediaPeriodsForSource.remove(j);
break;
}

View File

@ -16,7 +16,6 @@
package androidx.media3.exoplayer.source;
import static androidx.media3.test.utils.robolectric.RobolectricUtil.DEFAULT_TIMEOUT_MS;
import static androidx.media3.test.utils.robolectric.RobolectricUtil.runMainLooperUntil;
import static com.google.common.truth.Truth.assertThat;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.junit.Assert.assertThrows;
@ -25,11 +24,8 @@ import androidx.annotation.Nullable;
import androidx.media3.common.C;
import androidx.media3.common.Timeline;
import androidx.media3.common.util.Util;
import androidx.media3.exoplayer.analytics.PlayerId;
import androidx.media3.exoplayer.source.MediaSource.MediaPeriodId;
import androidx.media3.exoplayer.source.MergingMediaSource.IllegalMergeException;
import androidx.media3.exoplayer.upstream.Allocator;
import androidx.media3.exoplayer.upstream.DefaultAllocator;
import androidx.media3.test.utils.FakeMediaPeriod;
import androidx.media3.test.utils.FakeMediaSource;
import androidx.media3.test.utils.FakeTimeline;
@ -40,10 +36,7 @@ import com.google.common.collect.ConcurrentHashMultiset;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multiset;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -226,57 +219,6 @@ public class MergingMediaSourceTest {
}
}
@Test
public void createAndReleasePeriods_cleansUpReferences() throws Exception {
ArrayList<WeakReference<MediaPeriod>> createdChildPeriods = new ArrayList<>();
FakeMediaSource childSource =
new FakeMediaSource() {
@Override
public MediaPeriod createPeriod(
MediaPeriodId id, Allocator allocator, long startPositionUs) {
MediaPeriod period = super.createPeriod(id, allocator, startPositionUs);
createdChildPeriods.add(new WeakReference<>(period));
return period;
}
};
Allocator allocator =
new DefaultAllocator(/* trimOnReset= */ true, /* individualAllocationSize= */ 1024);
MergingMediaSource mergingMediaSource =
new MergingMediaSource(
/* adjustPeriodTimeOffsets= */ true,
/* clipDurations= */ true,
childSource,
childSource);
AtomicReference<Timeline> timelineReference = new AtomicReference<>();
mergingMediaSource.prepareSource(
(source, timeline) -> timelineReference.set(timeline),
/* mediaTransferListener= */ null,
PlayerId.UNSET);
runMainLooperUntil(() -> timelineReference.get() != null);
Object periodUid = timelineReference.get().getUidOfPeriod(/* periodIndex= */ 0);
// Create 20 periods.
ArrayList<MediaPeriod> createdMergedPeriods = new ArrayList<>();
for (int i = 0; i < 20; i++) {
createdMergedPeriods.add(
mergingMediaSource.createPeriod(
new MediaPeriodId(periodUid, /* windowSequenceNumber= */ i),
allocator,
/* startPositionUs= */ 0));
}
// Release 19 periods.
for (int i = 0; i < 19; i++) {
mergingMediaSource.releasePeriod(createdMergedPeriods.remove(0));
}
// Ensure all pending references are garbage collected
Runtime.getRuntime().gc();
// Assert that only 2 child periods remain in memory.
long nonNullChildPeriodReferences =
createdChildPeriods.stream().filter(reference -> reference.get() != null).count();
assertThat(nonNullChildPeriodReferences).isEqualTo(2);
}
/**
* Wraps the specified timelines in a {@link MergingMediaSource}, prepares it and returns the
* merged timeline.

View File

@ -573,6 +573,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
super.onPositionReset(positionUs, joining);
}
@Override
protected void onStarted() throws ExoPlaybackException {
super.onStarted();
videoSink.startRendering();
}
@Override
protected boolean maybeInitializeProcessingPipeline() throws ExoPlaybackException {
if (videoSink.isInitialized()) {
@ -586,6 +592,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
}
}
@Override
protected void onStopped() {
super.onStopped();
videoSink.stopRendering();
}
@Override
protected void onStreamChanged(
Format[] formats,