1 /*****************************************************************************
2 * Copyright © 2015 VideoLAN Authors
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; either version 2.1 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
17 *****************************************************************************/
24 #include <vlc_block.h>
26 static bool block_WillRealloc( block_t
*p_block
, ssize_t i_prebody
, size_t i_body
)
28 if( i_prebody
<= 0 && i_body
<= (size_t)(-i_prebody
) )
31 return ( i_prebody
+ i_body
<= p_block
->i_size
);
34 static inline void hxxx_WritePrefix( uint8_t i_nal_length_size
, uint8_t *p_dest
, uint32_t i_payload
)
36 if( i_nal_length_size
== 4 )
37 SetDWBE( p_dest
, i_payload
);
38 else if( i_nal_length_size
== 2 )
39 SetWBE( p_dest
, i_payload
);
44 block_t
*hxxx_AnnexB_to_xVC( block_t
*p_block
, uint8_t i_nal_length_size
)
46 unsigned i_nalcount
= 0;
50 const uint8_t *p
; /* start of prefixed nal */
51 uint8_t prefix
; /* startcode length */
52 off_t move
; /* move offset */
55 if(!p_block
->i_buffer
|| p_block
->p_buffer
[0])
58 if(! (p_list
= malloc( sizeof(*p_list
) * i_list
)) )
61 /* Search all startcode of size 3 */
62 const uint8_t *p_buf
= p_block
->p_buffer
;
63 const uint8_t *p_end
= &p_block
->p_buffer
[p_block
->i_buffer
];
64 unsigned i_bitflow
= 0;
66 while( p_buf
!= p_end
)
73 else if( *p_buf
== 0x01 && (i_bitflow
& 0x06) == 0x06 ) /* >= two zero prefixed 1 */
75 if( i_bitflow
& 0x08 ) /* three zero prefixed 1 */
77 p_list
[i_nalcount
].p
= &p_buf
[-3];
78 p_list
[i_nalcount
].prefix
= 4;
80 else /* two zero prefixed 1 */
82 p_list
[i_nalcount
].p
= &p_buf
[-2];
83 p_list
[i_nalcount
].prefix
= 3;
85 i_move
+= (off_t
) i_nal_length_size
- p_list
[i_nalcount
].prefix
;
86 p_list
[i_nalcount
++].move
= i_move
;
88 /* Check and realloc our list */
89 if(i_nalcount
== i_list
)
92 struct nalmoves_e
*p_new
= realloc( p_list
, sizeof(*p_new
) * i_list
);
104 /* Optimization for 1 NAL block only case */
105 if( i_nalcount
== 1 && block_WillRealloc( p_block
, p_list
[0].move
, p_block
->i_buffer
) )
107 uint32_t i_payload
= p_block
->i_buffer
- p_list
[0].prefix
;
108 block_t
*p_newblock
= block_Realloc( p_block
, p_list
[0].move
, p_block
->i_buffer
);
109 if( unlikely(!p_newblock
) )
111 p_block
= p_newblock
;
112 hxxx_WritePrefix( i_nal_length_size
, p_block
->p_buffer
, i_payload
);
117 block_t
*p_release
= NULL
;
118 const uint8_t *p_source
= NULL
;
119 const uint8_t *p_sourceend
= NULL
;
120 uint8_t *p_dest
= NULL
;
121 const size_t i_dest
= p_block
->i_buffer
+ p_list
[i_nalcount
- 1].move
;
123 if( p_list
[i_nalcount
- 1].move
!= 0 || i_nal_length_size
!= 4 ) /* We'll need to grow or shrink */
125 /* If we grow in size, try using realloc to avoid memcpy */
126 if( p_list
[i_nalcount
- 1].move
> 0 && block_WillRealloc( p_block
, 0, i_dest
) )
128 uint32_t i_sizebackup
= p_block
->i_buffer
;
129 block_t
*p_newblock
= block_Realloc( p_block
, 0, i_dest
);
130 if( unlikely(!p_newblock
) )
133 p_block
= p_newblock
;
134 p_sourceend
= &p_block
->p_buffer
[i_sizebackup
];
135 p_source
= p_dest
= p_block
->p_buffer
;
139 block_t
*p_newblock
= block_Alloc( i_dest
);
140 if( unlikely(!p_newblock
) )
143 p_release
= p_block
; /* Will be released after use */
144 p_source
= p_release
->p_buffer
;
145 p_sourceend
= &p_release
->p_buffer
[p_release
->i_buffer
];
147 p_block
= p_newblock
;
148 p_dest
= p_newblock
->p_buffer
;
153 p_source
= p_dest
= p_block
->p_buffer
;
154 p_sourceend
= &p_block
->p_buffer
[p_block
->i_buffer
];
160 /* Do reverse order moves, so we never overlap when growing only */
161 for( unsigned i
=i_nalcount
; i
!=0; i
-- )
163 const uint8_t *p_readstart
= p_list
[i
- 1].p
;
164 uint32_t i_payload
= p_sourceend
- p_readstart
- p_list
[i
- 1].prefix
;
165 off_t offset
= p_list
[i
- 1].p
- p_source
+ p_list
[i
- 1].prefix
+ p_list
[i
- 1].move
;
166 // printf(" move offset %ld, length = %ld prefix %ld move %ld\n", p_readstart - p_source, i_payload, p_list[i - 1].prefix, p_list[i-1].move);
168 /* move in same / copy between buffers */
169 memmove( &p_dest
[ offset
], &p_list
[i
- 1].p
[ p_list
[i
- 1].prefix
], i_payload
);
171 hxxx_WritePrefix( i_nal_length_size
, &p_dest
[ offset
- i_nal_length_size
] , i_payload
);
173 p_sourceend
= p_readstart
;
177 block_Release( p_release
);
183 block_Release( p_block
);