bplaum / gmerlin-encoders

Gmerlin encoder plugins
Other
0 stars 1 forks source link

ffmpeg compat #2

Closed umlaeute closed 2 weeks ago

umlaeute commented 1 year ago

i just recently discovered, that FFmpeg/avcodec no longer ships with avcodec_get_context_defaults3(), so the FFMPEG-encoders all fail to load:

[pluginregistry] dlopen failed for /usr/lib/x86_64-linux-gnu/gmerlin/plugins/c_ffmpeg_vp8.so: /usr/lib/x86_64-linux-gnu/gmerlin/plugins/c_ffmpeg_vp8.so: undefined symbol: avcodec_get_context_defaults3
[pluginregistry] dlopen failed for /usr/lib/x86_64-linux-gnu/gmerlin/plugins/c_ffmpeg_mpeg2.so: /usr/lib/x86_64-linux-gnu/gmerlin/plugins/c_ffmpeg_mpeg2.so: undefined symbol: avcodec_get_context_defaults3
[pluginregistry] dlopen failed for /usr/lib/x86_64-linux-gnu/gmerlin/plugins/e_ffmpeg.so: /usr/lib/x86_64-linux-gnu/gmerlin/plugins/e_ffmpeg.so: undefined symbol: avcodec_get_context_defaults3
[pluginregistry] dlopen failed for /usr/lib/x86_64-linux-gnu/gmerlin/plugins/c_ffmpeg_x264.so: /usr/lib/x86_64-linux-gnu/gmerlin/plugins/c_ffmpeg_x264.so: undefined symbol: avcodec_get_context_defaults3
[pluginregistry] dlopen failed for /usr/lib/x86_64-linux-gnu/gmerlin/plugins/c_ffmpeg_jpeg.so: /usr/lib/x86_64-linux-gnu/gmerlin/plugins/c_ffmpeg_jpeg.so: undefined symbol: avcodec_get_context_defaults3
[...]

This hasn't been caught by the linker, as the encoder plugins are, well, plugins (which often lack symbols provided by the host application).

It has slipped by me, because i usually don't use gmerlin for encoding...

umlaeute commented 1 year ago

for now i'm doing something like this (NOTE: i previously posted a faulty version of the patch, that would crash; this one seems to work instead):

diff --git a/plugins/ffmpeg/codec.c b/plugins/ffmpeg/codec.c
index 9a63bfb..5686154 100644
--- a/plugins/ffmpeg/codec.c
+++ b/plugins/ffmpeg/codec.c
@@ -59,8 +59,15 @@ static int find_encoder(bg_ffmpeg_codec_context_t * ctx)
     return 0;
     }

-  /* Set codec deftaults */
-  avcodec_get_context_defaults3(ctx->avctx, ctx->codec);
+  /* Set codec defaults */
+  avcodec_free_context(&ctx->avctx);
+  if(!(ctx->avctx = avcodec_alloc_context3 (ctx->codec)))
+    {
+    gavl_log(GAVL_LOG_ERROR, LOG_DOMAIN,
+           "Context for Codec %s could not be initialized",
+           bg_ffmpeg_get_codec_name(ctx->id));
+    return 0;
+    }
   return 1;
   }

@@ -86,12 +93,13 @@ bg_ffmpeg_codec_context_t * bg_ffmpeg_codec_create(int type,
   ret->type = type;

   /* Create private codec context */
-  ret->avctx_priv = avcodec_alloc_context3(NULL);
-  ret->avctx = ret->avctx_priv;
+  ret->avctx_priv = NULL;
+  ret->avctx = NULL;

   if(!find_encoder(ret))
     {
-    av_free(ret->avctx_priv);
+    if(ret->avctx)
+      avcodec_free_context(&ret->avctx);
     free(ret);
     return NULL;
     }
@@ -826,20 +834,10 @@ void bg_ffmpeg_codec_destroy(bg_ffmpeg_codec_context_t * ctx)
   if(!(ctx->flags & FLAG_FLUSHED))
     bg_ffmpeg_codec_flush(ctx);

-  /* Close */
-
-  if(ctx->avctx->stats_in)
-    {
-    free(ctx->avctx->stats_in);
-    ctx->avctx->stats_in = NULL;
-    }
-//  if(ctx->flags & FLAG_INITIALIZED)
-    avcodec_close(ctx->avctx);
-  
   /* Destroy */

-  if(ctx->avctx_priv)
-    av_free(ctx->avctx_priv);
+  if(ctx->avctx)
+    avcodec_free_context(&ctx->avctx);

   if(ctx->pc)
     bg_encoder_pts_cache_destroy(ctx->pc);

note

as of FFmpeg5 it is not longer possible to open/close codec contexts; instead, a context just has to be freed with avcodec_free_context and re-created. also, you can no longer apply codec defaults to an existing context (avcodec_get_context_defaults3), but instead pass the codec to the context-creator avcodec_alloc_context3.

this kind of obsoletes the avctx_priv member of bg_ffmpeg_codec_context_t (but i left it in the struct for now).

bplaum commented 1 year ago

Thanks for the notice. I think I fixed it. The avctx_priv was indeed uneccesary.