rtp_aac.c

Go to the documentation of this file.
00001 /* *
00002  * This file is part of libnemesi
00003  *
00004  * Copyright (C) 2007 by LScube team <team@streaming.polito.it>
00005  * See AUTHORS for more details
00006  *
00007  * libnemesi 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  * libnemesi 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 libnemesi; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  *
00021  * */
00022 
00023 #include "rtpparser.h"
00024 #include "rtp_utils.h"
00025 #include <math.h>
00026 
00035 typedef struct aac_elem_s {
00036     uint8_t *data;
00037     long len;
00038     struct aac_elem_s *next;
00039 } aac_elem;
00040 
00045 typedef struct {
00046     uint8_t *data;  
00047     long len;       
00048     long data_size; 
00049     unsigned long timestamp; 
00050     uint8_t *conf;  
00051     long conf_len;  
00052     int size_len;   
00053     int index_len;  
00054     int delta_len;  
00055     aac_elem *head; 
00056 } rtp_aac;
00057 
00058 
00059 
00060 static const rtpparser_info aac_served = {
00061     -1,
00062     {"MPEG4-GENERIC", NULL}
00063 };
00064 
00065 static int aac_init_parser(rtp_session * rtp_sess, unsigned pt)
00066 {
00067     rtp_aac *priv = calloc(1, sizeof(rtp_aac));
00068     rtp_pt_attrs *attrs = &rtp_sess->ptdefs[pt]->attrs;
00069     char value[1024];
00070     uint8_t buffer[1024];
00071     int i, v_len, len, err = RTP_ERRALLOC;
00072 
00073     if (!priv)
00074         return RTP_ERRALLOC;
00075 
00076     for (i=0; i < attrs->size; i++){
00077         if ((v_len = nms_get_attr_value(attrs->data[i], "config", value,
00078                 sizeof(value)))) {
00079             if (!(v_len % 2) && v_len > 0) {
00080                 if ((len = nms_hex_decode(buffer, value, sizeof(buffer))) < 0)
00081                     goto err_alloc;
00082                 if (!(priv->conf = realloc(priv->conf, priv->conf_len + len)))
00083                     goto err_alloc;
00084                 memcpy(priv->conf + priv->conf_len, buffer, len);
00085                 priv->conf_len += len;
00086             }
00087         }
00088         if ((v_len = nms_get_attr_value(attrs->data[i], "mode", value,
00089                 sizeof(value)))) {
00090             if (strcmp(value,"AAC-hbr")) {
00091                 nms_printf(NMSML_ERR, "Mode %s not supported\n",
00092                            value);
00093                 err = RTP_PARSE_ERROR;
00094                 goto err_alloc;
00095             }
00096         }
00097         if ((v_len = nms_get_attr_value(attrs->data[i], "sizeLength",
00098                 value, sizeof(value)))) {
00099             if ((priv->size_len = strtol(value, NULL, 0)) != 13) {
00100                 nms_printf(NMSML_ERR, "Size Length %d not supported\n",
00101                            priv->size_len);
00102                 err = RTP_PARSE_ERROR;
00103                 goto err_alloc;
00104             }
00105         }
00106         if ((v_len = nms_get_attr_value(attrs->data[i], "indexLength",
00107                 value, sizeof(value)))) {
00108             if ((priv->index_len = strtol(value, NULL, 0)) != 3) {
00109                 nms_printf(NMSML_ERR, "Index Length %d not supported\n",
00110                            priv->index_len);
00111                 err = RTP_PARSE_ERROR;
00112                 goto err_alloc;
00113             }
00114         }
00115         if ((v_len = nms_get_attr_value(attrs->data[i], "indexDeltaLength",
00116                 value, sizeof(value)))) {
00117             if ((priv->delta_len = strtol(value, NULL, 0)) != 3) {
00118                 nms_printf(NMSML_ERR, "Index Delta Length %d not supported\n",
00119                            priv->index_len);
00120                 err = RTP_PARSE_ERROR;
00121                 goto err_alloc;
00122             }
00123         }
00124     }
00125 
00126     rtp_sess->ptdefs[pt]->priv = priv;
00127 
00128     return 0;
00129 
00130     err_alloc:
00131     if (priv->data)
00132         free(priv->data);
00133     free(priv);
00134     return err;
00135 }
00136 
00137 static int aac_uninit_parser(rtp_ssrc * ssrc, unsigned pt)
00138 {
00139     aac_elem *tmp;
00140     rtp_aac *priv = ssrc->rtp_sess->ptdefs[pt]->priv;
00141 
00142     if (priv) {
00143         if (priv->data)
00144             free(priv->data);
00145         if (priv->conf)
00146             free(priv->conf);
00147         while (priv->head) {
00148             tmp = priv->head;
00149             priv->head = priv->head->next;
00150             if (tmp->data)
00151                 free(tmp->data);
00152             free(tmp);
00153         }
00154         free(priv);
00155     }
00156 
00157     ssrc->rtp_sess->ptdefs[pt]->priv = NULL;
00158 
00159     return 0;
00160 }
00161 
00167 static int aac_parse(rtp_ssrc * ssrc, rtp_frame * fr, rtp_buff * config)
00168 {
00169     rtp_pkt *pkt;
00170     uint8_t *buf, *payload;
00171     aac_elem *cur = NULL;
00172     rtp_aac *priv = ssrc->rtp_sess->ptdefs[fr->pt]->priv;
00173     size_t len;
00174     int i, buf_index;
00175     int header_len, header_len_bytes, headers_num, frame_len, frame_index;
00176 
00177     int err = RTP_FILL_OK;
00178 
00179     if (!(pkt = rtp_get_pkt(ssrc, &len)))
00180         return RTP_BUFF_EMPTY;
00181 
00182     payload = buf = RTP_PKT_DATA(pkt);
00183     len = RTP_PAYLOAD_SIZE(pkt, len);
00184 
00185     if (priv->len && (RTP_PKT_TS(pkt) != priv->timestamp)) {
00186         //incomplete packet without final fragment -> flush
00187         fr->data = priv->data;
00188         fr->len  = priv->len;
00189         priv->len = 0;
00190         return RTP_FILL_OK;
00191     }
00192 
00193     if (!priv->head) {
00194         header_len = (buf[0] << 8) | buf[1]; // the value in bits
00195         header_len_bytes = (header_len + 7) / 8;
00196         headers_num = header_len / 16; //ripped from gstreamer
00197 
00198         payload += 2;
00199         buf_index = 2 + header_len_bytes;
00200 
00201         for (i = 0; i < headers_num; i++) {
00202             frame_len = ((payload[0] << 8) | payload[1]) >> 3;
00203             frame_index = payload[1] & 0x7;
00204             payload += 2;
00205 
00206             if (!cur) {
00207                 cur = priv->head = calloc(1, sizeof(aac_elem));
00208             } else {
00209                 cur->next = calloc(1, sizeof(aac_elem));
00210                 cur = cur->next;
00211             }
00212 
00213             if (!cur)
00214                 return RTP_ERRALLOC;
00215 
00216             cur->data = malloc(frame_len);
00217 
00218             if (!cur->data)
00219                 return RTP_ERRALLOC;
00220 
00221             memcpy(cur->data, buf + buf_index, frame_len);
00222 
00223             cur->len = frame_len;
00224             buf_index += frame_len;
00225         }
00226     }
00227 
00228     if (priv->data_size < priv->len + priv->head->len) {
00229         if (!(priv->data = realloc(priv->data, len + priv->len))) {
00230             return RTP_ERRALLOC;
00231         }
00232         priv->data_size = priv->len + priv->head->len;
00233     }
00234 
00235     if (priv->head) {
00236         memcpy(priv->data + priv->len, priv->head->data, priv->head->len);
00237         priv->len += priv->head->len;
00238         cur = priv->head;
00239         priv->head = priv->head->next;
00240         if (cur->data)
00241             free(cur->data);
00242         free(cur);
00243     }
00244 
00245     if (!RTP_PKT_MARK(pkt)) {
00246         priv->timestamp = RTP_PKT_TS(pkt);
00247         err = EAGAIN;
00248     } else {
00249         fr->data = priv->data;
00250         fr->len  = priv->len;
00251         priv->len = 0;
00252     }
00253 
00254     if (priv->conf_len) {
00255         config->data = priv->conf;
00256         config->len = priv->conf_len;
00257     }
00258 
00259     if (!priv->head) {
00260         rtp_rm_pkt(ssrc);
00261     }
00262 
00263     return err;
00264 }
00265 
00266 RTP_PARSER_FULL(aac);

Generated on Tue Feb 3 03:10:02 2009 for libnemesi by  doxygen 1.5.4