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