[FFmpeg-devel,v2,3/3] lavc/libdavs2.c: use decoder data directly instead of memcpy

Submitted by hwren on July 12, 2019, 12:47 p.m.

Details

Message ID 1562935660-6235-3-git-send-email-hwrenx@126.com
State New
Headers show

Commit Message

hwren July 12, 2019, 12:47 p.m.
Signed-off-by: hwrenx <hwrenx@126.com>
---
 libavcodec/libdavs2.c | 55 ++++++++++++++++++++++++++++++---------------------
 1 file changed, 32 insertions(+), 23 deletions(-)

Comments

hwren July 12, 2019, 3:21 p.m.
The previous version 2 patches were deprecated for using
pointer to itself can be unsafe when release frames.

This patch set is mainly about avoiding using memcpy when fetching
frame data, and fixed missing start codes which may cause error
packetization sometime. Default info level of libdavs2 was changed
because we found debug info is useless in most of the time.

hwrenx (3):
  lavc/avs2_parser.c: fix for missing start code
  lavc/libdavs2.c: change decoder info level
  lavc/libdavs2.c: use decoder data directly instead of memcpy

 libavcodec/avs2_parser.c |  4 +++-
 libavcodec/libdavs2.c    | 58 ++++++++++++++++++++++++++++--------------------
 2 files changed, 37 insertions(+), 25 deletions(-)

The performance comparison is like following:

[Platform]
  Intel® Core™ i7-8700k CPU @ 3.70GHz × 6 / 16GiB
[Command]
  ffmpeg -i test.avs2 -vsync 0 -f null -
[Stream]
  7680x4320 yuv420p Random Access
[Original version]
  frame= 2669 fps= 23 q=-0.0 Lsize=N/A time=00:00:53.44 bitrate=N/A speed=0.465x
[Optimized version]
  frame= 2669 fps= 42 q=-0.0 Lsize=N/A time=00:00:53.44 bitrate=N/A speed=0.836x

Patch hide | download patch | download mbox

diff --git a/libavcodec/libdavs2.c b/libavcodec/libdavs2.c
index df538af..f88dfa0 100644
--- a/libavcodec/libdavs2.c
+++ b/libavcodec/libdavs2.c
@@ -58,13 +58,25 @@  static av_cold int davs2_init(AVCodecContext *avctx)
     return 0;
 }
 
+static void davs2_frame_unref(void *opaque, uint8_t *data) {
+    DAVS2Context    *cad = (DAVS2Context *)opaque;
+    davs2_picture_t *pic = (davs2_picture_t *)data;
+
+    /* set release pointer to itself */
+    pic->magic = pic;
+
+    if (cad->decoder) {
+        davs2_decoder_frame_unref(cad->decoder, pic);
+    } else {
+        av_log(NULL, AV_LOG_WARNING, "Decoder not found, frame unreference failed.\n");
+    }
+}
+
 static int davs2_dump_frames(AVCodecContext *avctx, davs2_picture_t *pic, int *got_frame,
                              davs2_seq_info_t *headerset, int ret_type, AVFrame *frame)
 {
     DAVS2Context *cad    = avctx->priv_data;
-    int bytes_per_sample = pic->bytes_per_sample;
-    int plane = 0;
-    int line  = 0;
+    int plane;
 
     if (!headerset) {
         *got_frame = 0;
@@ -102,29 +114,28 @@  static int davs2_dump_frames(AVCodecContext *avctx, davs2_picture_t *pic, int *g
         return AVERROR_EXTERNAL;
     }
 
-    for (plane = 0; plane < 3; ++plane) {
-        int size_line = pic->widths[plane] * bytes_per_sample;
-        frame->buf[plane]  = av_buffer_alloc(size_line * pic->lines[plane]);
-
-        if (!frame->buf[plane]){
-            av_log(avctx, AV_LOG_ERROR, "Decoder error: allocation failure, can't dump frames.\n");
-            return AVERROR(ENOMEM);
-        }
-
-        frame->data[plane]     = frame->buf[plane]->data;
-        frame->linesize[plane] = size_line;
-
-        for (line = 0; line < pic->lines[plane]; ++line)
-            memcpy(frame->data[plane] + line * size_line,
-                   pic->planes[plane] + line * pic->strides[plane],
-                   pic->widths[plane] * bytes_per_sample);
-    }
-
     frame->width     = cad->headerset.width;
     frame->height    = cad->headerset.height;
     frame->pts       = cad->out_frame.pts;
     frame->format    = avctx->pix_fmt;
 
+    /* handle the actual picture in magic */
+    frame->buf[0]    = av_buffer_create((uint8_t *)pic->magic,
+                                        sizeof(davs2_picture_t *),
+                                        davs2_frame_unref,
+                                        (void *)cad,
+                                        AV_BUFFER_FLAG_READONLY);
+    if (!frame->buf[0]) {
+        av_log(avctx, AV_LOG_ERROR,
+            "Decoder error: allocation failure, can't dump frames.\n");
+        return AVERROR(ENOMEM);
+    }
+
+    for (plane = 0; plane < 3; ++plane) {
+        frame->linesize[plane] = pic->strides[plane];
+        frame->data[plane] = pic->planes[plane];
+    }
+
     *got_frame = 1;
     return 0;
 }
@@ -156,7 +167,6 @@  static int send_delayed_frame(AVCodecContext *avctx, AVFrame *frame, int *got_fr
     }
     if (ret == DAVS2_GOT_FRAME) {
         ret = davs2_dump_frames(avctx, &cad->out_frame, got_frame, &cad->headerset, ret, frame);
-        davs2_decoder_frame_unref(cad->decoder, &cad->out_frame);
     }
     return ret;
 }
@@ -205,7 +215,6 @@  static int davs2_decode_frame(AVCodecContext *avctx, void *data,
 
     if (ret != DAVS2_DEFAULT) {
         ret = davs2_dump_frames(avctx, &cad->out_frame, got_frame, &cad->headerset, ret, frame);
-        davs2_decoder_frame_unref(cad->decoder, &cad->out_frame);
     }
 
     return ret == 0 ? buf_size : ret;