annotate ffmpeg/libavformat/rtpdec_h264.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /*
yading@11 2 * RTP H264 Protocol (RFC3984)
yading@11 3 * Copyright (c) 2006 Ryan Martell
yading@11 4 *
yading@11 5 * This file is part of FFmpeg.
yading@11 6 *
yading@11 7 * FFmpeg is free software; you can redistribute it and/or
yading@11 8 * modify it under the terms of the GNU Lesser General Public
yading@11 9 * License as published by the Free Software Foundation; either
yading@11 10 * version 2.1 of the License, or (at your option) any later version.
yading@11 11 *
yading@11 12 * FFmpeg is distributed in the hope that it will be useful,
yading@11 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 15 * Lesser General Public License for more details.
yading@11 16 *
yading@11 17 * You should have received a copy of the GNU Lesser General Public
yading@11 18 * License along with FFmpeg; if not, write to the Free Software
yading@11 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 20 */
yading@11 21
yading@11 22 /**
yading@11 23 * @file
yading@11 24 * @brief H.264 / RTP Code (RFC3984)
yading@11 25 * @author Ryan Martell <rdm4@martellventures.com>
yading@11 26 *
yading@11 27 * @note Notes:
yading@11 28 * Notes:
yading@11 29 * This currently supports packetization mode:
yading@11 30 * Single Nal Unit Mode (0), or
yading@11 31 * Non-Interleaved Mode (1). It currently does not support
yading@11 32 * Interleaved Mode (2). (This requires implementing STAP-B, MTAP16, MTAP24,
yading@11 33 * FU-B packet types)
yading@11 34 */
yading@11 35
yading@11 36 #include "libavutil/base64.h"
yading@11 37 #include "libavutil/avstring.h"
yading@11 38 #include "libavcodec/get_bits.h"
yading@11 39 #include "avformat.h"
yading@11 40
yading@11 41 #include "network.h"
yading@11 42 #include <assert.h>
yading@11 43
yading@11 44 #include "rtpdec.h"
yading@11 45 #include "rtpdec_formats.h"
yading@11 46
yading@11 47 struct PayloadContext {
yading@11 48 // sdp setup parameters
yading@11 49 uint8_t profile_idc;
yading@11 50 uint8_t profile_iop;
yading@11 51 uint8_t level_idc;
yading@11 52 int packetization_mode;
yading@11 53 #ifdef DEBUG
yading@11 54 int packet_types_received[32];
yading@11 55 #endif
yading@11 56 };
yading@11 57
yading@11 58 #ifdef DEBUG
yading@11 59 #define COUNT_NAL_TYPE(data, nal) data->packet_types_received[(nal) & 0x1f]++
yading@11 60 #else
yading@11 61 #define COUNT_NAL_TYPE(data, nal) do { } while (0)
yading@11 62 #endif
yading@11 63
yading@11 64 static const uint8_t start_sequence[] = { 0, 0, 0, 1 };
yading@11 65
yading@11 66 static int sdp_parse_fmtp_config_h264(AVStream *stream,
yading@11 67 PayloadContext *h264_data,
yading@11 68 char *attr, char *value)
yading@11 69 {
yading@11 70 AVCodecContext *codec = stream->codec;
yading@11 71 assert(codec->codec_id == AV_CODEC_ID_H264);
yading@11 72 assert(h264_data != NULL);
yading@11 73
yading@11 74 if (!strcmp(attr, "packetization-mode")) {
yading@11 75 av_log(codec, AV_LOG_DEBUG, "RTP Packetization Mode: %d\n", atoi(value));
yading@11 76 h264_data->packetization_mode = atoi(value);
yading@11 77 /*
yading@11 78 * Packetization Mode:
yading@11 79 * 0 or not present: Single NAL mode (Only nals from 1-23 are allowed)
yading@11 80 * 1: Non-interleaved Mode: 1-23, 24 (STAP-A), 28 (FU-A) are allowed.
yading@11 81 * 2: Interleaved Mode: 25 (STAP-B), 26 (MTAP16), 27 (MTAP24), 28 (FU-A),
yading@11 82 * and 29 (FU-B) are allowed.
yading@11 83 */
yading@11 84 if (h264_data->packetization_mode > 1)
yading@11 85 av_log(codec, AV_LOG_ERROR,
yading@11 86 "Interleaved RTP mode is not supported yet.\n");
yading@11 87 } else if (!strcmp(attr, "profile-level-id")) {
yading@11 88 if (strlen(value) == 6) {
yading@11 89 char buffer[3];
yading@11 90 // 6 characters=3 bytes, in hex.
yading@11 91 uint8_t profile_idc;
yading@11 92 uint8_t profile_iop;
yading@11 93 uint8_t level_idc;
yading@11 94
yading@11 95 buffer[0] = value[0];
yading@11 96 buffer[1] = value[1];
yading@11 97 buffer[2] = '\0';
yading@11 98 profile_idc = strtol(buffer, NULL, 16);
yading@11 99 buffer[0] = value[2];
yading@11 100 buffer[1] = value[3];
yading@11 101 profile_iop = strtol(buffer, NULL, 16);
yading@11 102 buffer[0] = value[4];
yading@11 103 buffer[1] = value[5];
yading@11 104 level_idc = strtol(buffer, NULL, 16);
yading@11 105
yading@11 106 av_log(codec, AV_LOG_DEBUG,
yading@11 107 "RTP Profile IDC: %x Profile IOP: %x Level: %x\n",
yading@11 108 profile_idc, profile_iop, level_idc);
yading@11 109 h264_data->profile_idc = profile_idc;
yading@11 110 h264_data->profile_iop = profile_iop;
yading@11 111 h264_data->level_idc = level_idc;
yading@11 112 }
yading@11 113 } else if (!strcmp(attr, "sprop-parameter-sets")) {
yading@11 114 codec->extradata_size = 0;
yading@11 115 av_freep(&codec->extradata);
yading@11 116
yading@11 117 while (*value) {
yading@11 118 char base64packet[1024];
yading@11 119 uint8_t decoded_packet[1024];
yading@11 120 int packet_size;
yading@11 121 char *dst = base64packet;
yading@11 122
yading@11 123 while (*value && *value != ','
yading@11 124 && (dst - base64packet) < sizeof(base64packet) - 1) {
yading@11 125 *dst++ = *value++;
yading@11 126 }
yading@11 127 *dst++ = '\0';
yading@11 128
yading@11 129 if (*value == ',')
yading@11 130 value++;
yading@11 131
yading@11 132 packet_size = av_base64_decode(decoded_packet, base64packet,
yading@11 133 sizeof(decoded_packet));
yading@11 134 if (packet_size > 0) {
yading@11 135 uint8_t *dest = av_malloc(packet_size + sizeof(start_sequence) +
yading@11 136 codec->extradata_size +
yading@11 137 FF_INPUT_BUFFER_PADDING_SIZE);
yading@11 138 if (!dest) {
yading@11 139 av_log(codec, AV_LOG_ERROR,
yading@11 140 "Unable to allocate memory for extradata!\n");
yading@11 141 return AVERROR(ENOMEM);
yading@11 142 }
yading@11 143 if (codec->extradata_size) {
yading@11 144 memcpy(dest, codec->extradata, codec->extradata_size);
yading@11 145 av_free(codec->extradata);
yading@11 146 }
yading@11 147
yading@11 148 memcpy(dest + codec->extradata_size, start_sequence,
yading@11 149 sizeof(start_sequence));
yading@11 150 memcpy(dest + codec->extradata_size + sizeof(start_sequence),
yading@11 151 decoded_packet, packet_size);
yading@11 152 memset(dest + codec->extradata_size + sizeof(start_sequence) +
yading@11 153 packet_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
yading@11 154
yading@11 155 codec->extradata = dest;
yading@11 156 codec->extradata_size += sizeof(start_sequence) + packet_size;
yading@11 157 }
yading@11 158 }
yading@11 159 av_log(codec, AV_LOG_DEBUG, "Extradata set to %p (size: %d)!\n",
yading@11 160 codec->extradata, codec->extradata_size);
yading@11 161 }
yading@11 162 return 0;
yading@11 163 }
yading@11 164
yading@11 165 // return 0 on packet, no more left, 1 on packet, 1 on partial packet
yading@11 166 static int h264_handle_packet(AVFormatContext *ctx, PayloadContext *data,
yading@11 167 AVStream *st, AVPacket *pkt, uint32_t *timestamp,
yading@11 168 const uint8_t *buf, int len, uint16_t seq,
yading@11 169 int flags)
yading@11 170 {
yading@11 171 uint8_t nal;
yading@11 172 uint8_t type;
yading@11 173 int result = 0;
yading@11 174
yading@11 175 if (!len) {
yading@11 176 av_log(ctx, AV_LOG_ERROR, "Empty H264 RTP packet\n");
yading@11 177 return AVERROR_INVALIDDATA;
yading@11 178 }
yading@11 179 nal = buf[0];
yading@11 180 type = nal & 0x1f;
yading@11 181
yading@11 182 assert(data);
yading@11 183 assert(buf);
yading@11 184
yading@11 185 /* Simplify the case (these are all the nal types used internally by
yading@11 186 * the h264 codec). */
yading@11 187 if (type >= 1 && type <= 23)
yading@11 188 type = 1;
yading@11 189 switch (type) {
yading@11 190 case 0: // undefined, but pass them through
yading@11 191 case 1:
yading@11 192 av_new_packet(pkt, len + sizeof(start_sequence));
yading@11 193 memcpy(pkt->data, start_sequence, sizeof(start_sequence));
yading@11 194 memcpy(pkt->data + sizeof(start_sequence), buf, len);
yading@11 195 COUNT_NAL_TYPE(data, nal);
yading@11 196 break;
yading@11 197
yading@11 198 case 24: // STAP-A (one packet, multiple nals)
yading@11 199 // consume the STAP-A NAL
yading@11 200 buf++;
yading@11 201 len--;
yading@11 202 // first we are going to figure out the total size
yading@11 203 {
yading@11 204 int pass = 0;
yading@11 205 int total_length = 0;
yading@11 206 uint8_t *dst = NULL;
yading@11 207
yading@11 208 for (pass = 0; pass < 2; pass++) {
yading@11 209 const uint8_t *src = buf;
yading@11 210 int src_len = len;
yading@11 211
yading@11 212 while (src_len > 2) {
yading@11 213 uint16_t nal_size = AV_RB16(src);
yading@11 214
yading@11 215 // consume the length of the aggregate
yading@11 216 src += 2;
yading@11 217 src_len -= 2;
yading@11 218
yading@11 219 if (nal_size <= src_len) {
yading@11 220 if (pass == 0) {
yading@11 221 // counting
yading@11 222 total_length += sizeof(start_sequence) + nal_size;
yading@11 223 } else {
yading@11 224 // copying
yading@11 225 assert(dst);
yading@11 226 memcpy(dst, start_sequence, sizeof(start_sequence));
yading@11 227 dst += sizeof(start_sequence);
yading@11 228 memcpy(dst, src, nal_size);
yading@11 229 COUNT_NAL_TYPE(data, *src);
yading@11 230 dst += nal_size;
yading@11 231 }
yading@11 232 } else {
yading@11 233 av_log(ctx, AV_LOG_ERROR,
yading@11 234 "nal size exceeds length: %d %d\n", nal_size, src_len);
yading@11 235 }
yading@11 236
yading@11 237 // eat what we handled
yading@11 238 src += nal_size;
yading@11 239 src_len -= nal_size;
yading@11 240
yading@11 241 if (src_len < 0)
yading@11 242 av_log(ctx, AV_LOG_ERROR,
yading@11 243 "Consumed more bytes than we got! (%d)\n", src_len);
yading@11 244 }
yading@11 245
yading@11 246 if (pass == 0) {
yading@11 247 /* now we know the total size of the packet (with the
yading@11 248 * start sequences added) */
yading@11 249 av_new_packet(pkt, total_length);
yading@11 250 dst = pkt->data;
yading@11 251 } else {
yading@11 252 assert(dst - pkt->data == total_length);
yading@11 253 }
yading@11 254 }
yading@11 255 }
yading@11 256 break;
yading@11 257
yading@11 258 case 25: // STAP-B
yading@11 259 case 26: // MTAP-16
yading@11 260 case 27: // MTAP-24
yading@11 261 case 29: // FU-B
yading@11 262 av_log(ctx, AV_LOG_ERROR,
yading@11 263 "Unhandled type (%d) (See RFC for implementation details\n",
yading@11 264 type);
yading@11 265 result = AVERROR(ENOSYS);
yading@11 266 break;
yading@11 267
yading@11 268 case 28: // FU-A (fragmented nal)
yading@11 269 buf++;
yading@11 270 len--; // skip the fu_indicator
yading@11 271 if (len > 1) {
yading@11 272 // these are the same as above, we just redo them here for clarity
yading@11 273 uint8_t fu_indicator = nal;
yading@11 274 uint8_t fu_header = *buf;
yading@11 275 uint8_t start_bit = fu_header >> 7;
yading@11 276 uint8_t av_unused end_bit = (fu_header & 0x40) >> 6;
yading@11 277 uint8_t nal_type = fu_header & 0x1f;
yading@11 278 uint8_t reconstructed_nal;
yading@11 279
yading@11 280 // Reconstruct this packet's true nal; only the data follows.
yading@11 281 /* The original nal forbidden bit and NRI are stored in this
yading@11 282 * packet's nal. */
yading@11 283 reconstructed_nal = fu_indicator & 0xe0;
yading@11 284 reconstructed_nal |= nal_type;
yading@11 285
yading@11 286 // skip the fu_header
yading@11 287 buf++;
yading@11 288 len--;
yading@11 289
yading@11 290 if (start_bit)
yading@11 291 COUNT_NAL_TYPE(data, nal_type);
yading@11 292 if (start_bit) {
yading@11 293 /* copy in the start sequence, and the reconstructed nal */
yading@11 294 av_new_packet(pkt, sizeof(start_sequence) + sizeof(nal) + len);
yading@11 295 memcpy(pkt->data, start_sequence, sizeof(start_sequence));
yading@11 296 pkt->data[sizeof(start_sequence)] = reconstructed_nal;
yading@11 297 memcpy(pkt->data + sizeof(start_sequence) + sizeof(nal), buf, len);
yading@11 298 } else {
yading@11 299 av_new_packet(pkt, len);
yading@11 300 memcpy(pkt->data, buf, len);
yading@11 301 }
yading@11 302 } else {
yading@11 303 av_log(ctx, AV_LOG_ERROR, "Too short data for FU-A H264 RTP packet\n");
yading@11 304 result = AVERROR_INVALIDDATA;
yading@11 305 }
yading@11 306 break;
yading@11 307
yading@11 308 case 30: // undefined
yading@11 309 case 31: // undefined
yading@11 310 default:
yading@11 311 av_log(ctx, AV_LOG_ERROR, "Undefined type (%d)\n", type);
yading@11 312 result = AVERROR_INVALIDDATA;
yading@11 313 break;
yading@11 314 }
yading@11 315
yading@11 316 pkt->stream_index = st->index;
yading@11 317
yading@11 318 return result;
yading@11 319 }
yading@11 320
yading@11 321 static PayloadContext *h264_new_context(void)
yading@11 322 {
yading@11 323 return av_mallocz(sizeof(PayloadContext) + FF_INPUT_BUFFER_PADDING_SIZE);
yading@11 324 }
yading@11 325
yading@11 326 static void h264_free_context(PayloadContext *data)
yading@11 327 {
yading@11 328 #ifdef DEBUG
yading@11 329 int ii;
yading@11 330
yading@11 331 for (ii = 0; ii < 32; ii++) {
yading@11 332 if (data->packet_types_received[ii])
yading@11 333 av_log(NULL, AV_LOG_DEBUG, "Received %d packets of type %d\n",
yading@11 334 data->packet_types_received[ii], ii);
yading@11 335 }
yading@11 336 #endif
yading@11 337
yading@11 338 av_free(data);
yading@11 339 }
yading@11 340
yading@11 341 static int h264_init(AVFormatContext *s, int st_index, PayloadContext *data)
yading@11 342 {
yading@11 343 if (st_index < 0)
yading@11 344 return 0;
yading@11 345 s->streams[st_index]->need_parsing = AVSTREAM_PARSE_FULL;
yading@11 346 return 0;
yading@11 347 }
yading@11 348
yading@11 349 static int parse_h264_sdp_line(AVFormatContext *s, int st_index,
yading@11 350 PayloadContext *h264_data, const char *line)
yading@11 351 {
yading@11 352 AVStream *stream;
yading@11 353 AVCodecContext *codec;
yading@11 354 const char *p = line;
yading@11 355
yading@11 356 if (st_index < 0)
yading@11 357 return 0;
yading@11 358
yading@11 359 stream = s->streams[st_index];
yading@11 360 codec = stream->codec;
yading@11 361
yading@11 362 if (av_strstart(p, "framesize:", &p)) {
yading@11 363 char buf1[50];
yading@11 364 char *dst = buf1;
yading@11 365
yading@11 366 // remove the protocol identifier
yading@11 367 while (*p && *p == ' ')
yading@11 368 p++; // strip spaces.
yading@11 369 while (*p && *p != ' ')
yading@11 370 p++; // eat protocol identifier
yading@11 371 while (*p && *p == ' ')
yading@11 372 p++; // strip trailing spaces.
yading@11 373 while (*p && *p != '-' && (dst - buf1) < sizeof(buf1) - 1)
yading@11 374 *dst++ = *p++;
yading@11 375 *dst = '\0';
yading@11 376
yading@11 377 // a='framesize:96 320-240'
yading@11 378 // set our parameters
yading@11 379 codec->width = atoi(buf1);
yading@11 380 codec->height = atoi(p + 1); // skip the -
yading@11 381 } else if (av_strstart(p, "fmtp:", &p)) {
yading@11 382 return ff_parse_fmtp(stream, h264_data, p, sdp_parse_fmtp_config_h264);
yading@11 383 } else if (av_strstart(p, "cliprect:", &p)) {
yading@11 384 // could use this if we wanted.
yading@11 385 }
yading@11 386
yading@11 387 return 0;
yading@11 388 }
yading@11 389
yading@11 390 RTPDynamicProtocolHandler ff_h264_dynamic_handler = {
yading@11 391 .enc_name = "H264",
yading@11 392 .codec_type = AVMEDIA_TYPE_VIDEO,
yading@11 393 .codec_id = AV_CODEC_ID_H264,
yading@11 394 .init = h264_init,
yading@11 395 .parse_sdp_a_line = parse_h264_sdp_line,
yading@11 396 .alloc = h264_new_context,
yading@11 397 .free = h264_free_context,
yading@11 398 .parse_packet = h264_handle_packet
yading@11 399 };