@@ -855,6 +855,13 @@ impl Mp4FileMuxer {
855855 ( max_w. max ( w) , max_h. max ( h) )
856856 } ) ;
857857
858+ let width = i16:: try_from ( max_width) . map_err ( |_| {
859+ MuxError :: EncodeError ( Error :: invalid_data ( "video width exceeds i16::MAX" ) )
860+ } ) ?;
861+ let height = i16:: try_from ( max_height) . map_err ( |_| {
862+ MuxError :: EncodeError ( Error :: invalid_data ( "video height exceeds i16::MAX" ) )
863+ } ) ?;
864+
858865 let creation_time = Mp4FileTime :: from_unix_time ( self . options . creation_timestamp ) ;
859866 let tkhd_box = TkhdBox {
860867 flag_track_enabled : true ,
@@ -869,8 +876,8 @@ impl Mp4FileMuxer {
869876 alternate_group : TkhdBox :: DEFAULT_ALTERNATE_GROUP ,
870877 volume : TkhdBox :: DEFAULT_VIDEO_VOLUME ,
871878 matrix : TkhdBox :: DEFAULT_MATRIX ,
872- width : FixedPointNumber :: new ( max_width as i16 , 0 ) ,
873- height : FixedPointNumber :: new ( max_height as i16 , 0 ) ,
879+ width : FixedPointNumber :: new ( width , 0 ) ,
880+ height : FixedPointNumber :: new ( height , 0 ) ,
874881 } ;
875882
876883 Ok ( TrakBox {
@@ -1412,6 +1419,89 @@ mod tests {
14121419 muxer. finalize ( ) . expect ( "failed to finalize muxer" ) ;
14131420 }
14141421
1422+ /// `muxer` に解像度 `width` x `height` の AVC1 サンプルを 1 つ追加して `finalize()` を呼ぶ
1423+ fn finalize_after_appending_video_sample (
1424+ muxer : & mut Mp4FileMuxer ,
1425+ width : u16 ,
1426+ height : u16 ,
1427+ ) -> Result < ( ) , MuxError > {
1428+ let initial_size = muxer. initial_boxes_bytes ( ) . len ( ) as u64 ;
1429+ let mut entry = create_avc1_sample_entry ( ) ;
1430+ let SampleEntry :: Avc1 ( avc1) = & mut entry else {
1431+ panic ! ( "create_avc1_sample_entry must return SampleEntry::Avc1" ) ;
1432+ } ;
1433+ avc1. visual . width = width;
1434+ avc1. visual . height = height;
1435+
1436+ let sample = Sample {
1437+ track_kind : TrackKind :: Video ,
1438+ sample_entry : Some ( entry) ,
1439+ keyframe : true ,
1440+ timescale : NonZeroU32 :: MIN . saturating_add ( 30 - 1 ) ,
1441+ duration : 1 ,
1442+ composition_time_offset : None ,
1443+ data_offset : initial_size,
1444+ data_size : 1024 ,
1445+ } ;
1446+ muxer
1447+ . append_sample ( & sample)
1448+ . expect ( "failed to append sample" ) ;
1449+ muxer. finalize ( ) . map ( |_| ( ) )
1450+ }
1451+
1452+ /// 映像解像度の幅と高さが i16::MAX (32767) の境界値で finalize が成功するテスト
1453+ #[ test]
1454+ fn test_finalize_video_resolution_i16_max_succeeds ( ) {
1455+ let mut muxer = Mp4FileMuxer :: new ( ) . expect ( "failed to create muxer" ) ;
1456+ finalize_after_appending_video_sample ( & mut muxer, i16:: MAX as u16 , i16:: MAX as u16 )
1457+ . expect ( "failed to finalize at i16::MAX resolution" ) ;
1458+ }
1459+
1460+ /// faststart 有効化 (with_options) 経路でも i16::MAX 境界値で finalize が成功するテスト
1461+ #[ test]
1462+ fn test_finalize_video_resolution_i16_max_with_faststart ( ) {
1463+ let options = Mp4FileMuxerOptions {
1464+ reserved_moov_box_size : 8192 ,
1465+ ..Default :: default ( )
1466+ } ;
1467+ let mut muxer =
1468+ Mp4FileMuxer :: with_options ( options) . expect ( "failed to create muxer with options" ) ;
1469+ finalize_after_appending_video_sample ( & mut muxer, i16:: MAX as u16 , i16:: MAX as u16 )
1470+ . expect ( "failed to finalize at i16::MAX resolution under faststart" ) ;
1471+ }
1472+
1473+ /// 映像幅が i16::MAX を超える場合に width 側のエラーメッセージが返ることを検証するテスト
1474+ #[ test]
1475+ fn test_finalize_video_width_exceeds_i16_max ( ) {
1476+ // i16::MAX を超える最小値の u16 (= 32768) を渡す
1477+ let mut muxer = Mp4FileMuxer :: new ( ) . expect ( "failed to create muxer" ) ;
1478+ let err = finalize_after_appending_video_sample ( & mut muxer, 32_768 , 1 )
1479+ . expect_err ( "expected encode error for width exceeding i16::MAX" ) ;
1480+ assert ! ( matches!( err, MuxError :: EncodeError ( _) ) ) ;
1481+ // MuxError::EncodeError は他原因でも返るためメッセージ内容まで確認する
1482+ let message = format ! ( "{err}" ) ;
1483+ assert ! (
1484+ message. contains( "video width exceeds i16::MAX" ) ,
1485+ "unexpected error message: {message}" ,
1486+ ) ;
1487+ }
1488+
1489+ /// 映像高さが i16::MAX を超える場合に height 側のエラーメッセージが返ることを検証するテスト
1490+ #[ test]
1491+ fn test_finalize_video_height_exceeds_i16_max ( ) {
1492+ // i16::MAX を超える最小値の u16 (= 32768) を渡す
1493+ let mut muxer = Mp4FileMuxer :: new ( ) . expect ( "failed to create muxer" ) ;
1494+ let err = finalize_after_appending_video_sample ( & mut muxer, 1 , 32_768 )
1495+ . expect_err ( "expected encode error for height exceeding i16::MAX" ) ;
1496+ assert ! ( matches!( err, MuxError :: EncodeError ( _) ) ) ;
1497+ // MuxError::EncodeError は他原因でも返るためメッセージ内容まで確認する
1498+ let message = format ! ( "{err}" ) ;
1499+ assert ! (
1500+ message. contains( "video height exceeds i16::MAX" ) ,
1501+ "unexpected error message: {message}" ,
1502+ ) ;
1503+ }
1504+
14151505 /// 音声と映像の複数トラックのテスト
14161506 #[ test]
14171507 fn test_audio_and_video_tracks ( ) {
0 commit comments