00001
00030 #include "rtpdec_formats.h"
00031 #include "internal.h"
00032 #include "libavutil/avstring.h"
00033 #include "libavcodec/get_bits.h"
00034 #include <strings.h>
00035
00037 struct PayloadContext
00038 {
00039 int sizelength;
00040 int indexlength;
00041 int indexdeltalength;
00042 int profile_level_id;
00043 int streamtype;
00044 int objecttype;
00045 char *mode;
00046
00048 struct AUHeaders {
00049 int size;
00050 int index;
00051 int cts_flag;
00052 int cts;
00053 int dts_flag;
00054 int dts;
00055 int rap_flag;
00056 int streamstate;
00057 } *au_headers;
00058 int au_headers_allocated;
00059 int nb_au_headers;
00060 int au_headers_length_bytes;
00061 int cur_au_index;
00062 };
00063
00064 typedef struct {
00065 const char *str;
00066 uint16_t type;
00067 uint32_t offset;
00068 } AttrNameMap;
00069
00070
00071 #define ATTR_NAME_TYPE_INT 0
00072 #define ATTR_NAME_TYPE_STR 1
00073 static const AttrNameMap attr_names[]=
00074 {
00075 { "SizeLength", ATTR_NAME_TYPE_INT,
00076 offsetof(PayloadContext, sizelength) },
00077 { "IndexLength", ATTR_NAME_TYPE_INT,
00078 offsetof(PayloadContext, indexlength) },
00079 { "IndexDeltaLength", ATTR_NAME_TYPE_INT,
00080 offsetof(PayloadContext, indexdeltalength) },
00081 { "profile-level-id", ATTR_NAME_TYPE_INT,
00082 offsetof(PayloadContext, profile_level_id) },
00083 { "StreamType", ATTR_NAME_TYPE_INT,
00084 offsetof(PayloadContext, streamtype) },
00085 { "mode", ATTR_NAME_TYPE_STR,
00086 offsetof(PayloadContext, mode) },
00087 { NULL, -1, -1 },
00088 };
00089
00090 static PayloadContext *new_context(void)
00091 {
00092 return av_mallocz(sizeof(PayloadContext));
00093 }
00094
00095 static void free_context(PayloadContext * data)
00096 {
00097 int i;
00098 for (i = 0; i < data->nb_au_headers; i++) {
00099
00100
00101
00102
00103
00104 av_free(&data->au_headers[i]);
00105 }
00106 av_free(data->mode);
00107 av_free(data);
00108 }
00109
00110 static int parse_fmtp_config(AVCodecContext * codec, char *value)
00111 {
00112
00113 int len = ff_hex_to_data(NULL, value);
00114 if (codec->extradata)
00115 av_free(codec->extradata);
00116 codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
00117 if (!codec->extradata)
00118 return AVERROR(ENOMEM);
00119 codec->extradata_size = len;
00120 ff_hex_to_data(codec->extradata, value);
00121 return 0;
00122 }
00123
00124 static int rtp_parse_mp4_au(PayloadContext *data, const uint8_t *buf)
00125 {
00126 int au_headers_length, au_header_size, i;
00127 GetBitContext getbitcontext;
00128
00129
00130
00131 au_headers_length = AV_RB16(buf);
00132
00133 if (au_headers_length > RTP_MAX_PACKET_LENGTH)
00134 return -1;
00135
00136 data->au_headers_length_bytes = (au_headers_length + 7) / 8;
00137
00138
00139 buf += 2;
00140
00141 init_get_bits(&getbitcontext, buf, data->au_headers_length_bytes * 8);
00142
00143
00144 au_header_size = data->sizelength + data->indexlength;
00145 if (au_header_size <= 0 || (au_headers_length % au_header_size != 0))
00146 return -1;
00147
00148 data->nb_au_headers = au_headers_length / au_header_size;
00149 if (!data->au_headers || data->au_headers_allocated < data->nb_au_headers) {
00150 av_free(data->au_headers);
00151 data->au_headers = av_malloc(sizeof(struct AUHeaders) * data->nb_au_headers);
00152 data->au_headers_allocated = data->nb_au_headers;
00153 }
00154
00155
00156
00157
00158 data->au_headers[0].size = 0;
00159 data->au_headers[0].index = 0;
00160 for (i = 0; i < data->nb_au_headers; ++i) {
00161 data->au_headers[0].size += get_bits_long(&getbitcontext, data->sizelength);
00162 data->au_headers[0].index = get_bits_long(&getbitcontext, data->indexlength);
00163 }
00164
00165 data->nb_au_headers = 1;
00166
00167 return 0;
00168 }
00169
00170
00171
00172 static int aac_parse_packet(AVFormatContext *ctx,
00173 PayloadContext *data,
00174 AVStream *st,
00175 AVPacket *pkt,
00176 uint32_t *timestamp,
00177 const uint8_t *buf, int len, int flags)
00178 {
00179 if (rtp_parse_mp4_au(data, buf))
00180 return -1;
00181
00182 buf += data->au_headers_length_bytes + 2;
00183 len -= data->au_headers_length_bytes + 2;
00184
00185
00186
00187 av_new_packet(pkt, data->au_headers[0].size);
00188 memcpy(pkt->data, buf, data->au_headers[0].size);
00189
00190 pkt->stream_index = st->index;
00191 return 0;
00192 }
00193
00194 static int parse_fmtp(AVStream *stream, PayloadContext *data,
00195 char *attr, char *value)
00196 {
00197 AVCodecContext *codec = stream->codec;
00198 int res, i;
00199
00200 if (!strcmp(attr, "config")) {
00201 res = parse_fmtp_config(codec, value);
00202
00203 if (res < 0)
00204 return res;
00205 }
00206
00207 if (codec->codec_id == CODEC_ID_AAC) {
00208
00209 for (i = 0; attr_names[i].str; ++i) {
00210 if (!strcasecmp(attr, attr_names[i].str)) {
00211 if (attr_names[i].type == ATTR_NAME_TYPE_INT) {
00212 *(int *)((char *)data+
00213 attr_names[i].offset) = atoi(value);
00214 } else if (attr_names[i].type == ATTR_NAME_TYPE_STR)
00215 *(char **)((char *)data+
00216 attr_names[i].offset) = av_strdup(value);
00217 }
00218 }
00219 }
00220 return 0;
00221 }
00222
00223 static int parse_sdp_line(AVFormatContext *s, int st_index,
00224 PayloadContext *data, const char *line)
00225 {
00226 const char *p;
00227
00228 if (av_strstart(line, "fmtp:", &p))
00229 return ff_parse_fmtp(s->streams[st_index], data, p, parse_fmtp);
00230
00231 return 0;
00232 }
00233
00234 RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler = {
00235 .enc_name = "MP4V-ES",
00236 .codec_type = AVMEDIA_TYPE_VIDEO,
00237 .codec_id = CODEC_ID_MPEG4,
00238 .parse_sdp_a_line = parse_sdp_line,
00239 .open = NULL,
00240 .close = NULL,
00241 .parse_packet = NULL
00242 };
00243
00244 RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler = {
00245 .enc_name = "mpeg4-generic",
00246 .codec_type = AVMEDIA_TYPE_AUDIO,
00247 .codec_id = CODEC_ID_AAC,
00248 .parse_sdp_a_line = parse_sdp_line,
00249 .open = new_context,
00250 .close = free_context,
00251 .parse_packet = aac_parse_packet
00252 };