]> git.sesse.net Git - vlc/blob - modules/demux/mpeg/hevc.c
Fix CreateDecodedNAL return
[vlc] / modules / demux / mpeg / hevc.c
1 /*****************************************************************************
2  * hevc.c : HEVC Video demuxer
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_demux.h>
35 #include <vlc_codec.h>
36 #include <vlc_bits.h>
37
38 #include "mpeg_parser_helpers.h"
39
40 /*****************************************************************************
41  * Module descriptor
42  *****************************************************************************/
43 static int  Open ( vlc_object_t * );
44 static void Close( vlc_object_t * );
45
46 #define FPS_TEXT N_("Frames per Second")
47 #define FPS_LONGTEXT N_("Desired frame rate for the stream.")
48
49
50 vlc_module_begin ()
51     set_shortname( "HEVC")
52     set_category( CAT_INPUT )
53     set_subcategory( SUBCAT_INPUT_DEMUX )
54     set_description( N_("HEVC/H.265 video demuxer" ) )
55     set_capability( "demux", 0 )
56     add_float( "hevc-force-fps", 0.0, FPS_TEXT, FPS_LONGTEXT, true )
57     set_callbacks( Open, Close )
58     add_shortcut( "hevc" )
59 vlc_module_end ()
60
61 /*****************************************************************************
62  * Local prototypes
63  *****************************************************************************/
64
65 static int Demux( demux_t * );
66 static int Control( demux_t *, int, va_list );
67 static int32_t getFPS( demux_t *, block_t * );
68
69 struct demux_sys_t
70 {
71     mtime_t     i_dts;
72     es_out_id_t *p_es;
73
74     float       f_force_fps;
75     float       f_fps;
76     decoder_t *p_packetizer;
77 };
78 #define HEVC_BLOCK_SIZE 2048
79
80 /*****************************************************************************
81  * Open: initializes demux structures
82  *****************************************************************************/
83 static int Open( vlc_object_t * p_this )
84 {
85     demux_t     *p_demux = (demux_t*)p_this;
86     demux_sys_t *p_sys;
87     const uint8_t *p_peek;
88     es_format_t fmt;
89
90     if( stream_Peek( p_demux->s, &p_peek, 5 ) < 5 ) return VLC_EGENERIC;
91
92     if( p_peek[0] != 0x00 || p_peek[1] != 0x00 ||
93         p_peek[2] != 0x00 || p_peek[3] != 0x01 ||
94         (p_peek[4]&0xFE) != 0x40 ) /* VPS & forbidden zero bit*/
95     {
96         if( !p_demux->b_force )
97         {
98             msg_Warn( p_demux, "hevc module discarded (no startcode)" );
99             return VLC_EGENERIC;
100         }
101
102         msg_Err( p_demux, "this doesn't look like a HEVC ES stream, "
103                  "continuing anyway" );
104     }
105
106     p_demux->p_sys     = p_sys = malloc( sizeof( demux_sys_t ) );
107
108     if( !p_demux->p_sys )
109         return VLC_ENOMEM;
110
111     p_sys->p_es        = NULL;
112     p_sys->i_dts       = VLC_TS_0;
113     p_sys->f_force_fps = var_CreateGetFloat( p_demux, "hevc-force-fps" );
114     if( p_sys->f_force_fps != 0.0f )
115     {
116         p_sys->f_fps = ( p_sys->f_force_fps < 0.001f )? 0.001f:
117             p_sys->f_force_fps;
118         msg_Dbg( p_demux, "using %.2f fps", p_sys->f_fps );
119     }
120     else
121         p_sys->f_fps = 0.0f;
122
123     /* Load the hevc packetizer */
124     es_format_Init( &fmt, VIDEO_ES, VLC_CODEC_HEVC );
125     p_sys->p_packetizer = demux_PacketizerNew( p_demux, &fmt, "hevc" );
126     if( !p_sys->p_packetizer )
127     {
128         free( p_sys );
129         return VLC_EGENERIC;
130     }
131
132     p_sys->p_packetizer->fmt_out.b_packetized = true;
133     p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_out);
134
135     if( !p_sys->p_es )
136     {
137         demux_PacketizerDestroy( p_sys->p_packetizer );
138         free( p_sys );
139         return VLC_ENOMEM;
140     }
141     p_demux->pf_demux  = Demux;
142     p_demux->pf_control= Control;
143
144     return VLC_SUCCESS;
145 }
146
147 /*****************************************************************************
148  * Close: frees unused data
149  *****************************************************************************/
150 static void Close( vlc_object_t * p_this )
151 {
152     demux_t     *p_demux = (demux_t*)p_this;
153     demux_sys_t *p_sys = p_demux->p_sys;
154
155     demux_PacketizerDestroy( p_sys->p_packetizer );
156     free( p_sys );
157 }
158
159 /*****************************************************************************
160  * Demux: reads and demuxes data packets
161  *****************************************************************************
162  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
163  *****************************************************************************/
164 static int Demux( demux_t *p_demux)
165 {
166     demux_sys_t *p_sys = p_demux->p_sys;
167     block_t *p_block_in, *p_block_out;
168
169     if( ( p_block_in = stream_Block( p_demux->s, HEVC_BLOCK_SIZE ) ) == NULL )
170     {
171         return 0;
172     }
173
174     p_block_in->i_dts = VLC_TS_INVALID;
175     p_block_in->i_pts = VLC_TS_INVALID;
176
177     while( (p_block_out = p_sys->p_packetizer->pf_packetize( p_sys->p_packetizer, &p_block_in )) )
178     {
179         while( p_block_out )
180         {
181             block_t *p_next = p_block_out->p_next;
182
183             p_block_out->p_next = NULL;
184
185             p_block_out->i_dts = p_sys->i_dts;
186             p_block_out->i_pts = VLC_TS_INVALID;
187
188             uint8_t nal_type = p_block_out->p_buffer[4] & 0x7E;
189
190             /*Get fps from vps if available and not already forced*/
191             if( p_sys->f_fps == 0.0f && nal_type == 0x40 )
192             {
193                 if( getFPS( p_demux, p_block_out) )
194                 {
195                     msg_Err(p_demux,"getFPS failed");
196                     return 0;
197                 }
198             }
199
200             /* Update DTS only on VCL NAL*/
201             if( nal_type < 0x40 && p_sys->f_fps )
202             {
203                 es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_dts );
204                 p_sys->i_dts += (int64_t)((double)1000000.0 / p_sys->f_fps);
205             }
206
207             es_out_Send( p_demux->out, p_sys->p_es, p_block_out );
208
209             p_block_out = p_next;
210
211         }
212     }
213     return 1;
214 }
215
216 /*****************************************************************************
217  * Control:
218  *****************************************************************************/
219 static int Control( demux_t *p_demux, int i_query, va_list args )
220 {
221     return demux_vaControlHelper( p_demux->s,
222                                   0, -1,
223                                   0, 1, i_query, args );
224 }
225
226
227 static uint8_t * CreateDecodedNAL( int *pi_ret,
228                               const uint8_t *src, int i_src )
229 {
230     uint8_t *dst = malloc( i_src );
231     if( !dst )
232         return NULL;
233
234     *pi_ret = nal_decode( src, dst, i_src );
235     return dst;
236 }
237
238 static int32_t getFPS( demux_t *p_demux, block_t * p_block )
239 {
240     demux_sys_t *p_sys = p_demux->p_sys;
241
242     bs_t bs;
243     uint8_t * p_decoded_nal;
244     int i_decoded_nal;
245
246     if( p_block->i_buffer < 5 )
247         return -1;
248
249     p_decoded_nal = CreateDecodedNAL(&i_decoded_nal,
250                                      p_block->p_buffer+4, p_block->i_buffer-4);
251
252     if( !p_decoded_nal )
253         return -1;
254
255     bs_init( &bs, p_decoded_nal, i_decoded_nal );
256     bs_skip( &bs, 12 );
257     int32_t max_sub_layer_minus1 = bs_read( &bs, 3 );
258     bs_skip( &bs, 17 );
259
260     hevc_skip_profile_tiers_level( &bs, max_sub_layer_minus1 );
261
262     int32_t vps_sub_layer_ordering_info_present_flag = bs_read1( &bs );
263     int32_t i = vps_sub_layer_ordering_info_present_flag? 0 : max_sub_layer_minus1;
264     for( ; i <= max_sub_layer_minus1; i++ )
265     {
266         read_ue( &bs );
267         read_ue( &bs );
268         read_ue( &bs );
269     }
270     uint32_t vps_max_layer_id = bs_read( &bs, 6);
271     uint32_t vps_num_layer_sets_minus1 = read_ue( &bs );
272     bs_skip( &bs, vps_max_layer_id * vps_num_layer_sets_minus1 );
273
274     if( bs_read1( &bs ))
275     {
276         uint32_t num_units_in_tick = bs_read( &bs, 32 );
277         uint32_t time_scale = bs_read( &bs, 32 );
278         if( num_units_in_tick )
279         {
280             p_sys->f_fps = ( (float) time_scale )/( (float) num_units_in_tick );
281             msg_Dbg(p_demux,"Using framerate %f fps from VPS", p_sys->f_fps);
282         }
283         else
284         {
285             msg_Err( p_demux, "vps_num_units_in_tick null defaulting to 25 fps");
286             p_sys->f_fps = 25.0f;
287         }
288     }
289     else
290     {
291         msg_Err( p_demux, "No timing info in VPS defaulting to 25 fps");
292         p_sys->f_fps = 25.0f;
293     }
294     free(p_decoded_nal);
295     return 0;
296 }