FFmpeg
rtpdec_qdm2.c
Go to the documentation of this file.
1 /*
2  * QDesign Music 2 (QDM2) payload for RTP
3  * Copyright (c) 2010 Ronald S. Bultje
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * @brief RTP support for the QDM2 payload (todo: wiki)
25  * @author Ronald S. Bultje <rbultje@ronald.bitfreak.net>
26  */
27 
28 #include <string.h>
29 #include "libavutil/avassert.h"
30 #include "libavutil/intreadwrite.h"
31 #include "libavcodec/avcodec.h"
32 #include "internal.h"
33 #include "rtp.h"
34 #include "rtpdec.h"
35 #include "rtpdec_formats.h"
36 
37 struct PayloadContext {
38  /** values read from the config header, used as packet headers */
39  //@{
40  int block_type; ///< superblock type, value 2 .. 8
41  int block_size; ///< from extradata, used as pkt length
42  int subpkts_per_block; ///< max. nr. of subpackets to add per output buffer
43  //@}
44 
45  /** Temporary storage for superblock restoring, per packet ID (0x80 total) */
46  //@{
47  uint16_t len[0x80]; ///< how much the temporary buffer is filled
48  uint8_t buf[0x80][0x800]; ///< the temporary storage buffer
49 
50  unsigned int cache; ///< number of data packets that we have cached right now
51  unsigned int n_pkts; ///< number of RTP packets received since last packet output / config
52  uint32_t timestamp; ///< timestamp of next-to-be-returned packet
53  //@}
54 };
55 
56 /**
57  * Parse configuration (basically the codec-specific extradata) from
58  * an RTP config subpacket (starts with 0xff).
59  *
60  * Layout of the config subpacket (in bytes):
61  * 1: 0xFF <- config ID
62  * then an array {
63  * 1: size <- of the current item
64  * 1: item type <- 0 .. 4
65  * size-2: data <- data depends on the item type
66  * }
67  *
68  * Item 0 implies the end of the config subpacket, and has no data.
69  * Item 1 implies a stream configuration without extradata.
70  * Item 2 max. nr. of subpackets per superblock
71  * Item 3 superblock type for the stream
72  * Item 4 implies a stream configuration with extradata (size >= 0x1c).
73  *
74  * @return <0 on error, otherwise the number of bytes parsed from the
75  * input buffer.
76  */
78  const uint8_t *buf, const uint8_t *end)
79 {
80  const uint8_t *p = buf;
81 
82  while (end - p >= 2) {
83  unsigned int item_len = p[0], config_item = p[1];
84 
85  if (item_len < 2 || end - p < item_len || config_item > 4)
86  return AVERROR_INVALIDDATA;
87 
88  switch (config_item) {
89  case 0: /* end of config block */
90  return p - buf + item_len;
91  case 1: /* stream without extradata */
92  /* FIXME: set default qdm->block_size */
93  break;
94  case 2: /**< subpackets per block */
95  if (item_len < 3)
96  return AVERROR_INVALIDDATA;
97  qdm->subpkts_per_block = p[2];
98  break;
99  case 3: /* superblock type */
100  if (item_len < 4)
101  return AVERROR_INVALIDDATA;
102  qdm->block_type = AV_RB16(p + 2);
103  break;
104  case 4: /* stream with extradata */
105  if (item_len < 30)
106  return AVERROR_INVALIDDATA;
107  av_freep(&st->codecpar->extradata);
108  if (ff_alloc_extradata(st->codecpar, 26 + item_len)) {
109  return AVERROR(ENOMEM);
110  }
111  AV_WB32(st->codecpar->extradata, 12);
112  memcpy(st->codecpar->extradata + 4, "frma", 4);
113  memcpy(st->codecpar->extradata + 8, "QDM2", 4);
114  AV_WB32(st->codecpar->extradata + 12, 6 + item_len);
115  memcpy(st->codecpar->extradata + 16, "QDCA", 4);
116  memcpy(st->codecpar->extradata + 20, p + 2, item_len - 2);
117  AV_WB32(st->codecpar->extradata + 18 + item_len, 8);
118  AV_WB32(st->codecpar->extradata + 22 + item_len, 0);
119 
120  qdm->block_size = AV_RB32(p + 26);
121  break;
122  }
123 
124  p += item_len;
125  }
126 
127  return AVERROR(EAGAIN); /* not enough data */
128 }
129 
130 /**
131  * Parse a single subpacket. We store this subpacket in an intermediate
132  * buffer (position depends on the ID (byte[0]). When called, at least
133  * 4 bytes are available for reading (see qdm2_parse_packet()).
134  *
135  * Layout of a single subpacket (RTP packets commonly contain multiple
136  * such subpackets) - length in bytes:
137  * 1: ordering ID <- 0 .. 0x7F
138  * 1: subpacket type <- 0 .. 0x7F; value & 0x80 means subpacket length = 2 bytes, else 1 byte
139  * 1/2: subpacket length <- length of the data following the flags/length fields
140  * if (subpacket type & 0x7F) == 0x7F
141  * 1: subpacket type, higher bits
142  * size: subpacket data
143  *
144  * The subpackets come in randomly, and should be encapsulated into 1
145  * or more superblocks (containing qdm->subpkts_per_block subpackets
146  * each) per RTP packet, in order of ascending "ordering ID", see
147  * qdm2_restore_block().
148  *
149  * @return <0 on error, otherwise the number of bytes parsed from the
150  * input buffer.
151  */
153  const uint8_t *buf, const uint8_t *end)
154 {
155  const uint8_t *p = buf;
156  unsigned int id, len, type, to_copy;
157 
158  /* parse header so we know the size of the header/data */
159  id = *p++;
160  type = *p++;
161  if (type & 0x80) {
162  len = AV_RB16(p);
163  p += 2;
164  type &= 0x7F;
165  } else
166  len = *p++;
167 
168  if (end - p < len + (type == 0x7F) || id >= 0x80)
169  return AVERROR_INVALIDDATA;
170  if (type == 0x7F)
171  type |= *p++ << 8;
172 
173  /* copy data into a temporary buffer */
174  to_copy = FFMIN(len + (p - &buf[1]), 0x800 - qdm->len[id]);
175  memcpy(&qdm->buf[id][qdm->len[id]], buf + 1, to_copy);
176  qdm->len[id] += to_copy;
177 
178  return p + len - buf;
179 }
180 
181 /**
182  * Add a superblock header around a set of subpackets.
183  *
184  * @return <0 on error, else 0.
185  */
187 {
188  int to_copy, n, res, include_csum;
189  uint8_t *p, *csum_pos = NULL;
190 
191  /* create packet to hold subpkts into a superblock */
192  av_assert0(qdm->cache > 0);
193  for (n = 0; n < 0x80; n++)
194  if (qdm->len[n] > 0)
195  break;
196  av_assert0(n < 0x80);
197 
198  if ((res = av_new_packet(pkt, qdm->block_size)) < 0)
199  return res;
200  memset(pkt->data, 0, pkt->size);
201  pkt->stream_index = st->index;
202  p = pkt->data;
203 
204  /* superblock header */
205  if (qdm->len[n] > 0xff) {
206  *p++ = qdm->block_type | 0x80;
207  AV_WB16(p, qdm->len[n]);
208  p += 2;
209  } else {
210  *p++ = qdm->block_type;
211  *p++ = qdm->len[n];
212  }
213  if ((include_csum = (qdm->block_type == 2 || qdm->block_type == 4))) {
214  csum_pos = p;
215  p += 2;
216  }
217 
218  /* subpacket data */
219  to_copy = FFMIN(qdm->len[n], pkt->size - (p - pkt->data));
220  memcpy(p, qdm->buf[n], to_copy);
221  qdm->len[n] = 0;
222 
223  /* checksum header */
224  if (include_csum) {
225  unsigned int total = 0;
226  uint8_t *q;
227 
228  for (q = pkt->data; q < &pkt->data[qdm->block_size]; q++)
229  total += *q;
230  AV_WB16(csum_pos, (uint16_t) total);
231  }
232 
233  return 0;
234 }
235 
236 /** return 0 on packet, no more left, 1 on packet, -1 on partial packet... */
238  AVStream *st, AVPacket *pkt,
239  uint32_t *timestamp,
240  const uint8_t *buf, int len, uint16_t seq,
241  int flags)
242 {
243  int res = AVERROR_INVALIDDATA, n;
244  const uint8_t *end = buf + len, *p = buf;
245 
246  if (len > 0) {
247  if (len < 2)
248  return AVERROR_INVALIDDATA;
249 
250  /* configuration block */
251  if (*p == 0xff) {
252  if (qdm->n_pkts > 0) {
254  "Out of sequence config - dropping queue\n");
255  qdm->n_pkts = 0;
256  memset(qdm->len, 0, sizeof(qdm->len));
257  }
258 
259  if ((res = qdm2_parse_config(qdm, st, ++p, end)) < 0)
260  return res;
261  p += res;
262 
263  /* We set codec_id to AV_CODEC_ID_NONE initially to
264  * delay decoder initialization since extradata is
265  * carried within the RTP stream, not SDP. Here,
266  * by setting codec_id to AV_CODEC_ID_QDM2, we are signalling
267  * to the decoder that it is OK to initialize. */
269  }
270  if (st->codecpar->codec_id == AV_CODEC_ID_NONE)
271  return AVERROR(EAGAIN);
272 
273  /* subpackets */
274  while (end - p >= 4) {
275  if ((res = qdm2_parse_subpacket(qdm, st, p, end)) < 0)
276  return res;
277  p += res;
278  }
279 
280  qdm->timestamp = *timestamp;
281  if (++qdm->n_pkts < qdm->subpkts_per_block)
282  return AVERROR(EAGAIN);
283  qdm->cache = 0;
284  for (n = 0; n < 0x80; n++)
285  if (qdm->len[n] > 0)
286  qdm->cache++;
287  }
288 
289  /* output the subpackets into freshly created superblock structures */
290  if (!qdm->cache || (res = qdm2_restore_block(qdm, st, pkt)) < 0)
291  return res;
292  if (--qdm->cache == 0)
293  qdm->n_pkts = 0;
294 
295  *timestamp = qdm->timestamp;
296  qdm->timestamp = RTP_NOTS_VALUE;
297 
298  return (qdm->cache > 0) ? 1 : 0;
299 }
300 
302  .enc_name = "X-QDM",
303  .codec_type = AVMEDIA_TYPE_AUDIO,
304  .codec_id = AV_CODEC_ID_NONE,
305  .priv_data_size = sizeof(PayloadContext),
307 };
AVPacket pkt
Definition: rtpdec_qt.c:37
const RTPDynamicProtocolHandler ff_qdm2_dynamic_handler
Definition: rtpdec_qdm2.c:301
#define NULL
Definition: coverity.c:32
int block_size
from extradata, used as pkt length
Definition: rtpdec_qdm2.c:41
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
unsigned int n_pkts
number of RTP packets received since last packet output / config
Definition: rtpdec_qdm2.c:51
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index, int flush)
Parse a packet, add all split parts to parse_queue.
Definition: utils.c:1447
RTP/JPEG specific private data.
Definition: rdt.c:83
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3968
int index
stream index in AVFormatContext
Definition: avformat.h:882
int size
Definition: avcodec.h:1481
GLint GLenum type
Definition: opengl_enc.c:104
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_WB24 unsigned int_TMPL AV_RB16
Definition: bytestream.h:87
Format I/O context.
Definition: avformat.h:1358
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
uint8_t
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_RB32
Definition: bytestream.h:87
uint8_t * data
Definition: avcodec.h:1480
static int qdm2_parse_subpacket(PayloadContext *qdm, AVStream *st, const uint8_t *buf, const uint8_t *end)
Parse a single subpacket.
Definition: rtpdec_qdm2.c:152
int subpkts_per_block
max. nr. of subpackets to add per output buffer
Definition: rtpdec_qdm2.c:42
#define AV_WB16(p, v)
Definition: intreadwrite.h:405
#define av_log(a,...)
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:86
static int qdm2_parse_packet(AVFormatContext *s, PayloadContext *qdm, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len, uint16_t seq, int flags)
return 0 on packet, no more left, 1 on packet, -1 on partial packet...
Definition: rtpdec_qdm2.c:237
uint32_t timestamp
current frame timestamp
Definition: rtpdec_ac3.c:31
static int qdm2_parse_config(PayloadContext *qdm, AVStream *st, const uint8_t *buf, const uint8_t *end)
Parse configuration (basically the codec-specific extradata) from an RTP config subpacket (starts wit...
Definition: rtpdec_qdm2.c:77
int block_type
values read from the config header, used as packet headers
Definition: rtpdec_qdm2.c:40
simple assert() macros that are a bit more flexible than ISO C assert().
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:3321
#define FFMIN(a, b)
Definition: common.h:96
unsigned int cache
number of data packets that we have cached right now
Definition: rtpdec_qdm2.c:50
#define s(width, name)
Definition: cbs_vp9.c:257
int n
Definition: avisynth_c.h:760
Stream structure.
Definition: avformat.h:881
Libavcodec external API header.
static int qdm2_restore_block(PayloadContext *qdm, AVStream *st, AVPacket *pkt)
Add a superblock header around a set of subpackets.
Definition: rtpdec_qdm2.c:186
#define AV_WB32(p, v)
Definition: intreadwrite.h:419
uint8_t * buf
the temporary storage buffer
Definition: rtpdec_asf.c:183
const char * enc_name
Definition: rtpdec.h:116
#define flags(name, subs,...)
Definition: cbs_av1.c:561
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: avcodec.h:3982
#define RTP_NOTS_VALUE
Definition: rtpdec.h:40
#define av_freep(p)
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1028
int stream_index
Definition: avcodec.h:1482
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
enum AVCodecID id
This structure stores compressed data.
Definition: avcodec.h:1457