| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * RTP H264 Protocol (RFC3984) | 
					
						
							| 
									
										
										
										
											2009-01-19 15:46:40 +00:00
										 |  |  |  * Copyright (c) 2006 Ryan Martell | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This file is part of FFmpeg. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * FFmpeg is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License as published by the Free Software Foundation; either | 
					
						
							|  |  |  |  * version 2.1 of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * FFmpeg is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |  * Lesser General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License along with FFmpeg; if not, write to the Free Software | 
					
						
							|  |  |  |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2010-04-20 14:45:34 +00:00
										 |  |  | * @file | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |  * @brief H.264 / RTP Code (RFC3984) | 
					
						
							|  |  |  |  * @author Ryan Martell <rdm4@martellventures.com> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @note Notes: | 
					
						
							|  |  |  |  * Notes: | 
					
						
							|  |  |  |  * This currently supports packetization mode: | 
					
						
							|  |  |  |  * Single Nal Unit Mode (0), or | 
					
						
							|  |  |  |  * Non-Interleaved Mode (1).  It currently does not support | 
					
						
							|  |  |  |  * Interleaved Mode (2). (This requires implementing STAP-B, MTAP16, MTAP24, FU-B packet types) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @note TODO: | 
					
						
							|  |  |  |  * 1) RTCP sender reports for udp streams are required.. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-09 11:56:36 +00:00
										 |  |  | #include "libavutil/base64.h"
 | 
					
						
							|  |  |  | #include "libavutil/avstring.h"
 | 
					
						
							| 
									
										
										
										
											2009-04-13 16:20:26 +00:00
										 |  |  | #include "libavcodec/get_bits.h"
 | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  | #include "avformat.h"
 | 
					
						
							|  |  |  | #include "mpegts.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							| 
									
										
										
										
											2007-02-04 17:05:44 +00:00
										 |  |  | #include "network.h"
 | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  | #include <assert.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-06 10:35:52 +00:00
										 |  |  | #include "rtpdec.h"
 | 
					
						
							| 
									
										
										
										
											2010-02-28 11:03:14 +00:00
										 |  |  | #include "rtpdec_h264.h"
 | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |     RTP/H264 specific private data. | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2008-10-04 04:11:12 +00:00
										 |  |  | struct PayloadContext { | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |     unsigned long cookie;       ///< sanity check, to make sure we get the pointer we're expecting.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //sdp setup parameters
 | 
					
						
							|  |  |  |     uint8_t profile_idc;        ///< from the sdp setup parameters.
 | 
					
						
							|  |  |  |     uint8_t profile_iop;        ///< from the sdp setup parameters.
 | 
					
						
							|  |  |  |     uint8_t level_idc;          ///< from the sdp setup parameters.
 | 
					
						
							|  |  |  |     int packetization_mode;     ///< from the sdp setup parameters.
 | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  |     int packet_types_received[32]; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-10-04 04:11:12 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define MAGIC_COOKIE (0xdeadbeef)       ///< Cookie for the extradata; to verify we are what we think we are, and that we haven't been freed.
 | 
					
						
							|  |  |  | #define DEAD_COOKIE (0xdeaddead)        ///< Cookie for the extradata; once it is freed.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ---------------- private code */ | 
					
						
							| 
									
										
										
										
											2010-06-28 11:25:39 +00:00
										 |  |  | static int sdp_parse_fmtp_config_h264(AVStream * stream, | 
					
						
							| 
									
										
										
										
											2010-06-28 11:26:29 +00:00
										 |  |  |                                       PayloadContext * h264_data, | 
					
						
							|  |  |  |                                       char *attr, char *value) | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     AVCodecContext *codec = stream->codec; | 
					
						
							|  |  |  |     assert(codec->codec_id == CODEC_ID_H264); | 
					
						
							|  |  |  |     assert(h264_data != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!strcmp(attr, "packetization-mode")) { | 
					
						
							| 
									
										
										
										
											2009-03-02 09:28:37 +00:00
										 |  |  |         av_log(codec, AV_LOG_DEBUG, "RTP Packetization Mode: %d\n", atoi(value)); | 
					
						
							| 
									
										
										
										
											2007-08-10 13:34:56 +00:00
										 |  |  |         h264_data->packetization_mode = atoi(value); | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |         /*
 | 
					
						
							|  |  |  |            Packetization Mode: | 
					
						
							|  |  |  |            0 or not present: Single NAL mode (Only nals from 1-23 are allowed) | 
					
						
							|  |  |  |            1: Non-interleaved Mode: 1-23, 24 (STAP-A), 28 (FU-A) are allowed. | 
					
						
							|  |  |  |            2: Interleaved Mode: 25 (STAP-B), 26 (MTAP16), 27 (MTAP24), 28 (FU-A), and 29 (FU-B) are allowed. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         if (h264_data->packetization_mode > 1) | 
					
						
							| 
									
										
										
										
											2009-03-02 09:28:37 +00:00
										 |  |  |             av_log(codec, AV_LOG_ERROR, | 
					
						
							|  |  |  |                    "Interleaved RTP mode is not supported yet."); | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |     } else if (!strcmp(attr, "profile-level-id")) { | 
					
						
							|  |  |  |         if (strlen(value) == 6) { | 
					
						
							|  |  |  |             char buffer[3]; | 
					
						
							|  |  |  |             // 6 characters=3 bytes, in hex.
 | 
					
						
							|  |  |  |             uint8_t profile_idc; | 
					
						
							|  |  |  |             uint8_t profile_iop; | 
					
						
							|  |  |  |             uint8_t level_idc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             buffer[0] = value[0]; buffer[1] = value[1]; buffer[2] = '\0'; | 
					
						
							|  |  |  |             profile_idc = strtol(buffer, NULL, 16); | 
					
						
							|  |  |  |             buffer[0] = value[2]; buffer[1] = value[3]; | 
					
						
							|  |  |  |             profile_iop = strtol(buffer, NULL, 16); | 
					
						
							|  |  |  |             buffer[0] = value[4]; buffer[1] = value[5]; | 
					
						
							|  |  |  |             level_idc = strtol(buffer, NULL, 16); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // set the parameters...
 | 
					
						
							| 
									
										
										
										
											2009-03-02 09:28:37 +00:00
										 |  |  |             av_log(codec, AV_LOG_DEBUG, | 
					
						
							|  |  |  |                    "RTP Profile IDC: %x Profile IOP: %x Level: %x\n", | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |                    profile_idc, profile_iop, level_idc); | 
					
						
							|  |  |  |             h264_data->profile_idc = profile_idc; | 
					
						
							|  |  |  |             h264_data->profile_iop = profile_iop; | 
					
						
							|  |  |  |             h264_data->level_idc = level_idc; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else  if (!strcmp(attr, "sprop-parameter-sets")) { | 
					
						
							|  |  |  |         uint8_t start_sequence[]= { 0, 0, 1 }; | 
					
						
							|  |  |  |         codec->extradata_size= 0; | 
					
						
							|  |  |  |         codec->extradata= NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         while (*value) { | 
					
						
							|  |  |  |             char base64packet[1024]; | 
					
						
							|  |  |  |             uint8_t decoded_packet[1024]; | 
					
						
							| 
									
										
										
										
											2010-07-11 11:54:48 +00:00
										 |  |  |             int packet_size; | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |             char *dst = base64packet; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             while (*value && *value != ',' | 
					
						
							|  |  |  |                    && (dst - base64packet) < sizeof(base64packet) - 1) { | 
					
						
							|  |  |  |                 *dst++ = *value++; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             *dst++ = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (*value == ',') | 
					
						
							|  |  |  |                 value++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             packet_size= av_base64_decode(decoded_packet, base64packet, sizeof(decoded_packet)); | 
					
						
							| 
									
										
										
										
											2010-07-11 11:54:48 +00:00
										 |  |  |             if (packet_size > 0) { | 
					
						
							| 
									
										
										
										
											2010-03-03 21:00:50 +00:00
										 |  |  |                 uint8_t *dest = av_malloc(packet_size + sizeof(start_sequence) + | 
					
						
							|  |  |  |                                          codec->extradata_size + | 
					
						
							|  |  |  |                                          FF_INPUT_BUFFER_PADDING_SIZE); | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |                 if(dest) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     if(codec->extradata_size) | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                         // av_realloc?
 | 
					
						
							|  |  |  |                         memcpy(dest, codec->extradata, codec->extradata_size); | 
					
						
							|  |  |  |                         av_free(codec->extradata); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     memcpy(dest+codec->extradata_size, start_sequence, sizeof(start_sequence)); | 
					
						
							|  |  |  |                     memcpy(dest+codec->extradata_size+sizeof(start_sequence), decoded_packet, packet_size); | 
					
						
							| 
									
										
										
										
											2010-03-03 21:00:50 +00:00
										 |  |  |                     memset(dest+codec->extradata_size+sizeof(start_sequence)+ | 
					
						
							|  |  |  |                            packet_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     codec->extradata= dest; | 
					
						
							|  |  |  |                     codec->extradata_size+= sizeof(start_sequence)+packet_size; | 
					
						
							|  |  |  |                 } else { | 
					
						
							| 
									
										
										
										
											2009-03-02 09:28:37 +00:00
										 |  |  |                     av_log(codec, AV_LOG_ERROR, "Unable to allocate memory for extradata!"); | 
					
						
							| 
									
										
										
										
											2010-06-28 11:25:39 +00:00
										 |  |  |                     return AVERROR(ENOMEM); | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-03-02 09:28:37 +00:00
										 |  |  |         av_log(codec, AV_LOG_DEBUG, "Extradata set to %p (size: %d)!", codec->extradata, codec->extradata_size); | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-06-28 11:25:39 +00:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // return 0 on packet, no more left, 1 on packet, 1 on partial packet...
 | 
					
						
							| 
									
										
										
										
											2009-02-06 01:37:19 +00:00
										 |  |  | static int h264_handle_packet(AVFormatContext *ctx, | 
					
						
							|  |  |  |                               PayloadContext *data, | 
					
						
							| 
									
										
										
										
											2008-10-04 04:15:06 +00:00
										 |  |  |                               AVStream *st, | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |                               AVPacket * pkt, | 
					
						
							|  |  |  |                               uint32_t * timestamp, | 
					
						
							|  |  |  |                               const uint8_t * buf, | 
					
						
							| 
									
										
										
										
											2008-01-18 20:48:32 +00:00
										 |  |  |                               int len, int flags) | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     uint8_t nal = buf[0]; | 
					
						
							|  |  |  |     uint8_t type = (nal & 0x1f); | 
					
						
							|  |  |  |     int result= 0; | 
					
						
							|  |  |  |     uint8_t start_sequence[]= {0, 0, 1}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-13 17:43:18 +00:00
										 |  |  | #ifdef DEBUG
 | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |     assert(data); | 
					
						
							|  |  |  |     assert(data->cookie == MAGIC_COOKIE); | 
					
						
							| 
									
										
										
										
											2008-05-13 17:43:18 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |     assert(buf); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (type >= 1 && type <= 23) | 
					
						
							|  |  |  |         type = 1;              // simplify the case. (these are all the nal types used internally by the h264 codec)
 | 
					
						
							|  |  |  |     switch (type) { | 
					
						
							|  |  |  |     case 0:                    // undefined;
 | 
					
						
							|  |  |  |         result= -1; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case 1: | 
					
						
							|  |  |  |         av_new_packet(pkt, len+sizeof(start_sequence)); | 
					
						
							|  |  |  |         memcpy(pkt->data, start_sequence, sizeof(start_sequence)); | 
					
						
							|  |  |  |         memcpy(pkt->data+sizeof(start_sequence), buf, len); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  |         data->packet_types_received[nal & 0x1f]++; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case 24:                   // STAP-A (one packet, multiple nals)
 | 
					
						
							|  |  |  |         // consume the STAP-A NAL
 | 
					
						
							|  |  |  |         buf++; | 
					
						
							|  |  |  |         len--; | 
					
						
							|  |  |  |         // first we are going to figure out the total size....
 | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             int pass= 0; | 
					
						
							|  |  |  |             int total_length= 0; | 
					
						
							|  |  |  |             uint8_t *dst= NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for(pass= 0; pass<2; pass++) { | 
					
						
							|  |  |  |                 const uint8_t *src= buf; | 
					
						
							|  |  |  |                 int src_len= len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 do { | 
					
						
							| 
									
										
										
										
											2007-01-19 22:12:59 +00:00
										 |  |  |                     uint16_t nal_size = AV_RB16(src); // this going to be a problem if unaligned (can it be?)
 | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     // consume the length of the aggregate...
 | 
					
						
							|  |  |  |                     src += 2; | 
					
						
							|  |  |  |                     src_len -= 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (nal_size <= src_len) { | 
					
						
							|  |  |  |                         if(pass==0) { | 
					
						
							|  |  |  |                             // counting...
 | 
					
						
							|  |  |  |                             total_length+= sizeof(start_sequence)+nal_size; | 
					
						
							|  |  |  |                         } else { | 
					
						
							|  |  |  |                             // copying
 | 
					
						
							|  |  |  |                             assert(dst); | 
					
						
							|  |  |  |                             memcpy(dst, start_sequence, sizeof(start_sequence)); | 
					
						
							|  |  |  |                             dst+= sizeof(start_sequence); | 
					
						
							|  |  |  |                             memcpy(dst, src, nal_size); | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  |                             data->packet_types_received[*src & 0x1f]++; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |                             dst+= nal_size; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } else { | 
					
						
							| 
									
										
										
										
											2009-03-02 09:28:37 +00:00
										 |  |  |                         av_log(ctx, AV_LOG_ERROR, | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |                                "nal size exceeds length: %d %d\n", nal_size, src_len); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     // eat what we handled...
 | 
					
						
							|  |  |  |                     src += nal_size; | 
					
						
							|  |  |  |                     src_len -= nal_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (src_len < 0) | 
					
						
							| 
									
										
										
										
											2009-03-02 09:28:37 +00:00
										 |  |  |                         av_log(ctx, AV_LOG_ERROR, | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |                                "Consumed more bytes than we got! (%d)\n", src_len); | 
					
						
							|  |  |  |                 } while (src_len > 2);      // because there could be rtp padding..
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if(pass==0) { | 
					
						
							|  |  |  |                     // now we know the total size of the packet (with the start sequences added)
 | 
					
						
							|  |  |  |                     av_new_packet(pkt, total_length); | 
					
						
							|  |  |  |                     dst= pkt->data; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     assert(dst-pkt->data==total_length); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case 25:                   // STAP-B
 | 
					
						
							|  |  |  |     case 26:                   // MTAP-16
 | 
					
						
							|  |  |  |     case 27:                   // MTAP-24
 | 
					
						
							|  |  |  |     case 29:                   // FU-B
 | 
					
						
							| 
									
										
										
										
											2009-03-02 09:28:37 +00:00
										 |  |  |         av_log(ctx, AV_LOG_ERROR, | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |                "Unhandled type (%d) (See RFC for implementation details\n", | 
					
						
							|  |  |  |                type); | 
					
						
							|  |  |  |         result= -1; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case 28:                   // FU-A (fragmented nal)
 | 
					
						
							|  |  |  |         buf++; | 
					
						
							|  |  |  |         len--;                  // skip the fu_indicator
 | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // these are the same as above, we just redo them here for clarity...
 | 
					
						
							|  |  |  |             uint8_t fu_indicator = nal; | 
					
						
							|  |  |  |             uint8_t fu_header = *buf;   // read the fu_header.
 | 
					
						
							| 
									
										
										
										
											2007-06-07 14:47:40 +00:00
										 |  |  |             uint8_t start_bit = fu_header >> 7; | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  | //            uint8_t end_bit = (fu_header & 0x40) >> 6;
 | 
					
						
							|  |  |  |             uint8_t nal_type = (fu_header & 0x1f); | 
					
						
							|  |  |  |             uint8_t reconstructed_nal; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // reconstruct this packet's true nal; only the data follows..
 | 
					
						
							|  |  |  |             reconstructed_nal = fu_indicator & (0xe0);  // the original nal forbidden bit and NRI are stored in this packet's nal;
 | 
					
						
							| 
									
										
										
										
											2007-06-07 14:48:29 +00:00
										 |  |  |             reconstructed_nal |= nal_type; | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // skip the fu_header...
 | 
					
						
							|  |  |  |             buf++; | 
					
						
							|  |  |  |             len--; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  |             if (start_bit) | 
					
						
							| 
									
										
										
										
											2007-06-07 14:51:26 +00:00
										 |  |  |                 data->packet_types_received[nal_type]++; | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |             if(start_bit) { | 
					
						
							|  |  |  |                 // copy in the start sequence, and the reconstructed nal....
 | 
					
						
							|  |  |  |                 av_new_packet(pkt, sizeof(start_sequence)+sizeof(nal)+len); | 
					
						
							|  |  |  |                 memcpy(pkt->data, start_sequence, sizeof(start_sequence)); | 
					
						
							|  |  |  |                 pkt->data[sizeof(start_sequence)]= reconstructed_nal; | 
					
						
							|  |  |  |                 memcpy(pkt->data+sizeof(start_sequence)+sizeof(nal), buf, len); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 av_new_packet(pkt, len); | 
					
						
							|  |  |  |                 memcpy(pkt->data, buf, len); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case 30:                   // undefined
 | 
					
						
							|  |  |  |     case 31:                   // undefined
 | 
					
						
							|  |  |  |     default: | 
					
						
							| 
									
										
										
										
											2009-03-02 09:28:37 +00:00
										 |  |  |         av_log(ctx, AV_LOG_ERROR, "Undefined type (%d)", type); | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |         result= -1; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-03 13:51:34 +00:00
										 |  |  |     pkt->stream_index = st->index; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ---------------- public code */ | 
					
						
							| 
									
										
										
										
											2009-07-27 14:29:06 +00:00
										 |  |  | static PayloadContext *h264_new_context(void) | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-10-04 04:11:12 +00:00
										 |  |  |     PayloadContext *data = | 
					
						
							|  |  |  |         av_mallocz(sizeof(PayloadContext) + | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |                    FF_INPUT_BUFFER_PADDING_SIZE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (data) { | 
					
						
							|  |  |  |         data->cookie = MAGIC_COOKIE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return data; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-27 14:29:06 +00:00
										 |  |  | static void h264_free_context(PayloadContext *data) | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  | { | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  |     int ii; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (ii = 0; ii < 32; ii++) { | 
					
						
							|  |  |  |         if (data->packet_types_received[ii]) | 
					
						
							|  |  |  |             av_log(NULL, AV_LOG_DEBUG, "Received %d packets of type %d\n", | 
					
						
							|  |  |  |                    data->packet_types_received[ii], ii); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(data); | 
					
						
							|  |  |  |     assert(data->cookie == MAGIC_COOKIE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // avoid stale pointers (assert)
 | 
					
						
							|  |  |  |     data->cookie = DEAD_COOKIE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // and clear out this...
 | 
					
						
							|  |  |  |     av_free(data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-06 18:41:17 +00:00
										 |  |  | static int parse_h264_sdp_line(AVFormatContext *s, int st_index, | 
					
						
							|  |  |  |                                PayloadContext *h264_data, const char *line) | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-06 18:41:17 +00:00
										 |  |  |     AVStream *stream = s->streams[st_index]; | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |     AVCodecContext *codec = stream->codec; | 
					
						
							|  |  |  |     const char *p = line; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(h264_data->cookie == MAGIC_COOKIE); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-06-24 11:27:12 +00:00
										 |  |  |     if (av_strstart(p, "framesize:", &p)) { | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |         char buf1[50]; | 
					
						
							|  |  |  |         char *dst = buf1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // remove the protocol identifier..
 | 
					
						
							|  |  |  |         while (*p && *p == ' ') p++; // strip spaces.
 | 
					
						
							|  |  |  |         while (*p && *p != ' ') p++; // eat protocol identifier
 | 
					
						
							|  |  |  |         while (*p && *p == ' ') p++; // strip trailing spaces.
 | 
					
						
							| 
									
										
										
										
											2009-11-05 14:25:37 +00:00
										 |  |  |         while (*p && *p != '-' && (dst - buf1) < sizeof(buf1) - 1) { | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |             *dst++ = *p++; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         *dst = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // a='framesize:96 320-240'
 | 
					
						
							|  |  |  |         // set our parameters..
 | 
					
						
							|  |  |  |         codec->width = atoi(buf1); | 
					
						
							|  |  |  |         codec->height = atoi(p + 1); // skip the -
 | 
					
						
							|  |  |  |         codec->pix_fmt = PIX_FMT_YUV420P; | 
					
						
							| 
									
										
										
										
											2007-06-24 11:27:12 +00:00
										 |  |  |     } else if (av_strstart(p, "fmtp:", &p)) { | 
					
						
							| 
									
										
										
										
											2010-06-28 11:28:02 +00:00
										 |  |  |         return ff_parse_fmtp(stream, h264_data, p, sdp_parse_fmtp_config_h264); | 
					
						
							| 
									
										
										
										
											2007-06-24 11:27:12 +00:00
										 |  |  |     } else if (av_strstart(p, "cliprect:", &p)) { | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  |         // could use this if we wanted.
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0;                   // keep processing it the normal way...
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  | This is the structure for expanding on the dynamic rtp protocols (makes everything static. yay!) | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | RTPDynamicProtocolHandler ff_h264_dynamic_handler = { | 
					
						
							| 
									
										
										
										
											2009-07-27 14:29:06 +00:00
										 |  |  |     .enc_name         = "H264", | 
					
						
							| 
									
										
										
										
											2010-03-30 23:30:55 +00:00
										 |  |  |     .codec_type       = AVMEDIA_TYPE_VIDEO, | 
					
						
							| 
									
										
										
										
											2009-07-27 14:29:06 +00:00
										 |  |  |     .codec_id         = CODEC_ID_H264, | 
					
						
							|  |  |  |     .parse_sdp_a_line = parse_h264_sdp_line, | 
					
						
							|  |  |  |     .open             = h264_new_context, | 
					
						
							|  |  |  |     .close            = h264_free_context, | 
					
						
							|  |  |  |     .parse_packet     = h264_handle_packet | 
					
						
							| 
									
										
										
										
											2006-11-07 22:10:07 +00:00
										 |  |  | }; |