Libav 0.7.1
|
00001 /* 00002 * RTP packetization for Xiph audio and video 00003 * Copyright (c) 2010 Josh Allmann 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 00022 #include "avformat.h" 00023 #include "rtpenc.h" 00024 00030 void ff_rtp_send_xiph(AVFormatContext *s1, const uint8_t *buff, int size) 00031 { 00032 RTPMuxContext *s = s1->priv_data; 00033 int max_pkt_size, xdt, frag; 00034 uint8_t *q; 00035 00036 max_pkt_size = s->max_payload_size; 00037 00038 // set xiph data type 00039 switch (*buff) { 00040 case 0x01: // vorbis id 00041 case 0x05: // vorbis setup 00042 case 0x80: // theora header 00043 case 0x82: // theora tables 00044 xdt = 1; // packed config payload 00045 break; 00046 case 0x03: // vorbis comments 00047 case 0x81: // theora comments 00048 xdt = 2; // comment payload 00049 break; 00050 default: 00051 xdt = 0; // raw data payload 00052 break; 00053 } 00054 00055 // Set ident. 00056 // Probably need a non-fixed way of generating 00057 // this, but it has to be done in SDP and passed in from there. 00058 q = s->buf; 00059 *q++ = (RTP_XIPH_IDENT >> 16) & 0xff; 00060 *q++ = (RTP_XIPH_IDENT >> 8) & 0xff; 00061 *q++ = (RTP_XIPH_IDENT ) & 0xff; 00062 00063 // set fragment 00064 // 0 - whole frame (possibly multiple frames) 00065 // 1 - first fragment 00066 // 2 - fragment continuation 00067 // 3 - last fragmement 00068 frag = size <= max_pkt_size ? 0 : 1; 00069 00070 if (!frag && !xdt) { // do we have a whole frame of raw data? 00071 uint8_t *end_ptr = s->buf + 6 + max_pkt_size; // what we're allowed to write 00072 uint8_t *ptr = s->buf_ptr + 2 + size; // what we're going to write 00073 int remaining = end_ptr - ptr; 00074 00075 assert(s->num_frames <= s->max_frames_per_packet); 00076 if ((s->num_frames > 0 && remaining < 0) || 00077 s->num_frames == s->max_frames_per_packet) { 00078 // send previous packets now; no room for new data 00079 ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 0); 00080 s->num_frames = 0; 00081 } 00082 00083 // buffer current frame to send later 00084 if (0 == s->num_frames) s->timestamp = s->cur_timestamp; 00085 s->num_frames++; 00086 00087 // Set packet header. Normally, this is OR'd with frag and xdt, 00088 // but those are zero, so omitted here 00089 *q++ = s->num_frames; 00090 00091 if (s->num_frames > 1) q = s->buf_ptr; // jump ahead if needed 00092 *q++ = (size >> 8) & 0xff; 00093 *q++ = size & 0xff; 00094 memcpy(q, buff, size); 00095 q += size; 00096 s->buf_ptr = q; 00097 00098 return; 00099 } else if (s->num_frames) { 00100 // immediately send buffered frames if buffer is not raw data, 00101 // or if current frame is fragmented. 00102 ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 0); 00103 } 00104 00105 s->timestamp = s->cur_timestamp; 00106 s->num_frames = 0; 00107 s->buf_ptr = q; 00108 while (size > 0) { 00109 int len = (!frag || frag == 3) ? size : max_pkt_size; 00110 q = s->buf_ptr; 00111 00112 // set packet headers 00113 *q++ = (frag << 6) | (xdt << 4); // num_frames = 0 00114 *q++ = (len >> 8) & 0xff; 00115 *q++ = len & 0xff; 00116 // set packet body 00117 memcpy(q, buff, len); 00118 q += len; 00119 buff += len; 00120 size -= len; 00121 00122 ff_rtp_send_data(s1, s->buf, q - s->buf, 0); 00123 00124 frag = size <= max_pkt_size ? 3 : 2; 00125 } 00126 }