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 av_free(codec->extradata);
00115 codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
00116 if (!codec->extradata)
00117 return AVERROR(ENOMEM);
00118 codec->extradata_size = len;
00119 ff_hex_to_data(codec->extradata, value);
00120 return 0;
00121 }
00122
00123 static int rtp_parse_mp4_au(PayloadContext *data, const uint8_t *buf)
00124 {
00125 int au_headers_length, au_header_size, i;
00126 GetBitContext getbitcontext;
00127
00128
00129
00130 au_headers_length = AV_RB16(buf);
00131
00132 if (au_headers_length > RTP_MAX_PACKET_LENGTH)
00133 return -1;
00134
00135 data->au_headers_length_bytes = (au_headers_length + 7) / 8;
00136
00137
00138 buf += 2;
00139
00140 init_get_bits(&getbitcontext, buf, data->au_headers_length_bytes * 8);
00141
00142
00143 au_header_size = data->sizelength + data->indexlength;
00144 if (au_header_size <= 0 || (au_headers_length % au_header_size != 0))
00145 return -1;
00146
00147 data->nb_au_headers = au_headers_length / au_header_size;
00148 if (!data->au_headers || data->au_headers_allocated < data->nb_au_headers) {
00149 av_free(data->au_headers);
00150 data->au_headers = av_malloc(sizeof(struct AUHeaders) * data->nb_au_headers);
00151 data->au_headers_allocated = data->nb_au_headers;
00152 }
00153
00154
00155
00156
00157 data->au_headers[0].size = 0;
00158 data->au_headers[0].index = 0;
00159 for (i = 0; i < data->nb_au_headers; ++i) {
00160 data->au_headers[0].size += get_bits_long(&getbitcontext, data->sizelength);
00161 data->au_headers[0].index = get_bits_long(&getbitcontext, data->indexlength);
00162 }
00163
00164 data->nb_au_headers = 1;
00165
00166 return 0;
00167 }
00168
00169
00170
00171 static int aac_parse_packet(AVFormatContext *ctx,
00172 PayloadContext *data,
00173 AVStream *st,
00174 AVPacket *pkt,
00175 uint32_t *timestamp,
00176 const uint8_t *buf, int len, int flags)
00177 {
00178 if (rtp_parse_mp4_au(data, buf))
00179 return -1;
00180
00181 buf += data->au_headers_length_bytes + 2;
00182 len -= data->au_headers_length_bytes + 2;
00183
00184
00185
00186 av_new_packet(pkt, data->au_headers[0].size);
00187 memcpy(pkt->data, buf, data->au_headers[0].size);
00188
00189 pkt->stream_index = st->index;
00190 return 0;
00191 }
00192
00193 static int parse_fmtp(AVStream *stream, PayloadContext *data,
00194 char *attr, char *value)
00195 {
00196 AVCodecContext *codec = stream->codec;
00197 int res, i;
00198
00199 if (!strcmp(attr, "config")) {
00200 res = parse_fmtp_config(codec, value);
00201
00202 if (res < 0)
00203 return res;
00204 }
00205
00206 if (codec->codec_id == CODEC_ID_AAC) {
00207
00208 for (i = 0; attr_names[i].str; ++i) {
00209 if (!strcasecmp(attr, attr_names[i].str)) {
00210 if (attr_names[i].type == ATTR_NAME_TYPE_INT) {
00211 *(int *)((char *)data+
00212 attr_names[i].offset) = atoi(value);
00213 } else if (attr_names[i].type == ATTR_NAME_TYPE_STR)
00214 *(char **)((char *)data+
00215 attr_names[i].offset) = av_strdup(value);
00216 }
00217 }
00218 }
00219 return 0;
00220 }
00221
00222 static int parse_sdp_line(AVFormatContext *s, int st_index,
00223 PayloadContext *data, const char *line)
00224 {
00225 const char *p;
00226
00227 if (av_strstart(line, "fmtp:", &p))
00228 return ff_parse_fmtp(s->streams[st_index], data, p, parse_fmtp);
00229
00230 return 0;
00231 }
00232
00233 RTPDynamicProtocolHandler ff_mp4v_es_dynamic_handler = {
00234 .enc_name = "MP4V-ES",
00235 .codec_type = AVMEDIA_TYPE_VIDEO,
00236 .codec_id = CODEC_ID_MPEG4,
00237 .parse_sdp_a_line = parse_sdp_line,
00238 .alloc = NULL,
00239 .free = NULL,
00240 .parse_packet = NULL
00241 };
00242
00243 RTPDynamicProtocolHandler ff_mpeg4_generic_dynamic_handler = {
00244 .enc_name = "mpeg4-generic",
00245 .codec_type = AVMEDIA_TYPE_AUDIO,
00246 .codec_id = CODEC_ID_AAC,
00247 .parse_sdp_a_line = parse_sdp_line,
00248 .alloc = new_context,
00249 .free = free_context,
00250 .parse_packet = aac_parse_packet
00251 };