annotate ffmpeg/libavformat/rtpdec_vp8.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /*
yading@11 2 * RTP VP8 Depacketizer
yading@11 3 * Copyright (c) 2010 Josh Allmann
yading@11 4 * Copyright (c) 2012 Martin Storsjo
yading@11 5 *
yading@11 6 * This file is part of FFmpeg.
yading@11 7 *
yading@11 8 * FFmpeg is free software; you can redistribute it and/or
yading@11 9 * modify it under the terms of the GNU Lesser General Public
yading@11 10 * License as published by the Free Software Foundation; either
yading@11 11 * version 2.1 of the License, or (at your option) any later version.
yading@11 12 *
yading@11 13 * FFmpeg is distributed in the hope that it will be useful,
yading@11 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 16 * Lesser General Public License for more details.
yading@11 17 *
yading@11 18 * You should have received a copy of the GNU Lesser General Public
yading@11 19 * License along with FFmpeg; if not, write to the Free Software
yading@11 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 21 */
yading@11 22
yading@11 23 /**
yading@11 24 * @file
yading@11 25 * @brief RTP support for the VP8 payload
yading@11 26 * @author Josh Allmann <joshua.allmann@gmail.com>
yading@11 27 * @see http://tools.ietf.org/html/draft-ietf-payload-vp8-05
yading@11 28 */
yading@11 29
yading@11 30 #include "libavcodec/bytestream.h"
yading@11 31
yading@11 32 #include "rtpdec_formats.h"
yading@11 33
yading@11 34 struct PayloadContext {
yading@11 35 AVIOContext *data;
yading@11 36 uint32_t timestamp;
yading@11 37 int is_keyframe;
yading@11 38 /* If sequence_ok is set, we keep returning data (even if we might have
yading@11 39 * lost some data, but we haven't lost any too critical data that would
yading@11 40 * cause the decoder to desynchronize and output random garbage).
yading@11 41 */
yading@11 42 int sequence_ok;
yading@11 43 int first_part_size;
yading@11 44 uint16_t prev_seq;
yading@11 45 int prev_pictureid;
yading@11 46 int broken_frame;
yading@11 47 /* If sequence_dirty is set, we have lost some data (critical or
yading@11 48 * non-critical) and decoding will have some sort of artefacts, and
yading@11 49 * we thus should request a new keyframe.
yading@11 50 */
yading@11 51 int sequence_dirty;
yading@11 52 int got_keyframe;
yading@11 53 };
yading@11 54
yading@11 55 static void vp8_free_buffer(PayloadContext *vp8)
yading@11 56 {
yading@11 57 uint8_t *tmp;
yading@11 58 if (!vp8->data)
yading@11 59 return;
yading@11 60 avio_close_dyn_buf(vp8->data, &tmp);
yading@11 61 av_free(tmp);
yading@11 62 vp8->data = NULL;
yading@11 63 }
yading@11 64
yading@11 65 static int vp8_broken_sequence(AVFormatContext *ctx, PayloadContext *vp8,
yading@11 66 const char *msg)
yading@11 67 {
yading@11 68 vp8->sequence_ok = 0;
yading@11 69 av_log(ctx, AV_LOG_WARNING, "%s", msg);
yading@11 70 vp8_free_buffer(vp8);
yading@11 71 return AVERROR(EAGAIN);
yading@11 72 }
yading@11 73
yading@11 74 static int vp8_handle_packet(AVFormatContext *ctx, PayloadContext *vp8,
yading@11 75 AVStream *st, AVPacket *pkt, uint32_t *timestamp,
yading@11 76 const uint8_t *buf, int len, uint16_t seq,
yading@11 77 int flags)
yading@11 78 {
yading@11 79 int start_partition, end_packet;
yading@11 80 int extended_bits, part_id;
yading@11 81 int pictureid_present = 0, tl0picidx_present = 0, tid_present = 0,
yading@11 82 keyidx_present = 0;
yading@11 83 int pictureid = -1, pictureid_mask = 0;
yading@11 84 int returned_old_frame = 0;
yading@11 85 uint32_t old_timestamp = 0;
yading@11 86
yading@11 87 if (!buf) {
yading@11 88 if (vp8->data) {
yading@11 89 int ret = ff_rtp_finalize_packet(pkt, &vp8->data, st->index);
yading@11 90 if (ret < 0)
yading@11 91 return ret;
yading@11 92 *timestamp = vp8->timestamp;
yading@11 93 if (vp8->sequence_dirty)
yading@11 94 pkt->flags |= AV_PKT_FLAG_CORRUPT;
yading@11 95 return 0;
yading@11 96 }
yading@11 97 return AVERROR(EAGAIN);
yading@11 98 }
yading@11 99
yading@11 100 if (len < 1)
yading@11 101 return AVERROR_INVALIDDATA;
yading@11 102
yading@11 103 extended_bits = buf[0] & 0x80;
yading@11 104 start_partition = buf[0] & 0x10;
yading@11 105 part_id = buf[0] & 0x0f;
yading@11 106 end_packet = flags & RTP_FLAG_MARKER;
yading@11 107 buf++;
yading@11 108 len--;
yading@11 109 if (extended_bits) {
yading@11 110 if (len < 1)
yading@11 111 return AVERROR_INVALIDDATA;
yading@11 112 pictureid_present = buf[0] & 0x80;
yading@11 113 tl0picidx_present = buf[0] & 0x40;
yading@11 114 tid_present = buf[0] & 0x20;
yading@11 115 keyidx_present = buf[0] & 0x10;
yading@11 116 buf++;
yading@11 117 len--;
yading@11 118 }
yading@11 119 if (pictureid_present) {
yading@11 120 if (len < 1)
yading@11 121 return AVERROR_INVALIDDATA;
yading@11 122 if (buf[0] & 0x80) {
yading@11 123 if (len < 2)
yading@11 124 return AVERROR_INVALIDDATA;
yading@11 125 pictureid = AV_RB16(buf) & 0x7fff;
yading@11 126 pictureid_mask = 0x7fff;
yading@11 127 buf += 2;
yading@11 128 len -= 2;
yading@11 129 } else {
yading@11 130 pictureid = buf[0] & 0x7f;
yading@11 131 pictureid_mask = 0x7f;
yading@11 132 buf++;
yading@11 133 len--;
yading@11 134 }
yading@11 135 }
yading@11 136 if (tl0picidx_present) {
yading@11 137 // Ignoring temporal level zero index
yading@11 138 buf++;
yading@11 139 len--;
yading@11 140 }
yading@11 141 if (tid_present || keyidx_present) {
yading@11 142 // Ignoring temporal layer index, layer sync bit and keyframe index
yading@11 143 buf++;
yading@11 144 len--;
yading@11 145 }
yading@11 146 if (len < 1)
yading@11 147 return AVERROR_INVALIDDATA;
yading@11 148
yading@11 149 if (start_partition && part_id == 0 && len >= 3) {
yading@11 150 int res;
yading@11 151 int non_key = buf[0] & 0x01;
yading@11 152 if (!non_key) {
yading@11 153 vp8_free_buffer(vp8);
yading@11 154 // Keyframe, decoding ok again
yading@11 155 vp8->sequence_ok = 1;
yading@11 156 vp8->sequence_dirty = 0;
yading@11 157 vp8->got_keyframe = 1;
yading@11 158 } else {
yading@11 159 int can_continue = vp8->data && !vp8->is_keyframe &&
yading@11 160 avio_tell(vp8->data) >= vp8->first_part_size;
yading@11 161 if (!vp8->sequence_ok)
yading@11 162 return AVERROR(EAGAIN);
yading@11 163 if (!vp8->got_keyframe)
yading@11 164 return vp8_broken_sequence(ctx, vp8, "Keyframe missing\n");
yading@11 165 if (pictureid >= 0) {
yading@11 166 if (pictureid != ((vp8->prev_pictureid + 1) & pictureid_mask)) {
yading@11 167 return vp8_broken_sequence(ctx, vp8,
yading@11 168 "Missed a picture, sequence broken\n");
yading@11 169 } else {
yading@11 170 if (vp8->data && !can_continue)
yading@11 171 return vp8_broken_sequence(ctx, vp8,
yading@11 172 "Missed a picture, sequence broken\n");
yading@11 173 }
yading@11 174 } else {
yading@11 175 uint16_t expected_seq = vp8->prev_seq + 1;
yading@11 176 int16_t diff = seq - expected_seq;
yading@11 177 if (vp8->data) {
yading@11 178 // No picture id, so we can't know if missed packets
yading@11 179 // contained any new frames. If diff == 0, we did get
yading@11 180 // later packets from the same frame (matching timestamp),
yading@11 181 // so we know we didn't miss any frame. If diff == 1 and
yading@11 182 // we still have data (not flushed by the end of frame
yading@11 183 // marker), the single missed packet must have been part
yading@11 184 // of the same frame.
yading@11 185 if ((diff == 0 || diff == 1) && can_continue) {
yading@11 186 // Proceed with what we have
yading@11 187 } else {
yading@11 188 return vp8_broken_sequence(ctx, vp8,
yading@11 189 "Missed too much, sequence broken\n");
yading@11 190 }
yading@11 191 } else {
yading@11 192 if (diff != 0)
yading@11 193 return vp8_broken_sequence(ctx, vp8,
yading@11 194 "Missed unknown data, sequence broken\n");
yading@11 195 }
yading@11 196 }
yading@11 197 if (vp8->data) {
yading@11 198 vp8->sequence_dirty = 1;
yading@11 199 if (avio_tell(vp8->data) >= vp8->first_part_size) {
yading@11 200 int ret = ff_rtp_finalize_packet(pkt, &vp8->data, st->index);
yading@11 201 if (ret < 0)
yading@11 202 return ret;
yading@11 203 pkt->flags |= AV_PKT_FLAG_CORRUPT;
yading@11 204 returned_old_frame = 1;
yading@11 205 old_timestamp = vp8->timestamp;
yading@11 206 } else {
yading@11 207 // Shouldn't happen
yading@11 208 vp8_free_buffer(vp8);
yading@11 209 }
yading@11 210 }
yading@11 211 }
yading@11 212 vp8->first_part_size = (AV_RL16(&buf[1]) << 3 | buf[0] >> 5) + 3;
yading@11 213 if ((res = avio_open_dyn_buf(&vp8->data)) < 0)
yading@11 214 return res;
yading@11 215 vp8->timestamp = *timestamp;
yading@11 216 vp8->broken_frame = 0;
yading@11 217 vp8->prev_pictureid = pictureid;
yading@11 218 vp8->is_keyframe = !non_key;
yading@11 219 } else {
yading@11 220 uint16_t expected_seq = vp8->prev_seq + 1;
yading@11 221
yading@11 222 if (!vp8->sequence_ok)
yading@11 223 return AVERROR(EAGAIN);
yading@11 224
yading@11 225 if (vp8->timestamp != *timestamp) {
yading@11 226 // Missed the start of the new frame, sequence broken
yading@11 227 return vp8_broken_sequence(ctx, vp8,
yading@11 228 "Received no start marker; dropping frame\n");
yading@11 229 }
yading@11 230
yading@11 231 if (seq != expected_seq) {
yading@11 232 if (vp8->is_keyframe) {
yading@11 233 return vp8_broken_sequence(ctx, vp8,
yading@11 234 "Missed part of a keyframe, sequence broken\n");
yading@11 235 } else if (vp8->data && avio_tell(vp8->data) >= vp8->first_part_size) {
yading@11 236 vp8->broken_frame = 1;
yading@11 237 vp8->sequence_dirty = 1;
yading@11 238 } else {
yading@11 239 return vp8_broken_sequence(ctx, vp8,
yading@11 240 "Missed part of the first partition, sequence broken\n");
yading@11 241 }
yading@11 242 }
yading@11 243 }
yading@11 244
yading@11 245 if (!vp8->data)
yading@11 246 return vp8_broken_sequence(ctx, vp8, "Received no start marker\n");
yading@11 247
yading@11 248 vp8->prev_seq = seq;
yading@11 249 if (!vp8->broken_frame)
yading@11 250 avio_write(vp8->data, buf, len);
yading@11 251
yading@11 252 if (returned_old_frame) {
yading@11 253 *timestamp = old_timestamp;
yading@11 254 return end_packet ? 1 : 0;
yading@11 255 }
yading@11 256
yading@11 257 if (end_packet) {
yading@11 258 int ret;
yading@11 259 ret = ff_rtp_finalize_packet(pkt, &vp8->data, st->index);
yading@11 260 if (ret < 0)
yading@11 261 return ret;
yading@11 262 if (vp8->sequence_dirty)
yading@11 263 pkt->flags |= AV_PKT_FLAG_CORRUPT;
yading@11 264 return 0;
yading@11 265 }
yading@11 266
yading@11 267 return AVERROR(EAGAIN);
yading@11 268 }
yading@11 269
yading@11 270 static PayloadContext *vp8_new_context(void)
yading@11 271 {
yading@11 272 PayloadContext *vp8 = av_mallocz(sizeof(PayloadContext));
yading@11 273 if (!vp8)
yading@11 274 return NULL;
yading@11 275 vp8->sequence_ok = 1;
yading@11 276 return vp8;
yading@11 277 }
yading@11 278
yading@11 279 static void vp8_free_context(PayloadContext *vp8)
yading@11 280 {
yading@11 281 vp8_free_buffer(vp8);
yading@11 282 av_free(vp8);
yading@11 283 }
yading@11 284
yading@11 285 static int vp8_need_keyframe(PayloadContext *vp8)
yading@11 286 {
yading@11 287 return vp8->sequence_dirty || !vp8->sequence_ok;
yading@11 288 }
yading@11 289
yading@11 290 RTPDynamicProtocolHandler ff_vp8_dynamic_handler = {
yading@11 291 .enc_name = "VP8",
yading@11 292 .codec_type = AVMEDIA_TYPE_VIDEO,
yading@11 293 .codec_id = AV_CODEC_ID_VP8,
yading@11 294 .alloc = vp8_new_context,
yading@11 295 .free = vp8_free_context,
yading@11 296 .parse_packet = vp8_handle_packet,
yading@11 297 .need_keyframe = vp8_need_keyframe,
yading@11 298 };