4040import static com .nextbreakpoint .ffmpeg4java .linux .Libffmpeg_1 .av_write_trailer ;
4141import static com .nextbreakpoint .ffmpeg4java .linux .Libffmpeg_1 .avcodec_find_decoder ;
4242import static com .nextbreakpoint .ffmpeg4java .linux .Libffmpeg_1 .avcodec_find_encoder ;
43+ import static com .nextbreakpoint .ffmpeg4java .linux .Libffmpeg_1 .avcodec_parameters_alloc ;
4344import static com .nextbreakpoint .ffmpeg4java .linux .Libffmpeg_1 .avformat_alloc_context ;
4445import static com .nextbreakpoint .ffmpeg4java .linux .Libffmpeg_1 .avformat_close_input ;
4546import static com .nextbreakpoint .ffmpeg4java .linux .Libffmpeg_1 .avformat_find_stream_info ;
@@ -112,10 +113,10 @@ private static int loadVideo(String fileName, BiConsumer<Integer, byte[]> consum
112113 try (var arena = Arena .ofConfined ()) {
113114 var ppInputFormatCtx = NULL ;
114115 var pInputCodecCtx = NULL ;
115- var pInputRGBFrame = NULL ;
116- var pInputYUVFrame = NULL ;
117116 var pInputSwsContext = NULL ;
117+ var pInputRGBFrame = NULL ;
118118 var pInputRGBBuffer = NULL ;
119+ var pInputTMPFrame = NULL ;
119120 var pInputPacket = NULL ;
120121
121122 try {
@@ -127,16 +128,16 @@ private static int loadVideo(String fileName, BiConsumer<Integer, byte[]> consum
127128 throw new RuntimeException (formatLoadVideoError (fileName , "Can't open file" ));
128129 }
129130
130- final var pFormatCtx = ppInputFormatCtx .get (C_POINTER , 0 );
131+ final var pInputFormatCtx = ppInputFormatCtx .get (C_POINTER , 0 );
131132
132- if (avformat_find_stream_info (pFormatCtx , NULL ) != 0 ) {
133+ if (avformat_find_stream_info (pInputFormatCtx , NULL ) != 0 ) {
133134 throw new RuntimeException (formatLoadVideoError (fileName , "Can't find stream info" ));
134135 }
135136
136- av_dump_format (pFormatCtx , 0 , pInputFileName , 0 );
137+ av_dump_format (pInputFormatCtx , 0 , pInputFileName , 0 );
137138
138- final int nbStreams = AVFormatContext .nb_streams (pFormatCtx );
139- final var pInputStreams = AVFormatContext .streams (pFormatCtx );
139+ final int nbStreams = AVFormatContext .nb_streams (pInputFormatCtx );
140+ final var pInputStreams = AVFormatContext .streams (pInputFormatCtx );
140141
141142 var pInputCodecParameters = NULL ;
142143 int videoStreamIndex = -1 ;
@@ -162,7 +163,7 @@ private static int loadVideo(String fileName, BiConsumer<Integer, byte[]> consum
162163 }
163164
164165 if (pInputCodec .equals (NULL )) {
165- throw new RuntimeException (formatLoadVideoError (fileName , "Can't find codec " ));
166+ throw new RuntimeException (formatLoadVideoError (fileName , "Can't find decoder " ));
166167 }
167168
168169 pInputCodecCtx = avcodec_alloc_context3 (pInputCodec );
@@ -176,7 +177,7 @@ private static int loadVideo(String fileName, BiConsumer<Integer, byte[]> consum
176177 }
177178
178179 if (avcodec_open2 (pInputCodecCtx , pInputCodec , NULL ) < 0 ) {
179- throw new RuntimeException (formatLoadVideoError (fileName , "Can't open codec " ));
180+ throw new RuntimeException (formatLoadVideoError (fileName , "Can't open decoder " ));
180181 }
181182
182183 final int frameWidth = AVCodecContext .width (pInputCodecCtx );
@@ -190,14 +191,14 @@ private static int loadVideo(String fileName, BiConsumer<Integer, byte[]> consum
190191 }
191192
192193 pInputRGBFrame = av_frame_alloc ();
193- pInputYUVFrame = av_frame_alloc ();
194+ pInputTMPFrame = av_frame_alloc ();
194195
195196 if (pInputRGBFrame .equals (NULL )) {
196197 throw new RuntimeException (formatLoadVideoError (fileName , "Can't allocate RGB frame" ));
197198 }
198199
199- if (pInputYUVFrame .equals (NULL )) {
200- throw new RuntimeException (formatLoadVideoError (fileName , "Can't allocate YUV frame" ));
200+ if (pInputTMPFrame .equals (NULL )) {
201+ throw new RuntimeException (formatLoadVideoError (fileName , "Can't allocate TMP frame" ));
201202 }
202203
203204 final int rgbByteSize = av_image_get_buffer_size (AV_PIX_FMT_RGB24 (), frameWidth , frameHeight , 1 );
@@ -222,11 +223,11 @@ private static int loadVideo(String fileName, BiConsumer<Integer, byte[]> consum
222223
223224 final byte [] buffer = new byte [rgbByteSize ];
224225
225- while (av_read_frame (pFormatCtx , pInputPacket ) == 0 ) {
226+ while (av_read_frame (pInputFormatCtx , pInputPacket ) == 0 ) {
226227 if (AVPacket .stream_index (pInputPacket ) == videoStreamIndex ) {
227228 if (avcodec_send_packet (pInputCodecCtx , pInputPacket ) == 0 ) {
228- while (avcodec_receive_frame (pInputCodecCtx , pInputYUVFrame ) == 0 ) {
229- sws_scale (pInputSwsContext , AVFrame .data (pInputYUVFrame ), AVFrame .linesize (pInputYUVFrame ), 0 , frameHeight , AVFrame .data (pInputRGBFrame ), AVFrame .linesize (pInputRGBFrame ));
229+ while (avcodec_receive_frame (pInputCodecCtx , pInputTMPFrame ) == 0 ) {
230+ sws_scale (pInputSwsContext , AVFrame .data (pInputTMPFrame ), AVFrame .linesize (pInputTMPFrame ), 0 , frameHeight , AVFrame .data (pInputRGBFrame ), AVFrame .linesize (pInputRGBFrame ));
230231
231232 final var pInputData = AVFrame .data (pInputRGBFrame );
232233 MemorySegment .copy (pInputData .get (C_POINTER , 0 ), 0 , MemorySegment .ofArray (buffer ), 0 , rgbByteSize );
@@ -238,16 +239,20 @@ private static int loadVideo(String fileName, BiConsumer<Integer, byte[]> consum
238239 }
239240
240241 if (avcodec_send_packet (pInputCodecCtx , NULL ) == 0 ) {
241- while (avcodec_receive_frame (pInputCodecCtx , pInputYUVFrame ) == 0 ) {
242- sws_scale (pInputSwsContext , AVFrame .data (pInputYUVFrame ), AVFrame .linesize (pInputYUVFrame ), 0 , frameHeight , AVFrame .data (pInputRGBFrame ), AVFrame .linesize (pInputRGBFrame ));
242+ while (avcodec_receive_frame (pInputCodecCtx , pInputTMPFrame ) == 0 ) {
243+ sws_scale (pInputSwsContext , AVFrame .data (pInputTMPFrame ), AVFrame .linesize (pInputTMPFrame ), 0 , frameHeight , AVFrame .data (pInputRGBFrame ), AVFrame .linesize (pInputRGBFrame ));
243244
244245 final var pInputData = AVFrame .data (pInputRGBFrame );
245246 MemorySegment .copy (pInputData .get (C_POINTER , 0 ), 0 , MemorySegment .ofArray (buffer ), 0 , rgbByteSize );
246247
247248 consumer .accept (++frameCount , buffer );
248249 }
249250 }
250- } catch (Exception e ) {
251+ } finally {
252+ if (!pInputPacket .equals (NULL )) {
253+ av_packet_unref (pInputPacket );
254+ }
255+
251256 if (!pInputCodecCtx .equals (NULL )) {
252257 avcodec_close (pInputCodecCtx );
253258 }
@@ -256,12 +261,8 @@ private static int loadVideo(String fileName, BiConsumer<Integer, byte[]> consum
256261 sws_freeContext (pInputSwsContext );
257262 }
258263
259- if (!pInputPacket .equals (NULL )) {
260- av_packet_unref (pInputPacket );
261- }
262-
263- if (!pInputYUVFrame .equals (NULL )) {
264- av_free (pInputYUVFrame );
264+ if (!pInputTMPFrame .equals (NULL )) {
265+ av_free (pInputTMPFrame );
265266 }
266267
267268 if (!pInputRGBFrame .equals (NULL )) {
@@ -280,16 +281,14 @@ private static int saveVideo(String fileName, int fps, int frames, int frameWidt
280281 int frameCount = 0 ;
281282
282283 try (var arena = Arena .ofConfined ()) {
283- var ppOutputAVIOCtx = NULL ;
284284 var pOutputFormatCtx = NULL ;
285- var pOutputFormat = NULL ;
286285 var pOutputCodecCtx = NULL ;
286+ var pOutputAVIOCtx = NULL ;
287+ var pOutputSwsContext = NULL ;
287288 var pOutputRGBFrame = NULL ;
288289 var pOutputYUVFrame = NULL ;
289- var pOutputSwsContext = NULL ;
290290 var pOutputRGBBuffer = NULL ;
291291 var pOutputYUVBuffer = NULL ;
292- var pOutputProperties = NULL ;
293292
294293 try {
295294 pOutputFormatCtx = avformat_alloc_context ();
@@ -300,22 +299,24 @@ private static int saveVideo(String fileName, int fps, int frames, int frameWidt
300299
301300 final var pOutputFileName = arena .allocateFrom (fileName );
302301
303- pOutputFormat = av_guess_format (NULL , pOutputFileName , NULL );
302+ final var pOutputFormat = av_guess_format (NULL , pOutputFileName , NULL );
304303
305304 if (pOutputFormat .equals (NULL )) {
306305 throw new RuntimeException (formatSaveVideoError (fileName , "Can't allocate output format" ));
307306 }
308307
309- if (AVOutputFormat .video_codec (pOutputFormat ) == AV_CODEC_ID_NONE ()) {
310- throw new RuntimeException (formatSaveVideoError (fileName , "Can't find codec" ));
308+ final int outputVideoCodec = AVOutputFormat .video_codec (pOutputFormat );
309+
310+ if (outputVideoCodec == AV_CODEC_ID_NONE ()) {
311+ throw new RuntimeException (formatSaveVideoError (fileName , "Video codec not found" ));
311312 }
312313
313314 AVFormatContext .oformat (pOutputFormatCtx , pOutputFormat );
314315
315- final var pOutputCodec = avcodec_find_encoder (AVOutputFormat . video_codec ( pOutputFormat ) );
316+ final var pOutputCodec = avcodec_find_encoder (outputVideoCodec );
316317
317318 if (pOutputCodec .equals (NULL )) {
318- throw new RuntimeException (formatSaveVideoError (fileName , "Can't find codec " ));
319+ throw new RuntimeException (formatSaveVideoError (fileName , "Can't find encoder " ));
319320 }
320321
321322 pOutputCodecCtx = avcodec_alloc_context3 (pOutputCodec );
@@ -328,7 +329,7 @@ private static int saveVideo(String fileName, int fps, int frames, int frameWidt
328329 AVRational .num (pTimeBase , 1 );
329330 AVRational .den (pTimeBase , fps );
330331
331- AVCodecContext .codec_id (pOutputCodecCtx , AVOutputFormat . video_codec ( pOutputFormat ) );
332+ AVCodecContext .codec_id (pOutputCodecCtx , outputVideoCodec );
332333 AVCodecContext .codec_type (pOutputCodecCtx , AVMEDIA_TYPE_VIDEO ());
333334 AVCodecContext .width (pOutputCodecCtx , frameWidth );
334335 AVCodecContext .height (pOutputCodecCtx , frameHeight );
@@ -348,7 +349,7 @@ private static int saveVideo(String fileName, int fps, int frames, int frameWidt
348349 throw new RuntimeException (formatSaveVideoError (fileName , "Unexpected number of streams" ));
349350 }
350351
351- final var pOutputCodecParameters = arena . allocate ( AVCodecParameters . layout () );
352+ final var pOutputCodecParameters = avcodec_parameters_alloc ( );
352353
353354 if (pOutputCodecParameters .equals (NULL )) {
354355 throw new RuntimeException (formatSaveVideoError (fileName , "Can't allocate codec parameters" ));
@@ -358,27 +359,27 @@ private static int saveVideo(String fileName, int fps, int frames, int frameWidt
358359 throw new RuntimeException (formatLoadVideoError (fileName , "Can't copy codec parameters" ));
359360 }
360361
361- AVCodecParameters .codec_id (pOutputCodecParameters , AVOutputFormat . video_codec ( pOutputFormat ) );
362+ AVCodecParameters .codec_id (pOutputCodecParameters , outputVideoCodec );
362363 AVCodecParameters .codec_type (pOutputCodecParameters , AVMEDIA_TYPE_VIDEO ());
363364 AVCodecParameters .width (pOutputCodecParameters , frameWidth );
364365 AVCodecParameters .height (pOutputCodecParameters , frameHeight );
365366 AVStream .codecpar (pOutputStream , pOutputCodecParameters );
366367 AVStream .time_base (pOutputStream , pTimeBase );
367368
368- pOutputProperties = av_stream_new_side_data (pOutputStream , AV_PKT_DATA_CPB_PROPERTIES (), AVCPBProperties .sizeof ());
369+ final var pOutputProperties = av_stream_new_side_data (pOutputStream , AV_PKT_DATA_CPB_PROPERTIES (), AVCPBProperties .sizeof ());
369370 AVCPBProperties .buffer_size (pOutputProperties , frameWidth * frameHeight * 3L * 2L );
370371
371372 if (avcodec_open2 (pOutputCodecCtx , pOutputCodec , NULL ) != 0 ) {
372- throw new RuntimeException (formatSaveVideoError (fileName , "Can't open codec " ));
373+ throw new RuntimeException (formatSaveVideoError (fileName , "Can't open encoder " ));
373374 }
374375
375- ppOutputAVIOCtx = arena .allocate (C_POINTER );
376+ final var ppOutputAVIOCtx = arena .allocate (C_POINTER );
376377
377378 if (avio_open2 (ppOutputAVIOCtx , pOutputFileName , AVIO_FLAG_WRITE (), NULL , NULL ) < 0 ) {
378379 throw new RuntimeException (formatSaveVideoError (fileName , "Can't open file" ));
379380 }
380381
381- final var pOutputAVIOCtx = ppOutputAVIOCtx .get (C_POINTER , 0 );
382+ pOutputAVIOCtx = ppOutputAVIOCtx .get (C_POINTER , 0 );
382383
383384 if (pOutputAVIOCtx .equals (NULL )) {
384385 throw new RuntimeException (formatLoadVideoError (fileName , "Can't allocate IO context" ));
@@ -473,9 +474,9 @@ private static int saveVideo(String fileName, int fps, int frames, int frameWidt
473474 }
474475
475476 av_write_trailer (pOutputFormatCtx );
476- } catch ( Exception e ) {
477- if (!ppOutputAVIOCtx .equals (NULL )) {
478- avio_close (ppOutputAVIOCtx );
477+ } finally {
478+ if (!pOutputAVIOCtx .equals (NULL )) {
479+ avio_close (pOutputAVIOCtx );
479480 }
480481
481482 if (!pOutputCodecCtx .equals (NULL )) {
@@ -486,10 +487,6 @@ private static int saveVideo(String fileName, int fps, int frames, int frameWidt
486487 sws_freeContext (pOutputSwsContext );
487488 }
488489
489- if (!pOutputProperties .equals (NULL )) {
490- av_free (pOutputProperties );
491- }
492-
493490 if (!pOutputYUVFrame .equals (NULL )) {
494491 av_free (pOutputYUVFrame );
495492 }
@@ -498,10 +495,6 @@ private static int saveVideo(String fileName, int fps, int frames, int frameWidt
498495 av_free (pOutputRGBFrame );
499496 }
500497
501- if (!pOutputFormat .equals (NULL )) {
502- av_free (pOutputFormat );
503- }
504-
505498 if (!pOutputFormatCtx .equals (NULL )) {
506499 avformat_free_context (pOutputFormatCtx );
507500 }
0 commit comments