Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
To: ffmpeg-devel@ffmpeg.org
Cc: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Subject: [FFmpeg-devel] [PATCH 06/11] avcodec/encode, frame_thread_encoder: Unify calling encode callback
Date: Wed, 24 Aug 2022 03:40:01 +0200
Message-ID: <DB6PR0101MB221491EEF77F4A89A033BCBB8F739@DB6PR0101MB2214.eurprd01.prod.exchangelabs.com> (raw)
In-Reply-To: <DB6PR0101MB22147759BB89DB6819E1B5998F739@DB6PR0101MB2214.eurprd01.prod.exchangelabs.com>

The encode-callback (the callback used by the FF_CODEC_CB_TYPE_ENCODE
encoders) is currently called in two places: encode_simple_internal()
and by the worker threads of frame-threaded encoders.

After the call, some packet properties are set based upon
the corresponding AVFrame properties and the packet is made
refcounted if it isn't already. So there is some code duplication.

There was also non-duplicated code in encode_simple_internal()
which is executed even when using frame-threading. This included
an emms_c() (which is needed for frame-threading, too, if it is
needed for the single-threaded case, because there are allocations
(via av_packet_make_refcounted()) immediately after returning
from the encode-callback).

Furthermore, some further properties are only set in
encode_simple_internal(): For audio, pts and duration are derived
from the corresponding fields of the frame if the encoder does not
have the AV_CODEC_CAP_DELAY set. Yet this is wrong for frame-threaded
encoders, because frame-threading always introduces delay regardless
of whether the underlying codec has said cap. This only worked because
there are no frame-threaded audio encoders.

This commit fixes the code duplication and the above issue by factoring
this code out and reusing it in both places. It would work in case
of audio codecs with frame-threading, because now the values are
derived from the correct AVFrame.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/encode.c               | 86 ++++++++++++++++---------------
 libavcodec/encode.h               |  3 ++
 libavcodec/frame_thread_encoder.c | 12 ++---
 3 files changed, 50 insertions(+), 51 deletions(-)

diff --git a/libavcodec/encode.c b/libavcodec/encode.c
index 01b59bbf70..f7b13c8ba1 100644
--- a/libavcodec/encode.c
+++ b/libavcodec/encode.c
@@ -172,6 +172,48 @@ int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame)
     return 0;
 }
 
+int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt,
+                        const AVFrame *frame, int *got_packet)
+{
+    const FFCodec *const codec = ffcodec(avctx->codec);
+    int ret;
+
+    ret = codec->cb.encode(avctx, avpkt, frame, got_packet);
+    emms_c();
+    av_assert0(ret <= 0);
+
+    if (!ret && *got_packet) {
+        if (avpkt->data) {
+            ret = av_packet_make_refcounted(avpkt);
+            if (ret < 0)
+                goto unref;
+            // Date returned by encoders must always be ref-counted
+            av_assert0(avpkt->buf);
+        }
+
+        if (avctx->codec->type == AVMEDIA_TYPE_VIDEO &&
+            !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY))
+            avpkt->pts = avpkt->dts = frame->pts;
+        if (frame && !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) {
+            if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) {
+                if (avpkt->pts == AV_NOPTS_VALUE)
+                    avpkt->pts = frame->pts;
+                if (!avpkt->duration)
+                    avpkt->duration = ff_samples_to_time_base(avctx,
+                                                              frame->nb_samples);
+            }
+        }
+        if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) {
+            avpkt->dts = avpkt->pts;
+        }
+    } else {
+unref:
+        av_packet_unref(avpkt);
+    }
+
+    return ret;
+}
+
 static int encode_simple_internal(AVCodecContext *avctx, AVPacket *avpkt)
 {
     AVCodecInternal   *avci = avctx->internal;
@@ -204,58 +246,18 @@ static int encode_simple_internal(AVCodecContext *avctx, AVPacket *avpkt)
     av_assert0(codec->cb_type == FF_CODEC_CB_TYPE_ENCODE);
 
     if (CONFIG_FRAME_THREAD_ENCODER && avci->frame_thread_encoder)
-        /* This might modify frame, but it doesn't matter, because
-         * the frame properties used below are not used for video
-         * (due to the delay inherent in frame threaded encoding, it makes
-         *  no sense to use the properties of the current frame anyway). */
+        /* This might unref frame. */
         ret = ff_thread_video_encode_frame(avctx, avpkt, frame, &got_packet);
     else {
-        ret = codec->cb.encode(avctx, avpkt, frame, &got_packet);
-        if (avctx->codec->type == AVMEDIA_TYPE_VIDEO && !ret && got_packet &&
-            !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY))
-            avpkt->pts = avpkt->dts = frame->pts;
-    }
-
-    av_assert0(ret <= 0);
-
-    emms_c();
-
-    if (!ret && got_packet) {
-        if (avpkt->data) {
-            ret = av_packet_make_refcounted(avpkt);
-            if (ret < 0)
-                goto end;
-        }
-
-        if (frame && !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) {
-            if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) {
-                if (avpkt->pts == AV_NOPTS_VALUE)
-                    avpkt->pts = frame->pts;
-                if (!avpkt->duration)
-                    avpkt->duration = ff_samples_to_time_base(avctx,
-                                                              frame->nb_samples);
-            }
-        }
-        if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) {
-            avpkt->dts = avpkt->pts;
-        }
+        ret = ff_encode_encode_cb(avctx, avpkt, frame, &got_packet);
     }
 
     if (avci->draining && !got_packet)
         avci->draining_done = 1;
 
