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_h264.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 void 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 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) +
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 }
00159 }
00160 }
00161 av_log(codec, AV_LOG_DEBUG, "Extradata set to %p (size: %d)!", codec->extradata, codec->extradata_size);
00162 }
00163 }
00164
00165
00166 static int h264_handle_packet(AVFormatContext *ctx,
00167 PayloadContext *data,
00168 AVStream *st,
00169 AVPacket * pkt,
00170 uint32_t * timestamp,
00171 const uint8_t * buf,
00172 int len, int flags)
00173 {
00174 uint8_t nal = buf[0];
00175 uint8_t type = (nal & 0x1f);
00176 int result= 0;
00177 uint8_t start_sequence[]= {0, 0, 1};
00178
00179 #ifdef DEBUG
00180 assert(data);
00181 assert(data->cookie == MAGIC_COOKIE);
00182 #endif
00183 assert(buf);
00184
00185 if (type >= 1 && type <= 23)
00186 type = 1;
00187 switch (type) {
00188 case 0:
00189 result= -1;
00190 break;
00191
00192 case 1:
00193 av_new_packet(pkt, len+sizeof(start_sequence));
00194 memcpy(pkt->data, start_sequence, sizeof(start_sequence));
00195 memcpy(pkt->data+sizeof(start_sequence), buf, len);
00196 #ifdef DEBUG
00197 data->packet_types_received[nal & 0x1f]++;
00198 #endif
00199 break;
00200
00201 case 24:
00202
00203 buf++;
00204 len--;
00205
00206 {
00207 int pass= 0;
00208 int total_length= 0;
00209 uint8_t *dst= NULL;
00210
00211 for(pass= 0; pass<2; pass++) {
00212 const uint8_t *src= buf;
00213 int src_len= len;
00214
00215 do {
00216 uint16_t nal_size = AV_RB16(src);
00217
00218
00219 src += 2;
00220 src_len -= 2;
00221
00222 if (nal_size <= src_len) {
00223 if(pass==0) {
00224
00225 total_length+= sizeof(start_sequence)+nal_size;
00226 } else {
00227
00228 assert(dst);
00229 memcpy(dst, start_sequence, sizeof(start_sequence));
00230 dst+= sizeof(start_sequence);
00231 memcpy(dst, src, nal_size);
00232 #ifdef DEBUG
00233 data->packet_types_received[*src & 0x1f]++;
00234 #endif
00235 dst+= nal_size;
00236 }
00237 } else {
00238 av_log(ctx, AV_LOG_ERROR,
00239 "nal size exceeds length: %d %d\n", nal_size, src_len);
00240 }
00241
00242
00243 src += nal_size;
00244 src_len -= nal_size;
00245
00246 if (src_len < 0)
00247 av_log(ctx, AV_LOG_ERROR,
00248 "Consumed more bytes than we got! (%d)\n", src_len);
00249 } while (src_len > 2);
00250
00251 if(pass==0) {
00252
00253 av_new_packet(pkt, total_length);
00254 dst= pkt->data;
00255 } else {
00256 assert(dst-pkt->data==total_length);
00257 }
00258 }
00259 }
00260 break;
00261
00262 case 25:
00263 case 26:
00264 case 27:
00265 case 29:
00266 av_log(ctx, AV_LOG_ERROR,
00267 "Unhandled type (%d) (See RFC for implementation details\n",
00268 type);
00269 result= -1;
00270 break;
00271
00272 case 28:
00273 buf++;
00274 len--;
00275 {
00276
00277 uint8_t fu_indicator = nal;
00278 uint8_t fu_header = *buf;
00279 uint8_t start_bit = fu_header >> 7;
00280
00281 uint8_t nal_type = (fu_header & 0x1f);
00282 uint8_t reconstructed_nal;
00283
00284
00285 reconstructed_nal = fu_indicator & (0xe0);
00286 reconstructed_nal |= nal_type;
00287
00288
00289 buf++;
00290 len--;
00291
00292 #ifdef DEBUG
00293 if (start_bit)
00294 data->packet_types_received[nal_type]++;
00295 #endif
00296 if(start_bit) {
00297
00298 av_new_packet(pkt, sizeof(start_sequence)+sizeof(nal)+len);
00299 memcpy(pkt->data, start_sequence, sizeof(start_sequence));
00300 pkt->data[sizeof(start_sequence)]= reconstructed_nal;
00301 memcpy(pkt->data+sizeof(start_sequence)+sizeof(nal), buf, len);
00302 } else {
00303 av_new_packet(pkt, len);
00304 memcpy(pkt->data, buf, len);
00305 }
00306 }
00307 break;
00308
00309 case 30:
00310 case 31:
00311 default:
00312 av_log(ctx, AV_LOG_ERROR, "Undefined type (%d)", type);
00313 result= -1;
00314 break;
00315 }
00316
00317 pkt->stream_index = st->index;
00318
00319 return result;
00320 }
00321
00322
00323 static PayloadContext *h264_new_context(void)
00324 {
00325 PayloadContext *data =
00326 av_mallocz(sizeof(PayloadContext) +
00327 FF_INPUT_BUFFER_PADDING_SIZE);
00328
00329 if (data) {
00330 data->cookie = MAGIC_COOKIE;
00331 }
00332
00333 return data;
00334 }
00335
00336 static void h264_free_context(PayloadContext *data)
00337 {
00338 #ifdef DEBUG
00339 int ii;
00340
00341 for (ii = 0; ii < 32; ii++) {
00342 if (data->packet_types_received[ii])
00343 av_log(NULL, AV_LOG_DEBUG, "Received %d packets of type %d\n",
00344 data->packet_types_received[ii], ii);
00345 }
00346 #endif
00347
00348 assert(data);
00349 assert(data->cookie == MAGIC_COOKIE);
00350
00351
00352 data->cookie = DEAD_COOKIE;
00353
00354
00355 av_free(data);
00356 }
00357
00358 static int parse_h264_sdp_line(AVFormatContext *s, int st_index,
00359 PayloadContext *h264_data, const char *line)
00360 {
00361 AVStream *stream = s->streams[st_index];
00362 AVCodecContext *codec = stream->codec;
00363 const char *p = line;
00364
00365 assert(h264_data->cookie == MAGIC_COOKIE);
00366
00367 if (av_strstart(p, "framesize:", &p)) {
00368 char buf1[50];
00369 char *dst = buf1;
00370
00371
00372 while (*p && *p == ' ') p++;
00373 while (*p && *p != ' ') p++;
00374 while (*p && *p == ' ') p++;
00375 while (*p && *p != '-' && (dst - buf1) < sizeof(buf1) - 1) {
00376 *dst++ = *p++;
00377 }
00378 *dst = '\0';
00379
00380
00381
00382 codec->width = atoi(buf1);
00383 codec->height = atoi(p + 1);
00384 codec->pix_fmt = PIX_FMT_YUV420P;
00385 } else if (av_strstart(p, "fmtp:", &p)) {
00386 char attr[256];
00387 char value[4096];
00388
00389
00390 while (*p && *p == ' ') p++;
00391 while (*p && *p != ' ') p++;
00392 while (*p && *p == ' ') p++;
00393
00394
00395 while (ff_rtsp_next_attr_and_value
00396 (&p, attr, sizeof(attr), value, sizeof(value))) {
00397
00398 sdp_parse_fmtp_config_h264(stream, h264_data, attr, value);
00399 }
00400 } else if (av_strstart(p, "cliprect:", &p)) {
00401
00402 }
00403
00404 av_set_pts_info(stream, 33, 1, 90000);
00405
00406 return 0;
00407 }
00408
00412 RTPDynamicProtocolHandler ff_h264_dynamic_handler = {
00413 .enc_name = "H264",
00414 .codec_type = AVMEDIA_TYPE_VIDEO,
00415 .codec_id = CODEC_ID_H264,
00416 .parse_sdp_a_line = parse_h264_sdp_line,
00417 .open = h264_new_context,
00418 .close = h264_free_context,
00419 .parse_packet = h264_handle_packet
00420 };