Imported Debian version 2.5.0~trusty1.1
[deb_ffmpeg.git] / ffmpeg / libavformat / rtpenc_hevc.c
CommitLineData
f6fa7814
DM
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 "avc.h"
23#include "avformat.h"
24#include "rtpenc.h"
25
26#define RTP_HEVC_HEADERS_SIZE 3
27
28static void nal_send(AVFormatContext *ctx, const uint8_t *buf, int len, int last_packet_of_frame)
29{
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;
33
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);
38 } else {
39 /*
40 create the HEVC payload header and transmit the buffer as fragmentation units (FU)
41
42 0 1
43 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
44 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 |F| Type | LayerId | TID |
46 +-------------+-----------------+
47
48 F = 0
49 Type = 49 (fragmentation unit (FU))
50 LayerId = 0
51 TID = 1
52 */
53 rtp_ctx->buf[0] = 49 << 1;
54 rtp_ctx->buf[1] = 1;
55
56 /*
57 create the FU header
58
59 0 1 2 3 4 5 6 7
60 +-+-+-+-+-+-+-+-+
61 |S|E| FuType |
62 +---------------+
63
64 S = variable
65 E = variable
66 FuType = NAL unit type
67 */
68 rtp_ctx->buf[2] = nal_type;
69 /* set the S bit: mark as start fragment */
70 rtp_ctx->buf[2] |= 1 << 7;
71
72 /* pass the original NAL header */
73 buf += 2;
74 len -= 2;
75
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);
80
81 buf += rtp_payload_size;
82 len -= rtp_payload_size;
83
84 /* reset the S bit */
85 rtp_ctx->buf[2] &= ~(1 << 7);
86 }
87
88 /* set the E bit: mark as last fragment */
89 rtp_ctx->buf[2] |= 1 << 6;
90
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);
94 }
95}
96
97void ff_rtp_send_hevc(AVFormatContext *ctx, const uint8_t *frame_buf, int frame_size)
98{
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;
102
103 /* use the default 90 KHz time stamp */
104 rtp_ctx->timestamp = rtp_ctx->cur_timestamp;
105
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;
108 else
109 buf_ptr = ff_avc_find_startcode(frame_buf, buf_end);
110
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);
115 if (!next_NAL_unit)
116 next_NAL_unit = buf_end;
117
118 buf_ptr += rtp_ctx->nal_length_size;
119 } else {
120 while (!*(buf_ptr++))
121 ;
122 next_NAL_unit = ff_avc_find_startcode(buf_ptr, buf_end);
123 }
124 /* send the next NAL unit */
125 nal_send(ctx, buf_ptr, next_NAL_unit - buf_ptr, next_NAL_unit == buf_end);
126
127 /* jump to the next NAL unit */
128 buf_ptr = next_NAL_unit;
129 }
130}