1+ use mp4parse:: unstable:: Indice ;
12use mp4parse_capi:: * ;
23use num_traits:: ToPrimitive ;
34use std:: io:: Read ;
@@ -11,19 +12,8 @@ extern "C" fn buf_read(buf: *mut u8, size: usize, userdata: *mut std::os::raw::c
1112 }
1213}
1314
14- unsafe fn parse_file_and_get_info ( path : & str ) -> ( * mut Mp4parseAvifParser , Mp4parseAvifInfo ) {
15- let mut file = std:: fs:: File :: open ( path) . expect ( "Unknown file" ) ;
16- let io = Mp4parseIo {
17- read : Some ( buf_read) ,
18- userdata : & mut file as * mut _ as * mut std:: os:: raw:: c_void ,
19- } ;
20-
21- let mut parser = std:: ptr:: null_mut ( ) ;
22- let mut rv = mp4parse_avif_new ( & io, ParseStrictness :: Normal , & mut parser) ;
23- assert_eq ! ( rv, Mp4parseStatus :: Ok ) ;
24- assert ! ( !parser. is_null( ) ) ;
25-
26- let mut info = Mp4parseAvifInfo {
15+ fn default_avif_info ( ) -> Mp4parseAvifInfo {
16+ Mp4parseAvifInfo {
2717 premultiplied_alpha : Default :: default ( ) ,
2818 major_brand : Default :: default ( ) ,
2919 unsupported_features_bitfield : Default :: default ( ) ,
@@ -44,12 +34,44 @@ unsafe fn parse_file_and_get_info(path: &str) -> (*mut Mp4parseAvifParser, Mp4pa
4434 color_track_bit_depth : Default :: default ( ) ,
4535 alpha_track_id : Default :: default ( ) ,
4636 alpha_track_bit_depth : Default :: default ( ) ,
37+ }
38+ }
39+
40+ fn default_avif_image ( ) -> Mp4parseAvifImage {
41+ Mp4parseAvifImage {
42+ primary_image : Default :: default ( ) ,
43+ alpha_image : Default :: default ( ) ,
44+ }
45+ }
46+
47+ unsafe fn parse_file ( path : & str ) -> * mut Mp4parseAvifParser {
48+ let mut file = std:: fs:: File :: open ( path) . expect ( "Unknown file" ) ;
49+ let io = Mp4parseIo {
50+ read : Some ( buf_read) ,
51+ userdata : & mut file as * mut _ as * mut std:: os:: raw:: c_void ,
4752 } ;
48- rv = mp4parse_avif_get_info ( parser, & mut info) ;
53+
54+ let mut parser = std:: ptr:: null_mut ( ) ;
55+ let rv = mp4parse_avif_new ( & io, ParseStrictness :: Normal , & mut parser) ;
56+ assert_eq ! ( rv, Mp4parseStatus :: Ok ) ;
57+ assert ! ( !parser. is_null( ) ) ;
58+
59+ parser
60+ }
61+
62+ unsafe fn parse_file_and_get_info ( path : & str ) -> ( * mut Mp4parseAvifParser , Mp4parseAvifInfo ) {
63+ let parser = parse_file ( path) ;
64+ let mut info = default_avif_info ( ) ;
65+ let rv = mp4parse_avif_get_info ( parser, & mut info) ;
4966 assert_eq ! ( rv, Mp4parseStatus :: Ok ) ;
5067 ( parser, info)
5168}
5269
70+ unsafe fn assert_slice_pointer_is_readable < T > ( ptr : * const T , len : usize ) {
71+ let slice = std:: slice:: from_raw_parts ( ptr, len) ;
72+ assert_eq ! ( slice. len( ) , len) ;
73+ }
74+
5375fn check_loop_count ( path : & str , expected_loop_count : i64 ) {
5476 let ( parser, info) = unsafe { parse_file_and_get_info ( path) } ;
5577 match info. loop_mode {
@@ -111,3 +133,143 @@ fn check_timescales() {
111133 check_timescale ( "tests/loop_forever.avif" , 2 ) ;
112134 check_timescale ( "tests/no_edts.avif" , 16384 ) ;
113135}
136+
137+ #[ test]
138+ fn repeated_get_info_returns_stable_pointers ( ) {
139+ let ( parser, info1) = unsafe { parse_file_and_get_info ( "tests/loop_1.avif" ) } ;
140+
141+ unsafe {
142+ let mut info2 = default_avif_info ( ) ;
143+ let rv = mp4parse_avif_get_info ( parser, & mut info2) ;
144+ assert_eq ! ( rv, Mp4parseStatus :: Ok ) ;
145+
146+ assert_eq ! ( info1. spatial_extents, info2. spatial_extents) ;
147+ assert ! ( !info1. spatial_extents. is_null( ) ) ;
148+ assert_slice_pointer_is_readable ( info1. spatial_extents , 1 ) ;
149+
150+ assert_eq ! ( info1. nclx_colour_information, info2. nclx_colour_information) ;
151+ if !info1. nclx_colour_information . is_null ( ) {
152+ assert_slice_pointer_is_readable ( info1. nclx_colour_information , 1 ) ;
153+ }
154+
155+ assert_eq ! (
156+ info1. icc_colour_information. length,
157+ info2. icc_colour_information. length
158+ ) ;
159+ assert_eq ! (
160+ info1. icc_colour_information. data,
161+ info2. icc_colour_information. data
162+ ) ;
163+ if info1. icc_colour_information . length == 0 {
164+ assert ! ( info1. icc_colour_information. data. is_null( ) ) ;
165+ } else {
166+ assert_slice_pointer_is_readable (
167+ info1. icc_colour_information . data ,
168+ info1. icc_colour_information . length ,
169+ ) ;
170+ }
171+
172+ assert_eq ! ( info1. image_mirror, info2. image_mirror) ;
173+ if !info1. image_mirror . is_null ( ) {
174+ assert_slice_pointer_is_readable ( info1. image_mirror , 1 ) ;
175+ }
176+
177+ assert_eq ! ( info1. pixel_aspect_ratio, info2. pixel_aspect_ratio) ;
178+ if !info1. pixel_aspect_ratio . is_null ( ) {
179+ assert_slice_pointer_is_readable ( info1. pixel_aspect_ratio , 1 ) ;
180+ }
181+
182+ mp4parse_avif_free ( parser) ;
183+ }
184+ }
185+
186+ #[ test]
187+ fn repeated_get_image_returns_stable_pointers ( ) {
188+ let parser = unsafe { parse_file ( "tests/loop_1.avif" ) } ;
189+
190+ unsafe {
191+ let mut image1 = default_avif_image ( ) ;
192+ let rv = mp4parse_avif_get_image ( parser, & mut image1) ;
193+ assert_eq ! ( rv, Mp4parseStatus :: Ok ) ;
194+ assert ! ( image1. primary_image. length > 0 ) ;
195+ assert ! ( !image1. primary_image. data. is_null( ) ) ;
196+ assert ! ( image1. alpha_image. length > 0 ) ;
197+ assert ! ( !image1. alpha_image. data. is_null( ) ) ;
198+
199+ let mut image2 = default_avif_image ( ) ;
200+ let rv = mp4parse_avif_get_image ( parser, & mut image2) ;
201+ assert_eq ! ( rv, Mp4parseStatus :: Ok ) ;
202+
203+ assert_eq ! ( image1. primary_image. length, image2. primary_image. length) ;
204+ assert_eq ! ( image1. primary_image. data, image2. primary_image. data) ;
205+ assert_eq ! ( image1. alpha_image. length, image2. alpha_image. length) ;
206+ assert_eq ! ( image1. alpha_image. data, image2. alpha_image. data) ;
207+
208+ assert_slice_pointer_is_readable ( image1. primary_image . data , image1. primary_image . length ) ;
209+ assert_slice_pointer_is_readable ( image1. alpha_image . data , image1. alpha_image . length ) ;
210+
211+ mp4parse_avif_free ( parser) ;
212+ }
213+ }
214+
215+ #[ test]
216+ fn repeated_get_indice_table_returns_stable_pointer ( ) {
217+ let ( parser, info) = unsafe { parse_file_and_get_info ( "tests/loop_1.avif" ) } ;
218+
219+ unsafe {
220+ let mut indices1 = Mp4parseByteData :: default ( ) ;
221+ let mut timescale1: u64 = 0 ;
222+ let rv = mp4parse_avif_get_indice_table (
223+ parser,
224+ info. color_track_id ,
225+ & mut indices1,
226+ & mut timescale1,
227+ ) ;
228+ assert_eq ! ( rv, Mp4parseStatus :: Ok ) ;
229+ assert ! ( indices1. length > 0 ) ;
230+ assert ! ( !indices1. indices. is_null( ) ) ;
231+
232+ let mut indices2 = Mp4parseByteData :: default ( ) ;
233+ let mut timescale2: u64 = 0 ;
234+ let rv = mp4parse_avif_get_indice_table (
235+ parser,
236+ info. color_track_id ,
237+ & mut indices2,
238+ & mut timescale2,
239+ ) ;
240+ assert_eq ! ( rv, Mp4parseStatus :: Ok ) ;
241+
242+ assert_eq ! ( timescale1, timescale2) ;
243+ assert_eq ! ( indices1. length, indices2. length) ;
244+ assert_eq ! ( indices1. indices, indices2. indices) ;
245+ assert_slice_pointer_is_readable ( indices1. indices , indices1. length ) ;
246+
247+ let first1: & [ Indice ] = std:: slice:: from_raw_parts ( indices1. indices , indices1. length ) ;
248+ let first2: & [ Indice ] = std:: slice:: from_raw_parts ( indices2. indices , indices2. length ) ;
249+ assert_eq ! ( first1[ 0 ] , first2[ 0 ] ) ;
250+
251+ mp4parse_avif_free ( parser) ;
252+ }
253+ }
254+
255+ #[ test]
256+ fn empty_avif_byte_slices_use_null_pointers ( ) {
257+ let ( parser, info) = unsafe { parse_file_and_get_info ( "tests/no_edts.avif" ) } ;
258+
259+ unsafe {
260+ let mut image = default_avif_image ( ) ;
261+ let rv = mp4parse_avif_get_image ( parser, & mut image) ;
262+ assert_eq ! ( rv, Mp4parseStatus :: Ok ) ;
263+
264+ assert ! ( image. primary_image. length > 0 ) ;
265+ assert ! ( !image. primary_image. data. is_null( ) ) ;
266+ assert_eq ! ( image. alpha_image. length, 0 ) ;
267+ assert ! ( image. alpha_image. data. is_null( ) ) ;
268+
269+ if info. icc_colour_information . length == 0 {
270+ assert ! ( info. icc_colour_information. data. is_null( ) ) ;
271+ }
272+
273+ mp4parse_avif_free ( parser) ;
274+ }
275+ }
0 commit comments