Libav 0.7.1
libavformat/rtpdec_svq3.c
Go to the documentation of this file.
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 };