2 * RTP H264 Protocol (RFC3984)
3 * Copyright (c) 2006 Ryan Martell
5 * This file is part of Libav.
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.
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.
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
24 * @brief H.264 / RTP Code (RFC3984)
25 * @author Ryan Martell <rdm4@martellventures.com>
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,
36 #include "libavutil/attributes.h"
37 #include "libavutil/base64.h"
38 #include "libavutil/avstring.h"
39 #include "libavcodec/get_bits.h"
46 #include "rtpdec_formats.h"
48 struct PayloadContext
{
49 // sdp setup parameters
53 int packetization_mode
;
55 int packet_types_received
[32];
60 #define COUNT_NAL_TYPE(data, nal) data->packet_types_received[(nal) & 0x1f]++
62 #define COUNT_NAL_TYPE(data, nal) do { } while (0)
65 static const uint8_t start_sequence
[] = { 0, 0, 0, 1 };
67 static void parse_profile_level_id(AVFormatContext
*s
,
68 PayloadContext
*h264_data
,
72 // 6 characters=3 bytes, in hex.
80 profile_idc
= strtol(buffer
, NULL
, 16);
83 profile_iop
= strtol(buffer
, NULL
, 16);
86 level_idc
= strtol(buffer
, NULL
, 16);
88 av_log(s
, AV_LOG_DEBUG
,
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
;
96 static int sdp_parse_fmtp_config_h264(AVFormatContext
*s
,
98 PayloadContext
*h264_data
,
99 char *attr
, char *value
)
101 AVCodecContext
*codec
= stream
->codec
;
102 assert(codec
->codec_id
== AV_CODEC_ID_H264
);
103 assert(h264_data
!= NULL
);
105 if (!strcmp(attr
, "packetization-mode")) {
106 av_log(s
, AV_LOG_DEBUG
, "RTP Packetization Mode: %d\n", atoi(value
));
107 h264_data
->packetization_mode
= atoi(value
);
109 * Packetization Mode:
110 * 0 or not present: Single NAL mode (Only nals from 1-23 are allowed)
111 * 1: Non-interleaved Mode: 1-23, 24 (STAP-A), 28 (FU-A) are allowed.
112 * 2: Interleaved Mode: 25 (STAP-B), 26 (MTAP16), 27 (MTAP24), 28 (FU-A),
113 * and 29 (FU-B) are allowed.
115 if (h264_data
->packetization_mode
> 1)
116 av_log(s
, AV_LOG_ERROR
,
117 "Interleaved RTP mode is not supported yet.\n");
118 } else if (!strcmp(attr
, "profile-level-id")) {
119 if (strlen(value
) == 6)
120 parse_profile_level_id(s
, h264_data
, value
);
121 } else if (!strcmp(attr
, "sprop-parameter-sets")) {
122 codec
->extradata_size
= 0;
123 av_freep(&codec
->extradata
);
126 char base64packet
[1024];
127 uint8_t decoded_packet
[1024];
129 char *dst
= base64packet
;
131 while (*value
&& *value
!= ','
132 && (dst
- base64packet
) < sizeof(base64packet
) - 1) {
140 packet_size
= av_base64_decode(decoded_packet
, base64packet
,
141 sizeof(decoded_packet
));
142 if (packet_size
> 0) {
143 uint8_t *dest
= av_malloc(packet_size
+ sizeof(start_sequence
) +
144 codec
->extradata_size
+
145 FF_INPUT_BUFFER_PADDING_SIZE
);
147 av_log(s
, AV_LOG_ERROR
,
148 "Unable to allocate memory for extradata!\n");
149 return AVERROR(ENOMEM
);
151 if (codec
->extradata_size
) {
152 memcpy(dest
, codec
->extradata
, codec
->extradata_size
);
153 av_free(codec
->extradata
);
156 memcpy(dest
+ codec
->extradata_size
, start_sequence
,
157 sizeof(start_sequence
));
158 memcpy(dest
+ codec
->extradata_size
+ sizeof(start_sequence
),
159 decoded_packet
, packet_size
);
160 memset(dest
+ codec
->extradata_size
+ sizeof(start_sequence
) +
161 packet_size
, 0, FF_INPUT_BUFFER_PADDING_SIZE
);
163 codec
->extradata
= dest
;
164 codec
->extradata_size
+= sizeof(start_sequence
) + packet_size
;
167 av_log(s
, AV_LOG_DEBUG
, "Extradata set to %p (size: %d)!\n",
168 codec
->extradata
, codec
->extradata_size
);
173 // return 0 on packet, no more left, 1 on packet, 1 on partial packet
174 static int h264_handle_packet(AVFormatContext
*ctx
, PayloadContext
*data
,
175 AVStream
*st
, AVPacket
*pkt
, uint32_t *timestamp
,
176 const uint8_t *buf
, int len
, uint16_t seq
,
184 av_log(ctx
, AV_LOG_ERROR
, "Empty H264 RTP packet\n");
185 return AVERROR_INVALIDDATA
;
193 /* Simplify the case (these are all the nal types used internally by
194 * the h264 codec). */
195 if (type
>= 1 && type
<= 23)
198 case 0: // undefined, but pass them through
200 if ((result
= av_new_packet(pkt
, len
+ sizeof(start_sequence
))) < 0)
202 memcpy(pkt
->data
, start_sequence
, sizeof(start_sequence
));
203 memcpy(pkt
->data
+ sizeof(start_sequence
), buf
, len
);
204 COUNT_NAL_TYPE(data
, nal
);
207 case 24: // STAP-A (one packet, multiple nals)
208 // consume the STAP-A NAL
211 // first we are going to figure out the total size
214 int total_length
= 0;
217 for (pass
= 0; pass
< 2; pass
++) {
218 const uint8_t *src
= buf
;
221 while (src_len
> 2) {
222 uint16_t nal_size
= AV_RB16(src
);
224 // consume the length of the aggregate
228 if (nal_size
<= src_len
) {
231 total_length
+= sizeof(start_sequence
) + nal_size
;
235 memcpy(dst
, start_sequence
, sizeof(start_sequence
));
236 dst
+= sizeof(start_sequence
);
237 memcpy(dst
, src
, nal_size
);
238 COUNT_NAL_TYPE(data
, *src
);
242 av_log(ctx
, AV_LOG_ERROR
,
243 "nal size exceeds length: %d %d\n", nal_size
, src_len
);
246 // eat what we handled
251 av_log(ctx
, AV_LOG_ERROR
,
252 "Consumed more bytes than we got! (%d)\n", src_len
);
256 /* now we know the total size of the packet (with the
257 * start sequences added) */
258 if ((result
= av_new_packet(pkt
, total_length
)) < 0)
262 assert(dst
- pkt
->data
== total_length
);
272 av_log(ctx
, AV_LOG_ERROR
,
273 "Unhandled type (%d) (See RFC for implementation details\n",
275 result
= AVERROR(ENOSYS
);
278 case 28: // FU-A (fragmented nal)
280 len
--; // skip the fu_indicator
282 // these are the same as above, we just redo them here for clarity
283 uint8_t fu_indicator
= nal
;
284 uint8_t fu_header
= *buf
;
285 uint8_t start_bit
= fu_header
>> 7;
286 uint8_t av_unused end_bit
= (fu_header
& 0x40) >> 6;
287 uint8_t nal_type
= fu_header
& 0x1f;
288 uint8_t reconstructed_nal
;
290 // Reconstruct this packet's true nal; only the data follows.
291 /* The original nal forbidden bit and NRI are stored in this
293 reconstructed_nal
= fu_indicator
& 0xe0;
294 reconstructed_nal
|= nal_type
;
296 // skip the fu_header
301 COUNT_NAL_TYPE(data
, nal_type
);
303 /* copy in the start sequence, and the reconstructed nal */
304 if ((result
= av_new_packet(pkt
, sizeof(start_sequence
) + sizeof(nal
) + len
)) < 0)
306 memcpy(pkt
->data
, start_sequence
, sizeof(start_sequence
));
307 pkt
->data
[sizeof(start_sequence
)] = reconstructed_nal
;
308 memcpy(pkt
->data
+ sizeof(start_sequence
) + sizeof(nal
), buf
, len
);
310 if ((result
= av_new_packet(pkt
, len
)) < 0)
312 memcpy(pkt
->data
, buf
, len
);
315 av_log(ctx
, AV_LOG_ERROR
, "Too short data for FU-A H264 RTP packet\n");
316 result
= AVERROR_INVALIDDATA
;
320 case 30: // undefined
321 case 31: // undefined
323 av_log(ctx
, AV_LOG_ERROR
, "Undefined type (%d)\n", type
);
324 result
= AVERROR_INVALIDDATA
;
328 pkt
->stream_index
= st
->index
;
333 static PayloadContext
*h264_new_context(void)
335 return av_mallocz(sizeof(PayloadContext
) + FF_INPUT_BUFFER_PADDING_SIZE
);
338 static void h264_free_context(PayloadContext
*data
)
343 for (ii
= 0; ii
< 32; ii
++) {
344 if (data
->packet_types_received
[ii
])
345 av_log(NULL
, AV_LOG_DEBUG
, "Received %d packets of type %d\n",
346 data
->packet_types_received
[ii
], ii
);
353 static av_cold
int h264_init(AVFormatContext
*s
, int st_index
,
354 PayloadContext
*data
)
358 s
->streams
[st_index
]->need_parsing
= AVSTREAM_PARSE_FULL
;
362 static int parse_h264_sdp_line(AVFormatContext
*s
, int st_index
,
363 PayloadContext
*h264_data
, const char *line
)
366 AVCodecContext
*codec
;
367 const char *p
= line
;
372 stream
= s
->streams
[st_index
];
373 codec
= stream
->codec
;
375 if (av_strstart(p
, "framesize:", &p
)) {
379 // remove the protocol identifier
380 while (*p
&& *p
== ' ')
381 p
++; // strip spaces.
382 while (*p
&& *p
!= ' ')
383 p
++; // eat protocol identifier
384 while (*p
&& *p
== ' ')
385 p
++; // strip trailing spaces.
386 while (*p
&& *p
!= '-' && (dst
- buf1
) < sizeof(buf1
) - 1)
390 // a='framesize:96 320-240'
391 // set our parameters
392 codec
->width
= atoi(buf1
);
393 codec
->height
= atoi(p
+ 1); // skip the -
394 } else if (av_strstart(p
, "fmtp:", &p
)) {
395 return ff_parse_fmtp(s
, stream
, h264_data
, p
, sdp_parse_fmtp_config_h264
);
396 } else if (av_strstart(p
, "cliprect:", &p
)) {
397 // could use this if we wanted.
403 RTPDynamicProtocolHandler ff_h264_dynamic_handler
= {
405 .codec_type
= AVMEDIA_TYPE_VIDEO
,
406 .codec_id
= AV_CODEC_ID_H264
,
408 .parse_sdp_a_line
= parse_h264_sdp_line
,
409 .alloc
= h264_new_context
,
410 .free
= h264_free_context
,
411 .parse_packet
= h264_handle_packet