Libav
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 Libav.
6  *
7  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
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.
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  par->extradata_size = 0;
170  av_freep(&par->extradata);
172  &par->extradata_size, value);
173  av_log(s, AV_LOG_DEBUG, "Extradata set to %p (size: %d)\n",
174  par->extradata, par->extradata_size);
175  return ret;
176  }
177  return 0;
178 }
179 
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  par->width = atoi(buf1);
199  par->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 H.264 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 H.264 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 H.264 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, 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  avpriv_report_missing_feature(ctx, "RTP H.264 NAL unit type %d", type);
351  result = AVERROR_PATCHWELCOME;
352  break;
353 
354  case 28: // FU-A (fragmented nal)
355  result = h264_handle_packet_fu_a(ctx, pkt, buf, len,
357  break;
358 
359  case 30: // undefined
360  case 31: // undefined
361  default:
362  av_log(ctx, AV_LOG_ERROR, "Undefined type (%d)\n", type);
363  result = AVERROR_INVALIDDATA;
364  break;
365  }
366 
367  pkt->stream_index = st->index;
368 
369  return result;
370 }
371 
373 {
374 #ifdef DEBUG
375  int ii;
376 
377  for (ii = 0; ii < 32; ii++) {
378  if (data->packet_types_received[ii])
379  av_log(NULL, AV_LOG_DEBUG, "Received %d packets of type %d\n",
380  data->packet_types_received[ii], ii);
381  }
382 #endif
383 }
384 
385 static int parse_h264_sdp_line(AVFormatContext *s, int st_index,
386  PayloadContext *h264_data, const char *line)
387 {
388  AVStream *stream;
389  const char *p = line;
390 
391  if (st_index < 0)
392  return 0;
393 
394  stream = s->streams[st_index];
395 
396  if (av_strstart(p, "framesize:", &p)) {
397  ff_h264_parse_framesize(stream->codecpar, p);
398  } else if (av_strstart(p, "fmtp:", &p)) {
399  return ff_parse_fmtp(s, stream, h264_data, p, sdp_parse_fmtp_config_h264);
400  } else if (av_strstart(p, "cliprect:", &p)) {
401  // could use this if we wanted.
402  }
403 
404  return 0;
405 }
406 
408  .enc_name = "H264",
409  .codec_type = AVMEDIA_TYPE_VIDEO,
410  .codec_id = AV_CODEC_ID_H264,
411  .need_parsing = AVSTREAM_PARSE_FULL,
412  .priv_data_size = sizeof(PayloadContext),
413  .parse_sdp_a_line = parse_h264_sdp_line,
414  .close = h264_close_context,
416 };
uint8_t profile_idc
Definition: rtpdec_h264.c:47
AVPacket pkt
Definition: rtpdec_qt.c:37
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:54
RTP/JPEG specific private data.
Definition: rdt.c:83
int index
stream index in AVFormatContext
Definition: avformat.h:706
av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (%s)\, len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt), use_generic ? ac->func_descr_generic :ac->func_descr)
int packetization_mode
Definition: rtpdec_h264.c:50
RTPDynamicProtocolHandler ff_h264_dynamic_handler
Definition: rtpdec_h264.c:407
This struct describes the properties of an encoded stream.
Definition: avcodec.h:3475
Macro definitions for various function/variable attributes.
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:202
Format I/O context.
Definition: avformat.h:940
uint8_t
int width
Video only.
Definition: avcodec.h:3525
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1008
uint8_t * data
Definition: avcodec.h:1346
static int flags
Definition: log.c:50
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 src
Definition: vp8dsp.c:254
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:84
uint32_t timestamp
current frame timestamp
Definition: rtpdec_ac3.c:31
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:124
static void h264_close_context(PayloadContext *data)
Definition: rtpdec_h264.c:372
static int h264_handle_packet_fu_a(AVFormatContext *ctx, AVPacket *pkt, const uint8_t *buf, int len, int *nal_counters, int nal_mask)
Definition: rtpdec_h264.c:281
#define AV_RB16
Definition: intreadwrite.h:53
#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:145
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:385
char buffer[RTP_MAX_PACKET_LENGTH+AV_INPUT_BUFFER_PADDING_SIZE]
Definition: rdt.c:89
int extradata_size
Size of the extradata content in bytes.
Definition: avcodec.h:3501
#define pass
Definition: fft_template.c:328
void ff_h264_parse_framesize(AVCodecParameters *par, const char *p)
Definition: rtpdec_h264.c:180
AVFormatContext * ctx
Definition: movenc.c:48
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:705
#define AVERROR_PATCHWELCOME
Not yet implemented in Libav, patches welcome.
Definition: error.h:57
NULL
Definition: eval.c:55
AVIOContext * data
Definition: rtpdec_vp8.c:36
static void parse_profile_level_id(AVFormatContext *s, PayloadContext *h264_data, const char *value)
Definition: rtpdec_h264.c:67
uint8_t level_idc
Definition: rtpdec_h264.c:49
uint8_t * buf
the temporary storage buffer
Definition: rtpdec_asf.c:168
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:853
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 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:32
full parsing and repack
Definition: avformat.h:657
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:117
int ff_h264_parse_sprop_parameter_sets(AVFormatContext *s, uint8_t **data_ptr, int *size_ptr, const char *value)
Definition: rtpdec_h264.c:96
int ff_h264_handle_aggregated_packet(AVFormatContext *ctx, AVPacket *pkt, const uint8_t *buf, int len, int skip_between, int *nal_counters, int nal_mask)
Definition: rtpdec_h264.c:202
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
Definition: avcodec.h:638
static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index)
Parse a packet, add all split parts to parse_queue.
Definition: utils.c:816
static const uint8_t start_sequence[]
Definition: rtpdec_h264.c:65
int av_base64_decode(uint8_t *out, const char *in, int out_size)
Decode a base64-encoded string.
Definition: base64.c:45
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: avcodec.h:3497
AVCodecParameters * codecpar
Definition: avformat.h:831
int stream_index
Definition: avcodec.h:1348
This structure stores compressed data.
Definition: avcodec.h:1323