2 * RTP packetizer for HEVC/H.265 payload format (draft version 6)
3 * Copyright (c) 2014 Thomas Volkert <thomas@homer-conferencing.com>
5 * This file is part of FFmpeg.
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.
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.
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
26 #define RTP_HEVC_HEADERS_SIZE 3
28 static void nal_send(AVFormatContext
*ctx
, const uint8_t *buf
, int len
, int last_packet_of_frame
)
30 RTPMuxContext
*rtp_ctx
= ctx
->priv_data
;
31 int rtp_payload_size
= rtp_ctx
->max_payload_size
- RTP_HEVC_HEADERS_SIZE
;
32 int nal_type
= (buf
[0] >> 1) & 0x3F;
34 /* send it as one single NAL unit? */
35 if (len
<= rtp_ctx
->max_payload_size
) {
36 /* use the original NAL unit buffer and transmit it as RTP payload */
37 ff_rtp_send_data(ctx
, buf
, len
, last_packet_of_frame
);
40 create the HEVC payload header and transmit the buffer as fragmentation units (FU)
43 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
44 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 |F| Type | LayerId | TID |
46 +-------------+-----------------+
49 Type = 49 (fragmentation unit (FU))
53 rtp_ctx
->buf
[0] = 49 << 1;
66 FuType = NAL unit type
68 rtp_ctx
->buf
[2] = nal_type
;
69 /* set the S bit: mark as start fragment */
70 rtp_ctx
->buf
[2] |= 1 << 7;
72 /* pass the original NAL header */
76 while (len
> rtp_payload_size
) {
77 /* complete and send current RTP packet */
78 memcpy(&rtp_ctx
->buf
[RTP_HEVC_HEADERS_SIZE
], buf
, rtp_payload_size
);
79 ff_rtp_send_data(ctx
, rtp_ctx
->buf
, rtp_ctx
->max_payload_size
, 0);
81 buf
+= rtp_payload_size
;
82 len
-= rtp_payload_size
;
85 rtp_ctx
->buf
[2] &= ~(1 << 7);
88 /* set the E bit: mark as last fragment */
89 rtp_ctx
->buf
[2] |= 1 << 6;
91 /* complete and send last RTP packet */
92 memcpy(&rtp_ctx
->buf
[RTP_HEVC_HEADERS_SIZE
], buf
, len
);
93 ff_rtp_send_data(ctx
, rtp_ctx
->buf
, len
+ 2, last_packet_of_frame
);
97 void ff_rtp_send_hevc(AVFormatContext
*ctx
, const uint8_t *frame_buf
, int frame_size
)
99 const uint8_t *next_NAL_unit
;
100 const uint8_t *buf_ptr
, *buf_end
= frame_buf
+ frame_size
;
101 RTPMuxContext
*rtp_ctx
= ctx
->priv_data
;
103 /* use the default 90 KHz time stamp */
104 rtp_ctx
->timestamp
= rtp_ctx
->cur_timestamp
;
106 if (rtp_ctx
->nal_length_size
)
107 buf_ptr
= ff_avc_mp4_find_startcode(frame_buf
, buf_end
, rtp_ctx
->nal_length_size
) ? frame_buf
: buf_end
;
109 buf_ptr
= ff_avc_find_startcode(frame_buf
, buf_end
);
111 /* find all NAL units and send them as separate packets */
112 while (buf_ptr
< buf_end
) {
113 if (rtp_ctx
->nal_length_size
) {
114 next_NAL_unit
= ff_avc_mp4_find_startcode(buf_ptr
, buf_end
, rtp_ctx
->nal_length_size
);
116 next_NAL_unit
= buf_end
;
118 buf_ptr
+= rtp_ctx
->nal_length_size
;
120 while (!*(buf_ptr
++))
122 next_NAL_unit
= ff_avc_find_startcode(buf_ptr
, buf_end
);
124 /* send the next NAL unit */
125 nal_send(ctx
, buf_ptr
, next_NAL_unit
- buf_ptr
, next_NAL_unit
== buf_end
);
127 /* jump to the next NAL unit */
128 buf_ptr
= next_NAL_unit
;