FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rtpdec_h264.c
Go to the documentation of this file.
1 /*
2  * RTP H264 Protocol (RFC3984)
3  * Copyright (c) 2006 Ryan Martell
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * @brief H.264 / RTP Code (RFC3984)
25  * @author Ryan Martell <rdm4@martellventures.com>
26  *
27  * @note Notes:
28  * Notes:
29  * This currently supports packetization mode:
30  * Single Nal Unit Mode (0), or
31  * Non-Interleaved Mode (1). It currently does not support
32  * Interleaved Mode (2). (This requires implementing STAP-B, MTAP16, MTAP24,
33  * FU-B packet types)
34  */
35 
36 #include "libavutil/attributes.h"
37 #include "libavutil/base64.h"
38 #include "libavutil/intreadwrite.h"
39 #include "libavutil/avstring.h"
40 #include "avformat.h"
41 
42 #include "rtpdec.h"
43 #include "rtpdec_formats.h"
44 
45 struct PayloadContext {
46  // sdp setup parameters
51 #ifdef DEBUG
52  int packet_types_received[32];
53 #endif
54 };
55 
56 #ifdef DEBUG
57 #define COUNT_NAL_TYPE(data, nal) data->packet_types_received[(nal) & 0x1f]++
58 #define NAL_COUNTERS data->packet_types_received
59 #else
60 #define COUNT_NAL_TYPE(data, nal) do { } while (0)
61 #define NAL_COUNTERS NULL
62 #endif
63 #define NAL_MASK 0x1f
64 
65 static const uint8_t start_sequence[] = { 0, 0, 0, 1 };
66 
68  PayloadContext *h264_data,
69  const char *value)
70 {
71  char buffer[3];
72  // 6 characters=3 bytes, in hex.
73  uint8_t profile_idc;
74  uint8_t profile_iop;
75  uint8_t level_idc;
76 
77  buffer[0] = value[0];
78  buffer[1] = value[1];
79  buffer[2] = '\0';
80  profile_idc = strtol(buffer, NULL, 16);
81  buffer[0] = value[2];
82  buffer[1] = value[3];
83  profile_iop = strtol(buffer, NULL, 16);
84  buffer[0] = value[4];
85  buffer[1] = value[5];
86  level_idc = strtol(buffer, NULL, 16);
87 
89  "RTP Profile IDC: %x Profile IOP: %x Level: %x\n",
90  profile_idc, profile_iop, level_idc);
91  h264_data->profile_idc = profile_idc;
92  h264_data->profile_iop = profile_iop;
93  h264_data->level_idc = level_idc;
94 }
95 
97  uint8_t **data_ptr, int *size_ptr,
98  const char *value)
99 {
100  char base64packet[1024];
101  uint8_t decoded_packet[1024];
102  int packet_size;
103 
104  while (*value) {
105  char *dst = base64packet;
106 
107  while (*value && *value != ','
108  && (dst - base64packet) < sizeof(base64packet) - 1) {
109  *dst++ = *value++;
110  }
111  *dst++ = '\0';
112 
113  if (*value == ',')
114  value++;
115 
116  packet_size = av_base64_decode(decoded_packet, base64packet,
117  sizeof(decoded_packet));
118  if (packet_size > 0) {
119  uint8_t *dest = av_realloc(*data_ptr,
120  packet_size + sizeof(start_sequence) +
121  *size_ptr +
123  if (!dest) {
124  av_log(s, AV_LOG_ERROR,
125  "Unable to allocate memory for extradata!\n");
126  return AVERROR(ENOMEM);
127  }
128  *data_ptr = dest;
129 
130  memcpy(dest + *size_ptr, start_sequence,
131  sizeof(start_sequence));
132  memcpy(dest + *size_ptr + sizeof(start_sequence),
133  decoded_packet, packet_size);
134  memset(dest + *size_ptr + sizeof(start_sequence) +
135  packet_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
136 
137  *size_ptr += sizeof(start_sequence) + packet_size;
138  }
139  }
140 
141  return 0;
142 }
143 
145  AVStream *stream,
146  PayloadContext *h264_data,
147  const char *attr, const char *value)
148 {
149  AVCodecContext *codec = stream->codec;
150 
151  if (!strcmp(attr, "packetization-mode")) {
152  av_log(s, AV_LOG_DEBUG, "RTP Packetization Mode: %d\n", atoi(value));
153  h264_data->packetization_mode = atoi(value);
154  /*
155  * Packetization Mode:
156  * 0 or not present: Single NAL mode (Only nals from 1-23 are allowed)
157  * 1: Non-interleaved Mode: 1-23, 24 (STAP-A), 28 (FU-A) are allowed.
158  * 2: Interleaved Mode: 25 (STAP-B), 26 (MTAP16), 27 (MTAP24), 28 (FU-A),
159  * and 29 (FU-B) are allowed.
160  */
161  if (h264_data->packetization_mode > 1)
162  av_log(s, AV_LOG_ERROR,
163  "Interleaved RTP mode is not supported yet.\n");
164  } else if (!strcmp(attr, "profile-level-id")) {
165  if (strlen(value) == 6)
166  parse_profile_level_id(s, h264_data, value);
167  } else if (!strcmp(attr, "sprop-parameter-sets")) {
168  int ret;
169  codec->extradata_size = 0;
170  av_freep(&codec->extradata);
172  &codec->extradata_size, value);
173  av_log(s, AV_LOG_DEBUG, "Extradata set to %p (size: %d)\n",
174  codec->extradata, codec->extradata_size);
175  return ret;
176  }
177  return 0;
178 }
179 
180 void ff_h264_parse_framesize(AVCodecContext *codec, const char *p)
181 {
182  char buf1[50];
183  char *dst = buf1;
184 
185  // remove the protocol identifier
186  while (*p && *p == ' ')
187  p++; // strip spaces.
188  while (*p && *p != ' ')
189  p++; // eat protocol identifier
190  while (*p && *p == ' ')
191  p++; // strip trailing spaces.
192  while (*p && *p != '-' && (dst - buf1) < sizeof(buf1) - 1)
193  *dst++ = *p++;
194  *dst = '\0';
195 
196  // a='framesize:96 320-240'
197  // set our parameters
198  codec->width = atoi(buf1);
199  codec->height = atoi(p + 1); // skip the -
200 }
201 
203  const uint8_t *buf, int len,
204  int skip_between, int *nal_counters,
205  int nal_mask)
206 {
207  int pass = 0;
208  int total_length = 0;
209  uint8_t *dst = NULL;
210  int ret;
211 
212  // first we are going to figure out the total size
213  for (pass = 0; pass < 2; pass++) {
214  const uint8_t *src = buf;
215  int src_len = len;
216 
217  while (src_len > 2) {
218  uint16_t nal_size = AV_RB16(src);
219 
220  // consume the length of the aggregate
221  src += 2;
222  src_len -= 2;
223 
224  if (nal_size <= src_len) {
225  if (pass == 0) {
226  // counting
227  total_length += sizeof(start_sequence) + nal_size;
228  } else {
229  // copying
230  memcpy(dst, start_sequence, sizeof(start_sequence));
231  dst += sizeof(start_sequence);
232  memcpy(dst, src, nal_size);
233  if (nal_counters)
234  nal_counters[(*src) & nal_mask]++;
235  dst += nal_size;
236  }
237  } else {
238  av_log(ctx, AV_LOG_ERROR,
239  "nal size exceeds length: %d %d\n", nal_size, src_len);
240  return AVERROR_INVALIDDATA;
241  }
242 
243  // eat what we handled
244  src += nal_size + skip_between;
245  src_len -= nal_size + skip_between;
246  }
247 
248  if (pass == 0) {
249  /* now we know the total size of the packet (with the
250  * start sequences added) */
251  if ((ret = av_new_packet(pkt, total_length)) < 0)
252  return ret;
253  dst = pkt->data;
254  }
255  }
256 
257  return 0;
258 }
259 
261  int start_bit, const uint8_t *nal_header,
262  int nal_header_len)
263 {
264  int ret;
265  int tot_len = len;
266  int pos = 0;
267  if (start_bit)
268  tot_len += sizeof(start_sequence) + nal_header_len;
269  if ((ret = av_new_packet(pkt, tot_len)) < 0)
270  return ret;
271  if (start_bit) {
272  memcpy(pkt->data + pos, start_sequence, sizeof(start_sequence));
273  pos += sizeof(start_sequence);
274  memcpy(pkt->data + pos, nal_header, nal_header_len);
275  pos += nal_header_len;
276  }
277  memcpy(pkt->data + pos, buf, len);
278  return 0;
279 }
280 
282  const uint8_t *buf, int len,
283  int *nal_counters, int nal_mask)
284 {
285  uint8_t fu_indicator, fu_header, start_bit, nal_type, nal;
286 
287  if (len < 3) {
288  av_log(ctx, AV_LOG_ERROR, "Too short data for FU-A H264 RTP packet\n");
289  return AVERROR_INVALIDDATA;
290  }
291 
292  fu_indicator = buf[0];
293  fu_header = buf[1];
294  start_bit = fu_header >> 7;
295  nal_type = fu_header & 0x1f;
296  nal = fu_indicator & 0xe0 | nal_type;
297 
298  // skip the fu_indicator and fu_header
299  buf += 2;
300  len -= 2;
301 
302  if (start_bit && nal_counters)
303  nal_counters[nal_type & nal_mask]++;
304  return ff_h264_handle_frag_packet(pkt, buf, len, start_bit, &nal, 1);
305 }
306 
307 // return 0 on packet, no more left, 1 on packet, 1 on partial packet
309  AVStream *st, AVPacket *pkt, uint32_t *timestamp,
310  const uint8_t *buf, int len, uint16_t seq,
311  int flags)
312 {
313  uint8_t nal;
314  uint8_t type;
315  int result = 0;
316 
317  if (!len) {
318  av_log(ctx, AV_LOG_ERROR, "Empty H264 RTP packet\n");
319  return AVERROR_INVALIDDATA;
320  }
321  nal = buf[0];
322  type = nal & 0x1f;
323 
324  /* Simplify the case (these are all the nal types used internally by
325  * the h264 codec). */
326  if (type >= 1 && type <= 23)
327  type = 1;
328  switch (type) {
329  case 0: // undefined, but pass them through
330  case 1:
331  if ((result = av_new_packet(pkt, len + sizeof(start_sequence))) < 0)
332  return result;
333  memcpy(pkt->data, start_sequence, sizeof(start_sequence));
334  memcpy(pkt->data + sizeof(start_sequence), buf, len);
335  COUNT_NAL_TYPE(data, nal);
336  break;
337 
338  case 24: // STAP-A (one packet, multiple nals)
339  // consume the STAP-A NAL
340  buf++;
341  len--;
342  result = ff_h264_handle_aggregated_packet(ctx, data, pkt, buf, len, 0,
344  break;
345 
346  case 25: // STAP-B
347  case 26: // MTAP-16
348  case 27: // MTAP-24
349  case 29: // FU-B
350  av_log(ctx, AV_LOG_ERROR,
351  "Unhandled type (%d) (See RFC for implementation details)\n",
352  type);
353  result = AVERROR(ENOSYS);
354  break;
355 
356  case 28: // FU-A (fragmented nal)
357  result = h264_handle_packet_fu_a(ctx, data, pkt, buf, len,
359  break;
360 
361  case 30: // undefined
362  case 31: // undefined
363  default:
364  av_log(ctx, AV_LOG_ERROR, "Undefined type (%d)\n", type);
365  result = AVERROR_INVALIDDATA;
366  break;
367  }
368 
369  pkt->stream_index = st->index;
370 
371  return result;
372 }
373 
375 {
376 #ifdef DEBUG
377  int ii;
378 
379  for (ii = 0; ii < 32; ii++) {
380  if (data->packet_types_received[ii])
381  av_log(NULL, AV_LOG_DEBUG, "Received %d packets of type %d\n",
382  data->packet_types_received[ii], ii);
383  }
384 #endif
385 }
386 
387 static int parse_h264_sdp_line(AVFormatContext *s, int st_index,
388  PayloadContext *h264_data, const char *line)
389 {
390  AVStream *stream;
391  const char *p = line;
392 
393  if (st_index < 0)
394  return 0;
395 
396  stream = s->streams[st_index];
397 
398  if (av_strstart(p, "framesize:", &p)) {
399  ff_h264_parse_framesize(stream->codec, p);
400  } else if (av_strstart(p, "fmtp:", &p)) {
401  return ff_parse_fmtp(s, stream, h264_data, p, sdp_parse_fmtp_config_h264);
402  } else if (av_strstart(p, "cliprect:", &p)) {
403  // could use this if we wanted.
404  }
405 
406  return 0;
407 }
408 
410  .enc_name = "H264",
411  .codec_type = AVMEDIA_TYPE_VIDEO,
412  .codec_id = AV_CODEC_ID_H264,
413  .need_parsing = AVSTREAM_PARSE_FULL,
414  .priv_data_size = sizeof(PayloadContext),
415  .parse_sdp_a_line = parse_h264_sdp_line,
416  .close = h264_close_context,
418 };
uint8_t profile_idc
Definition: rtpdec_h264.c:47
#define NULL
Definition: coverity.c:32
const char * s
Definition: avisynth_c.h:631
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
RTP/JPEG specific private data.
Definition: rdt.c:83
int index
stream index in AVFormatContext
Definition: avformat.h:843
static int h264_handle_packet_fu_a(AVFormatContext *ctx, PayloadContext *data, AVPacket *pkt, const uint8_t *buf, int len, int *nal_counters, int nal_mask)
Definition: rtpdec_h264.c:281
int packetization_mode
Definition: rtpdec_h264.c:50
void ff_h264_parse_framesize(AVCodecContext *codec, const char *p)
Definition: rtpdec_h264.c:180
RTPDynamicProtocolHandler ff_h264_dynamic_handler
Definition: rtpdec_h264.c:409
static AVPacket pkt
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_WB24 unsigned int_TMPL AV_RB16
Definition: bytestream.h:87
Macro definitions for various function/variable attributes.
Format I/O context.
Definition: avformat.h:1273
uint8_t
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:1617
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1341
uint8_t * data
Definition: avcodec.h:1423
int ff_h264_handle_frag_packet(AVPacket *pkt, const uint8_t *buf, int len, int start_bit, const uint8_t *nal_header, int nal_header_len)
Definition: rtpdec_h264.c:260
#define av_log(a,...)
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:83
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
static void h264_close_context(PayloadContext *data)
Definition: rtpdec_h264.c:374
#define AVERROR(e)
Definition: error.h:43
static int sdp_parse_fmtp_config_h264(AVFormatContext *s, AVStream *stream, PayloadContext *h264_data, const char *attr, const char *value)
Definition: rtpdec_h264.c:144
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
Definition: graph2dot.c:48
static int parse_h264_sdp_line(AVFormatContext *s, int st_index, PayloadContext *h264_data, const char *line)
Definition: rtpdec_h264.c:387
#define pass
Definition: fft_template.c:509
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:861
int width
picture width / height.
Definition: avcodec.h:1681
GLsizei GLboolean const GLfloat * value
Definition: opengl_enc.c:109
uint8_t profile_iop
Definition: rtpdec_h264.c:48
#define COUNT_NAL_TYPE(data, nal)
Definition: rtpdec_h264.c:60
Stream structure.
Definition: avformat.h:842
AVS_Value src
Definition: avisynth_c.h:482
main external API structure.
Definition: avcodec.h:1502
static void parse_profile_level_id(AVFormatContext *s, PayloadContext *h264_data, const char *value)
Definition: rtpdec_h264.c:67
void * buf
Definition: avisynth_c.h:553
GLint GLenum type
Definition: opengl_enc.c:105
int extradata_size
Definition: avcodec.h:1618
uint8_t level_idc
Definition: rtpdec_h264.c:49
int ff_parse_fmtp(AVFormatContext *s, AVStream *stream, PayloadContext *data, const char *p, int(*parse_fmtp)(AVFormatContext *s, AVStream *stream, PayloadContext *data, const char *attr, const char *value))
Definition: rtpdec.c:850
const char * enc_name
Definition: rtpdec.h:116
static int flags
Definition: cpu.c:47
#define NAL_MASK
Definition: rtpdec_h264.c:63
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition: avstring.c:34
full parsing and repack
Definition: avformat.h:774
Main libavformat public API header.
#define NAL_COUNTERS
Definition: rtpdec_h264.c:61
static int h264_handle_packet(AVFormatContext *ctx, PayloadContext *data, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len, uint16_t seq, int flags)
Definition: rtpdec_h264.c:308
void * av_realloc(void *ptr, size_t size)
Allocate or reallocate a block of memory.
Definition: mem.c:145
int ff_h264_parse_sprop_parameter_sets(AVFormatContext *s, uint8_t **data_ptr, int *size_ptr, const char *value)
Definition: rtpdec_h264.c:96
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
Definition: avcodec.h:636
static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index)
Parse a packet, add all split parts to parse_queue.
Definition: utils.c:1190
int ff_h264_handle_aggregated_packet(AVFormatContext *ctx, PayloadContext *data, AVPacket *pkt, const uint8_t *buf, int len, int skip_between, int *nal_counters, int nal_mask)
Definition: rtpdec_h264.c:202
int len
static const uint8_t start_sequence[]
Definition: rtpdec_h264.c:65
int av_base64_decode(uint8_t *out, const char *in_str, int out_size)
Decode a base64-encoded string.
Definition: base64.c:79
#define av_freep(p)
int stream_index
Definition: avcodec.h:1425
This structure stores compressed data.
Definition: avcodec.h:1400
GLuint buffer
Definition: opengl_enc.c:102