]> git.sesse.net Git - vlc/blob - modules/codec/h264_nal.c
mediacodec: fix warning
[vlc] / modules / codec / h264_nal.c
1 /*****************************************************************************
2  * Copyright © 2010-2014 VideoLAN
3  *
4  * Authors: Jean-Baptiste Kempf <jb@videolan.org>
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 "h264_nal.h"
22
23 #include <limits.h>
24
25 int convert_sps_pps( decoder_t *p_dec, const uint8_t *p_buf,
26                      uint32_t i_buf_size, uint8_t *p_out_buf,
27                      uint32_t i_out_buf_size, uint32_t *p_sps_pps_size,
28                      uint32_t *p_nal_size)
29 {
30     int i_profile;
31     uint32_t i_data_size = i_buf_size, i_nal_size, i_sps_pps_size = 0;
32     unsigned int i_loop_end;
33
34     /* */
35     if( i_data_size < 7 )
36     {
37         msg_Err( p_dec, "Input Metadata too small" );
38         return VLC_ENOMEM;
39     }
40
41     /* Read infos in first 6 bytes */
42     i_profile = (p_buf[1] << 16) | (p_buf[2] << 8) | p_buf[3];
43     if (p_nal_size)
44         *p_nal_size  = (p_buf[4] & 0x03) + 1;
45     p_buf       += 5;
46     i_data_size -= 5;
47
48     for ( unsigned int j = 0; j < 2; j++ )
49     {
50         /* First time is SPS, Second is PPS */
51         if( i_data_size < 1 )
52         {
53             msg_Err( p_dec, "PPS too small after processing SPS/PPS %u",
54                     i_data_size );
55             return VLC_ENOMEM;
56         }
57         i_loop_end = p_buf[0] & (j == 0 ? 0x1f : 0xff);
58         p_buf++; i_data_size--;
59
60         for ( unsigned int i = 0; i < i_loop_end; i++)
61         {
62             if( i_data_size < 2 )
63             {
64                 msg_Err( p_dec, "SPS is too small %u", i_data_size );
65                 return VLC_ENOMEM;
66             }
67
68             i_nal_size = (p_buf[0] << 8) | p_buf[1];
69             p_buf += 2;
70             i_data_size -= 2;
71
72             if( i_data_size < i_nal_size )
73             {
74                 msg_Err( p_dec, "SPS size does not match NAL specified size %u",
75                         i_data_size );
76                 return VLC_ENOMEM;
77             }
78             if( i_sps_pps_size + 4 + i_nal_size > i_out_buf_size )
79             {
80                 msg_Err( p_dec, "Output SPS/PPS buffer too small" );
81                 return VLC_ENOMEM;
82             }
83
84             p_out_buf[i_sps_pps_size++] = 0;
85             p_out_buf[i_sps_pps_size++] = 0;
86             p_out_buf[i_sps_pps_size++] = 0;
87             p_out_buf[i_sps_pps_size++] = 1;
88
89             memcpy( p_out_buf + i_sps_pps_size, p_buf, i_nal_size );
90             i_sps_pps_size += i_nal_size;
91
92             p_buf += i_nal_size;
93             i_data_size -= i_nal_size;
94         }
95     }
96
97     *p_sps_pps_size = i_sps_pps_size;
98
99     return VLC_SUCCESS;
100 }
101
102 void convert_h264_to_annexb( uint8_t *p_buf, uint32_t i_len,
103                              size_t i_nal_size,
104                              struct H264ConvertState *state )
105 {
106     if( i_nal_size < 3 || i_nal_size > 4 )
107         return;
108
109     /* This only works for NAL sizes 3-4 */
110     while( i_len > 0 )
111     {
112         if( state->nal_pos < i_nal_size ) {
113             unsigned int i;
114             for( i = 0; state->nal_pos < i_nal_size && i < i_len; i++, state->nal_pos++ ) {
115                 state->nal_len = (state->nal_len << 8) | p_buf[i];
116                 p_buf[i] = 0;
117             }
118             if( state->nal_pos < i_nal_size )
119                 return;
120             p_buf[i - 1] = 1;
121             p_buf += i;
122             i_len -= i;
123         }
124         if( state->nal_len > INT_MAX )
125             return;
126         if( state->nal_len > i_len )
127         {
128             state->nal_len -= i_len;
129             return;
130         }
131         else
132         {
133             p_buf += state->nal_len;
134             i_len -= state->nal_len;
135             state->nal_len = 0;
136             state->nal_pos = 0;
137         }
138     }
139 }
140
141 bool h264_get_profile_level(const es_format_t *p_fmt, size_t *p_profile,
142                             size_t *p_level, size_t *p_nal_size)
143 {
144     uint8_t *p = (uint8_t*)p_fmt->p_extra;
145     if(!p || !p_fmt->p_extra) return false;
146
147     /* Check the profile / level */
148     if (p_fmt->i_original_fourcc == VLC_FOURCC('a','v','c','1') && p[0] == 1)
149     {
150         if (p_fmt->i_extra < 12) return false;
151         if (p_nal_size) *p_nal_size = 1 + (p[4]&0x03);
152         if (!(p[5]&0x1f)) return false;
153         p += 8;
154     }
155     else
156     {
157         if (p_fmt->i_extra < 8) return false;
158         if (!p[0] && !p[1] && !p[2] && p[3] == 1) p += 4;
159         else if (!p[0] && !p[1] && p[2] == 1) p += 3;
160         else return false;
161     }
162
163     if ( ((*p++)&0x1f) != 7) return false;
164
165     /* Get profile/level out of first SPS */
166     if (p_profile) *p_profile = p[0];
167     if (p_level) *p_level = p[2];
168     return true;
169 }