Skip to content

Commit

Permalink
Factor out RTP timestamp to sample time method
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 465337074
  • Loading branch information
claincly authored and marcbaechinger committed Oct 19, 2022
1 parent fe2b846 commit a1be6d6
Show file tree
Hide file tree
Showing 12 changed files with 86 additions and 120 deletions.
Expand Up @@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.source.rtsp.reader;

import static com.google.android.exoplayer2.source.rtsp.reader.RtpReaderUtils.toSampleTimeUs;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;

import com.google.android.exoplayer2.C;
Expand Down Expand Up @@ -153,14 +154,4 @@ private static void outputSampleMetadata(TrackOutput trackOutput, long sampleTim
trackOutput.sampleMetadata(
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);
}
}
Expand Up @@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.source.rtsp.reader;

import static com.google.android.exoplayer2.source.rtsp.reader.RtpReaderUtils.toSampleTimeUs;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import static com.google.android.exoplayer2.util.Assertions.checkState;
import static com.google.android.exoplayer2.util.Util.castNonNull;
Expand All @@ -26,7 +27,6 @@
import com.google.android.exoplayer2.source.rtsp.RtpPayloadFormat;
import com.google.android.exoplayer2.util.ParsableBitArray;
import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.Util;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;

/** Parses an AC3 byte stream carried on RTP packets, and extracts AC3 frames. */
Expand Down Expand Up @@ -206,14 +206,4 @@ private void outputSampleMetadataForFragmentedPackets() {
/* cryptoData= */ null);
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);
}
}
Expand Up @@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.source.rtsp.reader;

import static com.google.android.exoplayer2.source.rtsp.reader.RtpReaderUtils.toSampleTimeUs;
import static com.google.android.exoplayer2.util.Assertions.checkArgument;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull;
Expand Down Expand Up @@ -183,14 +184,4 @@ public static int getFrameSize(int frameType, boolean isWideBand) {
? AMR_WB_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);
}
}
Expand Up @@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.source.rtsp.reader;

import static com.google.android.exoplayer2.source.rtsp.reader.RtpReaderUtils.toSampleTimeUs;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import static com.google.android.exoplayer2.util.Assertions.checkState;
import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull;
Expand All @@ -35,7 +36,7 @@
/* package */ final class RtpH263Reader implements RtpPayloadReader {
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. */
private static final int I_VOP = 0;
Expand Down Expand Up @@ -164,7 +165,8 @@ public void consume(
// Write the video sample.
trackOutput.sampleData(data, fragmentSize);
fragmentedSampleSizeBytes += fragmentSize;
fragmentedSampleTimeUs = toSampleUs(startTimeOffsetUs, timestamp, firstReceivedTimestamp);
fragmentedSampleTimeUs =
toSampleTimeUs(startTimeOffsetUs, timestamp, firstReceivedTimestamp, MEDIA_CLOCK_FREQUENCY);

if (rtpMarker) {
outputSampleMetadataForFragmentedPackets();
Expand Down Expand Up @@ -242,13 +244,4 @@ private void outputSampleMetadataForFragmentedPackets() {
isKeyFrame = 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);
}
}
Expand Up @@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.source.rtsp.reader;

import static com.google.android.exoplayer2.source.rtsp.reader.RtpReaderUtils.toSampleTimeUs;
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;
Expand All @@ -36,7 +37,7 @@
/* package */ final class RtpH264Reader implements RtpPayloadReader {
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. */
private static final int FU_PAYLOAD_OFFSET = 2;
Expand Down Expand Up @@ -115,7 +116,9 @@ public void consume(ParsableByteArray data, long timestamp, int sequenceNumber,
firstReceivedTimestamp = timestamp;
}

long timeUs = toSampleUs(startTimeOffsetUs, timestamp, firstReceivedTimestamp);
long timeUs =
toSampleTimeUs(
startTimeOffsetUs, timestamp, firstReceivedTimestamp, MEDIA_CLOCK_FREQUENCY);
trackOutput.sampleMetadata(
timeUs, bufferFlags, fragmentedSampleSizeBytes, /* offset= */ 0, /* cryptoData= */ null);
fragmentedSampleSizeBytes = 0;
Expand Down Expand Up @@ -287,15 +290,6 @@ private int writeStartCode() {
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) {
return nalType == NAL_UNIT_TYPE_IDR ? C.BUFFER_FLAG_KEY_FRAME : 0;
}
Expand Down
Expand Up @@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.source.rtsp.reader;

import static com.google.android.exoplayer2.source.rtsp.reader.RtpReaderUtils.toSampleTimeUs;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull;

Expand All @@ -38,7 +39,7 @@
/* package */ final class RtpH265Reader implements RtpPayloadReader {

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. */
private static final int FU_PAYLOAD_OFFSET = 3;
/** Aggregation Packet. RFC7798 Section 4.4.2. */
Expand Down Expand Up @@ -111,7 +112,9 @@ public void consume(ParsableByteArray data, long timestamp, int sequenceNumber,
firstReceivedTimestamp = timestamp;
}

long timeUs = toSampleUs(startTimeOffsetUs, timestamp, firstReceivedTimestamp);
long timeUs =
toSampleTimeUs(
startTimeOffsetUs, timestamp, firstReceivedTimestamp, MEDIA_CLOCK_FREQUENCY);
trackOutput.sampleMetadata(
timeUs, bufferFlags, fragmentedSampleSizeBytes, /* offset= */ 0, /* cryptoData= */ null);
fragmentedSampleSizeBytes = 0;
Expand Down Expand Up @@ -254,15 +257,6 @@ private int writeStartCode() {
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) {
return (nalType == NAL_IDR_W_RADL || nalType == NAL_IDR_N_LP) ? C.BUFFER_FLAG_KEY_FRAME : 0;
}
Expand Down
Expand Up @@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.source.rtsp.reader;

import static com.google.android.exoplayer2.source.rtsp.reader.RtpReaderUtils.toSampleTimeUs;
import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull;
import static com.google.android.exoplayer2.util.Util.castNonNull;

Expand All @@ -36,7 +37,7 @@
/* package */ final class RtpMpeg4Reader implements RtpPayloadReader {
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. */
private static final int I_VOP = 0;
Expand Down Expand Up @@ -102,7 +103,9 @@ public void consume(
firstReceivedTimestamp = timestamp;
}

long timeUs = toSampleUs(startTimeOffsetUs, timestamp, firstReceivedTimestamp);
long timeUs =
toSampleTimeUs(
startTimeOffsetUs, timestamp, firstReceivedTimestamp, MEDIA_CLOCK_FREQUENCY);
trackOutput.sampleMetadata(timeUs, bufferFlags, sampleLength, 0, null);
sampleLength = 0;
}
Expand Down Expand Up @@ -135,13 +138,4 @@ public void seek(long nextRtpTimestamp, long timeUs) {
}
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);
}
}
Expand Up @@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.source.rtsp.reader;

