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