rtpdec_vp8.c
Go to the documentation of this file.
1 /*
2  * RTP VP8 Depacketizer
3  * Copyright (c) 2010 Josh Allmann
4  * Copyright (c) 2012 Martin Storsjo
5  *
6  * This file is part of FFmpeg.
7  *
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.
12  *
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.
17  *
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
21  */
22 
23 /**
24  * @file
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
28  */
29 
30 #include "libavcodec/bytestream.h"
31 
32 #include "rtpdec_formats.h"
33 
34 struct PayloadContext {
36  uint32_t timestamp;
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).
41  */
44  uint16_t prev_seq;
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.
50  */
53 };
54 
56 {
57  uint8_t *tmp;
58  if (!vp8->data)
59  return;
60  avio_close_dyn_buf(vp8->data, &tmp);
61  av_free(tmp);
62  vp8->data = NULL;
63 }
64 
66  const char *msg)
67 {
68  vp8->sequence_ok = 0;
69  av_log(ctx, AV_LOG_WARNING, "%s", msg);
70  vp8_free_buffer(vp8);
71  return AVERROR(EAGAIN);
72 }
73 
75  AVStream *st, AVPacket *pkt, uint32_t *timestamp,
76  const uint8_t *buf, int len, uint16_t seq,
77  int flags)
78 {
79  int start_partition, end_packet;
80  int extended_bits, part_id;
81  int pictureid_present = 0, tl0picidx_present = 0, tid_present = 0,
82  keyidx_present = 0;
83  int pictureid = -1, pictureid_mask = 0;
84  int returned_old_frame = 0;
85  uint32_t old_timestamp = 0;
86 
87  if (!buf) {
88  if (vp8->data) {
89  int ret = ff_rtp_finalize_packet(pkt, &vp8->data, st->index);
90  if (ret < 0)
91  return ret;
92  *timestamp = vp8->timestamp;
93  if (vp8->sequence_dirty)
94  pkt->flags |= AV_PKT_FLAG_CORRUPT;
95  return 0;
96  }
97  return AVERROR(EAGAIN);
98  }
99 
100  if (len < 1)
101  return AVERROR_INVALIDDATA;
102 
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;
107  buf++;
108  len--;
109  if (extended_bits) {
110  if (len < 1)
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;
116  buf++;
117  len--;
118  }
119  if (pictureid_present) {
120  if (len < 1)
121  return AVERROR_INVALIDDATA;
122  if (buf[0] & 0x80) {
123  if (len < 2)
124  return AVERROR_INVALIDDATA;
125  pictureid = AV_RB16(buf) & 0x7fff;
126  pictureid_mask = 0x7fff;
127  buf += 2;
128  len -= 2;
129  } else {
130  pictureid = buf[0] & 0x7f;
131  pictureid_mask = 0x7f;
132  buf++;
133  len--;
134  }
135  }
136  if (tl0picidx_present) {
137  // Ignoring temporal level zero index
138  buf++;
139  len--;
140  }
141  if (tid_present || keyidx_present) {
142  // Ignoring temporal layer index, layer sync bit and keyframe index
143  buf++;
144  len--;
145  }
146  if (len < 1)
147  return AVERROR_INVALIDDATA;
148 
149  if (start_partition && part_id == 0 && len >= 3) {
150  int res;
151  int non_key = buf[0] & 0x01;
152  if (!non_key) {
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;
158  } else {
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");
169  } else {
170  if (vp8->data && !can_continue)
171  return vp8_broken_sequence(ctx, vp8,
172  "Missed a picture, sequence broken\n");
173  }
174  } else {
175  uint16_t expected_seq = vp8->prev_seq + 1;
176  int16_t diff = seq - expected_seq;
177  if (vp8->data) {
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
187  } else {
188  return vp8_broken_sequence(ctx, vp8,
189  "Missed too much, sequence broken\n");
190  }
191  } else {
192  if (diff != 0)
193  return vp8_broken_sequence(ctx, vp8,
194  "Missed unknown data, sequence broken\n");
195  }
196  }
197  if (vp8->data) {
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);
201  if (ret < 0)
202  return ret;
203  pkt->flags |= AV_PKT_FLAG_CORRUPT;
204  returned_old_frame = 1;
205  old_timestamp = vp8->timestamp;
206  } else {
207  // Shouldn't happen
208  vp8_free_buffer(vp8);
209  }
210  }
211  }
212  vp8->first_part_size = (AV_RL16(&buf[1]) << 3 | buf[0] >> 5) + 3;
213  if ((res = avio_open_dyn_buf(&vp8->data)) < 0)
214  return res;
215  vp8->timestamp = *timestamp;
216  vp8->broken_frame = 0;
217  vp8->prev_pictureid = pictureid;
218  vp8->is_keyframe = !non_key;
219  } else {
220  uint16_t expected_seq = vp8->prev_seq + 1;
221 
222  if (!vp8->sequence_ok)
223  return AVERROR(EAGAIN);
224 
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");
229  }
230 
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;
238  } else {
239  return vp8_broken_sequence(ctx, vp8,
240  "Missed part of the first partition, sequence broken\n");
241  }
242  }
243  }
244 
245  if (!vp8->data)
246  return vp8_broken_sequence(ctx, vp8, "Received no start marker\n");
247 
248  vp8->prev_seq = seq;
249  if (!vp8->broken_frame)
250  avio_write(vp8->data, buf, len);
251 
252  if (returned_old_frame) {
253  *timestamp = old_timestamp;
254  return end_packet ? 1 : 0;
255  }
256 
257  if (end_packet) {
258  int ret;
259  ret = ff_rtp_finalize_packet(pkt, &vp8->data, st->index);
260  if (ret < 0)
261  return ret;
262  if (vp8->sequence_dirty)
263  pkt->flags |= AV_PKT_FLAG_CORRUPT;
264  return 0;
265  }
266 
267  return AVERROR(EAGAIN);
268 }
269 
271 {
272  PayloadContext *vp8 = av_mallocz(sizeof(PayloadContext));
273  if (!vp8)
274  return NULL;
275  vp8->sequence_ok = 1;
276  return vp8;
277 }
278 
280 {
281  vp8_free_buffer(vp8);
282  av_free(vp8);
283 }
284 
286 {
287  return vp8->sequence_dirty || !vp8->sequence_ok;
288 }
289 
291  .enc_name = "VP8",
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,
298 };
AVPacket pkt
Definition: rtpdec_qt.c:37
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:205
Bytestream IO Context.
Definition: avio.h:68
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:988
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
RTP/JPEG specific private data.
Definition: rdt.c:83
int index
stream index in AVFormatContext
Definition: avformat.h:644
static void vp8_free_buffer(PayloadContext *vp8)
Definition: rtpdec_vp8.c:55
#define AV_RL16
uint8_t * buf
the temporary storage buffer
Definition: rtpdec_asf.c:160
RTPDynamicProtocolHandler ff_vp8_dynamic_handler
Definition: rtpdec_vp8.c:290
int first_part_size
Definition: rtpdec_vp8.c:43
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition: aviobuf.c:976
uint16_t prev_seq
Definition: rtpdec_vp8.c:44
Format I/O context.
Definition: avformat.h:944
uint8_t
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:248
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:173
uint32_t timestamp
current frame timestamp
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
#define RTP_FLAG_MARKER
RTP marker bit was set for this packet.
Definition: rtpdec.h:97
#define AV_RB16
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
static int vp8_handle_packet(AVFormatContext *ctx, PayloadContext *vp8, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len, uint16_t seq, int flags)
Definition: rtpdec_vp8.c:74
int flags
A combination of AV_PKT_FLAG values.
static void vp8_free_context(PayloadContext *vp8)
Definition: rtpdec_vp8.c:279
ret
Definition: avfilter.c:821
static int vp8_need_keyframe(PayloadContext *vp8)
Definition: rtpdec_vp8.c:285
int prev_pictureid
Definition: rtpdec_vp8.c:45
int sequence_dirty
Definition: rtpdec_vp8.c:51
#define diff(a, as, b, bs)
Definition: vf_phase.c:80
Stream structure.
Definition: avformat.h:643
NULL
Definition: eval.c:55
AVIOContext * data
Definition: rtpdec_vp8.c:35
static PayloadContext * vp8_new_context(void)
Definition: rtpdec_vp8.c:270
const char enc_name[50]
Definition: rtpdec.h:120
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer 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.Buffer references ownership and permissions
static int flags
Definition: cpu.c:23
static int vp8_broken_sequence(AVFormatContext *ctx, PayloadContext *vp8, const char *msg)
Definition: rtpdec_vp8.c:65
#define AV_PKT_FLAG_CORRUPT
The packet content is corrupted.
int ff_rtp_finalize_packet(AVPacket *pkt, AVIOContext **dyn_buf, int stream_idx)
Close the dynamic buffer and make a packet from it.
Definition: rtpdec.c:865
This structure stores compressed data.