mirror of
https://github.com/androidx/media.git
synced 2025-05-06 23:20:42 +08:00
Introduce RtpDataChannel interface.
#minor-release PiperOrigin-RevId: 371326814
This commit is contained in:
parent
3ddf73fdcf
commit
a64c6e80ed
@ -43,11 +43,11 @@ import com.google.android.exoplayer2.source.TrackGroup;
|
|||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
import com.google.android.exoplayer2.source.rtsp.RtspClient.PlaybackEventListener;
|
import com.google.android.exoplayer2.source.rtsp.RtspClient.PlaybackEventListener;
|
||||||
import com.google.android.exoplayer2.source.rtsp.RtspMediaSource.RtspPlaybackException;
|
import com.google.android.exoplayer2.source.rtsp.RtspMediaSource.RtspPlaybackException;
|
||||||
|
import com.google.android.exoplayer2.source.rtsp.rtp.RtpDataChannel;
|
||||||
import com.google.android.exoplayer2.source.rtsp.rtp.RtpDataLoadable;
|
import com.google.android.exoplayer2.source.rtsp.rtp.RtpDataLoadable;
|
||||||
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
|
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||||
import com.google.android.exoplayer2.upstream.Allocator;
|
import com.google.android.exoplayer2.upstream.Allocator;
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
|
||||||
import com.google.android.exoplayer2.upstream.Loader;
|
import com.google.android.exoplayer2.upstream.Loader;
|
||||||
import com.google.android.exoplayer2.upstream.Loader.Loadable;
|
import com.google.android.exoplayer2.upstream.Loader.Loadable;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
@ -72,6 +72,7 @@ public final class RtspMediaPeriod implements MediaPeriod {
|
|||||||
|
|
||||||
private final InternalListener internalListener;
|
private final InternalListener internalListener;
|
||||||
private final RtspClient rtspClient;
|
private final RtspClient rtspClient;
|
||||||
|
private final RtpDataChannel.Factory rtpDataChannelFactory;
|
||||||
private final List<RtspLoaderWrapper> rtspLoaderWrappers;
|
private final List<RtspLoaderWrapper> rtspLoaderWrappers;
|
||||||
private final List<RtpLoadInfo> selectedLoadInfos;
|
private final List<RtpLoadInfo> selectedLoadInfos;
|
||||||
|
|
||||||
@ -93,9 +94,13 @@ public final class RtspMediaPeriod implements MediaPeriod {
|
|||||||
* @param allocator An {@link Allocator} from which to obtain media buffer allocations.
|
* @param allocator An {@link Allocator} from which to obtain media buffer allocations.
|
||||||
* @param rtspTracks A list of tracks in an RTSP playback session.
|
* @param rtspTracks A list of tracks in an RTSP playback session.
|
||||||
* @param rtspClient The {@link RtspClient} for the current RTSP playback.
|
* @param rtspClient The {@link RtspClient} for the current RTSP playback.
|
||||||
|
* @param rtpDataChannelFactory A {@link RtpDataChannel.Factory} for {@link RtpDataChannel}.
|
||||||
*/
|
*/
|
||||||
public RtspMediaPeriod(
|
public RtspMediaPeriod(
|
||||||
Allocator allocator, List<RtspMediaTrack> rtspTracks, RtspClient rtspClient) {
|
Allocator allocator,
|
||||||
|
List<RtspMediaTrack> rtspTracks,
|
||||||
|
RtspClient rtspClient,
|
||||||
|
RtpDataChannel.Factory rtpDataChannelFactory) {
|
||||||
this.allocator = allocator;
|
this.allocator = allocator;
|
||||||
handler = Util.createHandlerForCurrentLooper();
|
handler = Util.createHandlerForCurrentLooper();
|
||||||
|
|
||||||
@ -103,6 +108,7 @@ public final class RtspMediaPeriod implements MediaPeriod {
|
|||||||
rtspLoaderWrappers = new ArrayList<>(rtspTracks.size());
|
rtspLoaderWrappers = new ArrayList<>(rtspTracks.size());
|
||||||
this.rtspClient = rtspClient;
|
this.rtspClient = rtspClient;
|
||||||
this.rtspClient.setPlaybackEventListener(internalListener);
|
this.rtspClient.setPlaybackEventListener(internalListener);
|
||||||
|
this.rtpDataChannelFactory = rtpDataChannelFactory;
|
||||||
|
|
||||||
for (int i = 0; i < rtspTracks.size(); i++) {
|
for (int i = 0; i < rtspTracks.size(); i++) {
|
||||||
RtspMediaTrack rtspMediaTrack = rtspTracks.get(i);
|
RtspMediaTrack rtspMediaTrack = rtspTracks.get(i);
|
||||||
@ -506,7 +512,7 @@ public final class RtspMediaPeriod implements MediaPeriod {
|
|||||||
playbackException = error;
|
playbackException = error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Handles the {@link Loadable} whose {@link DataSource} timed out. */
|
/** Handles the {@link Loadable} whose {@link RtpDataChannel} timed out. */
|
||||||
private void handleSocketTimeout(RtpDataLoadable loadable) {
|
private void handleSocketTimeout(RtpDataLoadable loadable) {
|
||||||
// TODO(b/172331505) Allow for retry when loading is not ending.
|
// TODO(b/172331505) Allow for retry when loading is not ending.
|
||||||
if (getBufferedPositionUs() == Long.MIN_VALUE) {
|
if (getBufferedPositionUs() == Long.MIN_VALUE) {
|
||||||
@ -648,7 +654,8 @@ public final class RtspMediaPeriod implements MediaPeriod {
|
|||||||
trackId,
|
trackId,
|
||||||
mediaTrack,
|
mediaTrack,
|
||||||
/* eventListener= */ transportEventListener,
|
/* eventListener= */ transportEventListener,
|
||||||
/* output= */ internalListener);
|
/* output= */ internalListener,
|
||||||
|
rtpDataChannelFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,6 +31,7 @@ import com.google.android.exoplayer2.source.MediaSource;
|
|||||||
import com.google.android.exoplayer2.source.MediaSourceFactory;
|
import com.google.android.exoplayer2.source.MediaSourceFactory;
|
||||||
import com.google.android.exoplayer2.source.SinglePeriodTimeline;
|
import com.google.android.exoplayer2.source.SinglePeriodTimeline;
|
||||||
import com.google.android.exoplayer2.source.rtsp.RtspClient.SessionInfoListener;
|
import com.google.android.exoplayer2.source.rtsp.RtspClient.SessionInfoListener;
|
||||||
|
import com.google.android.exoplayer2.source.rtsp.rtp.RtpDataChannel;
|
||||||
import com.google.android.exoplayer2.upstream.Allocator;
|
import com.google.android.exoplayer2.upstream.Allocator;
|
||||||
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
||||||
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
|
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy;
|
||||||
@ -131,6 +132,7 @@ public final class RtspMediaSource extends BaseMediaSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final MediaItem mediaItem;
|
private final MediaItem mediaItem;
|
||||||
|
private final RtpDataChannel.Factory rtpDataChannelFactory;
|
||||||
private @MonotonicNonNull RtspClient rtspClient;
|
private @MonotonicNonNull RtspClient rtspClient;
|
||||||
|
|
||||||
@Nullable private ImmutableList<RtspMediaTrack> rtspMediaTracks;
|
@Nullable private ImmutableList<RtspMediaTrack> rtspMediaTracks;
|
||||||
@ -138,6 +140,7 @@ public final class RtspMediaSource extends BaseMediaSource {
|
|||||||
|
|
||||||
private RtspMediaSource(MediaItem mediaItem) {
|
private RtspMediaSource(MediaItem mediaItem) {
|
||||||
this.mediaItem = mediaItem;
|
this.mediaItem = mediaItem;
|
||||||
|
rtpDataChannelFactory = RtpDataChannel.DEFAULT_FACTORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -174,7 +177,8 @@ public final class RtspMediaSource extends BaseMediaSource {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
|
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs) {
|
||||||
return new RtspMediaPeriod(allocator, checkNotNull(rtspMediaTracks), checkNotNull(rtspClient));
|
return new RtspMediaPeriod(
|
||||||
|
allocator, checkNotNull(rtspMediaTracks), checkNotNull(rtspClient), rtpDataChannelFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.google.android.exoplayer2.source.rtsp.rtp;
|
||||||
|
|
||||||
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
|
|
||||||
|
/** An RTP {@link DataSource}. */
|
||||||
|
public interface RtpDataChannel extends DataSource {
|
||||||
|
|
||||||
|
/** Creates {@link RtpDataChannel} for RTSP streams. */
|
||||||
|
interface Factory {
|
||||||
|
|
||||||
|
/** Creates a new {@link RtpDataChannel} instance. */
|
||||||
|
RtpDataChannel createDataChannel();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The default {@link Factory} that returns a new {@link UdpDataSourceRtpDataChannel}. */
|
||||||
|
Factory DEFAULT_FACTORY = UdpDataSourceRtpDataChannel::new;
|
||||||
|
|
||||||
|
/** Returns the local port used in the underlying transport channel. */
|
||||||
|
int getLocalPort();
|
||||||
|
}
|
@ -30,7 +30,6 @@ import com.google.android.exoplayer2.extractor.PositionHolder;
|
|||||||
import com.google.android.exoplayer2.source.rtsp.RtspMediaTrack;
|
import com.google.android.exoplayer2.source.rtsp.RtspMediaTrack;
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
import com.google.android.exoplayer2.upstream.Loader;
|
import com.google.android.exoplayer2.upstream.Loader;
|
||||||
import com.google.android.exoplayer2.upstream.UdpDataSource;
|
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
@ -39,10 +38,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
* A {@link Loader.Loadable} that sets up a sockets listening to incoming RTP traffic, carried by
|
* A {@link Loader.Loadable} that sets up a sockets listening to incoming RTP traffic, carried by
|
||||||
* UDP packets.
|
* UDP packets.
|
||||||
*
|
*
|
||||||
* <p>Uses a {@link UdpDataSource} to listen on incoming packets. The local UDP port is selected by
|
* <p>Uses a {@link RtpDataChannel} to listen on incoming packets. The local UDP port is selected by
|
||||||
* the runtime on opening; it also opens another {@link UdpDataSource} for RTCP on the RTP UDP port
|
* the runtime on opening; it also opens another {@link RtpDataChannel} for RTCP on the RTP UDP port
|
||||||
* number plus one one. Pass a listener via constructor to receive a callback when the local port is
|
* number plus one one. Pass a listener via constructor to receive a callback when the local port is
|
||||||
* opened. {@link #load} will throw an {@link IOException} if either of the two data sources fails
|
* opened. {@link #load} will throw an {@link IOException} if either of the two data channels fails
|
||||||
* to open.
|
* to open.
|
||||||
*
|
*
|
||||||
* <p>Received RTP packets' payloads will be extracted by an {@link RtpExtractor}, and will be
|
* <p>Received RTP packets' payloads will be extracted by an {@link RtpExtractor}, and will be
|
||||||
@ -76,6 +75,7 @@ public final class RtpDataLoadable implements Loader.Loadable {
|
|||||||
private final EventListener eventListener;
|
private final EventListener eventListener;
|
||||||
private final ExtractorOutput output;
|
private final ExtractorOutput output;
|
||||||
private final Handler playbackThreadHandler;
|
private final Handler playbackThreadHandler;
|
||||||
|
private final RtpDataChannel.Factory rtpDataChannelFactory;
|
||||||
|
|
||||||
private @MonotonicNonNull RtpExtractor extractor;
|
private @MonotonicNonNull RtpExtractor extractor;
|
||||||
|
|
||||||
@ -92,17 +92,20 @@ public final class RtpDataLoadable implements Loader.Loadable {
|
|||||||
* @param rtspMediaTrack The {@link RtspMediaTrack} to load.
|
* @param rtspMediaTrack The {@link RtspMediaTrack} to load.
|
||||||
* @param eventListener The {@link EventListener}.
|
* @param eventListener The {@link EventListener}.
|
||||||
* @param output A {@link ExtractorOutput} instance to which the received and extracted data will
|
* @param output A {@link ExtractorOutput} instance to which the received and extracted data will
|
||||||
|
* @param rtpDataChannelFactory A {@link RtpDataChannel.Factory} for {@link RtpDataChannel}.
|
||||||
*/
|
*/
|
||||||
public RtpDataLoadable(
|
public RtpDataLoadable(
|
||||||
int trackId,
|
int trackId,
|
||||||
RtspMediaTrack rtspMediaTrack,
|
RtspMediaTrack rtspMediaTrack,
|
||||||
EventListener eventListener,
|
EventListener eventListener,
|
||||||
ExtractorOutput output) {
|
ExtractorOutput output,
|
||||||
|
RtpDataChannel.Factory rtpDataChannelFactory) {
|
||||||
this.trackId = trackId;
|
this.trackId = trackId;
|
||||||
this.rtspMediaTrack = rtspMediaTrack;
|
this.rtspMediaTrack = rtspMediaTrack;
|
||||||
this.eventListener = eventListener;
|
this.eventListener = eventListener;
|
||||||
this.output = output;
|
this.output = output;
|
||||||
this.playbackThreadHandler = Util.createHandlerForCurrentLooper();
|
this.playbackThreadHandler = Util.createHandlerForCurrentLooper();
|
||||||
|
this.rtpDataChannelFactory = rtpDataChannelFactory;
|
||||||
pendingSeekPositionUs = C.TIME_UNSET;
|
pendingSeekPositionUs = C.TIME_UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,30 +142,30 @@ public final class RtpDataLoadable implements Loader.Loadable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() throws IOException {
|
public void load() throws IOException {
|
||||||
@Nullable UdpDataSource firstDataSource = null;
|
@Nullable RtpDataChannel firstDataChannel = null;
|
||||||
@Nullable UdpDataSource secondDataSource = null;
|
@Nullable RtpDataChannel secondDataChannel = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Open and set up the data sources.
|
// Open and set up the data channel.
|
||||||
// From RFC3550 Section 11: "For UDP and similar protocols, RTP SHOULD use an even destination
|
// From RFC3550 Section 11: "For UDP and similar protocols, RTP SHOULD use an even destination
|
||||||
// port number and the corresponding RTCP stream SHOULD use the next higher (odd) destination
|
// port number and the corresponding RTCP stream SHOULD use the next higher (odd) destination
|
||||||
// port number". Some RTSP servers are strict about this rule.
|
// port number". Some RTSP servers are strict about this rule. We open a data channel first,
|
||||||
// We open a data source first, and depending its port number, open the next data source with
|
// and depending its port number, open the next data channel with a port number that is either
|
||||||
// a port number that is either the higher or the lower.
|
// the higher or the lower.
|
||||||
firstDataSource = new UdpDataSource();
|
firstDataChannel = rtpDataChannelFactory.createDataChannel();
|
||||||
firstDataSource.open(new DataSpec(Uri.parse(RTP_BIND_ADDRESS)));
|
firstDataChannel.open(new DataSpec(Uri.parse(RTP_BIND_ADDRESS)));
|
||||||
|
|
||||||
int firstPort = firstDataSource.getLocalPort();
|
int firstPort = firstDataChannel.getLocalPort();
|
||||||
boolean isFirstPortNumberEven = (firstPort % 2 == 0);
|
boolean isFirstPortNumberEven = (firstPort % 2 == 0);
|
||||||
int secondPort = isFirstPortNumberEven ? firstPort + 1 : firstPort - 1;
|
int secondPort = isFirstPortNumberEven ? firstPort + 1 : firstPort - 1;
|
||||||
|
|
||||||
// RTCP always uses the immediate next port.
|
// RTCP always uses the immediate next port.
|
||||||
secondDataSource = new UdpDataSource();
|
secondDataChannel = rtpDataChannelFactory.createDataChannel();
|
||||||
secondDataSource.open(new DataSpec(Uri.parse(RTP_ANY_INCOMING_IPV4 + ":" + secondPort)));
|
secondDataChannel.open(new DataSpec(Uri.parse(RTP_ANY_INCOMING_IPV4 + ":" + secondPort)));
|
||||||
|
|
||||||
// RTP data port is always the lower and even-numbered port.
|
// RTP data port is always the lower and even-numbered port.
|
||||||
UdpDataSource dataSource = isFirstPortNumberEven ? firstDataSource : secondDataSource;
|
RtpDataChannel dataChannel = isFirstPortNumberEven ? firstDataChannel : secondDataChannel;
|
||||||
int dataPort = dataSource.getLocalPort();
|
int dataPort = dataChannel.getLocalPort();
|
||||||
int rtcpPort = dataPort + 1;
|
int rtcpPort = dataPort + 1;
|
||||||
String transport = Util.formatInvariant(DEFAULT_TRANSPORT_FORMAT, dataPort, rtcpPort);
|
String transport = Util.formatInvariant(DEFAULT_TRANSPORT_FORMAT, dataPort, rtcpPort);
|
||||||
playbackThreadHandler.post(() -> eventListener.onTransportReady(transport));
|
playbackThreadHandler.post(() -> eventListener.onTransportReady(transport));
|
||||||
@ -170,7 +173,7 @@ public final class RtpDataLoadable implements Loader.Loadable {
|
|||||||
// Sets up the extractor.
|
// Sets up the extractor.
|
||||||
ExtractorInput extractorInput =
|
ExtractorInput extractorInput =
|
||||||
new DefaultExtractorInput(
|
new DefaultExtractorInput(
|
||||||
checkNotNull(dataSource), /* position= */ 0, /* length= */ C.LENGTH_UNSET);
|
checkNotNull(dataChannel), /* position= */ 0, /* length= */ C.LENGTH_UNSET);
|
||||||
extractor = new RtpExtractor(rtspMediaTrack.payloadFormat, trackId);
|
extractor = new RtpExtractor(rtspMediaTrack.payloadFormat, trackId);
|
||||||
extractor.init(output);
|
extractor.init(output);
|
||||||
|
|
||||||
@ -183,8 +186,8 @@ public final class RtpDataLoadable implements Loader.Loadable {
|
|||||||
extractor.read(extractorInput, /* seekPosition= */ new PositionHolder());
|
extractor.read(extractorInput, /* seekPosition= */ new PositionHolder());
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
closeQuietly(firstDataSource);
|
closeQuietly(firstDataChannel);
|
||||||
closeQuietly(secondDataSource);
|
closeQuietly(secondDataChannel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.google.android.exoplayer2.source.rtsp.rtp;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
|
import com.google.android.exoplayer2.upstream.TransferListener;
|
||||||
|
import com.google.android.exoplayer2.upstream.UdpDataSource;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/** An {@link RtpDataChannel} for UDP transport. */
|
||||||
|
public final class UdpDataSourceRtpDataChannel implements RtpDataChannel {
|
||||||
|
private final UdpDataSource dataSource;
|
||||||
|
|
||||||
|
/** Creates a new instance. */
|
||||||
|
public UdpDataSourceRtpDataChannel() {
|
||||||
|
dataSource = new UdpDataSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLocalPort() {
|
||||||
|
return dataSource.getLocalPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addTransferListener(TransferListener transferListener) {
|
||||||
|
dataSource.addTransferListener(transferListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long open(DataSpec dataSpec) throws IOException {
|
||||||
|
return dataSource.open(dataSpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Uri getUri() {
|
||||||
|
return dataSource.getUri();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
dataSource.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read(byte[] target, int offset, int length) throws IOException {
|
||||||
|
return dataSource.read(target, offset, length);
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,7 @@ import androidx.annotation.Nullable;
|
|||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.source.MediaPeriod;
|
import com.google.android.exoplayer2.source.MediaPeriod;
|
||||||
|
import com.google.android.exoplayer2.source.rtsp.rtp.RtpDataChannel;
|
||||||
import com.google.android.exoplayer2.source.rtsp.sdp.MediaDescription;
|
import com.google.android.exoplayer2.source.rtsp.sdp.MediaDescription;
|
||||||
import com.google.android.exoplayer2.source.rtsp.sdp.SessionDescription;
|
import com.google.android.exoplayer2.source.rtsp.sdp.SessionDescription;
|
||||||
import com.google.android.exoplayer2.upstream.DefaultAllocator;
|
import com.google.android.exoplayer2.upstream.DefaultAllocator;
|
||||||
@ -68,7 +69,8 @@ public class RtspMediaPeriodTest {
|
|||||||
.addAttribute(SessionDescription.ATTR_CONTROL, "track1")
|
.addAttribute(SessionDescription.ATTR_CONTROL, "track1")
|
||||||
.build(),
|
.build(),
|
||||||
Uri.parse("rtsp://localhost/test"))),
|
Uri.parse("rtsp://localhost/test"))),
|
||||||
PLACEHOLDER_RTSP_CLIENT);
|
PLACEHOLDER_RTSP_CLIENT,
|
||||||
|
RtpDataChannel.DEFAULT_FACTORY);
|
||||||
|
|
||||||
AtomicBoolean prepareCallbackCalled = new AtomicBoolean(false);
|
AtomicBoolean prepareCallbackCalled = new AtomicBoolean(false);
|
||||||
rtspMediaPeriod.prepare(
|
rtspMediaPeriod.prepare(
|
||||||
@ -95,7 +97,8 @@ public class RtspMediaPeriodTest {
|
|||||||
new RtspMediaPeriod(
|
new RtspMediaPeriod(
|
||||||
new DefaultAllocator(/* trimOnReset= */ true, C.DEFAULT_BUFFER_SEGMENT_SIZE),
|
new DefaultAllocator(/* trimOnReset= */ true, C.DEFAULT_BUFFER_SEGMENT_SIZE),
|
||||||
ImmutableList.of(),
|
ImmutableList.of(),
|
||||||
PLACEHOLDER_RTSP_CLIENT);
|
PLACEHOLDER_RTSP_CLIENT,
|
||||||
|
RtpDataChannel.DEFAULT_FACTORY);
|
||||||
|
|
||||||
assertThat(rtspMediaPeriod.getBufferedPositionUs()).isEqualTo(C.TIME_END_OF_SOURCE);
|
assertThat(rtspMediaPeriod.getBufferedPositionUs()).isEqualTo(C.TIME_END_OF_SOURCE);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user