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  int ret;
82 
83  while (end - p >= 2) {
84  unsigned int item_len = p[0], config_item = p[1];
85 
86  if (item_len < 2 || end - p < item_len || config_item > 4)
87  return AVERROR_INVALIDDATA;
88 
89  switch (config_item) {
90  case 0: /* end of config block */
91  return p - buf + item_len;
92  case 1: /* stream without extradata */
93  /* FIXME: set default qdm->block_size */
94  break;
95  case 2: /**< subpackets per block */
96  if (item_len < 3)
97  return AVERROR_INVALIDDATA;
98  qdm->subpkts_per_block = p[2];
99  break;
100  case 3: /* superblock type */
101  if (item_len < 4)
102  return AVERROR_INVALIDDATA;
103  qdm->block_type = AV_RB16(p + 2);
104  break;
105  case 4: /* stream with extradata */
106  if (item_len < 30)
107  return AVERROR_INVALIDDATA;
108 
109  ret = ff_alloc_extradata(st->codecpar, 26 + item_len);
110  if (ret < 0) {
111  return ret;
112  }
113  AV_WB32(st->codecpar->extradata, 12);
114  memcpy(st->codecpar->extradata + 4, "frma", 4);
115  memcpy(st->codecpar->extradata + 8, "QDM2", 4);
116  AV_WB32(st->codecpar->extradata + 12, 6 + item_len);
117  memcpy(st->codecpar->extradata + 16, "QDCA", 4);
118  memcpy(st->codecpar->extradata + 20, p + 2, item_len - 2);
119  AV_WB32(st->codecpar->extradata + 18 + item_len, 8);
120  AV_WB32(st->codecpar->extradata + 22 + item_len, 0);
121 
122  qdm->block_size = AV_RB32(p + 26);
123  break;
124  }
125 
126  p += item_len;
127  }
128 
129  return AVERROR(EAGAIN); /* not enough data */
130 }
131 
132 /**
133  * Parse a single subpacket. We store this subpacket in an intermediate
134  * buffer (position depends on the ID (byte[0]). When called, at least
135  * 4 bytes are available for reading (see qdm2_parse_packet()).
136  *
137  * Layout of a single subpacket (RTP packets commonly contain multiple
138  * such subpackets) - length in bytes:
139  * 1: ordering ID <- 0 .. 0x7F
140  * 1: subpacket type <- 0 .. 0x7F; value & 0x80 means subpacket length = 2 bytes, else 1 byte
141  * 1/2: subpacket length <- length of the data following the flags/length fields
142  * if (subpacket type & 0x7F) == 0x7F
143  * 1: subpacket type, higher bits
144  * size: subpacket data
145  *
146  * The subpackets come in randomly, and should be encapsulated into 1
147  * or more superblocks (containing qdm->subpkts_per_block subpackets
148  * each) per RTP packet, in order of ascending "ordering ID", see
149  * qdm2_restore_block().
150  *
151  * @return <0 on error, otherwise the number of bytes parsed from the
152  * input buffer.
153  */
155  const uint8_t *buf, const uint8_t *end)
156 {
157  const uint8_t *p = buf;
158  unsigned int id, len, type, to_copy;
159 
160  /* parse header so we know the size of the header/data */
161  id = *p++;
162  type = *p++;
163  if (type & 0x80) {
164  len = AV_RB16(p);
165  p += 2;
166  type &= 0x7F;
167  } else
168  len = *p++;
169 
170  if (end - p < len + (type == 0x7F) || id >= 0x80)
171  return AVERROR_INVALIDDATA;
172  if (type == 0x7F)
173  type |= *p++ << 8;
174 
175  /* copy data into a temporary buffer */
176  to_copy = FFMIN(len + (p - &buf[1]), 0x800 - qdm->len[id]);
177  memcpy(&qdm->buf[id][qdm->len[id]], buf + 1, to_copy);
178  qdm->len[id] += to_copy;
179 
180  return p + len - buf;
181 }
182 
183 /**
184  * Add a superblock header around a set of subpackets.
185  *
186  * @return <0 on error, else 0.
187  */
189 {
190  int to_copy, n, res, include_csum;
191  uint8_t *p, *csum_pos = NULL;
192 
193  /* create packet to hold subpkts into a superblock */
194  av_assert0(qdm->cache > 0);
195  for (n = 0; n < 0x80; n++)
196  if (qdm->len[n] > 0)
197  break;
198  av_assert0(n < 0x80);
199 
200  if ((res = av_new_packet(pkt, qdm->block_size)) < 0)
201  return res;
202  memset(pkt->data, 0, pkt->size);
203  pkt->stream_index = st->index;
204  p = pkt->data;
205 
206  /* superblock header */
207  if (qdm->len[n] > 0xff) {
208  *p++ = qdm->block_type | 0x80;
209  AV_WB16(p, qdm->len[n]);
210  p += 2;
211  } else {
212  *p++ = qdm->block_type;
213  *p++ = qdm->len[n];
214  }
215  if ((include_csum = (qdm->block_type == 2 || qdm->block_type == 4))) {
216  csum_pos = p;
217  p += 2;
218  }
219 
220  /* subpacket data */
221  to_copy = FFMIN(qdm->len[n], pkt->size - (p - pkt->data));
222  memcpy(p, qdm->buf[n], to_copy);
223  qdm->len[n] = 0;
224 
225  /* checksum header */
226  if (include_csum) {
227  unsigned int total = 0;
228  uint8_t *q;
229 
230  for (q = pkt->data; q < &pkt->data[qdm->block_size]; q++)
231  total += *q;
232  AV_WB16(csum_pos, (uint16_t) total);
233  }
234 
235  return 0;
236 }
237 
238 /** return 0 on packet, no more left, 1 on packet, -1 on partial packet... */
240  AVStream *st, AVPacket *pkt,
241  uint32_t *timestamp,
242  const uint8_t *buf, int len, uint16_t seq,
243  int flags)
244 {
245  int res = AVERROR_INVALIDDATA, n;
246  const uint8_t *end = buf + len, *p = buf;
247 
248  if (len > 0) {
249  if (len < 2)
250  return AVERROR_INVALIDDATA;
251 
252  /* configuration block */
253  if (*p == 0xff) {
254  if (qdm->n_pkts > 0) {
256  "Out of sequence config - dropping queue\n");
257  qdm->n_pkts = 0;
258  memset(qdm->len, 0, sizeof(qdm->len));
259  }
260 
261  if ((res = qdm2_parse_config(qdm, st, ++p, end)) < 0)
262  return res;
263  p += res;
264 
265  /* We set codec_id to AV_CODEC_ID_NONE initially to
266  * delay decoder initialization since extradata is
267  * carried within the RTP stream, not SDP. Here,
268  * by setting codec_id to AV_CODEC_ID_QDM2, we are signalling
269  * to the decoder that it is OK to initialize. */
271  }
272  if (st->codecpar->codec_id == AV_CODEC_ID_NONE)
273  return AVERROR(EAGAIN);
274 
275  /* subpackets */
276  while (end - p >= 4) {
277  if ((res = qdm2_parse_subpacket(qdm, st, p, end)) < 0)
278  return res;
279  p += res;
280  }
281 
282  qdm->timestamp = *timestamp;
283  if (++qdm->n_pkts < qdm->subpkts_per_block)
284  return AVERROR(EAGAIN);
285  qdm->cache = 0;
286  for (n = 0; n < 0x80; n++)
287  if (qdm->len[n] > 0)
288  qdm->cache++;
289  }
290 
291  /* output the subpackets into freshly created superblock structures */
292  if (!qdm->cache || (res = qdm2_restore_block(qdm, st, pkt)) < 0)
293  return res;
294  if (--qdm->cache == 0)
295  qdm->n_pkts = 0;
296 
297  *timestamp = qdm->timestamp;
298  qdm->timestamp = RTP_NOTS_VALUE;
299 
300  return (qdm->cache > 0) ? 1 : 0;
301 }
302 
304  .enc_name = "X-QDM",
305  .codec_type = AVMEDIA_TYPE_AUDIO,
306  .codec_id = AV_CODEC_ID_NONE,
307  .priv_data_size = sizeof(PayloadContext),
309 };
AVPacket pkt
Definition: rtpdec_qt.c:37
const RTPDynamicProtocolHandler ff_qdm2_dynamic_handler
Definition: rtpdec_qdm2.c:303
#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:200
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:1396
RTP/JPEG specific private data.
Definition: rdt.c:83
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:60
int index
stream index in AVFormatContext
Definition: avformat.h:877
int size
Definition: packet.h:364
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:1351
#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:92
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: packet.h:363
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:154
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:88
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:239
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:3259
#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
Stream structure.
Definition: avformat.h:876
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:188
#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:560
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: codec_par.h:74
#define RTP_NOTS_VALUE
Definition: rtpdec.h:40
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1023
int stream_index
Definition: packet.h:365
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: packet.h:340