• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavformat/rtpdec_latm.c

Go to the documentation of this file.
00001 
00022 #include "rtpdec_formats.h"
00023 #include "internal.h"
00024 #include "libavutil/avstring.h"
00025 #include "libavcodec/get_bits.h"
00026 #include <strings.h>
00027 
00028 struct PayloadContext {
00029     AVIOContext *dyn_buf;
00030     uint8_t *buf;
00031     int pos, len;
00032     uint32_t timestamp;
00033 };
00034 
00035 static PayloadContext *latm_new_context(void)
00036 {
00037     return av_mallocz(sizeof(PayloadContext));
00038 }
00039 
00040 static void latm_free_context(PayloadContext *data)
00041 {
00042     if (!data)
00043         return;
00044     if (data->dyn_buf) {
00045         uint8_t *p;
00046         avio_close_dyn_buf(data->dyn_buf, &p);
00047         av_free(p);
00048     }
00049     av_free(data->buf);
00050     av_free(data);
00051 }
00052 
00053 static int latm_parse_packet(AVFormatContext *ctx, PayloadContext *data,
00054                              AVStream *st, AVPacket *pkt, uint32_t *timestamp,
00055                              const uint8_t *buf, int len, int flags)
00056 {
00057     int ret, cur_len;
00058 
00059     if (buf) {
00060         if (!data->dyn_buf || data->timestamp != *timestamp) {
00061             av_freep(&data->buf);
00062             if (data->dyn_buf)
00063                 avio_close_dyn_buf(data->dyn_buf, &data->buf);
00064             data->dyn_buf = NULL;
00065             av_freep(&data->buf);
00066 
00067             data->timestamp = *timestamp;
00068             if ((ret = avio_open_dyn_buf(&data->dyn_buf)) < 0)
00069                 return ret;
00070         }
00071         avio_write(data->dyn_buf, buf, len);
00072 
00073         if (!(flags & RTP_FLAG_MARKER))
00074             return AVERROR(EAGAIN);
00075         av_free(data->buf);
00076         data->len = avio_close_dyn_buf(data->dyn_buf, &data->buf);
00077         data->dyn_buf = NULL;
00078         data->pos = 0;
00079     }
00080 
00081     if (!data->buf) {
00082         av_log(ctx, AV_LOG_ERROR, "No data available yet\n");
00083         return AVERROR(EIO);
00084     }
00085 
00086     cur_len = 0;
00087     while (data->pos < data->len) {
00088         uint8_t val = data->buf[data->pos++];
00089         cur_len += val;
00090         if (val != 0xff)
00091             break;
00092     }
00093     if (data->pos + cur_len > data->len) {
00094         av_log(ctx, AV_LOG_ERROR, "Malformed LATM packet\n");
00095         return AVERROR(EIO);
00096     }
00097 
00098     if ((ret = av_new_packet(pkt, cur_len)) < 0)
00099         return ret;
00100     memcpy(pkt->data, data->buf + data->pos, cur_len);
00101     data->pos += cur_len;
00102     pkt->stream_index = st->index;
00103     return data->pos < data->len;
00104 }
00105 
00106 static int parse_fmtp_config(AVStream *st, char *value)
00107 {
00108     int len = ff_hex_to_data(NULL, value), i, ret = 0;
00109     GetBitContext gb;
00110     uint8_t *config;
00111     int audio_mux_version, same_time_framing, num_programs, num_layers;
00112 
00113     /* Pad this buffer, too, to avoid out of bounds reads with get_bits below */
00114     config = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
00115     if (!config)
00116         return AVERROR(ENOMEM);
00117     ff_hex_to_data(config, value);
00118     init_get_bits(&gb, config, len*8);
00119     audio_mux_version = get_bits(&gb, 1);
00120     same_time_framing = get_bits(&gb, 1);
00121     skip_bits(&gb, 6); /* num_sub_frames */
00122     num_programs      = get_bits(&gb, 4);
00123     num_layers        = get_bits(&gb, 3);
00124     if (audio_mux_version != 0 || same_time_framing != 1 || num_programs != 0 ||
00125         num_layers != 0) {
00126         av_log(NULL, AV_LOG_WARNING, "Unsupported LATM config (%d,%d,%d,%d)\n",
00127                                      audio_mux_version, same_time_framing,
00128                                      num_programs, num_layers);
00129         ret = AVERROR_PATCHWELCOME;
00130         goto end;
00131     }
00132     av_freep(&st->codec->extradata);
00133     st->codec->extradata_size = (get_bits_left(&gb) + 7)/8;
00134     st->codec->extradata = av_mallocz(st->codec->extradata_size +
00135                                       FF_INPUT_BUFFER_PADDING_SIZE);
00136     if (!st->codec->extradata) {
00137         ret = AVERROR(ENOMEM);
00138         goto end;
00139     }
00140     for (i = 0; i < st->codec->extradata_size; i++)
00141         st->codec->extradata[i] = get_bits(&gb, 8);
00142 
00143 end:
00144     av_free(config);
00145     return ret;
00146 }
00147 
00148 static int parse_fmtp(AVStream *stream, PayloadContext *data,
00149                       char *attr, char *value)
00150 {
00151     int res;
00152 
00153     if (!strcmp(attr, "config")) {
00154         res = parse_fmtp_config(stream, value);
00155         if (res < 0)
00156             return res;
00157     } else if (!strcmp(attr, "cpresent")) {
00158         int cpresent = atoi(value);
00159         if (cpresent != 0)
00160             av_log_missing_feature(NULL, "RTP MP4A-LATM with in-band "
00161                                          "configuration", 1);
00162     }
00163 
00164     return 0;
00165 }
00166 
00167 static int latm_parse_sdp_line(AVFormatContext *s, int st_index,
00168                                PayloadContext *data, const char *line)
00169 {
00170     const char *p;
00171 
00172     if (av_strstart(line, "fmtp:", &p))
00173         return ff_parse_fmtp(s->streams[st_index], data, p, parse_fmtp);
00174 
00175     return 0;
00176 }
00177 
00178 RTPDynamicProtocolHandler ff_mp4a_latm_dynamic_handler = {
00179     .enc_name           = "MP4A-LATM",
00180     .codec_type         = AVMEDIA_TYPE_AUDIO,
00181     .codec_id           = CODEC_ID_AAC,
00182     .parse_sdp_a_line   = latm_parse_sdp_line,
00183     .alloc              = latm_new_context,
00184     .free               = latm_free_context,
00185     .parse_packet       = latm_parse_packet
00186 };

Generated on Fri Feb 22 2013 07:24:32 for FFmpeg by  doxygen 1.7.1