-end:
-    if (ret < 0 || !got_packet)
-        av_packet_unref(avpkt);
-
     if (frame)
         av_frame_unref(frame);
 
-    if (got_packet)
-        // Encoders must always return ref-counted buffers.
-        // Side-data only packets have no data and can be not ref-counted.
-        av_assert0(!avpkt->data || avpkt->buf);
-
     return ret;
 }
 
diff --git a/libavcodec/encode.h b/libavcodec/encode.h
index bc77918d8f..10c36435ad 100644
--- a/libavcodec/encode.h
+++ b/libavcodec/encode.h
@@ -75,4 +75,7 @@ int ff_alloc_packet(AVCodecContext *avctx, AVPacket *avpkt, int64_t size);
  */
 int ff_encode_preinit(AVCodecContext *avctx);
 
+int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt,
+                        const AVFrame *frame, int *got_packet);
+
 #endif /* AVCODEC_ENCODE_H */
diff --git a/libavcodec/frame_thread_encoder.c b/libavcodec/frame_thread_encoder.c
index b5765b6343..0d8134b258 100644
--- a/libavcodec/frame_thread_encoder.c
+++ b/libavcodec/frame_thread_encoder.c
@@ -29,6 +29,7 @@
 #include "libavutil/thread.h"
 #include "avcodec.h"
 #include "codec_internal.h"
+#include "encode.h"
 #include "internal.h"
 #include "pthread_internal.h"
 #include "thread.h"
