00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00039 #include "avformat.h"
00040 #include "mpegts.h"
00041 #include "bitstream.h"
00042
00043 #include <unistd.h>
00044 #include "network.h"
00045 #include <assert.h>
00046
00047 #include "rtp_internal.h"
00048 #include "rtp_h264.h"
00049 #include "base64.h"
00050 #include "avstring.h"
00051
00055 typedef struct h264_rtp_extra_data {
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 } h264_rtp_extra_data;
00067
00068 #define MAGIC_COOKIE (0xdeadbeef)
00069 #define DEAD_COOKIE (0xdeaddead)
00070
00071
00072 static void sdp_parse_fmtp_config_h264(AVStream * stream,
00073 h264_rtp_extra_data * 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(NULL, AV_LOG_DEBUG, "H.264/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(stream, AV_LOG_ERROR,
00091 "H.264/RTP 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(NULL, AV_LOG_DEBUG,
00109 "H.264/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 uint32_t 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) {
00137 uint8_t *dest= av_malloc(packet_size+sizeof(start_sequence)+codec->extradata_size);
00138 if(dest)
00139 {
00140 if(codec->extradata_size)
00141 {
00142
00143 memcpy(dest, codec->extradata, codec->extradata_size);
00144 av_free(codec->extradata);
00145 }
00146
00147 memcpy(dest+codec->extradata_size, start_sequence, sizeof(start_sequence));
00148 memcpy(dest+codec->extradata_size+sizeof(start_sequence), decoded_packet, packet_size);
00149
00150 codec->extradata= dest;
00151 codec->extradata_size+= sizeof(start_sequence)+packet_size;
00152 } else {
00153 av_log(NULL, AV_LOG_ERROR, "H.264/RTP Unable to allocate memory for extradata!");
00154 }
00155 }
00156 }
00157 av_log(NULL, AV_LOG_DEBUG, "H.264/RTP Extradata set to %p (size: %d)!", codec->extradata, codec->extradata_size);
00158 }
00159 }
00160
00161
00162 static int h264_handle_packet(RTPDemuxContext * s,
00163 AVPacket * pkt,
00164 uint32_t * timestamp,
00165 const uint8_t * buf,
00166 int len, int flags)
00167 {
00168 #ifdef DEBUG
00169 h264_rtp_extra_data *data = s->dynamic_protocol_context;
00170 #endif
00171 uint8_t nal = buf[0];
00172 uint8_t type = (nal & 0x1f);
00173 int result= 0;
00174 uint8_t start_sequence[]= {0, 0, 1};
00175
00176 assert(data);
00177 assert(data->cookie == MAGIC_COOKIE);
00178 assert(buf);
00179
00180 if (type >= 1 && type <= 23)
00181 type = 1;
00182 switch (type) {
00183 case 0:
00184 result= -1;
00185 break;
00186
00187 case 1:
00188 av_new_packet(pkt, len+sizeof(start_sequence));
00189 memcpy(pkt->data, start_sequence, sizeof(start_sequence));
00190 memcpy(pkt->data+sizeof(start_sequence), buf, len);
00191 #ifdef DEBUG
00192 data->packet_types_received[nal & 0x1f]++;
00193 #endif
00194 break;
00195
00196 case 24:
00197
00198 buf++;
00199 len--;
00200
00201 {
00202 int pass= 0;
00203 int total_length= 0;
00204 uint8_t *dst= NULL;
00205
00206 for(pass= 0; pass<2; pass++) {
00207 const uint8_t *src= buf;
00208 int src_len= len;
00209
00210 do {
00211 uint16_t nal_size = AV_RB16(src);
00212
00213
00214 src += 2;
00215 src_len -= 2;
00216
00217 if (nal_size <= src_len) {
00218 if(pass==0) {
00219
00220 total_length+= sizeof(start_sequence)+nal_size;
00221 } else {
00222
00223 assert(dst);
00224 memcpy(dst, start_sequence, sizeof(start_sequence));
00225 dst+= sizeof(start_sequence);
00226 memcpy(dst, src, nal_size);
00227 #ifdef DEBUG
00228 data->packet_types_received[*src & 0x1f]++;
00229 #endif
00230 dst+= nal_size;
00231 }
00232 } else {
00233 av_log(NULL, AV_LOG_ERROR,
00234 "nal size exceeds length: %d %d\n", nal_size, src_len);
00235 }
00236
00237
00238 src += nal_size;
00239 src_len -= nal_size;
00240
00241 if (src_len < 0)
00242 av_log(NULL, AV_LOG_ERROR,
00243 "Consumed more bytes than we got! (%d)\n", src_len);
00244 } while (src_len > 2);
00245
00246 if(pass==0) {
00247
00248 av_new_packet(pkt, total_length);
00249 dst= pkt->data;
00250 } else {
00251 assert(dst-pkt->data==total_length);
00252 }
00253 }
00254 }
00255 break;
00256
00257 case 25:
00258 case 26:
00259 case 27:
00260 case 29:
00261 av_log(NULL, AV_LOG_ERROR,
00262 "Unhandled type (%d) (See RFC for implementation details\n",
00263 type);
00264 result= -1;
00265 break;
00266
00267 case 28:
00268 buf++;
00269 len--;
00270 {
00271
00272 uint8_t fu_indicator = nal;
00273 uint8_t fu_header = *buf;
00274 uint8_t start_bit = fu_header >> 7;
00275
00276 uint8_t nal_type = (fu_header & 0x1f);
00277 uint8_t reconstructed_nal;
00278
00279
00280 reconstructed_nal = fu_indicator & (0xe0);
00281 reconstructed_nal |= nal_type;
00282
00283
00284 buf++;
00285 len--;
00286
00287 #ifdef DEBUG
00288 if (start_bit)
00289 data->packet_types_received[nal_type]++;
00290 #endif
00291 if(start_bit) {
00292
00293 av_new_packet(pkt, sizeof(start_sequence)+sizeof(nal)+len);
00294 memcpy(pkt->data, start_sequence, sizeof(start_sequence));
00295 pkt->data[sizeof(start_sequence)]= reconstructed_nal;
00296 memcpy(pkt->data+sizeof(start_sequence)+sizeof(nal), buf, len);
00297 } else {
00298 av_new_packet(pkt, len);
00299 memcpy(pkt->data, buf, len);
00300 }
00301 }
00302 break;
00303
00304 case 30:
00305 case 31:
00306 default:
00307 av_log(NULL, AV_LOG_ERROR, "Undefined type (%d)", type);
00308 result= -1;
00309 break;
00310 }
00311
00312 return result;
00313 }
00314
00315
00316 static void *h264_new_extradata(void)
00317 {
00318 h264_rtp_extra_data *data =
00319 av_mallocz(sizeof(h264_rtp_extra_data) +
00320 FF_INPUT_BUFFER_PADDING_SIZE);
00321
00322 if (data) {
00323 data->cookie = MAGIC_COOKIE;
00324 }
00325
00326 return data;
00327 }
00328
00329 static void h264_free_extradata(void *d)
00330 {
00331 h264_rtp_extra_data *data = (h264_rtp_extra_data *) d;
00332 #ifdef DEBUG
00333 int ii;
00334
00335 for (ii = 0; ii < 32; ii++) {
00336 if (data->packet_types_received[ii])
00337 av_log(NULL, AV_LOG_DEBUG, "Received %d packets of type %d\n",
00338 data->packet_types_received[ii], ii);
00339 }
00340 #endif
00341
00342 assert(data);
00343 assert(data->cookie == MAGIC_COOKIE);
00344
00345
00346 data->cookie = DEAD_COOKIE;
00347
00348
00349 av_free(data);
00350 }
00351
00352 static int parse_h264_sdp_line(AVStream * stream, void *data,
00353 const char *line)
00354 {
00355 AVCodecContext *codec = stream->codec;
00356 h264_rtp_extra_data *h264_data = (h264_rtp_extra_data *) data;
00357 const char *p = line;
00358
00359 assert(h264_data->cookie == MAGIC_COOKIE);
00360
00361 if (av_strstart(p, "framesize:", &p)) {
00362 char buf1[50];
00363 char *dst = buf1;
00364
00365
00366 while (*p && *p == ' ') p++;
00367 while (*p && *p != ' ') p++;
00368 while (*p && *p == ' ') p++;
00369 while (*p && *p != '-' && (buf1 - dst) < sizeof(buf1) - 1) {
00370 *dst++ = *p++;
00371 }
00372 *dst = '\0';
00373
00374
00375
00376 codec->width = atoi(buf1);
00377 codec->height = atoi(p + 1);
00378 codec->pix_fmt = PIX_FMT_YUV420P;
00379 } else if (av_strstart(p, "fmtp:", &p)) {
00380 char attr[256];
00381 char value[4096];
00382
00383
00384 while (*p && *p == ' ') p++;
00385 while (*p && *p != ' ') p++;
00386 while (*p && *p == ' ') p++;
00387
00388
00389 while (rtsp_next_attr_and_value
00390 (&p, attr, sizeof(attr), value, sizeof(value))) {
00391
00392 sdp_parse_fmtp_config_h264(stream, h264_data, attr, value);
00393 }
00394 } else if (av_strstart(p, "cliprect:", &p)) {
00395
00396 }
00397
00398 av_set_pts_info(stream, 33, 1, 90000);
00399
00400 return 0;
00401 }
00402
00406 RTPDynamicProtocolHandler ff_h264_dynamic_handler = {
00407 "H264",
00408 CODEC_TYPE_VIDEO,
00409 CODEC_ID_H264,
00410 parse_h264_sdp_line,
00411 h264_new_extradata,
00412 h264_free_extradata,
00413 h264_handle_packet
00414 };