]> git.sesse.net Git - vlc/blob - modules/codec/hevc_nal.c
upnp: change item b_net and i_type
[vlc] / modules / codec / hevc_nal.c
1 /*****************************************************************************
2  * Copyright © 2010-2014 VideoLAN
3  *
4  * Authors: Thomas Guillem <thomas.guillem@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19  *****************************************************************************/
20
21 #include "hevc_nal.h"
22
23 #include <limits.h>
24
25 /* Inspired by libavcodec/hevc.c */
26 int convert_hevc_nal_units(decoder_t *p_dec, const uint8_t *p_buf,
27                            uint32_t i_buf_size, uint8_t *p_out_buf,
28                            uint32_t i_out_buf_size, uint32_t *p_sps_pps_size,
29                            uint32_t *p_nal_size)
30 {
31     int i, num_arrays;
32     const uint8_t *p_end = p_buf + i_buf_size;
33     uint32_t i_sps_pps_size = 0;
34
35     if( i_buf_size <= 3 || ( !p_buf[0] && !p_buf[1] && p_buf[2] <= 1 ) )
36         return VLC_EGENERIC;
37
38     if( p_end - p_buf < 23 )
39     {
40         msg_Err( p_dec, "Input Metadata too small" );
41         return VLC_ENOMEM;
42     }
43
44     p_buf += 21;
45
46     if( p_nal_size )
47         *p_nal_size = (*p_buf & 0x03) + 1;
48     p_buf++;
49
50     num_arrays = *p_buf++;
51
52     for( i = 0; i < num_arrays; i++ )
53     {
54         int type, cnt, j;
55
56         if( p_end - p_buf < 3 )
57         {
58             msg_Err( p_dec, "Input Metadata too small" );
59             return VLC_ENOMEM;
60         }
61         type = *(p_buf++) & 0x3f;
62         VLC_UNUSED(type);
63
64         cnt = p_buf[0] << 8 | p_buf[1];
65         p_buf += 2;
66
67         for( j = 0; j < cnt; j++ )
68         {
69             int i_nal_size;
70
71             if( p_end - p_buf < 2 )
72             {
73                 msg_Err( p_dec, "Input Metadata too small" );
74                 return VLC_ENOMEM;
75             }
76             
77             i_nal_size = p_buf[0] << 8 | p_buf[1];
78             p_buf += 2;
79
80             if( i_nal_size < 0 || p_end - p_buf < i_nal_size )
81             {
82                 msg_Err( p_dec, "NAL unit size does not match Input Metadata size" );
83                 return VLC_ENOMEM;
84             }
85
86             if( i_sps_pps_size + 4 + i_nal_size > i_out_buf_size )
87             {
88                 msg_Err( p_dec, "Output buffer too small" );
89                 return VLC_ENOMEM;
90             }
91
92             p_out_buf[i_sps_pps_size++] = 0;
93             p_out_buf[i_sps_pps_size++] = 0;
94             p_out_buf[i_sps_pps_size++] = 0;
95             p_out_buf[i_sps_pps_size++] = 1;
96
97             memcpy(p_out_buf + i_sps_pps_size, p_buf, i_nal_size);
98             p_buf += i_nal_size;
99
100             i_sps_pps_size += i_nal_size;
101         }
102     }
103
104     *p_sps_pps_size = i_sps_pps_size;
105
106     return VLC_SUCCESS;
107 }