@@ -80,7 +81,7 @@ static void * attribute_align_arg worker(void *v){
     ThreadContext *c = avctx->internal->frame_thread_encoder;
 
     while (!atomic_load(&c->exit)) {
-        int got_packet = 0, ret;
+        int ret;
         AVPacket *pkt;
         AVFrame *frame;
         Task *task;
@@ -105,14 +106,7 @@ static void * attribute_align_arg worker(void *v){
         frame = task->indata;
         pkt   = task->outdata;
 
-        ret = ffcodec(avctx->codec)->cb.encode(avctx, pkt, frame, &got_packet);
-        if(got_packet) {
-            int ret2 = av_packet_make_refcounted(pkt);
-            if (ret >= 0 && ret2 < 0)
-                ret = ret2;
-            pkt->pts = pkt->dts = frame->pts;
-        }
-        task->got_packet = got_packet;
+        ret = ff_encode_encode_cb(avctx, pkt, frame, &task->got_packet);
         pthread_mutex_lock(&c->buffer_mutex);
         av_frame_unref(frame);
         pthread_mutex_unlock(&c->buffer_mutex);
-- 
2.34.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

  parent reply	other threads:[~2022-08-24  1:41 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-24  1:28 [FFmpeg-devel] [PATCH 01/11] avcodec/tests/avcodec: Mark frame-thrd encoder incompatible with delay Andreas Rheinhardt
2022-08-24  1:39 ` [FFmpeg-devel] [PATCH 02/11] avcodec/encode: Apply intra_only_flag for receive_packet-API, too Andreas Rheinhardt
2022-08-24  1:39 ` [FFmpeg-devel] [PATCH 03/11] avcodec/aptx: Move AudioFrameQueue to aptxenc.c Andreas Rheinhardt
2022-08-24  1:39 ` [FFmpeg-devel] [PATCH 04/11] avcodec/encode: Simplify check for frame-threaded encoder Andreas Rheinhardt
2022-08-24  1:40 ` [FFmpeg-devel] [PATCH 05/11] avcodec/frame_thread_encoder: Forward got_packet directly Andreas Rheinhardt
2022-08-24  1:40 ` Andreas Rheinhardt [this message]
2022-08-24  1:40 ` [FFmpeg-devel] [PATCH 07/11] avcodec/encode: Remove redundant check Andreas Rheinhardt
2022-08-24  1:40 ` [FFmpeg-devel] [PATCH 08/11] avcodec/(dca|tta|pcm-bluray|pcm-dvd|wavpack)enc: Set pts+dur generically Andreas Rheinhardt
2022-08-24  1:40 ` [FFmpeg-devel] [PATCH 09/11] avcodec: Make ff_alloc_packet() based encoders accept user buffers Andreas Rheinhardt
2022-08-24  1:40 ` [FFmpeg-devel] [PATCH 10/11] avcodec/encode: Fix outdated comment Andreas Rheinhardt
2022-08-24  1:40 ` [FFmpeg-devel] [PATCH 11/11] avcodec/internal: " Andreas Rheinhardt
2022-08-26  0:27   ` [FFmpeg-devel] [PATCH v2] " Andreas Rheinhardt
2022-08-25  2:07 ` [FFmpeg-devel] [PATCH 12/21] avcodec/roqvideoenc: Remove internal.h inclusion Andreas Rheinhardt
2022-08-27 12:13   ` Andreas Rheinhardt
2022-08-25  2:07 ` [FFmpeg-devel] [PATCH 13/21] avcodec/internal: Move ff_get_format() to decode.h Andreas Rheinhardt
2022-08-25  2:07 ` [FFmpeg-devel] [PATCH 14/21] avcodec/internal: Move ff_reget_buffer() " Andreas Rheinhardt
2022-08-25 16:33 ` [FFmpeg-devel] [PATCH 15/21] avcodec/internal: Move ff_get_buffer() " Andreas Rheinhardt
2022-08-25 16:33 ` [FFmpeg-devel] [PATCH 16/21] avcodec/internal: Move ff_set_sar() " Andreas Rheinhardt
2022-08-25 16:33 ` [FFmpeg-devel] [PATCH 17/21] avcodec/internal: Move ff_set_dimensions() " Andreas Rheinhardt
2022-08-25 16:33 ` [FFmpeg-devel] [PATCH 18/21] avcodec/internal: Move ff_samples_to_time_base() to encode.h Andreas Rheinhardt
2022-08-25 16:33 ` [FFmpeg-devel] [PATCH 19/21] avcodec/internal: Move ff_side_data_update_matrix_encoding to decode.h Andreas Rheinhardt
2022-08-25 16:33 ` [FFmpeg-devel] [PATCH 20/21] avcodec/internal: Move ff_dvdsub_parse_palette() to new header dvdsub.h Andreas Rheinhardt
2022-08-25 16:34 ` [FFmpeg-devel] [PATCH 21/21] avcodec/targa: Fix indentation Andreas Rheinhardt
2022-08-26  0:31 ` [FFmpeg-devel] [PATCH 01/11] avcodec/tests/avcodec: Mark frame-thrd encoder incompatible with delay Andreas Rheinhardt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DB6PR0101MB221491EEF77F4A89A033BCBB8F739@DB6PR0101MB2214.eurprd01.prod.exchangelabs.com \
    --to=andreas.rheinhardt@outlook.com \
    --cc=ffmpeg-devel@ffmpeg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git