yading@11: /* yading@11: * Sorenson-3 (SVQ3/SV3V) payload for RTP yading@11: * Copyright (c) 2010 Ronald S. Bultje yading@11: * yading@11: * This file is part of FFmpeg. yading@11: * yading@11: * FFmpeg is free software; you can redistribute it and/or yading@11: * modify it under the terms of the GNU Lesser General Public yading@11: * License as published by the Free Software Foundation; either yading@11: * version 2.1 of the License, or (at your option) any later version. yading@11: * yading@11: * FFmpeg is distributed in the hope that it will be useful, yading@11: * but WITHOUT ANY WARRANTY; without even the implied warranty of yading@11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU yading@11: * Lesser General Public License for more details. yading@11: * yading@11: * You should have received a copy of the GNU Lesser General Public yading@11: * License along with FFmpeg; if not, write to the Free Software yading@11: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA yading@11: */ yading@11: yading@11: /** yading@11: * @file yading@11: * @brief RTP support for the SV3V (SVQ3) payload yading@11: * @author Ronald S. Bultje yading@11: * @see http://wiki.multimedia.cx/index.php?title=Sorenson_Video_3#Packetization yading@11: */ yading@11: yading@11: #include yading@11: #include "libavutil/intreadwrite.h" yading@11: #include "rtp.h" yading@11: #include "rtpdec.h" yading@11: #include "rtpdec_formats.h" yading@11: yading@11: struct PayloadContext { yading@11: AVIOContext *pktbuf; yading@11: int64_t timestamp; yading@11: }; yading@11: yading@11: /** return 0 on packet, <0 on partial packet or error... */ yading@11: static int svq3_parse_packet (AVFormatContext *s, PayloadContext *sv, yading@11: AVStream *st, AVPacket *pkt, yading@11: uint32_t *timestamp, yading@11: const uint8_t *buf, int len, uint16_t seq, yading@11: int flags) yading@11: { yading@11: int config_packet, start_packet, end_packet; yading@11: yading@11: if (len < 2) yading@11: return AVERROR_INVALIDDATA; yading@11: yading@11: config_packet = buf[0] & 0x40; yading@11: start_packet = buf[0] & 0x20; yading@11: end_packet = buf[0] & 0x10; yading@11: buf += 2; // ignore buf[1] yading@11: len -= 2; yading@11: yading@11: if (config_packet) { yading@11: yading@11: av_freep(&st->codec->extradata); yading@11: st->codec->extradata_size = 0; yading@11: yading@11: if (len < 2 || !(st->codec->extradata = yading@11: av_malloc(len + 8 + FF_INPUT_BUFFER_PADDING_SIZE))) yading@11: return AVERROR_INVALIDDATA; yading@11: yading@11: st->codec->extradata_size = len + 8; yading@11: memcpy(st->codec->extradata, "SEQH", 4); yading@11: AV_WB32(st->codec->extradata + 4, len); yading@11: memcpy(st->codec->extradata + 8, buf, len); yading@11: yading@11: /* We set codec_id to AV_CODEC_ID_NONE initially to yading@11: * delay decoder initialization since extradata is yading@11: * carried within the RTP stream, not SDP. Here, yading@11: * by setting codec_id to AV_CODEC_ID_SVQ3, we are signalling yading@11: * to the decoder that it is OK to initialize. */ yading@11: st->codec->codec_id = AV_CODEC_ID_SVQ3; yading@11: yading@11: return AVERROR(EAGAIN); yading@11: } yading@11: yading@11: if (start_packet) { yading@11: int res; yading@11: yading@11: if (sv->pktbuf) { yading@11: uint8_t *tmp; yading@11: avio_close_dyn_buf(sv->pktbuf, &tmp); yading@11: av_free(tmp); yading@11: } yading@11: if ((res = avio_open_dyn_buf(&sv->pktbuf)) < 0) yading@11: return res; yading@11: sv->timestamp = *timestamp; yading@11: } yading@11: yading@11: if (!sv->pktbuf) yading@11: return AVERROR_INVALIDDATA; yading@11: yading@11: avio_write(sv->pktbuf, buf, len); yading@11: yading@11: if (end_packet) { yading@11: int ret = ff_rtp_finalize_packet(pkt, &sv->pktbuf, st->index); yading@11: if (ret < 0) yading@11: return ret; yading@11: yading@11: *timestamp = sv->timestamp; yading@11: return 0; yading@11: } yading@11: yading@11: return AVERROR(EAGAIN); yading@11: } yading@11: yading@11: static PayloadContext *svq3_extradata_new(void) yading@11: { yading@11: return av_mallocz(sizeof(PayloadContext)); yading@11: } yading@11: yading@11: static void svq3_extradata_free(PayloadContext *sv) yading@11: { yading@11: if (sv->pktbuf) { yading@11: uint8_t *buf; yading@11: avio_close_dyn_buf(sv->pktbuf, &buf); yading@11: av_free(buf); yading@11: } yading@11: av_free(sv); yading@11: } yading@11: yading@11: RTPDynamicProtocolHandler ff_svq3_dynamic_handler = { yading@11: .enc_name = "X-SV3V-ES", yading@11: .codec_type = AVMEDIA_TYPE_VIDEO, yading@11: .codec_id = AV_CODEC_ID_NONE, // see if (config_packet) above yading@11: .alloc = svq3_extradata_new, yading@11: .free = svq3_extradata_free, yading@11: .parse_packet = svq3_parse_packet, yading@11: };