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