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 H.264 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.
74  uint8_t profile_iop;
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  AVCodecParameters *par = stream->codecpar;
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  if (*value == 0 || value[strlen(value) - 1] == ',') {
170  av_log(s, AV_LOG_WARNING, "Missing PPS in sprop-parameter-sets, ignoring\n");
171  return 0;
172  }
173  par->extradata_size = 0;
174  av_freep(&par->extradata);
176  &par->extradata_size, value);
177  av_log(s, AV_LOG_DEBUG, "Extradata set to %p (size: %d)\n",
178  par->extradata, par->extradata_size);
179  return ret;
180  }
181  return 0;
182 }
183 
185 {
186  char buf1[50];
187  char *dst = buf1;
188 
189  // remove the protocol identifier
190  while (*p && *p == ' ')
191  p++; // strip spaces.
192  while (*p && *p != ' ')
193  p++; // eat protocol identifier
194  while (*p && *p == ' ')
195  p++; // strip trailing spaces.
196  while (*p && *p != '-' && (dst - buf1) < sizeof(buf1) - 1)
197  *dst++ = *p++;
198  *dst = '\0';
199 
200  // a='framesize:96 320-240'
201  // set our parameters
202  par->width = atoi(buf1);
203  par->height = atoi(p + 1); // skip the -
204 }
205 
207  const uint8_t *buf, int len,
208  int skip_between, int *nal_counters,
209  int nal_mask)
210 {
211  int pass = 0;
212  int total_length = 0;
213  uint8_t *dst = NULL;
214  int ret;
215 
216  // first we are going to figure out the total size
217  for (pass = 0; pass < 2; pass++) {
218  const uint8_t *src = buf;
219  int src_len = len;
220 
221  while (src_len > 2) {
222  uint16_t nal_size = AV_RB16(src);
223 
224  // consume the length of the aggregate
225  src += 2;
226  src_len -= 2;
227 
228  if (nal_size <= src_len) {
229  if (pass == 0) {
230  // counting
231  total_length += sizeof(start_sequence) + nal_size;
232  } else {
233  // copying
234  memcpy(dst, start_sequence, sizeof(start_sequence));
235  dst += sizeof(start_sequence);
236  memcpy(dst, src, nal_size);
237  if (nal_counters)
238  nal_counters[(*src) & nal_mask]++;
239  dst += nal_size;
240  }
241  } else {
242  av_log(ctx, AV_LOG_ERROR,
243  "nal size exceeds length: %d %d\n", nal_size, src_len);
244  return AVERROR_INVALIDDATA;
245  }
246 
247  // eat what we handled
248  src += nal_size + skip_between;
249  src_len -= nal_size + skip_between;
250  }
251 
252  if (pass == 0) {
253  /* now we know the total size of the packet (with the
254  * start sequences added) */
255  if ((ret = av_new_packet(pkt, total_length)) < 0)
256  return ret;
257  dst = pkt->data;
258  }
259  }
260 
261  return 0;
262 }
263 
265  int start_bit, const uint8_t *nal_header,
266  int nal_header_len)
267 {
268  int ret;
269  int tot_len = len;
270  int pos = 0;
271  if (start_bit)
272  tot_len += sizeof(start_sequence) + nal_header_len;
273  if ((ret = av_new_packet(pkt, tot_len)) < 0)
274  return ret;
275  if (start_bit) {
276  memcpy(pkt->data + pos, start_sequence, sizeof(start_sequence));
277  pos += sizeof(start_sequence);
278  memcpy(pkt->data + pos, nal_header, nal_header_len);
279  pos += nal_header_len;
280  }
281  memcpy(pkt->data + pos, buf, len);
282  return 0;
283 }
284 
286  const uint8_t *buf, int len,
287  int *nal_counters, int nal_mask)
288 {
289  uint8_t fu_indicator, fu_header, start_bit, nal_type, nal;
290 
291  if (len < 3) {
292  av_log(ctx, AV_LOG_ERROR, "Too short data for FU-A H.264 RTP packet\n");
293  return AVERROR_INVALIDDATA;
294  }
295 
296  fu_indicator = buf[0];
297  fu_header = buf[1];
298  start_bit = fu_header >> 7;
299  nal_type = fu_header & 0x1f;
300  nal = fu_indicator & 0xe0 | nal_type;
301 
302  // skip the fu_indicator and fu_header
303  buf += 2;
304  len -= 2;
305 
306  if (start_bit && nal_counters)
307  nal_counters[nal_type & nal_mask]++;
308  return ff_h264_handle_frag_packet(pkt, buf, len, start_bit, &nal, 1);
309 }
310 
311 // return 0 on packet, no more left, 1 on packet, 1 on partial packet
313  AVStream *st, AVPacket *pkt, uint32_t *timestamp,
314  const uint8_t *buf, int len, uint16_t seq,
315  int flags)
316 {
317  uint8_t nal;
318  uint8_t type;
319  int result = 0;
320 
321  if (!len) {
322  av_log(ctx, AV_LOG_ERROR, "Empty H.264 RTP packet\n");
323  return AVERROR_INVALIDDATA;
324  }
325  nal = buf[0];
326  type = nal & 0x1f;
327 
328  /* Simplify the case (these are all the NAL types used internally by
329  * the H.264 codec). */
330  if (type >= 1 && type <= 23)
331  type = 1;
332  switch (type) {
333  case 0: // undefined, but pass them through
334  case 1:
335  if ((result = av_new_packet(pkt, len + sizeof(start_sequence))) < 0)
336  return result;
337  memcpy(pkt->data, start_sequence, sizeof(start_sequence));
338  memcpy(pkt->data + sizeof(start_sequence), buf, len);
339  COUNT_NAL_TYPE(data, nal);
340  break;
341 
342  case 24: // STAP-A (one packet, multiple nals)
343  // consume the STAP-A NAL
344  buf++;
345  len--;
346  result = ff_h264_handle_aggregated_packet(ctx, data, pkt, buf, len, 0,
348  break;
349 
350  case 25: // STAP-B
351  case 26: // MTAP-16
352  case 27: // MTAP-24
353  case 29: // FU-B
354  avpriv_report_missing_feature(ctx, "RTP H.264 NAL unit type %d", type);
355  result = AVERROR_PATCHWELCOME;
356  break;
357 
358  case 28: // FU-A (fragmented nal)
359  result = h264_handle_packet_fu_a(ctx, data, pkt, buf, len,
361  break;
362 
363  case 30: // undefined
364  case 31: // undefined
365  default:
366  av_log(ctx, AV_LOG_ERROR, "Undefined type (%d)\n", type);
367  result = AVERROR_INVALIDDATA;
368  break;
369  }
370 
371  pkt->stream_index = st->index;
372 
373  return result;
374 }
375 
377 {
378 #ifdef DEBUG
379  int ii;
380 
381  for (ii = 0; ii < 32; ii++) {
382  if (data->packet_types_received[ii])
383  av_log(NULL, AV_LOG_DEBUG, "Received %d packets of type %d\n",
384  data->packet_types_received[ii], ii);
385  }
386 #endif
387 }
388 
389 static int parse_h264_sdp_line(AVFormatContext *s, int st_index,
390  PayloadContext *h264_data, const char *line)
391 {
392  AVStream *stream;
393  const char *p = line;
394 
395  if (st_index < 0)
396  return 0;
397 
398  stream = s->streams[st_index];
399 
400  if (av_strstart(p, "framesize:", &p)) {
401  ff_h264_parse_framesize(stream->codecpar, p);
402  } else if (av_strstart(p, "fmtp:", &p)) {
403  return ff_parse_fmtp(s, stream, h264_data, p, sdp_parse_fmtp_config_h264);
404  } else if (av_strstart(p, "cliprect:", &p)) {
405  // could use this if we wanted.
406  }
407 
408  return 0;
409 }
410 
412  .enc_name = "H264",
413  .codec_type = AVMEDIA_TYPE_VIDEO,
414  .codec_id = AV_CODEC_ID_H264,
415  .need_parsing = AVSTREAM_PARSE_FULL,
416  .priv_data_size = sizeof(PayloadContext),
417  .parse_sdp_a_line = parse_h264_sdp_line,
418  .close = h264_close_context,
420 };
uint8_t profile_idc
Definition: rtpdec_h264.c:47
const RTPDynamicProtocolHandler ff_h264_dynamic_handler
Definition: rtpdec_h264.c:411
#define NULL
Definition: coverity.c:32
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:135
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
RTP/JPEG specific private data.
Definition: rdt.c:83
int index
stream index in AVFormatContext
Definition: avformat.h:875
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:285
int packetization_mode
Definition: rtpdec_h264.c:50
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
#define src
Definition: vp8dsp.c:254
This struct describes the properties of an encoded stream.
Definition: avcodec.h:3892
Macro definitions for various function/variable attributes.
int profile_idc
Definition: h264_levels.c:52
Format I/O context.
Definition: avformat.h:1351
uint8_t
int width
Video only.
Definition: avcodec.h:3966
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1419
int level_idc
Definition: h264_levels.c:25
uint8_t * data
Definition: avcodec.h:1445
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:264
#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:86
#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:376
#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:389
int extradata_size
Size of the extradata content in bytes.
Definition: avcodec.h:3918
#define pass
Definition: fft_template.c:595
void ff_h264_parse_framesize(AVCodecParameters *par, const char *p)
Definition: rtpdec_h264.c:184
GLsizei GLboolean const GLfloat * value
Definition: opengl_enc.c:109
AVFormatContext * ctx
Definition: movenc.c:48
#define s(width, name)
Definition: cbs_vp9.c:257
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:874
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
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:690
GLint GLenum type
Definition: opengl_enc.c:105
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:889
const char * enc_name
Definition: rtpdec.h:116
void avpriv_report_missing_feature(void *avc, const char *msg,...) av_printf_format(2
Log a generic warning message about a missing feature.
#define flags(name, subs,...)
Definition: cbs_av1.c:596
#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:793
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:312
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:782
static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index)
Parse a packet, add all split parts to parse_queue.
Definition: utils.c:1438
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:206
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
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: avcodec.h:3914
#define av_freep(p)
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1021
int stream_index
Definition: avcodec.h:1447
This structure stores compressed data.
Definition: avcodec.h:1422
GLuint buffer
Definition: opengl_enc.c:102