Libav
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 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/avstring.h"
39 #include "libavcodec/get_bits.h"
40 #include "avformat.h"
41 
42 #include "network.h"
43 #include <assert.h>
44 
45 #include "rtpdec.h"
46 #include "rtpdec_formats.h"
47 
48 struct PayloadContext {
49  // sdp setup parameters
54 #ifdef DEBUG
55  int packet_types_received[32];
56 #endif
57 };
58 
59 #ifdef DEBUG
60 #define COUNT_NAL_TYPE(data, nal) data->packet_types_received[(nal) & 0x1f]++
61 #else
62 #define COUNT_NAL_TYPE(data, nal) do { } while (0)
63 #endif
64 
65 static const uint8_t start_sequence[] = { 0, 0, 0, 1 };
66 
68  AVStream *stream,
69  PayloadContext *h264_data,
70  char *attr, char *value)
71 {
72  AVCodecContext *codec = stream->codec;
73  assert(codec->codec_id == AV_CODEC_ID_H264);
74  assert(h264_data != NULL);
75 
76  if (!strcmp(attr, "packetization-mode")) {
77  av_log(s, AV_LOG_DEBUG, "RTP Packetization Mode: %d\n", atoi(value));
78  h264_data->packetization_mode = atoi(value);
79  /*
80  * Packetization Mode:
81  * 0 or not present: Single NAL mode (Only nals from 1-23 are allowed)
82  * 1: Non-interleaved Mode: 1-23, 24 (STAP-A), 28 (FU-A) are allowed.
83  * 2: Interleaved Mode: 25 (STAP-B), 26 (MTAP16), 27 (MTAP24), 28 (FU-A),
84  * and 29 (FU-B) are allowed.
85  */
86  if (h264_data->packetization_mode > 1)
88  "Interleaved RTP mode is not supported yet.\n");
89  } else if (!strcmp(attr, "profile-level-id")) {
90  if (strlen(value) == 6) {
91  char buffer[3];
92  // 6 characters=3 bytes, in hex.
93  uint8_t profile_idc;
94  uint8_t profile_iop;
95  uint8_t level_idc;
96 
97  buffer[0] = value[0];
98  buffer[1] = value[1];
99  buffer[2] = '\0';
100  profile_idc = strtol(buffer, NULL, 16);
101  buffer[0] = value[2];
102  buffer[1] = value[3];
103  profile_iop = strtol(buffer, NULL, 16);
104  buffer[0] = value[4];
105  buffer[1] = value[5];
106  level_idc = strtol(buffer, NULL, 16);
107 
108  av_log(s, AV_LOG_DEBUG,
109  "RTP Profile IDC: %x Profile IOP: %x Level: %x\n",
110  profile_idc, profile_iop, level_idc);
111  h264_data->profile_idc = profile_idc;
112  h264_data->profile_iop = profile_iop;
113  h264_data->level_idc = level_idc;
114  }
115  } else if (!strcmp(attr, "sprop-parameter-sets")) {
116  codec->extradata_size = 0;
117  av_freep(&codec->extradata);
118 
119  if (*value == 0 || value[strlen(value) - 1] == ',') {
120  av_log(s, AV_LOG_WARNING, "Missing PPS in sprop-parameter-sets, ignoring\n");
121  return 0;
122  }
123 
124  while (*value) {
125  char base64packet[1024];
126  uint8_t decoded_packet[1024];
127  int packet_size;
128  char *dst = base64packet;
129 
130  while (*value && *value != ','
131  && (dst - base64packet) < sizeof(base64packet) - 1) {
132  *dst++ = *value++;
133  }
134  *dst++ = '\0';
135 
136  if (*value == ',')
137  value++;
138 
139  packet_size = av_base64_decode(decoded_packet, base64packet,
140  sizeof(decoded_packet));
141  if (packet_size > 0) {
142  uint8_t *dest = av_malloc(packet_size + sizeof(start_sequence) +
143  codec->extradata_size +
145  if (!dest) {
146  av_log(s, AV_LOG_ERROR,
147  "Unable to allocate memory for extradata!\n");
148  return AVERROR(ENOMEM);
149  }
150  if (codec->extradata_size) {
151  memcpy(dest, codec->extradata, codec->extradata_size);
152  av_free(codec->extradata);
153  }
154 
155  memcpy(dest + codec->extradata_size, start_sequence,
156  sizeof(start_sequence));
157  memcpy(dest + codec->extradata_size + sizeof(start_sequence),
158  decoded_packet, packet_size);
159  memset(dest + codec->extradata_size + sizeof(start_sequence) +
160  packet_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
161 
162  codec->extradata = dest;
163  codec->extradata_size += sizeof(start_sequence) + packet_size;
164  }
165  }
166  av_log(s, AV_LOG_DEBUG, "Extradata set to %p (size: %d)!\n",
167  codec->extradata, codec->extradata_size);
168  }
169  return 0;
170 }
171 
172 // return 0 on packet, no more left, 1 on packet, 1 on partial packet
174  AVStream *st, AVPacket *pkt, uint32_t *timestamp,
175  const uint8_t *buf, int len, uint16_t seq,
176  int flags)
177 {
178  uint8_t nal;
179  uint8_t type;
180  int result = 0;
181 
182  if (!len) {
183  av_log(ctx, AV_LOG_ERROR, "Empty H264 RTP packet\n");
184  return AVERROR_INVALIDDATA;
185  }
186  nal = buf[0];
187  type = nal & 0x1f;
188 
189  assert(data);
190  assert(buf);
191 
192  /* Simplify the case (these are all the nal types used internally by
193  * the h264 codec). */
194  if (type >= 1 && type <= 23)
195  type = 1;
196  switch (type) {
197  case 0: // undefined, but pass them through
198  case 1:
199  if ((result = av_new_packet(pkt, len + sizeof(start_sequence))) < 0)
200  return result;
201  memcpy(pkt->data, start_sequence, sizeof(start_sequence));
202  memcpy(pkt->data + sizeof(start_sequence), buf, len);
203  COUNT_NAL_TYPE(data, nal);
204  break;
205 
206  case 24: // STAP-A (one packet, multiple nals)
207  // consume the STAP-A NAL
208  buf++;
209  len--;
210  // first we are going to figure out the total size
211  {
212  int pass = 0;
213  int total_length = 0;
214  uint8_t *dst = NULL;
215 
216  for (pass = 0; pass < 2; pass++) {
217  const uint8_t *src = buf;
218  int src_len = len;
219 
220  while (src_len > 2) {
221  uint16_t nal_size = AV_RB16(src);
222 
223  // consume the length of the aggregate
224  src += 2;
225  src_len -= 2;
226 
227  if (nal_size <= src_len) {
228  if (pass == 0) {
229  // counting
230  total_length += sizeof(start_sequence) + nal_size;
231  } else {
232  // copying
233  assert(dst);
234  memcpy(dst, start_sequence, sizeof(start_sequence));
235  dst += sizeof(start_sequence);
236  memcpy(dst, src, nal_size);
237  COUNT_NAL_TYPE(data, *src);
238  dst += nal_size;
239  }
240  } else {
241  av_log(ctx, AV_LOG_ERROR,
242  "nal size exceeds length: %d %d\n", nal_size, src_len);
243  }
244 
245  // eat what we handled
246  src += nal_size;
247  src_len -= nal_size;
248 
249  if (src_len < 0)
250  av_log(ctx, AV_LOG_ERROR,
251  "Consumed more bytes than we got! (%d)\n", src_len);
252  }
253 
254  if (pass == 0) {
255  /* now we know the total size of the packet (with the
256  * start sequences added) */
257  if ((result = av_new_packet(pkt, total_length)) < 0)
258  return result;
259  dst = pkt->data;
260  } else {
261  assert(dst - pkt->data == total_length);
262  }
263  }
264  }
265  break;
266 
267  case 25: // STAP-B
268  case 26: // MTAP-16
269  case 27: // MTAP-24
270  case 29: // FU-B
271  av_log(ctx, AV_LOG_ERROR,
272  "Unhandled type (%d) (See RFC for implementation details\n",
273  type);
274  result = AVERROR(ENOSYS);
275  break;
276 
277  case 28: // FU-A (fragmented nal)
278  buf++;
279  len--; // skip the fu_indicator
280  if (len > 1) {
281  // these are the same as above, we just redo them here for clarity
282  uint8_t fu_indicator = nal;
283  uint8_t fu_header = *buf;
284  uint8_t start_bit = fu_header >> 7;
285  uint8_t av_unused end_bit = (fu_header & 0x40) >> 6;
286  uint8_t nal_type = fu_header & 0x1f;
287  uint8_t reconstructed_nal;
288 
289  // Reconstruct this packet's true nal; only the data follows.
290  /* The original nal forbidden bit and NRI are stored in this
291  * packet's nal. */
292  reconstructed_nal = fu_indicator & 0xe0;
293  reconstructed_nal |= nal_type;
294 
295  // skip the fu_header
296  buf++;
297  len--;
298 
299  if (start_bit)
300  COUNT_NAL_TYPE(data, nal_type);
301  if (start_bit) {
302  /* copy in the start sequence, and the reconstructed nal */
303  if ((result = av_new_packet(pkt, sizeof(start_sequence) + sizeof(nal) + len)) < 0)
304  return result;
305  memcpy(pkt->data, start_sequence, sizeof(start_sequence));
306  pkt->data[sizeof(start_sequence)] = reconstructed_nal;
307  memcpy(pkt->data + sizeof(start_sequence) + sizeof(nal), buf, len);
308  } else {
309  if ((result = av_new_packet(pkt, len)) < 0)
310  return result;
311  memcpy(pkt->data, buf, len);
312  }
313  } else {
314  av_log(ctx, AV_LOG_ERROR, "Too short data for FU-A H264 RTP packet\n");
315  result = AVERROR_INVALIDDATA;
316  }
317  break;
318 
319  case 30: // undefined
320  case 31: // undefined
321  default:
322  av_log(ctx, AV_LOG_ERROR, "Undefined type (%d)\n", type);
323  result = AVERROR_INVALIDDATA;
324  break;
325  }
326 
327  pkt->stream_index = st->index;
328 
329  return result;
330 }
331 
333 {
335 }
336 
338 {
339 #ifdef DEBUG
340  int ii;
341 
342  for (ii = 0; ii < 32; ii++) {
343  if (data->packet_types_received[ii])
344  av_log(NULL, AV_LOG_DEBUG, "Received %d packets of type %d\n",
345  data->packet_types_received[ii], ii);
346  }
347 #endif
348 
349  av_free(data);
350 }
351 
352 static av_cold int h264_init(AVFormatContext *s, int st_index,
354 {
355  if (st_index < 0)
356  return 0;
357  s->streams[st_index]->need_parsing = AVSTREAM_PARSE_FULL;
358  return 0;
359 }
360 
361 static int parse_h264_sdp_line(AVFormatContext *s, int st_index,
362  PayloadContext *h264_data, const char *line)
363 {
364  AVStream *stream;
365  AVCodecContext *codec;
366  const char *p = line;
367 
368  if (st_index < 0)
369  return 0;
370 
371  stream = s->streams[st_index];
372  codec = stream->codec;
373 
374  if (av_strstart(p, "framesize:", &p)) {
375  char buf1[50];
376  char *dst = buf1;
377 
378  // remove the protocol identifier
379  while (*p && *p == ' ')
380  p++; // strip spaces.
381  while (*p && *p != ' ')
382  p++; // eat protocol identifier
383  while (*p && *p == ' ')
384  p++; // strip trailing spaces.
385  while (*p && *p != '-' && (dst - buf1) < sizeof(buf1) - 1)
386  *dst++ = *p++;
387  *dst = '\0';
388 
389  // a='framesize:96 320-240'
390  // set our parameters
391  codec->width = atoi(buf1);
392  codec->height = atoi(p + 1); // skip the -
393  } else if (av_strstart(p, "fmtp:", &p)) {
394  return ff_parse_fmtp(s, stream, h264_data, p, sdp_parse_fmtp_config_h264);
395  } else if (av_strstart(p, "cliprect:", &p)) {
396  // could use this if we wanted.
397  }
398 
399  return 0;
400 }
401 
403  .enc_name = "H264",
404  .codec_type = AVMEDIA_TYPE_VIDEO,
405  .codec_id = AV_CODEC_ID_H264,
406  .init = h264_init,
407  .parse_sdp_a_line = parse_h264_sdp_line,
408  .alloc = h264_new_context,
409  .free = h264_free_context,
410  .parse_packet = h264_handle_packet
411 };
uint8_t profile_idc
Definition: rtpdec_h264.c:50
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:62
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:54
int ff_parse_fmtp(AVFormatContext *s, AVStream *stream, PayloadContext *data, const char *p, int(*parse_fmtp)(AVFormatContext *s, AVStream *stream, PayloadContext *data, char *attr, char *value))
Definition: rtpdec.c:829
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:129
RTP/JPEG specific private data.
Definition: rdt.c:83
int index
stream index in AVFormatContext
Definition: avformat.h:700
int packetization_mode
Definition: rtpdec_h264.c:53
RTPDynamicProtocolHandler ff_h264_dynamic_handler
Definition: rtpdec_h264.c:402
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:198
Format I/O context.
Definition: avformat.h:922
static void h264_free_context(PayloadContext *data)
Definition: rtpdec_h264.c:337
uint8_t
#define av_cold
Definition: attributes.h:66
enum AVStreamParseType need_parsing
Definition: avformat.h:867
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:1164
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:990
const char data[16]
Definition: mxf.c:70
uint8_t * data
Definition: avcodec.h:973
static av_cold int h264_init(AVFormatContext *s, int st_index, PayloadContext *data)
Definition: rtpdec_h264.c:352
static int flags
Definition: log.c:44
bitstream reader API header.
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:81
static PayloadContext * h264_new_context(void)
Definition: rtpdec_h264.c:332
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:123
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:186
#define AV_RB16
Definition: intreadwrite.h:53
#define AVERROR(e)
Definition: error.h:43
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:144
Definition: graph2dot.c:49
static int parse_h264_sdp_line(AVFormatContext *s, int st_index, PayloadContext *h264_data, const char *line)
Definition: rtpdec_h264.c:361
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:169
#define pass
Definition: fft_template.c:335
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:718
#define FF_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
Definition: avcodec.h:531
int width
picture width / height.
Definition: avcodec.h:1229
static char buffer[20]
Definition: seek-test.c:31
uint8_t profile_iop
Definition: rtpdec_h264.c:51
#define COUNT_NAL_TYPE(data, nal)
Definition: rtpdec_h264.c:62
Stream structure.
Definition: avformat.h:699
static int sdp_parse_fmtp_config_h264(AVFormatContext *s, AVStream *stream, PayloadContext *h264_data, char *attr, char *value)
Definition: rtpdec_h264.c:67
NULL
Definition: eval.c:55
enum AVCodecID codec_id
Definition: avcodec.h:1067
main external API structure.
Definition: avcodec.h:1050
int extradata_size
Definition: avcodec.h:1165
uint8_t level_idc
Definition: rtpdec_h264.c:52
const char enc_name[50]
Definition: rtpdec.h:116
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:653
Main libavformat public API header.
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:173
int len
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
int stream_index
Definition: avcodec.h:975
This structure stores compressed data.
Definition: avcodec.h:950
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:205
#define av_unused
Definition: attributes.h:86