Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
a11c22b6
authored
Apr 06, 2022
by
Ian Baker
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge pull request #46 from ittiam-systems:rtp_amr
PiperOrigin-RevId: 437274290
parents
a5330d43
1761b423
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
225 additions
and
0 deletions
RELEASENOTES.md
libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/RtpPayloadFormat.java
libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/RtspMediaTrack.java
libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/reader/DefaultRtpPayloadReaderFactory.java
libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/reader/RtpAmrReader.java
RELEASENOTES.md
View file @
a11c22b6
...
...
@@ -38,6 +38,9 @@
*
RTSP:
*
Add RTP reader for HEVC
(
[
#36
](
https://github.com/androidx/media/pull/36
)
).
*
Add RTP reader for AMR. Currently only mono-channel, non-interleaved
AMR streams are supported. Compound AMR RTP payload is not supported.
(
[
#46
](
https://github.com/androidx/media/pull/46
)
)
*
Remove deprecated symbols:
*
Remove
`Player.Listener.onTracksChanged`
. Use
`Player.Listener.onTracksInfoChanged`
instead.
...
...
libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/RtpPayloadFormat.java
View file @
a11c22b6
...
...
@@ -37,6 +37,8 @@ import java.util.Map;
public
final
class
RtpPayloadFormat
{
private
static
final
String
RTP_MEDIA_AC3
=
"AC3"
;
private
static
final
String
RTP_MEDIA_AMR
=
"AMR"
;
private
static
final
String
RTP_MEDIA_AMR_WB
=
"AMR-WB"
;
private
static
final
String
RTP_MEDIA_MPEG4_GENERIC
=
"MPEG4-GENERIC"
;
private
static
final
String
RTP_MEDIA_H264
=
"H264"
;
private
static
final
String
RTP_MEDIA_H265
=
"H265"
;
...
...
@@ -45,6 +47,8 @@ public final class RtpPayloadFormat {
public
static
boolean
isFormatSupported
(
MediaDescription
mediaDescription
)
{
switch
(
Ascii
.
toUpperCase
(
mediaDescription
.
rtpMapAttribute
.
mediaEncoding
))
{
case
RTP_MEDIA_AC3:
case
RTP_MEDIA_AMR:
case
RTP_MEDIA_AMR_WB:
case
RTP_MEDIA_H264:
case
RTP_MEDIA_H265:
case
RTP_MEDIA_MPEG4_GENERIC:
...
...
@@ -65,6 +69,10 @@ public final class RtpPayloadFormat {
switch
(
Ascii
.
toUpperCase
(
mediaType
))
{
case
RTP_MEDIA_AC3:
return
MimeTypes
.
AUDIO_AC3
;
case
RTP_MEDIA_AMR:
return
MimeTypes
.
AUDIO_AMR_NB
;
case
RTP_MEDIA_AMR_WB:
return
MimeTypes
.
AUDIO_AMR_WB
;
case
RTP_MEDIA_H264:
return
MimeTypes
.
VIDEO_H264
;
case
RTP_MEDIA_H265:
...
...
libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/RtspMediaTrack.java
View file @
a11c22b6
...
...
@@ -48,6 +48,8 @@ import com.google.common.collect.ImmutableMap;
private
static
final
String
PARAMETER_H265_SPROP_PPS
=
"sprop-pps"
;
private
static
final
String
PARAMETER_H265_SPROP_VPS
=
"sprop-vps"
;
private
static
final
String
PARAMETER_H265_SPROP_MAX_DON_DIFF
=
"sprop-max-don-diff"
;
private
static
final
String
PARAMETER_AMR_OCTET_ALIGN
=
"octet-align"
;
private
static
final
String
PARAMETER_AMR_INTERLEAVING
=
"interleaving"
;
/** Prefix for the RFC6381 codecs string for AAC formats. */
private
static
final
String
AAC_CODECS_PREFIX
=
"mp4a.40."
;
...
...
@@ -121,6 +123,19 @@ import com.google.common.collect.ImmutableMap;
checkArgument
(!
fmtpParameters
.
isEmpty
());
processAacFmtpAttribute
(
formatBuilder
,
fmtpParameters
,
channelCount
,
clockRate
);
break
;
case
MimeTypes
.
AUDIO_AMR_NB
:
case
MimeTypes
.
AUDIO_AMR_WB
:
checkArgument
(
channelCount
==
1
,
"Multi channel AMR is not currently supported."
);
checkArgument
(
!
fmtpParameters
.
isEmpty
(),
"fmtp parameters must include "
+
PARAMETER_AMR_OCTET_ALIGN
+
"."
);
checkArgument
(
fmtpParameters
.
containsKey
(
PARAMETER_AMR_OCTET_ALIGN
),
"Only octet aligned mode is currently supported."
);
checkArgument
(
!
fmtpParameters
.
containsKey
(
PARAMETER_AMR_INTERLEAVING
),
"Interleaving mode is not currently supported."
);
break
;
case
MimeTypes
.
VIDEO_H264
:
checkArgument
(!
fmtpParameters
.
isEmpty
());
processH264FmtpAttribute
(
formatBuilder
,
fmtpParameters
);
...
...
libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/reader/DefaultRtpPayloadReaderFactory.java
View file @
a11c22b6
...
...
@@ -36,6 +36,9 @@ import androidx.media3.exoplayer.rtsp.RtpPayloadFormat;
return
new
RtpAc3Reader
(
payloadFormat
);
case
MimeTypes
.
AUDIO_AAC
:
return
new
RtpAacReader
(
payloadFormat
);
case
MimeTypes
.
AUDIO_AMR_NB
:
case
MimeTypes
.
AUDIO_AMR_WB
:
return
new
RtpAmrReader
(
payloadFormat
);
case
MimeTypes
.
VIDEO_H264
:
return
new
RtpH264Reader
(
payloadFormat
);
case
MimeTypes
.
VIDEO_H265
:
...
...
libraries/exoplayer_rtsp/src/main/java/androidx/media3/exoplayer/rtsp/reader/RtpAmrReader.java
0 → 100644
View file @
a11c22b6
/*
* 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
static
androidx
.
media3
.
common
.
util
.
Assertions
.
checkArgument
;
import
static
androidx
.
media3
.
common
.
util
.
Assertions
.
checkNotNull
;
import
static
androidx
.
media3
.
common
.
util
.
Assertions
.
checkStateNotNull
;
import
androidx.media3.common.C
;
import
androidx.media3.common.MimeTypes
;
import
androidx.media3.common.util.Log
;
import
androidx.media3.common.util.ParsableByteArray
;
import
androidx.media3.common.util.Util
;
import
androidx.media3.exoplayer.rtsp.RtpPacket
;
import
androidx.media3.exoplayer.rtsp.RtpPayloadFormat
;
import
androidx.media3.extractor.ExtractorOutput
;
import
androidx.media3.extractor.TrackOutput
;
import
org.checkerframework.checker.nullness.qual.MonotonicNonNull
;
/**
* Parses an AMR byte stream carried on RTP packets and extracts individual samples. Interleaving
* mode is not supported. Refer to RFC4867 for more details.
*/
/* package */
final
class
RtpAmrReader
implements
RtpPayloadReader
{
private
static
final
String
TAG
=
"RtpAmrReader"
;
/**
* The frame size in bytes, including header (1 byte), for each of the 16 frame types for AMR-NB
* (narrow band). AMR-NB supports eight narrow band speech encoding modes with bit rates between
* 4.75 and 12.2 kbps defined in RFC4867 Section 3.1. Refer to table 1a in 3GPP TS 26.101 for the
* mapping definition.
*/
private
static
final
int
[]
AMR_NB_FRAME_TYPE_INDEX_TO_FRAME_SIZE
=
{
13
,
// 4.75kbps
14
,
// 5.15kbps
16
,
// 5.90kbps
18
,
// 6.70kbps PDC-EFR
20
,
// 7.40kbps TDMA-EFR
21
,
// 7.95kbps
27
,
// 10.2kbps
32
,
// 12.2kbps GSM-EFR
6
,
// AMR SID
7
,
// GSM-EFR SID
6
,
// TDMA-EFR SID
6
,
// PDC-EFR SID
1
,
// Future use
1
,
// Future use
1
,
// Future use
1
// No data
};
/**
* The frame size in bytes, including header (1 byte), for each of the 16 frame types for AMR-WB
* (wide band). AMR-WB supports nine wide band speech encoding modes with bit rates between 6.6 to
* 23.85 kbps defined in RFC4867 Section 3.2. Refer to table 1a in 3GPP TS 26.201. for the mapping
* definition.
*/
private
static
final
int
[]
AMR_WB_FRAME_TYPE_INDEX_TO_FRAME_SIZE
=
{
18
,
// 6.60kbps
24
,
// 8.85kbps
33
,
// 12.65kbps
37
,
// 14.25kbps
41
,
// 15.85kbps
47
,
// 18.25kbps
51
,
// 19.85kbps
59
,
// 23.05kbps
61
,
// 23.85kbps
6
,
// AMR-WB SID
1
,
// Future use
1
,
// Future use
1
,
// Future use
1
,
// Future use
1
,
// speech lost
1
// No data
};
private
final
RtpPayloadFormat
payloadFormat
;
private
final
boolean
isWideBand
;
private
final
int
sampleRate
;
private
@MonotonicNonNull
TrackOutput
trackOutput
;
private
long
firstReceivedTimestamp
;
private
long
startTimeOffsetUs
;
private
int
previousSequenceNumber
;
public
RtpAmrReader
(
RtpPayloadFormat
payloadFormat
)
{
this
.
payloadFormat
=
payloadFormat
;
this
.
isWideBand
=
MimeTypes
.
AUDIO_AMR_WB
.
equals
(
checkNotNull
(
payloadFormat
.
format
.
sampleMimeType
));
this
.
sampleRate
=
payloadFormat
.
clockRate
;
this
.
firstReceivedTimestamp
=
C
.
TIME_UNSET
;
this
.
previousSequenceNumber
=
C
.
INDEX_UNSET
;
// Start time offset must be 0 before the first seek.
this
.
startTimeOffsetUs
=
0
;
}
// RtpPayloadReader implementation.
@Override
public
void
createTracks
(
ExtractorOutput
extractorOutput
,
int
trackId
)
{
trackOutput
=
extractorOutput
.
track
(
trackId
,
C
.
TRACK_TYPE_AUDIO
);
trackOutput
.
format
(
payloadFormat
.
format
);
}
@Override
public
void
onReceivingFirstPacket
(
long
timestamp
,
int
sequenceNumber
)
{
this
.
firstReceivedTimestamp
=
timestamp
;
}
@Override
public
void
consume
(
ParsableByteArray
data
,
long
timestamp
,
int
sequenceNumber
,
boolean
rtpMarker
)
{
checkStateNotNull
(
trackOutput
);
// Check that this packet is in the sequence of the previous packet.
if
(
previousSequenceNumber
!=
C
.
INDEX_UNSET
)
{
int
expectedSequenceNumber
=
RtpPacket
.
getNextSequenceNumber
(
previousSequenceNumber
);
if
(
sequenceNumber
!=
expectedSequenceNumber
)
{
Log
.
w
(
TAG
,
Util
.
formatInvariant
(
"Received RTP packet with unexpected sequence number. Expected: %d; received: %d."
,
expectedSequenceNumber
,
sequenceNumber
));
}
}
//
// AMR as RTP payload (RFC4867 Section 4.2).
//
// +----------------+-------------------+----------------
// | payload header | table of contents | speech data ...
// +----------------+-------------------+----------------
//
// Payload header (RFC4867 Section 4.4.1).
//
// The header won't contain ILL and ILP, as interleaving is not currently supported.
// +-+-+-+-+-+-+-+- - - - - - - -
// | CMR |R|R|R|R| ILL | ILP |
// +-+-+-+-+-+-+-+- - - - - - - -
//
// Skip CMR and reserved bits.
data
.
skipBytes
(
1
);
// Loop over sampleSize to send multiple frames along with appropriate timestamp when compound
// payload support is added.
int
frameType
=
(
data
.
peekUnsignedByte
()
>>
3
)
&
0x0f
;
int
frameSize
=
getFrameSize
(
frameType
,
isWideBand
);
int
sampleSize
=
data
.
bytesLeft
();
checkArgument
(
sampleSize
==
frameSize
,
"compound payload not supported currently"
);
trackOutput
.
sampleData
(
data
,
sampleSize
);
long
sampleTimeUs
=
toSampleTimeUs
(
startTimeOffsetUs
,
timestamp
,
firstReceivedTimestamp
,
sampleRate
);
trackOutput
.
sampleMetadata
(
sampleTimeUs
,
C
.
BUFFER_FLAG_KEY_FRAME
,
sampleSize
,
/* offset= */
0
,
/* cryptoData= */
null
);
previousSequenceNumber
=
sequenceNumber
;
}
@Override
public
void
seek
(
long
nextRtpTimestamp
,
long
timeUs
)
{
firstReceivedTimestamp
=
nextRtpTimestamp
;
startTimeOffsetUs
=
timeUs
;
}
// Internal methods.
public
static
int
getFrameSize
(
int
frameType
,
boolean
isWideBand
)
{
checkArgument
(
// Valid frame types are defined in RFC4867 Section 4.3.1.
(
frameType
>=
0
&&
frameType
<=
8
)
||
frameType
==
15
,
"Illegal AMR "
+
(
isWideBand
?
"WB"
:
"NB"
)
+
" frame type "
+
frameType
);
return
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
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment