FFmpeg
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
rtpdec_opus.c
Go to the documentation of this file.
1 /*
2  * RTP Depacketization of Opus, RFC 7587
3  * Copyright (c) 2025 Jonathan Baudanza <jon@jonb.org>
4  * Copyright (c) 2022 Erik Linge
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include "libavcodec/bytestream.h"
24 #include "libavutil/mem.h"
25 #include "libavutil/avstring.h"
26 #include "rtpdec_formats.h"
27 #include "internal.h"
28 
29 static int opus_duration(const uint8_t *src, int size)
30 {
31  unsigned nb_frames = 1;
32  unsigned toc = src[0];
33  unsigned toc_config = toc >> 3;
34  unsigned toc_count = toc & 3;
35  unsigned frame_size = toc_config < 12 ? FFMAX(480, 960 * (toc_config & 3)) :
36  toc_config < 16 ? 480 << (toc_config & 1) :
37  120 << (toc_config & 3);
38  if (toc_count == 3) {
39  if (size<2)
40  return AVERROR_INVALIDDATA;
41  nb_frames = src[1] & 0x3F;
42  } else if (toc_count) {
43  nb_frames = 2;
44  }
45 
46  return frame_size * nb_frames;
47 }
48 
50 {
51  uint8_t *bs;
52  int ret;
53 
54  /* This function writes an extradata with a channel mapping family of 0.
55  * This mapping family only supports mono and stereo layouts. And RFC7587
56  * specifies that the number of channels in the SDP must be 2.
57  */
58  if (codecpar->ch_layout.nb_channels > 2) {
59  return AVERROR_INVALIDDATA;
60  }
61 
62  ret = ff_alloc_extradata(codecpar, 19);
63  if (ret < 0)
64  return ret;
65 
66  bs = (uint8_t *)codecpar->extradata;
67 
68  /* Opus magic */
69  bytestream_put_buffer(&bs, "OpusHead", 8);
70  /* Version */
71  bytestream_put_byte (&bs, 0x1);
72  /* Channel count */
73  bytestream_put_byte (&bs, codecpar->ch_layout.nb_channels);
74  /* Pre skip */
75  bytestream_put_le16 (&bs, 0);
76  /* Input sample rate */
77  bytestream_put_le32 (&bs, 48000);
78  /* Output gain */
79  bytestream_put_le16 (&bs, 0x0);
80  /* Mapping family */
81  bytestream_put_byte (&bs, 0x0);
82 
83  return 0;
84 }
85 
86 static int opus_init(AVFormatContext *s, int st_index, PayloadContext *priv_data)
87 {
88  return opus_write_extradata(s->streams[st_index]->codecpar);
89 }
90 
92  AVStream *st, AVPacket *pkt, uint32_t *timestamp,
93  const uint8_t *buf, int len, uint16_t seq,
94  int flags)
95 {
96  int rv;
97  int duration;
98 
99  if ((rv = av_new_packet(pkt, len)) < 0)
100  return rv;
101 
102  memcpy(pkt->data, buf, len);
103  pkt->stream_index = st->index;
104 
105  duration = opus_duration(buf, len);
106  if (duration != AVERROR_INVALIDDATA) {
107  pkt->duration = duration;
108  }
109 
110  return 0;
111 }
112 
115  const char *attr, const char *value)
116 {
117  if (!strcmp(attr, "sprop-maxcapturerate")) {
118  int rate = atoi(value);
119  if (rate < 8000 || rate > 48000) {
121  "fmtp field 'sprop-maxcapturerate' must be between 8000 to 48000 (provided value: %s)",
122  value);
123  return AVERROR_INVALIDDATA;
124  }
125  stream->codecpar->sample_rate = rate;
126  }
127  return 0;
128 }
129 
130 static int opus_parse_sdp_line(AVFormatContext *s, int st_index,
131  PayloadContext *data, const char *line)
132 {
133  const char *p;
134 
135  if (st_index < 0)
136  return 0;
137 
138  if (av_strstart(line, "fmtp:", &p)) {
139  return ff_parse_fmtp(s, s->streams[st_index], data, p, parse_fmtp);
140  }
141  return 0;
142 }
143 
145  .enc_name = "opus",
146  .codec_type = AVMEDIA_TYPE_AUDIO,
147  .codec_id = AV_CODEC_ID_OPUS,
148  .parse_packet = opus_parse_packet,
149  .init = opus_init,
150  .parse_sdp_a_line = opus_parse_sdp_line,
151 };
flags
const SwsFlags flags[]
Definition: swscale.c:61
AVCodecParameters::extradata
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: codec_par.h:69
AVCodecParameters
This struct describes the properties of an encoded stream.
Definition: codec_par.h:47
rtpdec_formats.h
ff_parse_fmtp
int ff_parse_fmtp(AVFormatContext *s, AVStream *stream, PayloadContext *data, const char *p, int(*parse_fmtp)(AVFormatContext *s, AVStream *stream, PayloadContext *data, const char *attr, const char *value))
Definition: rtpdec.c:922
AVPacket::data
uint8_t * data
Definition: packet.h:535
data
const char data[16]
Definition: mxf.c:149
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:553
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition: channel_layout.h:329
RTPDynamicProtocolHandler::enc_name
const char * enc_name
Definition: rtpdec.h:117
pkt
AVPacket * pkt
Definition: movenc.c:60
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
duration
int64_t duration
Definition: movenc.c:65
MpegTSContext::stream
AVFormatContext * stream
Definition: mpegts.c:133
s
#define s(width, name)
Definition: cbs_vp9.c:198
av_new_packet
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: packet.c:99
frame_size
int frame_size
Definition: mxfenc.c:2446
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:201
ctx
AVFormatContext * ctx
Definition: movenc.c:49
opus_parse_packet
static int opus_parse_packet(AVFormatContext *ctx, PayloadContext *data, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len, uint16_t seq, int flags)
Definition: rtpdec_opus.c:91
AVFormatContext
Format I/O context.
Definition: avformat.h:1264
internal.h
AVCodecParameters::ch_layout
AVChannelLayout ch_layout
Audio only.
Definition: codec_par.h:180
opus_init
static int opus_init(AVFormatContext *s, int st_index, PayloadContext *priv_data)
Definition: rtpdec_opus.c:86
opus_write_extradata
static int opus_write_extradata(AVCodecParameters *codecpar)
Definition: rtpdec_opus.c:49
size
int size
Definition: twinvq_data.h:10344
opus_parse_sdp_line
static int opus_parse_sdp_line(AVFormatContext *s, int st_index, PayloadContext *data, const char *line)
Definition: rtpdec_opus.c:130
AV_CODEC_ID_OPUS
@ AV_CODEC_ID_OPUS
Definition: codec_id.h:509
line
Definition: graph2dot.c:48
av_strstart
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition: avstring.c:36
opus_duration
static int opus_duration(const uint8_t *src, int size)
Definition: rtpdec_opus.c:29
ff_opus_dynamic_handler
const RTPDynamicProtocolHandler ff_opus_dynamic_handler
Definition: rtpdec_opus.c:144
bytestream_put_buffer
static av_always_inline void bytestream_put_buffer(uint8_t **b, const uint8_t *src, unsigned int size)
Definition: bytestream.h:372
value
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
Definition: writing_filters.txt:86
parse_fmtp
static int parse_fmtp(AVFormatContext *s, AVStream *stream, PayloadContext *data, const char *attr, const char *value)
Definition: rtpdec_opus.c:113
len
int len
Definition: vorbis_enc_data.h:426
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:744
AVStream::index
int index
stream index in AVFormatContext
Definition: avformat.h:750
AVPacket::stream_index
int stream_index
Definition: packet.h:537
mem.h
AVPacket
This structure stores compressed data.
Definition: packet.h:512
bytestream.h
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
avstring.h
PayloadContext
RTP/AV1 specific private data.
Definition: rdt.c:85
src
#define src
Definition: vp8dsp.c:248
RTPDynamicProtocolHandler
Definition: rtpdec.h:116
ff_alloc_extradata
int ff_alloc_extradata(AVCodecParameters *par, int size)
Allocate extradata with additional AV_INPUT_BUFFER_PADDING_SIZE at end which is always set to 0.
Definition: utils.c:230