Skip to content

Commit

Permalink
Fix setDataSourceFactory handling in DefaultMediaSourceFactory
Browse files Browse the repository at this point in the history
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 6be0d6e)
  • Loading branch information
tonihei authored and rohitjoins committed Jul 13, 2022
1 parent 77a3b16 commit b82be04
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 6 deletions.
Expand Up @@ -274,6 +274,7 @@ public DefaultMediaSourceFactory clearLocalAdInsertionComponents() {
*/
public DefaultMediaSourceFactory setDataSourceFactory(DataSource.Factory dataSourceFactory) {
this.dataSourceFactory = dataSourceFactory;
delegateFactoryLoader.setDataSourceFactory(dataSourceFactory);
return this;
}

Expand Down Expand Up @@ -576,6 +577,7 @@ public void setDataSourceFactory(DataSource.Factory dataSourceFactory) {
this.dataSourceFactory = dataSourceFactory;
// TODO(b/233577470): Call MediaSource.Factory.setDataSourceFactory on each value when it
// exists on the interface.
mediaSourceFactorySuppliers.clear();
mediaSourceFactories.clear();
}
}
Expand Down Expand Up @@ -609,27 +611,28 @@ private Supplier<MediaSource.Factory> maybeLoadSupplier(@C.ContentType int conte
}

@Nullable Supplier<MediaSource.Factory> mediaSourceFactorySupplier = null;
DataSource.Factory dataSourceFactory = checkNotNull(this.dataSourceFactory);
try {
Class<? extends MediaSource.Factory> clazz;
switch (contentType) {
case C.CONTENT_TYPE_DASH:
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 =
Expand All @@ -639,9 +642,7 @@ private Supplier<MediaSource.Factory> maybeLoadSupplier(@C.ContentType int conte
break;
case C.CONTENT_TYPE_OTHER:
mediaSourceFactorySupplier =
() ->
new ProgressiveMediaSource.Factory(
checkNotNull(dataSourceFactory), extractorsFactory);
() -> new ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory);
break;
default:
// Do nothing.
Expand Down
Expand Up @@ -15,16 +15,21 @@
*/
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;
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;

Expand Down Expand Up @@ -82,4 +87,53 @@ public void getSupportedTypes_dashModule_containsTypeDash() {

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;
}
});
}
}
Expand Up @@ -15,16 +15,21 @@
*/
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;
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;

Expand Down Expand Up @@ -82,4 +87,53 @@ public void getSupportedTypes_hlsModule_containsTypeHls() {

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;
}
});
}
}
1 change: 1 addition & 0 deletions library/smoothstreaming/build.gradle
Expand Up @@ -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
}
Expand Down
Expand Up @@ -15,16 +15,21 @@
*/
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;
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;

Expand Down Expand Up @@ -93,4 +98,53 @@ public void getSupportedTypes_smoothstreamingModule_containsTypeSS() {

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;
}
});
}
}

0 comments on commit b82be04

Please sign in to comment.