00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "rtpparser.h"
00024 #include "rtp_xiph.h"
00025 #include "rtp_utils.h"
00026 #include <math.h>
00027
00038 typedef struct {
00039 long offset;
00040 int pkts;
00041 uint8_t *buf;
00042 long len;
00043 int id;
00044 rtp_xiph_conf *conf;
00045 int conf_len;
00046 } rtp_theora;
00047
00048 static const rtpparser_info theora_served = {
00049 -1,
00050 {"theora", NULL}
00051 };
00052
00053 static int single_parse(rtp_theora * priv, rtp_pkt * pkt, rtp_frame * fr,
00054 rtp_buff * config, rtp_ssrc * ssrc)
00055 {
00056 uint8_t * this_pkt = RTP_PKT_DATA(pkt) + priv->offset;
00057 unsigned len = nms_consume_BE2(&this_pkt);
00058
00059 if (priv->id != RTP_XIPH_ID(pkt) &&
00060
00061 (RTP_XIPH_T(pkt) != 1)
00062 ) {
00063 nms_printf(NMSML_ERR, "Id %0x unknown, expected %0x\n",
00064 (unsigned)RTP_XIPH_ID(pkt), (unsigned)priv->id);
00065 return RTP_PARSE_ERROR;
00066 }
00067
00068 fr->data = priv->buf = realloc(priv->buf, len);
00069 fr->len = priv->len = len;
00070
00071 memcpy(fr->data, this_pkt, fr->len);
00072 priv->pkts--;
00073 if (priv->pkts == 0) {
00074 rtp_rm_pkt(ssrc);
00075 }
00076
00077 if (RTP_XIPH_T(pkt) == 1)
00078 return -1;
00079 else {
00080 config->data = priv->conf[0].conf;
00081 config->len = priv->conf[0].len;
00082 }
00083
00084 return 0;
00085 }
00086
00087 static int frag_parse(rtp_theora * priv, rtp_pkt * pkt, rtp_frame * fr,
00088 rtp_buff * config, rtp_ssrc * ssrc)
00089 {
00090 int len, err = EAGAIN;
00091
00092 switch (RTP_XIPH_F(pkt)) {
00093 case 1:
00094 priv->len = 0;
00095 case 2:
00096 len = RTP_XIPH_LEN(pkt, 4);
00097 priv->buf = realloc(priv->buf, priv->len + len);
00098 memcpy(priv->buf + priv->len, RTP_XIPH_DATA(pkt, 4), len);
00099 priv->len += len;
00100 break;
00101 case 3:
00102 len = RTP_XIPH_LEN(pkt, 4);
00103 priv->buf = realloc(priv->buf, priv->len + len);
00104 memcpy(priv->buf + priv->len, RTP_XIPH_DATA(pkt, 4), len);
00105 priv->len += len;
00106
00107 if (priv->len > fr->len) {
00108 fr->data = realloc(fr->data, priv->len);
00109 fr->len = priv->len;
00110 }
00111 memcpy(fr->data, priv->buf, fr->len);
00112
00113 if (RTP_XIPH_T(pkt) == 1)
00114 err = -1;
00115 else {
00116 config->data = priv->conf[0].conf;
00117 config->len = priv->conf[0].len;
00118 err = 0;
00119 }
00120 break;
00121 default:
00122 err = -1;
00123 break;
00124 }
00125
00126 rtp_rm_pkt(ssrc);
00127
00128 return err;
00129 }
00130
00131 static int pack_parse(rtp_theora * priv, rtp_pkt * pkt, rtp_frame * fr,
00132 rtp_buff * config, rtp_ssrc * ssrc)
00133 {
00134 single_parse(priv, pkt, fr, config, ssrc);
00135 priv->offset += fr->len + 2;
00136 return 0;
00137 }
00138
00139 static uint64_t get_v(uint8_t **cur, int *len)
00140 {
00141 uint64_t val = 0;
00142 uint8_t *cursor = *cur;
00143 int tmp = 128, i;
00144 for (i = 0; i<*len && tmp&128; i++)
00145 {
00146 tmp = *cursor++;
00147 val= (val<<7) + (tmp&127);
00148 }
00149 *cur = cursor;
00150 *len -= i;
00151 return val;
00152 }
00153
00154 static int xiphrtp_to_mkv(rtp_theora *priv, uint8_t **value, int *size)
00155 {
00156 uint8_t *conf;
00157 rtp_xiph_conf *tmp;
00158 int i, count, offset = 1, val;
00159 int id = nms_consume_BE3(value);
00160 int len = nms_consume_BE2(value);
00161
00162
00163
00164 if (len) {
00165
00166 count = get_v(value, size);
00167 if (count != 2) {
00168
00169 return RTP_PARSE_ERROR;
00170 }
00171 conf = malloc(len + len/255 + 64);
00172 for (i=0; i < count && size > 0 && offset < len; i++) {
00173 val = get_v(value, size);
00174 offset += nms_xiphlacing(conf + offset, val);
00175 }
00176 if (len > *size) {
00177 free(conf);
00178 return RTP_PARSE_ERROR;
00179 }
00180 conf[0] = count;
00181 memcpy(conf + offset, *value, len);
00182 *value += len;
00183
00184 priv->conf_len++;
00185 priv->conf = realloc(priv->conf,
00186 priv->conf_len*sizeof(rtp_xiph_conf));
00187 tmp = priv->conf + priv->conf_len - 1;
00188 tmp->conf = conf;
00189 tmp->len = len + offset;
00190 tmp->id = id;
00191 }
00192 return 0;
00193 }
00194
00195
00196 static int unpack_config(rtp_theora *priv, char *value, int len)
00197 {
00198 uint8_t buff[len];
00199 uint8_t *cur = buff;
00200 int size = nms_base64_decode(buff, value, len);
00201 int count, i;
00202 if (size <= 0) return 1;
00203
00204 count = nms_consume_BE4(&cur);
00205 size -= 4;
00206
00207 for (i = 0; i < count && size > 0; i++) {
00208 if (xiphrtp_to_mkv(priv, &cur, &size)) return 1;
00209 }
00210
00211 return 0;
00212 }
00213
00214 static void cleanup (rtp_theora *priv)
00215 {
00216 int i;
00217 if (priv->buf)
00218 free(priv->buf);
00219 if (priv->conf) {
00220 for (i = 0; i < priv->conf_len; i++)
00221 if (priv->conf[i].conf)
00222 free(priv->conf[i].conf);
00223 free(priv->conf);
00224 }
00225
00226 free(priv);
00227 }
00228
00229 static int theora_uninit_parser(rtp_ssrc * ssrc, unsigned pt)
00230 {
00231 rtp_theora *priv = ssrc->rtp_sess->ptdefs[pt]->priv;
00232
00233 if (!priv) return 0;
00234
00235 cleanup(priv);
00236
00237 ssrc->rtp_sess->ptdefs[pt]->priv = NULL;
00238
00239 return 0;
00240 }
00241
00242 static int theora_init_parser(rtp_session * rtp_sess, unsigned pt)
00243 {
00244 rtp_theora *priv = calloc(1, sizeof(rtp_theora));
00245 rtp_pt_attrs *attrs = &rtp_sess->ptdefs[pt]->attrs;
00246 char value[65536];
00247 int i, err = -1;
00248 int len;
00249
00250 if (!priv)
00251 return RTP_ERRALLOC;
00252
00253 memset(priv, 0, sizeof(rtp_theora));
00254
00255
00256 for (i=0; i < attrs->size; i++) {
00257 if ((len = nms_get_attr_value(attrs->data[i], "configuration",
00258 value, sizeof(value)))) {
00259 err = unpack_config(priv, value, len);
00260 }
00261
00262 if (!err) break;
00263 }
00264
00265 if (err) {
00266 cleanup(priv);
00267 return RTP_PARSE_ERROR;
00268 }
00269
00270
00271 priv->id = priv->conf[0].id;
00272
00273 rtp_sess->ptdefs[pt]->priv = priv;
00274
00275 return 0;
00276 }
00277
00283 static int theora_parse(rtp_ssrc * ssrc, rtp_frame * fr, rtp_buff * config)
00284 {
00285 rtp_pkt *pkt;
00286 size_t len;
00287
00288 rtp_theora *priv = ssrc->rtp_sess->ptdefs[fr->pt]->priv;
00289
00290 config->data = priv->conf[0].conf;
00291 config->len = priv->conf[0].len;
00292
00293
00294 if (!(pkt = rtp_get_pkt(ssrc, &len)))
00295 return RTP_BUFF_EMPTY;
00296
00297
00298 if (!priv->pkts) {
00299
00300
00301 priv->pkts = RTP_XIPH_PKTS(pkt);
00302
00303
00304 if (priv->pkts > 0 && ( (RTP_XIPH_F(pkt)) || (RTP_XIPH_T(pkt) !=0) )) {
00305
00306 return RTP_PARSE_ERROR;
00307 }
00308
00309 if (RTP_XIPH_F(pkt))
00310 return frag_parse(priv, pkt, fr, config, ssrc);
00311
00312 priv->offset = 4;
00313
00314
00315 if (priv->pkts == 1) {
00316
00317 return single_parse(priv, pkt, fr, config, ssrc);
00318 }
00319 }
00320
00321
00322 return pack_parse(priv, pkt, fr, config, ssrc);
00323 }
00324
00325 RTP_PARSER_FULL(theora);