[FFmpeg-devel] [PATCH] avcodec/mediacodecenc: Check fifo write result and simplify fifo operation
Zhao Zhili
quinkblack at foxmail.com
Wed Dec 4 15:24:01 EET 2024
From: Zhao Zhili <zhilizhao at tencent.com>
---
libavcodec/mediacodecenc.c | 105 ++++++++++++++++++++-----------------
1 file changed, 58 insertions(+), 47 deletions(-)
diff --git a/libavcodec/mediacodecenc.c b/libavcodec/mediacodecenc.c
index 62bd7b4fda..464903d628 100644
--- a/libavcodec/mediacodecenc.c
+++ b/libavcodec/mediacodecenc.c
@@ -56,6 +56,11 @@ enum BitrateMode {
BITRATE_MODE_CBR_FD = 3,
};
+typedef struct MediaCodecAsyncOutput {
+ int32_t index;
+ FFAMediaCodecBufferInfo buf_info;
+} MediaCodecAsyncOutput;
+
typedef struct MediaCodecEncContext {
AVClass *avclass;
FFAMediaCodec *codec;
@@ -89,8 +94,7 @@ typedef struct MediaCodecEncContext {
AVMutex output_mutex;
AVCond output_cond;
int encode_status;
- AVFifo *output_index;
- AVFifo *output_buf_info;
+ AVFifo *async_output;
} MediaCodecEncContext;
enum {
@@ -235,34 +239,65 @@ static void copy_frame_to_buffer(AVCodecContext *avctx, const AVFrame *frame,
avctx->pix_fmt, avctx->width, avctx->height);
}
-static void on_input_available(FFAMediaCodec *codec, void *userdata,
- int32_t index)
+
+static void on_error(FFAMediaCodec *codec, void *userdata, int error,
+ const char *detail)
{
AVCodecContext *avctx = userdata;
MediaCodecEncContext *s = avctx->priv_data;
- ff_mutex_lock(&s->input_mutex);
+ if (error == AVERROR(EAGAIN))
+ return;
- av_fifo_write(s->input_index, &index, 1);
+ av_log(avctx, AV_LOG_ERROR, "On error, %s, %s\n", av_err2str(error), detail);
+ ff_mutex_lock(&s->input_mutex);
+ ff_mutex_lock(&s->output_mutex);
+ s->encode_status = error;
+ ff_mutex_unlock(&s->output_mutex);
ff_mutex_unlock(&s->input_mutex);
+
+ ff_cond_signal(&s->output_cond);
ff_cond_signal(&s->input_cond);
}
+static void on_input_available(FFAMediaCodec *codec, void *userdata,
+ int32_t index)
+{
+ AVCodecContext *avctx = userdata;
+ MediaCodecEncContext *s = avctx->priv_data;
+ int ret;
+
+ ff_mutex_lock(&s->input_mutex);
+ ret = av_fifo_write(s->input_index, &index, 1);
+ if (ret >= 0)
+ ff_cond_signal(&s->input_cond);
+ ff_mutex_unlock(&s->input_mutex);
+
+ if (ret < 0)
+ on_error(codec, userdata, ret, "av_fifo_write failed");
+}
+
static void on_output_available(FFAMediaCodec *codec, void *userdata,
int32_t index,
FFAMediaCodecBufferInfo *out_info)
{
AVCodecContext *avctx = userdata;
MediaCodecEncContext *s = avctx->priv_data;
+ MediaCodecAsyncOutput output = {
+ .index = index,
+ .buf_info = *out_info,
+ };
+ int ret;
ff_mutex_lock(&s->output_mutex);
-
- av_fifo_write(s->output_index, &index, 1);
- av_fifo_write(s->output_buf_info, out_info, 1);
-
+ ret = av_fifo_write(s->async_output, &output, 1);
+ if (ret >= 0)
+ ff_cond_signal(&s->output_cond);
ff_mutex_unlock(&s->output_mutex);
- ff_cond_signal(&s->output_cond);
+
+ if (ret < 0)
+ on_error(codec, userdata, ret, "av_fifo_write failed");
}
static void on_format_changed(FFAMediaCodec *codec, void *userdata,
@@ -271,27 +306,6 @@ static void on_format_changed(FFAMediaCodec *codec, void *userdata,
mediacodec_dump_format(userdata, format);
}
-static void on_error(FFAMediaCodec *codec, void *userdata, int error,
- const char *detail)
-{
- AVCodecContext *avctx = userdata;
- MediaCodecEncContext *s = avctx->priv_data;
-
- if (error == AVERROR(EAGAIN))
- return;
-
- av_log(avctx, AV_LOG_ERROR, "On error, %s, %s\n", av_err2str(error), detail);
-
- ff_mutex_lock(&s->input_mutex);
- ff_mutex_lock(&s->output_mutex);
- s->encode_status = error;
- ff_mutex_unlock(&s->output_mutex);
- ff_mutex_unlock(&s->input_mutex);
-
- ff_cond_signal(&s->output_cond);
- ff_cond_signal(&s->input_cond);
-}
-
static int mediacodec_init_async_state(AVCodecContext *avctx)
{
MediaCodecEncContext *s = avctx->priv_data;
@@ -307,10 +321,10 @@ static int mediacodec_init_async_state(AVCodecContext *avctx)
ff_cond_init(&s->output_cond, NULL);
s->input_index = av_fifo_alloc2(fifo_size, sizeof(int32_t), AV_FIFO_FLAG_AUTO_GROW);
- s->output_index = av_fifo_alloc2(fifo_size, sizeof(int32_t), AV_FIFO_FLAG_AUTO_GROW);
- s->output_buf_info = av_fifo_alloc2(fifo_size, sizeof(FFAMediaCodecBufferInfo), AV_FIFO_FLAG_AUTO_GROW);
+ s->async_output = av_fifo_alloc2(fifo_size, sizeof(MediaCodecAsyncOutput),
+ AV_FIFO_FLAG_AUTO_GROW);
- if (!s->input_index || !s->output_index || !s->output_buf_info)
+ if (!s->input_index || !s->async_output)
return AVERROR(ENOMEM);
return 0;
@@ -330,8 +344,7 @@ static void mediacodec_uninit_async_state(AVCodecContext *avctx)
ff_cond_destroy(&s->output_cond);
av_fifo_freep2(&s->input_index);
- av_fifo_freep2(&s->output_index);
- av_fifo_freep2(&s->output_buf_info);
+ av_fifo_freep2(&s->async_output);
s->async_mode = 0;
}
@@ -575,7 +588,7 @@ static int mediacodec_get_output_index(AVCodecContext *avctx, ssize_t *index,
MediaCodecEncContext *s = avctx->priv_data;
FFAMediaCodec *codec = s->codec;
int64_t timeout_us = s->eof_sent ? OUTPUT_DEQUEUE_TIMEOUT_US : 0;
- int n;
+ MediaCodecAsyncOutput output = { .index = -1 };
int ret;
if (!s->async_mode) {
@@ -585,28 +598,26 @@ static int mediacodec_get_output_index(AVCodecContext *avctx, ssize_t *index,
ff_mutex_lock(&s->output_mutex);
- n = -1;
- while (n < 0 && !s->encode_status) {
- if (av_fifo_can_read(s->output_index)) {
- av_fifo_read(s->output_index, &n, 1);
- av_fifo_read(s->output_buf_info, out_info, 1);
+ while (!s->encode_status) {
+ if (av_fifo_read(s->async_output, &output, 1) >= 0)
break;
- }
// Only wait after signalEndOfInputStream
- if (n < 0 && s->eof_sent && !s->encode_status)
+ if (s->eof_sent && !s->encode_status)
ff_cond_wait(&s->output_cond, &s->output_mutex);
else
break;
}
ret = s->encode_status;
- *index = n;
ff_mutex_unlock(&s->output_mutex);
// Get output index success
- if (*index >= 0)
+ if (output.index >= 0) {
+ *index = output.index;
+ *out_info = output.buf_info;
return 0;
+ }
return ret ? ret : AVERROR(EAGAIN);
}
--
2.46.0
More information about the ffmpeg-devel
mailing list