annotate rtpdec_qdm2.c @ 6455:3f50c7effad1 libavformat

rtsp: 10l, try to update the correct rtp stream This fixes a bug from rev 22917. Now RTSP streams where the individual RTCP sender reports aren't sent at the same time actually are synced properly.
author mstorsjo
date Fri, 03 Sep 2010 07:10:21 +0000
parents 491eea5c52d6
children 29e95ae56fa9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
6257
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
1 /*
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
2 * QDesign Music 2 (QDM2) payload for RTP
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
3 * Copyright (c) 2010 Ronald S. Bultje
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
4 *
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
5 * This file is part of FFmpeg.
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
6 *
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
11 *
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
15 * Lesser General Public License for more details.
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
16 *
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
20 */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
21
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
22 /**
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
23 * @file
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
24 * @brief RTP support for the QDM2 payload (todo: wiki)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
25 * @author Ronald S. Bultje <rbultje@ronald.bitfreak.net>
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
26 */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
27
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
28 #include <string.h>
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
29 #include "libavutil/intreadwrite.h"
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
30 #include "libavcodec/avcodec.h"
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
31 #include "rtp.h"
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
32 #include "rtpdec.h"
6339
491eea5c52d6 Remove mostly unnecessary rtpdec_*.h files, store the declarations in one file
mstorsjo
parents: 6257
diff changeset
33 #include "rtpdec_formats.h"
6257
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
34
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
35 struct PayloadContext {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
36 /** values read from the config header, used as packet headers */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
37 //@{
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
38 int block_type; ///< superblock type, value 2 .. 8
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
39 int block_size; ///< from extradata, used as pkt length
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
40 int subpkts_per_block; ///< max. nr. of subpackets to add per output buffer
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
41 //@}
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
42
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
43 /** Temporary storage for superblock restoring, per packet ID (0x80 total) */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
44 //@{
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
45 uint16_t len[0x80]; ///< how much the temporary buffer is filled
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
46 uint8_t buf[0x80][0x800]; ///< the temporary storage buffer
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
47
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
48 unsigned int cache; ///< number of data packets that we have cached right now
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
49 unsigned int n_pkts; ///< number of RTP packets received since last packet output / config
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
50 uint32_t timestamp; ///< timestamp of next-to-be-returned packet
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
51 //@}
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
52 };
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
53
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
54 /**
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
55 * Parses configuration (basically the codec-specific extradata) from
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
56 * a RTP config subpacket (starts with 0xff).
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
57 *
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
58 * Layout of the config subpacket (in bytes):
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
59 * 1: 0xFF <- config ID
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
60 * then an array {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
61 * 1: size <- of the current item
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
62 * 1: item type <- 0 .. 4
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
63 * size-2: data <- data depends on the item type
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
64 * }
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
65 *
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
66 * Item 0 implies the end of the config subpacket, and has no data.
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
67 * Item 1 implies a stream configuration without extradata.
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
68 * Item 2 max. nr. of subpackets per superblock
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
69 * Item 3 superblock type for the stream
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
70 * Item 4 implies a stream configuration with extradata (size >= 0x1c).
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
71 *
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
72 * @return <0 on error, otherwise the number of bytes parsed from the
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
73 * input buffer.
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
74 */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
75 static int qdm2_parse_config(PayloadContext *qdm, AVStream *st,
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
76 const uint8_t *buf, const uint8_t *end)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
77 {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
78 const uint8_t *p = buf;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
79
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
80 while (end - p >= 2) {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
81 unsigned int item_len = p[0], config_item = p[1];
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
82
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
83 if (item_len < 2 || end - p < item_len || config_item > 4)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
84 return AVERROR_INVALIDDATA;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
85
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
86 switch (config_item) {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
87 case 0: /* end of config block */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
88 return p - buf + item_len;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
89 case 1: /* stream without extradata */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
90 /* FIXME: set default qdm->block_size */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
91 break;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
92 case 2: /**< subpackets per block */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
93 if (item_len < 3)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
94 return AVERROR_INVALIDDATA;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
95 qdm->subpkts_per_block = p[2];
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
96 break;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
97 case 3: /* superblock type */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
98 if (item_len < 4)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
99 return AVERROR_INVALIDDATA;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
100 qdm->block_type = AV_RB16(p + 2);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
101 break;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
102 case 4: /* stream with extradata */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
103 if (item_len < 30)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
104 return AVERROR_INVALIDDATA;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
105 av_freep(&st->codec->extradata);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
106 st->codec->extradata_size = 26 + item_len;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
107 if (!(st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE))) {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
108 st->codec->extradata_size = 0;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
109 return AVERROR(ENOMEM);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
110 }
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
111 AV_WB32(st->codec->extradata, 12);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
112 memcpy(st->codec->extradata + 4, "frma", 4);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
113 memcpy(st->codec->extradata + 8, "QDM2", 4);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
114 AV_WB32(st->codec->extradata + 12, 6 + item_len);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
115 memcpy(st->codec->extradata + 16, "QDCA", 4);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
116 memcpy(st->codec->extradata + 20, p + 2, item_len - 2);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
117 AV_WB32(st->codec->extradata + 18 + item_len, 8);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
118 AV_WB32(st->codec->extradata + 22 + item_len, 0);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
119
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
120 qdm->block_size = AV_RB32(p + 26);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
121 break;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
122 }
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
123
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
124 p += item_len;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
125 }
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
126
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
127 return AVERROR(EAGAIN); /* not enough data */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
128 }
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
129
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
130 /**
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
131 * Parses a single subpacket. We store this subpacket in an intermediate
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
132 * buffer (position depends on the ID (byte[0]). When called, at least
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
133 * 4 bytes are available for reading (see qdm2_parse_packet()).
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
134 *
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
135 * Layout of a single subpacket (RTP packets commonly contain multiple
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
136 * such subpackets) - length in bytes:
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
137 * 1: ordering ID <- 0 .. 0x7F
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
138 * 1: subpacket type <- 0 .. 0x7F; value & 0x80 means subpacket length = 2 bytes, else 1 byte
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
139 * 1/2: subpacket length <- length of the data following the flags/length fields
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
140 * if (subpacket type & 0x7F) == 0x7F
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
141 * 1: subpacket type, higher bits
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
142 * size: subpacket data
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
143 *
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
144 * The subpackets come in randomly, and should be encapsulated into 1
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
145 * or more superblocks (containing qdm->subpkts_per_block subpackets
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
146 * each) per RTP packet, in order of ascending "ordering ID", see
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
147 * qdm2_restore_block().
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
148 *
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
149 * @return <0 on error, otherwise the number of bytes parsed from the
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
150 * input buffer.
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
151 */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
152 static int qdm2_parse_subpacket(PayloadContext *qdm, AVStream *st,
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
153 const uint8_t *buf, const uint8_t *end)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
154 {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
155 const uint8_t *p = buf;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
156 unsigned int id, len, type, to_copy;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
157
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
158 /* parse header so we know the size of the header/data */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
159 id = *p++;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
160 type = *p++;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
161 if (type & 0x80) {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
162 len = AV_RB16(p);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
163 p += 2;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
164 type &= 0x7F;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
165 } else
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
166 len = *p++;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
167
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
168 if (end - p < len + (type == 0x7F) || id >= 0x80)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
169 return AVERROR_INVALIDDATA;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
170 if (type == 0x7F)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
171 type |= *p++ << 8;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
172
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
173 /* copy data into a temporary buffer */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
174 to_copy = FFMIN(len + (p - &buf[1]), 0x800 - qdm->len[id]);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
175 memcpy(&qdm->buf[id][qdm->len[id]], buf + 1, to_copy);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
176 qdm->len[id] += to_copy;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
177
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
178 return p + len - buf;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
179 }
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
180
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
181 /**
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
182 * Adds a superblock header around a set of subpackets.
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
183 *
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
184 * @return <0 on error, else 0.
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
185 */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
186 static int qdm2_restore_block(PayloadContext *qdm, AVStream *st, AVPacket *pkt)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
187 {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
188 int to_copy, n, res, include_csum;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
189 uint8_t *p, *csum_pos = NULL;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
190
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
191 /* create packet to hold subpkts into a superblock */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
192 assert(qdm->cache > 0);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
193 for (n = 0; n < 0x80; n++)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
194 if (qdm->len[n] > 0)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
195 break;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
196 assert(n < 0x80);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
197
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
198 if ((res = av_new_packet(pkt, qdm->block_size)) < 0)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
199 return res;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
200 memset(pkt->data, 0, pkt->size);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
201 pkt->stream_index = st->index;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
202 p = pkt->data;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
203
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
204 /* superblock header */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
205 if (qdm->len[n] > 0xff) {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
206 *p++ = qdm->block_type | 0x80;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
207 AV_WB16(p, qdm->len[n]);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
208 p += 2;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
209 } else {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
210 *p++ = qdm->block_type;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
211 *p++ = qdm->len[n];
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
212 }
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
213 if ((include_csum = (qdm->block_type == 2 || qdm->block_type == 4))) {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
214 csum_pos = p;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
215 p += 2;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
216 }
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
217
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
218 /* subpacket data */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
219 to_copy = FFMIN(qdm->len[n], pkt->size - (p - pkt->data));
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
220 memcpy(p, qdm->buf[n], to_copy);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
221 qdm->len[n] = 0;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
222
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
223 /* checksum header */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
224 if (include_csum) {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
225 unsigned int total = 0;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
226 uint8_t *q;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
227
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
228 for (q = pkt->data; q < &pkt->data[qdm->block_size]; q++)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
229 total += *q;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
230 AV_WB16(csum_pos, (uint16_t) total);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
231 }
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
232
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
233 return 0;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
234 }
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
235
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
236 /** return 0 on packet, no more left, 1 on packet, -1 on partial packet... */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
237 static int qdm2_parse_packet(AVFormatContext *s, PayloadContext *qdm,
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
238 AVStream *st, AVPacket *pkt,
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
239 uint32_t *timestamp,
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
240 const uint8_t *buf, int len, int flags)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
241 {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
242 int res = AVERROR_INVALIDDATA, n;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
243 const uint8_t *end = buf + len, *p = buf;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
244
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
245 if (len > 0) {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
246 if (len < 2)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
247 return AVERROR_INVALIDDATA;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
248
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
249 /* configuration block */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
250 if (*p == 0xff) {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
251 if (qdm->n_pkts > 0) {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
252 av_log(s, AV_LOG_WARNING,
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
253 "Out of sequence config - dropping queue\n");
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
254 qdm->n_pkts = 0;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
255 memset(qdm->len, 0, sizeof(qdm->len));
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
256 }
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
257
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
258 if ((res = qdm2_parse_config(qdm, st, ++p, end)) < 0)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
259 return res;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
260 p += res;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
261
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
262 /* We set codec_id to CODEC_ID_NONE initially to
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
263 * delay decoder initialization since extradata is
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
264 * carried within the RTP stream, not SDP. Here,
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
265 * by setting codec_id to CODEC_ID_QDM2, we are signalling
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
266 * to the decoder that it is OK to initialize. */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
267 st->codec->codec_id = CODEC_ID_QDM2;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
268 }
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
269
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
270 /* subpackets */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
271 while (end - p >= 4) {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
272 if ((res = qdm2_parse_subpacket(qdm, st, p, end)) < 0)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
273 return res;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
274 p += res;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
275 }
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
276
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
277 qdm->timestamp = *timestamp;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
278 if (++qdm->n_pkts < qdm->subpkts_per_block)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
279 return AVERROR(EAGAIN);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
280 qdm->cache = 0;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
281 for (n = 0; n < 0x80; n++)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
282 if (qdm->len[n] > 0)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
283 qdm->cache++;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
284 }
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
285
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
286 /* output the subpackets into freshly created superblock structures */
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
287 if (!qdm->cache || (res = qdm2_restore_block(qdm, st, pkt)) < 0)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
288 return res;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
289 if (--qdm->cache == 0)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
290 qdm->n_pkts = 0;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
291
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
292 *timestamp = qdm->timestamp;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
293 qdm->timestamp = RTP_NOTS_VALUE;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
294
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
295 return (qdm->cache > 0) ? 1 : 0;
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
296 }
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
297
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
298 static PayloadContext *qdm2_extradata_new(void)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
299 {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
300 return av_mallocz(sizeof(PayloadContext));
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
301 }
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
302
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
303 static void qdm2_extradata_free(PayloadContext *qdm)
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
304 {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
305 av_free(qdm);
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
306 }
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
307
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
308 RTPDynamicProtocolHandler ff_qdm2_dynamic_handler = {
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
309 "X-QDM",
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
310 CODEC_TYPE_AUDIO,
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
311 CODEC_ID_NONE,
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
312 NULL,
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
313 qdm2_extradata_new,
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
314 qdm2_extradata_free,
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
315 qdm2_parse_packet,
0689434db2c6 Add a depacketizer for QDM2
mstorsjo
parents:
diff changeset
316 };