diff options
author | Sven Gothel <[email protected]> | 2023-12-30 21:18:16 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2023-12-30 21:18:16 +0100 |
commit | 68b2dad19bd6d84f18b22f967ce320b448e8a270 (patch) | |
tree | e4d49a1eadc12ef9a456f1eb1d5303eddfe192c8 /src/jogl/native/libav/ffmpeg_impl_template.c | |
parent | c6e39c6e313a34688ca0164d7a34b6465e92396f (diff) |
GLMediaPlayer/FFMPEGMediaPlayer: Add chapter metadata support and use com.jogamp.common.av.PTS.millisToTimeStr(..)
Chapter metadata is now supported via our FFMPEGMediaPlayer implementation.
Added public method: 'Chapters[] GLMediaPlayer.getChapters()'
Diffstat (limited to 'src/jogl/native/libav/ffmpeg_impl_template.c')
-rw-r--r-- | src/jogl/native/libav/ffmpeg_impl_template.c | 86 |
1 files changed, 80 insertions, 6 deletions
diff --git a/src/jogl/native/libav/ffmpeg_impl_template.c b/src/jogl/native/libav/ffmpeg_impl_template.c index 7b46bfd7c..6d09a9d60 100644 --- a/src/jogl/native/libav/ffmpeg_impl_template.c +++ b/src/jogl/native/libav/ffmpeg_impl_template.c @@ -100,6 +100,7 @@ typedef int (APIENTRYP AV_GET_BITS_PER_PIXEL)(const AVPixFmtDescriptor *pixdesc) typedef int (APIENTRYP AV_SAMPLES_GET_BUFFER_SIZE)(int *linesize, int nb_channels, int nb_samples, enum AVSampleFormat sample_fmt, int align); typedef int (APIENTRYP AV_GET_BYTES_PER_SAMPLE)(enum AVSampleFormat sample_fmt); typedef int (APIENTRYP AV_OPT_SET_INT)(void *obj, const char *name, int64_t val, int search_flags); +typedef AVDictionaryEntry* (APIENTRYP AV_DICT_ITERATE)(AVDictionary *m, const AVDictionaryEntry *prev); typedef AVDictionaryEntry* (APIENTRYP AV_DICT_GET)(AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags); typedef int (APIENTRYP AV_DICT_COUNT)(AVDictionary *m); typedef int (APIENTRYP AV_DICT_SET)(AVDictionary **pm, const char *key, const char *value, int flags); @@ -117,6 +118,7 @@ static AV_GET_BITS_PER_PIXEL sp_av_get_bits_per_pixel; static AV_SAMPLES_GET_BUFFER_SIZE sp_av_samples_get_buffer_size; static AV_GET_BYTES_PER_SAMPLE sp_av_get_bytes_per_sample; static AV_OPT_SET_INT sp_av_opt_set_int; +static AV_DICT_ITERATE sp_av_dict_iterate; static AV_DICT_GET sp_av_dict_get; static AV_DICT_COUNT sp_av_dict_count; static AV_DICT_SET sp_av_dict_set; @@ -125,7 +127,7 @@ 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 +// count: +17 = 40 // libavformat typedef AVFormatContext *(APIENTRYP AVFORMAT_ALLOC_CONTEXT)(void); @@ -157,12 +159,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: +14 = 53 +// count: +14 = 54 // libavdevice [53.0.0] typedef int (APIENTRYP AVDEVICE_REGISTER_ALL)(void); static AVDEVICE_REGISTER_ALL sp_avdevice_register_all; -// count: +1 = 54 +// count: +1 = 55 // 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! @@ -178,7 +180,7 @@ static SWR_INIT sp_swr_init; static SWR_FREE sp_swr_free; static SWR_CONVERT sp_swr_convert; static SWR_GET_OUT_SAMPLES sp_swr_get_out_samples; -// count: +6 = 60 +// count: +6 = 61 // We use JNI Monitor Locking, since this removes the need // to statically link-in pthreads on window .. @@ -202,7 +204,7 @@ static SWR_GET_OUT_SAMPLES sp_swr_get_out_samples; #define MY_MUTEX_UNLOCK(e,s) #endif -#define SYMBOL_COUNT 60 +#define SYMBOL_COUNT 61 JNIEXPORT jboolean JNICALL FF_FUNC(initSymbols0) (JNIEnv *env, jobject instance, jobject jmutex_avcodec_openclose, jobject jSymbols, jint count) @@ -256,6 +258,7 @@ JNIEXPORT jboolean JNICALL FF_FUNC(initSymbols0) sp_av_samples_get_buffer_size = (AV_SAMPLES_GET_BUFFER_SIZE) (intptr_t) symbols[i++]; sp_av_get_bytes_per_sample = (AV_GET_BYTES_PER_SAMPLE) (intptr_t) symbols[i++]; sp_av_opt_set_int = (AV_OPT_SET_INT) (intptr_t) symbols[i++]; + sp_av_dict_iterate = (AV_DICT_ITERATE) (intptr_t) symbols[i++]; sp_av_dict_get = (AV_DICT_GET) (intptr_t) symbols[i++]; sp_av_dict_count = (AV_DICT_COUNT) (intptr_t) symbols[i++]; sp_av_dict_set = (AV_DICT_SET) (intptr_t) symbols[i++]; @@ -1180,8 +1183,8 @@ JNIEXPORT void JNICALL FF_FUNC(setStream0) pAV->aPTS=0; initPTSStats(&pAV->vPTSStats); initPTSStats(&pAV->aPTSStats); - _updateJavaAttributes(env, pAV); pAV->ready = 1; + _updateJavaAttributes(env, pAV); } JNIEXPORT void JNICALL FF_FUNC(setGLFuncs0) @@ -1706,3 +1709,74 @@ JNIEXPORT jint JNICALL FF_FUNC(getAudioPTS0) return pAV->aPTS; } +static inline const char* meta_get_value(AVDictionary *tags, const char* key) +{ + // SECTION_ID_CHAPTER_TAGS + if (!tags) { + return NULL; + } + const AVDictionaryEntry *entry = NULL; + if ((entry = sp_av_dict_get(tags, key, entry, AV_DICT_IGNORE_SUFFIX))) { + return entry->value; + } + return NULL; +} +static inline const char* meta_get_chapter_title(AVChapter *chapter) +{ + return meta_get_value(chapter->metadata, "title"); +} +JNIEXPORT jint JNICALL FF_FUNC(getChapterCount0) + (JNIEnv *env, jobject instance, jlong ptr) +{ + FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr)); + if( 0 == pAV->ready ) { + return 0; + } + return pAV->pFormatCtx->nb_chapters; +} + +JNIEXPORT jint JNICALL FF_FUNC(getChapterID0) + (JNIEnv *env, jobject instance, jlong ptr, jint idx) +{ + FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr)); + if( 0 == pAV->ready || idx >= pAV->pFormatCtx->nb_chapters ) { + return 0; + } + AVChapter *chapter = pAV->pFormatCtx->chapters[idx]; + return chapter->id; +} + +JNIEXPORT jint JNICALL FF_FUNC(getChapterStartPTS0) + (JNIEnv *env, jobject instance, jlong ptr, jint idx) +{ + FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr)); + if( 0 == pAV->ready || idx >= pAV->pFormatCtx->nb_chapters ) { + return 0; + } + AVChapter *chapter = pAV->pFormatCtx->chapters[idx]; + return my_av_q2i32( chapter->start * 1000, chapter->time_base); +} + +JNIEXPORT jint JNICALL FF_FUNC(getChapterEndPTS0) + (JNIEnv *env, jobject instance, jlong ptr, jint idx) +{ + FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr)); + if( 0 == pAV->ready || idx >= pAV->pFormatCtx->nb_chapters ) { + return 0; + } + AVChapter *chapter = pAV->pFormatCtx->chapters[idx]; + return my_av_q2i32( chapter->end * 1000, chapter->time_base); +} + +JNIEXPORT jstring JNICALL FF_FUNC(getChapterTitle0) + (JNIEnv *env, jobject instance, jlong ptr, jint idx) +{ + FFMPEGToolBasicAV_t *pAV = (FFMPEGToolBasicAV_t *)((void *)((intptr_t)ptr)); + if( 0 == pAV->ready || idx >= pAV->pFormatCtx->nb_chapters ) { + return NULL; + } + AVChapter *chapter = pAV->pFormatCtx->chapters[idx]; + const char* title = meta_get_chapter_title(chapter); + return NULL != title ? (*env)->NewStringUTF(env, title) : NULL; +} + |