import static com.google.android.exoplayer2.source.rtsp.reader.RtpReaderUtils.toSampleTimeUs;
import static com.google.android.exoplayer2.util.Assertions.checkArgument;
import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull;

Expand All @@ -38,7 +39,7 @@
/* package */ final class RtpOpusReader implements RtpPayloadReader {
private static final String TAG = "RtpOpusReader";
/* 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;

Expand Down Expand Up @@ -113,7 +114,9 @@ public void consume(
// sending opus data.
int size = data.bytesLeft();
trackOutput.sampleData(data, size);
long timeUs = toSampleTimeUs(startTimeOffsetUs, timestamp, firstReceivedTimestamp);
long timeUs =
toSampleTimeUs(
startTimeOffsetUs, timestamp, firstReceivedTimestamp, MEDIA_CLOCK_FREQUENCY);
trackOutput.sampleMetadata(
timeUs, C.BUFFER_FLAG_KEY_FRAME, size, /* offset*/ 0, /* cryptoData*/ null);
}
Expand Down Expand Up @@ -144,14 +147,4 @@ private static void validateOpusIdHeader(ParsableByteArray data) {
checkArgument(data.readUnsignedByte() == 1, "version number must always be 1");
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);
}
}
Expand Up @@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.source.rtsp.reader;

import static com.google.android.exoplayer2.source.rtsp.reader.RtpReaderUtils.toSampleTimeUs;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;

import android.util.Log;
Expand Down Expand Up @@ -76,7 +77,8 @@ public void consume(
}

long sampleTimeUs =
toSampleUs(startTimeOffsetUs, timestamp, firstReceivedTimestamp, payloadFormat.clockRate);
toSampleTimeUs(
startTimeOffsetUs, timestamp, firstReceivedTimestamp, payloadFormat.clockRate);
int size = data.bytesLeft();
trackOutput.sampleData(data, size);
trackOutput.sampleMetadata(
Expand All @@ -91,14 +93,4 @@ public void seek(long nextRtpTimestamp, long timeUs) {
firstReceivedTimestamp = nextRtpTimestamp;
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 com.google.android.exoplayer2.source.rtsp.reader;

import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.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() {}
}

0 comments on commit a1be6d6

Please sign in to comment.