diff mbox series

[FFmpeg-devel,14/16] lavc/proresdec: add scaffolding for hwdec support

Message ID 20211122205330.43546-14-rcombs@rcombs.me
State New
Headers show
Series [FFmpeg-devel,01/16] ffmpeg: remove ffmpeg_videotoolbox
Related show

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished
andriy/make_ppc success Make finished
andriy/make_fate_ppc success Make fate finished

Commit Message

rcombs Nov. 22, 2021, 8:53 p.m. UTC
---
 libavcodec/proresdec.h  |  1 +
 libavcodec/proresdec2.c | 48 ++++++++++++++++++++++++++++++++++-------
 2 files changed, 41 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/libavcodec/proresdec.h b/libavcodec/proresdec.h
index 06e41dd09a..1e48752e6f 100644
--- a/libavcodec/proresdec.h
+++ b/libavcodec/proresdec.h
@@ -52,6 +52,7 @@  typedef struct {
     int first_field;
     int alpha_info;
     void (*unpack_alpha)(GetBitContext *gb, uint16_t *dst, int num_coeffs, const int num_bits);
+    enum AVPixelFormat pix_fmt;
 } ProresContext;
 
 #endif /* AVCODEC_PRORESDEC_H */
diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c
index 7750620b22..5b1d7da693 100644
--- a/libavcodec/proresdec2.c
+++ b/libavcodec/proresdec2.c
@@ -187,6 +187,8 @@  static av_cold int decode_init(AVCodecContext *avctx)
     permute(ctx->progressive_scan, ff_prores_progressive_scan, idct_permutation);
     permute(ctx->interlaced_scan, ff_prores_interlaced_scan, idct_permutation);
 
+    ctx->pix_fmt = AV_PIX_FMT_NONE;
+
     if (avctx->bits_per_raw_sample == 10){
         ctx->unpack_alpha = unpack_alpha_10;
     } else if (avctx->bits_per_raw_sample == 12){
@@ -204,6 +206,7 @@  static int decode_frame_header(ProresContext *ctx, const uint8_t *buf,
     int hdr_size, width, height, flags;
     int version;
     const uint8_t *ptr;
+    enum AVPixelFormat pix_fmt;
 
     hdr_size = AV_RB16(buf);
     ff_dlog(avctx, "header size %d\n", hdr_size);
@@ -252,18 +255,34 @@  static int decode_frame_header(ProresContext *ctx, const uint8_t *buf,
 
     if (ctx->alpha_info) {
         if (avctx->bits_per_raw_sample == 10) {
-            avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUVA444P10 : AV_PIX_FMT_YUVA422P10;
+            pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUVA444P10 : AV_PIX_FMT_YUVA422P10;
         } else { /* 12b */
-            avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUVA444P12 : AV_PIX_FMT_YUVA422P12;
+            pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUVA444P12 : AV_PIX_FMT_YUVA422P12;
         }
     } else {
         if (avctx->bits_per_raw_sample == 10) {
-            avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P10 : AV_PIX_FMT_YUV422P10;
+            pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P10 : AV_PIX_FMT_YUV422P10;
         } else { /* 12b */
-            avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P12 : AV_PIX_FMT_YUV422P12;
+            pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P12 : AV_PIX_FMT_YUV422P12;
         }
     }
 
+    if (pix_fmt != ctx->pix_fmt) {
+#define HWACCEL_MAX 0
+        enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmtp = pix_fmts;
+        int ret;
+
+        ctx->pix_fmt = pix_fmt;
+
+        *fmtp++ = ctx->pix_fmt;
+        *fmtp = AV_PIX_FMT_NONE;
+
+        if ((ret = ff_thread_get_format(avctx, pix_fmts)) < 0)
+            return ret;
+
+        avctx->pix_fmt = ret;
+    }
+
     avctx->color_primaries = buf[14];
     avctx->color_trc       = buf[15];
     avctx->colorspace      = buf[16];
@@ -782,6 +801,22 @@  static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
     buf += frame_hdr_size;
     buf_size -= frame_hdr_size;
 
+    if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0)
+        return ret;
+
+    if (avctx->hwaccel) {
+        ret = avctx->hwaccel->start_frame(avctx, NULL, 0);
+        if (ret < 0)
+            return ret;
+        ret = avctx->hwaccel->decode_slice(avctx, avpkt->data, avpkt->size);
+        if (ret < 0)
+            return ret;
+        ret = avctx->hwaccel->end_frame(avctx);
+        if (ret < 0)
+            return ret;
+        goto finish;
+    }
+
  decode_picture:
     pic_size = decode_picture_header(avctx, buf, buf_size);
     if (pic_size < 0) {
@@ -789,10 +824,6 @@  static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
         return pic_size;
     }
 
-    if (ctx->first_field)
-        if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0)
-            return ret;
-
     if ((ret = decode_picture(avctx)) < 0) {
         av_log(avctx, AV_LOG_ERROR, "error decoding picture\n");
         return ret;
@@ -806,6 +837,7 @@  static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
         goto decode_picture;
     }
 
+finish:
     *got_frame      = 1;
 
     return avpkt->size;