Commit b82be047 by tonihei Committed by Rohit Singh

Fix setDataSourceFactory handling in DefaultMediaSourceFactory

The call doesn't currently reset the already loaded suppliers and
factories. Also fix the supplier loading code to use a local copy
of the current dataSourceFactory to avoid leaking an updated
instance to a later invocation.

Issue: androidx/media#116

#minor-release

PiperOrigin-RevId: 460721541
(cherry picked from commit 6be0d6ea)
parent 77a3b16d
......@@ -274,6 +274,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
*/
public DefaultMediaSourceFactory setDataSourceFactory(DataSource.Factory dataSourceFactory) {
this.dataSourceFactory = dataSourceFactory;
delegateFactoryLoader.setDataSourceFactory(dataSourceFactory);
return this;
}
......@@ -576,6 +577,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
this.dataSourceFactory = dataSourceFactory;
// TODO(b/233577470): Call MediaSource.Factory.setDataSourceFactory on each value when it
// exists on the interface.
mediaSourceFactorySuppliers.clear();
mediaSourceFactories.clear();
}
}
......@@ -609,6 +611,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
}
@Nullable Supplier<MediaSource.Factory> mediaSourceFactorySupplier = null;
DataSource.Factory dataSourceFactory = checkNotNull(this.dataSourceFactory);
try {
Class<? extends MediaSource.Factory> clazz;
switch (contentType) {
......@@ -616,20 +619,20 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
clazz =
Class.forName("com.google.android.exoplayer2.source.dash.DashMediaSource$Factory")
.asSubclass(MediaSource.Factory.class);
mediaSourceFactorySupplier = () -> newInstance(clazz, checkNotNull(dataSourceFactory));
mediaSourceFactorySupplier = () -> newInstance(clazz, dataSourceFactory);
break;
case C.CONTENT_TYPE_SS:
clazz =
Class.forName(
"com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource$Factory")
.asSubclass(MediaSource.Factory.class);
mediaSourceFactorySupplier = () -> newInstance(clazz, checkNotNull(dataSourceFactory));
mediaSourceFactorySupplier = () -> newInstance(clazz, dataSourceFactory);
break;
case C.CONTENT_TYPE_HLS:
clazz =
Class.forName("com.google.android.exoplayer2.source.hls.HlsMediaSource$Factory")
.asSubclass(MediaSource.Factory.class);
mediaSourceFactorySupplier = () -> newInstance(clazz, checkNotNull(dataSourceFactory));
mediaSourceFactorySupplier = () -> newInstance(clazz, dataSourceFactory);
break;
case C.CONTENT_TYPE_RTSP:
clazz =
......@@ -639,9 +642,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
break;
case C.CONTENT_TYPE_OTHER:
mediaSourceFactorySupplier =
() ->
new ProgressiveMediaSource.Factory(
checkNotNull(dataSourceFactory), extractorsFactory);
() -> new ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory);
break;
default:
// Do nothing.
......
......@@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.source.dash;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
......@@ -22,9 +23,13 @@ import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.analytics.PlayerId;
import com.google.android.exoplayer2.robolectric.RobolectricUtil;
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.testutil.FakeDataSource;
import com.google.android.exoplayer2.util.MimeTypes;
import java.io.IOException;
import org.junit.Test;
import org.junit.runner.RunWith;
......@@ -82,4 +87,53 @@ public class DefaultMediaSourceFactoryTest {
assertThat(supportedTypes).asList().containsExactly(C.CONTENT_TYPE_OTHER, C.CONTENT_TYPE_DASH);
}
@Test
public void createMediaSource_withSetDataSourceFactory_usesDataSourceFactory() throws Exception {
FakeDataSource fakeDataSource = new FakeDataSource();
DefaultMediaSourceFactory defaultMediaSourceFactory =
new DefaultMediaSourceFactory((Context) ApplicationProvider.getApplicationContext())
.setDataSourceFactory(() -> fakeDataSource);
prepareDashUrlAndWaitForPrepareError(defaultMediaSourceFactory);
assertThat(fakeDataSource.getAndClearOpenedDataSpecs()).asList().isNotEmpty();
}
@Test
public void
createMediaSource_usingDefaultDataSourceFactoryAndSetDataSourceFactory_usesUpdatesDataSourceFactory()
throws Exception {
FakeDataSource fakeDataSource = new FakeDataSource();
DefaultMediaSourceFactory defaultMediaSourceFactory =
new DefaultMediaSourceFactory((Context) ApplicationProvider.getApplicationContext());
// Use default DataSource.Factory first.
prepareDashUrlAndWaitForPrepareError(defaultMediaSourceFactory);
defaultMediaSourceFactory.setDataSourceFactory(() -> fakeDataSource);
prepareDashUrlAndWaitForPrepareError(defaultMediaSourceFactory);
assertThat(fakeDataSource.getAndClearOpenedDataSpecs()).asList().isNotEmpty();
}
private static void prepareDashUrlAndWaitForPrepareError(
DefaultMediaSourceFactory defaultMediaSourceFactory) throws Exception {
MediaSource mediaSource =
defaultMediaSourceFactory.createMediaSource(MediaItem.fromUri(URI_MEDIA + "/file.mpd"));
getInstrumentation()
.runOnMainSync(
() ->
mediaSource.prepareSource(
(source, timeline) -> {}, /* mediaTransferListener= */ null, PlayerId.UNSET));
// We don't expect this to prepare successfully.
RobolectricUtil.runMainLooperUntil(
() -> {
try {
mediaSource.maybeThrowSourceInfoRefreshError();
return false;
} catch (IOException e) {
return true;
}
});
}
}
......@@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.source.hls;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
......@@ -22,9 +23,13 @@ import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.analytics.PlayerId;
import com.google.android.exoplayer2.robolectric.RobolectricUtil;
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.testutil.FakeDataSource;
import com.google.android.exoplayer2.util.MimeTypes;
import java.io.IOException;
import org.junit.Test;
import org.junit.runner.RunWith;
......@@ -82,4 +87,53 @@ public class DefaultMediaSourceFactoryTest {
assertThat(supportedTypes).asList().containsExactly(C.CONTENT_TYPE_OTHER, C.CONTENT_TYPE_HLS);
}
@Test
public void createMediaSource_withSetDataSourceFactory_usesDataSourceFactory() throws Exception {
FakeDataSource fakeDataSource = new FakeDataSource();
DefaultMediaSourceFactory defaultMediaSourceFactory =
new DefaultMediaSourceFactory((Context) ApplicationProvider.getApplicationContext())
.setDataSourceFactory(() -> fakeDataSource);
prepareHlsUrlAndWaitForPrepareError(defaultMediaSourceFactory);
assertThat(fakeDataSource.getAndClearOpenedDataSpecs()).asList().isNotEmpty();
}
@Test
public void
createMediaSource_usingDefaultDataSourceFactoryAndSetDataSourceFactory_usesUpdatesDataSourceFactory()
throws Exception {
FakeDataSource fakeDataSource = new FakeDataSource();
DefaultMediaSourceFactory defaultMediaSourceFactory =
new DefaultMediaSourceFactory((Context) ApplicationProvider.getApplicationContext());
// Use default DataSource.Factory first.
prepareHlsUrlAndWaitForPrepareError(defaultMediaSourceFactory);
defaultMediaSourceFactory.setDataSourceFactory(() -> fakeDataSource);
prepareHlsUrlAndWaitForPrepareError(defaultMediaSourceFactory);
assertThat(fakeDataSource.getAndClearOpenedDataSpecs()).asList().isNotEmpty();
}
private static void prepareHlsUrlAndWaitForPrepareError(
DefaultMediaSourceFactory defaultMediaSourceFactory) throws Exception {
MediaSource mediaSource =
defaultMediaSourceFactory.createMediaSource(MediaItem.fromUri(URI_MEDIA + "/file.m3u8"));
getInstrumentation()
.runOnMainSync(
() ->
mediaSource.prepareSource(
(source, timeline) -> {}, /* mediaTransferListener= */ null, PlayerId.UNSET));
// We don't expect this to prepare successfully.
RobolectricUtil.runMainLooperUntil(
() -> {
try {
mediaSource.maybeThrowSourceInfoRefreshError();
return false;
} catch (IOException e) {
return true;
}
});
}
}
......@@ -29,6 +29,7 @@ dependencies {
compileOnly 'org.checkerframework:checker-compat-qual:' + checkerframeworkCompatVersion
compileOnly 'org.jetbrains.kotlin:kotlin-annotations-jvm:' + kotlinAnnotationsVersion
implementation 'androidx.annotation:annotation:' + androidxAnnotationVersion
testImplementation project(modulePrefix + 'robolectricutils')
testImplementation project(modulePrefix + 'testutils')
testImplementation 'org.robolectric:robolectric:' + robolectricVersion
}
......
......@@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.source.smoothstreaming;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
......@@ -22,9 +23,13 @@ import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.analytics.PlayerId;
import com.google.android.exoplayer2.robolectric.RobolectricUtil;
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.testutil.FakeDataSource;
import com.google.android.exoplayer2.util.MimeTypes;
import java.io.IOException;
import org.junit.Test;
import org.junit.runner.RunWith;
......@@ -93,4 +98,53 @@ public class DefaultMediaSourceFactoryTest {
assertThat(supportedTypes).asList().containsExactly(C.CONTENT_TYPE_OTHER, C.CONTENT_TYPE_SS);
}
@Test
public void createMediaSource_withSetDataSourceFactory_usesDataSourceFactory() throws Exception {
FakeDataSource fakeDataSource = new FakeDataSource();
DefaultMediaSourceFactory defaultMediaSourceFactory =
new DefaultMediaSourceFactory((Context) ApplicationProvider.getApplicationContext())
.setDataSourceFactory(() -> fakeDataSource);
prepareSsUrlAndWaitForPrepareError(defaultMediaSourceFactory);
assertThat(fakeDataSource.getAndClearOpenedDataSpecs()).asList().isNotEmpty();
}
@Test
public void
createMediaSource_usingDefaultDataSourceFactoryAndSetDataSourceFactory_usesUpdatesDataSourceFactory()
throws Exception {
FakeDataSource fakeDataSource = new FakeDataSource();
DefaultMediaSourceFactory defaultMediaSourceFactory =
new DefaultMediaSourceFactory((Context) ApplicationProvider.getApplicationContext());
// Use default DataSource.Factory first.
prepareSsUrlAndWaitForPrepareError(defaultMediaSourceFactory);
defaultMediaSourceFactory.setDataSourceFactory(() -> fakeDataSource);
prepareSsUrlAndWaitForPrepareError(defaultMediaSourceFactory);
assertThat(fakeDataSource.getAndClearOpenedDataSpecs()).asList().isNotEmpty();
}
private static void prepareSsUrlAndWaitForPrepareError(
DefaultMediaSourceFactory defaultMediaSourceFactory) throws Exception {
MediaSource mediaSource =
defaultMediaSourceFactory.createMediaSource(MediaItem.fromUri(URI_MEDIA + "/file.ism"));
getInstrumentation()
.runOnMainSync(
() ->
mediaSource.prepareSource(
(source, timeline) -> {}, /* mediaTransferListener= */ null, PlayerId.UNSET));
// We don't expect this to prepare successfully.
RobolectricUtil.runMainLooperUntil(
() -> {
try {
mediaSource.maybeThrowSourceInfoRefreshError();
return false;
} catch (IOException e) {
return true;
}
});
}
}
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