]> git.sesse.net Git - vlc/blob - modules/packetizer/hevc.c
decoder: factor some common code into DecoderUpdateFormatLocked()
[vlc] / modules / packetizer / hevc.c
1 /*****************************************************************************
2  * hevc.c: h.265/hevc video packetizer
3  *****************************************************************************
4  * Copyright (C) 2014 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Denis Charmet <typx@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_codec.h>
35 #include <vlc_block.h>
36
37 #include <vlc_bits.h>
38 #include <vlc_block_helper.h>
39 #include "packetizer_helper.h"
40
41 /*****************************************************************************
42  * Module descriptor
43  *****************************************************************************/
44 static int  Open (vlc_object_t *);
45 static void Close(vlc_object_t *);
46
47 vlc_module_begin ()
48     set_category(CAT_SOUT)
49     set_subcategory(SUBCAT_SOUT_PACKETIZER)
50     set_description(N_("HEVC/H.265 video packetizer"))
51     set_capability("packetizer", 50)
52     set_callbacks(Open, Close)
53 vlc_module_end ()
54
55
56 /****************************************************************************
57  * Local prototypes
58  ****************************************************************************/
59 static block_t *Packetize(decoder_t *, block_t **);
60 static void PacketizeReset(void *p_private, bool b_broken);
61 static block_t *PacketizeParse(void *p_private, bool *pb_ts_used, block_t *);
62 static int PacketizeValidate(void *p_private, block_t *);
63
64 struct decoder_sys_t
65 {
66     /* */
67     packetizer_t packetizer;
68
69     bool     b_vcl;
70     block_t *p_frame;
71
72 };
73
74 /* NAL types from https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-H.265-201304-I!!PDF-E&type=items */
75 enum nal_unit_type_e
76 {
77     TRAIL_N    = 0,
78     TRAIL_R    = 1,
79     TSA_N      = 2,
80     TSA_R      = 3,
81     STSA_N     = 4,
82     STSA_R     = 5,
83     RADL_N     = 6,
84     RADL_R     = 7,
85     RASL_N     = 8,
86     RASL_R     = 9,
87     /* 10 to 15 reserved */
88     /* Key frames */
89     BLA_W_LP   = 16,
90     BLA_W_RADL = 17,
91     BLA_N_LP   = 18,
92     IDR_W_RADL = 19,
93     IDR_N_LP   = 20,
94     CRA        = 21,
95     /* 22 to 31 reserved */
96     /* Non VCL NAL*/
97     VPS        = 32,
98     SPS        = 33,
99     PPS        = 34,
100     AUD        = 35, /* Access unit delimiter */
101     EOS        = 36, /* End of sequence */
102     EOB        = 37, /* End of bitstream */
103     FD         = 38, /* Filler data*/
104     PREF_SEI   = 39, /* Prefix SEI */
105     SUFF_SEI   = 40, /* Suffix SEI */
106     UNKNOWN_NAL
107 };
108
109 static const uint8_t p_hevc_startcode[3] = {0x00, 0x00, 0x01};
110
111 /*****************************************************************************
112  * Open
113  *****************************************************************************/
114 static int Open(vlc_object_t *p_this)
115 {
116     decoder_t     *p_dec = (decoder_t*)p_this;
117
118     if (p_dec->fmt_in.i_codec != VLC_CODEC_HEVC)
119         return VLC_EGENERIC;
120
121     p_dec->p_sys = calloc(1, sizeof(decoder_sys_t));
122     if (!p_dec->p_sys)
123         return VLC_ENOMEM;
124
125     packetizer_Init(&p_dec->p_sys->packetizer,
126                     p_hevc_startcode, sizeof(p_hevc_startcode),
127                     p_hevc_startcode, 1, 5,
128                     PacketizeReset, PacketizeParse, PacketizeValidate, p_dec);
129
130     /* Copy properties */
131     es_format_Copy(&p_dec->fmt_out, &p_dec->fmt_in);
132
133     /* Set callback */
134     p_dec->pf_packetize = Packetize;
135
136     return VLC_SUCCESS;
137
138 }
139
140 /*****************************************************************************
141  * Close
142  *****************************************************************************/
143 static void Close(vlc_object_t *p_this)
144 {
145     decoder_t *p_dec = (decoder_t*)p_this;
146     decoder_sys_t *p_sys = p_dec->p_sys;
147     packetizer_Clean(&p_sys->packetizer);
148
149     free(p_sys);
150 }
151
152 /****************************************************************************
153  * Packetize
154  ****************************************************************************/
155 static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
156 {
157     decoder_sys_t *p_sys = p_dec->p_sys;
158
159     return packetizer_Packetize(&p_sys->packetizer, pp_block);
160 }
161
162 /****************************************************************************
163  * Packetizer Helpers
164  ****************************************************************************/
165 static void PacketizeReset(void *p_private, bool b_broken)
166 {
167     VLC_UNUSED(b_broken);
168
169     decoder_t *p_dec = p_private;
170     decoder_sys_t *p_sys = p_dec->p_sys;
171     block_ChainRelease(p_sys->p_frame);
172
173     p_sys->p_frame = NULL;
174     p_sys->b_vcl = false;
175 }
176
177 static block_t *PacketizeParse(void *p_private, bool *pb_ts_used, block_t *p_block)
178 {
179     decoder_t *p_dec = p_private;
180     decoder_sys_t *p_sys = p_dec->p_sys;
181
182     block_t * p_nal = NULL;
183
184     while (p_block->i_buffer > 5 && p_block->p_buffer[p_block->i_buffer-1] == 0x00 )
185         p_block->i_buffer--;
186
187     bs_t bs;
188     bs_init(&bs, p_block->p_buffer+4, p_block->i_buffer-4);
189
190     /* Get NALU type */
191     uint32_t forbidden_zero_bit = bs_read1(&bs);
192
193     if (forbidden_zero_bit)
194     {
195         msg_Err(p_dec,"Forbidden zero bit not null, corrupted NAL");
196         p_sys->p_frame = NULL;
197         p_sys->b_vcl = false;
198         return NULL;
199     }
200     uint32_t nalu_type = bs_read(&bs,6);
201     bs_skip(&bs, 9);
202
203     if (nalu_type < VPS)
204     {
205         /* NAL is a VCL NAL */
206         p_sys->b_vcl = true;
207
208         uint32_t first_slice_in_pic = bs_read1(&bs);
209
210         if (first_slice_in_pic && p_sys->p_frame)
211         {
212             p_nal = block_ChainGather(p_sys->p_frame);
213             p_sys->p_frame = NULL;
214         }
215
216         block_ChainAppend(&p_sys->p_frame, p_block);
217     }
218     else
219     {
220         if (p_sys->b_vcl)
221         {
222             p_nal = block_ChainGather(p_sys->p_frame);
223             p_nal->p_next = p_block;
224             p_sys->p_frame = NULL;
225             p_sys->b_vcl =false;
226         }
227         else
228             p_nal = p_block;
229     }
230
231     *pb_ts_used = false;
232     return p_nal;
233 }
234
235 static int PacketizeValidate( void *p_private, block_t *p_au )
236 {
237     VLC_UNUSED(p_private);
238     VLC_UNUSED(p_au);
239     return VLC_SUCCESS;
240 }