mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Add support for RTSPT scheme in RtspMediaSource.Factory
If the `RtspMediaSource.Factory` is provided a `MediaItem` containing a uri with the scheme `rtspt`, then the factory will create its `RtspMediaSource` configured to use TCP. Issue: androidx/media#1484 PiperOrigin-RevId: 740340604
This commit is contained in:
parent
0cba160c22
commit
a220b0cb5e
@ -54,6 +54,9 @@
|
|||||||
* DASH extension:
|
* DASH extension:
|
||||||
* Smooth Streaming extension:
|
* Smooth Streaming extension:
|
||||||
* RTSP extension:
|
* RTSP extension:
|
||||||
|
* Add support for URI with RTSPT scheme as a way to configure the RTSP
|
||||||
|
session to use TCP
|
||||||
|
([#1484](https://github.com/androidx/media/issues/1484)).
|
||||||
* Decoder extensions (FFmpeg, VP9, AV1, etc.):
|
* Decoder extensions (FFmpeg, VP9, AV1, etc.):
|
||||||
* MIDI extension:
|
* MIDI extension:
|
||||||
* Leanback extension:
|
* Leanback extension:
|
||||||
|
@ -2570,7 +2570,8 @@ public final class Util {
|
|||||||
*/
|
*/
|
||||||
public static @ContentType int inferContentType(Uri uri) {
|
public static @ContentType int inferContentType(Uri uri) {
|
||||||
@Nullable String scheme = uri.getScheme();
|
@Nullable String scheme = uri.getScheme();
|
||||||
if (scheme != null && Ascii.equalsIgnoreCase("rtsp", scheme)) {
|
if (scheme != null
|
||||||
|
&& (Ascii.equalsIgnoreCase("rtsp", scheme) || Ascii.equalsIgnoreCase("rtspt", scheme))) {
|
||||||
return C.CONTENT_TYPE_RTSP;
|
return C.CONTENT_TYPE_RTSP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ import androidx.media3.exoplayer.source.MediaSourceFactory;
|
|||||||
import androidx.media3.exoplayer.source.SinglePeriodTimeline;
|
import androidx.media3.exoplayer.source.SinglePeriodTimeline;
|
||||||
import androidx.media3.exoplayer.upstream.Allocator;
|
import androidx.media3.exoplayer.upstream.Allocator;
|
||||||
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy;
|
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy;
|
||||||
|
import com.google.common.base.Ascii;
|
||||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import javax.net.SocketFactory;
|
import javax.net.SocketFactory;
|
||||||
@ -182,13 +183,21 @@ public final class RtspMediaSource extends BaseMediaSource {
|
|||||||
checkNotNull(mediaItem.localConfiguration);
|
checkNotNull(mediaItem.localConfiguration);
|
||||||
return new RtspMediaSource(
|
return new RtspMediaSource(
|
||||||
mediaItem,
|
mediaItem,
|
||||||
forceUseRtpTcp
|
shouldForceUseRtpTcp(mediaItem)
|
||||||
? new TransferRtpDataChannelFactory(timeoutMs)
|
? new TransferRtpDataChannelFactory(timeoutMs)
|
||||||
: new UdpDataSourceRtpDataChannelFactory(timeoutMs),
|
: new UdpDataSourceRtpDataChannelFactory(timeoutMs),
|
||||||
userAgent,
|
userAgent,
|
||||||
socketFactory,
|
socketFactory,
|
||||||
debugLoggingEnabled);
|
debugLoggingEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean shouldForceUseRtpTcp(MediaItem mediaItem) {
|
||||||
|
if (forceUseRtpTcp) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@Nullable String scheme = checkNotNull(mediaItem.localConfiguration).uri.getScheme();
|
||||||
|
return scheme != null && Ascii.equalsIgnoreCase("rtspt", scheme);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Thrown when an exception or error is encountered during loading an RTSP stream. */
|
/** Thrown when an exception or error is encountered during loading an RTSP stream. */
|
||||||
@ -237,7 +246,7 @@ public final class RtspMediaSource extends BaseMediaSource {
|
|||||||
this.mediaItem = mediaItem;
|
this.mediaItem = mediaItem;
|
||||||
this.rtpDataChannelFactory = rtpDataChannelFactory;
|
this.rtpDataChannelFactory = rtpDataChannelFactory;
|
||||||
this.userAgent = userAgent;
|
this.userAgent = userAgent;
|
||||||
this.uri = checkNotNull(mediaItem.localConfiguration).uri;
|
this.uri = maybeConvertRtsptUriScheme(checkNotNull(mediaItem.localConfiguration).uri);
|
||||||
this.socketFactory = socketFactory;
|
this.socketFactory = socketFactory;
|
||||||
this.debugLoggingEnabled = debugLoggingEnabled;
|
this.debugLoggingEnabled = debugLoggingEnabled;
|
||||||
this.timelineDurationUs = C.TIME_UNSET;
|
this.timelineDurationUs = C.TIME_UNSET;
|
||||||
@ -262,7 +271,8 @@ public final class RtspMediaSource extends BaseMediaSource {
|
|||||||
@Override
|
@Override
|
||||||
public boolean canUpdateMediaItem(MediaItem mediaItem) {
|
public boolean canUpdateMediaItem(MediaItem mediaItem) {
|
||||||
@Nullable MediaItem.LocalConfiguration newConfiguration = mediaItem.localConfiguration;
|
@Nullable MediaItem.LocalConfiguration newConfiguration = mediaItem.localConfiguration;
|
||||||
return newConfiguration != null && newConfiguration.uri.equals(this.uri);
|
return newConfiguration != null
|
||||||
|
&& maybeConvertRtsptUriScheme(newConfiguration.uri).equals(this.uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -309,6 +319,14 @@ public final class RtspMediaSource extends BaseMediaSource {
|
|||||||
|
|
||||||
// Internal methods.
|
// Internal methods.
|
||||||
|
|
||||||
|
private static Uri maybeConvertRtsptUriScheme(Uri uri) {
|
||||||
|
@Nullable String scheme = uri.getScheme();
|
||||||
|
if (scheme == null || !Ascii.equalsIgnoreCase("rtspt", scheme)) {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
return Uri.parse("rtsp" + uri.toString().substring(5));
|
||||||
|
}
|
||||||
|
|
||||||
private void notifySourceInfoRefreshed() {
|
private void notifySourceInfoRefreshed() {
|
||||||
Timeline timeline =
|
Timeline timeline =
|
||||||
new SinglePeriodTimeline(
|
new SinglePeriodTimeline(
|
||||||
|
@ -66,6 +66,18 @@ public class RtspMediaSourceTest {
|
|||||||
assertThat(canUpdateMediaItem).isFalse();
|
assertThat(canUpdateMediaItem).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void canUpdateMediaItem_withChangeToRtspFromRtspt_returnsTrue() {
|
||||||
|
MediaItem initialMediaItem = new MediaItem.Builder().setUri("rtspt://test.test").build();
|
||||||
|
MediaItem updatedMediaItem =
|
||||||
|
TestUtil.buildFullyCustomizedMediaItem().buildUpon().setUri("rtsp://test.test").build();
|
||||||
|
MediaSource mediaSource = buildMediaSource(initialMediaItem);
|
||||||
|
|
||||||
|
boolean canUpdateMediaItem = mediaSource.canUpdateMediaItem(updatedMediaItem);
|
||||||
|
|
||||||
|
assertThat(canUpdateMediaItem).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void updateMediaItem_createsTimelineWithUpdatedItem() throws Exception {
|
public void updateMediaItem_createsTimelineWithUpdatedItem() throws Exception {
|
||||||
MediaItem initialMediaItem =
|
MediaItem initialMediaItem =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user