diff options
Diffstat (limited to 'src/jogl/native/libav/ffmpeg_impl_template.c')
-rw-r--r-- | src/jogl/native/libav/ffmpeg_impl_template.c | 808 |
1 files changed, 412 insertions, 396 deletions
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); } |