@@ -893,58 +893,122 @@ AVS_VideoFrame* AVSC_CC assrender_get_frame(AVS_FilterInfo* p, int n)
893893 udata * ud = (udata * )p -> user_data ;
894894 ASS_Image * img ;
895895 AVS_VideoFrame * src ;
896-
896+ AVS_VideoFrame * dst ;
897897 int64_t ts ;
898898 int changed ;
899899
900+ // 1) Get upstream frame
900901 src = avs_get_frame (p -> child , n );
901902
902- avs_make_writable (p -> env , & src );
903+ // 2) Allocate a new writable destination frame
904+ dst = avs_new_video_frame_a (p -> env , & p -> vi , AVS_FRAME_ALIGN );
905+ if (!dst ) {
906+ avs_release_video_frame (src );
907+ return 0 ;
908+ }
909+
910+ // 3) Copy src -> dst (real pixel copy), then free src
911+
912+ if (avs_is_planar (& p -> vi )) {
913+ if (avs_is_rgb (& p -> vi )) {
914+ // Planar RGB: R, G, B planes
915+ const int planes [3 ] = { AVS_PLANAR_R , AVS_PLANAR_G , AVS_PLANAR_B };
916+ for (int i = 0 ; i < 3 ; ++ i ) {
917+ const uint8_t * srcp = avs_get_read_ptr_p (src , planes [i ]);
918+ int src_pitch = avs_get_pitch_p (src , planes [i ]);
919+ uint8_t * dstp = avs_get_write_ptr_p (dst , planes [i ]);
920+ int dst_pitch = avs_get_pitch_p (dst , planes [i ]);
921+ int row_size = avs_get_row_size_p (src , planes [i ]);
922+ int height = avs_get_height_p (src , planes [i ]);
923+ avs_bit_blt (p -> env , dstp , dst_pitch , srcp , src_pitch , row_size , height );
924+ }
925+ }
926+ else {
927+ // Planar YUV: Y, U, V planes
928+ const int planes [3 ] = { AVS_PLANAR_Y , AVS_PLANAR_U , AVS_PLANAR_V };
929+ for (int i = 0 ; i < 3 ; ++ i ) {
930+ const uint8_t * srcp = avs_get_read_ptr_p (src , planes [i ]);
931+ int src_pitch = avs_get_pitch_p (src , planes [i ]);
932+ uint8_t * dstp = avs_get_write_ptr_p (dst , planes [i ]);
933+ int dst_pitch = avs_get_pitch_p (dst , planes [i ]);
934+ int row_size = avs_get_row_size_p (src , planes [i ]);
935+ int height = avs_get_height_p (src , planes [i ]);
936+ avs_bit_blt (p -> env , dstp , dst_pitch , srcp , src_pitch , row_size , height );
937+ }
938+ }
939+ }
940+ else {
941+ // Packed formats (e.g. RGB32, YUY2, etc.)
942+ const uint8_t * srcp = avs_get_read_ptr_p (src , AVS_DEFAULT_PLANE );
943+ int src_pitch = avs_get_pitch_p (src , AVS_DEFAULT_PLANE );
944+ uint8_t * dstp = avs_get_write_ptr_p (dst , AVS_DEFAULT_PLANE );
945+ int dst_pitch = avs_get_pitch_p (dst , AVS_DEFAULT_PLANE );
946+ int row_size = avs_get_row_size_p (src , AVS_DEFAULT_PLANE );
947+ int height = avs_get_height_p (src , AVS_DEFAULT_PLANE );
948+ avs_bit_blt (p -> env , dstp , dst_pitch , srcp , src_pitch , row_size , height );
949+ }
903950
951+ // Original frame no longer needed locally
952+ avs_release_video_frame (src );
953+
954+ // 4) Compute timestamp for libass
904955 if (!ud -> isvfr ) {
905- // it’ s a casting party!
956+ // it' s a casting party!
906957 ts = (int64_t )n * (int64_t )1000 * (int64_t )p -> vi .fps_denominator / (int64_t )p -> vi .fps_numerator ;
907- } else {
958+ }
959+ else {
908960 ts = ud -> timestamp [n ];
909961 }
910962
963+ // 5) Render ASS
911964 img = ass_render_frame (ud -> ass_renderer , ud -> ass , ts , & changed );
912965
913966 if (img ) {
914- uint32_t height , width , pitch [2 ];
967+ uint32_t width = p -> vi .width ;
968+ uint32_t height = p -> vi .height ;
915969 uint8_t * data [3 ];
970+ uint32_t pitch [2 ];
916971
972+ // 6) Build write pointers for the copied frame (dst)
917973 if (avs_is_planar (& p -> vi ) && !ud -> greyscale ) {
918- if (avs_is_rgb (& p -> vi )) {
919- // planar RGB as 444
920- data [0 ] = avs_get_write_ptr_p (src , AVS_PLANAR_R );
921- data [1 ] = avs_get_write_ptr_p (src , AVS_PLANAR_G );
922- data [2 ] = avs_get_write_ptr_p (src , AVS_PLANAR_B );
923- pitch [0 ] = avs_get_pitch_p (src , AVS_DEFAULT_PLANE );
924- }
925- else {
926- data [0 ] = avs_get_write_ptr_p (src , AVS_PLANAR_Y );
927- data [1 ] = avs_get_write_ptr_p (src , AVS_PLANAR_U );
928- data [2 ] = avs_get_write_ptr_p (src , AVS_PLANAR_V );
929- pitch [0 ] = avs_get_pitch_p (src , AVS_PLANAR_Y );
930- pitch [1 ] = avs_get_pitch_p (src , AVS_PLANAR_U );
931- }
974+ if (avs_is_rgb (& p -> vi )) {
975+ // planar RGB as 4:4:4
976+ data [0 ] = avs_get_write_ptr_p (dst , AVS_PLANAR_R );
977+ data [1 ] = avs_get_write_ptr_p (dst , AVS_PLANAR_G );
978+ data [2 ] = avs_get_write_ptr_p (dst , AVS_PLANAR_B );
979+ pitch [0 ] = avs_get_pitch_p (dst , AVS_DEFAULT_PLANE );
980+ }
981+ else {
982+ data [0 ] = avs_get_write_ptr_p (dst , AVS_PLANAR_Y );
983+ data [1 ] = avs_get_write_ptr_p (dst , AVS_PLANAR_U );
984+ data [2 ] = avs_get_write_ptr_p (dst , AVS_PLANAR_V );
985+ pitch [0 ] = avs_get_pitch_p (dst , AVS_PLANAR_Y );
986+ pitch [1 ] = avs_get_pitch_p (dst , AVS_PLANAR_U );
987+ }
932988 }
933989 else {
934- data [0 ] = avs_get_write_ptr_p (src , AVS_DEFAULT_PLANE );
935- pitch [0 ] = avs_get_pitch_p (src , AVS_DEFAULT_PLANE );
990+ data [0 ] = avs_get_write_ptr_p (dst , AVS_DEFAULT_PLANE );
991+ pitch [0 ] = avs_get_pitch_p (dst , AVS_DEFAULT_PLANE );
936992 }
937993
938- height = p -> vi .height ;
939- width = p -> vi .width ;
940-
994+ // 7) Rebuild cached subtitle bitmap if changed
941995 if (changed ) {
942- memset (ud -> sub_img [0 ], 0x00 , height * width * ud -> pixelsize );
943- ud -> f_make_sub_img (img , ud -> sub_img , width , ud -> bits_per_pixel , ud -> rgb_fullscale , & ud -> mx );
996+ memset (ud -> sub_img [0 ], 0 , height * width * ud -> pixelsize );
997+ ud -> f_make_sub_img (
998+ img ,
999+ ud -> sub_img ,
1000+ width ,
1001+ ud -> bits_per_pixel ,
1002+ ud -> rgb_fullscale ,
1003+ & ud -> mx
1004+ );
9441005 }
9451006
1007+ // 8) Blend ASS into the copied frame
9461008 ud -> apply (ud -> sub_img , data , pitch , width , height );
9471009 }
9481010
949- return src ;
1011+ // 9) Return the modified copy
1012+ return dst ;
9501013}
1014+
0 commit comments