diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/MediaDescription.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/MediaDescription.java index e4467d395e..3998e67331 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/MediaDescription.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/MediaDescription.java @@ -232,7 +232,6 @@ import java.lang.annotation.RetentionPolicy; public final int bitrate; /** The assigned media title. */ @Nullable public final String mediaTitle; - // TODO(internal b/172331505) Parse the String representations into objects. /** The connection parameters. */ @Nullable public final String connection; /** The encryption parameter. */ diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtpExtractor.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtpExtractor.java index 50894a45f5..73fb3758d5 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtpExtractor.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtpExtractor.java @@ -106,15 +106,15 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @Override public boolean sniff(ExtractorInput input) { - // TODO(b/172331505) Build sniff support. - return false; + throw new UnsupportedOperationException( + "RTP packets are transmitted in a packet stream do not support sniffing."); } @Override public void init(ExtractorOutput output) { payloadReader.createTracks(output, trackId); output.endTracks(); - // TODO(b/172331505) replace hardcoded unseekable seekmap. + // RTP does not embed duration or seek info. output.seekMap(new SeekMap.Unseekable(C.TIME_UNSET)); this.output = output; } diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtpPacketReorderingQueue.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtpPacketReorderingQueue.java index 1f1cb79595..3e92c7ef85 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtpPacketReorderingQueue.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtpPacketReorderingQueue.java @@ -36,8 +36,10 @@ import java.util.TreeSet; private static final int MAX_SEQUENCE_NUMBER = RtpPacket.MAX_SEQUENCE_NUMBER; + /** Queue size threshold for resetting the queue. 5000 packets equate about 7MB in buffer size. */ + private static final int QUEUE_SIZE_THRESHOLD_FOR_RESET = 5000; + // Use set to eliminate duplicating packets. - // TODO(b/172331505) Set a upper limit on packetQueue to mitigate out of memory error. @GuardedBy("this") private final TreeSet packetQueue; @@ -86,6 +88,11 @@ import java.util.TreeSet; * returns {@code true}). */ public synchronized boolean offer(RtpPacket packet, long receivedTimestampMs) { + if (packetQueue.size() >= QUEUE_SIZE_THRESHOLD_FOR_RESET) { + throw new IllegalStateException( + "Queue size limit of " + QUEUE_SIZE_THRESHOLD_FOR_RESET + " reached."); + } + int packetSequenceNumber = packet.sequenceNumber; if (!started) { reset(); diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaPeriod.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaPeriod.java index 19ce014c2b..cb288fc427 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaPeriod.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMediaPeriod.java @@ -420,12 +420,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @Override public void endTracks() { - // TODO(b/172331505) Implement this method. + handler.post(RtspMediaPeriod.this::maybeFinishPrepare); } @Override public void seekMap(SeekMap seekMap) { - // TODO(b/172331505) Implement this method. + // RTSP does not support seek map. } // Loadable.Callback implementation. @@ -445,16 +445,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; long loadDurationMs, IOException error, int errorCount) { - /* TODO(b/172331505) Sort out the retry policy. - Three cases for IOException: - - Socket open failure for RTP or RTCP. - - RETRY for the RTCP open failure. - - ExtractorInput read IOException (socket timeout, etc) - - Keep retrying unless playback is stopped. - - RtpPayloadReader consume ParserException (mal-formatted RTP packet) - - Don't retry? (if a packet is distorted on the fly, the packet is likely discarded by the - system, i.e. the server's sent a mal-formatted packet). - */ if (!prepared) { preparationError = error; } else { diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMessageChannel.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMessageChannel.java index d45af667dc..526f508953 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMessageChannel.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspMessageChannel.java @@ -279,7 +279,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @Override public void load() throws IOException { while (!loadCanceled) { - // TODO(internal b/172331505) Use a buffered read. byte firstByte = dataInputStream.readByte(); if (firstByte == INTERLEAVED_MESSAGE_MARKER) { handleInterleavedBinaryData(); diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspOptionsResponse.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspOptionsResponse.java index 989303b461..6a3403c797 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspOptionsResponse.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspOptionsResponse.java @@ -19,8 +19,6 @@ import com.google.common.collect.ImmutableList; import java.util.List; /** Represents an RTSP OPTIONS response. */ -// TODO(b/180434754) Move all classes under message to the parent rtsp package, and change the -// visibility. /* package */ final class RtspOptionsResponse { /** The response's status code. */ public final int status; diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspResponse.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspResponse.java index 38a7f9a7e0..ec15fa7556 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspResponse.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspResponse.java @@ -18,9 +18,6 @@ package com.google.android.exoplayer2.source.rtsp; /** Represents an RTSP Response. */ /* package */ final class RtspResponse { - // TODO(b/172331505) Move this constant to MimeTypes. - /** The MIME type associated with Session Description Protocol (RFC4566). */ - public static final String SDP_MIME_TYPE = "application/sdp"; /** The status code of this response, as defined in RFC 2326 section 11. */ public final int status; diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspSetupResponse.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspSetupResponse.java index 03d1698b8b..5f4cf51b4b 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspSetupResponse.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/RtspSetupResponse.java @@ -16,8 +16,6 @@ package com.google.android.exoplayer2.source.rtsp; /** Represents an RTSP SETUP response. */ -// TODO(b/180434754) Move all classes under message to the parent rtsp package, and change the -// visibility. /* package */ final class RtspSetupResponse { /** The response's status code. */ diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/SessionDescription.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/SessionDescription.java index 4ac138f554..ea745b4abe 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/SessionDescription.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/SessionDescription.java @@ -237,7 +237,6 @@ import com.google.common.collect.ImmutableMap; public final ImmutableList mediaDescriptionList; /** The name of a session. */ public final String sessionName; - // TODO(internal b/172331505) Parse the String representations into objects. /** The origin sender info. */ public final String origin; /** The timing info. */ diff --git a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/reader/RtpH264Reader.java b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/reader/RtpH264Reader.java index bd7bfb4496..cad99f8d05 100644 --- a/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/reader/RtpH264Reader.java +++ b/library/rtsp/src/main/java/com/google/android/exoplayer2/source/rtsp/reader/RtpH264Reader.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.source.rtsp.reader; +import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull; import static com.google.android.exoplayer2.util.Util.castNonNull; @@ -35,10 +36,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; /* package */ final class RtpH264Reader implements RtpPayloadReader { private static final String TAG = "RtpH264Reader"; - // TODO(b/172331505) Move NAL related constants to NalUnitUtil. - private static final ParsableByteArray NAL_START_CODE = - new ParsableByteArray(NalUnitUtil.NAL_START_CODE); - private static final int NAL_START_CODE_LENGTH = NalUnitUtil.NAL_START_CODE.length; private static final long MEDIA_CLOCK_FREQUENCY = 90_000; /** Offset of payload data within a FU type A payload. */ @@ -55,6 +52,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; /** Scratch for Fragmentation Unit RTP packets. */ private final ParsableByteArray fuScratchBuffer; + private final ParsableByteArray nalStartCodeArray = + new ParsableByteArray(NalUnitUtil.NAL_START_CODE); + private final RtpPayloadFormat payloadFormat; private @MonotonicNonNull TrackOutput trackOutput; @@ -160,7 +160,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ int numBytesInData = data.bytesLeft(); - fragmentedSampleSizeBytes += writeStartCode(trackOutput); + fragmentedSampleSizeBytes += writeStartCode(); trackOutput.sampleData(data, numBytesInData); fragmentedSampleSizeBytes += numBytesInData; @@ -203,13 +203,12 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; int nalUnitLength; while (data.bytesLeft() > 4) { nalUnitLength = data.readUnsignedShort(); - fragmentedSampleSizeBytes += writeStartCode(trackOutput); + fragmentedSampleSizeBytes += writeStartCode(); trackOutput.sampleData(data, nalUnitLength); fragmentedSampleSizeBytes += nalUnitLength; } // Treat Aggregated NAL units as non key frames. - // TODO(internal b/172331505) examine whether STAP mode carries keyframes. bufferFlags = 0; } @@ -252,7 +251,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; if (isFirstFuPacket) { // Prepends starter code. - fragmentedSampleSizeBytes += writeStartCode(trackOutput); + fragmentedSampleSizeBytes += writeStartCode(); // The bytes needed is 1 (NALU header) + payload size. The original data array has size 2 (FU // indicator/header) + payload size. Thus setting the correct header and set position to 1. @@ -286,6 +285,13 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } } + private int writeStartCode() { + nalStartCodeArray.setPosition(/* position= */ 0); + int bytesWritten = nalStartCodeArray.bytesLeft(); + checkNotNull(trackOutput).sampleData(nalStartCodeArray, bytesWritten); + return bytesWritten; + } + private static long toSampleUs( long startTimeOffsetUs, long rtpTimestamp, long firstReceivedRtpTimestamp) { return startTimeOffsetUs @@ -295,12 +301,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; /* divisor= */ MEDIA_CLOCK_FREQUENCY); } - private static int writeStartCode(TrackOutput trackOutput) { - trackOutput.sampleData(NAL_START_CODE, NAL_START_CODE_LENGTH); - NAL_START_CODE.setPosition(/* position= */ 0); - return NAL_START_CODE_LENGTH; - } - @C.BufferFlags private static int getBufferFlagsFromNalType(int nalType) { return nalType == NAL_UNIT_TYPE_IDR ? C.BUFFER_FLAG_KEY_FRAME : 0;