3 * Copyright (c) 2010 Josh Allmann
4 * Copyright (c) 2012 Martin Storsjo
6 * This file is part of FFmpeg.
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.
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.
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
25 * @brief RTP support for the VP8 payload
26 * @author Josh Allmann <joshua.allmann@gmail.com>
27 * @see http://tools.ietf.org/html/draft-ietf-payload-vp8-05
30 #include "libavcodec/bytestream.h"
32 #include "rtpdec_formats.h"
34 struct PayloadContext
{
38 /* If sequence_ok is set, we keep returning data (even if we might have
39 * lost some data, but we haven't lost any too critical data that would
40 * cause the decoder to desynchronize and output random garbage).
47 /* If sequence_dirty is set, we have lost some data (critical or
48 * non-critical) and decoding will have some sort of artefacts, and
49 * we thus should request a new keyframe.
55 static void vp8_free_buffer(PayloadContext
*vp8
)
60 avio_close_dyn_buf(vp8
->data
, &tmp
);
65 static int vp8_broken_sequence(AVFormatContext
*ctx
, PayloadContext
*vp8
,
69 av_log(ctx
, AV_LOG_WARNING
, "%s", msg
);
71 return AVERROR(EAGAIN
);
74 static int vp8_handle_packet(AVFormatContext
*ctx
, PayloadContext
*vp8
,
75 AVStream
*st
, AVPacket
*pkt
, uint32_t *timestamp
,
76 const uint8_t *buf
, int len
, uint16_t seq
,
79 int start_partition
, end_packet
;
80 int extended_bits
, part_id
;
81 int pictureid_present
= 0, tl0picidx_present
= 0, tid_present
= 0,
83 int pictureid
= -1, pictureid_mask
= 0;
84 int returned_old_frame
= 0;
85 uint32_t old_timestamp
= 0;
89 int ret
= ff_rtp_finalize_packet(pkt
, &vp8
->data
, st
->index
);
92 *timestamp
= vp8
->timestamp
;
93 if (vp8
->sequence_dirty
)
94 pkt
->flags
|= AV_PKT_FLAG_CORRUPT
;
97 return AVERROR(EAGAIN
);
101 return AVERROR_INVALIDDATA
;
103 extended_bits
= buf
[0] & 0x80;
104 start_partition
= buf
[0] & 0x10;
105 part_id
= buf
[0] & 0x0f;
106 end_packet
= flags
& RTP_FLAG_MARKER
;
111 return AVERROR_INVALIDDATA
;
112 pictureid_present
= buf
[0] & 0x80;
113 tl0picidx_present
= buf
[0] & 0x40;
114 tid_present
= buf
[0] & 0x20;
115 keyidx_present
= buf
[0] & 0x10;
119 if (pictureid_present
) {
121 return AVERROR_INVALIDDATA
;
124 return AVERROR_INVALIDDATA
;
125 pictureid
= AV_RB16(buf
) & 0x7fff;
126 pictureid_mask
= 0x7fff;
130 pictureid
= buf
[0] & 0x7f;
131 pictureid_mask
= 0x7f;
136 if (tl0picidx_present
) {
137 // Ignoring temporal level zero index
141 if (tid_present
|| keyidx_present
) {
142 // Ignoring temporal layer index, layer sync bit and keyframe index
147 return AVERROR_INVALIDDATA
;
149 if (start_partition
&& part_id
== 0 && len
>= 3) {
151 int non_key
= buf
[0] & 0x01;
153 vp8_free_buffer(vp8
);
154 // Keyframe, decoding ok again
155 vp8
->sequence_ok
= 1;
156 vp8
->sequence_dirty
= 0;
157 vp8
->got_keyframe
= 1;
159 int can_continue
= vp8
->data
&& !vp8
->is_keyframe
&&
160 avio_tell(vp8
->data
) >= vp8
->first_part_size
;
161 if (!vp8
->sequence_ok
)
162 return AVERROR(EAGAIN
);
163 if (!vp8
->got_keyframe
)
164 return vp8_broken_sequence(ctx
, vp8
, "Keyframe missing\n");
165 if (pictureid
>= 0) {
166 if (pictureid
!= ((vp8
->prev_pictureid
+ 1) & pictureid_mask
)) {
167 return vp8_broken_sequence(ctx
, vp8
,
168 "Missed a picture, sequence broken\n");
170 if (vp8
->data
&& !can_continue
)
171 return vp8_broken_sequence(ctx
, vp8
,
172 "Missed a picture, sequence broken\n");
175 uint16_t expected_seq
= vp8
->prev_seq
+ 1;
176 int16_t diff
= seq
- expected_seq
;
178 // No picture id, so we can't know if missed packets
179 // contained any new frames. If diff == 0, we did get
180 // later packets from the same frame (matching timestamp),
181 // so we know we didn't miss any frame. If diff == 1 and
182 // we still have data (not flushed by the end of frame
183 // marker), the single missed packet must have been part
184 // of the same frame.
185 if ((diff
== 0 || diff
== 1) && can_continue
) {
186 // Proceed with what we have
188 return vp8_broken_sequence(ctx
, vp8
,
189 "Missed too much, sequence broken\n");
193 return vp8_broken_sequence(ctx
, vp8
,
194 "Missed unknown data, sequence broken\n");
198 vp8
->sequence_dirty
= 1;
199 if (avio_tell(vp8
->data
) >= vp8
->first_part_size
) {
200 int ret
= ff_rtp_finalize_packet(pkt
, &vp8
->data
, st
->index
);
203 pkt
->flags
|= AV_PKT_FLAG_CORRUPT
;
204 returned_old_frame
= 1;
205 old_timestamp
= vp8
->timestamp
;
208 vp8_free_buffer(vp8
);
212 vp8
->first_part_size
= (AV_RL16(&buf
[1]) << 3 | buf
[0] >> 5) + 3;
213 if ((res
= avio_open_dyn_buf(&vp8
->data
)) < 0)
215 vp8
->timestamp
= *timestamp
;
216 vp8
->broken_frame
= 0;
217 vp8
->prev_pictureid
= pictureid
;
218 vp8
->is_keyframe
= !non_key
;
220 uint16_t expected_seq
= vp8
->prev_seq
+ 1;
222 if (!vp8
->sequence_ok
)
223 return AVERROR(EAGAIN
);
225 if (vp8
->timestamp
!= *timestamp
) {
226 // Missed the start of the new frame, sequence broken
227 return vp8_broken_sequence(ctx
, vp8
,
228 "Received no start marker; dropping frame\n");
231 if (seq
!= expected_seq
) {
232 if (vp8
->is_keyframe
) {
233 return vp8_broken_sequence(ctx
, vp8
,
234 "Missed part of a keyframe, sequence broken\n");
235 } else if (vp8
->data
&& avio_tell(vp8
->data
) >= vp8
->first_part_size
) {
236 vp8
->broken_frame
= 1;
237 vp8
->sequence_dirty
= 1;
239 return vp8_broken_sequence(ctx
, vp8
,
240 "Missed part of the first partition, sequence broken\n");
246 return vp8_broken_sequence(ctx
, vp8
, "Received no start marker\n");
249 if (!vp8
->broken_frame
)
250 avio_write(vp8
->data
, buf
, len
);
252 if (returned_old_frame
) {
253 *timestamp
= old_timestamp
;
254 return end_packet
? 1 : 0;
259 ret
= ff_rtp_finalize_packet(pkt
, &vp8
->data
, st
->index
);
262 if (vp8
->sequence_dirty
)
263 pkt
->flags
|= AV_PKT_FLAG_CORRUPT
;
267 return AVERROR(EAGAIN
);
270 static PayloadContext
*vp8_new_context(void)
272 PayloadContext
*vp8
= av_mallocz(sizeof(PayloadContext
));
275 vp8
->sequence_ok
= 1;
279 static void vp8_free_context(PayloadContext
*vp8
)
281 vp8_free_buffer(vp8
);
285 static int vp8_need_keyframe(PayloadContext
*vp8
)
287 return vp8
->sequence_dirty
|| !vp8
->sequence_ok
;
290 RTPDynamicProtocolHandler ff_vp8_dynamic_handler
= {
292 .codec_type
= AVMEDIA_TYPE_VIDEO
,
293 .codec_id
= AV_CODEC_ID_VP8
,
294 .alloc
= vp8_new_context
,
295 .free
= vp8_free_context
,
296 .parse_packet
= vp8_handle_packet
,
297 .need_keyframe
= vp8_need_keyframe
,