diff options
Diffstat (limited to 'src')
14 files changed, 639 insertions, 796 deletions
diff --git a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java index f09d289fa..5d686fc21 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java +++ b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java @@ -576,6 +576,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { this.vid = vid; this.aid = aid; new InterruptSource.Thread() { + @Override public void run() { try { // StreamWorker may be used, see API-doc of StreamWorker diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java index f1049ce6e..71fa70080 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java +++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGDynamicLibraryBundleInfo.java @@ -51,41 +51,39 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { private static final List<String> glueLibNames = new ArrayList<String>(); // none - private static final int symbolCount = 65; + private static final int symbolCount = 59; private static final String[] symbolNames = { "avutil_version", "avformat_version", "avcodec_version", - "avresample_version", -/* 5 */ "swresample_version", + "avdevice_version", // (opt) + "swresample_version", + /* 5 */ // libavcodec - "avcodec_register_all", "avcodec_close", "avcodec_string", "avcodec_find_decoder", - "avcodec_open2", // 53.6.0 (opt) - "avcodec_alloc_frame", - "avcodec_get_frame_defaults", - "avcodec_free_frame", // 54.28.0 (opt) - "avcodec_default_get_buffer", // <= 54 (opt), else sp_avcodec_default_get_buffer2 - "avcodec_default_release_buffer", // <= 54 (opt), else sp_av_frame_unref - "avcodec_default_get_buffer2", // 55 (opt) - "avcodec_get_edge_width", + "avcodec_alloc_context3", + "avcodec_free_context", + "avcodec_parameters_to_context", + "avcodec_open2", // 53.6.0 + "av_frame_alloc", // >= 55.28.1 + "av_frame_free", // >= 55.28.1 + "avcodec_default_get_buffer2", // 55 "av_image_fill_linesizes", - "avcodec_align_dimensions", - "avcodec_align_dimensions2", "avcodec_flush_buffers", - "av_init_packet", + "av_packet_alloc", + "av_packet_free", "av_new_packet", - "av_destruct_packet", - "av_free_packet", - "avcodec_decode_audio4", // 53.25.0 (opt) -/* 27 */ "avcodec_decode_video2", // 52.23.0 + "av_packet_unref", + "avcodec_send_packet", // 57 + "avcodec_receive_frame", // 57 + /* +18 = 23 */ // libavutil - "av_pix_fmt_descriptors", - "av_frame_unref", // 55.0.0 (opt) + "av_pix_fmt_desc_get", // >= lavu 51.45 + "av_frame_unref", // 55.0.0 "av_realloc", "av_free", "av_get_bits_per_pixel", @@ -93,15 +91,19 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { "av_get_bytes_per_sample", // 51.4.0 "av_opt_set_int", // 51.12.0 "av_dict_get", - "av_dict_count", // 54.* (opt) + "av_dict_count", // 54.* (opt) "av_dict_set", -/* 28 */ "av_dict_free", + "av_dict_free", + "av_channel_layout_default", // >= 59 (opt) + "av_channel_layout_uninit", // >= 59 (opt) + "av_channel_layout_describe", // >= 59 (opt) + "av_opt_set_chlayout", // >= 59 + /* +16 = 39 */ // libavformat "avformat_alloc_context", - "avformat_free_context", // 52.96.0 (opt) - "avformat_close_input", // 53.17.0 (opt) - "av_register_all", + "avformat_free_context", // 52.96.0 + "avformat_close_input", // 53.17.0 "av_find_input_format", "avformat_open_input", "av_dump_format", @@ -112,85 +114,74 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { "av_read_pause", "avformat_network_init", // 53.13.0 (opt) "avformat_network_deinit", // 53.13.0 (opt) -/* 54 */ "avformat_find_stream_info", // 53.3.0 (opt) + "avformat_find_stream_info", // 53.3.0 (opt) + /* +14 = 53 */ // libavdevice -/* 55 */ "avdevice_register_all", // supported in all version <= 56 + "avdevice_register_all", // supported in all versions (opt) + /* +1 = 54 */ - // libavresample - "avresample_alloc_context", // 1.0.1 - "avresample_open", - "avresample_close", - "avresample_free", -/* 60 */ "avresample_convert", - - // libavresample + // libswresample "av_opt_set_sample_fmt", // actually lavu .. but exist only w/ swresample! "swr_alloc", "swr_init", "swr_free", -/* 65 */ "swr_convert", - + "swr_convert", + /* +5 = 59 */ }; // optional symbol names private static final String[] optionalSymbolNames = { "avformat_seek_file", // ??? (opt) - "avcodec_free_frame", // 54.28.0 (opt) - "av_frame_unref", // 55.0.0 (opt) "av_dict_count", // 54.* (opt) - "avcodec_default_get_buffer", // <= 54 (opt), else sp_avcodec_default_get_buffer2 - "avcodec_default_release_buffer", // <= 54 (opt), else sp_av_frame_unref - "avcodec_default_get_buffer2", // 55 (opt) + + // libavutil + "av_channel_layout_default", // >= 59 (opt) + "av_channel_layout_uninit", // >= 59 (opt) + "av_channel_layout_describe", // >= 59 (opt) + "av_opt_set_chlayout", // >= 59 // libavdevice + "avdevice_version", // (opt) "avdevice_register_all", // 53.0.0 (opt) - // libavresample - "avresample_version", // 1.0.1 - "avresample_alloc_context", // 1.0.1 - "avresample_open", - "avresample_close", - "avresample_free", - "avresample_convert", - // libswresample "av_opt_set_sample_fmt", // actually lavu .. but exist only w/ swresample! - "swresample_version", // 0 "swr_alloc", "swr_init", "swr_free", "swr_convert", }; - /** util, format, codec, device, avresample, swresample */ - private static final boolean[] libLoaded = new boolean[6]; + private static final int LIB_COUNT = 5; + private static final int LIB_IDX_UTI = 0; + private static final int LIB_IDX_FMT = 1; + private static final int LIB_IDX_COD = 2; + private static final int LIB_IDX_DEV = 3; + private static final int LIB_IDX_SWR = 4; + + /** util, format, codec, device, swresample */ + private static final boolean[] libLoaded = new boolean[LIB_COUNT]; private static final long[] symbolAddr = new long[symbolCount]; private static final boolean ready; - private static final boolean libsUFCLoaded; + private static final boolean libsCFUSLoaded; static final VersionNumber avCodecVersion; static final VersionNumber avFormatVersion; static final VersionNumber avUtilVersion; - static final VersionNumber avResampleVersion; + static final VersionNumber avDeviceVersion; static final VersionNumber swResampleVersion; private static final FFMPEGNatives natives; - private static final int LIB_IDX_UTI = 0; - private static final int LIB_IDX_FMT = 1; - private static final int LIB_IDX_COD = 2; - private static final int LIB_IDX_DEV = 3; - private static final int LIB_IDX_AVR = 4; - private static final int LIB_IDX_SWR = 5; - private static final PrivilegedAction<DynamicLibraryBundle> privInitSymbolsAction = new PrivilegedAction<DynamicLibraryBundle>() { @Override public DynamicLibraryBundle run() { final DynamicLibraryBundle dl = new DynamicLibraryBundle(new FFMPEGDynamicLibraryBundleInfo()); - for(int i=0; i<6; i++) { + for(int i=0; i<libLoaded.length; i++) { libLoaded[i] = dl.isToolLibLoaded(i); } - if( !libLoaded[LIB_IDX_UTI] || !libLoaded[LIB_IDX_FMT] || !libLoaded[LIB_IDX_COD] ) { - System.err.println("FFMPEG Tool library incomplete: [ avutil "+libLoaded[LIB_IDX_UTI]+", avformat "+libLoaded[LIB_IDX_FMT]+", avcodec "+libLoaded[LIB_IDX_COD]+"]"); + if( !libLoaded[LIB_IDX_COD] || !libLoaded[LIB_IDX_FMT] || !libLoaded[LIB_IDX_UTI] || !libLoaded[LIB_IDX_SWR]) { + System.err.println("FFMPEG Tool library incomplete: [ avcodec "+libLoaded[LIB_IDX_COD]+", avformat "+libLoaded[LIB_IDX_FMT]+ + ", avutil "+libLoaded[LIB_IDX_UTI]+", swres "+libLoaded[LIB_IDX_SWR]+" ]"); return null; } dl.claimAllLinkPermission(); @@ -205,12 +196,11 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { } }; /** - * @param loaded 6: util, format, codec, device, avresample, swresample - * @param versions 5: util, format, codec, avresample, swresample + * @param versions 5: util, format, codec, swresample * @return */ private static final boolean initSymbols(final VersionNumber[] versions) { - for(int i=0; i<6; i++) { + for(int i=0; i<libLoaded.length; i++) { libLoaded[i] = false; } if(symbolNames.length != symbolCount) { @@ -233,18 +223,22 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { // no symbol, check optional and alternative symbols final String symbol = symbolNames[i]; if ( !optionalSymbolNameSet.contains(symbol) ) { - System.err.println("Fail: Could not resolve symbol <"+symbolNames[i]+">: not optional, no alternatives."); + System.err.println("FFmpeg: Fail: Could not resolve symbol <"+symbolNames[i]+">: not optional, no alternatives."); res = false; } else if(DEBUG) { - System.err.println("OK: Unresolved optional symbol <"+symbolNames[i]+">"); + System.err.println("FFmpeg: OK: Unresolved optional symbol <"+symbolNames[i]+">"); } } } - versions[0] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[0])); - versions[1] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[1])); - versions[2] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[2])); - versions[3] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[3])); - versions[4] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[4])); + versions[LIB_IDX_UTI] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[LIB_IDX_UTI])); + versions[LIB_IDX_FMT] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[LIB_IDX_FMT])); + versions[LIB_IDX_COD] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[LIB_IDX_COD])); + if( 0 != symbolAddr[LIB_IDX_DEV] ) { + versions[LIB_IDX_DEV] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[LIB_IDX_DEV])); + } else { + versions[LIB_IDX_DEV] = new VersionNumber(0, 0, 0); + } + versions[LIB_IDX_SWR] = FFMPEGStaticNatives.getAVVersion(FFMPEGStaticNatives.getAvVersion0(symbolAddr[LIB_IDX_SWR])); return res; } @@ -254,58 +248,75 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { GLProfile.initSingleton(); boolean _ready = false; - /** util, format, codec, avresample, swresample */ - final VersionNumber[] _versions = new VersionNumber[5]; + /** util, format, codec, swresample */ + final VersionNumber[] _versions = new VersionNumber[LIB_COUNT]; try { _ready = initSymbols(_versions); } catch (final Throwable t) { ExceptionUtils.dumpThrowable("", t); } - libsUFCLoaded = libLoaded[LIB_IDX_UTI] && libLoaded[LIB_IDX_FMT] && libLoaded[LIB_IDX_COD]; - avUtilVersion = _versions[0]; - avFormatVersion = _versions[1]; - avCodecVersion = _versions[2]; - avResampleVersion = _versions[3]; - swResampleVersion = _versions[4]; - if(!libsUFCLoaded) { - System.err.println("LIB_AV Not Available: lavu, lavc, lavu"); + libsCFUSLoaded = libLoaded[LIB_IDX_COD] && libLoaded[LIB_IDX_FMT] && libLoaded[LIB_IDX_UTI] && libLoaded[LIB_IDX_SWR]; + avUtilVersion = _versions[LIB_IDX_UTI]; + avFormatVersion = _versions[LIB_IDX_FMT]; + avCodecVersion = _versions[LIB_IDX_COD]; + avDeviceVersion = _versions[LIB_IDX_DEV]; + swResampleVersion = _versions[LIB_IDX_SWR]; + if(!libsCFUSLoaded) { + String missing = ""; + if( !libLoaded[LIB_IDX_COD] ) { + missing = missing + "avcodec, "; + } + if( !libLoaded[LIB_IDX_FMT] ) { + missing = missing + "avformat, "; + } + if( !libLoaded[LIB_IDX_UTI] ) { + missing = missing + "avutil, "; + } + if( !libLoaded[LIB_IDX_SWR] ) { + missing = missing + "swresample"; + } + System.err.println("FFmpeg Not Available, missing libs: "+missing); natives = null; ready = false; } else if(!_ready) { - System.err.println("LIB_AV Not Matching"); + System.err.println("FFmpeg Symbol Lookup Failed"); natives = null; ready = false; } else { final int avCodecMajor = avCodecVersion.getMajor(); final int avFormatMajor = avFormatVersion.getMajor(); final int avUtilMajor = avUtilVersion.getMajor(); - if( avCodecMajor == 53 && avFormatMajor == 53 && avUtilMajor == 51 ) { - // lavc53.lavf53.lavu51 - natives = new FFMPEGv08Natives(); - } else if( avCodecMajor == 54 && avFormatMajor == 54 && avUtilMajor == 52 ) { - // lavc54.lavf54.lavu52.lavr01 - natives = new FFMPEGv09Natives(); - } else if( avCodecMajor == 55 && avFormatMajor == 55 && ( avUtilMajor == 52 || avUtilMajor == 53 ) ) { - // lavc55.lavf55.lavu52.lavr01 (ffmpeg) or lavc55.lavf55.lavu53.lavr01 (libav) - natives = new FFMPEGv10Natives(); - } else if( avCodecMajor == 56 && avFormatMajor == 56 && avUtilMajor == 54 ) { - // lavc56.lavf56.lavu54.lavr02 - natives = new FFMPEGv11Natives(); + final int avDeviceMajor = avDeviceVersion.getMajor(); + final int swResampleMajor = swResampleVersion.getMajor(); + if( avCodecMajor == 58 && avFormatMajor == 58 && ( avDeviceMajor == 58 || avDeviceMajor == 0 ) && avUtilMajor == 56 && swResampleMajor == 3) { + // Exact match: ffmpeg 4.x.y + natives = new FFMPEGv0400Natives(); + } else if( avCodecMajor == 59 && avFormatMajor == 59 && ( avDeviceMajor == 59 || avDeviceMajor == 0 ) && avUtilMajor == 57 && swResampleMajor == 4) { + // Exact match: ffmpeg 5.x.y + natives = new FFMPEGv0500Natives(); + } else if( avCodecMajor == 60 && avFormatMajor == 60 && ( avDeviceMajor == 60 || avDeviceMajor == 0 ) && avUtilMajor == 58 && swResampleMajor == 4) { + // Exact match: ffmpeg 6.x.y + natives = new FFMPEGv0600Natives(); } else { - System.err.println("LIB_AV No Version/Native-Impl Match"); natives = null; } - if( null != natives && FFMPEGStaticNatives.initIDs0() ) { + if( null == natives ) { + System.err.println("FFmpeg Native Class matching runtime-versions not found."); + ready = false; + } else if( FFMPEGStaticNatives.initIDs0() ) { ready = natives.initSymbols0(symbolAddr, symbolCount); + if( !ready ) { + System.err.println("FFmpeg Native Symbols Initialization Failed"); + } } else { + System.err.println("FFmpeg Native ID Initialization Failed"); ready = false; } } } - static boolean libsLoaded() { return libsUFCLoaded; } + static boolean libsLoaded() { return libsCFUSLoaded; } static boolean avDeviceLoaded() { return libLoaded[LIB_IDX_DEV]; } - static boolean avResampleLoaded() { return libLoaded[LIB_IDX_AVR]; } static boolean swResampleLoaded() { return libLoaded[LIB_IDX_SWR]; } static FFMPEGNatives getNatives() { return natives; } static boolean initSingleton() { return ready; } @@ -354,21 +365,13 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { } else { avutil.add("internal_avutil"); // internal } - avutil.add("libavutil.so.56"); // ffmpeg 4.[0-x] (Debian-10) - avutil.add("libavutil.so.55"); // - avutil.add("libavutil.so.54"); // ffmpeg 2.[4-x] / libav 11 - avutil.add("libavutil.so.53"); // ffmpeg 2.[0-3] / libav 10 - avutil.add("libavutil.so.52"); // ffmpeg 1.2 + 2.[0-3] / libav 9 - avutil.add("libavutil.so.51"); // 0.8 - avutil.add("libavutil.so.50"); // 0.7 + avutil.add("libavutil.so.58"); // ffmpeg 6.[0-x] + avutil.add("libavutil.so.57"); // ffmpeg 5.[0-x] + avutil.add("libavutil.so.56"); // ffmpeg 4.[0-x] (Debian-11) + avutil.add("avutil-58"); // ffmpeg 6.[0-x] + avutil.add("avutil-57"); // ffmpeg 5.[0-x] avutil.add("avutil-56"); // ffmpeg 4.[0-x] - avutil.add("avutil-55"); // - avutil.add("avutil-54"); // ffmpeg 2.[4-x] / libav 11 - avutil.add("avutil-53"); // ffmpeg 2.[0-3] / libav 10 - avutil.add("avutil-52"); // ffmpeg 1.2 + 2.[0-3] / libav 9 - avutil.add("avutil-51"); // 0.8 - avutil.add("avutil-50"); // 0.7 if( FFMPEGMediaPlayer.PREFER_SYSTEM_LIBS ) { avutil.add("internal_avutil"); // internal } else { @@ -382,21 +385,13 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { } else { avformat.add("internal_avformat"); // internal } - avformat.add("libavformat.so.58"); // ffmpeg 4.[0-x] (Debian-10) - avformat.add("libavformat.so.57"); // - avformat.add("libavformat.so.56"); // ffmpeg 2.[4-x] / libav 11 - avformat.add("libavformat.so.55"); // ffmpeg 2.[0-3] / libav 10 - avformat.add("libavformat.so.54"); // ffmpeg 1.2 / libav 9 - avformat.add("libavformat.so.53"); // 0.8 - avformat.add("libavformat.so.52"); // 0.7 + avformat.add("libavformat.so.60"); // ffmpeg 6.[0-x] + avformat.add("libavformat.so.59"); // ffmpeg 5.[0-x] + avformat.add("libavformat.so.58"); // ffmpeg 4.[0-x] (Debian-11) + avformat.add("avformat-60"); // ffmpeg 6.[0-x] + avformat.add("avformat-59"); // ffmpeg 5.[0-x] avformat.add("avformat-58"); // ffmpeg 4.[0-x] - avformat.add("avformat-57"); // - avformat.add("avformat-56"); // ffmpeg 2.[4-x] / libav 11 - avformat.add("avformat-55"); // ffmpeg 2.[0-3] / libav 10 - avformat.add("avformat-54"); // ffmpeg 1.2 / libav 9 - avformat.add("avformat-53"); // 0.8 - avformat.add("avformat-52"); // 0.7 if( FFMPEGMediaPlayer.PREFER_SYSTEM_LIBS ) { avformat.add("internal_avformat"); // internal } else { @@ -410,21 +405,13 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { } else { avcodec.add("internal_avcodec"); // internal } - avcodec.add("libavcodec.so.58"); // ffmpeg 4.[0-x] (Debian-10) - avcodec.add("libavcodec.so.57"); // - avcodec.add("libavcodec.so.56"); // ffmpeg 2.[4-x] / libav 11 - avcodec.add("libavcodec.so.55"); // ffmpeg 2.[0-3] / libav 10 - avcodec.add("libavcodec.so.54"); // ffmpeg 1.2 / libav 9 - avcodec.add("libavcodec.so.53"); // 0.8 - avcodec.add("libavcodec.so.52"); // 0.7 + avcodec.add("libavcodec.so.60"); // ffmpeg 6.[0-x] + avcodec.add("libavcodec.so.59"); // ffmpeg 5.[0-x] + avcodec.add("libavcodec.so.58"); // ffmpeg 4.[0-x] (Debian-11) + avcodec.add("avcodec-60"); // ffmpeg 6.[0-x] + avcodec.add("avcodec-59"); // ffmpeg 5.[0-x] avcodec.add("avcodec-58"); // ffmpeg 4.[0-x] - avcodec.add("avcodec-57"); // - avcodec.add("avcodec-56"); // ffmpeg 2.[4-x] / libav 11 - avcodec.add("avcodec-55"); // ffmpeg 2.[0-3] / libav 10 - avcodec.add("avcodec-54"); // ffmpeg 1.2 / libav 9 - avcodec.add("avcodec-53"); // 0.8 - avcodec.add("avcodec-52"); // 0.7 if( FFMPEGMediaPlayer.PREFER_SYSTEM_LIBS ) { avcodec.add("internal_avcodec"); // internal } else { @@ -438,19 +425,13 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { } else { avdevice.add("internal_avdevice"); // internal } - avdevice.add("libavdevice.so.58"); // ffmpeg 4.[0-x] (Debian-10) - avdevice.add("libavdevice.so.57"); // - avdevice.add("libavdevice.so.56"); // ffmpeg 2.[4-x] - avdevice.add("libavdevice.so.55"); // ffmpeg 2.[0-3] / libav 11 - avdevice.add("libavdevice.so.54"); // ffmpeg 1.2 / libav 10 - avdevice.add("libavdevice.so.53"); // 0.8 && libav 9 + avdevice.add("libavdevice.so.60"); // ffmpeg 6.[0-x] + avdevice.add("libavdevice.so.59"); // ffmpeg 5.[0-x] + avdevice.add("libavdevice.so.58"); // ffmpeg 4.[0-x] (Debian-11) + avdevice.add("avdevice-60"); // ffmpeg 6.[0-x] + avdevice.add("avdevice-59"); // ffmpeg 5.[0-x] avdevice.add("avdevice-58"); // ffmpeg 4.[0-x] - avdevice.add("avdevice-57"); // - avdevice.add("avdevice-56"); // ffmpeg 2.[4-x] - avdevice.add("avdevice-55"); // ffmpeg 2.[0-3] / libav 11 - avdevice.add("avdevice-54"); // ffmpeg 1.2 / libav 10 - avdevice.add("avdevice-53"); // 0.8 && libav 9 if( FFMPEGMediaPlayer.PREFER_SYSTEM_LIBS ) { avdevice.add("internal_avdevice"); // internal } else { @@ -458,43 +439,17 @@ class FFMPEGDynamicLibraryBundleInfo implements DynamicLibraryBundleInfo { } libsList.add(avdevice); - final List<String> avresample = new ArrayList<String>(); - if( FFMPEGMediaPlayer.PREFER_SYSTEM_LIBS ) { - avresample.add("avresample"); // system default - } else { - avresample.add("internal_avresample");// internal - } - avresample.add("libavresample.so.4"); // ffmpeg 4.[0-x] (Debian-10) - avresample.add("libavresample.so.3"); // - avresample.add("libavresample.so.2"); // libav 11 - avresample.add("libavresample.so.1"); // libav 9 + 10 - - avresample.add("avresample-4"); // ffmpeg 4.[0-x] - avresample.add("avresample-3"); // - avresample.add("avresample-2"); // libav 11 - avresample.add("avresample-1"); // libav 9 + 10 - if( FFMPEGMediaPlayer.PREFER_SYSTEM_LIBS ) { - avresample.add("internal_avresample");// internal - } else { - avresample.add("avresample"); // system default - } - libsList.add(avresample); - final List<String> swresample = new ArrayList<String>(); if( FFMPEGMediaPlayer.PREFER_SYSTEM_LIBS ) { swresample.add("swresample"); // system default } else { swresample.add("internal_swresample");// internal } - swresample.add("libswresample.so.3"); // ffmpeg 4.[0-x] (Debian-10) - swresample.add("libswresample.so.2"); // - swresample.add("libswresample.so.1"); // ffmpeg 2.[4-x] - swresample.add("libswresample.so.0"); // ffmpeg 1.2 + 2.[0-3] + swresample.add("libswresample.so.4"); // ffmpeg 5.[0-x] - 6.[0-x] + swresample.add("libswresample.so.3"); // ffmpeg 4.[0-x] (Debian-11) + swresample.add("swresample-4"); // ffmpeg 5.[0-x] - 6.[0-x] swresample.add("swresample-3"); // ffmpeg 4.[0-x] - swresample.add("swresample-2"); // - swresample.add("swresample-1"); // ffmpeg 2.[4-x] - swresample.add("swresample-0"); // ffmpeg 1.2 + 2.[0-3] if( FFMPEGMediaPlayer.PREFER_SYSTEM_LIBS ) { swresample.add("internal_swresample");// internal } else { diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java index 6e44dcc37..c1a7eceda 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java +++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java @@ -56,16 +56,12 @@ import jogamp.opengl.util.av.GLMediaPlayerImpl; import jogamp.opengl.util.av.VideoPixelFormat; /*** - * Implementation utilizes <a href="http://libav.org/">Libav</a> - * or <a href="http://ffmpeg.org/">FFmpeg</a> which are ubiquitous + * Implementation utilizes <a href="http://ffmpeg.org/">FFmpeg</a> which is ubiquitous * available and usually pre-installed on Unix platforms. * <p> - * Due to legal reasons we cannot deploy binaries of it, which contains patented codecs. - * </p> - * <p> * Besides the default BSD/Linux/.. repositories and installations, * precompiled binaries can be found at the - * <a href="#libavavail">listed location below</a>. + * <a href="#ffmpegavail">listed location below</a>. * </p> * * <a name="implspecifics"><h5>Implementation specifics</h5></a> @@ -90,29 +86,26 @@ import jogamp.opengl.util.av.VideoPixelFormat; * </p> * <p> * - * <a name="libavspecifics"><h5>Libav Specifics</h5></a> + * <a name="ffmpegspecifics"><h5>FFmpeg Specifics</h5></a> * <p> - * Utilizes a slim dynamic and native binding to the Lib_av - * libraries: + * Utilizes a slim dynamic and native binding to the FFmpeg libraries: * <ul> - * <li>libavcodec</li> - * <li>libavformat</li> - * <li>libavutil</li> - * <li>libavresample (opt)</li> - * <li>libavdevice (opt)</li> + * <li>avcodec</li> + * <li>avformat</li> + * <li>avutil</li> + * <li>avdevice (optional for video input devices)</li> + * <li>swresample</li> * </ul> * </p> * - * <a name="compatibility"><h5>LibAV Compatibility</h5></a> + * <a name="compatibility"><h5>FFmpeg Compatibility</h5></a> * <p> - * Currently we are binary compatible w/: + * Currently we are binary compatible with the following major versions: * <table border="1"> - * <tr><th>libav / ffmpeg</th><th>lavc</th><th>lavf</th><th>lavu</th><th>lavr/lswr</th> <th>FFMPEG* class</th></tr> - * <tr><td>0.8</td> <td>53</td> <td>53</td> <td>51</td> <td></td> <td>FFMPEGv08</td></tr> - * <tr><td>9.0 / 1.2</td> <td>54</td> <td>54</td> <td>52</td> <td>01/00</td> <td>FFMPEGv09</td></tr> - * <tr><td>10 / 2.[0-3]</td> <td>55</td> <td>55</td> <td>53/52</td> <td>01/00</td> <td>FFMPEGv10</td></tr> - * <tr><td>11 / 2.[4-8]</td> <td>56</td> <td>56</td> <td>54</td> <td>02/01</td> <td>FFMPEGv11</td></tr> - * <tr><td>12 / 2.[9-x]</td> <td>57</td> <td>57</td> <td>55</td> <td>02/01</td> <td>TODO</td></tr> + * <tr><th>ffmpeg</th><th>lavcodec</th><th>lavformat</th><th>lavdevice</th><th>lavutil</th><th>swresample</th> <th>FFMPEG* class</th></tr> + * <tr><td>4</td> <td>58</td> <td>58</td> <td>58</td> <td>56</td> <td>03</td> <td>FFMPEGv0400</td></tr> + * <tr><td>5</td> <td>59</td> <td>59</td> <td>59</td> <td>57</td> <td>04</td> <td>FFMPEGv0500</td></tr> + * <tr><td>6</td> <td>60</td> <td>60</td> <td>60</td> <td>58</td> <td>04</td> <td>FFMPEGv0600</td></tr> * </table> * </p> * <p> @@ -121,11 +114,6 @@ import jogamp.opengl.util.av.VideoPixelFormat; * <li>http://ffmpeg.org/documentation.html</li> * <li>http://git.videolan.org/?p=ffmpeg.git;a=blob;f=doc/APIchanges;hb=HEAD</li> * </ul> - * See libav: - * <ul> - * <li>https://libav.org/documentation.html</li> - * <li>http://upstream-tracker.org/versions/libav.html</li> - * </ul> * </p> * <p> * Check tag 'FIXME: Add more planar formats !' @@ -141,15 +129,14 @@ import jogamp.opengl.util.av.VideoPixelFormat; * </ul> * </p> * - * <a name="libavavail"><h5>FFMPEG / LibAV Availability</h5></a> + * <a name="ffmpegavail"><h5>FFmpeg Availability</h5></a> * <p> * <ul> - * <li>GNU/Linux: ffmpeg or libav are deployed in most distributions.</li> + * <li>GNU/Linux: ffmpeg is deployed in most distributions.</li> * <li>Windows: * <ul> * <li>https://ffmpeg.org/download.html#build-windows</li> * <li>http://ffmpeg.zeranoe.com/builds/ (ffmpeg) <i>recommended, works w/ dshow</i></li> - * <li>http://win32.libav.org/releases/ (libav)</li> * </ul></li> * <li>MacOSX * <ul> @@ -211,11 +198,9 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { private static final int avUtilMajorVersionCC; private static final int avFormatMajorVersionCC; private static final int avCodecMajorVersionCC; - private static final int avResampleMajorVersionCC; + private static final int avDeviceMajorVersionCC; private static final int swResampleMajorVersionCC; private static final boolean available; - private static final boolean enableAvResample; - private static final boolean enableSwResample; static { // PREFER_SYSTEM_LIBS default on all systems is true for now! @@ -230,58 +215,51 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { avCodecMajorVersionCC = natives.getAvCodecMajorVersionCC0(); avFormatMajorVersionCC = natives.getAvFormatMajorVersionCC0(); avUtilMajorVersionCC = natives.getAvUtilMajorVersionCC0(); - avResampleMajorVersionCC = natives.getAvResampleMajorVersionCC0(); + avDeviceMajorVersionCC = natives.getAvDeviceMajorVersionCC0(); swResampleMajorVersionCC = natives.getSwResampleMajorVersionCC0(); } else { avUtilMajorVersionCC = 0; avFormatMajorVersionCC = 0; avCodecMajorVersionCC = 0; - avResampleMajorVersionCC = 0; + avDeviceMajorVersionCC = 0; swResampleMajorVersionCC = 0; } final VersionNumber avCodecVersion = FFMPEGDynamicLibraryBundleInfo.avCodecVersion; final VersionNumber avFormatVersion = FFMPEGDynamicLibraryBundleInfo.avFormatVersion; final VersionNumber avUtilVersion = FFMPEGDynamicLibraryBundleInfo.avUtilVersion; - final VersionNumber avResampleVersion = FFMPEGDynamicLibraryBundleInfo.avResampleVersion; - final boolean avResampleLoaded = FFMPEGDynamicLibraryBundleInfo.avResampleLoaded(); + final VersionNumber avDeviceVersion = FFMPEGDynamicLibraryBundleInfo.avDeviceVersion; final VersionNumber swResampleVersion = FFMPEGDynamicLibraryBundleInfo.swResampleVersion; + final boolean avDeviceLoaded = FFMPEGDynamicLibraryBundleInfo.avDeviceLoaded(); final boolean swResampleLoaded = FFMPEGDynamicLibraryBundleInfo.swResampleLoaded(); - if( DEBUG ) { - System.err.println("LIB_AV Codec : "+avCodecVersion+" [cc "+avCodecMajorVersionCC+"]"); - System.err.println("LIB_AV Format : "+avFormatVersion+" [cc "+avFormatMajorVersionCC+"]"); - System.err.println("LIB_AV Util : "+avUtilVersion+" [cc "+avUtilMajorVersionCC+"]"); - System.err.println("LIB_AV Resample: "+avResampleVersion+" [cc "+avResampleMajorVersionCC+", loaded "+avResampleLoaded+"]"); - System.err.println("LIB_SW Resample: "+swResampleVersion+" [cc "+swResampleMajorVersionCC+", loaded "+swResampleLoaded+"]"); - System.err.println("LIB_AV Device : [loaded "+FFMPEGDynamicLibraryBundleInfo.avDeviceLoaded()+"]"); - System.err.println("LIB_AV Class : "+(null!= natives ? natives.getClass().getSimpleName() : "n/a")); - } final int avCodecMajor = avCodecVersion.getMajor(); final int avFormatMajor = avFormatVersion.getMajor(); final int avUtilMajor = avUtilVersion.getMajor(); + final int avDeviceMajor = avDeviceVersion.getMajor(); + final int swResampleMajor = swResampleVersion.getMajor(); libAVVersionGood = avCodecMajorVersionCC == avCodecMajor && avFormatMajorVersionCC == avFormatMajor && - ( avUtilMajorVersionCC == avUtilMajor || - 55 == avCodecMajorVersionCC && 53 == avUtilMajorVersionCC && 52 == avUtilMajor /* ffmpeg 2.x */ - ); - enableAvResample = avResampleLoaded && avResampleMajorVersionCC == avResampleVersion.getMajor(); - enableSwResample = swResampleLoaded && swResampleMajorVersionCC == swResampleVersion.getMajor(); - if( DEBUG ) { - System.err.println("LIB_AV Resample: enabled "+enableAvResample); - System.err.println("LIB_SW Resample: enabled "+enableSwResample); - } + avUtilMajorVersionCC == avUtilMajor && + ( avDeviceMajorVersionCC == avDeviceMajor || 0 == avDeviceMajor ) && + swResampleMajorVersionCC == swResampleMajor; if( !libAVVersionGood ) { - System.err.println("LIB_AV Not Matching Compile-Time / Runtime Major-Version"); + System.err.println("FFmpeg Not Matching Compile-Time / Runtime Major-Version"); + } + if( !libAVVersionGood || DEBUG ) { + System.err.println("FFmpeg Codec : "+avCodecVersion+" [cc "+avCodecMajorVersionCC+"]"); + System.err.println("FFmpeg Format : "+avFormatVersion+" [cc "+avFormatMajorVersionCC+"]"); + System.err.println("FFmpeg Util : "+avUtilVersion+" [cc "+avUtilMajorVersionCC+"]"); + System.err.println("FFmpeg Device : "+avDeviceVersion+" [cc "+avDeviceMajorVersionCC+", loaded "+avDeviceLoaded+"]"); + System.err.println("FFmpeg Resample: "+swResampleVersion+" [cc "+swResampleMajorVersionCC+", loaded "+swResampleLoaded+"]"); + System.err.println("FFmpeg Class : "+(null!= natives ? natives.getClass().getSimpleName() : "n/a")); } } else { natives = null; avUtilMajorVersionCC = 0; avFormatMajorVersionCC = 0; avCodecMajorVersionCC = 0; - avResampleMajorVersionCC = 0; + avDeviceMajorVersionCC = 0; swResampleMajorVersionCC = 0; libAVVersionGood = false; - enableAvResample = false; - enableSwResample = false; } available = libAVGood && libAVVersionGood && null != natives; } @@ -319,7 +297,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { if(!available) { throw new RuntimeException("FFMPEGMediaPlayer not available"); } - moviePtr = natives.createInstance0(this, enableAvResample, enableSwResample, DEBUG_NATIVE); + moviePtr = natives.createInstance0(this, DEBUG_NATIVE); if(0==moviePtr) { throw new GLException("Couldn't create FFMPEGInstance"); } @@ -521,8 +499,8 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { /** * Native callback - * Converts the given libav/ffmpeg values to {@link AudioFormat} and returns {@link AudioSink#isSupported(AudioFormat)}. - * @param audioSampleFmt ffmpeg/libav audio-sample-format, see {@link AudioSampleFormat}. + * Converts the given ffmpeg values to {@link AudioFormat} and returns {@link AudioSink#isSupported(AudioFormat)}. + * @param audioSampleFmt ffmpeg audio-sample-format, see {@link AudioSampleFormat}. * @param audioSampleRate sample rate in Hz (1/s) * @param audioChannels number of channels */ @@ -537,8 +515,8 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { } /** - * Returns {@link AudioFormat} as converted from the given libav/ffmpeg values. - * @param audioSampleFmt ffmpeg/libav audio-sample-format, see {@link AudioSampleFormat}. + * Returns {@link AudioFormat} as converted from the given ffmpeg values. + * @param audioSampleFmt ffmpeg audio-sample-format, see {@link AudioSampleFormat}. * @param audioSampleRate sample rate in Hz (1/s) * @param audioChannels number of channels */ @@ -853,7 +831,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { } final int errno = natives.play0(moviePtr); if( DEBUG_NATIVE && errno != 0 && errno != -ENOSYS) { - System.err.println("libav play err: "+errno); + System.err.println("ffmpeg play err: "+errno); } return true; } @@ -865,7 +843,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { } final int errno = natives.pause0(moviePtr); if( DEBUG_NATIVE && errno != 0 && errno != -ENOSYS) { - System.err.println("libav pause err: "+errno); + System.err.println("ffmpeg pause err: "+errno); } return true; } diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java index 3b8fc83d9..9099bfb08 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java +++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGNatives.java @@ -1,5 +1,5 @@ /** - * Copyright 2013 JogAmp Community. All rights reserved. + * Copyright 2013-2023 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -40,10 +40,10 @@ import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; abstract int getAvUtilMajorVersionCC0(); abstract int getAvFormatMajorVersionCC0(); abstract int getAvCodecMajorVersionCC0(); - abstract int getAvResampleMajorVersionCC0(); + abstract int getAvDeviceMajorVersionCC0(); abstract int getSwResampleMajorVersionCC0(); - abstract long createInstance0(FFMPEGMediaPlayer upstream, boolean enableAvResample, boolean enableSwResample, boolean verbose); + abstract long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose); abstract void destroyInstance0(long moviePtr); /** diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv08Natives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0400Natives.java index eff9ee5f5..0f7d02904 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv08Natives.java +++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0400Natives.java @@ -1,5 +1,5 @@ /** - * Copyright 2013 JogAmp Community. All rights reserved. + * Copyright 2015-2023 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -27,7 +27,7 @@ */ package jogamp.opengl.util.av.impl; -class FFMPEGv08Natives extends FFMPEGNatives { +class FFMPEGv0400Natives extends FFMPEGNatives { @Override native boolean initSymbols0(Object mutex_avcodec_openclose, long[] symbols, int count); @@ -41,13 +41,13 @@ class FFMPEGv08Natives extends FFMPEGNatives { native int getAvCodecMajorVersionCC0(); @Override - native int getAvResampleMajorVersionCC0(); + native int getAvDeviceMajorVersionCC0(); @Override native int getSwResampleMajorVersionCC0(); @Override - native long createInstance0(FFMPEGMediaPlayer upstream, boolean enableAvResample, boolean enableSwResample, boolean verbose); + native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose); @Override native void destroyInstance0(long moviePtr); diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv09Natives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0500Natives.java index d61b39c77..8d62ac1c5 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv09Natives.java +++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0500Natives.java @@ -1,5 +1,5 @@ /** - * Copyright 2013 JogAmp Community. All rights reserved. + * Copyright 2015-2023 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -27,7 +27,7 @@ */ package jogamp.opengl.util.av.impl; -class FFMPEGv09Natives extends FFMPEGNatives { +class FFMPEGv0500Natives extends FFMPEGNatives { @Override native boolean initSymbols0(Object mutex_avcodec_openclose, long[] symbols, int count); @@ -41,13 +41,13 @@ class FFMPEGv09Natives extends FFMPEGNatives { native int getAvCodecMajorVersionCC0(); @Override - native int getAvResampleMajorVersionCC0(); + native int getAvDeviceMajorVersionCC0(); @Override native int getSwResampleMajorVersionCC0(); @Override - native long createInstance0(FFMPEGMediaPlayer upstream, boolean enableAvResample, boolean enableSwResample, boolean verbose); + native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose); @Override native void destroyInstance0(long moviePtr); diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv10Natives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0600Natives.java index 109fd8953..0de167285 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv10Natives.java +++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv0600Natives.java @@ -1,5 +1,5 @@ /** - * Copyright 2013 JogAmp Community. All rights reserved. + * Copyright 2015-2023 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -27,7 +27,7 @@ */ package jogamp.opengl.util.av.impl; -class FFMPEGv10Natives extends FFMPEGNatives { +class FFMPEGv0600Natives extends FFMPEGNatives { @Override native boolean initSymbols0(Object mutex_avcodec_openclose, long[] symbols, int count); @@ -41,13 +41,13 @@ class FFMPEGv10Natives extends FFMPEGNatives { native int getAvCodecMajorVersionCC0(); @Override - native int getAvResampleMajorVersionCC0(); + native int getAvDeviceMajorVersionCC0(); @Override native int getSwResampleMajorVersionCC0(); @Override - native long createInstance0(FFMPEGMediaPlayer upstream, boolean enableAvResample, boolean enableSwResample, boolean verbose); + native long createInstance0(FFMPEGMediaPlayer upstream, boolean verbose); @Override native void destroyInstance0(long moviePtr); diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv11Natives.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv11Natives.java deleted file mode 100644 index 9654eca82..000000000 --- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGv11Natives.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright 2015 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ -package jogamp.opengl.util.av.impl; - -class FFMPEGv11Natives extends FFMPEGNatives { - @Override - native boolean initSymbols0(Object mutex_avcodec_openclose, long[] symbols, int count); - - @Override - native int getAvUtilMajorVersionCC0(); - - @Override - native int getAvFormatMajorVersionCC0(); - - @Override - native int getAvCodecMajorVersionCC0(); - - @Override - native int getAvResampleMajorVersionCC0(); - - @Override - native int getSwResampleMajorVersionCC0(); - - @Override - native long createInstance0(FFMPEGMediaPlayer upstream, boolean enableAvResample, boolean enableSwResample, boolean verbose); - - @Override - native void destroyInstance0(long moviePtr); - - @Override - native void setStream0(long moviePtr, String url, boolean isCameraInput, int vid, String sizes, int vWidth, int vHeight, int vRate, int aid, int aMaxChannelCount, int aPrefSampleRate); - - @Override - native void setGLFuncs0(long moviePtr, long procAddrGLTexSubImage2D, long procAddrGLGetError, long procAddrGLFlush, long procAddrGLFinish); - - @Override - native int getVideoPTS0(long moviePtr); - - @Override - native int getAudioPTS0(long moviePtr); - - @Override - native int readNextPacket0(long moviePtr, int texTarget, int texFmt, int texType); - - @Override - native int play0(long moviePtr); - - @Override - native int pause0(long moviePtr); - - @Override - native int seek0(long moviePtr, int position); -} diff --git a/src/jogl/native/libav/ffmpeg_impl_template.c b/src/jogl/native/libav/ffmpeg_impl_template.c index d02770eb7..3e6b29d05 100644 --- a/src/jogl/native/libav/ffmpeg_impl_template.c +++ b/src/jogl/native/libav/ffmpeg_impl_template.c @@ -1,5 +1,5 @@ /** - * Copyright 2012 JogAmp Community. All rights reserved. + * Copyright 2012-2023 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -33,13 +33,6 @@ #include "ffmpeg_static.h" #include "ffmpeg_dshow.h" -#include "libavutil/pixdesc.h" -#include "libavutil/samplefmt.h" -#if LIBAVUTIL_VERSION_MAJOR < 53 - #include "libavutil/audioconvert.h" - // 52: #include "libavutil/channel_layout.h" -#endif - #include <GL/gl.h> #define HAS_FUNC(f) (NULL!=(f)) @@ -47,65 +40,59 @@ typedef unsigned (APIENTRYP AVUTIL_VERSION)(void); typedef unsigned (APIENTRYP AVFORMAT_VERSION)(void); typedef unsigned (APIENTRYP AVCODEC_VERSION)(void); -typedef unsigned (APIENTRYP AVRESAMPLE_VERSION)(void); +typedef unsigned (APIENTRYP AVDEVICE_VERSION)(void); typedef unsigned (APIENTRYP SWRESAMPLE_VERSION)(void); static AVUTIL_VERSION sp_avutil_version; static AVFORMAT_VERSION sp_avformat_version; static AVCODEC_VERSION sp_avcodec_version; -static AVRESAMPLE_VERSION sp_avresample_version; +static AVDEVICE_VERSION sp_avdevice_version; static SWRESAMPLE_VERSION sp_swresample_version; // count: 5 // libavcodec -typedef int (APIENTRYP AVCODEC_REGISTER_ALL)(void); typedef int (APIENTRYP AVCODEC_CLOSE)(AVCodecContext *avctx); typedef void (APIENTRYP AVCODEC_STRING)(char *buf, int buf_size, AVCodecContext *enc, int encode); -typedef AVCodec *(APIENTRYP AVCODEC_FIND_DECODER)(int avCodecID); // lavc 53: 'enum CodecID id', lavc 54: 'enum AVCodecID id' +typedef AVCodec *(APIENTRYP AVCODEC_FIND_DECODER)(enum AVCodecID avCodecID); // lavc 53: 'enum CodecID id', lavc 54: 'enum AVCodecID id' +typedef AVCodecContext* (APIENTRYP AVCODEC_ALLOC_CONTEXT3)(const AVCodec* codec); +typedef void (APIENTRYP AVCODEC_FREE_CONTEXT)(AVCodecContext** avctx); +typedef int (APIENTRYP AVCODEC_PARAMTERS_TO_CONTEXT)(AVCodecContext *codec, const AVCodecParameters *par); typedef int (APIENTRYP AVCODEC_OPEN2)(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options); // 53.6.0 -typedef AVFrame *(APIENTRYP AVCODEC_ALLOC_FRAME)(void); -typedef void (APIENTRYP AVCODEC_GET_FRAME_DEFAULTS)(AVFrame *frame); -typedef void (APIENTRYP AVCODEC_FREE_FRAME)(AVFrame **frame); -typedef int (APIENTRYP AVCODEC_DEFAULT_GET_BUFFER)(AVCodecContext *s, AVFrame *pic); // <= 54 (opt), else AVCODEC_DEFAULT_GET_BUFFER2 -typedef void (APIENTRYP AVCODEC_DEFAULT_RELEASE_BUFFER)(AVCodecContext *s, AVFrame *pic); // <= 54 (opt), else AV_FRAME_UNREF -typedef int (APIENTRYP AVCODEC_DEFAULT_GET_BUFFER2)(AVCodecContext *s, AVFrame *frame, int flags); // 55. (opt) -typedef int (APIENTRYP AVCODEC_GET_EDGE_WIDTH)(); -typedef int (APIENTRYP AV_IMAGE_FILL_LINESIZES)(int linesizes[4], int pix_fmt, int width); // lavu 51: 'enum PixelFormat pix_fmt', lavu 53: 'enum AVPixelFormat pix_fmt' -typedef void (APIENTRYP AVCODEC_ALIGN_DIMENSIONS)(AVCodecContext *s, int *width, int *height); -typedef void (APIENTRYP AVCODEC_ALIGN_DIMENSIONS2)(AVCodecContext *s, int *width, int *height, int linesize_align[AV_NUM_DATA_POINTERS]); +typedef AVFrame *(APIENTRYP AV_FRAME_ALLOC)(void); // 55.28.1 +typedef void (APIENTRYP AV_FREE_FRAME)(AVFrame **frame); // 55.28.1 +typedef int (APIENTRYP AVCODEC_DEFAULT_GET_BUFFER2)(AVCodecContext *s, AVFrame *frame, int flags); // 55. +typedef int (APIENTRYP AV_IMAGE_FILL_LINESIZES)(int linesizes[4], enum AVPixelFormat pix_fmt, int width); // lavu 51: 'enum PixelFormat pix_fmt', lavu 53: 'enum AVPixelFormat pix_fmt' typedef void (APIENTRYP AVCODEC_FLUSH_BUFFERS)(AVCodecContext *avctx); -typedef void (APIENTRYP AV_INIT_PACKET)(AVPacket *pkt); +typedef AVPacket* (APIENTRYP AV_PACKET_ALLOC)(void); +typedef void (APIENTRYP AV_PACKET_FREE)(AVPacket **pkt); typedef int (APIENTRYP AV_NEW_PACKET)(AVPacket *pkt, int size); -typedef void (APIENTRYP AV_DESTRUCT_PACKET)(AVPacket *pkt); -typedef void (APIENTRYP AV_FREE_PACKET)(AVPacket *pkt); -typedef int (APIENTRYP AVCODEC_DECODE_AUDIO4)(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt); // 53.25.0 -typedef int (APIENTRYP AVCODEC_DECODE_VIDEO2)(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, AVPacket *avpkt); // 52.23.0 +typedef void (APIENTRYP AV_PACKET_UNREF)(AVPacket *pkt); +typedef int (APIENTRYP AVCODEC_SEND_PACKET)(AVCodecContext *avctx, AVPacket *avpkt); // 57 +typedef int (APIENTRYP AVCODEC_RECEIVE_FRAME)(AVCodecContext *avctx, AVFrame *picture); // 57 -static AVCODEC_REGISTER_ALL sp_avcodec_register_all; static AVCODEC_CLOSE sp_avcodec_close; static AVCODEC_STRING sp_avcodec_string; static AVCODEC_FIND_DECODER sp_avcodec_find_decoder; +static AVCODEC_ALLOC_CONTEXT3 sp_avcodec_alloc_context3; +static AVCODEC_FREE_CONTEXT sp_avcodec_free_context; +static AVCODEC_PARAMTERS_TO_CONTEXT sp_avcodec_parameters_to_context; static AVCODEC_OPEN2 sp_avcodec_open2; // 53.6.0 -static AVCODEC_ALLOC_FRAME sp_avcodec_alloc_frame; -static AVCODEC_GET_FRAME_DEFAULTS sp_avcodec_get_frame_defaults; -static AVCODEC_FREE_FRAME sp_avcodec_free_frame; -static AVCODEC_DEFAULT_GET_BUFFER sp_avcodec_default_get_buffer; // <= 54 (opt), else sp_avcodec_default_get_buffer2 -static AVCODEC_DEFAULT_RELEASE_BUFFER sp_avcodec_default_release_buffer; // <= 54 (opt), else sp_av_frame_unref -static AVCODEC_DEFAULT_GET_BUFFER2 sp_avcodec_default_get_buffer2; // 55. (opt) -static AVCODEC_GET_EDGE_WIDTH sp_avcodec_get_edge_width; +static AV_FRAME_ALLOC sp_av_frame_alloc; // 55.28.1 +static AV_FREE_FRAME sp_av_free_frame; // 55.28.1 +static AVCODEC_DEFAULT_GET_BUFFER2 sp_avcodec_default_get_buffer2; // 55. static AV_IMAGE_FILL_LINESIZES sp_av_image_fill_linesizes; -static AVCODEC_ALIGN_DIMENSIONS sp_avcodec_align_dimensions; -static AVCODEC_ALIGN_DIMENSIONS2 sp_avcodec_align_dimensions2; static AVCODEC_FLUSH_BUFFERS sp_avcodec_flush_buffers; -static AV_INIT_PACKET sp_av_init_packet; +static AV_PACKET_ALLOC sp_av_packet_alloc; // sp_av_init_packet +static AV_PACKET_FREE sp_av_packet_free; static AV_NEW_PACKET sp_av_new_packet; -static AV_DESTRUCT_PACKET sp_av_destruct_packet; -static AV_FREE_PACKET sp_av_free_packet; -static AVCODEC_DECODE_AUDIO4 sp_avcodec_decode_audio4; // 53.25.0 -static AVCODEC_DECODE_VIDEO2 sp_avcodec_decode_video2; // 52.23.0 -// count: 27 +static AV_PACKET_UNREF sp_av_packet_unref; + +static AVCODEC_SEND_PACKET sp_avcodec_send_packet; // 57 +static AVCODEC_RECEIVE_FRAME sp_avcodec_receive_frame; // 57 +// count: +18 = 23 // libavutil +typedef AVPixFmtDescriptor* (APIENTRYP AV_PIX_FMT_DESC_GET)(enum AVPixelFormat pix_fmt); // lavu >= 51.45; lavu 51: 'enum PixelFormat pix_fmt', lavu 53: 'enum AVPixelFormat pix_fmt' typedef void (APIENTRYP AV_FRAME_UNREF)(AVFrame *frame); typedef void* (APIENTRYP AV_REALLOC)(void *ptr, size_t size); typedef void (APIENTRYP AV_FREE)(void *ptr); @@ -117,8 +104,12 @@ typedef AVDictionaryEntry* (APIENTRYP AV_DICT_GET)(AVDictionary *m, const char * typedef int (APIENTRYP AV_DICT_COUNT)(AVDictionary *m); typedef int (APIENTRYP AV_DICT_SET)(AVDictionary **pm, const char *key, const char *value, int flags); typedef void (APIENTRYP AV_DICT_FREE)(AVDictionary **m); +typedef void (APIENTRYP AV_CHANNEL_LAYOUT_DEFAULT)(AVChannelLayoutPtr ch_layout, int nb_channels); +typedef void (APIENTRYP AV_CHANNEL_LAYOUT_UNINIT)(AVChannelLayoutPtr ch_layout); +typedef int (APIENTRYP AV_CHANNEL_LAYOUT_DESCRIBE)(AVChannelLayoutPtr ch_layout, char* buf, size_t buf_size); +typedef int (APIENTRYP AV_OPT_SET_CHLAYOUT)(void *obj, const char *name, const AVChannelLayoutPtr val, int search_flags); -static const AVPixFmtDescriptor* sp_av_pix_fmt_descriptors; +static AV_PIX_FMT_DESC_GET sp_av_pix_fmt_desc_get; static AV_FRAME_UNREF sp_av_frame_unref; static AV_REALLOC sp_av_realloc; static AV_FREE sp_av_free; @@ -130,13 +121,16 @@ static AV_DICT_GET sp_av_dict_get; static AV_DICT_COUNT sp_av_dict_count; static AV_DICT_SET sp_av_dict_set; static AV_DICT_FREE sp_av_dict_free; -// count: 39 +static AV_CHANNEL_LAYOUT_DEFAULT sp_av_channel_layout_default; // >= 59 +static AV_CHANNEL_LAYOUT_UNINIT sp_av_channel_layout_uninit; // >= 59 +static AV_CHANNEL_LAYOUT_DESCRIBE sp_av_channel_layout_describe; // >= 59 +static AV_OPT_SET_CHLAYOUT sp_av_opt_set_chlayout; // >= 59 +// count: +16 = 39 // libavformat typedef AVFormatContext *(APIENTRYP AVFORMAT_ALLOC_CONTEXT)(void); typedef void (APIENTRYP AVFORMAT_FREE_CONTEXT)(AVFormatContext *s); // 52.96.0 typedef void (APIENTRYP AVFORMAT_CLOSE_INPUT)(AVFormatContext **s); // 53.17.0 -typedef void (APIENTRYP AV_REGISTER_ALL)(void); typedef AVInputFormat *(APIENTRYP AV_FIND_INPUT_FORMAT)(const char *short_name); typedef int (APIENTRYP AVFORMAT_OPEN_INPUT)(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options); typedef void (APIENTRYP AV_DUMP_FORMAT)(AVFormatContext *ic, int index, const char *url, int is_output); @@ -152,7 +146,6 @@ typedef int (APIENTRYP AVFORMAT_FIND_STREAM_INFO)(AVFormatContext *ic, AVDiction static AVFORMAT_ALLOC_CONTEXT sp_avformat_alloc_context; static AVFORMAT_FREE_CONTEXT sp_avformat_free_context; // 52.96.0 (not used, only for outfile cts) static AVFORMAT_CLOSE_INPUT sp_avformat_close_input; // 53.17.0 -static AV_REGISTER_ALL sp_av_register_all; static AV_FIND_INPUT_FORMAT sp_av_find_input_format; static AVFORMAT_OPEN_INPUT sp_avformat_open_input; static AV_DUMP_FORMAT sp_av_dump_format; @@ -164,27 +157,12 @@ static AV_READ_PAUSE sp_av_read_pause; static AVFORMAT_NETWORK_INIT sp_avformat_network_init; // 53.13.0 static AVFORMAT_NETWORK_DEINIT sp_avformat_network_deinit; // 53.13.0 static AVFORMAT_FIND_STREAM_INFO sp_avformat_find_stream_info; // 53.3.0 -// count: 54 +// count: +14 = 53 // libavdevice [53.0.0] typedef int (APIENTRYP AVDEVICE_REGISTER_ALL)(void); static AVDEVICE_REGISTER_ALL sp_avdevice_register_all; -// count: 55 - -// libavresample [1.0.1] -typedef AVAudioResampleContext* (APIENTRYP AVRESAMPLE_ALLOC_CONTEXT)(void); // 1.0.1 -typedef int (APIENTRYP AVRESAMPLE_OPEN)(AVAudioResampleContext *avr); // 1.0.1 -typedef void (APIENTRYP AVRESAMPLE_CLOSE)(AVAudioResampleContext *avr); // 1.0.1 -typedef void (APIENTRYP AVRESAMPLE_FREE)(AVAudioResampleContext **avr); // 1.0.1 -typedef int (APIENTRYP AVRESAMPLE_CONVERT)(AVAudioResampleContext *avr, uint8_t **output, - int out_plane_size, int out_samples, uint8_t **input, - int in_plane_size, int in_samples); // 1.0.1 -static AVRESAMPLE_ALLOC_CONTEXT sp_avresample_alloc_context; -static AVRESAMPLE_OPEN sp_avresample_open; -static AVRESAMPLE_CLOSE sp_avresample_close; -static AVRESAMPLE_FREE sp_avresample_free; -static AVRESAMPLE_CONVERT sp_avresample_convert; -// count: 60 +// count: +1 = 54 // libswresample [1...] typedef int (APIENTRYP AV_OPT_SET_SAMPLE_FMT)(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags); // actually lavu .. but exist only w/ swresample! @@ -198,7 +176,7 @@ static SWR_ALLOC sp_swr_alloc; static SWR_INIT sp_swr_init; static SWR_FREE sp_swr_free; static SWR_CONVERT sp_swr_convert; -// count: 65 +// count: +5 = 59 // We use JNI Monitor Locking, since this removes the need // to statically link-in pthreads on window .. @@ -222,7 +200,7 @@ static SWR_CONVERT sp_swr_convert; #define MY_MUTEX_UNLOCK(e,s) #endif -#define SYMBOL_COUNT 65 +#define SYMBOL_COUNT 59 JNIEXPORT jboolean JNICALL FF_FUNC(initSymbols0) (JNIEnv *env, jobject instance, jobject jmutex_avcodec_openclose, jobject jSymbols, jint count) @@ -246,33 +224,29 @@ JNIEXPORT jboolean JNICALL FF_FUNC(initSymbols0) sp_avutil_version = (AVUTIL_VERSION) (intptr_t) symbols[i++]; sp_avformat_version = (AVFORMAT_VERSION) (intptr_t) symbols[i++]; sp_avcodec_version = (AVCODEC_VERSION) (intptr_t) symbols[i++]; - sp_avresample_version = (AVRESAMPLE_VERSION) (intptr_t) symbols[i++]; + sp_avdevice_version = (AVDEVICE_VERSION) (intptr_t) symbols[i++]; sp_swresample_version = (SWRESAMPLE_VERSION) (intptr_t) symbols[i++]; - sp_avcodec_register_all = (AVCODEC_REGISTER_ALL) (intptr_t) symbols[i++]; sp_avcodec_close = (AVCODEC_CLOSE) (intptr_t) symbols[i++]; sp_avcodec_string = (AVCODEC_STRING) (intptr_t) symbols[i++]; sp_avcodec_find_decoder = (AVCODEC_FIND_DECODER) (intptr_t) symbols[i++]; + sp_avcodec_alloc_context3 = (AVCODEC_ALLOC_CONTEXT3) (intptr_t) symbols[i++]; + sp_avcodec_free_context = (AVCODEC_FREE_CONTEXT) (intptr_t) symbols[i++]; + sp_avcodec_parameters_to_context = (AVCODEC_PARAMTERS_TO_CONTEXT) (intptr_t) symbols[i++]; sp_avcodec_open2 = (AVCODEC_OPEN2) (intptr_t) symbols[i++]; - sp_avcodec_alloc_frame = (AVCODEC_ALLOC_FRAME) (intptr_t) symbols[i++]; - sp_avcodec_get_frame_defaults = (AVCODEC_GET_FRAME_DEFAULTS) (intptr_t) symbols[i++]; - sp_avcodec_free_frame = (AVCODEC_FREE_FRAME) (intptr_t) symbols[i++]; - sp_avcodec_default_get_buffer = (AVCODEC_DEFAULT_GET_BUFFER) (intptr_t) symbols[i++]; - sp_avcodec_default_release_buffer = (AVCODEC_DEFAULT_RELEASE_BUFFER) (intptr_t) symbols[i++]; + sp_av_frame_alloc = (AV_FRAME_ALLOC) (intptr_t) symbols[i++]; + sp_av_free_frame = (AV_FREE_FRAME) (intptr_t) symbols[i++]; sp_avcodec_default_get_buffer2 = (AVCODEC_DEFAULT_GET_BUFFER2) (intptr_t) symbols[i++]; - sp_avcodec_get_edge_width = (AVCODEC_GET_EDGE_WIDTH) (intptr_t) symbols[i++]; sp_av_image_fill_linesizes = (AV_IMAGE_FILL_LINESIZES) (intptr_t) symbols[i++]; - sp_avcodec_align_dimensions = (AVCODEC_ALIGN_DIMENSIONS) (intptr_t) symbols[i++]; - sp_avcodec_align_dimensions2 = (AVCODEC_ALIGN_DIMENSIONS2) (intptr_t) symbols[i++]; sp_avcodec_flush_buffers = (AVCODEC_FLUSH_BUFFERS) (intptr_t) symbols[i++]; - sp_av_init_packet = (AV_INIT_PACKET) (intptr_t) symbols[i++]; + sp_av_packet_alloc = (AV_PACKET_ALLOC) (intptr_t) symbols[i++]; + sp_av_packet_free = (AV_PACKET_FREE) (intptr_t) symbols[i++]; sp_av_new_packet = (AV_NEW_PACKET) (intptr_t) symbols[i++]; - sp_av_destruct_packet = (AV_DESTRUCT_PACKET) (intptr_t) symbols[i++]; - sp_av_free_packet = (AV_FREE_PACKET) (intptr_t) symbols[i++]; - sp_avcodec_decode_audio4 = (AVCODEC_DECODE_AUDIO4) (intptr_t) symbols[i++]; - sp_avcodec_decode_video2 = (AVCODEC_DECODE_VIDEO2) (intptr_t) symbols[i++]; + sp_av_packet_unref = (AV_PACKET_UNREF) (intptr_t) symbols[i++]; + sp_avcodec_send_packet = (AVCODEC_SEND_PACKET) (intptr_t) symbols[i++]; + sp_avcodec_receive_frame = (AVCODEC_RECEIVE_FRAME) (intptr_t) symbols[i++]; - sp_av_pix_fmt_descriptors = (const AVPixFmtDescriptor*) (intptr_t) symbols[i++]; + sp_av_pix_fmt_desc_get = (AV_PIX_FMT_DESC_GET) (intptr_t) symbols[i++]; sp_av_frame_unref = (AV_FRAME_UNREF) (intptr_t) symbols[i++]; sp_av_realloc = (AV_REALLOC) (intptr_t) symbols[i++]; sp_av_free = (AV_FREE) (intptr_t) symbols[i++]; @@ -284,11 +258,14 @@ JNIEXPORT jboolean JNICALL FF_FUNC(initSymbols0) sp_av_dict_count = (AV_DICT_COUNT) (intptr_t) symbols[i++]; sp_av_dict_set = (AV_DICT_SET) (intptr_t) symbols[i++]; sp_av_dict_free = (AV_DICT_FREE) (intptr_t) symbols[i++]; + sp_av_channel_layout_default = (AV_CHANNEL_LAYOUT_DEFAULT) (intptr_t) symbols[i++]; + sp_av_channel_layout_uninit = (AV_CHANNEL_LAYOUT_UNINIT) (intptr_t) symbols[i++]; + sp_av_channel_layout_describe = (AV_CHANNEL_LAYOUT_DESCRIBE) (intptr_t) symbols[i++]; + sp_av_opt_set_chlayout = (AV_OPT_SET_CHLAYOUT) (intptr_t) symbols[i++]; sp_avformat_alloc_context = (AVFORMAT_ALLOC_CONTEXT) (intptr_t) symbols[i++];; sp_avformat_free_context = (AVFORMAT_FREE_CONTEXT) (intptr_t) symbols[i++]; sp_avformat_close_input = (AVFORMAT_CLOSE_INPUT) (intptr_t) symbols[i++]; - sp_av_register_all = (AV_REGISTER_ALL) (intptr_t) symbols[i++]; sp_av_find_input_format = (AV_FIND_INPUT_FORMAT) (intptr_t) symbols[i++]; sp_avformat_open_input = (AVFORMAT_OPEN_INPUT) (intptr_t) symbols[i++]; sp_av_dump_format = (AV_DUMP_FORMAT) (intptr_t) symbols[i++]; @@ -303,12 +280,6 @@ JNIEXPORT jboolean JNICALL FF_FUNC(initSymbols0) sp_avdevice_register_all = (AVDEVICE_REGISTER_ALL) (intptr_t) symbols[i++]; - sp_avresample_alloc_context = (AVRESAMPLE_ALLOC_CONTEXT) (intptr_t) symbols[i++]; - sp_avresample_open = (AVRESAMPLE_OPEN) (intptr_t) symbols[i++]; - sp_avresample_close = (AVRESAMPLE_CLOSE) (intptr_t) symbols[i++]; - sp_avresample_free = (AVRESAMPLE_FREE) (intptr_t) symbols[i++]; - sp_avresample_convert = (AVRESAMPLE_CONVERT) (intptr_t) symbols[i++]; - sp_av_opt_set_sample_fmt = (AV_OPT_SET_SAMPLE_FMT) (intptr_t) symbols[i++]; sp_swr_alloc = (SWR_ALLOC) (intptr_t) symbols[i++]; sp_swr_init = (SWR_INIT) (intptr_t) symbols[i++]; @@ -324,21 +295,23 @@ JNIEXPORT jboolean JNICALL FF_FUNC(initSymbols0) return JNI_FALSE; } - #if LIBAVCODEC_VERSION_MAJOR >= 55 - if(!HAS_FUNC(sp_avcodec_default_get_buffer2) || - !HAS_FUNC(sp_av_frame_unref) ) { - fprintf(stderr, "avcodec >= 55: avcodec_default_get_buffer2 %p, av_frame_unref %p\n", - sp_avcodec_default_get_buffer2, sp_av_frame_unref); - return JNI_FALSE; - } - #else - if(!HAS_FUNC(sp_avcodec_default_get_buffer) || - !HAS_FUNC(sp_avcodec_default_release_buffer)) { - fprintf(stderr, "avcodec < 55: avcodec_default_get_buffer %p, sp_avcodec_default_release_buffer %p\n", - sp_avcodec_default_get_buffer2, sp_avcodec_default_release_buffer); - return JNI_FALSE; - } - #endif + if(!HAS_FUNC(sp_avcodec_default_get_buffer2) || + !HAS_FUNC(sp_av_frame_unref) ) { + fprintf(stderr, "FFMPEGNatives.initSymbols0: avcodec >= 55: avcodec_default_get_buffer2 %p, av_frame_unref %p\n", + sp_avcodec_default_get_buffer2, sp_av_frame_unref); + return JNI_FALSE; + } + +#if LIBAVCODEC_VERSION_MAJOR >= 59 + if( !HAS_FUNC(sp_av_channel_layout_default) || + !HAS_FUNC(sp_av_channel_layout_uninit) || + !HAS_FUNC(sp_av_channel_layout_describe) || + !HAS_FUNC(sp_av_opt_set_chlayout) + ) { + fprintf(stderr, "FFMPEGNatives.initSymbols0: avcodec >= 59: av_channel_layout_* missing\n"); + return JNI_FALSE; + } +#endif #if defined (USE_PTHREAD_LOCKING) pthread_mutexattr_init(&renderLockAttr); @@ -389,25 +362,12 @@ static void _setIsGLOriented(JNIEnv *env, FFMPEGToolBasicAV_t* pAV) { static void freeInstance(JNIEnv *env, FFMPEGToolBasicAV_t* pAV) { int i; if(NULL != pAV) { - // Close the A resampler - if( NULL != pAV->avResampleCtx ) { - sp_avresample_free(&pAV->avResampleCtx); - pAV->avResampleCtx = NULL; - } - if( NULL != pAV->swResampleCtx ) { - sp_swr_free(&pAV->swResampleCtx); - pAV->swResampleCtx = NULL; - } - if( NULL != pAV->aResampleBuffer ) { - sp_av_free(pAV->aResampleBuffer); - pAV->aResampleBuffer = NULL; - } - MY_MUTEX_LOCK(env, mutex_avcodec_openclose); { // Close the V codec if(NULL != pAV->pVCodecCtx) { sp_avcodec_close(pAV->pVCodecCtx); + sp_avcodec_free_context(&pAV->pVCodecCtx); pAV->pVCodecCtx = NULL; } pAV->pVCodec=NULL; @@ -415,20 +375,33 @@ static void freeInstance(JNIEnv *env, FFMPEGToolBasicAV_t* pAV) { // Close the A codec if(NULL != pAV->pACodecCtx) { sp_avcodec_close(pAV->pACodecCtx); + sp_avcodec_free_context(&pAV->pACodecCtx); pAV->pACodecCtx = NULL; } pAV->pACodec=NULL; + + // Close the video file + if(NULL != pAV->pFormatCtx) { + sp_avformat_close_input(&pAV->pFormatCtx); + sp_avformat_free_context(pAV->pFormatCtx); + pAV->pFormatCtx = NULL; + } } MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose); + // Close the A resampler + if( NULL != pAV->swResampleCtx ) { + sp_swr_free(&pAV->swResampleCtx); + pAV->swResampleCtx = NULL; + } + if( NULL != pAV->aResampleBuffer ) { + sp_av_free(pAV->aResampleBuffer); + pAV->aResampleBuffer = NULL; + } + // Close the frames if(NULL != pAV->pVFrame) { - if(HAS_FUNC(sp_avcodec_free_frame)) { - sp_avcodec_free_frame(&pAV->pVFrame); - } else { - sp_av_free(pAV->pVFrame); - } - pAV->pVFrame = NULL; + sp_av_free_frame(&pAV->pVFrame); } if(NULL != pAV->pANIOBuffers) { for(i=0; i<pAV->aFrameCount; i++) { @@ -446,33 +419,27 @@ static void freeInstance(JNIEnv *env, FFMPEGToolBasicAV_t* pAV) { } if(NULL != pAV->pAFrames) { for(i=0; i<pAV->aFrameCount; i++) { - if(HAS_FUNC(sp_avcodec_free_frame)) { - sp_avcodec_free_frame(&pAV->pAFrames[i]); - } else { - sp_av_free(pAV->pAFrames[i]); - } + sp_av_free_frame(&pAV->pAFrames[i]); } free(pAV->pAFrames); pAV->pAFrames = NULL; } - // Close the video file - if(NULL != pAV->pFormatCtx) { - sp_avformat_close_input(&pAV->pFormatCtx); - // Only for output files! - // sp_avformat_free_context(pAV->pFormatCtx); - pAV->pFormatCtx = NULL; - } if( NULL != pAV->ffmpegMediaPlayer ) { (*env)->DeleteGlobalRef(env, pAV->ffmpegMediaPlayer); pAV->ffmpegMediaPlayer = NULL; } + if( NULL != pAV->packet ) { + sp_av_packet_free(&pAV->packet); + pAV->packet = NULL; + } + free(pAV); } } -static int my_getPlaneCount(AVPixFmtDescriptor *pDesc) { +static int my_getPlaneCount(const AVPixFmtDescriptor *pDesc) { int i, p=-1; for(i=pDesc->nb_components-1; i>=0; i--) { int p0 = pDesc->comp[i].plane; @@ -524,9 +491,9 @@ JNIEXPORT jint JNICALL FF_FUNC(getAvCodecMajorVersionCC0) return (jint) LIBAVCODEC_VERSION_MAJOR; } -JNIEXPORT jint JNICALL FF_FUNC(getAvResampleMajorVersionCC0) +JNIEXPORT jint JNICALL FF_FUNC(getAvDeviceMajorVersionCC0) (JNIEnv *env, jobject instance) { - return (jint) LIBAVRESAMPLE_VERSION_MAJOR; + return (jint) LIBAVDEVICE_VERSION_MAJOR; } JNIEXPORT jint JNICALL FF_FUNC(getSwResampleMajorVersionCC0) @@ -535,8 +502,7 @@ JNIEXPORT jint JNICALL FF_FUNC(getSwResampleMajorVersionCC0) } JNIEXPORT jlong JNICALL FF_FUNC(createInstance0) - (JNIEnv *env, jobject instance, jobject ffmpegMediaPlayer, - jboolean enableAvResample, jboolean enableSwResample, jboolean verbose) + (JNIEnv *env, jobject instance, jobject ffmpegMediaPlayer, jboolean verbose) { FFMPEGToolBasicAV_t * pAV = calloc(1, sizeof(FFMPEGToolBasicAV_t)); if(NULL==pAV) { @@ -546,26 +512,23 @@ JNIEXPORT jlong JNICALL FF_FUNC(createInstance0) pAV->avcodecVersion = sp_avcodec_version(); pAV->avformatVersion = sp_avformat_version(); pAV->avutilVersion = sp_avutil_version(); - if(HAS_FUNC(sp_avresample_version) && enableAvResample) { - pAV->avresampleVersion = sp_avresample_version(); + if( HAS_FUNC(sp_avdevice_version) ) { + pAV->avdeviceVersion = sp_avdevice_version(); } else { - pAV->avresampleVersion = 0; + pAV->avdeviceVersion = 0; } - if(HAS_FUNC(sp_swresample_version) && enableSwResample) { + if( HAS_FUNC(sp_swresample_version) ) { pAV->swresampleVersion = sp_swresample_version(); } else { pAV->swresampleVersion = 0; } - #if LIBAVCODEC_VERSION_MAJOR >= 55 - // TODO: We keep code on using 1 a/v frame per decoding cycle now. - // This is compatible w/ OpenAL's alBufferData(..) - // and w/ OpenGL's texture update command, both copy data immediatly. - // pAV->useRefCountedFrames = AV_HAS_API_REFCOUNTED_FRAMES(pAV); - pAV->useRefCountedFrames = 0; - #else - pAV->useRefCountedFrames = 0; - #endif + // NOTE: We keep code on using 1 a/v frame per decoding cycle now. + // This is compatible w/ OpenAL's alBufferData(..) + // and w/ OpenGL's texture update command, both copy data immediately. + // + // NOTE: ffmpeg using `avcodec_receive_frame()` always uses `refcounted_frames`, i.e. always true now! + // pAV->useRefCountedFrames = 1; pAV->ffmpegMediaPlayer = (*env)->NewGlobalRef(env, ffmpegMediaPlayer); pAV->verbose = verbose; @@ -573,8 +536,8 @@ JNIEXPORT jlong JNICALL FF_FUNC(createInstance0) pAV->aid=AV_STREAM_ID_AUTO; if(pAV->verbose) { - fprintf(stderr, "Info: Has avresample %d, swresample %d, device %d, refCount %d\n", - AV_HAS_API_AVRESAMPLE(pAV), AV_HAS_API_SWRESAMPLE(pAV), HAS_FUNC(sp_avdevice_register_all), pAV->useRefCountedFrames); + fprintf(stderr, "Info: Has swresample %d, device %d\n", + AV_HAS_API_SWRESAMPLE(pAV), HAS_FUNC(sp_avdevice_register_all)); } return (jlong) (intptr_t) pAV; } @@ -589,6 +552,7 @@ JNIEXPORT void JNICALL FF_FUNC(destroyInstance0) } } +#if LIBAVCODEC_VERSION_MAJOR < 59 static uint64_t getDefaultAudioChannelLayout(int channelCount) { switch(channelCount) { case 1: return AV_CH_LAYOUT_MONO; @@ -602,6 +566,24 @@ static uint64_t getDefaultAudioChannelLayout(int channelCount) { default: return AV_CH_LAYOUT_NATIVE; } } +#else +static void getDefaultAVChannelLayout(AVChannelLayout* cl, int channelCount) { + sp_av_channel_layout_uninit(cl); + switch(channelCount) { + case 1: *cl = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; break; + case 2: *cl = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; break; + case 3: *cl = (AVChannelLayout)AV_CHANNEL_LAYOUT_SURROUND; break; + case 4: *cl = (AVChannelLayout)AV_CHANNEL_LAYOUT_QUAD; break; + case 5: *cl = (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0; break; + case 6: *cl = (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1; break; + case 7: *cl = (AVChannelLayout)AV_CHANNEL_LAYOUT_6POINT1; break; + case 8: *cl = (AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1; break; + default: { + sp_av_channel_layout_default(cl, channelCount); + } + } +} +#endif static void initPTSStats(PTSStats *ptsStats); static int64_t evalPTS(PTSStats *ptsStats, int64_t inPTS, int64_t inDTS); @@ -675,6 +657,16 @@ static void getAlignedLinesizes(AVCodecContext *avctx, int linesize[/*4*/]) { } #endif +#if LIBAVCODEC_VERSION_MAJOR < 60 +static int64_t getFrameNum(const AVCodecContext *avctx) { + return (int64_t)avctx->frame_number; +} +#else +static int64_t getFrameNum(const AVCodecContext *avctx) { + return avctx->frame_num; +} +#endif + JNIEXPORT void JNICALL FF_FUNC(setStream0) (JNIEnv *env, jobject instance, jlong ptr, jstring jURL, jboolean jIsCameraInput, jint vid, jstring jSizeS, jint vWidth, jint vHeight, jint vRate, @@ -691,16 +683,19 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) } // Register all formats and codecs - sp_avcodec_register_all(); if( jIsCameraInput && HAS_FUNC(sp_avdevice_register_all) ) { sp_avdevice_register_all(); } - sp_av_register_all(); // Network too .. if(HAS_FUNC(sp_avformat_network_init)) { sp_avformat_network_init(); } + pAV->packet = sp_av_packet_alloc(); + if( NULL == pAV->packet ) { + JoglCommon_throwNewRuntimeException(env, "Couldn't allocate AVPacket"); + return; + } pAV->pFormatCtx = sp_avformat_alloc_context(); const char *urlPath = (*env)->GetStringUTFChars(env, jURL, &iscopy); @@ -812,14 +807,14 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) for(i=0; ( AV_STREAM_ID_AUTO==pAV->aid || AV_STREAM_ID_AUTO==pAV->vid ) && i<pAV->pFormatCtx->nb_streams; i++) { AVStream *st = pAV->pFormatCtx->streams[i]; if(pAV->verbose) { - fprintf(stderr, "Stream: %d: is-video %d, is-audio %d\n", i, (AVMEDIA_TYPE_VIDEO == st->codec->codec_type), AVMEDIA_TYPE_AUDIO == st->codec->codec_type); + fprintf(stderr, "Stream: %d: is-video %d, is-audio %d\n", i, (AVMEDIA_TYPE_VIDEO == st->codecpar->codec_type), AVMEDIA_TYPE_AUDIO == st->codecpar->codec_type); } - if(AVMEDIA_TYPE_VIDEO == st->codec->codec_type) { + if(AVMEDIA_TYPE_VIDEO == st->codecpar->codec_type) { if(AV_STREAM_ID_AUTO==pAV->vid && (AV_STREAM_ID_AUTO==vid || vid == i) ) { pAV->pVStream = st; pAV->vid=i; } - } else if(AVMEDIA_TYPE_AUDIO == st->codec->codec_type) { + } else if(AVMEDIA_TYPE_AUDIO == st->codecpar->codec_type) { if(AV_STREAM_ID_AUTO==pAV->aid && (AV_STREAM_ID_AUTO==aid || aid == i) ) { pAV->pAStream = st; pAV->aid=i; @@ -838,7 +833,7 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) } if(0<=pAV->aid) { - AVFrame * pAFrame0 = sp_avcodec_alloc_frame(); + AVFrame * pAFrame0 = sp_av_frame_alloc(); if( NULL == pAFrame0 ) { JoglCommon_throwNewRuntimeException(env, "Couldn't alloc 1st audio frame\n"); return; @@ -846,11 +841,30 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) // Get a pointer to the codec context for the audio stream // FIXME: Libav Binary compatibility! JAU01 - pAV->pACodecCtx=pAV->pAStream->codec; + pAV->pACodecPar=pAV->pAStream->codecpar; // FIXME: Libav Binary compatibility! JAU01 - if (pAV->pACodecCtx->bit_rate) { - pAV->bps_audio = pAV->pACodecCtx->bit_rate; + if (pAV->pACodecPar->bit_rate) { + pAV->bps_audio = pAV->pACodecPar->bit_rate; + } + + // Find the decoder for the audio stream + pAV->pACodec=sp_avcodec_find_decoder(pAV->pACodecPar->codec_id); + if(pAV->pACodec==NULL) { + JoglCommon_throwNewRuntimeException(env, "Couldn't find audio codec for codec_id %d", pAV->pACodecPar->codec_id); + return; + } + + // Allocate the decoder context for the audio stream + pAV->pACodecCtx = sp_avcodec_alloc_context3(pAV->pACodec); + if(pAV->pACodecCtx==NULL) { + JoglCommon_throwNewRuntimeException(env, "Couldn't allocate audio decoder context for codec_id %d", pAV->pACodecPar->codec_id); + return; + } + res = sp_avcodec_parameters_to_context(pAV->pACodecCtx, pAV->pACodecPar); + if(res<0) { + JoglCommon_throwNewRuntimeException(env, "Couldn't copy audio codec-par to context"); + return; } // Customize .. @@ -864,30 +878,13 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) // Note: OpenAL well supports n-channel by now (SOFT), // however - AFAIK AV_SAMPLE_FMT_S16 would allow no conversion! pAV->pACodecCtx->request_sample_fmt=AV_SAMPLE_FMT_S16; - if( 1 <= aMaxChannelCount && aMaxChannelCount <= 2 ) { - pAV->pACodecCtx->request_channel_layout=getDefaultAudioChannelLayout(aMaxChannelCount); - #if LIBAVCODEC_VERSION_MAJOR < 54 - /** Until 55.0.0, but stopped working w/ 54 already :( */ - pAV->pACodecCtx->request_channels=aMaxChannelCount; - #endif - } pAV->pACodecCtx->skip_frame=AVDISCARD_DEFAULT; sp_avcodec_string(pAV->acodec, sizeof(pAV->acodec), pAV->pACodecCtx, 0); - // Find the decoder for the audio stream - pAV->pACodec=sp_avcodec_find_decoder(pAV->pACodecCtx->codec_id); - if(pAV->pACodec==NULL) { - JoglCommon_throwNewRuntimeException(env, "Couldn't find audio codec %d, %s", pAV->pACodecCtx->codec_id, pAV->acodec); - return; - } - // Open codec MY_MUTEX_LOCK(env, mutex_avcodec_openclose); { - #if LIBAVCODEC_VERSION_MAJOR >= 55 - pAV->pACodecCtx->refcounted_frames = pAV->useRefCountedFrames; - #endif res = sp_avcodec_open2(pAV->pACodecCtx, pAV->pACodec, NULL); } MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose); @@ -895,32 +892,44 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) JoglCommon_throwNewRuntimeException(env, "Couldn't open audio codec %d, %s", pAV->pACodecCtx->codec_id, pAV->acodec); return; } - if (!pAV->pACodecCtx->channel_layout) { - pAV->pACodecCtx->channel_layout = getDefaultAudioChannelLayout(pAV->pACodecCtx->channels); + // try to shape audio channel-layout on fixed audio channel-count +#if LIBAVCODEC_VERSION_MAJOR < 59 + pAV->aChannels = pAV->pACodecCtx->channels; + if ( !pAV->pACodecCtx->channel_layout ) { + const uint64_t cl = getDefaultAudioChannelLayout(pAV->aChannels); + if ( !cl ) { + JoglCommon_throwNewRuntimeException(env, "Couldn't determine channel layout of %d channels\n", pAV->aChannels); + return; + } + pAV->pACodecCtx->channel_layout = cl; } - if (!pAV->pACodecCtx->channel_layout) { - JoglCommon_throwNewRuntimeException(env, "Couldn't determine channel layout of %d channels\n", pAV->pACodecCtx->channels); - return; + if( pAV->verbose ) { + fprintf(stderr, "A channels %d, layout 0x%"PRIx64"\n", + pAV->aChannels, pAV->pACodecCtx->channel_layout); + } +#else + pAV->aChannels = pAV->pACodecCtx->ch_layout.nb_channels; + if ( pAV->pACodecCtx->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC ) { + getDefaultAVChannelLayout(&pAV->pACodecCtx->ch_layout, pAV->aChannels); + } + if( pAV->verbose ) { + char buf[256]; + sp_av_channel_layout_describe(&pAV->pACodecCtx->ch_layout, buf, sizeof(buf)); + fprintf(stderr, "A channels %d, layout %s\n", pAV->aChannels, buf); } +#endif pAV->aSampleRate = pAV->pACodecCtx->sample_rate; - pAV->aChannels = pAV->pACodecCtx->channels; pAV->aFrameSize = pAV->pACodecCtx->frame_size; // in samples per channel! pAV->aSampleFmt = pAV->pACodecCtx->sample_fmt; pAV->frames_audio = pAV->pAStream->nb_frames; pAV->aSinkSupport = _isAudioFormatSupported(env, pAV->ffmpegMediaPlayer, pAV->aSampleFmt, pAV->aSampleRate, pAV->aChannels); if( pAV->verbose ) { - fprintf(stderr, "A channels %d [l %"PRId64"], sample_rate %d, frame_size %d, frame_number %d, [afps %f, cfps %f, sfps %f], nb_frames %"PRId64", [maxChan %d, prefRate %d, req_chan_layout %"PRId64", req_chan %d], sink-support %d \n", - pAV->aChannels, pAV->pACodecCtx->channel_layout, pAV->aSampleRate, pAV->aFrameSize, pAV->pACodecCtx->frame_number, + fprintf(stderr, "A sample_rate %d, frame_size %d, frame_number %"PRId64", [afps %f, sfps %f], nb_frames %"PRId64", [maxChan %d, prefRate %d], sink-support %d \n", + pAV->aSampleRate, pAV->aFrameSize, getFrameNum(pAV->pACodecCtx), my_av_q2f(pAV->pAStream->avg_frame_rate), - my_av_q2f_r(pAV->pAStream->codec->time_base), my_av_q2f_r(pAV->pAStream->time_base), pAV->pAStream->nb_frames, - aMaxChannelCount, aPrefSampleRate, pAV->pACodecCtx->request_channel_layout, - #if LIBAVCODEC_VERSION_MAJOR < 54 - pAV->pACodecCtx->request_channels, - #else - 0, - #endif + aMaxChannelCount, aPrefSampleRate, pAV->aSinkSupport); } @@ -929,11 +938,12 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) pAV->aChannelsOut = pAV->aChannels; pAV->aSampleRateOut = pAV->aSampleRate; - if( ( AV_HAS_API_AVRESAMPLE(pAV) || AV_HAS_API_SWRESAMPLE(pAV) ) && + if( ( AV_HAS_API_SWRESAMPLE(pAV) ) && ( pAV->aSampleFmt != AV_SAMPLE_FMT_S16 || ( 0 != aPrefSampleRate && pAV->aSampleRate != aPrefSampleRate ) || - !pAV->aSinkSupport ) ) { - + !pAV->aSinkSupport ) ) + { + const int32_t maxOutChannelCount = MIN_INT(aMaxChannelCount, MAX_INT(1, pAV->aChannels)); if( 0 == aPrefSampleRate ) { aPrefSampleRate = pAV->aSampleRate; } @@ -941,65 +951,64 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) enum AVSampleFormat aSampleFmtOut = AV_SAMPLE_FMT_S16; int32_t aChannelsOut; int32_t aSampleRateOut; - int32_t minChannelCount = MIN_INT(aMaxChannelCount,pAV->pACodecCtx->channels); - if( _isAudioFormatSupported(env, pAV->ffmpegMediaPlayer, aSampleFmtOut, aPrefSampleRate, pAV->pACodecCtx->channels) ) { - aChannelsOut = pAV->pACodecCtx->channels; + if( _isAudioFormatSupported(env, pAV->ffmpegMediaPlayer, aSampleFmtOut, aPrefSampleRate, pAV->aChannels) ) { + aChannelsOut = pAV->aChannels; aSampleRateOut = aPrefSampleRate; aSinkSupport = 1; - } else if( _isAudioFormatSupported(env, pAV->ffmpegMediaPlayer, aSampleFmtOut, aPrefSampleRate, minChannelCount) ) { - aChannelsOut = minChannelCount; + } else if( _isAudioFormatSupported(env, pAV->ffmpegMediaPlayer, aSampleFmtOut, aPrefSampleRate, maxOutChannelCount) ) { + aChannelsOut = maxOutChannelCount; aSampleRateOut = aPrefSampleRate; aSinkSupport = 1; } - if( aSinkSupport ) { - if( AV_HAS_API_AVRESAMPLE(pAV) ) { - pAV->avResampleCtx = sp_avresample_alloc_context(); - sp_av_opt_set_int(pAV->avResampleCtx, "in_channel_layout", pAV->pACodecCtx->channel_layout, 0); - sp_av_opt_set_int(pAV->avResampleCtx, "out_channel_layout", getDefaultAudioChannelLayout(aChannelsOut), 0); - sp_av_opt_set_int(pAV->avResampleCtx, "in_sample_rate", pAV->aSampleRate, 0); - sp_av_opt_set_int(pAV->avResampleCtx, "out_sample_rate", aSampleRateOut, 0); - sp_av_opt_set_int(pAV->avResampleCtx, "in_sample_fmt", pAV->aSampleFmt, 0); - sp_av_opt_set_int(pAV->avResampleCtx, "out_sample_fmt", aSampleFmtOut, 0); - - if ( sp_avresample_open(pAV->avResampleCtx) < 0 ) { - sp_avresample_free(&pAV->avResampleCtx); - pAV->avResampleCtx = NULL; - fprintf(stderr, "error initializing avresample ctx\n"); - } else { - // OK - pAV->aSampleFmtOut = aSampleFmtOut; - pAV->aChannelsOut = aChannelsOut; - pAV->aSampleRateOut = aSampleRateOut; - pAV->aSinkSupport = 1; - } - } else if( AV_HAS_API_SWRESAMPLE(pAV) ) { - pAV->swResampleCtx = sp_swr_alloc(); - sp_av_opt_set_int(pAV->swResampleCtx, "in_channel_layout", pAV->pACodecCtx->channel_layout, 0); - sp_av_opt_set_int(pAV->swResampleCtx, "out_channel_layout", getDefaultAudioChannelLayout(aChannelsOut), 0); - sp_av_opt_set_int(pAV->swResampleCtx, "in_sample_rate", pAV->aSampleRate, 0); - sp_av_opt_set_int(pAV->swResampleCtx, "out_sample_rate", aSampleRateOut, 0); - sp_av_opt_set_sample_fmt(pAV->swResampleCtx, "in_sample_fmt", pAV->aSampleFmt, 0); - sp_av_opt_set_sample_fmt(pAV->swResampleCtx, "out_sample_fmt", aSampleFmtOut, 0); - - if ( sp_swr_init(pAV->swResampleCtx) < 0 ) { - sp_swr_free(&pAV->swResampleCtx); - pAV->swResampleCtx = NULL; - fprintf(stderr, "error initializing swresample ctx\n"); - } else { - // OK - pAV->aSampleFmtOut = aSampleFmtOut; - pAV->aChannelsOut = aChannelsOut; - pAV->aSampleRateOut = aSampleRateOut; - pAV->aSinkSupport = 1; - } + if( aSinkSupport && AV_HAS_API_SWRESAMPLE(pAV) ) { + pAV->swResampleCtx = sp_swr_alloc(); +#if LIBAVCODEC_VERSION_MAJOR < 59 + const int64_t out_channel_layout = getDefaultAudioChannelLayout(aChannelsOut); + sp_av_opt_set_int(pAV->swResampleCtx, "in_channel_layout", pAV->pACodecCtx->channel_layout, 0); + sp_av_opt_set_int(pAV->swResampleCtx, "out_channel_layout", out_channel_layout, 0); + if( pAV->verbose ) { + fprintf(stderr, "A Resample: channels %d -> %d, layout 0x%"PRIx64" -> 0x%"PRIx64", rate %d -> %d, fmt 0x%x -> 0x%x\n", + pAV->aChannels, aChannelsOut, pAV->pACodecCtx->channel_layout, out_channel_layout, + pAV->aSampleRate, aSampleRateOut, (int)pAV->aSampleFmt, (int)aSampleFmtOut); + } +#else + AVChannelLayout out_ch_layout = {0}; + getDefaultAVChannelLayout(&out_ch_layout, aChannelsOut); + sp_av_opt_set_chlayout(pAV->swResampleCtx, "in_chlayout", &pAV->pACodecCtx->ch_layout, 0); + sp_av_opt_set_chlayout(pAV->swResampleCtx, "out_chlayout", &out_ch_layout, 0); + if( pAV->verbose ) { + char buf1[256], buf2[256]; + sp_av_channel_layout_describe(&pAV->pACodecCtx->ch_layout, buf1, sizeof(buf1)); + sp_av_channel_layout_describe(&out_ch_layout, buf2, sizeof(buf2)); + fprintf(stderr, "A Resample: channels %d -> %d, layout %s -> %s, rate %d -> %d, fmt 0x%x -> 0x%x\n", + pAV->aChannels, aChannelsOut, buf1, buf2, + pAV->aSampleRate, aSampleRateOut, (int)pAV->aSampleFmt, (int)aSampleFmtOut); + } + av_channel_layout_uninit(&out_ch_layout); +#endif + sp_av_opt_set_int(pAV->swResampleCtx, "in_sample_rate", pAV->aSampleRate, 0); + sp_av_opt_set_int(pAV->swResampleCtx, "out_sample_rate", aSampleRateOut, 0); + sp_av_opt_set_sample_fmt(pAV->swResampleCtx, "in_sample_fmt", pAV->aSampleFmt, 0); + sp_av_opt_set_sample_fmt(pAV->swResampleCtx, "out_sample_fmt", aSampleFmtOut, 0); + + if ( sp_swr_init(pAV->swResampleCtx) < 0 ) { + sp_swr_free(&pAV->swResampleCtx); + pAV->swResampleCtx = NULL; + fprintf(stderr, "error initializing swresample ctx\n"); + } else { + // OK + pAV->aSampleFmtOut = aSampleFmtOut; + pAV->aChannelsOut = aChannelsOut; + pAV->aSampleRateOut = aSampleRateOut; + pAV->aSinkSupport = 1; } } } if(pAV->verbose) { - fprintf(stderr, "Info: Need resample %d, Use avresample %d, swresample %d\n", - pAV->aSinkSupport, NULL!=pAV->avResampleCtx, NULL!=pAV->swResampleCtx); + fprintf(stderr, "Info: Need resample %d, Use swresample %d\n", + pAV->aSinkSupport, NULL!=pAV->swResampleCtx); } // Allocate audio frames @@ -1009,7 +1018,7 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) pAV->pAFrames = calloc(pAV->aFrameCount, sizeof(AVFrame*)); pAV->pAFrames[0] = pAFrame0; for(i=1; i<pAV->aFrameCount; i++) { - pAV->pAFrames[i] = sp_avcodec_alloc_frame(); + pAV->pAFrames[i] = sp_av_frame_alloc(); if( NULL == pAV->pAFrames[i] ) { JoglCommon_throwNewRuntimeException(env, "Couldn't alloc audio frame %d / %d", i, pAV->aFrameCount); return; @@ -1021,16 +1030,34 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) if(0<=pAV->vid) { // Get a pointer to the codec context for the video stream // FIXME: Libav Binary compatibility! JAU01 - pAV->pVCodecCtx=pAV->pVStream->codec; + pAV->pVCodecPar = pAV->pVStream->codecpar; #if 0 pAV->pVCodecCtx->get_format = my_get_format; #endif - if (pAV->pVCodecCtx->bit_rate) { + if (pAV->pVCodecPar->bit_rate) { // FIXME: Libav Binary compatibility! JAU01 - pAV->bps_video = pAV->pVCodecCtx->bit_rate; + pAV->bps_video = pAV->pVCodecPar->bit_rate; + } + + // Find the decoder for the video stream + pAV->pVCodec=sp_avcodec_find_decoder(pAV->pVCodecPar->codec_id); + if(pAV->pVCodec==NULL) { + JoglCommon_throwNewRuntimeException(env, "Couldn't find video codec for codec_id %d", pAV->pVCodecPar->codec_id); + return; } + // Allocate the decoder context for the video stream + pAV->pVCodecCtx = sp_avcodec_alloc_context3(pAV->pVCodec); + if(pAV->pVCodecCtx==NULL) { + JoglCommon_throwNewRuntimeException(env, "Couldn't allocate video decoder context for codec_id %d", pAV->pVCodecPar->codec_id); + return; + } + res = sp_avcodec_parameters_to_context(pAV->pVCodecCtx, pAV->pVCodecPar); + if(res<0) { + JoglCommon_throwNewRuntimeException(env, "Couldn't copy video codec-par to context"); + return; + } // Customize .. // pAV->pVCodecCtx->thread_count=2; // pAV->pVCodecCtx->thread_type=FF_THREAD_FRAME|FF_THREAD_SLICE; // Decode more than one frame at once @@ -1041,19 +1068,9 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) sp_avcodec_string(pAV->vcodec, sizeof(pAV->vcodec), pAV->pVCodecCtx, 0); - // Find the decoder for the video stream - pAV->pVCodec=sp_avcodec_find_decoder(pAV->pVCodecCtx->codec_id); - if(pAV->pVCodec==NULL) { - JoglCommon_throwNewRuntimeException(env, "Couldn't find video codec %d, %s", pAV->pVCodecCtx->codec_id, pAV->vcodec); - return; - } - // Open codec MY_MUTEX_LOCK(env, mutex_avcodec_openclose); { - #if LIBAVCODEC_VERSION_MAJOR >= 55 - pAV->pVCodecCtx->refcounted_frames = pAV->useRefCountedFrames; - #endif res = sp_avcodec_open2(pAV->pVCodecCtx, pAV->pVCodec, NULL); } MY_MUTEX_UNLOCK(env, mutex_avcodec_openclose); @@ -1070,12 +1087,6 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) // FIXME: Libav Binary compatibility! JAU01 if( pAV->pVStream->avg_frame_rate.den && pAV->pVStream->avg_frame_rate.num ) { pAV->fps = my_av_q2f(pAV->pVStream->avg_frame_rate); - #if LIBAVCODEC_VERSION_MAJOR < 55 - } else if( pAV->pVStream->r_frame_rate.den && pAV->pVStream->r_frame_rate.num ) { - pAV->fps = my_av_q2f(pAV->pVStream->r_frame_rate); - #endif - } else if( pAV->pVStream->codec->time_base.den && pAV->pVStream->codec->time_base.num ) { - pAV->fps = my_av_q2f_r(pAV->pVStream->codec->time_base); } else if( pAV->pVStream->time_base.den && pAV->pVStream->time_base.num ) { pAV->fps = my_av_q2f_r(pAV->pVStream->time_base); } else { @@ -1087,31 +1098,30 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) // FIXME: Libav Binary compatibility! JAU01 pAV->vWidth = pAV->pVCodecCtx->width; pAV->vHeight = pAV->pVCodecCtx->height; - pAV->vPixFmt = pAV->pVCodecCtx->pix_fmt; + pAV->vPixFmt = pAV->pVCodecCtx->pix_fmt; // AV_PIX_FMT_NONE pAV->vFlipped = JNI_FALSE; { - AVPixFmtDescriptor pixDesc = sp_av_pix_fmt_descriptors[pAV->vPixFmt]; - pAV->vBitsPerPixel = sp_av_get_bits_per_pixel(&pixDesc); - pAV->vBufferPlanes = my_getPlaneCount(&pixDesc); + const AVPixFmtDescriptor* pixDesc = sp_av_pix_fmt_desc_get(pAV->vPixFmt); + if( NULL != pixDesc ) { + pAV->vBitsPerPixel = sp_av_get_bits_per_pixel(pixDesc); + pAV->vBufferPlanes = my_getPlaneCount(pixDesc); + } else { + JoglCommon_throwNewRuntimeException(env, "Couldn't query AVPixFmtDescriptor from v-ctx pix_fmt 0x%x", (int)pAV->vPixFmt); + return; + } } if( pAV->verbose ) { - fprintf(stderr, "V frame_size %d, frame_number %d, [afps %f, rfps %f, cfps %f, sfps %f] -> %f fps, nb_frames %"PRId64", size %dx%d, fmt 0x%X, bpp %d, planes %d, codecCaps 0x%X\n", - pAV->pVCodecCtx->frame_size, pAV->pVCodecCtx->frame_number, + fprintf(stderr, "V frame_size %d, frame_number %"PRId64", [afps %f, sfps %f] -> %f fps, nb_frames %"PRId64", size %dx%d, fmt 0x%X, bpp %d, planes %d, codecCaps 0x%X\n", + pAV->pVCodecCtx->frame_size, getFrameNum(pAV->pVCodecCtx), my_av_q2f(pAV->pVStream->avg_frame_rate), - #if LIBAVCODEC_VERSION_MAJOR < 55 - my_av_q2f(pAV->pVStream->r_frame_rate), - #else - 0.0f, - #endif - my_av_q2f_r(pAV->pVStream->codec->time_base), my_av_q2f_r(pAV->pVStream->time_base), pAV->fps, pAV->pVStream->nb_frames, pAV->vWidth, pAV->vHeight, pAV->vPixFmt, pAV->vBitsPerPixel, pAV->vBufferPlanes, pAV->pVCodecCtx->codec->capabilities); } - pAV->pVFrame=sp_avcodec_alloc_frame(); + pAV->pVFrame=sp_av_frame_alloc(); if( pAV->pVFrame == NULL ) { JoglCommon_throwNewRuntimeException(env, "Couldn't alloc video frame"); return; @@ -1120,11 +1130,7 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) pAV->pVFrame->width = pAV->pVCodecCtx->width; pAV->pVFrame->height = pAV->pVCodecCtx->height; pAV->pVFrame->format = pAV->pVCodecCtx->pix_fmt; - #if LIBAVCODEC_VERSION_MAJOR >= 55 - res = sp_avcodec_default_get_buffer2(pAV->pVCodecCtx, pAV->pVFrame, 0); - #else - res = sp_avcodec_default_get_buffer(pAV->pVCodecCtx, pAV->pVFrame); - #endif + res = sp_avcodec_default_get_buffer2(pAV->pVCodecCtx, pAV->pVFrame, 0); if(0!=res) { JoglCommon_throwNewRuntimeException(env, "Couldn't peek video buffer dimension"); return; @@ -1138,23 +1144,15 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) } int32_t vLinesize[4]; if( pAV->vBufferPlanes > 1 ) { - #if 0 - getAlignedLinesizes(pAV->pVCodecCtx, vLinesize); - for(i=0; i<pAV->vBufferPlanes; i++) { - // FIXME: Libav Binary compatibility! JAU01 - pAV->vTexWidth[i] = vLinesize[i] / pAV->vBytesPerPixelPerPlane ; - } - #else - for(i=0; i<pAV->vBufferPlanes; i++) { - // FIXME: Libav Binary compatibility! JAU01 - vLinesize[i] = pAV->pVFrame->linesize[i]; - pAV->vTexWidth[i] = vLinesize[i] / pAV->vBytesPerPixelPerPlane ; - } - #endif + for(i=0; i<pAV->vBufferPlanes; i++) { + // FIXME: Libav Binary compatibility! JAU01 + vLinesize[i] = pAV->pVFrame->linesize[i]; + pAV->vTexWidth[i] = vLinesize[i] / pAV->vBytesPerPixelPerPlane ; + } } else { vLinesize[0] = pAV->pVFrame->linesize[0]; - if( pAV->vPixFmt == PIX_FMT_YUYV422 || - pAV->vPixFmt == PIX_FMT_UYVY422 ) + if( pAV->vPixFmt == AV_PIX_FMT_YUYV422 || + pAV->vPixFmt == AV_PIX_FMT_UYVY422 ) { // Stuff 2x 16bpp (YUYV, UYVY) into one RGBA pixel! pAV->vTexWidth[0] = pAV->pVCodecCtx->width / 2; @@ -1168,11 +1166,7 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) } } } - #if LIBAVCODEC_VERSION_MAJOR >= 55 - sp_av_frame_unref(pAV->pVFrame); - #else - sp_avcodec_default_release_buffer(pAV->pVCodecCtx, pAV->pVFrame); - #endif + sp_av_frame_unref(pAV->pVFrame); } pAV->vPTS=0; pAV->aPTS=0; @@ -1204,18 +1198,11 @@ JNIEXPORT jint JNICALL FF_FUNC(readNextPacket0) { FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr)); - AVPacket packet; jint resPTS = INVALID_PTS; uint8_t * pkt_odata; int pkt_osize; - packet.data = NULL; // minimum - packet.size = 0; // requirement - sp_av_init_packet(&packet); - - const int avRes = sp_av_read_frame(pAV->pFormatCtx, &packet); - pkt_odata = packet.data; - pkt_osize = packet.size; + const int avRes = sp_av_read_frame(pAV->pFormatCtx, pAV->packet); if( AVERROR_EOF == avRes || ( pAV->pFormatCtx->pb && pAV->pFormatCtx->pb->eof_reached ) ) { if( pAV->verbose ) { fprintf(stderr, "EOS: avRes[res %d, eos %d], pb-EOS %d\n", @@ -1225,44 +1212,64 @@ JNIEXPORT jint JNICALL FF_FUNC(readNextPacket0) resPTS = END_OF_STREAM_PTS; } else if( 0 <= avRes ) { if( pAV->verbose ) { - fprintf(stderr, "P: ptr %p, size %d\n", packet.data, packet.size); + fprintf(stderr, "P: ptr %p, size %d\n", pAV->packet->data, pAV->packet->size); } - if(packet.stream_index==pAV->aid) { + int send_pkt = 1; // only send pkt once + if(pAV->packet->stream_index==pAV->aid) { // Decode audio frame if(NULL == pAV->pAFrames) { // no audio registered - sp_av_free_packet(&packet); + sp_av_packet_unref(pAV->packet); return INVALID_PTS; } - int frameCount; - int flush_complete = 0; - for ( frameCount=0; 0 < packet.size || 0 == frameCount; frameCount++ ) { - int frameDecoded; - int len1; + int res = 0; + for (int frameCount=0; 0 <= res || 0 == frameCount; ++frameCount) { AVFrame* pAFrameCurrent = pAV->pAFrames[pAV->aFrameCurrent]; - if( pAV->useRefCountedFrames ) { - sp_av_frame_unref(pAFrameCurrent); - pAV->aFrameCurrent = ( pAV->aFrameCurrent + 1 ) % pAV->aFrameCount ; - } - sp_avcodec_get_frame_defaults(pAFrameCurrent); - - if (flush_complete) { - break; - } - len1 = sp_avcodec_decode_audio4(pAV->pACodecCtx, pAFrameCurrent, &frameDecoded, &packet); - if (len1 < 0) { - // if error, we skip the frame - packet.size = 0; - break; + sp_av_frame_unref(pAFrameCurrent); + pAV->aFrameCurrent = ( pAV->aFrameCurrent + 1 ) % pAV->aFrameCount ; + + if( 0 < send_pkt ) { // only send pkt once + send_pkt = 0; + res = sp_avcodec_send_packet(pAV->pACodecCtx, pAV->packet); + if ( AVERROR(EAGAIN) == res ) { + // input is not accepted in the current state - user must read output + res = 0; // continue draining frames + if( pAV->verbose ) { + fprintf(stderr, "A-P: EAGAIN @ %d\n", frameCount); + } + } else if ( AVERROR_EOF == res ) { + // the decoder has been flushed, and no new packets can be sent to it + res = 0; // continue draining frames + if( pAV->verbose ) { + fprintf(stderr, "A-P: EOF @ %d\n", frameCount); + } + } else if ( 0 > res ) { + res = 0; // error, but continue draining frames + res = 0; // continue draining frames + if( pAV->verbose ) { + fprintf(stderr, "A-P: ERROR %d @ %d\n", res, frameCount); + } + } } - packet.data += len1; - packet.size -= len1; - - if (!frameDecoded) { - // stop sending empty packets if the decoder is finished - if (!packet.data && pAV->pACodecCtx->codec->capabilities & CODEC_CAP_DELAY) { - flush_complete = 1; + res = sp_avcodec_receive_frame(pAV->pACodecCtx, pAFrameCurrent); + if( 0 > res ) { + if ( AVERROR(EAGAIN) == res ) { + // output is not available in this state - user must try to send new input + res = 0; + if( 0 == frameCount && pAV->verbose ) { + fprintf(stderr, "A-F: EAGAIN @ %d\n", frameCount); // drained at start + } // else expected to be drained + } else if ( AVERROR_EOF == res ) { + // the decoder has been fully flushed + res = 0; + if( pAV->verbose ) { + fprintf(stderr, "A-F: EOF @ %d\n", frameCount); + } + } else { + if( pAV->verbose ) { + fprintf(stderr, "A-F: ERROR %d @ %d\n", res, frameCount); + } } - continue; + break; // end loop } int32_t data_size = 0; @@ -1279,7 +1286,7 @@ JNIEXPORT jint JNICALL FF_FUNC(readNextPacket0) #endif const AVRational time_base = pAV->pAStream->time_base; - const int64_t pkt_pts = pAFrameCurrent->pkt_pts; + const int64_t pkt_pts = pAFrameCurrent->pts; if( 0 == frameCount && AV_NOPTS_VALUE != pkt_pts ) { // 1st frame only, discard invalid PTS .. pAV->aPTS = my_av_q2i32( pkt_pts * 1000, time_base); } else { // subsequent frames or invalid PTS .. @@ -1289,14 +1296,14 @@ JNIEXPORT jint JNICALL FF_FUNC(readNextPacket0) if( pAV->verbose ) { int32_t aDTS = my_av_q2i32( pAFrameCurrent->pkt_dts * 1000, time_base); - fprintf(stderr, "A pts %d [pkt_pts %"PRId64"], dts %d [pkt_dts %"PRId64"], f# %d, aFrame %d/%d %p, dataPtr %p, dataSize %d\n", + fprintf(stderr, "A pts %d [pkt_pts %"PRId64"], dts %d [pkt_dts %"PRId64"], f# %d, aFrame %d/%d %p, dataPtr %p, dataSize %d\n", pAV->aPTS, pkt_pts, aDTS, pAFrameCurrent->pkt_dts, frameCount, pAV->aFrameCurrent, pAV->aFrameCount, pAFrameCurrent, pAFrameCurrent->data[0], data_size); } if( NULL != env ) { void* data_ptr = pAFrameCurrent->data[0]; // default - if( NULL != pAV->avResampleCtx || NULL != pAV->swResampleCtx ) { + if( NULL != pAV->swResampleCtx ) { uint8_t *tmp_out; int out_samples=-1, out_size, out_linesize; int osize = sp_av_get_bytes_per_sample( pAV->aSampleFmtOut ); @@ -1314,14 +1321,7 @@ JNIEXPORT jint JNICALL FF_FUNC(readNextPacket0) } pAV->aResampleBuffer = tmp_out; - if( NULL != pAV->avResampleCtx ) { - out_samples = sp_avresample_convert(pAV->avResampleCtx, - &pAV->aResampleBuffer, - out_linesize, nb_samples, - pAFrameCurrent->data, - pAFrameCurrent->linesize[0], - pAFrameCurrent->nb_samples); - } else if( NULL != pAV->swResampleCtx ) { + if( NULL != pAV->swResampleCtx ) { out_samples = sp_swr_convert(pAV->swResampleCtx, &pAV->aResampleBuffer, nb_samples, (const uint8_t **)pAFrameCurrent->data, pAFrameCurrent->nb_samples); @@ -1357,41 +1357,63 @@ JNIEXPORT jint JNICALL FF_FUNC(readNextPacket0) (*env)->CallVoidMethod(env, pAV->ffmpegMediaPlayer, ffmpeg_jni_mid_pushSound, pNIOBufferCurrent->nioRef, data_size, pAV->aPTS); } } - } else if(packet.stream_index==pAV->vid) { + } else if(pAV->packet->stream_index==pAV->vid) { // Decode video frame if(NULL == pAV->pVFrame) { - sp_av_free_packet(&packet); + sp_av_packet_unref(pAV->packet); return INVALID_PTS; } - int frameCount; - int flush_complete = 0; - for ( frameCount=0; 0 < packet.size || 0 == frameCount; frameCount++ ) { - int frameDecoded; - int len1; - sp_avcodec_get_frame_defaults(pAV->pVFrame); - if (flush_complete) { - break; - } - len1 = sp_avcodec_decode_video2(pAV->pVCodecCtx, pAV->pVFrame, &frameDecoded, &packet); - if (len1 < 0) { - // if error, we skip the frame - packet.size = 0; - break; + int res = 0; + for (int frameCount=0; 0 <= res || 0 == frameCount; ++frameCount) { + sp_av_frame_unref(pAV->pVFrame); + + if( 0 < send_pkt ) { // only send pkt once + send_pkt = 0; + res = sp_avcodec_send_packet(pAV->pVCodecCtx, pAV->packet); + if ( AVERROR(EAGAIN) == res ) { + // input is not accepted in the current state - user must read output + res = 0; // continue draining frames + if( pAV->verbose ) { + fprintf(stderr, "V-P: EAGAIN @ %d\n", frameCount); + } + } else if ( AVERROR_EOF == res ) { + // the decoder has been flushed, and no new packets can be sent to it + res = 0; // continue draining frames + if( pAV->verbose ) { + fprintf(stderr, "V-P: EOF @ %d\n", frameCount); + } + } else if ( 0 > res ) { + res = 0; // error, but continue draining frames + if( pAV->verbose ) { + fprintf(stderr, "V-P: ERROR %d @ %d\n", res, frameCount); + } + } } - packet.data += len1; - packet.size -= len1; - - if (!frameDecoded) { - // stop sending empty packets if the decoder is finished - if (!packet.data && pAV->pVCodecCtx->codec->capabilities & CODEC_CAP_DELAY) { - flush_complete = 1; + res = sp_avcodec_receive_frame(pAV->pVCodecCtx, pAV->pVFrame); + if( 0 > res ) { + if ( AVERROR(EAGAIN) == res ) { + // output is not available in this state - user must try to send new input + res = 0; + if( 0 == frameCount && pAV->verbose ) { + fprintf(stderr, "V-F: EAGAIN @ %d\n", frameCount); // drained at start + } // else expected to be drained + } else if ( AVERROR_EOF == res ) { + // the decoder has been fully flushed + res = 0; + if( pAV->verbose ) { + fprintf(stderr, "V-F: EOF @ %d\n", frameCount); + } + } else { + if( pAV->verbose ) { + fprintf(stderr, "V-F: ERROR %d @ %d\n", res, frameCount); + } } - continue; + break; // end loop } // FIXME: Libav Binary compatibility! JAU01 const AVRational time_base = pAV->pVStream->time_base; - const int64_t pkt_pts = pAV->pVFrame->pkt_pts; + const int64_t pkt_pts = pAV->pVFrame->pts; const int64_t pkt_dts = pAV->pVFrame->pkt_dts; const int64_t fix_pts = evalPTS(&pAV->vPTSStats, pkt_pts, pkt_dts); if( AV_NOPTS_VALUE != fix_pts ) { // discard invalid PTS .. @@ -1409,17 +1431,15 @@ JNIEXPORT jint JNICALL FF_FUNC(readNextPacket0) const char * warn = frame_repeat_i > 0 ? "REPEAT" : "NORMAL" ; - fprintf(stderr, "V fix_pts %d, pts %d [pkt_pts %"PRId64"], dts %d [pkt_dts %"PRId64"], time d(%lf s + r %lf = %lf s), i(%d ms + r %d = %d ms) - %s - f# %d, dec %d, data %p, lsz %d\n", + fprintf(stderr, "V fix_pts %d, pts %d [pkt_pts %"PRId64"], dts %d [pkt_dts %"PRId64"], time d(%lf s + r %lf = %lf s), i(%d ms + r %d = %d ms) - %s - f# %d, data %p, lsz %d\n", pAV->vPTS, vPTS, pkt_pts, vDTS, pkt_dts, frame_delay_d, frame_repeat_d, (frame_delay_d + frame_repeat_d), frame_delay_i, frame_repeat_i, (frame_delay_i + frame_repeat_i), warn, frameCount, - len1, pAV->pVFrame->data[0], pAV->pVFrame->linesize[0]); + pAV->pVFrame->data[0], pAV->pVFrame->linesize[0]); // fflush(NULL); } if( 0 == pAV->pVFrame->linesize[0] ) { - if( pAV->useRefCountedFrames ) { - sp_av_frame_unref(pAV->pVFrame); - } + sp_av_frame_unref(pAV->pVFrame); continue; } resPTS = pAV->vPTS; // Video Frame! @@ -1458,7 +1478,7 @@ JNIEXPORT jint JNICALL FF_FUNC(readNextPacket0) texFmt, texType, pAV->pVFrame->data[0] + p_offset[0]); DBG_TEXSUBIMG2D_b(pAV); - if( pAV->vPixFmt == PIX_FMT_YUV420P || pAV->vPixFmt == PIX_FMT_YUVJ420P ) { + if( pAV->vPixFmt == AV_PIX_FMT_YUV420P || pAV->vPixFmt == AV_PIX_FMT_YUVJ420P ) { // U plane // FIXME: Libav Binary compatibility! JAU01 DBG_TEXSUBIMG2D_a('U',pAV,1,1,2,1); @@ -1475,7 +1495,7 @@ JNIEXPORT jint JNICALL FF_FUNC(readNextPacket0) pAV->vTexWidth[2], pAV->pVCodecCtx->height/2, texFmt, texType, pAV->pVFrame->data[2] + p_offset[2]); DBG_TEXSUBIMG2D_b(pAV); - } else if( pAV->vPixFmt == PIX_FMT_YUV422P || pAV->vPixFmt == PIX_FMT_YUVJ422P ) { + } else if( pAV->vPixFmt == AV_PIX_FMT_YUV422P || pAV->vPixFmt == AV_PIX_FMT_YUVJ422P ) { // U plane // FIXME: Libav Binary compatibility! JAU01 DBG_TEXSUBIMG2D_a('U',pAV,1,1,1,1); @@ -1496,15 +1516,11 @@ JNIEXPORT jint JNICALL FF_FUNC(readNextPacket0) pAV->procAddrGLFinish(); //pAV->procAddrGLFlush(); - if( pAV->useRefCountedFrames ) { - sp_av_frame_unref(pAV->pVFrame); - } + sp_av_frame_unref(pAV->pVFrame); } } // restore orig pointer and size values, we may have moved along within packet - packet.data = pkt_odata; - packet.size = pkt_osize; - sp_av_free_packet(&packet); + sp_av_packet_unref(pAV->packet); } return resPTS; } @@ -1560,12 +1576,12 @@ JNIEXPORT jint JNICALL FF_FUNC(seek0) pos0 = pAV->vPTS; streamID = pAV->vid; time_base = pAV->pVStream->time_base; - pts0 = pAV->pVFrame->pkt_pts; + pts0 = pAV->pVFrame->pts; } else if( pAV->aid >= 0 ) { pos0 = pAV->aPTS; streamID = pAV->aid; time_base = pAV->pAStream->time_base; - pts0 = pAV->pAFrames[pAV->aFrameCurrent]->pkt_pts; + pts0 = pAV->pAFrames[pAV->aFrameCurrent]->pts; } else { return pAV->vPTS; } @@ -1600,7 +1616,7 @@ JNIEXPORT jint JNICALL FF_FUNC(seek0) if(NULL != pAV->pACodecCtx) { sp_avcodec_flush_buffers( pAV->pACodecCtx ); } - const jint rPTS = my_av_q2i32( ( pAV->vid >= 0 ? pAV->pVFrame->pkt_pts : pAV->pAFrames[pAV->aFrameCurrent]->pkt_pts ) * 1000, time_base); + const jint rPTS = my_av_q2i32( ( pAV->vid >= 0 ? pAV->pVFrame->pts : pAV->pAFrames[pAV->aFrameCurrent]->pts ) * 1000, time_base); if(pAV->verbose) { fprintf(stderr, "SEEK: post : res %d, u %d\n", res, rPTS); } diff --git a/src/jogl/native/libav/ffmpeg_lavc56_lavf56_lavu54_lavr02.c b/src/jogl/native/libav/ffmpeg_lavc56_lavf56_lavu54_lavr02.c deleted file mode 100644 index d1657d0c6..000000000 --- a/src/jogl/native/libav/ffmpeg_lavc56_lavf56_lavu54_lavr02.c +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright 2013 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -#include "jogamp_opengl_util_av_impl_FFMPEGv11Natives.h" - -#define FF_FUNC(METHOD) Java_jogamp_opengl_util_av_impl_FFMPEGv11Natives_ ## METHOD - -#include "ffmpeg_impl_template.c" diff --git a/src/jogl/native/libav/ffmpeg_tool.h b/src/jogl/native/libav/ffmpeg_tool.h index 136be2ecc..dd39146e6 100644 --- a/src/jogl/native/libav/ffmpeg_tool.h +++ b/src/jogl/native/libav/ffmpeg_tool.h @@ -43,17 +43,12 @@ #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" +#include "libavdevice/avdevice.h" #include "libavutil/avutil.h" -#if LIBAVCODEC_VERSION_MAJOR >= 54 - #include "libavresample/avresample.h" - #include "libswresample/swresample.h" -#endif +#include "libavutil/pixdesc.h" +#include "libavutil/samplefmt.h" +#include "libswresample/swresample.h" -#ifndef LIBAVRESAMPLE_VERSION_MAJOR -#define LIBAVRESAMPLE_VERSION_MAJOR -1 -// Opaque -typedef void* AVAudioResampleContext; -#endif #ifndef LIBSWRESAMPLE_VERSION_MAJOR #define LIBSWRESAMPLE_VERSION_MAJOR -1 // Opaque @@ -76,9 +71,15 @@ typedef void (APIENTRYP PFNGLFINISH) (void); */ #define AV_TIME_BASE_MSEC (AV_TIME_BASE/1000) +#ifndef AV_VERSION_MAJOR #define AV_VERSION_MAJOR(i) ( ( i >> 16 ) & 0xFF ) +#endif +#ifndef AV_VERSION_MINOR #define AV_VERSION_MINOR(i) ( ( i >> 8 ) & 0xFF ) +#endif +#ifndef AV_VERSION_SUB #define AV_VERSION_SUB(i) ( ( i >> 0 ) & 0xFF ) +#endif /** Sync w/ GLMediaPlayer.STREAM_ID_NONE */ #define AV_STREAM_ID_NONE -2 @@ -95,9 +96,6 @@ typedef void (APIENTRYP PFNGLFINISH) (void); /** Constant PTS marking the end of the stream, i.e. Integer.MIN_VALUE - 1 == 0x7FFFFFFF == {@value}. Sync w/ TimeFrameI.END_OF_STREAM_PTS */ #define END_OF_STREAM_PTS 0x7FFFFFFF -/** Since 54.0.0.1 */ -#define AV_HAS_API_AVRESAMPLE(pAV) ( ( LIBAVRESAMPLE_VERSION_MAJOR >= 0 ) && ( pAV->avresampleVersion != 0 ) ) - /** Since 55.0.0.1 */ #define AV_HAS_API_SWRESAMPLE(pAV) ( ( LIBSWRESAMPLE_VERSION_MAJOR >= 0 ) && ( pAV->swresampleVersion != 0 ) ) @@ -117,6 +115,12 @@ static inline int my_align(int v, int a){ return ( v + a - 1 ) & ~( a - 1 ); } +#if LIBAVCODEC_VERSION_MAJOR < 59 + typedef void* AVChannelLayoutPtr; +#else + typedef AVChannelLayout* AVChannelLayoutPtr; +#endif + typedef struct { void *origPtr; jobject nioRef; @@ -137,26 +141,26 @@ typedef struct { uint32_t avcodecVersion; uint32_t avformatVersion; uint32_t avutilVersion; - uint32_t avresampleVersion; + uint32_t avdeviceVersion; uint32_t swresampleVersion; - int32_t useRefCountedFrames; - PFNGLTEXSUBIMAGE2DPROC procAddrGLTexSubImage2D; PFNGLGETERRORPROC procAddrGLGetError; PFNGLFLUSH procAddrGLFlush; PFNGLFINISH procAddrGLFinish; + AVPacket* packet; AVFormatContext* pFormatCtx; int32_t vid; AVStream* pVStream; + AVCodecParameters* pVCodecPar; AVCodecContext* pVCodecCtx; AVCodec* pVCodec; AVFrame* pVFrame; uint32_t vBufferPlanes; // 1 for RGB*, 3 for YUV, .. uint32_t vBitsPerPixel; uint32_t vBytesPerPixelPerPlane; - enum PixelFormat vPixFmt; // native decoder fmt + enum AVPixelFormat vPixFmt; // native decoder fmt int32_t vPTS; // msec - overall last video PTS PTSStats vPTSStats; int32_t vTexWidth[4]; // decoded video tex width in bytes for each plane (max 4) @@ -166,6 +170,7 @@ typedef struct { int32_t aid; AVStream* pAStream; + AVCodecParameters* pACodecPar; AVCodecContext* pACodecCtx; AVCodec* pACodec; AVFrame** pAFrames; @@ -177,7 +182,6 @@ typedef struct { int32_t aSampleRate; int32_t aChannels; int32_t aSinkSupport; // supported by AudioSink - AVAudioResampleContext* avResampleCtx; struct SwrContext* swResampleCtx; uint8_t* aResampleBuffer; enum AVSampleFormat aSampleFmtOut; // out fmt diff --git a/src/jogl/native/libav/ffmpeg_lavc53_lavf53_lavu51.c b/src/jogl/native/libav/ffmpeg_v0400.c index edce2ba1d..669e2b4ce 100644 --- a/src/jogl/native/libav/ffmpeg_lavc53_lavf53_lavu51.c +++ b/src/jogl/native/libav/ffmpeg_v0400.c @@ -1,5 +1,5 @@ /** - * Copyright 2013 JogAmp Community. All rights reserved. + * Copyright 2013-2023 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -26,8 +26,8 @@ * or implied, of JogAmp Community. */ -#include "jogamp_opengl_util_av_impl_FFMPEGv08Natives.h" +#include "jogamp_opengl_util_av_impl_FFMPEGv0400Natives.h" -#define FF_FUNC(METHOD) Java_jogamp_opengl_util_av_impl_FFMPEGv08Natives_ ## METHOD +#define FF_FUNC(METHOD) Java_jogamp_opengl_util_av_impl_FFMPEGv0400Natives_ ## METHOD #include "ffmpeg_impl_template.c" diff --git a/src/jogl/native/libav/ffmpeg_lavc54_lavf54_lavu52_lavr01.c b/src/jogl/native/libav/ffmpeg_v0500.c index 651a64976..741a9c0ff 100644 --- a/src/jogl/native/libav/ffmpeg_lavc54_lavf54_lavu52_lavr01.c +++ b/src/jogl/native/libav/ffmpeg_v0500.c @@ -1,5 +1,5 @@ /** - * Copyright 2013 JogAmp Community. All rights reserved. + * Copyright 2013-2023 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -26,8 +26,8 @@ * or implied, of JogAmp Community. */ -#include "jogamp_opengl_util_av_impl_FFMPEGv09Natives.h" +#include "jogamp_opengl_util_av_impl_FFMPEGv0500Natives.h" -#define FF_FUNC(METHOD) Java_jogamp_opengl_util_av_impl_FFMPEGv09Natives_ ## METHOD +#define FF_FUNC(METHOD) Java_jogamp_opengl_util_av_impl_FFMPEGv0500Natives_ ## METHOD #include "ffmpeg_impl_template.c" diff --git a/src/jogl/native/libav/ffmpeg_lavc55_lavf55_lavu53_lavr01.c b/src/jogl/native/libav/ffmpeg_v0600.c index 277100398..e25e5bca8 100644 --- a/src/jogl/native/libav/ffmpeg_lavc55_lavf55_lavu53_lavr01.c +++ b/src/jogl/native/libav/ffmpeg_v0600.c @@ -1,5 +1,5 @@ /** - * Copyright 2013 JogAmp Community. All rights reserved. + * Copyright 2013-2023 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -26,8 +26,8 @@ * or implied, of JogAmp Community. */ -#include "jogamp_opengl_util_av_impl_FFMPEGv10Natives.h" +#include "jogamp_opengl_util_av_impl_FFMPEGv0600Natives.h" -#define FF_FUNC(METHOD) Java_jogamp_opengl_util_av_impl_FFMPEGv10Natives_ ## METHOD +#define FF_FUNC(METHOD) Java_jogamp_opengl_util_av_impl_FFMPEGv0600Natives_ ## METHOD #include "ffmpeg_impl_template.c" |