Libav 0.7.1
|
00001 /* 00002 * Sorenson-3 (SVQ3/SV3V) payload for RTP 00003 * Copyright (c) 2010 Ronald S. Bultje 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00029 #include <string.h> 00030 #include "libavutil/intreadwrite.h" 00031 #include "rtp.h" 00032 #include "rtpdec.h" 00033 #include "rtpdec_formats.h" 00034 00035 struct PayloadContext { 00036 AVIOContext *pktbuf; 00037 int64_t timestamp; 00038 }; 00039 00041 static int svq3_parse_packet (AVFormatContext *s, PayloadContext *sv, 00042 AVStream *st, AVPacket *pkt, 00043 uint32_t *timestamp, 00044 const uint8_t *buf, int len, int flags) 00045 { 00046 int config_packet, start_packet, end_packet; 00047 00048 if (len < 2) 00049 return AVERROR_INVALIDDATA; 00050 00051 config_packet = buf[0] & 0x40; 00052 start_packet = buf[0] & 0x20; 00053 end_packet = buf[0] & 0x10; 00054 buf += 2; // ignore buf[1] 00055 len -= 2; 00056 00057 if (config_packet) { 00058 00059 av_freep(&st->codec->extradata); 00060 st->codec->extradata_size = 0; 00061 00062 if (len < 2 || !(st->codec->extradata = 00063 av_malloc(len + 8 + FF_INPUT_BUFFER_PADDING_SIZE))) 00064 return AVERROR_INVALIDDATA; 00065 00066 st->codec->extradata_size = len + 8; 00067 memcpy(st->codec->extradata, "SEQH", 4); 00068 AV_WB32(st->codec->extradata + 4, len); 00069 memcpy(st->codec->extradata + 8, buf, len); 00070 00071 /* We set codec_id to CODEC_ID_NONE initially to 00072 * delay decoder initialization since extradata is 00073 * carried within the RTP stream, not SDP. Here, 00074 * by setting codec_id to CODEC_ID_SVQ3, we are signalling 00075 * to the decoder that it is OK to initialize. */ 00076 st->codec->codec_id = CODEC_ID_SVQ3; 00077 00078 return AVERROR(EAGAIN); 00079 } 00080 00081 if (start_packet) { 00082 int res; 00083 00084 if (sv->pktbuf) { 00085 uint8_t *tmp; 00086 avio_close_dyn_buf(sv->pktbuf, &tmp); 00087 av_free(tmp); 00088 } 00089 if ((res = avio_open_dyn_buf(&sv->pktbuf)) < 0) 00090 return res; 00091 sv->timestamp = *timestamp; 00092 } 00093 00094 if (!sv->pktbuf) 00095 return AVERROR_INVALIDDATA; 00096 00097 avio_write(sv->pktbuf, buf, len); 00098 00099 if (end_packet) { 00100 av_init_packet(pkt); 00101 pkt->stream_index = st->index; 00102 *timestamp = sv->timestamp; 00103 pkt->size = avio_close_dyn_buf(sv->pktbuf, &pkt->data); 00104 pkt->destruct = av_destruct_packet; 00105 sv->pktbuf = NULL; 00106 return 0; 00107 } 00108 00109 return AVERROR(EAGAIN); 00110 } 00111 00112 static PayloadContext *svq3_extradata_new(void) 00113 { 00114 return av_mallocz(sizeof(PayloadContext)); 00115 } 00116 00117 static void svq3_extradata_free(PayloadContext *sv) 00118 { 00119 if (sv->pktbuf) { 00120 uint8_t *buf; 00121 avio_close_dyn_buf(sv->pktbuf, &buf); 00122 av_free(buf); 00123 } 00124 av_free(sv); 00125 } 00126 00127 RTPDynamicProtocolHandler ff_svq3_dynamic_handler = { 00128 .enc_name = "X-SV3V-ES", 00129 .codec_type = AVMEDIA_TYPE_VIDEO, 00130 .codec_id = CODEC_ID_NONE, // see if (config_packet) above 00131 .alloc = svq3_extradata_new, 00132 .free = svq3_extradata_free, 00133 .parse_packet = svq3_parse_packet, 00134 };