33#![ allow( clippy:: match_like_matches_macro) ]
44#![ allow( clippy:: needless_range_loop) ]
55#![ allow( clippy:: needless_late_init) ]
6+ #![ allow( non_snake_case) ]
67
78#[ macro_use]
89extern crate num_derive;
@@ -12,56 +13,122 @@ pub mod h264;
1213pub mod y4m_cmp;
1314
1415use std:: env;
16+ use std:: fmt:: Error ;
1517use std:: fs;
1618use std:: io;
1719
1820use log:: info;
1921use v_frame:: plane:: PlaneOffset ;
20- use y4m_cmp:: { compare_files , compare_frames } ;
22+ use y4m_cmp:: compare_y4m_buffers ;
2123
2224fn main ( ) {
2325 diag:: init ( false ) ;
2426 let args: Vec < String > = env:: args ( ) . collect ( ) ;
25- let mut input_filename = "data/NL1_Sony_D.jsv" . to_string ( ) ;
27+ let input_filename: String ;
2628 if args. len ( ) > 1 {
2729 input_filename = args[ 1 ] . clone ( ) ;
30+ } else {
31+ print ! ( "No input file" ) ;
32+ return ;
2833 }
2934
30- let buf = fs:: read ( input_filename) . unwrap ( ) ;
35+ let encoded_video_buffer =
36+ fs:: read ( & input_filename) . expect ( format ! ( "can't read file: {input_filename}" ) . as_str ( ) ) ;
3137 let mut decoder = h264:: decoder:: Decoder :: new ( ) ;
32- decoder. decode ( & buf ) . expect ( "parsing error" ) ;
38+ decoder. decode ( & encoded_video_buffer ) . expect ( "Decoding error" ) ;
3339
3440 let first_frame = decoder. get_frame_buffer ( ) . first ( ) . unwrap ( ) ;
3541 let y_plane = & first_frame. planes [ 0 ] ;
3642 let w = y_plane. cfg . width as u32 ;
3743 let h = y_plane. cfg . height as u32 ;
3844
39- let mut writer = io:: BufWriter :: new ( fs:: File :: create ( "output.y4m" ) . unwrap ( ) ) ;
40- let mut encoder = y4m:: encode ( w as usize , h as usize , y4m:: Ratio { num : 15 , den : 1 } )
41- . with_colorspace ( y4m:: Colorspace :: C420 )
42- . write_header ( & mut writer)
43- . unwrap ( ) ;
44-
45- for ( num, frame) in decoder. get_frame_buffer ( ) . iter ( ) . enumerate ( ) {
46- info ! ( "Writing frame #{num} {w} x {h} to y4m" ) ;
47-
48- let mut planes = Vec :: < Vec < u8 > > :: new ( ) ;
49- for plane in & frame. planes {
50- let data_size = plane. cfg . width * plane. cfg . height ;
51- let mut data = vec ! [ 0 ; data_size] ;
52- plane. copy_to_raw_u8 ( & mut data, plane. cfg . width , 1 ) ;
53- planes. push ( data)
45+ let mut decoding_output = Vec :: < u8 > :: new ( ) ;
46+ {
47+ let mut writer = io:: BufWriter :: new ( & mut decoding_output) ;
48+ let mut encoder = y4m:: encode ( w as usize , h as usize , y4m:: Ratio { num : 15 , den : 1 } )
49+ . with_colorspace ( y4m:: Colorspace :: C420 )
50+ . write_header ( & mut writer)
51+ . unwrap ( ) ;
52+
53+ for ( num, frame) in decoder. get_frame_buffer ( ) . iter ( ) . enumerate ( ) {
54+ info ! ( "Writing frame #{num} {w} x {h} to y4m" ) ;
55+
56+ let mut planes = Vec :: < Vec < u8 > > :: new ( ) ;
57+ for plane in & frame. planes {
58+ let data_size = plane. cfg . width * plane. cfg . height ;
59+ let mut data = vec ! [ 0 ; data_size] ;
60+ plane. copy_to_raw_u8 ( & mut data, plane. cfg . width , 1 ) ;
61+ planes. push ( data)
62+ }
63+
64+ let yuv_frame = y4m:: Frame :: new (
65+ [ planes[ 0 ] . as_slice ( ) , planes[ 1 ] . as_slice ( ) , planes[ 2 ] . as_slice ( ) ] ,
66+ None ,
67+ ) ;
68+ encoder. write_frame ( & yuv_frame) . unwrap ( ) ;
69+ }
70+ }
71+ fs:: write ( "output.y4m" , decoding_output. as_slice ( ) ) . expect ( "can't save decoding result" ) ;
72+ }
73+
74+ #[ cfg( test) ]
75+ mod tests {
76+ pub use super :: * ;
77+
78+ fn test_decoding_against_gold (
79+ encoded_file_name : & str ,
80+ gold_y4m_filename : & str ,
81+ ) -> Result < ( ) , String > {
82+ fn stringify ( e : io:: Error ) -> String {
83+ format ! ( "IO error: {e}" )
5484 }
85+ let expected_y4m_buffer = fs:: read ( gold_y4m_filename) . map_err ( stringify) ?;
86+ let encoded_video_buffer = fs:: read ( encoded_file_name) . map_err ( stringify) ?;
87+ let mut decoder = h264:: decoder:: Decoder :: new ( ) ;
88+ decoder
89+ . decode ( & encoded_video_buffer)
90+ . map_err ( |e| -> String { format ! ( "Decoding error: {e:?}" ) } ) ?;
91+
92+ let first_frame = decoder. get_frame_buffer ( ) . first ( ) . unwrap ( ) ;
93+ let y_plane = & first_frame. planes [ 0 ] ;
94+ let w = y_plane. cfg . width as u32 ;
95+ let h = y_plane. cfg . height as u32 ;
96+
97+ let mut decoding_output = Vec :: < u8 > :: new ( ) ;
98+ {
99+ let mut writer = io:: BufWriter :: new ( & mut decoding_output) ;
100+ let mut encoder = y4m:: encode ( w as usize , h as usize , y4m:: Ratio { num : 15 , den : 1 } )
101+ . with_colorspace ( y4m:: Colorspace :: C420 )
102+ . write_header ( & mut writer)
103+ . unwrap ( ) ;
104+
105+ for ( num, frame) in decoder. get_frame_buffer ( ) . iter ( ) . enumerate ( ) {
106+ let mut planes = Vec :: < Vec < u8 > > :: new ( ) ;
107+ for plane in & frame. planes {
108+ let data_size = plane. cfg . width * plane. cfg . height ;
109+ let mut data = vec ! [ 0 ; data_size] ;
110+ plane. copy_to_raw_u8 ( & mut data, plane. cfg . width , 1 ) ;
111+ planes. push ( data)
112+ }
113+
114+ let yuv_frame = y4m:: Frame :: new (
115+ [ planes[ 0 ] . as_slice ( ) , planes[ 1 ] . as_slice ( ) , planes[ 2 ] . as_slice ( ) ] ,
116+ None ,
117+ ) ;
118+ encoder. write_frame ( & yuv_frame) . unwrap ( ) ;
119+ }
120+ }
121+
122+ compare_y4m_buffers ( decoding_output. as_slice ( ) , expected_y4m_buffer. as_slice ( ) )
123+ }
55124
56- let yuv_frame = y4m:: Frame :: new (
57- [ planes[ 0 ] . as_slice ( ) , planes[ 1 ] . as_slice ( ) , planes[ 2 ] . as_slice ( ) ] ,
58- None ,
59- ) ;
60- encoder. write_frame ( & yuv_frame) . unwrap ( ) ;
125+ #[ test]
126+ pub fn test_NL1_Sony_D ( ) -> Result < ( ) , String > {
127+ test_decoding_against_gold ( "data/NL1_Sony_D.jsv" , "data/NL1_Sony_D.y4m" )
61128 }
62- drop ( encoder) ;
63129
64- if let Err ( message) = compare_files ( "output.y4m" , "data/NL1_Sony_D.y4m" ) {
65- print ! ( "File comparison result: {message}" ) ;
130+ #[ test]
131+ pub fn test_SVA_NL1_B ( ) -> Result < ( ) , String > {
132+ test_decoding_against_gold ( "data/SVA_NL1_B.264" , "data/SVA_NL1_B.y4m" )
66133 }
67134}
0 commit comments