00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00039 #include "libavutil/base64.h"
00040 #include "libavutil/avstring.h"
00041 #include "libavcodec/get_bits.h"
00042 #include "avformat.h"
00043 #include "mpegts.h"
00044
00045 #include <unistd.h>
00046 #include "network.h"
00047 #include <assert.h>
00048
00049 #include "rtpdec.h"
00050 #include "rtpdec_formats.h"
00051
00055 struct PayloadContext {
00056 unsigned long cookie;
00057
00058
00059 uint8_t profile_idc;
00060 uint8_t profile_iop;
00061 uint8_t level_idc;
00062 int packetization_mode;
00063 #ifdef DEBUG
00064 int packet_types_received[32];
00065 #endif
00066 };
00067
00068 #define MAGIC_COOKIE (0xdeadbeef)
00069 #define DEAD_COOKIE (0xdeaddead)
00070
00071
00072 static int sdp_parse_fmtp_config_h264(AVStream * stream,
00073 PayloadContext * h264_data,
00074 char *attr, char *value)
00075 {
00076 AVCodecContext *codec = stream->codec;
00077 assert(codec->codec_id == CODEC_ID_H264);
00078 assert(h264_data != NULL);
00079
00080 if (!strcmp(attr, "packetization-mode")) {
00081 av_log(codec, AV_LOG_DEBUG, "RTP Packetization Mode: %d\n", atoi(value));
00082 h264_data->packetization_mode = atoi(value);
00083
00084
00085
00086
00087
00088
00089 if (h264_data->packetization_mode > 1)
00090 av_log(codec, AV_LOG_ERROR,
00091 "Interleaved RTP mode is not supported yet.");
00092 } else if (!strcmp(attr, "profile-level-id")) {
00093 if (strlen(value) == 6) {
00094 char buffer[3];
00095
00096 uint8_t profile_idc;
00097 uint8_t profile_iop;
00098 uint8_t level_idc;
00099
00100 buffer[0] = value[0]; buffer[1] = value[1]; buffer[2] = '\0';
00101 profile_idc = strtol(buffer, NULL, 16);
00102 buffer[0] = value[2]; buffer[1] = value[3];
00103 profile_iop = strtol(buffer, NULL, 16);
00104 buffer[0] = value[4]; buffer[1] = value[5];
00105 level_idc = strtol(buffer, NULL, 16);
00106
00107
00108 av_log(codec, AV_LOG_DEBUG,
00109 "RTP Profile IDC: %x Profile IOP: %x Level: %x\n",
00110 profile_idc, profile_iop, level_idc);
00111 h264_data->profile_idc = profile_idc;
00112 h264_data->profile_iop = profile_iop;
00113 h264_data->level_idc = level_idc;
00114 }
00115 } else if (!strcmp(attr, "sprop-parameter-sets")) {
00116 uint8_t start_sequence[]= { 0, 0, 1 };
00117 codec->extradata_size= 0;
00118 codec->extradata= NULL;
00119
00120 while (*value) {
00121 char base64packet[1024];
00122 uint8_t decoded_packet[1024];
00123 int packet_size;
00124 char *dst = base64packet;
00125
00126 while (*value && *value != ','
00127 && (dst - base64packet) < sizeof(base64packet) - 1) {
00128 *dst++ = *value++;
00129 }
00130 *dst++ = '\0';
00131
00132 if (*value == ',')
00133 value++;
00134
00135 packet_size= av_base64_decode(decoded_packet, base64packet, sizeof(decoded_packet));
00136 if (packet_size > 0) {
00137 uint8_t *dest = av_malloc(packet_size + sizeof(start_sequence) +
00138 codec->extradata_size +
00139 FF_INPUT_BUFFER_PADDING_SIZE);
00140 if(dest)
00141 {
00142 if(codec->extradata_size)
00143 {
00144
00145 memcpy(dest, codec->extradata, codec->extradata_size);
00146 av_free(codec->extradata);
00147 }
00148
00149 memcpy(dest+codec->extradata_size, start_sequence, sizeof(start_sequence));
00150 memcpy(dest+codec->extradata_size+sizeof(start_sequence), decoded_packet, packet_size);
00151 memset(dest+codec->extradata_size+sizeof(start_sequence)+
00152 packet_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
00153
00154 codec->extradata= dest;
00155 codec->extradata_size+= sizeof(start_sequence)+packet_size;
00156 } else {
00157 av_log(codec, AV_LOG_ERROR, "Unable to allocate memory for extradata!");
00158 return AVERROR(ENOMEM);
00159 }
00160 }
00161 }
00162 av_log(codec, AV_LOG_DEBUG, "Extradata set to %p (size: %d)!", codec->extradata, codec->extradata_size);
00163 }
00164 return 0;
00165 }
00166
00167
00168 static int h264_handle_packet(AVFormatContext *ctx,
00169 PayloadContext *data,
00170 AVStream *st,
00171 AVPacket * pkt,
00172 uint32_t * timestamp,
00173 const uint8_t * buf,
00174 int len, int flags)
00175 {
00176 uint8_t nal = buf[0];
00177 uint8_t type = (nal & 0x1f);
00178 int result= 0;
00179 uint8_t start_sequence[]= {0, 0, 1};
00180
00181 #ifdef DEBUG
00182 assert(data);
00183 assert(data->cookie == MAGIC_COOKIE);
00184 #endif
00185 assert(buf);
00186
00187 if (type >= 1 && type <= 23)
00188 type = 1;
00189 switch (type) {
00190 case 0:
00191 case 1:
00192 av_new_packet(pkt, len+sizeof(start_sequence));
00193 memcpy(pkt->data, start_sequence, sizeof(start_sequence));
00194 memcpy(pkt->data+sizeof(start_sequence), buf, len);
00195 #ifdef DEBUG
00196 data->packet_types_received[nal & 0x1f]++;
00197 #endif
00198 break;
00199
00200 case 24:
00201
00202 buf++;
00203 len--;
00204
00205 {
00206 int pass= 0;
00207 int total_length= 0;
00208 uint8_t *dst= NULL;
00209
00210 for(pass= 0; pass<2; pass++) {
00211 const uint8_t *src= buf;
00212 int src_len= len;
00213
00214 do {
00215 uint16_t nal_size = AV_RB16(src);
00216
00217
00218 src += 2;
00219 src_len -= 2;
00220
00221 if (nal_size <= src_len) {
00222 if(pass==0) {
00223
00224 total_length+= sizeof(start_sequence)+nal_size;
00225 } else {
00226
00227 assert(dst);
00228 memcpy(dst, start_sequence, sizeof(start_sequence));
00229 dst+= sizeof(start_sequence);
00230 memcpy(dst, src, nal_size);
00231 #ifdef DEBUG
00232 data->packet_types_received[*src & 0x1f]++;
00233 #endif
00234 dst+= nal_size;
00235 }
00236 } else {
00237 av_log(ctx, AV_LOG_ERROR,
00238 "nal size exceeds length: %d %d\n", nal_size, src_len);
00239 }
00240
00241
00242 src += nal_size;
00243 src_len -= nal_size;
00244
00245 if (src_len < 0)
00246 av_log(ctx, AV_LOG_ERROR,
00247 "Consumed more bytes than we got! (%d)\n", src_len);
00248 } while (src_len > 2);
00249
00250 if(pass==0) {
00251
00252 av_new_packet(pkt, total_length);
00253 dst= pkt->data;
00254 } else {
00255 assert(dst-pkt->data==total_length);
00256 }
00257 }
00258 }
00259 break;
00260
00261 case 25:
00262 case 26:
00263 case 27:
00264 case 29:
00265 av_log(ctx, AV_LOG_ERROR,
00266 "Unhandled type (%d) (See RFC for implementation details\n",
00267 type);
00268 result= -1;
00269 break;
00270
00271 case 28:
00272 buf++;
00273 len--;
00274 {
00275
00276 uint8_t fu_indicator = nal;
00277 uint8_t fu_header = *buf;
00278 uint8_t start_bit = fu_header >> 7;
00279
00280 uint8_t nal_type = (fu_header & 0x1f);
00281 uint8_t reconstructed_nal;
00282
00283
00284 reconstructed_nal = fu_indicator & (0xe0);
00285 reconstructed_nal |= nal_type;
00286
00287
00288 buf++;
00289 len--;
00290
00291 #ifdef DEBUG
00292 if (start_bit)
00293 data->packet_types_received[nal_type]++;
00294 #endif
00295 if(start_bit) {
00296
00297 av_new_packet(pkt, sizeof(start_sequence)+sizeof(nal)+len);
00298 memcpy(pkt->data, start_sequence, sizeof(start_sequence));
00299 pkt->data[sizeof(start_sequence)]= reconstructed_nal;
00300 memcpy(pkt->data+sizeof(start_sequence)+sizeof(nal), buf, len);
00301 } else {
00302 av_new_packet(pkt, len);
00303 memcpy(pkt->data, buf, len);
00304 }
00305 }
00306 break;
00307
00308 case 30:
00309 case 31:
00310 default:
00311 av_log(ctx, AV_LOG_ERROR, "Undefined type (%d)", type);
00312 result= -1;
00313 break;
00314 }
00315
00316 pkt->stream_index = st->index;
00317
00318 return result;
00319 }
00320
00321
00322 static PayloadContext *h264_new_context(void)
00323 {
00324 PayloadContext *data =
00325 av_mallocz(sizeof(PayloadContext) +
00326 FF_INPUT_BUFFER_PADDING_SIZE);
00327
00328 if (data) {
00329 data->cookie = MAGIC_COOKIE;
00330 }
00331
00332 return data;
00333 }
00334
00335 static void h264_free_context(PayloadContext *data)
00336 {
00337 #ifdef DEBUG
00338 int ii;
00339
00340 for (ii = 0; ii < 32; ii++) {
00341 if (data->packet_types_received[ii])
00342 av_log(NULL, AV_LOG_DEBUG, "Received %d packets of type %d\n",
00343 data->packet_types_received[ii], ii);
00344 }
00345 #endif
00346
00347 assert(data);
00348 assert(data->cookie == MAGIC_COOKIE);
00349
00350
00351 data->cookie = DEAD_COOKIE;
00352
00353
00354 av_free(data);
00355 }
00356
00357 static int parse_h264_sdp_line(AVFormatContext *s, int st_index,
00358 PayloadContext *h264_data, const char *line)
00359 {
00360 AVStream *stream = s->streams[st_index];
00361 AVCodecContext *codec = stream->codec;
00362 const char *p = line;
00363
00364 assert(h264_data->cookie == MAGIC_COOKIE);
00365
00366 if (av_strstart(p, "framesize:", &p)) {
00367 char buf1[50];
00368 char *dst = buf1;
00369
00370
00371 while (*p && *p == ' ') p++;
00372 while (*p && *p != ' ') p++;
00373 while (*p && *p == ' ') p++;
00374 while (*p && *p != '-' && (dst - buf1) < sizeof(buf1) - 1) {
00375 *dst++ = *p++;
00376 }
00377 *dst = '\0';
00378
00379
00380
00381 codec->width = atoi(buf1);
00382 codec->height = atoi(p + 1);
00383 codec->pix_fmt = PIX_FMT_YUV420P;
00384 } else if (av_strstart(p, "fmtp:", &p)) {
00385 return ff_parse_fmtp(stream, h264_data, p, sdp_parse_fmtp_config_h264);
00386 } else if (av_strstart(p, "cliprect:", &p)) {
00387
00388 }
00389
00390 return 0;
00391 }
00392
00396 RTPDynamicProtocolHandler ff_h264_dynamic_handler = {
00397 .enc_name = "H264",
00398 .codec_type = AVMEDIA_TYPE_VIDEO,
00399 .codec_id = CODEC_ID_H264,
00400 .parse_sdp_a_line = parse_h264_sdp_line,
00401 .alloc = h264_new_context,
00402 .free = h264_free_context,
00403 .parse_packet = h264_handle_packet
00404 };