FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rtpenc_hevc.c
Go to the documentation of this file.
1 /*
2  * RTP packetizer for HEVC/H.265 payload format (draft version 6)
3  * Copyright (c) 2014 Thomas Volkert <thomas@homer-conferencing.com>
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 #include "libavutil/intreadwrite.h"
23 
24 #include "avc.h"
25 #include "avformat.h"
26 #include "rtpenc.h"
27 
28 #define RTP_HEVC_HEADERS_SIZE 3
29 
30 static void flush_buffered(AVFormatContext *s1, int last)
31 {
32  RTPMuxContext *s = s1->priv_data;
33  if (s->buf_ptr != s->buf) {
34  // If only sending one single NAL unit, skip the aggregation framing
35  if (s->buffered_nals == 1)
36  ff_rtp_send_data(s1, s->buf + 4, s->buf_ptr - s->buf - 4, last);
37  else
38  ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, last);
39  }
40  s->buf_ptr = s->buf;
41  s->buffered_nals = 0;
42 }
43 
44 static void nal_send(AVFormatContext *ctx, const uint8_t *buf, int len, int last_packet_of_frame)
45 {
46  RTPMuxContext *rtp_ctx = ctx->priv_data;
47  int rtp_payload_size = rtp_ctx->max_payload_size - RTP_HEVC_HEADERS_SIZE;
48  int nal_type = (buf[0] >> 1) & 0x3F;
49 
50  /* send it as one single NAL unit? */
51  if (len <= rtp_ctx->max_payload_size) {
52  int buffered_size = rtp_ctx->buf_ptr - rtp_ctx->buf;
53  /* Flush buffered NAL units if the current unit doesn't fit */
54  if (buffered_size + 2 + len > rtp_ctx->max_payload_size) {
55  flush_buffered(ctx, 0);
56  buffered_size = 0;
57  }
58  /* If the NAL unit fits including the framing, write the unit
59  * to the buffer as an aggregate packet, otherwise flush and
60  * send as single NAL. */
61  if (buffered_size + 4 + len <= rtp_ctx->max_payload_size) {
62  if (buffered_size == 0) {
63  *rtp_ctx->buf_ptr++ = 48 << 1;
64  *rtp_ctx->buf_ptr++ = 1;
65  }
66  AV_WB16(rtp_ctx->buf_ptr, len);
67  rtp_ctx->buf_ptr += 2;
68  memcpy(rtp_ctx->buf_ptr, buf, len);
69  rtp_ctx->buf_ptr += len;
70  rtp_ctx->buffered_nals++;
71  } else {
72  flush_buffered(ctx, 0);
73  ff_rtp_send_data(ctx, buf, len, last_packet_of_frame);
74  }
75  } else {
76  flush_buffered(ctx, 0);
77  /*
78  create the HEVC payload header and transmit the buffer as fragmentation units (FU)
79 
80  0 1
81  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
82  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
83  |F| Type | LayerId | TID |
84  +-------------+-----------------+
85 
86  F = 0
87  Type = 49 (fragmentation unit (FU))
88  LayerId = 0
89  TID = 1
90  */
91  rtp_ctx->buf[0] = 49 << 1;
92  rtp_ctx->buf[1] = 1;
93 
94  /*
95  create the FU header
96 
97  0 1 2 3 4 5 6 7
98  +-+-+-+-+-+-+-+-+
99  |S|E| FuType |
100  +---------------+
101 
102  S = variable
103  E = variable
104  FuType = NAL unit type
105  */
106  rtp_ctx->buf[2] = nal_type;
107  /* set the S bit: mark as start fragment */
108  rtp_ctx->buf[2] |= 1 << 7;
109 
110  /* pass the original NAL header */
111  buf += 2;
112  len -= 2;
113 
114  while (len > rtp_payload_size) {
115  /* complete and send current RTP packet */
116  memcpy(&rtp_ctx->buf[RTP_HEVC_HEADERS_SIZE], buf, rtp_payload_size);
117  ff_rtp_send_data(ctx, rtp_ctx->buf, rtp_ctx->max_payload_size, 0);
118 
119  buf += rtp_payload_size;
120  len -= rtp_payload_size;
121 
122  /* reset the S bit */
123  rtp_ctx->buf[2] &= ~(1 << 7);
124  }
125 
126  /* set the E bit: mark as last fragment */
127  rtp_ctx->buf[2] |= 1 << 6;
128 
129  /* complete and send last RTP packet */
130  memcpy(&rtp_ctx->buf[RTP_HEVC_HEADERS_SIZE], buf, len);
131  ff_rtp_send_data(ctx, rtp_ctx->buf, len + 2, last_packet_of_frame);
132  }
133 }
134 
135 void ff_rtp_send_hevc(AVFormatContext *ctx, const uint8_t *frame_buf, int frame_size)
136 {
137  const uint8_t *next_NAL_unit;
138  const uint8_t *buf_ptr, *buf_end = frame_buf + frame_size;
139  RTPMuxContext *rtp_ctx = ctx->priv_data;
140 
141  /* use the default 90 KHz time stamp */
142  rtp_ctx->timestamp = rtp_ctx->cur_timestamp;
143  rtp_ctx->buf_ptr = rtp_ctx->buf;
144 
145  if (rtp_ctx->nal_length_size)
146  buf_ptr = ff_avc_mp4_find_startcode(frame_buf, buf_end, rtp_ctx->nal_length_size) ? frame_buf : buf_end;
147  else
148  buf_ptr = ff_avc_find_startcode(frame_buf, buf_end);
149 
150  /* find all NAL units and send them as separate packets */
151  while (buf_ptr < buf_end) {
152  if (rtp_ctx->nal_length_size) {
153  next_NAL_unit = ff_avc_mp4_find_startcode(buf_ptr, buf_end, rtp_ctx->nal_length_size);
154  if (!next_NAL_unit)
155  next_NAL_unit = buf_end;
156 
157  buf_ptr += rtp_ctx->nal_length_size;
158  } else {
159  while (!*(buf_ptr++))
160  ;
161  next_NAL_unit = ff_avc_find_startcode(buf_ptr, buf_end);
162  }
163  /* send the next NAL unit */
164  nal_send(ctx, buf_ptr, next_NAL_unit - buf_ptr, next_NAL_unit == buf_end);
165 
166  /* jump to the next NAL unit */
167  buf_ptr = next_NAL_unit;
168  }
169  flush_buffered(ctx, 1);
170 }