Factor out RTP timestamp to sample time method
PiperOrigin-RevId: 465337074 (cherry picked from commit 80ec64696e22856ce324ef03535754f838a49778)
This commit is contained in:
parent
35565cfea7
commit
e57a36bb20
@ -16,6 +16,7 @@
|
|||||||
package androidx.media3.exoplayer.rtsp.reader;
|
package androidx.media3.exoplayer.rtsp.reader;
|
||||||
|
|
||||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
|
import static androidx.media3.exoplayer.rtsp.reader.RtpReaderUtils.toSampleTimeUs;
|
||||||
|
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.util.ParsableBitArray;
|
import androidx.media3.common.util.ParsableBitArray;
|
||||||
@ -153,14 +154,4 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
trackOutput.sampleMetadata(
|
trackOutput.sampleMetadata(
|
||||||
sampleTimeUs, C.BUFFER_FLAG_KEY_FRAME, size, /* offset= */ 0, /* cryptoData= */ null);
|
sampleTimeUs, C.BUFFER_FLAG_KEY_FRAME, size, /* offset= */ 0, /* cryptoData= */ null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the correct sample time from RTP timestamp, accounting for the AAC sampling rate. */
|
|
||||||
private static long toSampleTimeUs(
|
|
||||||
long startTimeOffsetUs, long rtpTimestamp, long firstReceivedRtpTimestamp, int sampleRate) {
|
|
||||||
return startTimeOffsetUs
|
|
||||||
+ Util.scaleLargeTimestamp(
|
|
||||||
rtpTimestamp - firstReceivedRtpTimestamp,
|
|
||||||
/* multiplier= */ C.MICROS_PER_SECOND,
|
|
||||||
/* divisor= */ sampleRate);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -18,12 +18,12 @@ package androidx.media3.exoplayer.rtsp.reader;
|
|||||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
import static androidx.media3.common.util.Assertions.checkState;
|
import static androidx.media3.common.util.Assertions.checkState;
|
||||||
import static androidx.media3.common.util.Util.castNonNull;
|
import static androidx.media3.common.util.Util.castNonNull;
|
||||||
|
import static androidx.media3.exoplayer.rtsp.reader.RtpReaderUtils.toSampleTimeUs;
|
||||||
|
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.util.ParsableBitArray;
|
import androidx.media3.common.util.ParsableBitArray;
|
||||||
import androidx.media3.common.util.ParsableByteArray;
|
import androidx.media3.common.util.ParsableByteArray;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
import androidx.media3.common.util.Util;
|
|
||||||
import androidx.media3.exoplayer.rtsp.RtpPayloadFormat;
|
import androidx.media3.exoplayer.rtsp.RtpPayloadFormat;
|
||||||
import androidx.media3.extractor.Ac3Util;
|
import androidx.media3.extractor.Ac3Util;
|
||||||
import androidx.media3.extractor.ExtractorOutput;
|
import androidx.media3.extractor.ExtractorOutput;
|
||||||
@ -208,14 +208,4 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
/* cryptoData= */ null);
|
/* cryptoData= */ null);
|
||||||
numBytesPendingMetadataOutput = 0;
|
numBytesPendingMetadataOutput = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the correct sample time from RTP timestamp, accounting for the AC3 sampling rate. */
|
|
||||||
private static long toSampleTimeUs(
|
|
||||||
long startTimeOffsetUs, long rtpTimestamp, long firstReceivedRtpTimestamp, int sampleRate) {
|
|
||||||
return startTimeOffsetUs
|
|
||||||
+ Util.scaleLargeTimestamp(
|
|
||||||
rtpTimestamp - firstReceivedRtpTimestamp,
|
|
||||||
/* multiplier= */ C.MICROS_PER_SECOND,
|
|
||||||
/* divisor= */ sampleRate);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ package androidx.media3.exoplayer.rtsp.reader;
|
|||||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||||
|
import static androidx.media3.exoplayer.rtsp.reader.RtpReaderUtils.toSampleTimeUs;
|
||||||
|
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.MimeTypes;
|
import androidx.media3.common.MimeTypes;
|
||||||
@ -183,14 +184,4 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
? AMR_WB_FRAME_TYPE_INDEX_TO_FRAME_SIZE[frameType]
|
? AMR_WB_FRAME_TYPE_INDEX_TO_FRAME_SIZE[frameType]
|
||||||
: AMR_NB_FRAME_TYPE_INDEX_TO_FRAME_SIZE[frameType];
|
: AMR_NB_FRAME_TYPE_INDEX_TO_FRAME_SIZE[frameType];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the correct sample time from RTP timestamp, accounting for the AMR sampling rate. */
|
|
||||||
private static long toSampleTimeUs(
|
|
||||||
long startTimeOffsetUs, long rtpTimestamp, long firstReceivedRtpTimestamp, int sampleRate) {
|
|
||||||
return startTimeOffsetUs
|
|
||||||
+ Util.scaleLargeTimestamp(
|
|
||||||
rtpTimestamp - firstReceivedRtpTimestamp,
|
|
||||||
/* multiplier= */ C.MICROS_PER_SECOND,
|
|
||||||
/* divisor= */ sampleRate);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ package androidx.media3.exoplayer.rtsp.reader;
|
|||||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
import static androidx.media3.common.util.Assertions.checkState;
|
import static androidx.media3.common.util.Assertions.checkState;
|
||||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||||
|
import static androidx.media3.exoplayer.rtsp.reader.RtpReaderUtils.toSampleTimeUs;
|
||||||
|
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.util.Log;
|
import androidx.media3.common.util.Log;
|
||||||
@ -35,7 +36,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
/* package */ final class RtpH263Reader implements RtpPayloadReader {
|
/* package */ final class RtpH263Reader implements RtpPayloadReader {
|
||||||
private static final String TAG = "RtpH263Reader";
|
private static final String TAG = "RtpH263Reader";
|
||||||
|
|
||||||
private static final long MEDIA_CLOCK_FREQUENCY = 90_000;
|
private static final int MEDIA_CLOCK_FREQUENCY = 90_000;
|
||||||
|
|
||||||
/** I-frame VOP unit type. */
|
/** I-frame VOP unit type. */
|
||||||
private static final int I_VOP = 0;
|
private static final int I_VOP = 0;
|
||||||
@ -164,7 +165,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
// Write the video sample.
|
// Write the video sample.
|
||||||
trackOutput.sampleData(data, fragmentSize);
|
trackOutput.sampleData(data, fragmentSize);
|
||||||
fragmentedSampleSizeBytes += fragmentSize;
|
fragmentedSampleSizeBytes += fragmentSize;
|
||||||
fragmentedSampleTimeUs = toSampleUs(startTimeOffsetUs, timestamp, firstReceivedTimestamp);
|
fragmentedSampleTimeUs =
|
||||||
|
toSampleTimeUs(startTimeOffsetUs, timestamp, firstReceivedTimestamp, MEDIA_CLOCK_FREQUENCY);
|
||||||
|
|
||||||
if (rtpMarker) {
|
if (rtpMarker) {
|
||||||
outputSampleMetadataForFragmentedPackets();
|
outputSampleMetadataForFragmentedPackets();
|
||||||
@ -242,13 +244,4 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
isKeyFrame = false;
|
isKeyFrame = false;
|
||||||
gotFirstPacketOfH263Frame = false;
|
gotFirstPacketOfH263Frame = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long toSampleUs(
|
|
||||||
long startTimeOffsetUs, long rtpTimestamp, long firstReceivedRtpTimestamp) {
|
|
||||||
return startTimeOffsetUs
|
|
||||||
+ Util.scaleLargeTimestamp(
|
|
||||||
(rtpTimestamp - firstReceivedRtpTimestamp),
|
|
||||||
/* multiplier= */ C.MICROS_PER_SECOND,
|
|
||||||
/* divisor= */ MEDIA_CLOCK_FREQUENCY);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ package androidx.media3.exoplayer.rtsp.reader;
|
|||||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||||
import static androidx.media3.common.util.Util.castNonNull;
|
import static androidx.media3.common.util.Util.castNonNull;
|
||||||
|
import static androidx.media3.exoplayer.rtsp.reader.RtpReaderUtils.toSampleTimeUs;
|
||||||
|
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.ParserException;
|
import androidx.media3.common.ParserException;
|
||||||
@ -36,7 +37,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
/* package */ final class RtpH264Reader implements RtpPayloadReader {
|
/* package */ final class RtpH264Reader implements RtpPayloadReader {
|
||||||
private static final String TAG = "RtpH264Reader";
|
private static final String TAG = "RtpH264Reader";
|
||||||
|
|
||||||
private static final long MEDIA_CLOCK_FREQUENCY = 90_000;
|
private static final int MEDIA_CLOCK_FREQUENCY = 90_000;
|
||||||
|
|
||||||
/** Offset of payload data within a FU type A payload. */
|
/** Offset of payload data within a FU type A payload. */
|
||||||
private static final int FU_PAYLOAD_OFFSET = 2;
|
private static final int FU_PAYLOAD_OFFSET = 2;
|
||||||
@ -115,7 +116,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
firstReceivedTimestamp = timestamp;
|
firstReceivedTimestamp = timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
long timeUs = toSampleUs(startTimeOffsetUs, timestamp, firstReceivedTimestamp);
|
long timeUs =
|
||||||
|
toSampleTimeUs(
|
||||||
|
startTimeOffsetUs, timestamp, firstReceivedTimestamp, MEDIA_CLOCK_FREQUENCY);
|
||||||
trackOutput.sampleMetadata(
|
trackOutput.sampleMetadata(
|
||||||
timeUs, bufferFlags, fragmentedSampleSizeBytes, /* offset= */ 0, /* cryptoData= */ null);
|
timeUs, bufferFlags, fragmentedSampleSizeBytes, /* offset= */ 0, /* cryptoData= */ null);
|
||||||
fragmentedSampleSizeBytes = 0;
|
fragmentedSampleSizeBytes = 0;
|
||||||
@ -287,15 +290,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
return bytesWritten;
|
return bytesWritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long toSampleUs(
|
|
||||||
long startTimeOffsetUs, long rtpTimestamp, long firstReceivedRtpTimestamp) {
|
|
||||||
return startTimeOffsetUs
|
|
||||||
+ Util.scaleLargeTimestamp(
|
|
||||||
(rtpTimestamp - firstReceivedRtpTimestamp),
|
|
||||||
/* multiplier= */ C.MICROS_PER_SECOND,
|
|
||||||
/* divisor= */ MEDIA_CLOCK_FREQUENCY);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static @C.BufferFlags int getBufferFlagsFromNalType(int nalType) {
|
private static @C.BufferFlags int getBufferFlagsFromNalType(int nalType) {
|
||||||
return nalType == NAL_UNIT_TYPE_IDR ? C.BUFFER_FLAG_KEY_FRAME : 0;
|
return nalType == NAL_UNIT_TYPE_IDR ? C.BUFFER_FLAG_KEY_FRAME : 0;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ package androidx.media3.exoplayer.rtsp.reader;
|
|||||||
|
|
||||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||||
|
import static androidx.media3.exoplayer.rtsp.reader.RtpReaderUtils.toSampleTimeUs;
|
||||||
|
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.ParserException;
|
import androidx.media3.common.ParserException;
|
||||||
@ -38,7 +39,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
/* package */ final class RtpH265Reader implements RtpPayloadReader {
|
/* package */ final class RtpH265Reader implements RtpPayloadReader {
|
||||||
|
|
||||||
private static final String TAG = "RtpH265Reader";
|
private static final String TAG = "RtpH265Reader";
|
||||||
private static final long MEDIA_CLOCK_FREQUENCY = 90_000;
|
private static final int MEDIA_CLOCK_FREQUENCY = 90_000;
|
||||||
/** Offset of payload data within a FU payload. */
|
/** Offset of payload data within a FU payload. */
|
||||||
private static final int FU_PAYLOAD_OFFSET = 3;
|
private static final int FU_PAYLOAD_OFFSET = 3;
|
||||||
/** Aggregation Packet. RFC7798 Section 4.4.2. */
|
/** Aggregation Packet. RFC7798 Section 4.4.2. */
|
||||||
@ -111,7 +112,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
firstReceivedTimestamp = timestamp;
|
firstReceivedTimestamp = timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
long timeUs = toSampleUs(startTimeOffsetUs, timestamp, firstReceivedTimestamp);
|
long timeUs =
|
||||||
|
toSampleTimeUs(
|
||||||
|
startTimeOffsetUs, timestamp, firstReceivedTimestamp, MEDIA_CLOCK_FREQUENCY);
|
||||||
trackOutput.sampleMetadata(
|
trackOutput.sampleMetadata(
|
||||||
timeUs, bufferFlags, fragmentedSampleSizeBytes, /* offset= */ 0, /* cryptoData= */ null);
|
timeUs, bufferFlags, fragmentedSampleSizeBytes, /* offset= */ 0, /* cryptoData= */ null);
|
||||||
fragmentedSampleSizeBytes = 0;
|
fragmentedSampleSizeBytes = 0;
|
||||||
@ -254,15 +257,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|||||||
return bytesWritten;
|
return bytesWritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long toSampleUs(
|
|
||||||
long startTimeOffsetUs, long rtpTimestamp, long firstReceivedRtpTimestamp) {
|
|
||||||
return startTimeOffsetUs
|
|
||||||
+ Util.scaleLargeTimestamp(
|
|
||||||
(rtpTimestamp - firstReceivedRtpTimestamp),
|
|
||||||
/* multiplier= */ C.MICROS_PER_SECOND,
|
|
||||||
/* divisor= */ MEDIA_CLOCK_FREQUENCY);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static @C.BufferFlags int getBufferFlagsFromNalType(int nalType) {
|
private static @C.BufferFlags int getBufferFlagsFromNalType(int nalType) {
|
||||||
return (nalType == NAL_IDR_W_RADL || nalType == NAL_IDR_N_LP) ? C.BUFFER_FLAG_KEY_FRAME : 0;
|
return (nalType == NAL_IDR_W_RADL || nalType == NAL_IDR_N_LP) ? C.BUFFER_FLAG_KEY_FRAME : 0;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ package androidx.media3.exoplayer.rtsp.reader;
|
|||||||
|
|
||||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||||
import static androidx.media3.common.util.Util.castNonNull;
|
import static androidx.media3.common.util.Util.castNonNull;
|
||||||
|
import static androidx.media3.exoplayer.rtsp.reader.RtpReaderUtils.toSampleTimeUs;
|
||||||
|
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.util.Log;
|
import androidx.media3.common.util.Log;
|
||||||
@ -38,7 +39,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
/* package */ final class RtpMpeg4Reader implements RtpPayloadReader {
|
/* package */ final class RtpMpeg4Reader implements RtpPayloadReader {
|
||||||
private static final String TAG = "RtpMpeg4Reader";
|
private static final String TAG = "RtpMpeg4Reader";
|
||||||
|
|
||||||
private static final long MEDIA_CLOCK_FREQUENCY = 90_000;
|
private static final int MEDIA_CLOCK_FREQUENCY = 90_000;
|
||||||
|
|
||||||
/** VOP (Video Object Plane) unit type. */
|
/** VOP (Video Object Plane) unit type. */
|
||||||
private static final int I_VOP = 0;
|
private static final int I_VOP = 0;
|
||||||
@ -104,7 +105,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
firstReceivedTimestamp = timestamp;
|
firstReceivedTimestamp = timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
long timeUs = toSampleUs(startTimeOffsetUs, timestamp, firstReceivedTimestamp);
|
long timeUs =
|
||||||
|
toSampleTimeUs(
|
||||||
|
startTimeOffsetUs, timestamp, firstReceivedTimestamp, MEDIA_CLOCK_FREQUENCY);
|
||||||
trackOutput.sampleMetadata(timeUs, bufferFlags, sampleLength, 0, null);
|
trackOutput.sampleMetadata(timeUs, bufferFlags, sampleLength, 0, null);
|
||||||
sampleLength = 0;
|
sampleLength = 0;
|
||||||
}
|
}
|
||||||
@ -137,13 +140,4 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long toSampleUs(
|
|
||||||
long startTimeOffsetUs, long rtpTimestamp, long firstReceivedRtpTimestamp) {
|
|
||||||
return startTimeOffsetUs
|
|
||||||
+ Util.scaleLargeTimestamp(
|
|
||||||
(rtpTimestamp - firstReceivedRtpTimestamp),
|
|
||||||
/* multiplier= */ C.MICROS_PER_SECOND,
|
|
||||||
/* divisor= */ MEDIA_CLOCK_FREQUENCY);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ package androidx.media3.exoplayer.rtsp.reader;
|
|||||||
|
|
||||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||||
|
import static androidx.media3.exoplayer.rtsp.reader.RtpReaderUtils.toSampleTimeUs;
|
||||||
|
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.Format;
|
import androidx.media3.common.Format;
|
||||||
@ -38,7 +39,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
/* package */ final class RtpOpusReader implements RtpPayloadReader {
|
/* package */ final class RtpOpusReader implements RtpPayloadReader {
|
||||||
private static final String TAG = "RtpOpusReader";
|
private static final String TAG = "RtpOpusReader";
|
||||||
/* Opus uses a fixed 48KHz media clock RFC7845 Section 4. */
|
/* Opus uses a fixed 48KHz media clock RFC7845 Section 4. */
|
||||||
private static final long MEDIA_CLOCK_FREQUENCY = 48_000;
|
private static final int MEDIA_CLOCK_FREQUENCY = 48_000;
|
||||||
|
|
||||||
private final RtpPayloadFormat payloadFormat;
|
private final RtpPayloadFormat payloadFormat;
|
||||||
|
|
||||||
@ -113,7 +114,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
// sending opus data.
|
// sending opus data.
|
||||||
int size = data.bytesLeft();
|
int size = data.bytesLeft();
|
||||||
trackOutput.sampleData(data, size);
|
trackOutput.sampleData(data, size);
|
||||||
long timeUs = toSampleTimeUs(startTimeOffsetUs, timestamp, firstReceivedTimestamp);
|
long timeUs =
|
||||||
|
toSampleTimeUs(
|
||||||
|
startTimeOffsetUs, timestamp, firstReceivedTimestamp, MEDIA_CLOCK_FREQUENCY);
|
||||||
trackOutput.sampleMetadata(
|
trackOutput.sampleMetadata(
|
||||||
timeUs, C.BUFFER_FLAG_KEY_FRAME, size, /* offset*/ 0, /* cryptoData*/ null);
|
timeUs, C.BUFFER_FLAG_KEY_FRAME, size, /* offset*/ 0, /* cryptoData*/ null);
|
||||||
}
|
}
|
||||||
@ -144,14 +147,4 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
checkArgument(data.readUnsignedByte() == 1, "version number must always be 1");
|
checkArgument(data.readUnsignedByte() == 1, "version number must always be 1");
|
||||||
data.setPosition(currPosition);
|
data.setPosition(currPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the correct sample time from RTP timestamp, accounting for the OPUS sampling rate. */
|
|
||||||
private static long toSampleTimeUs(
|
|
||||||
long startTimeOffsetUs, long rtpTimestamp, long firstReceivedRtpTimestamp) {
|
|
||||||
return startTimeOffsetUs
|
|
||||||
+ Util.scaleLargeTimestamp(
|
|
||||||
rtpTimestamp - firstReceivedRtpTimestamp,
|
|
||||||
/* multiplier= */ C.MICROS_PER_SECOND,
|
|
||||||
/* divisor= */ MEDIA_CLOCK_FREQUENCY);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package androidx.media3.exoplayer.rtsp.reader;
|
package androidx.media3.exoplayer.rtsp.reader;
|
||||||
|
|
||||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
|
import static androidx.media3.exoplayer.rtsp.reader.RtpReaderUtils.toSampleTimeUs;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
@ -78,7 +79,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
}
|
}
|
||||||
|
|
||||||
long sampleTimeUs =
|
long sampleTimeUs =
|
||||||
toSampleUs(startTimeOffsetUs, timestamp, firstReceivedTimestamp, payloadFormat.clockRate);
|
toSampleTimeUs(
|
||||||
|
startTimeOffsetUs, timestamp, firstReceivedTimestamp, payloadFormat.clockRate);
|
||||||
int size = data.bytesLeft();
|
int size = data.bytesLeft();
|
||||||
trackOutput.sampleData(data, size);
|
trackOutput.sampleData(data, size);
|
||||||
trackOutput.sampleMetadata(
|
trackOutput.sampleMetadata(
|
||||||
@ -93,14 +95,4 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
firstReceivedTimestamp = nextRtpTimestamp;
|
firstReceivedTimestamp = nextRtpTimestamp;
|
||||||
startTimeOffsetUs = timeUs;
|
startTimeOffsetUs = timeUs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the correct sample time from RTP timestamp, accounting for the given clock rate. */
|
|
||||||
private static long toSampleUs(
|
|
||||||
long startTimeOffsetUs, long rtpTimestamp, long firstReceivedRtpTimestamp, int clockRate) {
|
|
||||||
return startTimeOffsetUs
|
|
||||||
+ Util.scaleLargeTimestamp(
|
|
||||||
rtpTimestamp - firstReceivedRtpTimestamp,
|
|
||||||
/* multiplier= */ C.MICROS_PER_SECOND,
|
|
||||||
/* divisor= */ clockRate);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 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 androidx.media3.exoplayer.rtsp.reader;
|
||||||
|
|
||||||
|
import androidx.media3.common.C;
|
||||||
|
import androidx.media3.common.util.Util;
|
||||||
|
|
||||||
|
/** Utility methods for {@link RtpPayloadReader}s. */
|
||||||
|
/* package */ class RtpReaderUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts RTP timestamp and media frequency to sample presentation time, in microseconds
|
||||||
|
*
|
||||||
|
* @param startTimeOffsetUs The offset of the RTP timebase, in microseconds.
|
||||||
|
* @param rtpTimestamp The RTP timestamp to convert.
|
||||||
|
* @param firstReceivedRtpTimestamp The first received RTP timestamp.
|
||||||
|
* @param mediaFrequency The media frequency.
|
||||||
|
* @return The calculated sample presentation time, in microseconds.
|
||||||
|
*/
|
||||||
|
public static long toSampleTimeUs(
|
||||||
|
long startTimeOffsetUs,
|
||||||
|
long rtpTimestamp,
|
||||||
|
long firstReceivedRtpTimestamp,
|
||||||
|
int mediaFrequency) {
|
||||||
|
return startTimeOffsetUs
|
||||||
|
+ Util.scaleLargeTimestamp(
|
||||||
|
rtpTimestamp - firstReceivedRtpTimestamp,
|
||||||
|
/* multiplier= */ C.MICROS_PER_SECOND,
|
||||||
|
/* divisor= */ mediaFrequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RtpReaderUtils() {}
|
||||||
|
}
|
@ -18,6 +18,7 @@ package androidx.media3.exoplayer.rtsp.reader;
|
|||||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
import static androidx.media3.common.util.Assertions.checkState;
|
import static androidx.media3.common.util.Assertions.checkState;
|
||||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||||
|
import static androidx.media3.exoplayer.rtsp.reader.RtpReaderUtils.toSampleTimeUs;
|
||||||
|
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.util.Log;
|
import androidx.media3.common.util.Log;
|
||||||
@ -37,7 +38,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
private static final String TAG = "RtpVP8Reader";
|
private static final String TAG = "RtpVP8Reader";
|
||||||
|
|
||||||
/** VP8 uses a 90 KHz media clock (RFC7741 Section 4.1). */
|
/** VP8 uses a 90 KHz media clock (RFC7741 Section 4.1). */
|
||||||
private static final long MEDIA_CLOCK_FREQUENCY = 90_000;
|
private static final int MEDIA_CLOCK_FREQUENCY = 90_000;
|
||||||
|
|
||||||
private final RtpPayloadFormat payloadFormat;
|
private final RtpPayloadFormat payloadFormat;
|
||||||
|
|
||||||
@ -124,7 +125,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
fragmentedSampleSizeBytes += fragmentSize;
|
fragmentedSampleSizeBytes += fragmentSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
fragmentedSampleTimeUs = toSampleUs(startTimeOffsetUs, timestamp, firstReceivedTimestamp);
|
fragmentedSampleTimeUs =
|
||||||
|
toSampleTimeUs(
|
||||||
|
startTimeOffsetUs, timestamp, firstReceivedTimestamp, MEDIA_CLOCK_FREQUENCY);
|
||||||
|
|
||||||
if (rtpMarker) {
|
if (rtpMarker) {
|
||||||
outputSampleMetadataForFragmentedPackets();
|
outputSampleMetadataForFragmentedPackets();
|
||||||
@ -215,13 +218,4 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
fragmentedSampleTimeUs = C.TIME_UNSET;
|
fragmentedSampleTimeUs = C.TIME_UNSET;
|
||||||
gotFirstPacketOfVp8Frame = false;
|
gotFirstPacketOfVp8Frame = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long toSampleUs(
|
|
||||||
long startTimeOffsetUs, long rtpTimestamp, long firstReceivedRtpTimestamp) {
|
|
||||||
return startTimeOffsetUs
|
|
||||||
+ Util.scaleLargeTimestamp(
|
|
||||||
(rtpTimestamp - firstReceivedRtpTimestamp),
|
|
||||||
/* multiplier= */ C.MICROS_PER_SECOND,
|
|
||||||
/* divisor= */ MEDIA_CLOCK_FREQUENCY);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import static androidx.media3.common.util.Assertions.checkArgument;
|
|||||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||||
import static androidx.media3.common.util.Assertions.checkState;
|
import static androidx.media3.common.util.Assertions.checkState;
|
||||||
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
import static androidx.media3.common.util.Assertions.checkStateNotNull;
|
||||||
|
import static androidx.media3.exoplayer.rtsp.reader.RtpReaderUtils.toSampleTimeUs;
|
||||||
|
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.util.Log;
|
import androidx.media3.common.util.Log;
|
||||||
@ -39,7 +40,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
|
|
||||||
private static final String TAG = "RtpVp9Reader";
|
private static final String TAG = "RtpVp9Reader";
|
||||||
|
|
||||||
private static final long MEDIA_CLOCK_FREQUENCY = 90_000;
|
private static final int MEDIA_CLOCK_FREQUENCY = 90_000;
|
||||||
private static final int SCALABILITY_STRUCTURE_SIZE = 4;
|
private static final int SCALABILITY_STRUCTURE_SIZE = 4;
|
||||||
|
|
||||||
private final RtpPayloadFormat payloadFormat;
|
private final RtpPayloadFormat payloadFormat;
|
||||||
@ -123,7 +124,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
} else {
|
} else {
|
||||||
fragmentedSampleSizeBytes += currentFragmentSizeBytes;
|
fragmentedSampleSizeBytes += currentFragmentSizeBytes;
|
||||||
}
|
}
|
||||||
fragmentedSampleTimeUs = toSampleUs(startTimeOffsetUs, timestamp, firstReceivedTimestamp);
|
fragmentedSampleTimeUs =
|
||||||
|
toSampleTimeUs(
|
||||||
|
startTimeOffsetUs, timestamp, firstReceivedTimestamp, MEDIA_CLOCK_FREQUENCY);
|
||||||
|
|
||||||
if (rtpMarker) {
|
if (rtpMarker) {
|
||||||
outputSampleMetadataForFragmentedPackets();
|
outputSampleMetadataForFragmentedPackets();
|
||||||
@ -271,13 +274,4 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
fragmentedSampleTimeUs = C.TIME_UNSET;
|
fragmentedSampleTimeUs = C.TIME_UNSET;
|
||||||
gotFirstPacketOfVp9Frame = false;
|
gotFirstPacketOfVp9Frame = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long toSampleUs(
|
|
||||||
long startTimeOffsetUs, long rtpTimestamp, long firstReceivedRtpTimestamp) {
|
|
||||||
return startTimeOffsetUs
|
|
||||||
+ Util.scaleLargeTimestamp(
|
|
||||||
(rtpTimestamp - firstReceivedRtpTimestamp),
|
|
||||||
/* multiplier= */ C.MICROS_PER_SECOND,
|
|
||||||
/* divisor= */ MEDIA_CLOCK_FREQUENCY);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user