Libav
|
00001 /* 00002 * RTP H264 Protocol (RFC3984) 00003 * Copyright (c) 2006 Ryan Martell 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 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 //sdp setup parameters 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) ///< Cookie for the extradata; to verify we are what we think we are, and that we haven't been freed. 00069 #define DEAD_COOKIE (0xdeaddead) ///< Cookie for the extradata; once it is freed. 00070 00071 /* ---------------- private code */ 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 Packetization Mode: 00085 0 or not present: Single NAL mode (Only nals from 1-23 are allowed) 00086 1: Non-interleaved Mode: 1-23, 24 (STAP-A), 28 (FU-A) are allowed. 00087 2: Interleaved Mode: 25 (STAP-B), 26 (MTAP16), 27 (MTAP24), 28 (FU-A), and 29 (FU-B) are allowed. 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 // 6 characters=3 bytes, in hex. 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 // set the parameters... 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 // av_realloc? 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 // return 0 on packet, no more left, 1 on packet, 1 on partial packet... 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; // simplify the case. (these are all the nal types used internally by the h264 codec) 00187 switch (type) { 00188 case 0: // undefined; 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: // STAP-A (one packet, multiple nals) 00202 // consume the STAP-A NAL 00203 buf++; 00204 len--; 00205 // first we are going to figure out the total size.... 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); // this going to be a problem if unaligned (can it be?) 00217 00218 // consume the length of the aggregate... 00219 src += 2; 00220 src_len -= 2; 00221 00222 if (nal_size <= src_len) { 00223 if(pass==0) { 00224 // counting... 00225 total_length+= sizeof(start_sequence)+nal_size; 00226 } else { 00227 // copying 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 // eat what we handled... 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); // because there could be rtp padding.. 00250 00251 if(pass==0) { 00252 // now we know the total size of the packet (with the start sequences added) 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: // STAP-B 00263 case 26: // MTAP-16 00264 case 27: // MTAP-24 00265 case 29: // FU-B 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: // FU-A (fragmented nal) 00273 buf++; 00274 len--; // skip the fu_indicator 00275 { 00276 // these are the same as above, we just redo them here for clarity... 00277 uint8_t fu_indicator = nal; 00278 uint8_t fu_header = *buf; // read the fu_header. 00279 uint8_t start_bit = fu_header >> 7; 00280 // uint8_t end_bit = (fu_header & 0x40) >> 6; 00281 uint8_t nal_type = (fu_header & 0x1f); 00282 uint8_t reconstructed_nal; 00283 00284 // reconstruct this packet's true nal; only the data follows.. 00285 reconstructed_nal = fu_indicator & (0xe0); // the original nal forbidden bit and NRI are stored in this packet's nal; 00286 reconstructed_nal |= nal_type; 00287 00288 // skip the fu_header... 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 // copy in the start sequence, and the reconstructed nal.... 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: // undefined 00310 case 31: // undefined 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 /* ---------------- public code */ 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 // avoid stale pointers (assert) 00352 data->cookie = DEAD_COOKIE; 00353 00354 // and clear out this... 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 // remove the protocol identifier.. 00372 while (*p && *p == ' ') p++; // strip spaces. 00373 while (*p && *p != ' ') p++; // eat protocol identifier 00374 while (*p && *p == ' ') p++; // strip trailing spaces. 00375 while (*p && *p != '-' && (dst - buf1) < sizeof(buf1) - 1) { 00376 *dst++ = *p++; 00377 } 00378 *dst = '\0'; 00379 00380 // a='framesize:96 320-240' 00381 // set our parameters.. 00382 codec->width = atoi(buf1); 00383 codec->height = atoi(p + 1); // skip the - 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 // remove the protocol identifier.. 00390 while (*p && *p == ' ') p++; // strip spaces. 00391 while (*p && *p != ' ') p++; // eat protocol identifier 00392 while (*p && *p == ' ') p++; // strip trailing spaces. 00393 00394 /* loop on each attribute */ 00395 while (ff_rtsp_next_attr_and_value 00396 (&p, attr, sizeof(attr), value, sizeof(value))) { 00397 /* grab the codec extra_data from the config parameter of the fmtp line */ 00398 sdp_parse_fmtp_config_h264(stream, h264_data, attr, value); 00399 } 00400 } else if (av_strstart(p, "cliprect:", &p)) { 00401 // could use this if we wanted. 00402 } 00403 00404 av_set_pts_info(stream, 33, 1, 90000); // 33 should be right, because the pts is 64 bit? (done elsewhere; this is a one time thing) 00405 00406 return 0; // keep processing it the normal way... 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 };