]> git.sesse.net Git - vlc/blob - modules/codec/h264_nal.h
Android: always return an empty proxy
[vlc] / modules / codec / h264_nal.h
1 /*****************************************************************************
2  * Copyright © 2010-2011 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 <limits.h>
22
23 /* Parse the SPS/PPS Metadata and convert it to annex b format */
24 static int convert_sps_pps( decoder_t *p_dec, const uint8_t *p_buf,
25                             uint32_t i_buf_size, uint8_t *p_out_buf,
26                             uint32_t i_out_buf_size, uint32_t *p_sps_pps_size,
27                             uint32_t *p_nal_size)
28 {
29     int i_profile;
30     uint32_t i_data_size = i_buf_size, i_nal_size, i_sps_pps_size = 0;
31     unsigned int i_loop_end;
32
33     /* */
34     if( i_data_size < 7 )
35     {
36         msg_Err( p_dec, "Input Metadata too small" );
37         return VLC_ENOMEM;
38     }
39
40     /* Read infos in first 6 bytes */
41     i_profile    = (p_buf[1] << 16) | (p_buf[2] << 8) | p_buf[3];
42     if (p_nal_size)
43         *p_nal_size  = (p_buf[4] & 0x03) + 1;
44     p_buf       += 5;
45     i_data_size -= 5;
46
47     for ( unsigned int j = 0; j < 2; j++ )
48     {
49         /* First time is SPS, Second is PPS */
50         if( i_data_size < 1 )
51         {
52             msg_Err( p_dec, "PPS too small after processing SPS/PPS %u",
53                     i_data_size );
54             return VLC_ENOMEM;
55         }
56         i_loop_end = p_buf[0] & (j == 0 ? 0x1f : 0xff);
57         p_buf++; i_data_size--;
58
59         for ( unsigned int i = 0; i < i_loop_end; i++)
60         {
61             if( i_data_size < 2 )
62             {
63                 msg_Err( p_dec, "SPS is too small %u", i_data_size );
64                 return VLC_ENOMEM;
65             }
66
67             i_nal_size = (p_buf[0] << 8) | p_buf[1];
68             p_buf += 2;
69             i_data_size -= 2;
70
71             if( i_data_size < i_nal_size )
72             {
73                 msg_Err( p_dec, "SPS size does not match NAL specified size %u",
74                         i_data_size );
75                 return VLC_ENOMEM;
76             }
77             if( i_sps_pps_size + 4 + i_nal_size > i_out_buf_size )
78             {
79                 msg_Err( p_dec, "Output SPS/PPS buffer too small" );
80                 return VLC_ENOMEM;
81             }
82
83             p_out_buf[i_sps_pps_size++] = 0;
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++] = 1;
87
88             memcpy( p_out_buf + i_sps_pps_size, p_buf, i_nal_size );
89             i_sps_pps_size += i_nal_size;
90
91             p_buf += i_nal_size;
92             i_data_size -= i_nal_size;
93         }
94     }
95
96     *p_sps_pps_size = i_sps_pps_size;
97
98     return VLC_SUCCESS;
99 }
100
101 /* Convert H.264 NAL format to annex b in-place */
102 struct H264ConvertState {
103     uint32_t nal_len;
104     uint32_t nal_pos;
105 };
106
107 static void convert_h264_to_annexb( uint8_t *p_buf, uint32_t i_len,
108                                     size_t i_nal_size,
109                                     struct H264ConvertState *state )
110 {
111     if( i_nal_size < 3 || i_nal_size > 4 )
112         return;
113
114     /* This only works for NAL sizes 3-4 */
115     while( i_len > 0 )
116     {
117         if( state->nal_pos < i_nal_size ) {
118             unsigned int i;
119             for( i = 0; state->nal_pos < i_nal_size && i < i_len; i++, state->nal_pos++ ) {
120                 state->nal_len = (state->nal_len << 8) | p_buf[i];
121                 p_buf[i] = 0;
122             }
123             if( state->nal_pos < i_nal_size )
124                 return;
125             p_buf[i - 1] = 1;
126             p_buf += i;
127             i_len -= i;
128         }
129         if( state->nal_len > INT_MAX )
130             return;
131         if( state->nal_len > i_len )
132         {
133             state->nal_len -= i_len;
134             return;
135         }
136         else
137         {
138             p_buf += state->nal_len;
139             i_len -= state->nal_len;
140             state->nal_len = 0;
141             state->nal_pos = 0;
142         }
143     }
144 }