summaryrefslogtreecommitdiff
path: root/src/codec/ffmpeg
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2025-09-08 18:36:05 -0400
committerAndrew Opalach <andrew@akon.city> 2025-09-08 18:36:05 -0400
commitf5038bc66041ba8a721cedb125cddc342a9a9e4b (patch)
treeefc1340642778b2481dd356038f74e159360b046 /src/codec/ffmpeg
parentac3fd1a688202375612e905da9ee63bd6cd36a6f (diff)
downloadcamu-f5038bc66041ba8a721cedb125cddc342a9a9e4b.tar.gz
camu-f5038bc66041ba8a721cedb125cddc342a9a9e4b.tar.bz2
camu-f5038bc66041ba8a721cedb125cddc342a9a9e4b.zip
Fix FFmpeg decoder/demuxer deinit, misc cleanup
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/codec/ffmpeg')
-rw-r--r--src/codec/ffmpeg/decoder.c34
-rw-r--r--src/codec/ffmpeg/demuxer.c13
-rw-r--r--src/codec/ffmpeg/resampler.c3
3 files changed, 26 insertions, 24 deletions
diff --git a/src/codec/ffmpeg/decoder.c b/src/codec/ffmpeg/decoder.c
index 47bab44..6eff28b 100644
--- a/src/codec/ffmpeg/decoder.c
+++ b/src/codec/ffmpeg/decoder.c
@@ -60,6 +60,7 @@ static s32 get_buffer2(AVCodecContext *context, AVFrame *pic, s32 flags)
return ret;
}
+// This is currently untested.
static s32 init_hwframe_context(struct camu_ff_decoder *av, AVCodecContext *context, AVBufferRef *hw_device_context)
{
AVBufferRef *hw_frames_ref;
@@ -83,9 +84,11 @@ static s32 init_hwframe_context(struct camu_ff_decoder *av, AVCodecContext *cont
return ret;
}
+ context->hw_frames_ctx = hw_frames_ref;
+ /*
context->hw_frames_ctx = av_buffer_ref(hw_frames_ref);
-
av_buffer_unref(&hw_frames_ref);
+ */
return ret;
}
@@ -128,8 +131,6 @@ out:
static s32 init_hwdevice_context(struct camu_ff_decoder *av, AVCodecContext *context)
{
- av->hw_context = NULL;
-
s32 ret = av_hwdevice_ctx_create(&av->hw_context, av->hw_device_type, NULL, NULL, 0);
if (ret < 0) {
log_error("Failed to create specified HW device.");
@@ -208,12 +209,14 @@ static void close_internal(struct camu_ff_decoder *av)
{
if (av->codec_context) avcodec_free_context(&av->codec_context);
#ifdef CAMU_FF_DECODER_HWACCEL
- if (av->errored_hw_context) avcodec_free_context(&av->errored_hw_context);
+ if (av->hw_context) av_buffer_unref(&av->hw_context);
al_array_free(av->supported_hw_codecs);
al_array_free(av->supported_hw_devices);
+ if (av->errored_hw_context) avcodec_free_context(&av->errored_hw_context);
#endif
}
+// If decoder_init() fails, we should still expect decoder_free() to by called which will run close_internal().
static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *renderer, struct camu_codec_stream *stream,
void (*callback)(void *, struct camu_codec_frame *), void *userdata)
{
@@ -221,16 +224,17 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend
av->codec_context = NULL;
#ifdef CAMU_FF_DECODER_HWACCEL
- av->errored_hw_context = NULL;
+ av->hw_context = NULL;
al_array_init(av->supported_hw_codecs);
al_array_init(av->supported_hw_devices);
+ av->errored_hw_context = NULL;
#endif
AVCodecParameters *codecpar = stream->av.stream->codecpar;
const AVCodec *codec = avcodec_find_decoder(codecpar->codec_id);
if (!codec) {
log_error("Failed to find decoder.");
- goto err;
+ return false;
}
bool is_video = codecpar->codec_type == AVMEDIA_TYPE_VIDEO && stream->duration > 0;
@@ -253,6 +257,7 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend
const AVCodec *hw_codec;
al_array_foreach(av->supported_hw_codecs, i, hw_codec) {
if (hw_codec->id == codecpar->codec_id) {
+ // @TODO: hw_codec's without a hwdevice (v4l2m2m, cuvid, amf).
size_t length = al_strlen(hw_codec->wrapper_name);
av->hw_device_type = hw_device_supported_by_name(av, hw_codec->wrapper_name, length);
if (get_hwdevice_config(av, hw_codec, av->hw_device_type)) {
@@ -270,7 +275,7 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend
#endif
if (!alloc_codec_context_internal(av, codec, codecpar)) {
- goto err;
+ return false;
}
#ifdef CAMU_FF_DECODER_HWACCEL
@@ -295,9 +300,10 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend
if (av->hw_device_type == AV_HWDEVICE_TYPE_NONE) {
#endif
// FF_THREAD_FRAME or FF_THREAD_SLICE.
- // Both modes can get choked on certain videos, sometimes SLICE can squeeze
- // out a little more performance but a higher thread_count with FRAME seems
- // like the safest default.
+ // Both modes can get choked on certain videos, higher thread_count with
+ // FRAME seems like the safest default.
+ // @TODO: Check ffmpeg source, SLICE + FRAME?
+ // - https://ffmpeg.org/ffmpeg-codecs.html#Codec-Options
av->codec_context->thread_type = FF_THREAD_FRAME;
av->codec_context->thread_count = av->thread_count;
log_info("Using %i threads for decoder.", av->thread_count);
@@ -310,7 +316,7 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend
//av->codec_context->flags2 |= AV_CODEC_FLAG2_FAST;
if (!open_avcodec_internal(av, codec)) {
- goto err;
+ return false;
}
log_info("Codec: %s (%s) %lldkbps.", codec->name,
@@ -321,15 +327,12 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend
av->userdata = userdata;
return true;
-err:
- close_internal(av);
- return false;
}
static s32 send_packet(struct camu_ff_decoder *av, AVPacket *pkt)
{
s32 ret = avcodec_send_packet(av->codec_context, pkt);
- if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) {
+ if (ret < 0 && !(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)) {
log_error("Error sending packet to the decoder (%s).", av_err2str(ret));
}
return ret;
@@ -361,6 +364,7 @@ static s32 receive_frames(struct camu_ff_decoder *av)
al_free(frame);
// Checking for EAGAIN should prevent an infinite loop.
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) break;
+ log_error("Error receiving packet from the decoder (%s).", av_err2str(ret));
continue;
}
if (avframe->best_effort_timestamp == AV_NOPTS_VALUE) {
diff --git a/src/codec/ffmpeg/demuxer.c b/src/codec/ffmpeg/demuxer.c
index a8f1df7..e5aa2f6 100644
--- a/src/codec/ffmpeg/demuxer.c
+++ b/src/codec/ffmpeg/demuxer.c
@@ -31,7 +31,7 @@ static bool ff_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handl
av->format_context = avformat_alloc_context();
if (!av->format_context) {
log_error("Failed to create format context.");
- goto err;
+ return false;
}
// This is meant to be the "block size" so, if I understand correctly, that would mean
@@ -40,7 +40,7 @@ static bool ff_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handl
av->io_context = avio_alloc_context(buf, al_page_size, 0, handle, camu_avio_read, NULL, camu_avio_seek);
if (!av->io_context) {
log_error("Failed to create custom io context.");
- goto err;
+ return false;
}
if (!cch_handle_can_seek(handle)) {
@@ -67,7 +67,7 @@ static bool ff_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handl
if (ret < 0) {
log_error("Failed to open input (%s).", av_err2str(ret));
av_dict_free(&opts);
- goto err;
+ return false;
}
av_dict_free(&opts);
@@ -75,12 +75,12 @@ static bool ff_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handl
ret = avformat_find_stream_info(av->format_context, NULL);
if (ret < 0) {
log_error("Failed to find stream info (%s).", av_err2str(ret));
- goto err;
+ return false;
}
if (!av->format_context->nb_streams) {
log_error("No streams found.");
- goto err;
+ return false;
}
s64 default_duration = (av->format_context->duration < 0) ? 0 : av->format_context->duration;
@@ -143,9 +143,6 @@ static bool ff_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handl
av->eof = false;
return true;
-err:
- close_internal(av);
- return false;
}
static bool subscribed_to_index(struct camu_demuxer *demux, s32 index)
diff --git a/src/codec/ffmpeg/resampler.c b/src/codec/ffmpeg/resampler.c
index b141681..fa868c8 100644
--- a/src/codec/ffmpeg/resampler.c
+++ b/src/codec/ffmpeg/resampler.c
@@ -8,8 +8,9 @@
static bool ff_resampler_init(struct camu_resampler *resamp, struct camu_resampler_format *fmt)
{
struct camu_ff_resampler *av = (struct camu_ff_resampler *)resamp;
- al_assert(fmt->resampler_needed);
+ av->resample_context = NULL;
+ al_assert(fmt->resampler_needed);
camu_audio_format_copy(&av->fmt, &fmt->req);
SwrContext *swr = swr_alloc();