Skip to content

Commit db30ce1

Browse files
alfredhrichaas
authored andcommitted
rtmp: proper handling of extended timestamps (#184)
1 parent dab3e4b commit db30ce1

File tree

3 files changed

+59
-18
lines changed

3 files changed

+59
-18
lines changed

src/rtmp/dechunk.c

+16
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,28 @@ int rtmp_dechunker_receive(struct rtmp_dechunker *rd, struct mbuf *mb)
184184
chunk->mb->end = chunk_sz;
185185

186186
chunk->hdr.format = hdr.format;
187+
chunk->hdr.ext_ts = hdr.ext_ts;
187188

188189
if (hdr.format == 1 || hdr.format == 2)
189190
chunk->hdr.timestamp += hdr.timestamp_delta;
190191
break;
191192

192193
case 3:
194+
if (chunk->hdr.ext_ts) {
195+
196+
uint32_t ext_ts;
197+
198+
if (mbuf_get_left(mb) < 4)
199+
return ENODATA;
200+
201+
ext_ts = ntohl(mbuf_read_u32(mb));
202+
203+
if (chunk->hdr.format == 0)
204+
chunk->hdr.timestamp = ext_ts;
205+
else
206+
chunk->hdr.timestamp_delta = ext_ts;
207+
}
208+
193209
if (!chunk->mb) {
194210

195211
chunk->mb = mbuf_alloc(chunk->hdr.length);

src/rtmp/hdr.c

+40-17
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ enum {
2121
RTMP_CHUNK_ID_MAX = 65599, /* 65535 + 64 */
2222

2323
RTMP_CHUNK_OFFSET = 64,
24+
TIMESTAMP_24MAX = 0x00ffffff,
2425
};
2526

2627

@@ -121,9 +122,20 @@ static int decode_basic_hdr(struct rtmp_header *hdr, struct mbuf *mb)
121122
}
122123

123124

124-
int rtmp_header_encode(struct mbuf *mb, const struct rtmp_header *hdr)
125+
static uint32_t ts_24(uint32_t ts)
126+
{
127+
return ts >= TIMESTAMP_24MAX ? TIMESTAMP_24MAX : ts;
128+
}
129+
130+
131+
static uint32_t ts_ext(uint32_t ts)
132+
{
133+
return ts >= TIMESTAMP_24MAX ? ts : 0;
134+
}
135+
136+
137+
int rtmp_header_encode(struct mbuf *mb, struct rtmp_header *hdr)
125138
{
126-
bool ext_ts;
127139
int err = 0;
128140

129141
if (!mb || !hdr)
@@ -136,39 +148,43 @@ int rtmp_header_encode(struct mbuf *mb, const struct rtmp_header *hdr)
136148
switch (hdr->format) {
137149

138150
case 0:
139-
ext_ts = (hdr->timestamp >= 0x00ffffff);
151+
hdr->timestamp_ext = ts_ext(hdr->timestamp);
140152

141-
err |= mbuf_write_u24_hton(mb,
142-
ext_ts ? 0xffffff : hdr->timestamp);
153+
err |= mbuf_write_u24_hton(mb, ts_24(hdr->timestamp));
143154
err |= mbuf_write_u24_hton(mb, hdr->length);
144155
err |= mbuf_write_u8(mb, hdr->type_id);
145156
err |= mbuf_write_u32(mb, sys_htoll(hdr->stream_id));
146-
147-
if (ext_ts) {
148-
err |= mbuf_write_u32(mb, htonl(hdr->timestamp));
149-
}
150157
break;
151158

152159
case 1:
153-
err |= mbuf_write_u24_hton(mb, hdr->timestamp_delta);
160+
hdr->timestamp_ext = ts_ext(hdr->timestamp_delta);
161+
162+
err |= mbuf_write_u24_hton(mb, ts_24(hdr->timestamp_delta));
154163
err |= mbuf_write_u24_hton(mb, hdr->length);
155164
err |= mbuf_write_u8(mb, hdr->type_id);
156165
break;
157166

158167
case 2:
159-
err |= mbuf_write_u24_hton(mb, hdr->timestamp_delta);
168+
hdr->timestamp_ext = ts_ext(hdr->timestamp_delta);
169+
170+
err |= mbuf_write_u24_hton(mb, ts_24(hdr->timestamp_delta));
160171
break;
161172

162173
case 3:
163174
break;
164175
}
165176

177+
if (hdr->timestamp_ext) {
178+
err |= mbuf_write_u32(mb, htonl(hdr->timestamp_ext));
179+
}
180+
166181
return err;
167182
}
168183

169184

170185
int rtmp_header_decode(struct rtmp_header *hdr, struct mbuf *mb)
171186
{
187+
uint32_t *timestamp_ext = NULL;
172188
int err;
173189

174190
if (!hdr || !mb)
@@ -190,12 +206,6 @@ int rtmp_header_decode(struct rtmp_header *hdr, struct mbuf *mb)
190206
hdr->length = mbuf_read_u24_ntoh(mb);
191207
hdr->type_id = mbuf_read_u8(mb);
192208
hdr->stream_id = sys_ltohl(mbuf_read_u32(mb));
193-
194-
if (hdr->timestamp == 0x00ffffff) {
195-
if (mbuf_get_left(mb) < 4)
196-
return ENODATA;
197-
hdr->timestamp = ntohl(mbuf_read_u32(mb));
198-
}
199209
break;
200210

201211
case 1:
@@ -219,6 +229,19 @@ int rtmp_header_decode(struct rtmp_header *hdr, struct mbuf *mb)
219229
break;
220230
}
221231

232+
if (hdr->timestamp == TIMESTAMP_24MAX)
233+
timestamp_ext = &hdr->timestamp;
234+
else if (hdr->timestamp_delta == TIMESTAMP_24MAX)
235+
timestamp_ext = &hdr->timestamp_delta;
236+
237+
if (timestamp_ext) {
238+
if (mbuf_get_left(mb) < 4)
239+
return ENODATA;
240+
241+
*timestamp_ext = ntohl(mbuf_read_u32(mb));
242+
hdr->ext_ts = true;
243+
}
244+
222245
return 0;
223246
}
224247

src/rtmp/rtmp.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,11 @@ struct rtmp_header {
8888

8989
uint32_t timestamp; /* 24-bit or 32-bit */
9090
uint32_t timestamp_delta; /* 24-bit */
91+
uint32_t timestamp_ext;
9192
uint32_t length; /* 24-bit */
9293
uint8_t type_id; /* enum rtmp_packet_type */
9394
uint32_t stream_id;
95+
bool ext_ts;
9496
};
9597

9698

@@ -139,7 +141,7 @@ int rtmp_chunker(unsigned format, uint32_t chunk_id,
139141
* RTMP Header
140142
*/
141143

142-
int rtmp_header_encode(struct mbuf *mb, const struct rtmp_header *hdr);
144+
int rtmp_header_encode(struct mbuf *mb, struct rtmp_header *hdr);
143145
int rtmp_header_decode(struct rtmp_header *hdr, struct mbuf *mb);
144146
int rtmp_header_print(struct re_printf *pf, const struct rtmp_header *hdr);
145147
const char *rtmp_packet_type_name(enum rtmp_packet_type type);

0 commit comments

Comments
 (0)