FFmpeg
Loading...
Searching...
No Matches
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
24#include "libavutil/mem.h"
25#include "libavutil/avstring.h"
26#include "rtpdec_formats.h"
27#include "internal.h"
28
29static 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)
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) {
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
86static 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);
107 pkt->duration = duration;
108 }
109
110 return 0;
111}
112
114 AVStream *stream, PayloadContext *data,
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
130static 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};
static av_always_inline void bytestream_put_buffer(uint8_t **b, const uint8_t *src, unsigned int size)
Definition bytestream.h:372
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define s(width, name)
Definition cbs_vp9.c:198
static AVPacket * pkt
double value
Definition eval.c:102
static int64_t duration
Definition ffplay.c:330
static const uint8_t frame_size[4]
Definition g723_1.h:222
@ AV_CODEC_ID_OPUS
Definition codec_id.h:513
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition packet.c:98
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
@ AVMEDIA_TYPE_AUDIO
Definition avutil.h:201
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
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:237
#define FFMAX(a, b)
Definition macros.h:47
Memory handling functions.
const char data[16]
Definition mxf.c:149
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:945
const RTPDynamicProtocolHandler ff_opus_dynamic_handler
static int parse_fmtp(AVFormatContext *s, AVStream *stream, PayloadContext *data, const char *attr, const char *value)
static int opus_init(AVFormatContext *s, int st_index, PayloadContext *priv_data)
Definition rtpdec_opus.c:86
static int opus_parse_sdp_line(AVFormatContext *s, int st_index, PayloadContext *data, const char *line)
static int parse_fmtp(AVFormatContext *s, AVStream *stream, PayloadContext *data, const char *attr, const char *value)
static int opus_duration(const uint8_t *src, int size)
Definition rtpdec_opus.c:29
static int opus_write_extradata(AVCodecParameters *codecpar)
Definition rtpdec_opus.c:49
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
int nb_channels
Number of channels in this layout.
This struct describes the properties of an encoded stream.
Definition codec_par.h:49
AVChannelLayout ch_layout
The channel layout and number of channels.
Definition codec_par.h:207
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition codec_par.h:71
int sample_rate
The number of audio samples per second.
Definition codec_par.h:213
Format I/O context.
Definition avformat.h:1333
This structure stores compressed data.
Definition packet.h:580
Stream structure.
Definition avformat.h:766
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition avformat.h:789
int index
stream index in AVFormatContext
Definition avformat.h:772
RTP/AV1 specific private data.
Definition rdt.c:85
#define av_log(a,...)
#define src
Definition vp8dsp.c:248
static AVFormatContext * ctx
Definition movenc.c:49
int size
int len