Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex
@ 2022-06-30 21:48 Andreas Rheinhardt
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 02/18] fate/hevc: add clip for persistent_rice_adaptation_enabled_flag Andreas Rheinhardt
                   ` (17 more replies)
  0 siblings, 18 replies; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-06-30 21:48 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andreas Rheinhardt

It results in undefined behaviour. Instead initialize the mutexes
and condition variables once during init (and check these
initializations).

Also combine the corresponding mutex and condition variable
into one structure so that one can allocate their array
jointly.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
Now also adding the fallback function in case threads are disabled.

 libavcodec/hevcdec.c       |  7 +++-
 libavcodec/pthread_slice.c | 83 ++++++++++++++++++++++++--------------
 libavcodec/thread.h        |  1 +
 libavcodec/utils.c         |  5 +++
 4 files changed, 63 insertions(+), 33 deletions(-)

diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index 7037048d53..f222f20706 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -3803,9 +3803,12 @@ static av_cold int hevc_decode_init(AVCodecContext *avctx)
     HEVCContext *s = avctx->priv_data;
     int ret;
 
-    if(avctx->active_thread_type & FF_THREAD_SLICE)
+    if (avctx->active_thread_type & FF_THREAD_SLICE) {
         s->threads_number = avctx->thread_count;
-    else
+        ret = ff_slice_thread_init_progress(avctx);
+        if (ret < 0)
+            return ret;
+    } else
         s->threads_number = 1;
 
     if((avctx->active_thread_type & FF_THREAD_FRAME) && avctx->thread_count > 1)
diff --git a/libavcodec/pthread_slice.c b/libavcodec/pthread_slice.c
index 0ad1965a22..e34116116d 100644
--- a/libavcodec/pthread_slice.c
+++ b/libavcodec/pthread_slice.c
@@ -41,6 +41,11 @@ typedef int (action_func)(AVCodecContext *c, void *arg);
 typedef int (action_func2)(AVCodecContext *c, void *arg, int jobnr, int threadnr);
 typedef int (main_func)(AVCodecContext *c);
 
+typedef struct Progress {
+    pthread_cond_t  cond;
+    pthread_mutex_t mutex;
+} Progress;
+
 typedef struct SliceThreadContext {
     AVSliceThread *thread;
     action_func *func;
@@ -53,8 +58,7 @@ typedef struct SliceThreadContext {
     int *entries;
     int entries_count;
     int thread_count;
-    pthread_cond_t *progress_cond;
-    pthread_mutex_t *progress_mutex;
+    Progress *progress;
 } SliceThreadContext;
 
 static void main_function(void *priv) {
@@ -83,13 +87,13 @@ void ff_slice_thread_free(AVCodecContext *avctx)
     avpriv_slicethread_free(&c->thread);
 
     for (i = 0; i < c->thread_count; i++) {
-        pthread_mutex_destroy(&c->progress_mutex[i]);
-        pthread_cond_destroy(&c->progress_cond[i]);
+        Progress *const progress = &c->progress[i];
+        pthread_mutex_destroy(&progress->mutex);
+        pthread_cond_destroy(&progress->cond);
     }
 
     av_freep(&c->entries);
-    av_freep(&c->progress_mutex);
-    av_freep(&c->progress_cond);
+    av_freep(&c->progress);
     av_freep(&avctx->internal->thread_ctx);
 }
 
@@ -172,65 +176,82 @@ int ff_slice_thread_init(AVCodecContext *avctx)
     return 0;
 }
 
+int av_cold ff_slice_thread_init_progress(AVCodecContext *avctx)
+{
+    SliceThreadContext *const p = avctx->internal->thread_ctx;
+    int err, i = 0, thread_count = avctx->thread_count;
+
+    p->progress = av_calloc(thread_count, sizeof(*p->progress));
+    if (!p->progress) {
+        err = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    for (; i < thread_count; i++) {
+        Progress *const progress = &p->progress[i];
+        err = pthread_mutex_init(&progress->mutex, NULL);
+        if (err) {
+            err = AVERROR(err);
+            goto fail;
+        }
+        err = pthread_cond_init (&progress->cond,  NULL);
+        if (err) {
+            err = AVERROR(err);
+            pthread_mutex_destroy(&progress->mutex);
+            goto fail;
+        }
+    }
+    err = 0;
+fail:
+    p->thread_count = i;
+    return err;
+}
+
 void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, int n)
 {
     SliceThreadContext *p = avctx->internal->thread_ctx;
+    Progress *const progress = &p->progress[thread];
     int *entries = p->entries;
 
-    pthread_mutex_lock(&p->progress_mutex[thread]);
+    pthread_mutex_lock(&progress->mutex);
     entries[field] +=n;
-    pthread_cond_signal(&p->progress_cond[thread]);
-    pthread_mutex_unlock(&p->progress_mutex[thread]);
+    pthread_cond_signal(&progress->cond);
+    pthread_mutex_unlock(&progress->mutex);
 }
 
 void ff_thread_await_progress2(AVCodecContext *avctx, int field, int thread, int shift)
 {
     SliceThreadContext *p  = avctx->internal->thread_ctx;
+    Progress *progress;
     int *entries      = p->entries;
 
     if (!entries || !field) return;
 
     thread = thread ? thread - 1 : p->thread_count - 1;
+    progress = &p->progress[thread];
 
-    pthread_mutex_lock(&p->progress_mutex[thread]);
+    pthread_mutex_lock(&progress->mutex);
     while ((entries[field - 1] - entries[field]) < shift){
-        pthread_cond_wait(&p->progress_cond[thread], &p->progress_mutex[thread]);
+        pthread_cond_wait(&progress->cond, &progress->mutex);
     }
-    pthread_mutex_unlock(&p->progress_mutex[thread]);
+    pthread_mutex_unlock(&progress->mutex);
 }
 
 int ff_alloc_entries(AVCodecContext *avctx, int count)
 {
-    int i;
-
     if (avctx->active_thread_type & FF_THREAD_SLICE)  {
         SliceThreadContext *p = avctx->internal->thread_ctx;
 
         if (p->entries) {
-            av_assert0(p->thread_count == avctx->thread_count);
             av_freep(&p->entries);
         }
 
-        p->thread_count  = avctx->thread_count;
         p->entries       = av_calloc(count, sizeof(*p->entries));
-
-        if (!p->progress_mutex) {
-            p->progress_mutex = av_malloc_array(p->thread_count, sizeof(pthread_mutex_t));
-            p->progress_cond  = av_malloc_array(p->thread_count, sizeof(pthread_cond_t));
-        }
-
-        if (!p->entries || !p->progress_mutex || !p->progress_cond) {
-            av_freep(&p->entries);
-            av_freep(&p->progress_mutex);
-            av_freep(&p->progress_cond);
+        if (!p->entries) {
+            p->entries_count = 0;
             return AVERROR(ENOMEM);
         }
         p->entries_count  = count;
-
-        for (i = 0; i < p->thread_count; i++) {
-            pthread_mutex_init(&p->progress_mutex[i], NULL);
-            pthread_cond_init(&p->progress_cond[i], NULL);
-        }
     }
 
     return 0;
diff --git a/libavcodec/thread.h b/libavcodec/thread.h
index d36dc83bd7..92cbd927f1 100644
--- a/libavcodec/thread.h
+++ b/libavcodec/thread.h
@@ -106,6 +106,7 @@ int ff_slice_thread_execute_with_mainfunc(AVCodecContext *avctx,
 void ff_thread_free(AVCodecContext *s);
 int ff_alloc_entries(AVCodecContext *avctx, int count);
 void ff_reset_entries(AVCodecContext *avctx);
+int ff_slice_thread_init_progress(AVCodecContext *avctx);
 void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, int n);
 void ff_thread_await_progress2(AVCodecContext *avctx,  int field, int thread, int shift);
 
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 940f25fe7a..f78475d0ad 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -958,6 +958,11 @@ int ff_thread_can_start_frame(AVCodecContext *avctx)
     return 1;
 }
 
+int ff_slice_thread_init_progress(AVCodecContext *avctx)
+{
+    return 0;
+}
+
 int ff_alloc_entries(AVCodecContext *avctx, int count)
 {
     return 0;
-- 
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [FFmpeg-devel] [PATCH 02/18] fate/hevc: add clip for persistent_rice_adaptation_enabled_flag
  2022-06-30 21:48 [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Andreas Rheinhardt
@ 2022-06-30 22:29 ` Andreas Rheinhardt
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 03/18] avcodec/hevcdec: Don't initialize HEVCContexts twice Andreas Rheinhardt
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-06-30 22:29 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Xu Guangxin

From: Xu Guangxin <oddstone@gmail.com>

Tests the issue fixed in c8bc0f66a875bc3708d8dc11b757f2198606ffd7.

Signed-off-by: Xu Guangxin <oddstone@gmail.com>
---
Thanks to James for uploading the sample.

There is something weird going on with this sample:
If I max out my computer and concurrently run this test
with slice threading, it sometimes fails (in about 1/3 of all runs).
Yet for some reason #9 made this happen only very infrequently.
tsan does not show any race that has anything to do with
updating the cabac state (which is what #9 is about),
but it shows other races (both before and after this patchset).
I did not encounter this with any other sample.

 tests/fate/hevc.mak                                       | 1 +
 .../hevc-conformance-WPP_HIGH_TP_444_8BIT_RExt_Apple_2    | 8 ++++++++
 2 files changed, 9 insertions(+)
 create mode 100644 tests/ref/fate/hevc-conformance-WPP_HIGH_TP_444_8BIT_RExt_Apple_2

diff --git a/tests/fate/hevc.mak b/tests/fate/hevc.mak
index 2f16e3a29f..6c1e7447ad 100644
--- a/tests/fate/hevc.mak
+++ b/tests/fate/hevc.mak
@@ -141,6 +141,7 @@ HEVC_SAMPLES_8BIT =             \
     WPP_D_ericsson_MAIN_2       \
     WPP_E_ericsson_MAIN_2       \
     WPP_F_ericsson_MAIN_2       \
+    WPP_HIGH_TP_444_8BIT_RExt_Apple_2 \
 
 HEVC_SAMPLES_10BIT =            \
     DBLK_A_MAIN10_VIXS_3        \
diff --git a/tests/ref/fate/hevc-conformance-WPP_HIGH_TP_444_8BIT_RExt_Apple_2 b/tests/ref/fate/hevc-conformance-WPP_HIGH_TP_444_8BIT_RExt_Apple_2
new file mode 100644
index 0000000000..fcb1d2894a
--- /dev/null
+++ b/tests/ref/fate/hevc-conformance-WPP_HIGH_TP_444_8BIT_RExt_Apple_2
@@ -0,0 +1,8 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 1024x768
+#sar 0: 0/1
+0,          0,          0,        1,  1179648, 0x78e55a69
+0,          1,          1,        1,  1179648, 0x5babb3cb
+0,          2,          2,        1,  1179648, 0x65935648
-- 
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [FFmpeg-devel] [PATCH 03/18] avcodec/hevcdec: Don't initialize HEVCContexts twice
  2022-06-30 21:48 [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Andreas Rheinhardt
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 02/18] fate/hevc: add clip for persistent_rice_adaptation_enabled_flag Andreas Rheinhardt
@ 2022-06-30 22:29 ` Andreas Rheinhardt
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 04/18] avcodec/hevcdec: Add pointers to logctx and parent ctx to HEVCLocalCtx Andreas Rheinhardt
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-06-30 22:29 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andreas Rheinhardt

The slicethread contexts need to be initialized for
every frame, not only the first one, so one can
remove the initialization when allocating these contexts,
because the ordinary per-frame initialization will
initialize them again just a few lines below.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/hevcdec.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index f222f20706..5ad02742ba 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -2661,8 +2661,6 @@ static int hls_slice_data_wpp(HEVCContext *s, const H2645NAL *nal)
             res = AVERROR(ENOMEM);
             goto error;
         }
-        memcpy(s->sList[i], s, sizeof(HEVCContext));
-        s->sList[i]->HEVClc = s->HEVClcList[i];
     }
 
     offset = (lc->gb.index >> 3);
@@ -2701,10 +2699,10 @@ static int hls_slice_data_wpp(HEVCContext *s, const H2645NAL *nal)
     s->data = data;
 
     for (i = 1; i < s->threads_number; i++) {
-        s->sList[i]->HEVClc->first_qp_group = 1;
-        s->sList[i]->HEVClc->qp_y = s->sList[0]->HEVClc->qp_y;
         memcpy(s->sList[i], s, sizeof(HEVCContext));
         s->sList[i]->HEVClc = s->HEVClcList[i];
+        s->sList[i]->HEVClc->first_qp_group = 1;
+        s->sList[i]->HEVClc->qp_y = s->sList[0]->HEVClc->qp_y;
     }
 
     atomic_store(&s->wpp_err, 0);
-- 
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [FFmpeg-devel] [PATCH 04/18] avcodec/hevcdec: Add pointers to logctx and parent ctx to HEVCLocalCtx
  2022-06-30 21:48 [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Andreas Rheinhardt
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 02/18] fate/hevc: add clip for persistent_rice_adaptation_enabled_flag Andreas Rheinhardt
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 03/18] avcodec/hevcdec: Don't initialize HEVCContexts twice Andreas Rheinhardt
@ 2022-06-30 22:29 ` Andreas Rheinhardt
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 05/18] avcodec/hevc_refs: Constify ff_hevc_get_ref_list() Andreas Rheinhardt
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-06-30 22:29 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andreas Rheinhardt

It is safe for a slice thread to read the main context
and therefore it is safe to add a pointer to const HEVCContext
(namely the parent context) to each HEVCLocalContext.
It is also safe (and actually redundant) to add a pointer
to a logcontext to HEVCLocalContext.

Doing so allows to pass the HEVCLocalContext as context in
the parts of the code that is run slice-threaded when slice-threading
is in use (currently these parts of the code use ordinary
HEVCContext*). This way one is not tempted to modify
the main context from the slice contexts.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
One could btw also cache the pointers to the current SPS and PPS;
doing so would make several accesses to the parent context superfluous.

 libavcodec/hevcdec.c | 4 ++++
 libavcodec/hevcdec.h | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index 5ad02742ba..111da42836 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -2661,6 +2661,8 @@ static int hls_slice_data_wpp(HEVCContext *s, const H2645NAL *nal)
             res = AVERROR(ENOMEM);
             goto error;
         }
+        s->HEVClcList[i]->logctx = s->avctx;
+        s->HEVClcList[i]->parent = s->sList[i];
     }
 
     offset = (lc->gb.index >> 3);
@@ -3646,6 +3648,8 @@ static av_cold int hevc_init_context(AVCodecContext *avctx)
     s->sList = av_mallocz(sizeof(HEVCContext*) * s->threads_number);
     if (!s->HEVClc || !s->HEVClcList || !s->sList)
         return AVERROR(ENOMEM);
+    s->HEVClc->parent = s;
+    s->HEVClc->logctx = avctx;
     s->HEVClcList[0] = s->HEVClc;
     s->sList[0] = s;
 
diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h
index ff2199aa5a..a4cea2284d 100644
--- a/libavcodec/hevcdec.h
+++ b/libavcodec/hevcdec.h
@@ -428,6 +428,9 @@ typedef struct HEVCLocalContext {
 
     uint8_t first_qp_group;
 
+    void *logctx;
+    const struct HEVCContext *parent;
+
     GetBitContext gb;
     CABACContext cc;
 
-- 
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [FFmpeg-devel] [PATCH 05/18] avcodec/hevc_refs: Constify ff_hevc_get_ref_list()
  2022-06-30 21:48 [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Andreas Rheinhardt
                   ` (2 preceding siblings ...)
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 04/18] avcodec/hevcdec: Add pointers to logctx and parent ctx to HEVCLocalCtx Andreas Rheinhardt
@ 2022-06-30 22:29 ` Andreas Rheinhardt
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 06/18] avcodec/hevc_cabac: Don't cast const away unnecessarily Andreas Rheinhardt
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-06-30 22:29 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andreas Rheinhardt

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/hevc_filter.c | 16 ++++++++--------
 libavcodec/hevc_mvs.c    | 10 +++++-----
 libavcodec/hevc_refs.c   |  5 +++--
 libavcodec/hevcdec.h     |  4 ++--
 4 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c
index 1ef214b0ff..7b53c66c3b 100644
--- a/libavcodec/hevc_filter.c
+++ b/libavcodec/hevc_filter.c
@@ -645,8 +645,8 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0)
     }
 }
 
-static int boundary_strength(HEVCContext *s, MvField *curr, MvField *neigh,
-                             RefPicList *neigh_refPicList)
+static int boundary_strength(const HEVCContext *s, const MvField *curr, const MvField *neigh,
+                             const RefPicList *neigh_refPicList)
 {
     if (curr->pred_flag == PF_BI &&  neigh->pred_flag == PF_BI) {
         // same L0 and L1
@@ -734,9 +734,9 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0,
         boundary_upper = 0;
 
     if (boundary_upper) {
-        RefPicList *rpl_top = (lc->boundary_flags & BOUNDARY_UPPER_SLICE) ?
-                              ff_hevc_get_ref_list(s, s->ref, x0, y0 - 1) :
-                              s->ref->refPicList;
+        const RefPicList *rpl_top = (lc->boundary_flags & BOUNDARY_UPPER_SLICE) ?
+                                    ff_hevc_get_ref_list(s, s->ref, x0, y0 - 1) :
+                                    s->ref->refPicList;
         int yp_pu = (y0 - 1) >> log2_min_pu_size;
         int yq_pu =  y0      >> log2_min_pu_size;
         int yp_tu = (y0 - 1) >> log2_min_tu_size;
@@ -772,9 +772,9 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0,
         boundary_left = 0;
 
     if (boundary_left) {
-        RefPicList *rpl_left = (lc->boundary_flags & BOUNDARY_LEFT_SLICE) ?
-                               ff_hevc_get_ref_list(s, s->ref, x0 - 1, y0) :
-                               s->ref->refPicList;
+        const RefPicList *rpl_left = (lc->boundary_flags & BOUNDARY_LEFT_SLICE) ?
+                                     ff_hevc_get_ref_list(s, s->ref, x0 - 1, y0) :
+                                     s->ref->refPicList;
         int xp_pu = (x0 - 1) >> log2_min_pu_size;
         int xq_pu =  x0      >> log2_min_pu_size;
         int xp_tu = (x0 - 1) >> log2_min_tu_size;
diff --git a/libavcodec/hevc_mvs.c b/libavcodec/hevc_mvs.c
index 7477efcf52..516e4a6b7a 100644
--- a/libavcodec/hevc_mvs.c
+++ b/libavcodec/hevc_mvs.c
@@ -113,7 +113,7 @@ static av_always_inline int compare_mv_ref_idx(struct MvField A, struct MvField
     return 0;
 }
 
-static av_always_inline void mv_scale(Mv *dst, Mv *src, int td, int tb)
+static av_always_inline void mv_scale(Mv *dst, const Mv *src, int td, int tb)
 {
     int tx, scale_factor;
 
@@ -127,10 +127,10 @@ static av_always_inline void mv_scale(Mv *dst, Mv *src, int td, int tb)
                            (scale_factor * src->y < 0)) >> 8);
 }
 
-static int check_mvset(Mv *mvLXCol, Mv *mvCol,
+static int check_mvset(Mv *mvLXCol, const Mv *mvCol,
                        int colPic, int poc,
-                       RefPicList *refPicList, int X, int refIdxLx,
-                       RefPicList *refPicList_col, int listCol, int refidxCol)
+                       const RefPicList *refPicList, int X, int refIdxLx,
+                       const RefPicList *refPicList_col, int listCol, int refidxCol)
 {
     int cur_lt = refPicList[X].isLongTerm[refIdxLx];
     int col_lt = refPicList_col[listCol].isLongTerm[refidxCol];
@@ -163,7 +163,7 @@ static int check_mvset(Mv *mvLXCol, Mv *mvCol,
 // derive the motion vectors section 8.5.3.1.8
 static int derive_temporal_colocated_mvs(HEVCContext *s, MvField temp_col,
                                          int refIdxLx, Mv *mvLXCol, int X,
-                                         int colPic, RefPicList *refPicList_col)
+                                         int colPic, const RefPicList *refPicList_col)
 {
     RefPicList *refPicList = s->ref->refPicList;
 
diff --git a/libavcodec/hevc_refs.c b/libavcodec/hevc_refs.c
index fe18ca2b1d..6a70c817b0 100644
--- a/libavcodec/hevc_refs.c
+++ b/libavcodec/hevc_refs.c
@@ -55,13 +55,14 @@ void ff_hevc_unref_frame(HEVCContext *s, HEVCFrame *frame, int flags)
     }
 }
 
-RefPicList *ff_hevc_get_ref_list(HEVCContext *s, HEVCFrame *ref, int x0, int y0)
+const RefPicList *ff_hevc_get_ref_list(const HEVCContext *s,
+                                       const HEVCFrame *ref, int x0, int y0)
 {
     int x_cb         = x0 >> s->ps.sps->log2_ctb_size;
     int y_cb         = y0 >> s->ps.sps->log2_ctb_size;
     int pic_width_cb = s->ps.sps->ctb_width;
     int ctb_addr_ts  = s->ps.pps->ctb_addr_rs_to_ts[y_cb * pic_width_cb + x_cb];
-    return (RefPicList *)ref->rpl_tab[ctb_addr_ts];
+    return &ref->rpl_tab[ctb_addr_ts]->refPicList[0];
 }
 
 void ff_hevc_clear_refs(HEVCContext *s)
diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h
index a4cea2284d..271a55df2f 100644
--- a/libavcodec/hevcdec.h
+++ b/libavcodec/hevcdec.h
@@ -587,8 +587,8 @@ void ff_hevc_clear_refs(HEVCContext *s);
  */
 void ff_hevc_flush_dpb(HEVCContext *s);
 
-RefPicList *ff_hevc_get_ref_list(HEVCContext *s, HEVCFrame *frame,
-                                 int x0, int y0);
+const RefPicList *ff_hevc_get_ref_list(const HEVCContext *s, const HEVCFrame *frame,
+                                       int x0, int y0);
 
 /**
  * Construct the reference picture sets for the current frame.
-- 
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [FFmpeg-devel] [PATCH 06/18] avcodec/hevc_cabac: Don't cast const away unnecessarily
  2022-06-30 21:48 [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Andreas Rheinhardt
                   ` (3 preceding siblings ...)
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 05/18] avcodec/hevc_refs: Constify ff_hevc_get_ref_list() Andreas Rheinhardt
@ 2022-06-30 22:29 ` Andreas Rheinhardt
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 07/18] avcodec/hevc_mvs: Pass HEVCLocalContext when slice-threading Andreas Rheinhardt
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-06-30 22:29 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andreas Rheinhardt

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/hevc_cabac.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c
index 9b8c8e342d..a194f8a02a 100644
--- a/libavcodec/hevc_cabac.c
+++ b/libavcodec/hevc_cabac.c
@@ -1282,7 +1282,7 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,
             int scf_offset = 0;
             if (s->ps.sps->transform_skip_context_enabled_flag &&
                 (transform_skip_flag || lc->cu.cu_transquant_bypass_flag)) {
-                ctx_idx_map_p = (uint8_t*) &ctx_idx_map[4 * 16];
+                ctx_idx_map_p = &ctx_idx_map[4 * 16];
                 if (c_idx == 0) {
                     scf_offset = 40;
                 } else {
@@ -1292,9 +1292,9 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,
                 if (c_idx != 0)
                     scf_offset = 27;
                 if (log2_trafo_size == 2) {
-                    ctx_idx_map_p = (uint8_t*) &ctx_idx_map[0];
+                    ctx_idx_map_p = &ctx_idx_map[0];
                 } else {
-                    ctx_idx_map_p = (uint8_t*) &ctx_idx_map[(prev_sig + 1) << 4];
+                    ctx_idx_map_p = &ctx_idx_map[(prev_sig + 1) << 4];
                     if (c_idx == 0) {
                         if ((x_cg > 0 || y_cg > 0))
                             scf_offset += 3;
-- 
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [FFmpeg-devel] [PATCH 07/18] avcodec/hevc_mvs: Pass HEVCLocalContext when slice-threading
  2022-06-30 21:48 [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Andreas Rheinhardt
                   ` (4 preceding siblings ...)
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 06/18] avcodec/hevc_cabac: Don't cast const away unnecessarily Andreas Rheinhardt
@ 2022-06-30 22:29 ` Andreas Rheinhardt
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 08/18] avcodec/hevc_filter: " Andreas Rheinhardt
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-06-30 22:29 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andreas Rheinhardt

The HEVC decoder has both HEVCContext and HEVCLocalContext
structures. The latter is supposed to be the structure
containing the per-slicethread state.

Yet that is not how it is handled in practice: Each HEVCLocalContext
has a unique HEVCContext allocated for it and each of these
coincides except in exactly one field: The corresponding
HEVCLocalContext. This makes it possible to pass the HEVCContext
everywhere where logically a HEVCLocalContext should be used.

This commit stops doing this for lavc/hevc_mvs.c; it also constifies
everything that is possible in order to ensure that no slice thread
accidentally modifies the main HEVCContext state.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/hevc_mvs.c | 56 +++++++++++++++++++++----------------------
 libavcodec/hevcdec.c  | 27 +++++++++++----------
 libavcodec/hevcdec.h  |  6 ++---
 3 files changed, 45 insertions(+), 44 deletions(-)

diff --git a/libavcodec/hevc_mvs.c b/libavcodec/hevc_mvs.c
index 516e4a6b7a..bcf6ec3abc 100644
--- a/libavcodec/hevc_mvs.c
+++ b/libavcodec/hevc_mvs.c
@@ -40,10 +40,10 @@ static const uint8_t l0_l1_cand_idx[12][2] = {
     { 3, 2, },
 };
 
-void ff_hevc_set_neighbour_available(HEVCContext *s, int x0, int y0,
+void ff_hevc_set_neighbour_available(HEVCLocalContext *lc, int x0, int y0,
                                      int nPbW, int nPbH)
 {
-    HEVCLocalContext *lc = s->HEVClc;
+    const HEVCContext *const s = lc->parent;
     int x0b = av_mod_uintp2(x0, s->ps.sps->log2_ctb_size);
     int y0b = av_mod_uintp2(y0, s->ps.sps->log2_ctb_size);
 
@@ -62,7 +62,7 @@ void ff_hevc_set_neighbour_available(HEVCContext *s, int x0, int y0,
 /*
  * 6.4.1 Derivation process for z-scan order block availability
  */
-static av_always_inline int z_scan_block_avail(HEVCContext *s, int xCurr, int yCurr,
+static av_always_inline int z_scan_block_avail(const HEVCContext *s, int xCurr, int yCurr,
                               int xN, int yN)
 {
 #define MIN_TB_ADDR_ZS(x, y)                                            \
@@ -84,7 +84,7 @@ static av_always_inline int z_scan_block_avail(HEVCContext *s, int xCurr, int yC
 }
 
 //check if the two luma locations belong to the same motion estimation region
-static av_always_inline int is_diff_mer(HEVCContext *s, int xN, int yN, int xP, int yP)
+static av_always_inline int is_diff_mer(const HEVCContext *s, int xN, int yN, int xP, int yP)
 {
     uint8_t plevel = s->ps.pps->log2_parallel_merge_level;
 
@@ -161,11 +161,11 @@ static int check_mvset(Mv *mvLXCol, const Mv *mvCol,
                 refPicList_col, L ## l, temp_col.ref_idx[l])
 
 // derive the motion vectors section 8.5.3.1.8
-static int derive_temporal_colocated_mvs(HEVCContext *s, MvField temp_col,
+static int derive_temporal_colocated_mvs(const HEVCContext *s, MvField temp_col,
                                          int refIdxLx, Mv *mvLXCol, int X,
                                          int colPic, const RefPicList *refPicList_col)
 {
-    RefPicList *refPicList = s->ref->refPicList;
+    const RefPicList *refPicList = s->ref->refPicList;
 
     if (temp_col.pred_flag == PF_INTRA)
         return 0;
@@ -216,11 +216,11 @@ static int derive_temporal_colocated_mvs(HEVCContext *s, MvField temp_col,
 /*
  * 8.5.3.1.7  temporal luma motion vector prediction
  */
-static int temporal_luma_motion_vector(HEVCContext *s, int x0, int y0,
+static int temporal_luma_motion_vector(const HEVCContext *s, int x0, int y0,
                                        int nPbW, int nPbH, int refIdxLx,
                                        Mv *mvLXCol, int X)
 {
-    MvField *tab_mvf;
+    const MvField *tab_mvf;
     MvField temp_col;
     int x, y, x_pu, y_pu;
     int min_pu_width = s->ps.sps->min_pu_width;
@@ -283,16 +283,16 @@ static int temporal_luma_motion_vector(HEVCContext *s, int x0, int y0,
 /*
  * 8.5.3.1.2  Derivation process for spatial merging candidates
  */
-static void derive_spatial_merge_candidates(HEVCContext *s, int x0, int y0,
+static void derive_spatial_merge_candidates(HEVCLocalContext *lc, const HEVCContext *s,
+                                            int x0, int y0,
                                             int nPbW, int nPbH,
                                             int log2_cb_size,
                                             int singleMCLFlag, int part_idx,
                                             int merge_idx,
                                             struct MvField mergecandlist[])
 {
-    HEVCLocalContext *lc   = s->HEVClc;
-    RefPicList *refPicList = s->ref->refPicList;
-    MvField *tab_mvf       = s->ref->tab_mvf;
+    const RefPicList *refPicList = s->ref->refPicList;
+    const MvField *tab_mvf       = s->ref->tab_mvf;
 
     const int min_pu_width = s->ps.sps->min_pu_width;
 
@@ -477,16 +477,16 @@ static void derive_spatial_merge_candidates(HEVCContext *s, int x0, int y0,
 /*
  * 8.5.3.1.1 Derivation process of luma Mvs for merge mode
  */
-void ff_hevc_luma_mv_merge_mode(HEVCContext *s, int x0, int y0, int nPbW,
+void ff_hevc_luma_mv_merge_mode(HEVCLocalContext *lc, int x0, int y0, int nPbW,
                                 int nPbH, int log2_cb_size, int part_idx,
                                 int merge_idx, MvField *mv)
 {
+    const HEVCContext *const s = lc->parent;
     int singleMCLFlag = 0;
     int nCS = 1 << log2_cb_size;
     MvField mergecand_list[MRG_MAX_NUM_CANDS];
     int nPbW2 = nPbW;
     int nPbH2 = nPbH;
-    HEVCLocalContext *lc = s->HEVClc;
 
     if (s->ps.pps->log2_parallel_merge_level > 2 && nCS == 8) {
         singleMCLFlag = 1;
@@ -497,8 +497,8 @@ void ff_hevc_luma_mv_merge_mode(HEVCContext *s, int x0, int y0, int nPbW,
         part_idx      = 0;
     }
 
-    ff_hevc_set_neighbour_available(s, x0, y0, nPbW, nPbH);
-    derive_spatial_merge_candidates(s, x0, y0, nPbW, nPbH, log2_cb_size,
+    ff_hevc_set_neighbour_available(lc, x0, y0, nPbW, nPbH);
+    derive_spatial_merge_candidates(lc, s, x0, y0, nPbW, nPbH, log2_cb_size,
                                     singleMCLFlag, part_idx,
                                     merge_idx, mergecand_list);
 
@@ -510,12 +510,12 @@ void ff_hevc_luma_mv_merge_mode(HEVCContext *s, int x0, int y0, int nPbW,
     *mv = mergecand_list[merge_idx];
 }
 
-static av_always_inline void dist_scale(HEVCContext *s, Mv *mv,
+static av_always_inline void dist_scale(const HEVCContext *s, Mv *mv,
                                         int min_pu_width, int x, int y,
                                         int elist, int ref_idx_curr, int ref_idx)
 {
-    RefPicList *refPicList = s->ref->refPicList;
-    MvField *tab_mvf       = s->ref->tab_mvf;
+    const RefPicList *refPicList = s->ref->refPicList;
+    const MvField *tab_mvf       = s->ref->tab_mvf;
     int ref_pic_elist      = refPicList[elist].list[TAB_MVF(x, y).ref_idx[elist]];
     int ref_pic_curr       = refPicList[ref_idx_curr].list[ref_idx];
 
@@ -527,13 +527,13 @@ static av_always_inline void dist_scale(HEVCContext *s, Mv *mv,
     }
 }
 
-static int mv_mp_mode_mx(HEVCContext *s, int x, int y, int pred_flag_index,
+static int mv_mp_mode_mx(const HEVCContext *s, int x, int y, int pred_flag_index,
                          Mv *mv, int ref_idx_curr, int ref_idx)
 {
-    MvField *tab_mvf = s->ref->tab_mvf;
+    const MvField *tab_mvf = s->ref->tab_mvf;
     int min_pu_width = s->ps.sps->min_pu_width;
 
-    RefPicList *refPicList = s->ref->refPicList;
+    const RefPicList *refPicList = s->ref->refPicList;
 
     if (((TAB_MVF(x, y).pred_flag) & (1 << pred_flag_index)) &&
         refPicList[pred_flag_index].list[TAB_MVF(x, y).ref_idx[pred_flag_index]] == refPicList[ref_idx_curr].list[ref_idx]) {
@@ -543,13 +543,13 @@ static int mv_mp_mode_mx(HEVCContext *s, int x, int y, int pred_flag_index,
     return 0;
 }
 
-static int mv_mp_mode_mx_lt(HEVCContext *s, int x, int y, int pred_flag_index,
+static int mv_mp_mode_mx_lt(const HEVCContext *s, int x, int y, int pred_flag_index,
                             Mv *mv, int ref_idx_curr, int ref_idx)
 {
-    MvField *tab_mvf = s->ref->tab_mvf;
+    const MvField *tab_mvf = s->ref->tab_mvf;
     int min_pu_width = s->ps.sps->min_pu_width;
 
-    RefPicList *refPicList = s->ref->refPicList;
+    const RefPicList *refPicList = s->ref->refPicList;
 
     if ((TAB_MVF(x, y).pred_flag) & (1 << pred_flag_index)) {
         int currIsLongTerm     = refPicList[ref_idx_curr].isLongTerm[ref_idx];
@@ -580,13 +580,13 @@ static int mv_mp_mode_mx_lt(HEVCContext *s, int x, int y, int pred_flag_index,
                      (y ## v) >> s->ps.sps->log2_min_pu_size,      \
                      pred, &mx, ref_idx_curr, ref_idx)
 
-void ff_hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0, int nPbW,
+void ff_hevc_luma_mv_mvp_mode(HEVCLocalContext *lc, int x0, int y0, int nPbW,
                               int nPbH, int log2_cb_size, int part_idx,
                               int merge_idx, MvField *mv,
                               int mvp_lx_flag, int LX)
 {
-    HEVCLocalContext *lc = s->HEVClc;
-    MvField *tab_mvf = s->ref->tab_mvf;
+    const HEVCContext *const s = lc->parent;
+    const MvField *const tab_mvf = s->ref->tab_mvf;
     int isScaledFlag_L0 = 0;
     int availableFlagLXA0 = 1;
     int availableFlagLXB0 = 1;
diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index 111da42836..4786282669 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -1106,7 +1106,7 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
 
     if (lc->cu.pred_mode == MODE_INTRA) {
         int trafo_size = 1 << log2_trafo_size;
-        ff_hevc_set_neighbour_available(s, x0, y0, trafo_size, trafo_size);
+        ff_hevc_set_neighbour_available(lc, x0, y0, trafo_size, trafo_size);
 
         s->hpc.intra_pred[log2_trafo_size - 2](s, x0, y0, 0);
     }
@@ -1193,7 +1193,7 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
             }
             for (i = 0; i < (s->ps.sps->chroma_format_idc == 2 ? 2 : 1); i++) {
                 if (lc->cu.pred_mode == MODE_INTRA) {
-                    ff_hevc_set_neighbour_available(s, x0, y0 + (i << log2_trafo_size_c), trafo_size_h, trafo_size_v);
+                    ff_hevc_set_neighbour_available(lc, x0, y0 + (i << log2_trafo_size_c), trafo_size_h, trafo_size_v);
                     s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (i << log2_trafo_size_c), 1);
                 }
                 if (cbf_cb[i])
@@ -1222,7 +1222,8 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
             }
             for (i = 0; i < (s->ps.sps->chroma_format_idc == 2 ? 2 : 1); i++) {
                 if (lc->cu.pred_mode == MODE_INTRA) {
-                    ff_hevc_set_neighbour_available(s, x0, y0 + (i << log2_trafo_size_c), trafo_size_h, trafo_size_v);
+                    ff_hevc_set_neighbour_available(lc, x0, y0 + (i << log2_trafo_size_c),
+                                                    trafo_size_h, trafo_size_v);
                     s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (i << log2_trafo_size_c), 2);
                 }
                 if (cbf_cr[i])
@@ -1250,7 +1251,7 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
             int trafo_size_v = 1 << (log2_trafo_size + s->ps.sps->vshift[1]);
             for (i = 0; i < (s->ps.sps->chroma_format_idc == 2 ? 2 : 1); i++) {
                 if (lc->cu.pred_mode == MODE_INTRA) {
-                    ff_hevc_set_neighbour_available(s, xBase, yBase + (i << log2_trafo_size),
+                    ff_hevc_set_neighbour_available(lc, xBase, yBase + (i << log2_trafo_size),
                                                     trafo_size_h, trafo_size_v);
                     s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (i << log2_trafo_size), 1);
                 }
@@ -1260,7 +1261,7 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
             }
             for (i = 0; i < (s->ps.sps->chroma_format_idc == 2 ? 2 : 1); i++) {
                 if (lc->cu.pred_mode == MODE_INTRA) {
-                    ff_hevc_set_neighbour_available(s, xBase, yBase + (i << log2_trafo_size),
+                    ff_hevc_set_neighbour_available(lc, xBase, yBase + (i << log2_trafo_size),
                                                 trafo_size_h, trafo_size_v);
                     s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (i << log2_trafo_size), 2);
                 }
@@ -1273,11 +1274,11 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
         if (log2_trafo_size > 2 || s->ps.sps->chroma_format_idc == 3) {
             int trafo_size_h = 1 << (log2_trafo_size_c + s->ps.sps->hshift[1]);
             int trafo_size_v = 1 << (log2_trafo_size_c + s->ps.sps->vshift[1]);
-            ff_hevc_set_neighbour_available(s, x0, y0, trafo_size_h, trafo_size_v);
+            ff_hevc_set_neighbour_available(lc, x0, y0, trafo_size_h, trafo_size_v);
             s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0, 1);
             s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0, 2);
             if (s->ps.sps->chroma_format_idc == 2) {
-                ff_hevc_set_neighbour_available(s, x0, y0 + (1 << log2_trafo_size_c),
+                ff_hevc_set_neighbour_available(lc, x0, y0 + (1 << log2_trafo_size_c),
                                                 trafo_size_h, trafo_size_v);
                 s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (1 << log2_trafo_size_c), 1);
                 s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (1 << log2_trafo_size_c), 2);
@@ -1285,12 +1286,12 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
         } else if (blk_idx == 3) {
             int trafo_size_h = 1 << (log2_trafo_size + 1);
             int trafo_size_v = 1 << (log2_trafo_size + s->ps.sps->vshift[1]);
-            ff_hevc_set_neighbour_available(s, xBase, yBase,
+            ff_hevc_set_neighbour_available(lc, xBase, yBase,
                                             trafo_size_h, trafo_size_v);
             s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase, 1);
             s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase, 2);
             if (s->ps.sps->chroma_format_idc == 2) {
-                ff_hevc_set_neighbour_available(s, xBase, yBase + (1 << (log2_trafo_size)),
+                ff_hevc_set_neighbour_available(lc, xBase, yBase + (1 << (log2_trafo_size)),
                                                 trafo_size_h, trafo_size_v);
                 s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (1 << (log2_trafo_size)), 1);
                 s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (1 << (log2_trafo_size)), 2);
@@ -1821,7 +1822,7 @@ static void hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0, int nPbW,
     enum InterPredIdc inter_pred_idc = PRED_L0;
     int mvp_flag;
 
-    ff_hevc_set_neighbour_available(s, x0, y0, nPbW, nPbH);
+    ff_hevc_set_neighbour_available(lc, x0, y0, nPbW, nPbH);
     mv->pred_flag = 0;
     if (s->sh.slice_type == HEVC_SLICE_B)
         inter_pred_idc = ff_hevc_inter_pred_idc_decode(s, nPbW, nPbH);
@@ -1833,7 +1834,7 @@ static void hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0, int nPbW,
         mv->pred_flag = PF_L0;
         ff_hevc_hls_mvd_coding(s, x0, y0, 0);
         mvp_flag = ff_hevc_mvp_lx_flag_decode(s);
-        ff_hevc_luma_mv_mvp_mode(s, x0, y0, nPbW, nPbH, log2_cb_size,
+        ff_hevc_luma_mv_mvp_mode(lc, x0, y0, nPbW, nPbH, log2_cb_size,
                                  part_idx, merge_idx, mv, mvp_flag, 0);
         mv->mv[0].x += lc->pu.mvd.x;
         mv->mv[0].y += lc->pu.mvd.y;
@@ -1851,7 +1852,7 @@ static void hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0, int nPbW,
 
         mv->pred_flag += PF_L1;
         mvp_flag = ff_hevc_mvp_lx_flag_decode(s);
-        ff_hevc_luma_mv_mvp_mode(s, x0, y0, nPbW, nPbH, log2_cb_size,
+        ff_hevc_luma_mv_mvp_mode(lc, x0, y0, nPbW, nPbH, log2_cb_size,
                                  part_idx, merge_idx, mv, mvp_flag, 1);
         mv->mv[1].x += lc->pu.mvd.x;
         mv->mv[1].y += lc->pu.mvd.y;
@@ -1895,7 +1896,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0,
         else
             merge_idx = 0;
 
-        ff_hevc_luma_mv_merge_mode(s, x0, y0, nPbW, nPbH, log2_cb_size,
+        ff_hevc_luma_mv_merge_mode(lc, x0, y0, nPbW, nPbH, log2_cb_size,
                                    partIdx, merge_idx, &current_mv);
     } else {
         hevc_luma_mv_mvp_mode(s, x0, y0, nPbW, nPbH, log2_cb_size,
diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h
index 271a55df2f..3bb3fdb90a 100644
--- a/libavcodec/hevcdec.h
+++ b/libavcodec/hevcdec.h
@@ -667,12 +667,12 @@ void ff_hevc_bump_frame(HEVCContext *s);
 
 void ff_hevc_unref_frame(HEVCContext *s, HEVCFrame *frame, int flags);
 
-void ff_hevc_set_neighbour_available(HEVCContext *s, int x0, int y0,
+void ff_hevc_set_neighbour_available(HEVCLocalContext *lc, int x0, int y0,
                                      int nPbW, int nPbH);
-void ff_hevc_luma_mv_merge_mode(HEVCContext *s, int x0, int y0,
+void ff_hevc_luma_mv_merge_mode(HEVCLocalContext *lc, int x0, int y0,
                                 int nPbW, int nPbH, int log2_cb_size,
                                 int part_idx, int merge_idx, MvField *mv);
-void ff_hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0,
+void ff_hevc_luma_mv_mvp_mode(HEVCLocalContext *lc, int x0, int y0,
                               int nPbW, int nPbH, int log2_cb_size,
                               int part_idx, int merge_idx,
                               MvField *mv, int mvp_lx_flag, int LX);
-- 
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [FFmpeg-devel] [PATCH 08/18] avcodec/hevc_filter: Pass HEVCLocalContext when slice-threading
  2022-06-30 21:48 [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Andreas Rheinhardt
                   ` (5 preceding siblings ...)
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 07/18] avcodec/hevc_mvs: Pass HEVCLocalContext when slice-threading Andreas Rheinhardt
@ 2022-06-30 22:29 ` Andreas Rheinhardt
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 09/18] avcodec/hevcdec: Add stat_coeffs to HEVCABACState Andreas Rheinhardt
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-06-30 22:29 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andreas Rheinhardt

The HEVC decoder has both HEVCContext and HEVCLocalContext
structures. The latter is supposed to be the structure
containing the per-slicethread state.

Yet that is not how it is handled in practice: Each HEVCLocalContext
has a unique HEVCContext allocated for it and each of these
coincides with the main HEVCContext except in exactly one field:
The corresponding HEVCLocalContext.
This makes it possible to pass the HEVCContext everywhere where
logically a HEVCLocalContext should be used.

This commit stops doing this for lavc/hevc_filter.c; it also constifies
everything that is possible in order to ensure that no slice thread
accidentally modifies the main HEVCContext state.

There are places where this was not possible, namely with the SAOParams
in sao_filter_CTB() or with sao_pixels_buffer_h in copy_CTB_to_hv().
Both of these instances lead to data races, see
https://fate.ffmpeg.org/report.cgi?time=20220629145651&slot=x86_64-archlinux-gcc-tsan-slices

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/hevc_filter.c | 77 ++++++++++++++++++++--------------------
 libavcodec/hevcdec.c     | 21 +++++------
 libavcodec/hevcdec.h     |  8 ++---
 3 files changed, 54 insertions(+), 52 deletions(-)

diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c
index 7b53c66c3b..2fe05a2327 100644
--- a/libavcodec/hevc_filter.c
+++ b/libavcodec/hevc_filter.c
@@ -44,7 +44,7 @@ static const uint8_t betatable[52] = {
     38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64                      // QP 38...51
 };
 
-static int chroma_tc(HEVCContext *s, int qp_y, int c_idx, int tc_offset)
+static int chroma_tc(const HEVCContext *s, int qp_y, int c_idx, int tc_offset)
 {
     static const int qp_c[] = {
         29, 30, 31, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37
@@ -73,9 +73,9 @@ static int chroma_tc(HEVCContext *s, int qp_y, int c_idx, int tc_offset)
     return tctable[idxt];
 }
 
-static int get_qPy_pred(HEVCContext *s, int xBase, int yBase, int log2_cb_size)
+static int get_qPy_pred(HEVCLocalContext *lc, const HEVCContext *s,
+                        int xBase, int yBase, int log2_cb_size)
 {
-    HEVCLocalContext *lc     = s->HEVClc;
     int ctb_size_mask        = (1 << s->ps.sps->log2_ctb_size) - 1;
     int MinCuQpDeltaSizeMask = (1 << (s->ps.sps->log2_ctb_size -
                                       s->ps.pps->diff_cu_qp_delta_depth)) - 1;
@@ -116,19 +116,20 @@ static int get_qPy_pred(HEVCContext *s, int xBase, int yBase, int log2_cb_size)
     return (qPy_a + qPy_b + 1) >> 1;
 }
 
-void ff_hevc_set_qPy(HEVCContext *s, int xBase, int yBase, int log2_cb_size)
+void ff_hevc_set_qPy(HEVCLocalContext *lc, int xBase, int yBase, int log2_cb_size)
 {
-    int qp_y = get_qPy_pred(s, xBase, yBase, log2_cb_size);
+    const HEVCContext *const s = lc->parent;
+    int qp_y = get_qPy_pred(lc, s, xBase, yBase, log2_cb_size);
 
-    if (s->HEVClc->tu.cu_qp_delta != 0) {
+    if (lc->tu.cu_qp_delta != 0) {
         int off = s->ps.sps->qp_bd_offset;
-        s->HEVClc->qp_y = FFUMOD(qp_y + s->HEVClc->tu.cu_qp_delta + 52 + 2 * off,
+        lc->qp_y = FFUMOD(qp_y + lc->tu.cu_qp_delta + 52 + 2 * off,
                                  52 + off) - off;
     } else
-        s->HEVClc->qp_y = qp_y;
+        lc->qp_y = qp_y;
 }
 
-static int get_qPy(HEVCContext *s, int xC, int yC)
+static int get_qPy(const HEVCContext *s, int xC, int yC)
 {
     int log2_min_cb_size  = s->ps.sps->log2_min_cb_size;
     int x                 = xC >> log2_min_cb_size;
@@ -186,7 +187,7 @@ static void copy_vert(uint8_t *dst, const uint8_t *src,
     }
 }
 
-static void copy_CTB_to_hv(HEVCContext *s, const uint8_t *src,
+static void copy_CTB_to_hv(const HEVCContext *s, const uint8_t *src,
                            ptrdiff_t stride_src, int x, int y, int width, int height,
                            int c_idx, int x_ctb, int y_ctb)
 {
@@ -206,7 +207,7 @@ static void copy_CTB_to_hv(HEVCContext *s, const uint8_t *src,
     copy_vert(s->sao_pixel_buffer_v[c_idx] + (((2 * x_ctb + 1) * h + y) << sh), src + ((width - 1) << sh), sh, height, 1 << sh, stride_src);
 }
 
-static void restore_tqb_pixels(HEVCContext *s,
+static void restore_tqb_pixels(const HEVCContext *s,
                                uint8_t *src1, const uint8_t *dst1,
                                ptrdiff_t stride_src, ptrdiff_t stride_dst,
                                int x0, int y0, int width, int height, int c_idx)
@@ -241,10 +242,9 @@ static void restore_tqb_pixels(HEVCContext *s,
 
 #define CTB(tab, x, y) ((tab)[(y) * s->ps.sps->ctb_width + (x)])
 
-static void sao_filter_CTB(HEVCContext *s, int x, int y)
+static void sao_filter_CTB(HEVCLocalContext *lc, const HEVCContext *s, int x, int y)
 {
     static const uint8_t sao_tab[8] = { 0, 1, 2, 2, 3, 3, 4, 4 };
-    HEVCLocalContext *lc = s->HEVClc;
     int c_idx;
     int edges[4];  // 0 left 1 top 2 right 3 bottom
     int x_ctb                = x >> s->ps.sps->log2_ctb_size;
@@ -450,7 +450,7 @@ static void sao_filter_CTB(HEVCContext *s, int x, int y)
     }
 }
 
-static int get_pcm(HEVCContext *s, int x, int y)
+static int get_pcm(const HEVCContext *s, int x, int y)
 {
     int log2_min_pu_size = s->ps.sps->log2_min_pu_size;
     int x_pu, y_pu;
@@ -471,7 +471,7 @@ static int get_pcm(HEVCContext *s, int x, int y)
                     (tc_offset & -2),                                   \
                     0, MAX_QP + DEFAULT_INTRA_TC_OFFSET)]
 
-static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0)
+static void deblocking_filter_CTB(const HEVCContext *s, int x0, int y0)
 {
     uint8_t *src;
     int x, y;
@@ -709,11 +709,11 @@ static int boundary_strength(const HEVCContext *s, const MvField *curr, const Mv
     return 1;
 }
 
-void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0,
+void ff_hevc_deblocking_boundary_strengths(HEVCLocalContext *lc, int x0, int y0,
                                            int log2_trafo_size)
 {
-    HEVCLocalContext *lc = s->HEVClc;
-    MvField *tab_mvf     = s->ref->tab_mvf;
+    const HEVCContext *s = lc->parent;
+    const MvField *tab_mvf = s->ref->tab_mvf;
     int log2_min_pu_size = s->ps.sps->log2_min_pu_size;
     int log2_min_tu_size = s->ps.sps->log2_min_tb_size;
     int min_pu_width     = s->ps.sps->min_pu_width;
@@ -745,8 +745,8 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0,
             for (i = 0; i < (1 << log2_trafo_size); i += 4) {
                 int x_pu = (x0 + i) >> log2_min_pu_size;
                 int x_tu = (x0 + i) >> log2_min_tu_size;
-                MvField *top  = &tab_mvf[yp_pu * min_pu_width + x_pu];
-                MvField *curr = &tab_mvf[yq_pu * min_pu_width + x_pu];
+                const MvField *top  = &tab_mvf[yp_pu * min_pu_width + x_pu];
+                const MvField *curr = &tab_mvf[yq_pu * min_pu_width + x_pu];
                 uint8_t top_cbf_luma  = s->cbf_luma[yp_tu * min_tu_width + x_tu];
                 uint8_t curr_cbf_luma = s->cbf_luma[yq_tu * min_tu_width + x_tu];
 
@@ -783,8 +783,8 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0,
             for (i = 0; i < (1 << log2_trafo_size); i += 4) {
                 int y_pu      = (y0 + i) >> log2_min_pu_size;
                 int y_tu      = (y0 + i) >> log2_min_tu_size;
-                MvField *left = &tab_mvf[y_pu * min_pu_width + xp_pu];
-                MvField *curr = &tab_mvf[y_pu * min_pu_width + xq_pu];
+                const MvField *left = &tab_mvf[y_pu * min_pu_width + xp_pu];
+                const MvField *curr = &tab_mvf[y_pu * min_pu_width + xq_pu];
                 uint8_t left_cbf_luma = s->cbf_luma[y_tu * min_tu_width + xp_tu];
                 uint8_t curr_cbf_luma = s->cbf_luma[y_tu * min_tu_width + xq_tu];
 
@@ -799,7 +799,7 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0,
     }
 
     if (log2_trafo_size > log2_min_pu_size && !is_intra) {
-        RefPicList *rpl = s->ref->refPicList;
+        const RefPicList *rpl = s->ref->refPicList;
 
         // bs for TU internal horizontal PU boundaries
         for (j = 8; j < (1 << log2_trafo_size); j += 8) {
@@ -808,8 +808,8 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0,
 
             for (i = 0; i < (1 << log2_trafo_size); i += 4) {
                 int x_pu = (x0 + i) >> log2_min_pu_size;
-                MvField *top  = &tab_mvf[yp_pu * min_pu_width + x_pu];
-                MvField *curr = &tab_mvf[yq_pu * min_pu_width + x_pu];
+                const MvField *top  = &tab_mvf[yp_pu * min_pu_width + x_pu];
+                const MvField *curr = &tab_mvf[yq_pu * min_pu_width + x_pu];
 
                 bs = boundary_strength(s, curr, top, rpl);
                 s->horizontal_bs[((x0 + i) + (y0 + j) * s->bs_width) >> 2] = bs;
@@ -823,8 +823,8 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0,
             for (i = 8; i < (1 << log2_trafo_size); i += 8) {
                 int xp_pu = (x0 + i - 1) >> log2_min_pu_size;
                 int xq_pu = (x0 + i)     >> log2_min_pu_size;
-                MvField *left = &tab_mvf[y_pu * min_pu_width + xp_pu];
-                MvField *curr = &tab_mvf[y_pu * min_pu_width + xq_pu];
+                const MvField *left = &tab_mvf[y_pu * min_pu_width + xp_pu];
+                const MvField *curr = &tab_mvf[y_pu * min_pu_width + xq_pu];
 
                 bs = boundary_strength(s, curr, left, rpl);
                 s->vertical_bs[((x0 + i) + (y0 + j) * s->bs_width) >> 2] = bs;
@@ -837,8 +837,9 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0,
 #undef CB
 #undef CR
 
-void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size)
+void ff_hevc_hls_filter(HEVCLocalContext *lc, int x, int y, int ctb_size)
 {
+    const HEVCContext *const s = lc->parent;
     int x_end = x >= s->ps.sps->width  - ctb_size;
     int skip = 0;
     if (s->avctx->skip_loop_filter >= AVDISCARD_ALL ||
@@ -856,16 +857,16 @@ void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size)
     if (s->ps.sps->sao_enabled && !skip) {
         int y_end = y >= s->ps.sps->height - ctb_size;
         if (y && x)
-            sao_filter_CTB(s, x - ctb_size, y - ctb_size);
+            sao_filter_CTB(lc, s, x - ctb_size, y - ctb_size);
         if (x && y_end)
-            sao_filter_CTB(s, x - ctb_size, y);
+            sao_filter_CTB(lc, s, x - ctb_size, y);
         if (y && x_end) {
-            sao_filter_CTB(s, x, y - ctb_size);
+            sao_filter_CTB(lc, s, x, y - ctb_size);
             if (s->threads_type & FF_THREAD_FRAME )
                 ff_thread_report_progress(&s->ref->tf, y, 0);
         }
         if (x_end && y_end) {
-            sao_filter_CTB(s, x , y);
+            sao_filter_CTB(lc, s, x , y);
             if (s->threads_type & FF_THREAD_FRAME )
                 ff_thread_report_progress(&s->ref->tf, y + ctb_size, 0);
         }
@@ -873,14 +874,14 @@ void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size)
         ff_thread_report_progress(&s->ref->tf, y + ctb_size - 4, 0);
 }
 
-void ff_hevc_hls_filters(HEVCContext *s, int x_ctb, int y_ctb, int ctb_size)
+void ff_hevc_hls_filters(HEVCLocalContext *lc, int x_ctb, int y_ctb, int ctb_size)
 {
-    int x_end = x_ctb >= s->ps.sps->width  - ctb_size;
-    int y_end = y_ctb >= s->ps.sps->height - ctb_size;
+    int x_end = x_ctb >= lc->parent->ps.sps->width  - ctb_size;
+    int y_end = y_ctb >= lc->parent->ps.sps->height - ctb_size;
     if (y_ctb && x_ctb)
-        ff_hevc_hls_filter(s, x_ctb - ctb_size, y_ctb - ctb_size, ctb_size);
+        ff_hevc_hls_filter(lc, x_ctb - ctb_size, y_ctb - ctb_size, ctb_size);
     if (y_ctb && x_end)
-        ff_hevc_hls_filter(s, x_ctb, y_ctb - ctb_size, ctb_size);
+        ff_hevc_hls_filter(lc, x_ctb, y_ctb - ctb_size, ctb_size);
     if (x_ctb && y_end)
-        ff_hevc_hls_filter(s, x_ctb - ctb_size, y_ctb, ctb_size);
+        ff_hevc_hls_filter(lc, x_ctb - ctb_size, y_ctb, ctb_size);
 }
diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index 4786282669..33c9d74e5f 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -1137,7 +1137,7 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
                 return AVERROR_INVALIDDATA;
             }
 
-            ff_hevc_set_qPy(s, cb_xBase, cb_yBase, log2_cb_size);
+            ff_hevc_set_qPy(lc, cb_xBase, cb_yBase, log2_cb_size);
         }
 
         if (s->sh.cu_chroma_qp_offset_enabled_flag && cbf_chroma &&
@@ -1431,7 +1431,7 @@ do {
                 }
         }
         if (!s->sh.disable_deblocking_filter_flag) {
-            ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_trafo_size);
+            ff_hevc_deblocking_boundary_strengths(lc, x0, y0, log2_trafo_size);
             if (s->ps.pps->transquant_bypass_enable_flag &&
                 lc->cu.cu_transquant_bypass_flag)
                 set_deblocking_bypass(s, x0, y0, log2_trafo_size);
@@ -1460,7 +1460,7 @@ static int hls_pcm_sample(HEVCContext *s, int x0, int y0, int log2_cb_size)
     int ret;
 
     if (!s->sh.disable_deblocking_filter_flag)
-        ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_cb_size);
+        ff_hevc_deblocking_boundary_strengths(lc, x0, y0, log2_cb_size);
 
     ret = init_get_bits(&gb, pcm, length);
     if (ret < 0)
@@ -2224,7 +2224,7 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size)
         intra_prediction_unit_default_value(s, x0, y0, log2_cb_size);
 
         if (!s->sh.disable_deblocking_filter_flag)
-            ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_cb_size);
+            ff_hevc_deblocking_boundary_strengths(lc, x0, y0, log2_cb_size);
     } else {
         int pcm_flag = 0;
 
@@ -2312,13 +2312,13 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size)
                     return ret;
             } else {
                 if (!s->sh.disable_deblocking_filter_flag)
-                    ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_cb_size);
+                    ff_hevc_deblocking_boundary_strengths(lc, x0, y0, log2_cb_size);
             }
         }
     }
 
     if (s->ps.pps->cu_qp_delta_enabled_flag && lc->tu.is_cu_qp_delta_coded == 0)
-        ff_hevc_set_qPy(s, x0, y0, log2_cb_size);
+        ff_hevc_set_qPy(lc, x0, y0, log2_cb_size);
 
     x = y_cb * min_cb_width + x_cb;
     for (y = 0; y < length; y++) {
@@ -2473,6 +2473,7 @@ static void hls_decode_neighbour(HEVCContext *s, int x_ctb, int y_ctb,
 static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread)
 {
     HEVCContext *s  = avctxt->priv_data;
+    HEVCLocalContext *const lc = s->HEVClc;
     int ctb_size    = 1 << s->ps.sps->log2_ctb_size;
     int more_data   = 1;
     int x_ctb       = 0;
@@ -2521,12 +2522,12 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread)
 
         ctb_addr_ts++;
         ff_hevc_save_states(s, ctb_addr_ts);
-        ff_hevc_hls_filters(s, x_ctb, y_ctb, ctb_size);
+        ff_hevc_hls_filters(lc, x_ctb, y_ctb, ctb_size);
     }
 
     if (x_ctb + ctb_size >= s->ps.sps->width &&
         y_ctb + ctb_size >= s->ps.sps->height)
-        ff_hevc_hls_filter(s, x_ctb, y_ctb, ctb_size);
+        ff_hevc_hls_filter(lc, x_ctb, y_ctb, ctb_size);
 
     return ctb_addr_ts;
 }
@@ -2593,7 +2594,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *input_ctb_row, int
 
         ff_hevc_save_states(s, ctb_addr_ts);
         ff_thread_report_progress2(s->avctx, ctb_row, thread, 1);
-        ff_hevc_hls_filters(s, x_ctb, y_ctb, ctb_size);
+        ff_hevc_hls_filters(lc, x_ctb, y_ctb, ctb_size);
 
         if (!more_data && (x_ctb+ctb_size) < s->ps.sps->width && ctb_row != s->sh.num_entry_point_offsets) {
             atomic_store(&s1->wpp_err, 1);
@@ -2602,7 +2603,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *input_ctb_row, int
         }
 
         if ((x_ctb+ctb_size) >= s->ps.sps->width && (y_ctb+ctb_size) >= s->ps.sps->height ) {
-            ff_hevc_hls_filter(s, x_ctb, y_ctb, ctb_size);
+            ff_hevc_hls_filter(lc, x_ctb, y_ctb, ctb_size);
             ff_thread_report_progress2(s->avctx, ctb_row , thread, SHIFT_CTB_WPP);
             return ctb_addr_ts;
         }
diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h
index 3bb3fdb90a..e2dba54f26 100644
--- a/libavcodec/hevcdec.h
+++ b/libavcodec/hevcdec.h
@@ -676,16 +676,16 @@ void ff_hevc_luma_mv_mvp_mode(HEVCLocalContext *lc, int x0, int y0,
                               int nPbW, int nPbH, int log2_cb_size,
                               int part_idx, int merge_idx,
                               MvField *mv, int mvp_lx_flag, int LX);
-void ff_hevc_set_qPy(HEVCContext *s, int xBase, int yBase,
+void ff_hevc_hls_filter(HEVCLocalContext *lc, int x, int y, int ctb_size);
+void ff_hevc_hls_filters(HEVCLocalContext *lc, int x_ctb, int y_ctb, int ctb_size);
+void ff_hevc_set_qPy(HEVCLocalContext *lc, int xBase, int yBase,
                      int log2_cb_size);
-void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0,
+void ff_hevc_deblocking_boundary_strengths(HEVCLocalContext *lc, int x0, int y0,
                                            int log2_trafo_size);
 int ff_hevc_cu_qp_delta_sign_flag(HEVCContext *s);
 int ff_hevc_cu_qp_delta_abs(HEVCContext *s);
 int ff_hevc_cu_chroma_qp_offset_flag(HEVCContext *s);
 int ff_hevc_cu_chroma_qp_offset_idx(HEVCContext *s);
-void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size);
-void ff_hevc_hls_filters(HEVCContext *s, int x_ctb, int y_ctb, int ctb_size);
 void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,
                                  int log2_trafo_size, enum ScanType scan_idx,
                                  int c_idx);
-- 
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [FFmpeg-devel] [PATCH 09/18] avcodec/hevcdec: Add stat_coeffs to HEVCABACState
  2022-06-30 21:48 [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Andreas Rheinhardt
                   ` (6 preceding siblings ...)
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 08/18] avcodec/hevc_filter: " Andreas Rheinhardt
@ 2022-06-30 22:29 ` Andreas Rheinhardt
  2022-07-02  8:34   ` Anton Khirnov
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 10/18] avcodec/hevc_cabac: Pass HEVCLocalContext when slice-threading Andreas Rheinhardt
                   ` (9 subsequent siblings)
  17 siblings, 1 reply; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-06-30 22:29 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andreas Rheinhardt

The HEVC decoder has both HEVCContext and HEVCLocalContext
structures. The latter is supposed to be the structure
containing the per-slicethread state.

Yet that is not how it is handled in practice: Each HEVCLocalContext
has a unique HEVCContext allocated for it and each of these
coincides with the main HEVCContext except in exactly one field:
The corresponding HEVCLocalContext.
This makes it possible to pass the HEVCContext everywhere where
logically a HEVCLocalContext should be used.

This led to confusion in the first version of what eventually became
commit c8bc0f66a875bc3708d8dc11b757f2198606ffd7:
Before said commit, the initialization of the Rice parameter derivation
state was incorrect; the fix for single-threaded as well as
frame-threaded decoding was to add backup stats to HEVCContext
that are used when the cabac state is updated*, see
https://ffmpeg.org/pipermail/ffmpeg-devel/2020-August/268861.html
Yet due to what has been said above, this does not work for
slice-threading, because the each HEVCLocalContext has its own
HEVCContext, so the Rice parameter state would not be transferred
between threads.

This is fixed in c8bc0f66a875bc3708d8dc11b757f2198606ffd7
by a hack: It rederives what the previous thread was and accesses
the corresponding HEVCContext.

Fix this by treating the Rice parameter state the same way
the ordinary CABAC parameters are shared between threads:
Make them part of the same struct that is shared between
slice threads. This does not cause races, because
the parts of the code that access these Rice parameters
are a subset of the parts of code that access the CABAC parameters.

*: And if the persistent_rice_adaptation_enabled_flag is set.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/hevc_cabac.c | 17 ++++++++---------
 libavcodec/hevcdec.c    | 10 +++++-----
 libavcodec/hevcdec.h    | 10 +++++++---
 3 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c
index a194f8a02a..985c97ef2a 100644
--- a/libavcodec/hevc_cabac.c
+++ b/libavcodec/hevc_cabac.c
@@ -453,19 +453,18 @@ void ff_hevc_save_states(HEVCContext *s, int ctb_addr_ts)
         (ctb_addr_ts % s->ps.sps->ctb_width == 2 ||
          (s->ps.sps->ctb_width == 2 &&
           ctb_addr_ts % s->ps.sps->ctb_width == 0))) {
-        memcpy(s->cabac_state, s->HEVClc->cabac_state, HEVC_CONTEXTS);
+        memcpy(s->cabac->state, s->HEVClc->cabac_state, HEVC_CONTEXTS);
         if (s->ps.sps->persistent_rice_adaptation_enabled_flag) {
-            memcpy(s->stat_coeff, s->HEVClc->stat_coeff, HEVC_STAT_COEFFS);
+            memcpy(s->cabac->stat_coeff, s->HEVClc->stat_coeff, HEVC_STAT_COEFFS);
         }
     }
 }
 
-static void load_states(HEVCContext *s, int thread)
+static void load_states(HEVCContext *s)
 {
-    memcpy(s->HEVClc->cabac_state, s->cabac_state, HEVC_CONTEXTS);
+    memcpy(s->HEVClc->cabac_state, s->cabac->state, HEVC_CONTEXTS);
     if (s->ps.sps->persistent_rice_adaptation_enabled_flag) {
-        const HEVCContext *prev = s->sList[(thread + s->threads_number - 1) % s->threads_number];
-        memcpy(s->HEVClc->stat_coeff, prev->stat_coeff, HEVC_STAT_COEFFS);
+        memcpy(s->HEVClc->stat_coeff, s->cabac->stat_coeff, HEVC_STAT_COEFFS);
     }
 }
 
@@ -508,7 +507,7 @@ static void cabac_init_state(HEVCContext *s)
         s->HEVClc->stat_coeff[i] = 0;
 }
 
-int ff_hevc_cabac_init(HEVCContext *s, int ctb_addr_ts, int thread)
+int ff_hevc_cabac_init(HEVCContext *s, int ctb_addr_ts)
 {
     if (ctb_addr_ts == s->ps.pps->ctb_addr_rs_to_ts[s->sh.slice_ctb_addr_rs]) {
         int ret = cabac_init_decoder(s);
@@ -525,7 +524,7 @@ int ff_hevc_cabac_init(HEVCContext *s, int ctb_addr_ts, int thread)
                 if (s->ps.sps->ctb_width == 1)
                     cabac_init_state(s);
                 else if (s->sh.dependent_slice_segment_flag == 1)
-                    load_states(s, thread);
+                    load_states(s);
             }
         }
     } else {
@@ -556,7 +555,7 @@ int ff_hevc_cabac_init(HEVCContext *s, int ctb_addr_ts, int thread)
                 if (s->ps.sps->ctb_width == 1)
                     cabac_init_state(s);
                 else
-                    load_states(s, thread);
+                    load_states(s);
             }
         }
     }
diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index 33c9d74e5f..7d4de414cd 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -2501,7 +2501,7 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread)
         y_ctb = (ctb_addr_rs / ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size)) << s->ps.sps->log2_ctb_size;
         hls_decode_neighbour(s, x_ctb, y_ctb, ctb_addr_ts);
 
-        ret = ff_hevc_cabac_init(s, ctb_addr_ts, 0);
+        ret = ff_hevc_cabac_init(s, ctb_addr_ts);
         if (ret < 0) {
             s->tab_slice_address[ctb_addr_rs] = -1;
             return ret;
@@ -2579,7 +2579,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *input_ctb_row, int
             return 0;
         }
 
-        ret = ff_hevc_cabac_init(s, ctb_addr_ts, thread);
+        ret = ff_hevc_cabac_init(s, ctb_addr_ts);
         if (ret < 0)
             goto error;
         hls_sao_param(s, x_ctb >> s->ps.sps->log2_ctb_size, y_ctb >> s->ps.sps->log2_ctb_size);
@@ -3601,7 +3601,7 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx)
 
     av_freep(&s->md5_ctx);
 
-    av_freep(&s->cabac_state);
+    av_freep(&s->cabac);
 
     for (i = 0; i < 3; i++) {
         av_freep(&s->sao_pixel_buffer_h[i]);
@@ -3655,8 +3655,8 @@ static av_cold int hevc_init_context(AVCodecContext *avctx)
     s->HEVClcList[0] = s->HEVClc;
     s->sList[0] = s;
 
-    s->cabac_state = av_malloc(HEVC_CONTEXTS);
-    if (!s->cabac_state)
+    s->cabac = av_malloc(sizeof(*s->cabac));
+    if (!s->cabac)
         return AVERROR(ENOMEM);
 
     s->output_frame = av_frame_alloc();
diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h
index e2dba54f26..b97b7d1354 100644
--- a/libavcodec/hevcdec.h
+++ b/libavcodec/hevcdec.h
@@ -226,6 +226,11 @@ enum ScanType {
     SCAN_VERT,
 };
 
+typedef struct HEVCCABACState {
+    uint8_t state[HEVC_CONTEXTS];
+    uint8_t stat_coeff[HEVC_STAT_COEFFS];
+} HEVCCABACState;
+
 typedef struct LongTermRPS {
     int     poc[32];
     uint8_t poc_msb_present[32];
@@ -482,8 +487,7 @@ typedef struct HEVCContext {
     int                 width;
     int                 height;
 
-    uint8_t *cabac_state;
-    uint8_t stat_coeff[HEVC_STAT_COEFFS];
+    HEVCCABACState *cabac;
 
     /** 1 if the independent slice segment header was successfully parsed */
     uint8_t slice_initialized;
@@ -601,7 +605,7 @@ int ff_hevc_frame_rps(HEVCContext *s);
 int ff_hevc_slice_rpl(HEVCContext *s);
 
 void ff_hevc_save_states(HEVCContext *s, int ctb_addr_ts);
-int ff_hevc_cabac_init(HEVCContext *s, int ctb_addr_ts, int thread);
+int ff_hevc_cabac_init(HEVCContext *s, int ctb_addr_ts);
 int ff_hevc_sao_merge_flag_decode(HEVCContext *s);
 int ff_hevc_sao_type_idx_decode(HEVCContext *s);
 int ff_hevc_sao_band_position_decode(HEVCContext *s);
-- 
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [FFmpeg-devel] [PATCH 10/18] avcodec/hevc_cabac: Pass HEVCLocalContext when slice-threading
  2022-06-30 21:48 [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Andreas Rheinhardt
                   ` (7 preceding siblings ...)
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 09/18] avcodec/hevcdec: Add stat_coeffs to HEVCABACState Andreas Rheinhardt
@ 2022-06-30 22:29 ` Andreas Rheinhardt
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 11/18] avcodec/hevcpred: " Andreas Rheinhardt
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-06-30 22:29 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andreas Rheinhardt

The HEVC decoder has both HEVCContext and HEVCLocalContext
structures. The latter is supposed to be the structure
containing the per-slicethread state.

Yet that is not how it is handled in practice: Each HEVCLocalContext
has a unique HEVCContext allocated for it and each of these
coincides except in exactly one field: The corresponding
HEVCLocalContext. This makes it possible to pass the HEVCContext
everywhere where logically a HEVCLocalContext should be used.

This commit stops doing this for lavc/hevc_cabac.c; it also constifies
everything that is possible in order to ensure that no slice thread
accidentally modifies the main HEVCContext state.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/hevc_cabac.c | 310 +++++++++++++++++++++-------------------
 libavcodec/hevcdec.c    | 102 ++++++-------
 libavcodec/hevcdec.h    |  72 +++++-----
 3 files changed, 246 insertions(+), 238 deletions(-)

diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c
index 985c97ef2a..f8f349dc4c 100644
--- a/libavcodec/hevc_cabac.c
+++ b/libavcodec/hevc_cabac.c
@@ -447,24 +447,26 @@ static const uint8_t diag_scan8x8_inv[8][8] = {
     { 28, 36, 43, 49, 54, 58, 61, 63, },
 };
 
-void ff_hevc_save_states(HEVCContext *s, int ctb_addr_ts)
+void ff_hevc_save_states(HEVCLocalContext *lc, int ctb_addr_ts)
 {
+    const HEVCContext *const s = lc->parent;
+
     if (s->ps.pps->entropy_coding_sync_enabled_flag &&
         (ctb_addr_ts % s->ps.sps->ctb_width == 2 ||
          (s->ps.sps->ctb_width == 2 &&
           ctb_addr_ts % s->ps.sps->ctb_width == 0))) {
-        memcpy(s->cabac->state, s->HEVClc->cabac_state, HEVC_CONTEXTS);
+        memcpy(s->cabac->state, lc->cabac_state, HEVC_CONTEXTS);
         if (s->ps.sps->persistent_rice_adaptation_enabled_flag) {
-            memcpy(s->cabac->stat_coeff, s->HEVClc->stat_coeff, HEVC_STAT_COEFFS);
+            memcpy(s->cabac->stat_coeff, lc->stat_coeff, HEVC_STAT_COEFFS);
         }
     }
 }
 
-static void load_states(HEVCContext *s)
+static void load_states(HEVCLocalContext *lc, const HEVCContext *s)
 {
-    memcpy(s->HEVClc->cabac_state, s->cabac->state, HEVC_CONTEXTS);
+    memcpy(lc->cabac_state, s->cabac->state, HEVC_CONTEXTS);
     if (s->ps.sps->persistent_rice_adaptation_enabled_flag) {
-        memcpy(s->HEVClc->stat_coeff, s->cabac->stat_coeff, HEVC_STAT_COEFFS);
+        memcpy(lc->stat_coeff, s->cabac->stat_coeff, HEVC_STAT_COEFFS);
     }
 }
 
@@ -473,17 +475,17 @@ static int cabac_reinit(HEVCLocalContext *lc)
     return skip_bytes(&lc->cc, 0) == NULL ? AVERROR_INVALIDDATA : 0;
 }
 
-static int cabac_init_decoder(HEVCContext *s)
+static int cabac_init_decoder(HEVCLocalContext *lc)
 {
-    GetBitContext *gb = &s->HEVClc->gb;
+    GetBitContext *gb = &lc->gb;
     skip_bits(gb, 1);
     align_get_bits(gb);
-    return ff_init_cabac_decoder(&s->HEVClc->cc,
+    return ff_init_cabac_decoder(&lc->cc,
                           gb->buffer + get_bits_count(gb) / 8,
                           (get_bits_left(gb) + 7) / 8);
 }
 
-static void cabac_init_state(HEVCContext *s)
+static void cabac_init_state(HEVCLocalContext *lc, const HEVCContext *s)
 {
     int init_type = 2 - s->sh.slice_type;
     int i;
@@ -500,31 +502,33 @@ static void cabac_init_state(HEVCContext *s)
         pre ^= pre >> 31;
         if (pre > 124)
             pre = 124 + (pre & 1);
-        s->HEVClc->cabac_state[i] = pre;
+        lc->cabac_state[i] = pre;
     }
 
     for (i = 0; i < 4; i++)
-        s->HEVClc->stat_coeff[i] = 0;
+        lc->stat_coeff[i] = 0;
 }
 
-int ff_hevc_cabac_init(HEVCContext *s, int ctb_addr_ts)
+int ff_hevc_cabac_init(HEVCLocalContext *lc, int ctb_addr_ts)
 {
+    const HEVCContext *const s = lc->parent;
+
     if (ctb_addr_ts == s->ps.pps->ctb_addr_rs_to_ts[s->sh.slice_ctb_addr_rs]) {
-        int ret = cabac_init_decoder(s);
+        int ret = cabac_init_decoder(lc);
         if (ret < 0)
             return ret;
         if (s->sh.dependent_slice_segment_flag == 0 ||
             (s->ps.pps->tiles_enabled_flag &&
              s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[ctb_addr_ts - 1]))
-            cabac_init_state(s);
+            cabac_init_state(lc, s);
 
         if (!s->sh.first_slice_in_pic_flag &&
             s->ps.pps->entropy_coding_sync_enabled_flag) {
             if (ctb_addr_ts % s->ps.sps->ctb_width == 0) {
                 if (s->ps.sps->ctb_width == 1)
-                    cabac_init_state(s);
+                    cabac_init_state(lc, s);
                 else if (s->sh.dependent_slice_segment_flag == 1)
-                    load_states(s);
+                    load_states(lc, s);
             }
         }
     } else {
@@ -532,111 +536,112 @@ int ff_hevc_cabac_init(HEVCContext *s, int ctb_addr_ts)
             s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[ctb_addr_ts - 1]) {
             int ret;
             if (s->threads_number == 1)
-                ret = cabac_reinit(s->HEVClc);
+                ret = cabac_reinit(lc);
             else {
-                ret = cabac_init_decoder(s);
+                ret = cabac_init_decoder(lc);
             }
             if (ret < 0)
                 return ret;
-            cabac_init_state(s);
+            cabac_init_state(lc, s);
         }
         if (s->ps.pps->entropy_coding_sync_enabled_flag) {
             if (ctb_addr_ts % s->ps.sps->ctb_width == 0) {
                 int ret;
-                get_cabac_terminate(&s->HEVClc->cc);
+                get_cabac_terminate(&lc->cc);
                 if (s->threads_number == 1)
-                    ret = cabac_reinit(s->HEVClc);
+                    ret = cabac_reinit(lc);
                 else {
-                    ret = cabac_init_decoder(s);
+                    ret = cabac_init_decoder(lc);
                 }
                 if (ret < 0)
                     return ret;
 
                 if (s->ps.sps->ctb_width == 1)
-                    cabac_init_state(s);
+                    cabac_init_state(lc, s);
                 else
-                    load_states(s);
+                    load_states(lc, s);
             }
         }
     }
     return 0;
 }
 
-#define GET_CABAC(ctx) get_cabac(&s->HEVClc->cc, &s->HEVClc->cabac_state[ctx])
+#define GET_CABAC(ctx)  get_cabac(&lc->cc, &lc->cabac_state[ctx])
 
-int ff_hevc_sao_merge_flag_decode(HEVCContext *s)
+int ff_hevc_sao_merge_flag_decode(HEVCLocalContext *lc)
 {
     return GET_CABAC(elem_offset[SAO_MERGE_FLAG]);
 }
 
-int ff_hevc_sao_type_idx_decode(HEVCContext *s)
+int ff_hevc_sao_type_idx_decode(HEVCLocalContext *lc)
 {
     if (!GET_CABAC(elem_offset[SAO_TYPE_IDX]))
         return 0;
 
-    if (!get_cabac_bypass(&s->HEVClc->cc))
+    if (!get_cabac_bypass(&lc->cc))
         return SAO_BAND;
     return SAO_EDGE;
 }
 
-int ff_hevc_sao_band_position_decode(HEVCContext *s)
+int ff_hevc_sao_band_position_decode(HEVCLocalContext *lc)
 {
     int i;
-    int value = get_cabac_bypass(&s->HEVClc->cc);
+    int value = get_cabac_bypass(&lc->cc);
 
     for (i = 0; i < 4; i++)
-        value = (value << 1) | get_cabac_bypass(&s->HEVClc->cc);
+        value = (value << 1) | get_cabac_bypass(&lc->cc);
     return value;
 }
 
-int ff_hevc_sao_offset_abs_decode(HEVCContext *s)
+int ff_hevc_sao_offset_abs_decode(HEVCLocalContext *lc)
 {
     int i = 0;
-    int length = (1 << (FFMIN(s->ps.sps->bit_depth, 10) - 5)) - 1;
+    int length = (1 << (FFMIN(lc->parent->ps.sps->bit_depth, 10) - 5)) - 1;
 
-    while (i < length && get_cabac_bypass(&s->HEVClc->cc))
+    while (i < length && get_cabac_bypass(&lc->cc))
         i++;
     return i;
 }
 
-int ff_hevc_sao_offset_sign_decode(HEVCContext *s)
+int ff_hevc_sao_offset_sign_decode(HEVCLocalContext *lc)
 {
-    return get_cabac_bypass(&s->HEVClc->cc);
+    return get_cabac_bypass(&lc->cc);
 }
 
-int ff_hevc_sao_eo_class_decode(HEVCContext *s)
+int ff_hevc_sao_eo_class_decode(HEVCLocalContext *lc)
 {
-    int ret = get_cabac_bypass(&s->HEVClc->cc) << 1;
-    ret    |= get_cabac_bypass(&s->HEVClc->cc);
+    int ret = get_cabac_bypass(&lc->cc) << 1;
+    ret    |= get_cabac_bypass(&lc->cc);
     return ret;
 }
 
-int ff_hevc_end_of_slice_flag_decode(HEVCContext *s)
+int ff_hevc_end_of_slice_flag_decode(HEVCLocalContext *lc)
 {
-    return get_cabac_terminate(&s->HEVClc->cc);
+    return get_cabac_terminate(&lc->cc);
 }
 
-int ff_hevc_cu_transquant_bypass_flag_decode(HEVCContext *s)
+int ff_hevc_cu_transquant_bypass_flag_decode(HEVCLocalContext *lc)
 {
     return GET_CABAC(elem_offset[CU_TRANSQUANT_BYPASS_FLAG]);
 }
 
-int ff_hevc_skip_flag_decode(HEVCContext *s, int x0, int y0, int x_cb, int y_cb)
+int ff_hevc_skip_flag_decode(HEVCLocalContext *lc, int x0, int y0, int x_cb, int y_cb)
 {
+    const HEVCContext *const s = lc->parent;
     int min_cb_width = s->ps.sps->min_cb_width;
     int inc = 0;
     int x0b = av_mod_uintp2(x0, s->ps.sps->log2_ctb_size);
     int y0b = av_mod_uintp2(y0, s->ps.sps->log2_ctb_size);
 
-    if (s->HEVClc->ctb_left_flag || x0b)
+    if (lc->ctb_left_flag || x0b)
         inc = !!SAMPLE_CTB(s->skip_flag, x_cb - 1, y_cb);
-    if (s->HEVClc->ctb_up_flag || y0b)
+    if (lc->ctb_up_flag || y0b)
         inc += !!SAMPLE_CTB(s->skip_flag, x_cb, y_cb - 1);
 
     return GET_CABAC(elem_offset[SKIP_FLAG] + inc);
 }
 
-int ff_hevc_cu_qp_delta_abs(HEVCContext *s)
+int ff_hevc_cu_qp_delta_abs(HEVCLocalContext *lc)
 {
     int prefix_val = 0;
     int suffix_val = 0;
@@ -648,34 +653,34 @@ int ff_hevc_cu_qp_delta_abs(HEVCContext *s)
     }
     if (prefix_val >= 5) {
         int k = 0;
-        while (k < 7 && get_cabac_bypass(&s->HEVClc->cc)) {
+        while (k < 7 && get_cabac_bypass(&lc->cc)) {
             suffix_val += 1 << k;
             k++;
         }
         if (k == 7) {
-            av_log(s->avctx, AV_LOG_ERROR, "CABAC_MAX_BIN : %d\n", k);
+            av_log(lc->logctx, AV_LOG_ERROR, "CABAC_MAX_BIN : %d\n", k);
             return AVERROR_INVALIDDATA;
         }
 
         while (k--)
-            suffix_val += get_cabac_bypass(&s->HEVClc->cc) << k;
+            suffix_val += get_cabac_bypass(&lc->cc) << k;
     }
     return prefix_val + suffix_val;
 }
 
-int ff_hevc_cu_qp_delta_sign_flag(HEVCContext *s)
+int ff_hevc_cu_qp_delta_sign_flag(HEVCLocalContext *lc)
 {
-    return get_cabac_bypass(&s->HEVClc->cc);
+    return get_cabac_bypass(&lc->cc);
 }
 
-int ff_hevc_cu_chroma_qp_offset_flag(HEVCContext *s)
+int ff_hevc_cu_chroma_qp_offset_flag(HEVCLocalContext *lc)
 {
     return GET_CABAC(elem_offset[CU_CHROMA_QP_OFFSET_FLAG]);
 }
 
-int ff_hevc_cu_chroma_qp_offset_idx(HEVCContext *s)
+int ff_hevc_cu_chroma_qp_offset_idx(HEVCLocalContext *lc)
 {
-    int c_max= FFMAX(5, s->ps.pps->chroma_qp_offset_list_len_minus1);
+    int c_max= FFMAX(5, lc->parent->ps.pps->chroma_qp_offset_list_len_minus1);
     int i = 0;
 
     while (i < c_max && GET_CABAC(elem_offset[CU_CHROMA_QP_OFFSET_IDX]))
@@ -684,23 +689,25 @@ int ff_hevc_cu_chroma_qp_offset_idx(HEVCContext *s)
     return i;
 }
 
-int ff_hevc_pred_mode_decode(HEVCContext *s)
+int ff_hevc_pred_mode_decode(HEVCLocalContext *lc)
 {
     return GET_CABAC(elem_offset[PRED_MODE_FLAG]);
 }
 
-int ff_hevc_split_coding_unit_flag_decode(HEVCContext *s, int ct_depth, int x0, int y0)
+int ff_hevc_split_coding_unit_flag_decode(HEVCLocalContext *lc, int ct_depth, int x0, int y0)
 {
+    const HEVCContext *const s = lc->parent;
+    const HEVCSPS *const sps = s->ps.sps;
     int inc = 0, depth_left = 0, depth_top = 0;
-    int x0b  = av_mod_uintp2(x0, s->ps.sps->log2_ctb_size);
-    int y0b  = av_mod_uintp2(y0, s->ps.sps->log2_ctb_size);
-    int x_cb = x0 >> s->ps.sps->log2_min_cb_size;
-    int y_cb = y0 >> s->ps.sps->log2_min_cb_size;
+    int x0b  = av_mod_uintp2(x0, sps->log2_ctb_size);
+    int y0b  = av_mod_uintp2(y0, sps->log2_ctb_size);
+    int x_cb = x0 >> sps->log2_min_cb_size;
+    int y_cb = y0 >> sps->log2_min_cb_size;
 
-    if (s->HEVClc->ctb_left_flag || x0b)
-        depth_left = s->tab_ct_depth[(y_cb) * s->ps.sps->min_cb_width + x_cb - 1];
-    if (s->HEVClc->ctb_up_flag || y0b)
-        depth_top = s->tab_ct_depth[(y_cb - 1) * s->ps.sps->min_cb_width + x_cb];
+    if (lc->ctb_left_flag || x0b)
+        depth_left = s->tab_ct_depth[(y_cb)     * sps->min_cb_width + x_cb - 1];
+    if (lc->ctb_up_flag || y0b)
+        depth_top  = s->tab_ct_depth[(y_cb - 1) * sps->min_cb_width + x_cb];
 
     inc += (depth_left > ct_depth);
     inc += (depth_top  > ct_depth);
@@ -708,12 +715,12 @@ int ff_hevc_split_coding_unit_flag_decode(HEVCContext *s, int ct_depth, int x0,
     return GET_CABAC(elem_offset[SPLIT_CODING_UNIT_FLAG] + inc);
 }
 
-int ff_hevc_part_mode_decode(HEVCContext *s, int log2_cb_size)
+int ff_hevc_part_mode_decode(HEVCLocalContext *lc, int log2_cb_size)
 {
     if (GET_CABAC(elem_offset[PART_MODE])) // 1
         return PART_2Nx2N;
-    if (log2_cb_size == s->ps.sps->log2_min_cb_size) {
-        if (s->HEVClc->cu.pred_mode == MODE_INTRA) // 0
+    if (log2_cb_size == lc->parent->ps.sps->log2_min_cb_size) {
+        if (lc->cu.pred_mode == MODE_INTRA) // 0
             return PART_NxN;
         if (GET_CABAC(elem_offset[PART_MODE] + 1)) // 01
             return PART_2NxN;
@@ -724,7 +731,7 @@ int ff_hevc_part_mode_decode(HEVCContext *s, int log2_cb_size)
         return PART_NxN; // 000
     }
 
-    if (!s->ps.sps->amp_enabled_flag) {
+    if (!lc->parent->ps.sps->amp_enabled_flag) {
         if (GET_CABAC(elem_offset[PART_MODE] + 1)) // 01
             return PART_2NxN;
         return PART_Nx2N;
@@ -733,84 +740,84 @@ int ff_hevc_part_mode_decode(HEVCContext *s, int log2_cb_size)
     if (GET_CABAC(elem_offset[PART_MODE] + 1)) { // 01X, 01XX
         if (GET_CABAC(elem_offset[PART_MODE] + 3)) // 011
             return PART_2NxN;
-        if (get_cabac_bypass(&s->HEVClc->cc)) // 0101
+        if (get_cabac_bypass(&lc->cc)) // 0101
             return PART_2NxnD;
         return PART_2NxnU; // 0100
     }
 
     if (GET_CABAC(elem_offset[PART_MODE] + 3)) // 001
         return PART_Nx2N;
-    if (get_cabac_bypass(&s->HEVClc->cc)) // 0001
+    if (get_cabac_bypass(&lc->cc)) // 0001
         return PART_nRx2N;
     return PART_nLx2N;  // 0000
 }
 
-int ff_hevc_pcm_flag_decode(HEVCContext *s)
+int ff_hevc_pcm_flag_decode(HEVCLocalContext *lc)
 {
-    return get_cabac_terminate(&s->HEVClc->cc);
+    return get_cabac_terminate(&lc->cc);
 }
 
-int ff_hevc_prev_intra_luma_pred_flag_decode(HEVCContext *s)
+int ff_hevc_prev_intra_luma_pred_flag_decode(HEVCLocalContext *lc)
 {
     return GET_CABAC(elem_offset[PREV_INTRA_LUMA_PRED_FLAG]);
 }
 
-int ff_hevc_mpm_idx_decode(HEVCContext *s)
+int ff_hevc_mpm_idx_decode(HEVCLocalContext *lc)
 {
     int i = 0;
-    while (i < 2 && get_cabac_bypass(&s->HEVClc->cc))
+    while (i < 2 && get_cabac_bypass(&lc->cc))
         i++;
     return i;
 }
 
-int ff_hevc_rem_intra_luma_pred_mode_decode(HEVCContext *s)
+int ff_hevc_rem_intra_luma_pred_mode_decode(HEVCLocalContext *lc)
 {
     int i;
-    int value = get_cabac_bypass(&s->HEVClc->cc);
+    int value = get_cabac_bypass(&lc->cc);
 
     for (i = 0; i < 4; i++)
-        value = (value << 1) | get_cabac_bypass(&s->HEVClc->cc);
+        value = (value << 1) | get_cabac_bypass(&lc->cc);
     return value;
 }
 
-int ff_hevc_intra_chroma_pred_mode_decode(HEVCContext *s)
+int ff_hevc_intra_chroma_pred_mode_decode(HEVCLocalContext *lc)
 {
     int ret;
     if (!GET_CABAC(elem_offset[INTRA_CHROMA_PRED_MODE]))
         return 4;
 
-    ret  = get_cabac_bypass(&s->HEVClc->cc) << 1;
-    ret |= get_cabac_bypass(&s->HEVClc->cc);
+    ret  = get_cabac_bypass(&lc->cc) << 1;
+    ret |= get_cabac_bypass(&lc->cc);
     return ret;
 }
 
-int ff_hevc_merge_idx_decode(HEVCContext *s)
+int ff_hevc_merge_idx_decode(HEVCLocalContext *lc)
 {
     int i = GET_CABAC(elem_offset[MERGE_IDX]);
 
     if (i != 0) {
-        while (i < s->sh.max_num_merge_cand-1 && get_cabac_bypass(&s->HEVClc->cc))
+        while (i < lc->parent->sh.max_num_merge_cand-1 && get_cabac_bypass(&lc->cc))
             i++;
     }
     return i;
 }
 
-int ff_hevc_merge_flag_decode(HEVCContext *s)
+int ff_hevc_merge_flag_decode(HEVCLocalContext *lc)
 {
     return GET_CABAC(elem_offset[MERGE_FLAG]);
 }
 
-int ff_hevc_inter_pred_idc_decode(HEVCContext *s, int nPbW, int nPbH)
+int ff_hevc_inter_pred_idc_decode(HEVCLocalContext *lc, int nPbW, int nPbH)
 {
     if (nPbW + nPbH == 12)
         return GET_CABAC(elem_offset[INTER_PRED_IDC] + 4);
-    if (GET_CABAC(elem_offset[INTER_PRED_IDC] + s->HEVClc->ct_depth))
+    if (GET_CABAC(elem_offset[INTER_PRED_IDC] + lc->ct_depth))
         return PRED_BI;
 
     return GET_CABAC(elem_offset[INTER_PRED_IDC] + 4);
 }
 
-int ff_hevc_ref_idx_lx_decode(HEVCContext *s, int num_ref_idx_lx)
+int ff_hevc_ref_idx_lx_decode(HEVCLocalContext *lc, int num_ref_idx_lx)
 {
     int i = 0;
     int max = num_ref_idx_lx - 1;
@@ -819,87 +826,88 @@ int ff_hevc_ref_idx_lx_decode(HEVCContext *s, int num_ref_idx_lx)
     while (i < max_ctx && GET_CABAC(elem_offset[REF_IDX_L0] + i))
         i++;
     if (i == 2) {
-        while (i < max && get_cabac_bypass(&s->HEVClc->cc))
+        while (i < max && get_cabac_bypass(&lc->cc))
             i++;
     }
 
     return i;
 }
 
-int ff_hevc_mvp_lx_flag_decode(HEVCContext *s)
+int ff_hevc_mvp_lx_flag_decode(HEVCLocalContext *lc)
 {
     return GET_CABAC(elem_offset[MVP_LX_FLAG]);
 }
 
-int ff_hevc_no_residual_syntax_flag_decode(HEVCContext *s)
+int ff_hevc_no_residual_syntax_flag_decode(HEVCLocalContext *lc)
 {
     return GET_CABAC(elem_offset[NO_RESIDUAL_DATA_FLAG]);
 }
 
-static av_always_inline int abs_mvd_greater0_flag_decode(HEVCContext *s)
+static av_always_inline int abs_mvd_greater0_flag_decode(HEVCLocalContext *lc)
 {
     return GET_CABAC(elem_offset[ABS_MVD_GREATER0_FLAG]);
 }
 
-static av_always_inline int abs_mvd_greater1_flag_decode(HEVCContext *s)
+static av_always_inline int abs_mvd_greater1_flag_decode(HEVCLocalContext *lc)
 {
     return GET_CABAC(elem_offset[ABS_MVD_GREATER1_FLAG] + 1);
 }
 
-static av_always_inline int mvd_decode(HEVCContext *s)
+static av_always_inline int mvd_decode(HEVCLocalContext *lc)
 {
     int ret = 2;
     int k = 1;
 
-    while (k < CABAC_MAX_BIN && get_cabac_bypass(&s->HEVClc->cc)) {
+    while (k < CABAC_MAX_BIN && get_cabac_bypass(&lc->cc)) {
         ret += 1U << k;
         k++;
     }
     if (k == CABAC_MAX_BIN) {
-        av_log(s->avctx, AV_LOG_ERROR, "CABAC_MAX_BIN : %d\n", k);
+        av_log(lc->logctx, AV_LOG_ERROR, "CABAC_MAX_BIN : %d\n", k);
         return 0;
     }
     while (k--)
-        ret += get_cabac_bypass(&s->HEVClc->cc) << k;
-    return get_cabac_bypass_sign(&s->HEVClc->cc, -ret);
+        ret += get_cabac_bypass(&lc->cc) << k;
+    return get_cabac_bypass_sign(&lc->cc, -ret);
 }
 
-static av_always_inline int mvd_sign_flag_decode(HEVCContext *s)
+static av_always_inline int mvd_sign_flag_decode(HEVCLocalContext *lc)
 {
-    return get_cabac_bypass_sign(&s->HEVClc->cc, -1);
+    return get_cabac_bypass_sign(&lc->cc, -1);
 }
 
-int ff_hevc_split_transform_flag_decode(HEVCContext *s, int log2_trafo_size)
+int ff_hevc_split_transform_flag_decode(HEVCLocalContext *lc, int log2_trafo_size)
 {
     return GET_CABAC(elem_offset[SPLIT_TRANSFORM_FLAG] + 5 - log2_trafo_size);
 }
 
-int ff_hevc_cbf_cb_cr_decode(HEVCContext *s, int trafo_depth)
+int ff_hevc_cbf_cb_cr_decode(HEVCLocalContext *lc, int trafo_depth)
 {
     return GET_CABAC(elem_offset[CBF_CB_CR] + trafo_depth);
 }
 
-int ff_hevc_cbf_luma_decode(HEVCContext *s, int trafo_depth)
+int ff_hevc_cbf_luma_decode(HEVCLocalContext *lc, int trafo_depth)
 {
     return GET_CABAC(elem_offset[CBF_LUMA] + !trafo_depth);
 }
 
-static int hevc_transform_skip_flag_decode(HEVCContext *s, int c_idx)
+static int hevc_transform_skip_flag_decode(HEVCLocalContext *lc, int c_idx)
 {
     return GET_CABAC(elem_offset[TRANSFORM_SKIP_FLAG] + !!c_idx);
 }
 
-static int explicit_rdpcm_flag_decode(HEVCContext *s, int c_idx)
+static int explicit_rdpcm_flag_decode(HEVCLocalContext *lc, int c_idx)
 {
     return GET_CABAC(elem_offset[EXPLICIT_RDPCM_FLAG] + !!c_idx);
 }
 
-static int explicit_rdpcm_dir_flag_decode(HEVCContext *s, int c_idx)
+static int explicit_rdpcm_dir_flag_decode(HEVCLocalContext *lc, int c_idx)
 {
     return GET_CABAC(elem_offset[EXPLICIT_RDPCM_DIR_FLAG] + !!c_idx);
 }
 
-int ff_hevc_log2_res_scale_abs(HEVCContext *s, int idx) {
+int ff_hevc_log2_res_scale_abs(HEVCLocalContext *lc, int idx)
+{
     int i =0;
 
     while (i < 4 && GET_CABAC(elem_offset[LOG2_RES_SCALE_ABS] + 4 * idx + i))
@@ -908,11 +916,12 @@ int ff_hevc_log2_res_scale_abs(HEVCContext *s, int idx) {
     return i;
 }
 
-int ff_hevc_res_scale_sign_flag(HEVCContext *s, int idx) {
+int ff_hevc_res_scale_sign_flag(HEVCLocalContext *lc, int idx)
+{
     return GET_CABAC(elem_offset[RES_SCALE_SIGN_FLAG] + idx);
 }
 
-static av_always_inline void last_significant_coeff_xy_prefix_decode(HEVCContext *s, int c_idx,
+static av_always_inline void last_significant_coeff_xy_prefix_decode(HEVCLocalContext *lc, int c_idx,
                                                    int log2_size, int *last_scx_prefix, int *last_scy_prefix)
 {
     int i = 0;
@@ -938,19 +947,19 @@ static av_always_inline void last_significant_coeff_xy_prefix_decode(HEVCContext
     *last_scy_prefix = i;
 }
 
-static av_always_inline int last_significant_coeff_suffix_decode(HEVCContext *s,
+static av_always_inline int last_significant_coeff_suffix_decode(HEVCLocalContext *lc,
                                                  int last_significant_coeff_prefix)
 {
     int i;
     int length = (last_significant_coeff_prefix >> 1) - 1;
-    int value = get_cabac_bypass(&s->HEVClc->cc);
+    int value = get_cabac_bypass(&lc->cc);
 
     for (i = 1; i < length; i++)
-        value = (value << 1) | get_cabac_bypass(&s->HEVClc->cc);
+        value = (value << 1) | get_cabac_bypass(&lc->cc);
     return value;
 }
 
-static av_always_inline int significant_coeff_group_flag_decode(HEVCContext *s, int c_idx, int ctx_cg)
+static av_always_inline int significant_coeff_group_flag_decode(HEVCLocalContext *lc, int c_idx, int ctx_cg)
 {
     int inc;
 
@@ -958,19 +967,19 @@ static av_always_inline int significant_coeff_group_flag_decode(HEVCContext *s,
 
     return GET_CABAC(elem_offset[SIGNIFICANT_COEFF_GROUP_FLAG] + inc);
 }
-static av_always_inline int significant_coeff_flag_decode(HEVCContext *s, int x_c, int y_c,
+static av_always_inline int significant_coeff_flag_decode(HEVCLocalContext *lc, int x_c, int y_c,
                                            int offset, const uint8_t *ctx_idx_map)
 {
     int inc = ctx_idx_map[(y_c << 2) + x_c] + offset;
     return GET_CABAC(elem_offset[SIGNIFICANT_COEFF_FLAG] + inc);
 }
 
-static av_always_inline int significant_coeff_flag_decode_0(HEVCContext *s, int c_idx, int offset)
+static av_always_inline int significant_coeff_flag_decode_0(HEVCLocalContext *lc, int c_idx, int offset)
 {
     return GET_CABAC(elem_offset[SIGNIFICANT_COEFF_FLAG] + offset);
 }
 
-static av_always_inline int coeff_abs_level_greater1_flag_decode(HEVCContext *s, int c_idx, int inc)
+static av_always_inline int coeff_abs_level_greater1_flag_decode(HEVCLocalContext *lc, int c_idx, int inc)
 {
 
     if (c_idx > 0)
@@ -979,7 +988,7 @@ static av_always_inline int coeff_abs_level_greater1_flag_decode(HEVCContext *s,
     return GET_CABAC(elem_offset[COEFF_ABS_LEVEL_GREATER1_FLAG] + inc);
 }
 
-static av_always_inline int coeff_abs_level_greater2_flag_decode(HEVCContext *s, int c_idx, int inc)
+static av_always_inline int coeff_abs_level_greater2_flag_decode(HEVCLocalContext *lc, int c_idx, int inc)
 {
     if (c_idx > 0)
         inc += 4;
@@ -987,47 +996,47 @@ static av_always_inline int coeff_abs_level_greater2_flag_decode(HEVCContext *s,
     return GET_CABAC(elem_offset[COEFF_ABS_LEVEL_GREATER2_FLAG] + inc);
 }
 
-static av_always_inline int coeff_abs_level_remaining_decode(HEVCContext *s, int rc_rice_param)
+static av_always_inline int coeff_abs_level_remaining_decode(HEVCLocalContext *lc, int rc_rice_param)
 {
     int prefix = 0;
     int suffix = 0;
     int last_coeff_abs_level_remaining;
     int i;
 
-    while (prefix < CABAC_MAX_BIN && get_cabac_bypass(&s->HEVClc->cc))
+    while (prefix < CABAC_MAX_BIN && get_cabac_bypass(&lc->cc))
         prefix++;
 
     if (prefix < 3) {
         for (i = 0; i < rc_rice_param; i++)
-            suffix = (suffix << 1) | get_cabac_bypass(&s->HEVClc->cc);
+            suffix = (suffix << 1) | get_cabac_bypass(&lc->cc);
         last_coeff_abs_level_remaining = (prefix << rc_rice_param) + suffix;
     } else {
         int prefix_minus3 = prefix - 3;
 
         if (prefix == CABAC_MAX_BIN || prefix_minus3 + rc_rice_param > 16 + 6) {
-            av_log(s->avctx, AV_LOG_ERROR, "CABAC_MAX_BIN : %d\n", prefix);
+            av_log(lc->logctx, AV_LOG_ERROR, "CABAC_MAX_BIN : %d\n", prefix);
             return 0;
         }
 
         for (i = 0; i < prefix_minus3 + rc_rice_param; i++)
-            suffix = (suffix << 1) | get_cabac_bypass(&s->HEVClc->cc);
+            suffix = (suffix << 1) | get_cabac_bypass(&lc->cc);
         last_coeff_abs_level_remaining = (((1 << prefix_minus3) + 3 - 1)
                                               << rc_rice_param) + suffix;
     }
     return last_coeff_abs_level_remaining;
 }
 
-static av_always_inline int coeff_sign_flag_decode(HEVCContext *s, uint8_t nb)
+static av_always_inline int coeff_sign_flag_decode(HEVCLocalContext *lc, uint8_t nb)
 {
     int i;
     int ret = 0;
 
     for (i = 0; i < nb; i++)
-        ret = (ret << 1) | get_cabac_bypass(&s->HEVClc->cc);
+        ret = (ret << 1) | get_cabac_bypass(&lc->cc);
     return ret;
 }
 
-void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,
+void ff_hevc_hls_residual_coding(HEVCLocalContext *lc, int x0, int y0,
                                 int log2_trafo_size, enum ScanType scan_idx,
                                 int c_idx)
 {
@@ -1036,7 +1045,7 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,
         x_c = (x_cg << 2) + scan_x_off[n];                      \
         y_c = (y_cg << 2) + scan_y_off[n];                      \
     } while (0)
-    HEVCLocalContext *lc = s->HEVClc;
+    const HEVCContext *const s = lc->parent;
     int transform_skip_flag = 0;
 
     int last_significant_coeff_x, last_significant_coeff_y;
@@ -1091,7 +1100,7 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,
 
         if (s->ps.pps->transform_skip_enabled_flag &&
             log2_trafo_size <= s->ps.pps->log2_max_transform_skip_block_size) {
-            transform_skip_flag = hevc_transform_skip_flag_decode(s, c_idx);
+            transform_skip_flag = hevc_transform_skip_flag_decode(lc, c_idx);
         }
 
         if (c_idx == 0) {
@@ -1150,24 +1159,24 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,
 
     if (lc->cu.pred_mode == MODE_INTER && s->ps.sps->explicit_rdpcm_enabled_flag &&
         (transform_skip_flag || lc->cu.cu_transquant_bypass_flag)) {
-        explicit_rdpcm_flag = explicit_rdpcm_flag_decode(s, c_idx);
+        explicit_rdpcm_flag = explicit_rdpcm_flag_decode(lc, c_idx);
         if (explicit_rdpcm_flag) {
-            explicit_rdpcm_dir_flag = explicit_rdpcm_dir_flag_decode(s, c_idx);
+            explicit_rdpcm_dir_flag = explicit_rdpcm_dir_flag_decode(lc, c_idx);
         }
     }
 
-    last_significant_coeff_xy_prefix_decode(s, c_idx, log2_trafo_size,
+    last_significant_coeff_xy_prefix_decode(lc, c_idx, log2_trafo_size,
                                            &last_significant_coeff_x, &last_significant_coeff_y);
 
     if (last_significant_coeff_x > 3) {
-        int suffix = last_significant_coeff_suffix_decode(s, last_significant_coeff_x);
+        int suffix = last_significant_coeff_suffix_decode(lc, last_significant_coeff_x);
         last_significant_coeff_x = (1 << ((last_significant_coeff_x >> 1) - 1)) *
         (2 + (last_significant_coeff_x & 1)) +
         suffix;
     }
 
     if (last_significant_coeff_y > 3) {
-        int suffix = last_significant_coeff_suffix_decode(s, last_significant_coeff_y);
+        int suffix = last_significant_coeff_suffix_decode(lc, last_significant_coeff_y);
         last_significant_coeff_y = (1 << ((last_significant_coeff_y >> 1) - 1)) *
         (2 + (last_significant_coeff_y & 1)) +
         suffix;
@@ -1246,7 +1255,7 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,
                 ctx_cg += significant_coeff_group_flag[x_cg][y_cg + 1];
 
             significant_coeff_group_flag[x_cg][y_cg] =
-                significant_coeff_group_flag_decode(s, c_idx, ctx_cg);
+                significant_coeff_group_flag_decode(lc, c_idx, ctx_cg);
             implicit_non_zero_coeff = 1;
         } else {
             significant_coeff_group_flag[x_cg][y_cg] =
@@ -1313,7 +1322,7 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,
             for (n = n_end; n > 0; n--) {
                 x_c = scan_x_off[n];
                 y_c = scan_y_off[n];
-                if (significant_coeff_flag_decode(s, x_c, y_c, scf_offset, ctx_idx_map_p)) {
+                if (significant_coeff_flag_decode(lc, x_c, y_c, scf_offset, ctx_idx_map_p)) {
                     significant_coeff_flag_idx[nb_significant_coeff_flag] = n;
                     nb_significant_coeff_flag++;
                     implicit_non_zero_coeff = 0;
@@ -1337,7 +1346,7 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,
                         scf_offset = 2 + scf_offset;
                     }
                 }
-                if (significant_coeff_flag_decode_0(s, c_idx, scf_offset) == 1) {
+                if (significant_coeff_flag_decode_0(lc, c_idx, scf_offset) == 1) {
                     significant_coeff_flag_idx[nb_significant_coeff_flag] = 0;
                     nb_significant_coeff_flag++;
                 }
@@ -1381,7 +1390,7 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,
             for (m = 0; m < (n_end > 8 ? 8 : n_end); m++) {
                 int inc = (ctx_set << 2) + greater1_ctx;
                 coeff_abs_level_greater1_flag[m] =
-                    coeff_abs_level_greater1_flag_decode(s, c_idx, inc);
+                    coeff_abs_level_greater1_flag_decode(lc, c_idx, inc);
                 if (coeff_abs_level_greater1_flag[m]) {
                     greater1_ctx = 0;
                     if (first_greater1_coeff_idx == -1)
@@ -1402,12 +1411,12 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,
                 sign_hidden = (last_nz_pos_in_cg - first_nz_pos_in_cg >= 4);
 
             if (first_greater1_coeff_idx != -1) {
-                coeff_abs_level_greater1_flag[first_greater1_coeff_idx] += coeff_abs_level_greater2_flag_decode(s, c_idx, ctx_set);
+                coeff_abs_level_greater1_flag[first_greater1_coeff_idx] += coeff_abs_level_greater2_flag_decode(lc, c_idx, ctx_set);
             }
             if (!s->ps.pps->sign_data_hiding_flag || !sign_hidden ) {
-                coeff_sign_flag = coeff_sign_flag_decode(s, nb_significant_coeff_flag) << (16 - nb_significant_coeff_flag);
+                coeff_sign_flag = coeff_sign_flag_decode(lc, nb_significant_coeff_flag) << (16 - nb_significant_coeff_flag);
             } else {
-                coeff_sign_flag = coeff_sign_flag_decode(s, nb_significant_coeff_flag - 1) << (16 - (nb_significant_coeff_flag - 1));
+                coeff_sign_flag = coeff_sign_flag_decode(lc, nb_significant_coeff_flag - 1) << (16 - (nb_significant_coeff_flag - 1));
             }
 
             for (m = 0; m < n_end; m++) {
@@ -1416,7 +1425,7 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,
                 if (m < 8) {
                     trans_coeff_level = 1 + coeff_abs_level_greater1_flag[m];
                     if (trans_coeff_level == ((m == first_greater1_coeff_idx) ? 3 : 2)) {
-                        int last_coeff_abs_level_remaining = coeff_abs_level_remaining_decode(s, c_rice_param);
+                        int last_coeff_abs_level_remaining = coeff_abs_level_remaining_decode(lc, c_rice_param);
 
                         trans_coeff_level += last_coeff_abs_level_remaining;
                         if (trans_coeff_level > (3 << c_rice_param))
@@ -1432,7 +1441,7 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,
                         }
                     }
                 } else {
-                    int last_coeff_abs_level_remaining = coeff_abs_level_remaining_decode(s, c_rice_param);
+                    int last_coeff_abs_level_remaining = coeff_abs_level_remaining_decode(lc, c_rice_param);
 
                     trans_coeff_level = 1 + last_coeff_abs_level_remaining;
                     if (trans_coeff_level > (3 << c_rice_param))
@@ -1537,26 +1546,25 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,
     s->hevcdsp.add_residual[log2_trafo_size-2](dst, coeffs, stride);
 }
 
-void ff_hevc_hls_mvd_coding(HEVCContext *s, int x0, int y0, int log2_cb_size)
+void ff_hevc_hls_mvd_coding(HEVCLocalContext *lc, int x0, int y0, int log2_cb_size)
 {
-    HEVCLocalContext *lc = s->HEVClc;
-    int x = abs_mvd_greater0_flag_decode(s);
-    int y = abs_mvd_greater0_flag_decode(s);
+    int x = abs_mvd_greater0_flag_decode(lc);
+    int y = abs_mvd_greater0_flag_decode(lc);
 
     if (x)
-        x += abs_mvd_greater1_flag_decode(s);
+        x += abs_mvd_greater1_flag_decode(lc);
     if (y)
-        y += abs_mvd_greater1_flag_decode(s);
+        y += abs_mvd_greater1_flag_decode(lc);
 
     switch (x) {
-    case 2: lc->pu.mvd.x = mvd_decode(s);           break;
-    case 1: lc->pu.mvd.x = mvd_sign_flag_decode(s); break;
+    case 2: lc->pu.mvd.x = mvd_decode(lc);           break;
+    case 1: lc->pu.mvd.x = mvd_sign_flag_decode(lc); break;
     case 0: lc->pu.mvd.x = 0;                       break;
     }
 
     switch (y) {
-    case 2: lc->pu.mvd.y = mvd_decode(s);           break;
-    case 1: lc->pu.mvd.y = mvd_sign_flag_decode(s); break;
+    case 2: lc->pu.mvd.y = mvd_decode(lc);           break;
+    case 1: lc->pu.mvd.y = mvd_sign_flag_decode(lc); break;
     case 0: lc->pu.mvd.y = 0;                       break;
     }
 }
diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index 7d4de414cd..b3965932e9 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -1017,11 +1017,11 @@ static void hls_sao_param(HEVCContext *s, int rx, int ry)
         s->sh.slice_sample_adaptive_offset_flag[1]) {
         if (rx > 0) {
             if (lc->ctb_left_flag)
-                sao_merge_left_flag = ff_hevc_sao_merge_flag_decode(s);
+                sao_merge_left_flag = ff_hevc_sao_merge_flag_decode(lc);
         }
         if (ry > 0 && !sao_merge_left_flag) {
             if (lc->ctb_up_flag)
-                sao_merge_up_flag = ff_hevc_sao_merge_flag_decode(s);
+                sao_merge_up_flag = ff_hevc_sao_merge_flag_decode(lc);
         }
     }
 
@@ -1038,27 +1038,27 @@ static void hls_sao_param(HEVCContext *s, int rx, int ry)
             sao->type_idx[2] = sao->type_idx[1];
             sao->eo_class[2] = sao->eo_class[1];
         } else {
-            SET_SAO(type_idx[c_idx], ff_hevc_sao_type_idx_decode(s));
+            SET_SAO(type_idx[c_idx], ff_hevc_sao_type_idx_decode(lc));
         }
 
         if (sao->type_idx[c_idx] == SAO_NOT_APPLIED)
             continue;
 
         for (i = 0; i < 4; i++)
-            SET_SAO(offset_abs[c_idx][i], ff_hevc_sao_offset_abs_decode(s));
+            SET_SAO(offset_abs[c_idx][i], ff_hevc_sao_offset_abs_decode(lc));
 
         if (sao->type_idx[c_idx] == SAO_BAND) {
             for (i = 0; i < 4; i++) {
                 if (sao->offset_abs[c_idx][i]) {
                     SET_SAO(offset_sign[c_idx][i],
-                            ff_hevc_sao_offset_sign_decode(s));
+                            ff_hevc_sao_offset_sign_decode(lc));
                 } else {
                     sao->offset_sign[c_idx][i] = 0;
                 }
             }
-            SET_SAO(band_position[c_idx], ff_hevc_sao_band_position_decode(s));
+            SET_SAO(band_position[c_idx], ff_hevc_sao_band_position_decode(lc));
         } else if (c_idx != 2) {
-            SET_SAO(eo_class[c_idx], ff_hevc_sao_eo_class_decode(s));
+            SET_SAO(eo_class[c_idx], ff_hevc_sao_eo_class_decode(lc));
         }
 
         // Inferred parameters
@@ -1081,10 +1081,10 @@ static void hls_sao_param(HEVCContext *s, int rx, int ry)
 
 static int hls_cross_component_pred(HEVCContext *s, int idx) {
     HEVCLocalContext *lc    = s->HEVClc;
-    int log2_res_scale_abs_plus1 = ff_hevc_log2_res_scale_abs(s, idx);
+    int log2_res_scale_abs_plus1 = ff_hevc_log2_res_scale_abs(lc, idx);
 
     if (log2_res_scale_abs_plus1 !=  0) {
-        int res_scale_sign_flag = ff_hevc_res_scale_sign_flag(s, idx);
+        int res_scale_sign_flag = ff_hevc_res_scale_sign_flag(lc, idx);
         lc->tu.res_scale_val = (1 << (log2_res_scale_abs_plus1 - 1)) *
                                (1 - 2 * res_scale_sign_flag);
     } else {
@@ -1120,9 +1120,9 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
                          (cbf_cb[1] || cbf_cr[1]));
 
         if (s->ps.pps->cu_qp_delta_enabled_flag && !lc->tu.is_cu_qp_delta_coded) {
-            lc->tu.cu_qp_delta = ff_hevc_cu_qp_delta_abs(s);
+            lc->tu.cu_qp_delta = ff_hevc_cu_qp_delta_abs(lc);
             if (lc->tu.cu_qp_delta != 0)
-                if (ff_hevc_cu_qp_delta_sign_flag(s) == 1)
+                if (ff_hevc_cu_qp_delta_sign_flag(lc) == 1)
                     lc->tu.cu_qp_delta = -lc->tu.cu_qp_delta;
             lc->tu.is_cu_qp_delta_coded = 1;
 
@@ -1142,11 +1142,11 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
 
         if (s->sh.cu_chroma_qp_offset_enabled_flag && cbf_chroma &&
             !lc->cu.cu_transquant_bypass_flag  &&  !lc->tu.is_cu_chroma_qp_offset_coded) {
-            int cu_chroma_qp_offset_flag = ff_hevc_cu_chroma_qp_offset_flag(s);
+            int cu_chroma_qp_offset_flag = ff_hevc_cu_chroma_qp_offset_flag(lc);
             if (cu_chroma_qp_offset_flag) {
                 int cu_chroma_qp_offset_idx  = 0;
                 if (s->ps.pps->chroma_qp_offset_list_len_minus1 > 0) {
-                    cu_chroma_qp_offset_idx = ff_hevc_cu_chroma_qp_offset_idx(s);
+                    cu_chroma_qp_offset_idx = ff_hevc_cu_chroma_qp_offset_idx(lc);
                     av_log(s->avctx, AV_LOG_ERROR,
                         "cu_chroma_qp_offset_idx not yet tested.\n");
                 }
@@ -1180,7 +1180,7 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
         lc->tu.cross_pf = 0;
 
         if (cbf_luma)
-            ff_hevc_hls_residual_coding(s, x0, y0, log2_trafo_size, scan_idx, 0);
+            ff_hevc_hls_residual_coding(lc, x0, y0, log2_trafo_size, scan_idx, 0);
         if (s->ps.sps->chroma_format_idc && (log2_trafo_size > 2 || s->ps.sps->chroma_format_idc == 3)) {
             int trafo_size_h = 1 << (log2_trafo_size_c + s->ps.sps->hshift[1]);
             int trafo_size_v = 1 << (log2_trafo_size_c + s->ps.sps->vshift[1]);
@@ -1197,7 +1197,7 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
                     s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (i << log2_trafo_size_c), 1);
                 }
                 if (cbf_cb[i])
-                    ff_hevc_hls_residual_coding(s, x0, y0 + (i << log2_trafo_size_c),
+                    ff_hevc_hls_residual_coding(lc, x0, y0 + (i << log2_trafo_size_c),
                                                 log2_trafo_size_c, scan_idx_c, 1);
                 else
                     if (lc->tu.cross_pf) {
@@ -1227,7 +1227,7 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
                     s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (i << log2_trafo_size_c), 2);
                 }
                 if (cbf_cr[i])
-                    ff_hevc_hls_residual_coding(s, x0, y0 + (i << log2_trafo_size_c),
+                    ff_hevc_hls_residual_coding(lc, x0, y0 + (i << log2_trafo_size_c),
                                                 log2_trafo_size_c, scan_idx_c, 2);
                 else
                     if (lc->tu.cross_pf) {
@@ -1256,7 +1256,7 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
                     s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (i << log2_trafo_size), 1);
                 }
                 if (cbf_cb[i])
-                    ff_hevc_hls_residual_coding(s, xBase, yBase + (i << log2_trafo_size),
+                    ff_hevc_hls_residual_coding(lc, xBase, yBase + (i << log2_trafo_size),
                                                 log2_trafo_size, scan_idx_c, 1);
             }
             for (i = 0; i < (s->ps.sps->chroma_format_idc == 2 ? 2 : 1); i++) {
@@ -1266,7 +1266,7 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
                     s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (i << log2_trafo_size), 2);
                 }
                 if (cbf_cr[i])
-                    ff_hevc_hls_residual_coding(s, xBase, yBase + (i << log2_trafo_size),
+                    ff_hevc_hls_residual_coding(lc, xBase, yBase + (i << log2_trafo_size),
                                                 log2_trafo_size, scan_idx_c, 2);
             }
         }
@@ -1355,7 +1355,7 @@ static int hls_transform_tree(HEVCContext *s, int x0, int y0,
         log2_trafo_size >  s->ps.sps->log2_min_tb_size    &&
         trafo_depth     < lc->cu.max_trafo_depth       &&
         !(lc->cu.intra_split_flag && trafo_depth == 0)) {
-        split_transform_flag = ff_hevc_split_transform_flag_decode(s, log2_trafo_size);
+        split_transform_flag = ff_hevc_split_transform_flag_decode(lc, log2_trafo_size);
     } else {
         int inter_split = s->ps.sps->max_transform_hierarchy_depth_inter == 0 &&
                           lc->cu.pred_mode == MODE_INTER &&
@@ -1369,16 +1369,16 @@ static int hls_transform_tree(HEVCContext *s, int x0, int y0,
 
     if (s->ps.sps->chroma_format_idc && (log2_trafo_size > 2 || s->ps.sps->chroma_format_idc == 3)) {
         if (trafo_depth == 0 || cbf_cb[0]) {
-            cbf_cb[0] = ff_hevc_cbf_cb_cr_decode(s, trafo_depth);
+            cbf_cb[0] = ff_hevc_cbf_cb_cr_decode(lc, trafo_depth);
             if (s->ps.sps->chroma_format_idc == 2 && (!split_transform_flag || log2_trafo_size == 3)) {
-                cbf_cb[1] = ff_hevc_cbf_cb_cr_decode(s, trafo_depth);
+                cbf_cb[1] = ff_hevc_cbf_cb_cr_decode(lc, trafo_depth);
             }
         }
 
         if (trafo_depth == 0 || cbf_cr[0]) {
-            cbf_cr[0] = ff_hevc_cbf_cb_cr_decode(s, trafo_depth);
+            cbf_cr[0] = ff_hevc_cbf_cb_cr_decode(lc, trafo_depth);
             if (s->ps.sps->chroma_format_idc == 2 && (!split_transform_flag || log2_trafo_size == 3)) {
-                cbf_cr[1] = ff_hevc_cbf_cb_cr_decode(s, trafo_depth);
+                cbf_cr[1] = ff_hevc_cbf_cb_cr_decode(lc, trafo_depth);
             }
         }
     }
@@ -1412,7 +1412,7 @@ do {
         if (lc->cu.pred_mode == MODE_INTRA || trafo_depth != 0 ||
             cbf_cb[0] || cbf_cr[0] ||
             (s->ps.sps->chroma_format_idc == 2 && (cbf_cb[1] || cbf_cr[1]))) {
-            cbf_luma = ff_hevc_cbf_luma_decode(s, trafo_depth);
+            cbf_luma = ff_hevc_cbf_luma_decode(lc, trafo_depth);
         }
 
         ret = hls_transform_unit(s, x0, y0, xBase, yBase, cb_xBase, cb_yBase,
@@ -1825,15 +1825,15 @@ static void hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0, int nPbW,
     ff_hevc_set_neighbour_available(lc, x0, y0, nPbW, nPbH);
     mv->pred_flag = 0;
     if (s->sh.slice_type == HEVC_SLICE_B)
-        inter_pred_idc = ff_hevc_inter_pred_idc_decode(s, nPbW, nPbH);
+        inter_pred_idc = ff_hevc_inter_pred_idc_decode(lc, nPbW, nPbH);
 
     if (inter_pred_idc != PRED_L1) {
         if (s->sh.nb_refs[L0])
-            mv->ref_idx[0]= ff_hevc_ref_idx_lx_decode(s, s->sh.nb_refs[L0]);
+            mv->ref_idx[0]= ff_hevc_ref_idx_lx_decode(lc, s->sh.nb_refs[L0]);
 
         mv->pred_flag = PF_L0;
-        ff_hevc_hls_mvd_coding(s, x0, y0, 0);
-        mvp_flag = ff_hevc_mvp_lx_flag_decode(s);
+        ff_hevc_hls_mvd_coding(lc, x0, y0, 0);
+        mvp_flag = ff_hevc_mvp_lx_flag_decode(lc);
         ff_hevc_luma_mv_mvp_mode(lc, x0, y0, nPbW, nPbH, log2_cb_size,
                                  part_idx, merge_idx, mv, mvp_flag, 0);
         mv->mv[0].x += lc->pu.mvd.x;
@@ -1842,16 +1842,16 @@ static void hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0, int nPbW,
 
     if (inter_pred_idc != PRED_L0) {
         if (s->sh.nb_refs[L1])
-            mv->ref_idx[1]= ff_hevc_ref_idx_lx_decode(s, s->sh.nb_refs[L1]);
+            mv->ref_idx[1]= ff_hevc_ref_idx_lx_decode(lc, s->sh.nb_refs[L1]);
 
         if (s->sh.mvd_l1_zero_flag == 1 && inter_pred_idc == PRED_BI) {
             AV_ZERO32(&lc->pu.mvd);
         } else {
-            ff_hevc_hls_mvd_coding(s, x0, y0, 1);
+            ff_hevc_hls_mvd_coding(lc, x0, y0, 1);
         }
 
         mv->pred_flag += PF_L1;
-        mvp_flag = ff_hevc_mvp_lx_flag_decode(s);
+        mvp_flag = ff_hevc_mvp_lx_flag_decode(lc);
         ff_hevc_luma_mv_mvp_mode(lc, x0, y0, nPbW, nPbH, log2_cb_size,
                                  part_idx, merge_idx, mv, mvp_flag, 1);
         mv->mv[1].x += lc->pu.mvd.x;
@@ -1888,11 +1888,11 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0,
     int skip_flag = SAMPLE_CTB(s->skip_flag, x_cb, y_cb);
 
     if (!skip_flag)
-        lc->pu.merge_flag = ff_hevc_merge_flag_decode(s);
+        lc->pu.merge_flag = ff_hevc_merge_flag_decode(lc);
 
     if (skip_flag || lc->pu.merge_flag) {
         if (s->sh.max_num_merge_cand > 1)
-            merge_idx = ff_hevc_merge_idx_decode(s);
+            merge_idx = ff_hevc_merge_idx_decode(lc);
         else
             merge_idx = 0;
 
@@ -2096,14 +2096,14 @@ static void intra_prediction_unit(HEVCContext *s, int x0, int y0,
 
     for (i = 0; i < side; i++)
         for (j = 0; j < side; j++)
-            prev_intra_luma_pred_flag[2 * i + j] = ff_hevc_prev_intra_luma_pred_flag_decode(s);
+            prev_intra_luma_pred_flag[2 * i + j] = ff_hevc_prev_intra_luma_pred_flag_decode(lc);
 
     for (i = 0; i < side; i++) {
         for (j = 0; j < side; j++) {
             if (prev_intra_luma_pred_flag[2 * i + j])
-                lc->pu.mpm_idx = ff_hevc_mpm_idx_decode(s);
+                lc->pu.mpm_idx = ff_hevc_mpm_idx_decode(lc);
             else
-                lc->pu.rem_intra_luma_pred_mode = ff_hevc_rem_intra_luma_pred_mode_decode(s);
+                lc->pu.rem_intra_luma_pred_mode = ff_hevc_rem_intra_luma_pred_mode_decode(lc);
 
             lc->pu.intra_pred_mode[2 * i + j] =
                 luma_intra_pred_mode(s, x0 + pb_size * j, y0 + pb_size * i, pb_size,
@@ -2114,7 +2114,7 @@ static void intra_prediction_unit(HEVCContext *s, int x0, int y0,
     if (s->ps.sps->chroma_format_idc == 3) {
         for (i = 0; i < side; i++) {
             for (j = 0; j < side; j++) {
-                lc->pu.chroma_mode_c[2 * i + j] = chroma_mode = ff_hevc_intra_chroma_pred_mode_decode(s);
+                lc->pu.chroma_mode_c[2 * i + j] = chroma_mode = ff_hevc_intra_chroma_pred_mode_decode(lc);
                 if (chroma_mode != 4) {
                     if (lc->pu.intra_pred_mode[2 * i + j] == intra_chroma_table[chroma_mode])
                         lc->pu.intra_pred_mode_c[2 * i + j] = 34;
@@ -2127,7 +2127,7 @@ static void intra_prediction_unit(HEVCContext *s, int x0, int y0,
         }
     } else if (s->ps.sps->chroma_format_idc == 2) {
         int mode_idx;
-        lc->pu.chroma_mode_c[0] = chroma_mode = ff_hevc_intra_chroma_pred_mode_decode(s);
+        lc->pu.chroma_mode_c[0] = chroma_mode = ff_hevc_intra_chroma_pred_mode_decode(lc);
         if (chroma_mode != 4) {
             if (lc->pu.intra_pred_mode[0] == intra_chroma_table[chroma_mode])
                 mode_idx = 34;
@@ -2138,7 +2138,7 @@ static void intra_prediction_unit(HEVCContext *s, int x0, int y0,
         }
         lc->pu.intra_pred_mode_c[0] = tab_mode_idx[mode_idx];
     } else if (s->ps.sps->chroma_format_idc != 0) {
-        chroma_mode = ff_hevc_intra_chroma_pred_mode_decode(s);
+        chroma_mode = ff_hevc_intra_chroma_pred_mode_decode(lc);
         if (chroma_mode != 4) {
             if (lc->pu.intra_pred_mode[0] == intra_chroma_table[chroma_mode])
                 lc->pu.intra_pred_mode_c[0] = 34;
@@ -2196,14 +2196,14 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size)
     for (x = 0; x < 4; x++)
         lc->pu.intra_pred_mode[x] = 1;
     if (s->ps.pps->transquant_bypass_enable_flag) {
-        lc->cu.cu_transquant_bypass_flag = ff_hevc_cu_transquant_bypass_flag_decode(s);
+        lc->cu.cu_transquant_bypass_flag = ff_hevc_cu_transquant_bypass_flag_decode(lc);
         if (lc->cu.cu_transquant_bypass_flag)
             set_deblocking_bypass(s, x0, y0, log2_cb_size);
     } else
         lc->cu.cu_transquant_bypass_flag = 0;
 
     if (s->sh.slice_type != HEVC_SLICE_I) {
-        uint8_t skip_flag = ff_hevc_skip_flag_decode(s, x0, y0, x_cb, y_cb);
+        uint8_t skip_flag = ff_hevc_skip_flag_decode(lc, x0, y0, x_cb, y_cb);
 
         x = y_cb * min_cb_width + x_cb;
         for (y = 0; y < length; y++) {
@@ -2229,10 +2229,10 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size)
         int pcm_flag = 0;
 
         if (s->sh.slice_type != HEVC_SLICE_I)
-            lc->cu.pred_mode = ff_hevc_pred_mode_decode(s);
+            lc->cu.pred_mode = ff_hevc_pred_mode_decode(lc);
         if (lc->cu.pred_mode != MODE_INTRA ||
             log2_cb_size == s->ps.sps->log2_min_cb_size) {
-            lc->cu.part_mode        = ff_hevc_part_mode_decode(s, log2_cb_size);
+            lc->cu.part_mode        = ff_hevc_part_mode_decode(lc, log2_cb_size);
             lc->cu.intra_split_flag = lc->cu.part_mode == PART_NxN &&
                                       lc->cu.pred_mode == MODE_INTRA;
         }
@@ -2241,7 +2241,7 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size)
             if (lc->cu.part_mode == PART_2Nx2N && s->ps.sps->pcm_enabled_flag &&
                 log2_cb_size >= s->ps.sps->pcm.log2_min_pcm_cb_size &&
                 log2_cb_size <= s->ps.sps->pcm.log2_max_pcm_cb_size) {
-                pcm_flag = ff_hevc_pcm_flag_decode(s);
+                pcm_flag = ff_hevc_pcm_flag_decode(lc);
             }
             if (pcm_flag) {
                 intra_prediction_unit_default_value(s, x0, y0, log2_cb_size);
@@ -2298,7 +2298,7 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size)
 
             if (lc->cu.pred_mode != MODE_INTRA &&
                 !(lc->cu.part_mode == PART_2Nx2N && lc->pu.merge_flag)) {
-                rqt_root_cbf = ff_hevc_no_residual_syntax_flag_decode(s);
+                rqt_root_cbf = ff_hevc_no_residual_syntax_flag_decode(lc);
             }
             if (rqt_root_cbf) {
                 const static int cbf[2] = { 0 };
@@ -2348,7 +2348,7 @@ static int hls_coding_quadtree(HEVCContext *s, int x0, int y0,
     if (x0 + cb_size <= s->ps.sps->width  &&
         y0 + cb_size <= s->ps.sps->height &&
         log2_cb_size > s->ps.sps->log2_min_cb_size) {
-        split_cu = ff_hevc_split_coding_unit_flag_decode(s, cb_depth, x0, y0);
+        split_cu = ff_hevc_split_coding_unit_flag_decode(lc, cb_depth, x0, y0);
     } else {
         split_cu = (log2_cb_size > s->ps.sps->log2_min_cb_size);
     }
@@ -2411,7 +2411,7 @@ static int hls_coding_quadtree(HEVCContext *s, int x0, int y0,
             (!((y0 + cb_size) %
                (1 << (s->ps.sps->log2_ctb_size))) ||
              (y0 + cb_size >= s->ps.sps->height))) {
-            int end_of_slice_flag = ff_hevc_end_of_slice_flag_decode(s);
+            int end_of_slice_flag = ff_hevc_end_of_slice_flag_decode(lc);
             return !end_of_slice_flag;
         } else {
             return 1;
@@ -2501,7 +2501,7 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread)
         y_ctb = (ctb_addr_rs / ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size)) << s->ps.sps->log2_ctb_size;
         hls_decode_neighbour(s, x_ctb, y_ctb, ctb_addr_ts);
 
-        ret = ff_hevc_cabac_init(s, ctb_addr_ts);
+        ret = ff_hevc_cabac_init(lc, ctb_addr_ts);
         if (ret < 0) {
             s->tab_slice_address[ctb_addr_rs] = -1;
             return ret;
@@ -2521,7 +2521,7 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread)
 
 
         ctb_addr_ts++;
-        ff_hevc_save_states(s, ctb_addr_ts);
+        ff_hevc_save_states(lc, ctb_addr_ts);
         ff_hevc_hls_filters(lc, x_ctb, y_ctb, ctb_size);
     }
 
@@ -2579,7 +2579,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *input_ctb_row, int
             return 0;
         }
 
-        ret = ff_hevc_cabac_init(s, ctb_addr_ts);
+        ret = ff_hevc_cabac_init(lc, ctb_addr_ts);
         if (ret < 0)
             goto error;
         hls_sao_param(s, x_ctb >> s->ps.sps->log2_ctb_size, y_ctb >> s->ps.sps->log2_ctb_size);
@@ -2592,7 +2592,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *input_ctb_row, int
 
         ctb_addr_ts++;
 
-        ff_hevc_save_states(s, ctb_addr_ts);
+        ff_hevc_save_states(lc, ctb_addr_ts);
         ff_thread_report_progress2(s->avctx, ctb_row, thread, 1);
         ff_hevc_hls_filters(lc, x_ctb, y_ctb, ctb_size);
 
diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h
index b97b7d1354..b33e8ae0f6 100644
--- a/libavcodec/hevcdec.h
+++ b/libavcodec/hevcdec.h
@@ -604,38 +604,38 @@ int ff_hevc_frame_rps(HEVCContext *s);
  */
 int ff_hevc_slice_rpl(HEVCContext *s);
 
-void ff_hevc_save_states(HEVCContext *s, int ctb_addr_ts);
-int ff_hevc_cabac_init(HEVCContext *s, int ctb_addr_ts);
-int ff_hevc_sao_merge_flag_decode(HEVCContext *s);
-int ff_hevc_sao_type_idx_decode(HEVCContext *s);
-int ff_hevc_sao_band_position_decode(HEVCContext *s);
-int ff_hevc_sao_offset_abs_decode(HEVCContext *s);
-int ff_hevc_sao_offset_sign_decode(HEVCContext *s);
-int ff_hevc_sao_eo_class_decode(HEVCContext *s);
-int ff_hevc_end_of_slice_flag_decode(HEVCContext *s);
-int ff_hevc_cu_transquant_bypass_flag_decode(HEVCContext *s);
-int ff_hevc_skip_flag_decode(HEVCContext *s, int x0, int y0,
+void ff_hevc_save_states(HEVCLocalContext *lc, int ctb_addr_ts);
+int ff_hevc_cabac_init(HEVCLocalContext *lc, int ctb_addr_ts);
+int ff_hevc_sao_merge_flag_decode(HEVCLocalContext *lc);
+int ff_hevc_sao_type_idx_decode(HEVCLocalContext *lc);
+int ff_hevc_sao_band_position_decode(HEVCLocalContext *lc);
+int ff_hevc_sao_offset_abs_decode(HEVCLocalContext *lc);
+int ff_hevc_sao_offset_sign_decode(HEVCLocalContext *lc);
+int ff_hevc_sao_eo_class_decode(HEVCLocalContext *lc);
+int ff_hevc_end_of_slice_flag_decode(HEVCLocalContext *lc);
+int ff_hevc_cu_transquant_bypass_flag_decode(HEVCLocalContext *lc);
+int ff_hevc_skip_flag_decode(HEVCLocalContext *lc, int x0, int y0,
                              int x_cb, int y_cb);
-int ff_hevc_pred_mode_decode(HEVCContext *s);
-int ff_hevc_split_coding_unit_flag_decode(HEVCContext *s, int ct_depth,
+int ff_hevc_pred_mode_decode(HEVCLocalContext *lc);
+int ff_hevc_split_coding_unit_flag_decode(HEVCLocalContext *lc, int ct_depth,
                                           int x0, int y0);
-int ff_hevc_part_mode_decode(HEVCContext *s, int log2_cb_size);
-int ff_hevc_pcm_flag_decode(HEVCContext *s);
-int ff_hevc_prev_intra_luma_pred_flag_decode(HEVCContext *s);
-int ff_hevc_mpm_idx_decode(HEVCContext *s);
-int ff_hevc_rem_intra_luma_pred_mode_decode(HEVCContext *s);
-int ff_hevc_intra_chroma_pred_mode_decode(HEVCContext *s);
-int ff_hevc_merge_idx_decode(HEVCContext *s);
-int ff_hevc_merge_flag_decode(HEVCContext *s);
-int ff_hevc_inter_pred_idc_decode(HEVCContext *s, int nPbW, int nPbH);
-int ff_hevc_ref_idx_lx_decode(HEVCContext *s, int num_ref_idx_lx);
-int ff_hevc_mvp_lx_flag_decode(HEVCContext *s);
-int ff_hevc_no_residual_syntax_flag_decode(HEVCContext *s);
-int ff_hevc_split_transform_flag_decode(HEVCContext *s, int log2_trafo_size);
-int ff_hevc_cbf_cb_cr_decode(HEVCContext *s, int trafo_depth);
-int ff_hevc_cbf_luma_decode(HEVCContext *s, int trafo_depth);
-int ff_hevc_log2_res_scale_abs(HEVCContext *s, int idx);
-int ff_hevc_res_scale_sign_flag(HEVCContext *s, int idx);
+int ff_hevc_part_mode_decode(HEVCLocalContext *lc, int log2_cb_size);
+int ff_hevc_pcm_flag_decode(HEVCLocalContext *lc);
+int ff_hevc_prev_intra_luma_pred_flag_decode(HEVCLocalContext *lc);
+int ff_hevc_mpm_idx_decode(HEVCLocalContext *lc);
+int ff_hevc_rem_intra_luma_pred_mode_decode(HEVCLocalContext *lc);
+int ff_hevc_intra_chroma_pred_mode_decode(HEVCLocalContext *lc);
+int ff_hevc_merge_idx_decode(HEVCLocalContext *lc);
+int ff_hevc_merge_flag_decode(HEVCLocalContext *lc);
+int ff_hevc_inter_pred_idc_decode(HEVCLocalContext *lc, int nPbW, int nPbH);
+int ff_hevc_ref_idx_lx_decode(HEVCLocalContext *lc, int num_ref_idx_lx);
+int ff_hevc_mvp_lx_flag_decode(HEVCLocalContext *lc);
+int ff_hevc_no_residual_syntax_flag_decode(HEVCLocalContext *lc);
+int ff_hevc_split_transform_flag_decode(HEVCLocalContext *lc, int log2_trafo_size);
+int ff_hevc_cbf_cb_cr_decode(HEVCLocalContext *lc, int trafo_depth);
+int ff_hevc_cbf_luma_decode(HEVCLocalContext *lc, int trafo_depth);
+int ff_hevc_log2_res_scale_abs(HEVCLocalContext *lc, int idx);
+int ff_hevc_res_scale_sign_flag(HEVCLocalContext *lc, int idx);
 
 /**
  * Get the number of candidate references for the current frame.
@@ -686,15 +686,15 @@ void ff_hevc_set_qPy(HEVCLocalContext *lc, int xBase, int yBase,
                      int log2_cb_size);
 void ff_hevc_deblocking_boundary_strengths(HEVCLocalContext *lc, int x0, int y0,
                                            int log2_trafo_size);
-int ff_hevc_cu_qp_delta_sign_flag(HEVCContext *s);
-int ff_hevc_cu_qp_delta_abs(HEVCContext *s);
-int ff_hevc_cu_chroma_qp_offset_flag(HEVCContext *s);
-int ff_hevc_cu_chroma_qp_offset_idx(HEVCContext *s);
-void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,
+int ff_hevc_cu_qp_delta_sign_flag(HEVCLocalContext *lc);
+int ff_hevc_cu_qp_delta_abs(HEVCLocalContext *lc);
+int ff_hevc_cu_chroma_qp_offset_flag(HEVCLocalContext *lc);
+int ff_hevc_cu_chroma_qp_offset_idx(HEVCLocalContext *lc);
+void ff_hevc_hls_residual_coding(HEVCLocalContext *lc, int x0, int y0,
                                  int log2_trafo_size, enum ScanType scan_idx,
                                  int c_idx);
 
-void ff_hevc_hls_mvd_coding(HEVCContext *s, int x0, int y0, int log2_cb_size);
+void ff_hevc_hls_mvd_coding(HEVCLocalContext *lc, int x0, int y0, int log2_cb_size);
 
 extern const uint8_t ff_hevc_qpel_extra_before[4];
 extern const uint8_t ff_hevc_qpel_extra_after[4];
-- 
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [FFmpeg-devel] [PATCH 11/18] avcodec/hevcpred: Pass HEVCLocalContext when slice-threading
  2022-06-30 21:48 [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Andreas Rheinhardt
                   ` (8 preceding siblings ...)
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 10/18] avcodec/hevc_cabac: Pass HEVCLocalContext when slice-threading Andreas Rheinhardt
@ 2022-06-30 22:29 ` Andreas Rheinhardt
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 12/18] avcodec/hevcdec: " Andreas Rheinhardt
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-06-30 22:29 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andreas Rheinhardt

The HEVC decoder has both HEVCContext and HEVCLocalContext
structures. The latter is supposed to be the structure
containing the per-slicethread state.

Yet that is not how it is handled in practice: Each HEVCLocalContext
has a unique HEVCContext allocated for it and each of these
coincides except in exactly one field: The corresponding
HEVCLocalContext. This makes it possible to pass the HEVCContext
everywhere where logically a HEVCLocalContext should be used.

This commit stops doing this for lavc/hevcpred as well as
the corresponding mips code; the latter is untested.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/hevcdec.c            | 28 ++++++++++++++--------------
 libavcodec/hevcpred.h           |  4 ++--
 libavcodec/hevcpred_template.c  |  8 ++++----
 libavcodec/mips/hevcpred_mips.h |  4 ++--
 libavcodec/mips/hevcpred_msa.c  |  8 ++++----
 5 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index b3965932e9..2fd0f3acd3 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -1108,7 +1108,7 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
         int trafo_size = 1 << log2_trafo_size;
         ff_hevc_set_neighbour_available(lc, x0, y0, trafo_size, trafo_size);
 
-        s->hpc.intra_pred[log2_trafo_size - 2](s, x0, y0, 0);
+        s->hpc.intra_pred[log2_trafo_size - 2](lc, x0, y0, 0);
     }
 
     if (cbf_luma || cbf_cb[0] || cbf_cr[0] ||
@@ -1194,7 +1194,7 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
             for (i = 0; i < (s->ps.sps->chroma_format_idc == 2 ? 2 : 1); i++) {
                 if (lc->cu.pred_mode == MODE_INTRA) {
                     ff_hevc_set_neighbour_available(lc, x0, y0 + (i << log2_trafo_size_c), trafo_size_h, trafo_size_v);
-                    s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (i << log2_trafo_size_c), 1);
+                    s->hpc.intra_pred[log2_trafo_size_c - 2](lc, x0, y0 + (i << log2_trafo_size_c), 1);
                 }
                 if (cbf_cb[i])
                     ff_hevc_hls_residual_coding(lc, x0, y0 + (i << log2_trafo_size_c),
@@ -1224,7 +1224,7 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
                 if (lc->cu.pred_mode == MODE_INTRA) {
                     ff_hevc_set_neighbour_available(lc, x0, y0 + (i << log2_trafo_size_c),
                                                     trafo_size_h, trafo_size_v);
-                    s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (i << log2_trafo_size_c), 2);
+                    s->hpc.intra_pred[log2_trafo_size_c - 2](lc, x0, y0 + (i << log2_trafo_size_c), 2);
                 }
                 if (cbf_cr[i])
                     ff_hevc_hls_residual_coding(lc, x0, y0 + (i << log2_trafo_size_c),
@@ -1253,7 +1253,7 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
                 if (lc->cu.pred_mode == MODE_INTRA) {
                     ff_hevc_set_neighbour_available(lc, xBase, yBase + (i << log2_trafo_size),
                                                     trafo_size_h, trafo_size_v);
-                    s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (i << log2_trafo_size), 1);
+                    s->hpc.intra_pred[log2_trafo_size - 2](lc, xBase, yBase + (i << log2_trafo_size), 1);
                 }
                 if (cbf_cb[i])
                     ff_hevc_hls_residual_coding(lc, xBase, yBase + (i << log2_trafo_size),
@@ -1263,7 +1263,7 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
                 if (lc->cu.pred_mode == MODE_INTRA) {
                     ff_hevc_set_neighbour_available(lc, xBase, yBase + (i << log2_trafo_size),
                                                 trafo_size_h, trafo_size_v);
-                    s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (i << log2_trafo_size), 2);
+                    s->hpc.intra_pred[log2_trafo_size - 2](lc, xBase, yBase + (i << log2_trafo_size), 2);
                 }
                 if (cbf_cr[i])
                     ff_hevc_hls_residual_coding(lc, xBase, yBase + (i << log2_trafo_size),
@@ -1275,26 +1275,26 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
             int trafo_size_h = 1 << (log2_trafo_size_c + s->ps.sps->hshift[1]);
             int trafo_size_v = 1 << (log2_trafo_size_c + s->ps.sps->vshift[1]);
             ff_hevc_set_neighbour_available(lc, x0, y0, trafo_size_h, trafo_size_v);
-            s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0, 1);
-            s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0, 2);
+            s->hpc.intra_pred[log2_trafo_size_c - 2](lc, x0, y0, 1);
+            s->hpc.intra_pred[log2_trafo_size_c - 2](lc, x0, y0, 2);
             if (s->ps.sps->chroma_format_idc == 2) {
                 ff_hevc_set_neighbour_available(lc, x0, y0 + (1 << log2_trafo_size_c),
                                                 trafo_size_h, trafo_size_v);
-                s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (1 << log2_trafo_size_c), 1);
-                s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (1 << log2_trafo_size_c), 2);
+                s->hpc.intra_pred[log2_trafo_size_c - 2](lc, x0, y0 + (1 << log2_trafo_size_c), 1);
+                s->hpc.intra_pred[log2_trafo_size_c - 2](lc, x0, y0 + (1 << log2_trafo_size_c), 2);
             }
         } else if (blk_idx == 3) {
             int trafo_size_h = 1 << (log2_trafo_size + 1);
             int trafo_size_v = 1 << (log2_trafo_size + s->ps.sps->vshift[1]);
             ff_hevc_set_neighbour_available(lc, xBase, yBase,
                                             trafo_size_h, trafo_size_v);
-            s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase, 1);
-            s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase, 2);
+            s->hpc.intra_pred[log2_trafo_size - 2](lc, xBase, yBase, 1);
+            s->hpc.intra_pred[log2_trafo_size - 2](lc, xBase, yBase, 2);
             if (s->ps.sps->chroma_format_idc == 2) {
-                ff_hevc_set_neighbour_available(lc, xBase, yBase + (1 << (log2_trafo_size)),
+                ff_hevc_set_neighbour_available(lc, xBase, yBase + (1 << log2_trafo_size),
                                                 trafo_size_h, trafo_size_v);
-                s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (1 << (log2_trafo_size)), 1);
-                s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (1 << (log2_trafo_size)), 2);
+                s->hpc.intra_pred[log2_trafo_size - 2](lc, xBase, yBase + (1 << log2_trafo_size), 1);
+                s->hpc.intra_pred[log2_trafo_size - 2](lc, xBase, yBase + (1 << log2_trafo_size), 2);
             }
         }
     }
diff --git a/libavcodec/hevcpred.h b/libavcodec/hevcpred.h
index eb17663683..b1b1dc4f3a 100644
--- a/libavcodec/hevcpred.h
+++ b/libavcodec/hevcpred.h
@@ -26,10 +26,10 @@
 #include <stddef.h>
 #include <stdint.h>
 
-struct HEVCContext;
+struct HEVCLocalContext;
 
 typedef struct HEVCPredContext {
-    void (*intra_pred[4])(struct HEVCContext *s, int x0, int y0, int c_idx);
+    void (*intra_pred[4])(struct HEVCLocalContext *lc, int x0, int y0, int c_idx);
 
     void (*pred_planar[4])(uint8_t *src, const uint8_t *top,
                            const uint8_t *left, ptrdiff_t stride);
diff --git a/libavcodec/hevcpred_template.c b/libavcodec/hevcpred_template.c
index ca75ec1128..16d1c7f35f 100644
--- a/libavcodec/hevcpred_template.c
+++ b/libavcodec/hevcpred_template.c
@@ -27,7 +27,7 @@
 
 #define POS(x, y) src[(x) + stride * (y)]
 
-static av_always_inline void FUNC(intra_pred)(HEVCContext *s, int x0, int y0,
+static av_always_inline void FUNC(intra_pred)(HEVCLocalContext *lc, int x0, int y0,
                                               int log2_size, int c_idx)
 {
 #define PU(x) \
@@ -70,7 +70,7 @@ do {                                  \
             else                                                               \
                 a = PIXEL_SPLAT_X4(ptr[i + 3])
 
-    HEVCLocalContext *lc = s->HEVClc;
+    const HEVCContext *const s = lc->parent;
     int i;
     int hshift = s->ps.sps->hshift[c_idx];
     int vshift = s->ps.sps->vshift[c_idx];
@@ -346,9 +346,9 @@ do {                                  \
 }
 
 #define INTRA_PRED(size)                                                            \
-static void FUNC(intra_pred_ ## size)(HEVCContext *s, int x0, int y0, int c_idx)    \
+static void FUNC(intra_pred_ ## size)(HEVCLocalContext *lc, int x0, int y0, int c_idx) \
 {                                                                                   \
-    FUNC(intra_pred)(s, x0, y0, size, c_idx);                                       \
+    FUNC(intra_pred)(lc, x0, y0, size, c_idx);                                      \
 }
 
 INTRA_PRED(2)
diff --git a/libavcodec/mips/hevcpred_mips.h b/libavcodec/mips/hevcpred_mips.h
index f22feff85e..6848700010 100644
--- a/libavcodec/mips/hevcpred_mips.h
+++ b/libavcodec/mips/hevcpred_mips.h
@@ -67,7 +67,7 @@ void ff_pred_intra_pred_angular_3_msa(uint8_t *dst,
                                       const uint8_t *src_left,
                                       ptrdiff_t stride, int c_idx, int mode);
 
-void ff_intra_pred_8_16x16_msa(struct HEVCContext *s, int x0, int y0, int c_idx);
-void ff_intra_pred_8_32x32_msa(struct HEVCContext *s, int x0, int y0, int c_idx);
+void ff_intra_pred_8_16x16_msa(struct HEVCLocalContext *s, int x0, int y0, int c_idx);
+void ff_intra_pred_8_32x32_msa(struct HEVCLocalContext *s, int x0, int y0, int c_idx);
 
 #endif  // #ifndef AVCODEC_MIPS_HEVCPRED_MIPS_H
diff --git a/libavcodec/mips/hevcpred_msa.c b/libavcodec/mips/hevcpred_msa.c
index f53276d34e..b056ee986b 100644
--- a/libavcodec/mips/hevcpred_msa.c
+++ b/libavcodec/mips/hevcpred_msa.c
@@ -1903,10 +1903,10 @@ void ff_pred_intra_pred_angular_3_msa(uint8_t *dst,
     }
 }
 
-void ff_intra_pred_8_16x16_msa(HEVCContext *s, int x0, int y0, int c_idx)
+void ff_intra_pred_8_16x16_msa(HEVCLocalContext *lc, int x0, int y0, int c_idx)
 {
     v16u8 vec0;
-    HEVCLocalContext *lc = s->HEVClc;
+    const HEVCContext *const s = lc->parent;
     int i;
     int hshift = s->ps.sps->hshift[c_idx];
     int vshift = s->ps.sps->vshift[c_idx];
@@ -2416,14 +2416,14 @@ void ff_intra_pred_8_16x16_msa(HEVCContext *s, int x0, int y0, int c_idx)
     }
 }
 
-void ff_intra_pred_8_32x32_msa(HEVCContext *s, int x0, int y0, int c_idx)
+void ff_intra_pred_8_32x32_msa(HEVCLocalContext *lc, int x0, int y0, int c_idx)
 {
     v16u8 vec0, vec1;
     v8i16 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
     v8i16 res0, res1, res2, res3;
     v8i16 mul_val0 = { 63, 62, 61, 60, 59, 58, 57, 56 };
     v8i16 mul_val1 = { 1, 2, 3, 4, 5, 6, 7, 8 };
-    HEVCLocalContext *lc = s->HEVClc;
+    const HEVCContext *const s = lc->parent;
     int i;
     int hshift = s->ps.sps->hshift[c_idx];
     int vshift = s->ps.sps->vshift[c_idx];
-- 
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [FFmpeg-devel] [PATCH 12/18] avcodec/hevcdec: Pass HEVCLocalContext when slice-threading
  2022-06-30 21:48 [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Andreas Rheinhardt
                   ` (9 preceding siblings ...)
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 11/18] avcodec/hevcpred: " Andreas Rheinhardt
@ 2022-06-30 22:29 ` Andreas Rheinhardt
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 13/18] avcodec/hevcdec: Pass HEVCLocalContext** via execute2 Andreas Rheinhardt
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-06-30 22:29 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andreas Rheinhardt

The HEVC decoder has both HEVCContext and HEVCLocalContext
structures. The latter is supposed to be the structure
containing the per-slicethread state.

Yet that is not how it is handled in practice: Each HEVCLocalContext
has a unique HEVCContext allocated for it and each of these
coincides except in exactly one field: The corresponding
HEVCLocalContext. This makes it possible to pass the HEVCContext
everywhere where logically a HEVCLocalContext should be used.

This commit stops doing this for lavc/hevcdec.c itself.
It also constifies what can be constified in order to make
the nonconst stuff stand out more.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/hevcdec.c | 184 +++++++++++++++++++++----------------------
 1 file changed, 92 insertions(+), 92 deletions(-)

diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index 2fd0f3acd3..1d0b80ea48 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -1005,9 +1005,9 @@ do {                                                    \
         sao->elem = 0;                                  \
 } while (0)
 
-static void hls_sao_param(HEVCContext *s, int rx, int ry)
+static void hls_sao_param(HEVCLocalContext *lc, int rx, int ry)
 {
-    HEVCLocalContext *lc    = s->HEVClc;
+    const HEVCContext *const s = lc->parent;
     int sao_merge_left_flag = 0;
     int sao_merge_up_flag   = 0;
     SAOParams *sao          = &CTB(s->sao, rx, ry);
@@ -1079,8 +1079,8 @@ static void hls_sao_param(HEVCContext *s, int rx, int ry)
 #undef SET_SAO
 #undef CTB
 
-static int hls_cross_component_pred(HEVCContext *s, int idx) {
-    HEVCLocalContext *lc    = s->HEVClc;
+static int hls_cross_component_pred(HEVCLocalContext *lc, int idx)
+{
     int log2_res_scale_abs_plus1 = ff_hevc_log2_res_scale_abs(lc, idx);
 
     if (log2_res_scale_abs_plus1 !=  0) {
@@ -1095,12 +1095,12 @@ static int hls_cross_component_pred(HEVCContext *s, int idx) {
     return 0;
 }
 
-static int hls_transform_unit(HEVCContext *s, int x0, int y0,
+static int hls_transform_unit(HEVCLocalContext *lc, int x0, int y0,
                               int xBase, int yBase, int cb_xBase, int cb_yBase,
                               int log2_cb_size, int log2_trafo_size,
                               int blk_idx, int cbf_luma, int *cbf_cb, int *cbf_cr)
 {
-    HEVCLocalContext *lc = s->HEVClc;
+    const HEVCContext *const s = lc->parent;
     const int log2_trafo_size_c = log2_trafo_size - s->ps.sps->hshift[1];
     int i;
 
@@ -1189,7 +1189,7 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
                                  (lc->tu.chroma_mode_c ==  4)));
 
             if (lc->tu.cross_pf) {
-                hls_cross_component_pred(s, 0);
+                hls_cross_component_pred(lc, 0);
             }
             for (i = 0; i < (s->ps.sps->chroma_format_idc == 2 ? 2 : 1); i++) {
                 if (lc->cu.pred_mode == MODE_INTRA) {
@@ -1218,7 +1218,7 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
             }
 
             if (lc->tu.cross_pf) {
-                hls_cross_component_pred(s, 1);
+                hls_cross_component_pred(lc, 1);
             }
             for (i = 0; i < (s->ps.sps->chroma_format_idc == 2 ? 2 : 1); i++) {
                 if (lc->cu.pred_mode == MODE_INTRA) {
@@ -1302,7 +1302,7 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
     return 0;
 }
 
-static void set_deblocking_bypass(HEVCContext *s, int x0, int y0, int log2_cb_size)
+static void set_deblocking_bypass(const HEVCContext *s, int x0, int y0, int log2_cb_size)
 {
     int cb_size          = 1 << log2_cb_size;
     int log2_min_pu_size = s->ps.sps->log2_min_pu_size;
@@ -1317,13 +1317,13 @@ static void set_deblocking_bypass(HEVCContext *s, int x0, int y0, int log2_cb_si
             s->is_pcm[i + j * min_pu_width] = 2;
 }
 
-static int hls_transform_tree(HEVCContext *s, int x0, int y0,
+static int hls_transform_tree(HEVCLocalContext *lc, int x0, int y0,
                               int xBase, int yBase, int cb_xBase, int cb_yBase,
                               int log2_cb_size, int log2_trafo_size,
                               int trafo_depth, int blk_idx,
                               const int *base_cbf_cb, const int *base_cbf_cr)
 {
-    HEVCLocalContext *lc = s->HEVClc;
+    const HEVCContext *const s = lc->parent;
     uint8_t split_transform_flag;
     int cbf_cb[2];
     int cbf_cr[2];
@@ -1390,7 +1390,7 @@ static int hls_transform_tree(HEVCContext *s, int x0, int y0,
 
 #define SUBDIVIDE(x, y, idx)                                                    \
 do {                                                                            \
-    ret = hls_transform_tree(s, x, y, x0, y0, cb_xBase, cb_yBase, log2_cb_size, \
+    ret = hls_transform_tree(lc, x, y, x0, y0, cb_xBase, cb_yBase, log2_cb_size,\
                              log2_trafo_size - 1, trafo_depth + 1, idx,         \
                              cbf_cb, cbf_cr);                                   \
     if (ret < 0)                                                                \
@@ -1415,7 +1415,7 @@ do {
             cbf_luma = ff_hevc_cbf_luma_decode(lc, trafo_depth);
         }
 
-        ret = hls_transform_unit(s, x0, y0, xBase, yBase, cb_xBase, cb_yBase,
+        ret = hls_transform_unit(lc, x0, y0, xBase, yBase, cb_xBase, cb_yBase,
                                  log2_cb_size, log2_trafo_size,
                                  blk_idx, cbf_luma, cbf_cb, cbf_cr);
         if (ret < 0)
@@ -1440,9 +1440,9 @@ do {
     return 0;
 }
 
-static int hls_pcm_sample(HEVCContext *s, int x0, int y0, int log2_cb_size)
+static int hls_pcm_sample(HEVCLocalContext *lc, int x0, int y0, int log2_cb_size)
 {
-    HEVCLocalContext *lc = s->HEVClc;
+    const HEVCContext *const s = lc->parent;
     GetBitContext gb;
     int cb_size   = 1 << log2_cb_size;
     ptrdiff_t stride0 = s->frame->linesize[0];
@@ -1497,11 +1497,11 @@ static int hls_pcm_sample(HEVCContext *s, int x0, int y0, int log2_cb_size)
  * @param luma_offset additive offset applied to the luma prediction value
  */
 
-static void luma_mc_uni(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride,
+static void luma_mc_uni(HEVCLocalContext *lc, uint8_t *dst, ptrdiff_t dststride,
                         AVFrame *ref, const Mv *mv, int x_off, int y_off,
                         int block_w, int block_h, int luma_weight, int luma_offset)
 {
-    HEVCLocalContext *lc = s->HEVClc;
+    const HEVCContext *const s = lc->parent;
     uint8_t *src         = ref->data[0];
     ptrdiff_t srcstride  = ref->linesize[0];
     int pic_width        = s->ps.sps->width;
@@ -1558,11 +1558,11 @@ static void luma_mc_uni(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride,
  * @param mv1 motion vector1 (relative to block position) to get pixel data from
  * @param current_mv current motion vector structure
  */
- static void luma_mc_bi(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride,
+ static void luma_mc_bi(HEVCLocalContext *lc, uint8_t *dst, ptrdiff_t dststride,
                        AVFrame *ref0, const Mv *mv0, int x_off, int y_off,
                        int block_w, int block_h, AVFrame *ref1, const Mv *mv1, struct MvField *current_mv)
 {
-    HEVCLocalContext *lc = s->HEVClc;
+    const HEVCContext *const s = lc->parent;
     ptrdiff_t src0stride  = ref0->linesize[0];
     ptrdiff_t src1stride  = ref1->linesize[0];
     int pic_width        = s->ps.sps->width;
@@ -1649,11 +1649,12 @@ static void luma_mc_uni(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride,
  * @param chroma_offset additive offset applied to the chroma prediction value
  */
 
-static void chroma_mc_uni(HEVCContext *s, uint8_t *dst0,
+static void chroma_mc_uni(HEVCLocalContext *lc, uint8_t *dst0,
                           ptrdiff_t dststride, uint8_t *src0, ptrdiff_t srcstride, int reflist,
-                          int x_off, int y_off, int block_w, int block_h, struct MvField *current_mv, int chroma_weight, int chroma_offset)
+                          int x_off, int y_off, int block_w, int block_h,
+                          const struct MvField *current_mv, int chroma_weight, int chroma_offset)
 {
-    HEVCLocalContext *lc = s->HEVClc;
+    const HEVCContext *const s = lc->parent;
     int pic_width        = s->ps.sps->width >> s->ps.sps->hshift[1];
     int pic_height       = s->ps.sps->height >> s->ps.sps->vshift[1];
     const Mv *mv         = &current_mv->mv[reflist];
@@ -1714,10 +1715,10 @@ static void chroma_mc_uni(HEVCContext *s, uint8_t *dst0,
  * @param current_mv current motion vector structure
  * @param cidx chroma component(cb, cr)
  */
-static void chroma_mc_bi(HEVCContext *s, uint8_t *dst0, ptrdiff_t dststride, AVFrame *ref0, AVFrame *ref1,
-                         int x_off, int y_off, int block_w, int block_h, struct MvField *current_mv, int cidx)
+static void chroma_mc_bi(HEVCLocalContext *lc, uint8_t *dst0, ptrdiff_t dststride, AVFrame *ref0, AVFrame *ref1,
+                         int x_off, int y_off, int block_w, int block_h, const MvField *current_mv, int cidx)
 {
-    HEVCLocalContext *lc = s->HEVClc;
+    const HEVCContext *const s = lc->parent;
     uint8_t *src1        = ref0->data[cidx+1];
     uint8_t *src2        = ref1->data[cidx+1];
     ptrdiff_t src1stride = ref0->linesize[cidx+1];
@@ -1726,8 +1727,8 @@ static void chroma_mc_bi(HEVCContext *s, uint8_t *dst0, ptrdiff_t dststride, AVF
                            (s->sh.slice_type == HEVC_SLICE_B && s->ps.pps->weighted_bipred_flag);
     int pic_width        = s->ps.sps->width >> s->ps.sps->hshift[1];
     int pic_height       = s->ps.sps->height >> s->ps.sps->vshift[1];
-    Mv *mv0              = &current_mv->mv[0];
-    Mv *mv1              = &current_mv->mv[1];
+    const Mv *const mv0  = &current_mv->mv[0];
+    const Mv *const mv1  = &current_mv->mv[1];
     int hshift = s->ps.sps->hshift[1];
     int vshift = s->ps.sps->vshift[1];
 
@@ -1804,7 +1805,7 @@ static void chroma_mc_bi(HEVCContext *s, uint8_t *dst0, ptrdiff_t dststride, AVF
                                                          _mx1, _my1, block_w);
 }
 
-static void hevc_await_progress(HEVCContext *s, HEVCFrame *ref,
+static void hevc_await_progress(const HEVCContext *s, HEVCFrame *ref,
                                 const Mv *mv, int y0, int height)
 {
     if (s->threads_type == FF_THREAD_FRAME ) {
@@ -1814,11 +1815,11 @@ static void hevc_await_progress(HEVCContext *s, HEVCFrame *ref,
     }
 }
 
-static void hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0, int nPbW,
+static void hevc_luma_mv_mvp_mode(HEVCLocalContext *lc, int x0, int y0, int nPbW,
                                   int nPbH, int log2_cb_size, int part_idx,
                                   int merge_idx, MvField *mv)
 {
-    HEVCLocalContext *lc = s->HEVClc;
+    const HEVCContext *const s = lc->parent;
     enum InterPredIdc inter_pred_idc = PRED_L0;
     int mvp_flag;
 
@@ -1859,21 +1860,21 @@ static void hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0, int nPbW,
     }
 }
 
-static void hls_prediction_unit(HEVCContext *s, int x0, int y0,
+static void hls_prediction_unit(HEVCLocalContext *lc, int x0, int y0,
                                 int nPbW, int nPbH,
                                 int log2_cb_size, int partIdx, int idx)
 {
 #define POS(c_idx, x, y)                                                              \
     &s->frame->data[c_idx][((y) >> s->ps.sps->vshift[c_idx]) * s->frame->linesize[c_idx] + \
                            (((x) >> s->ps.sps->hshift[c_idx]) << s->ps.sps->pixel_shift)]
-    HEVCLocalContext *lc = s->HEVClc;
+    const HEVCContext *const s = lc->parent;
     int merge_idx = 0;
     struct MvField current_mv = {{{ 0 }}};
 
     int min_pu_width = s->ps.sps->min_pu_width;
 
     MvField *tab_mvf = s->ref->tab_mvf;
-    RefPicList  *refPicList = s->ref->refPicList;
+    const RefPicList *refPicList = s->ref->refPicList;
     HEVCFrame *ref0 = NULL, *ref1 = NULL;
     uint8_t *dst0 = POS(0, x0, y0);
     uint8_t *dst1 = POS(1, x0, y0);
@@ -1899,7 +1900,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0,
         ff_hevc_luma_mv_merge_mode(lc, x0, y0, nPbW, nPbH, log2_cb_size,
                                    partIdx, merge_idx, &current_mv);
     } else {
-        hevc_luma_mv_mvp_mode(s, x0, y0, nPbW, nPbH, log2_cb_size,
+        hevc_luma_mv_mvp_mode(lc, x0, y0, nPbW, nPbH, log2_cb_size,
                               partIdx, merge_idx, &current_mv);
     }
 
@@ -1929,16 +1930,16 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0,
         int nPbW_c = nPbW >> s->ps.sps->hshift[1];
         int nPbH_c = nPbH >> s->ps.sps->vshift[1];
 
-        luma_mc_uni(s, dst0, s->frame->linesize[0], ref0->frame,
+        luma_mc_uni(lc, dst0, s->frame->linesize[0], ref0->frame,
                     &current_mv.mv[0], x0, y0, nPbW, nPbH,
                     s->sh.luma_weight_l0[current_mv.ref_idx[0]],
                     s->sh.luma_offset_l0[current_mv.ref_idx[0]]);
 
         if (s->ps.sps->chroma_format_idc) {
-            chroma_mc_uni(s, dst1, s->frame->linesize[1], ref0->frame->data[1], ref0->frame->linesize[1],
+            chroma_mc_uni(lc, dst1, s->frame->linesize[1], ref0->frame->data[1], ref0->frame->linesize[1],
                           0, x0_c, y0_c, nPbW_c, nPbH_c, &current_mv,
                           s->sh.chroma_weight_l0[current_mv.ref_idx[0]][0], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0]);
-            chroma_mc_uni(s, dst2, s->frame->linesize[2], ref0->frame->data[2], ref0->frame->linesize[2],
+            chroma_mc_uni(lc, dst2, s->frame->linesize[2], ref0->frame->data[2], ref0->frame->linesize[2],
                           0, x0_c, y0_c, nPbW_c, nPbH_c, &current_mv,
                           s->sh.chroma_weight_l0[current_mv.ref_idx[0]][1], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][1]);
         }
@@ -1948,17 +1949,17 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0,
         int nPbW_c = nPbW >> s->ps.sps->hshift[1];
         int nPbH_c = nPbH >> s->ps.sps->vshift[1];
 
-        luma_mc_uni(s, dst0, s->frame->linesize[0], ref1->frame,
+        luma_mc_uni(lc, dst0, s->frame->linesize[0], ref1->frame,
                     &current_mv.mv[1], x0, y0, nPbW, nPbH,
                     s->sh.luma_weight_l1[current_mv.ref_idx[1]],
                     s->sh.luma_offset_l1[current_mv.ref_idx[1]]);
 
         if (s->ps.sps->chroma_format_idc) {
-            chroma_mc_uni(s, dst1, s->frame->linesize[1], ref1->frame->data[1], ref1->frame->linesize[1],
+            chroma_mc_uni(lc, dst1, s->frame->linesize[1], ref1->frame->data[1], ref1->frame->linesize[1],
                           1, x0_c, y0_c, nPbW_c, nPbH_c, &current_mv,
                           s->sh.chroma_weight_l1[current_mv.ref_idx[1]][0], s->sh.chroma_offset_l1[current_mv.ref_idx[1]][0]);
 
-            chroma_mc_uni(s, dst2, s->frame->linesize[2], ref1->frame->data[2], ref1->frame->linesize[2],
+            chroma_mc_uni(lc, dst2, s->frame->linesize[2], ref1->frame->data[2], ref1->frame->linesize[2],
                           1, x0_c, y0_c, nPbW_c, nPbH_c, &current_mv,
                           s->sh.chroma_weight_l1[current_mv.ref_idx[1]][1], s->sh.chroma_offset_l1[current_mv.ref_idx[1]][1]);
         }
@@ -1968,15 +1969,15 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0,
         int nPbW_c = nPbW >> s->ps.sps->hshift[1];
         int nPbH_c = nPbH >> s->ps.sps->vshift[1];
 
-        luma_mc_bi(s, dst0, s->frame->linesize[0], ref0->frame,
+        luma_mc_bi(lc, dst0, s->frame->linesize[0], ref0->frame,
                    &current_mv.mv[0], x0, y0, nPbW, nPbH,
                    ref1->frame, &current_mv.mv[1], &current_mv);
 
         if (s->ps.sps->chroma_format_idc) {
-            chroma_mc_bi(s, dst1, s->frame->linesize[1], ref0->frame, ref1->frame,
+            chroma_mc_bi(lc, dst1, s->frame->linesize[1], ref0->frame, ref1->frame,
                          x0_c, y0_c, nPbW_c, nPbH_c, &current_mv, 0);
 
-            chroma_mc_bi(s, dst2, s->frame->linesize[2], ref0->frame, ref1->frame,
+            chroma_mc_bi(lc, dst2, s->frame->linesize[2], ref0->frame, ref1->frame,
                          x0_c, y0_c, nPbW_c, nPbH_c, &current_mv, 1);
         }
     }
@@ -1985,10 +1986,10 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0,
 /**
  * 8.4.1
  */
-static int luma_intra_pred_mode(HEVCContext *s, int x0, int y0, int pu_size,
+static int luma_intra_pred_mode(HEVCLocalContext *lc, int x0, int y0, int pu_size,
                                 int prev_intra_luma_pred_flag)
 {
-    HEVCLocalContext *lc = s->HEVClc;
+    const HEVCContext *const s = lc->parent;
     int x_pu             = x0 >> s->ps.sps->log2_min_pu_size;
     int y_pu             = y0 >> s->ps.sps->log2_min_pu_size;
     int min_pu_width     = s->ps.sps->min_pu_width;
@@ -2065,7 +2066,7 @@ static int luma_intra_pred_mode(HEVCContext *s, int x0, int y0, int pu_size,
     return intra_pred_mode;
 }
 
-static av_always_inline void set_ct_depth(HEVCContext *s, int x0, int y0,
+static av_always_inline void set_ct_depth(const HEVCContext *s, int x0, int y0,
                                           int log2_cb_size, int ct_depth)
 {
     int length = (1 << log2_cb_size) >> s->ps.sps->log2_min_cb_size;
@@ -2082,10 +2083,10 @@ static const uint8_t tab_mode_idx[] = {
      0,  1,  2,  2,  2,  2,  3,  5,  7,  8, 10, 12, 13, 15, 17, 18, 19, 20,
     21, 22, 23, 23, 24, 24, 25, 25, 26, 27, 27, 28, 28, 29, 29, 30, 31};
 
-static void intra_prediction_unit(HEVCContext *s, int x0, int y0,
+static void intra_prediction_unit(HEVCLocalContext *lc, int x0, int y0,
                                   int log2_cb_size)
 {
-    HEVCLocalContext *lc = s->HEVClc;
+    const HEVCContext *const s = lc->parent;
     static const uint8_t intra_chroma_table[4] = { 0, 26, 10, 1 };
     uint8_t prev_intra_luma_pred_flag[4];
     int split   = lc->cu.part_mode == PART_NxN;
@@ -2106,7 +2107,7 @@ static void intra_prediction_unit(HEVCContext *s, int x0, int y0,
                 lc->pu.rem_intra_luma_pred_mode = ff_hevc_rem_intra_luma_pred_mode_decode(lc);
 
             lc->pu.intra_pred_mode[2 * i + j] =
-                luma_intra_pred_mode(s, x0 + pb_size * j, y0 + pb_size * i, pb_size,
+                luma_intra_pred_mode(lc, x0 + pb_size * j, y0 + pb_size * i, pb_size,
                                      prev_intra_luma_pred_flag[2 * i + j]);
         }
     }
@@ -2150,11 +2151,11 @@ static void intra_prediction_unit(HEVCContext *s, int x0, int y0,
     }
 }
 
-static void intra_prediction_unit_default_value(HEVCContext *s,
+static void intra_prediction_unit_default_value(HEVCLocalContext *lc,
                                                 int x0, int y0,
                                                 int log2_cb_size)
 {
-    HEVCLocalContext *lc = s->HEVClc;
+    const HEVCContext *const s = lc->parent;
     int pb_size          = 1 << log2_cb_size;
     int size_in_pus      = pb_size >> s->ps.sps->log2_min_pu_size;
     int min_pu_width     = s->ps.sps->min_pu_width;
@@ -2173,10 +2174,9 @@ static void intra_prediction_unit_default_value(HEVCContext *s,
                 tab_mvf[(y_pu + j) * min_pu_width + x_pu + k].pred_flag = PF_INTRA;
 }
 
-static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size)
+static int hls_coding_unit(HEVCLocalContext *lc, const HEVCContext *s, int x0, int y0, int log2_cb_size)
 {
     int cb_size          = 1 << log2_cb_size;
-    HEVCLocalContext *lc = s->HEVClc;
     int log2_min_cb_size = s->ps.sps->log2_min_cb_size;
     int length           = cb_size >> log2_min_cb_size;
     int min_cb_width     = s->ps.sps->min_cb_width;
@@ -2220,8 +2220,8 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size)
     }
 
     if (SAMPLE_CTB(s->skip_flag, x_cb, y_cb)) {
-        hls_prediction_unit(s, x0, y0, cb_size, cb_size, log2_cb_size, 0, idx);
-        intra_prediction_unit_default_value(s, x0, y0, log2_cb_size);
+        hls_prediction_unit(lc, x0, y0, cb_size, cb_size, log2_cb_size, 0, idx);
+        intra_prediction_unit_default_value(lc, x0, y0, log2_cb_size);
 
         if (!s->sh.disable_deblocking_filter_flag)
             ff_hevc_deblocking_boundary_strengths(lc, x0, y0, log2_cb_size);
@@ -2244,51 +2244,51 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size)
                 pcm_flag = ff_hevc_pcm_flag_decode(lc);
             }
             if (pcm_flag) {
-                intra_prediction_unit_default_value(s, x0, y0, log2_cb_size);
-                ret = hls_pcm_sample(s, x0, y0, log2_cb_size);
+                intra_prediction_unit_default_value(lc, x0, y0, log2_cb_size);
+                ret = hls_pcm_sample(lc, x0, y0, log2_cb_size);
                 if (s->ps.sps->pcm.loop_filter_disable_flag)
                     set_deblocking_bypass(s, x0, y0, log2_cb_size);
 
                 if (ret < 0)
                     return ret;
             } else {
-                intra_prediction_unit(s, x0, y0, log2_cb_size);
+                intra_prediction_unit(lc, x0, y0, log2_cb_size);
             }
         } else {
-            intra_prediction_unit_default_value(s, x0, y0, log2_cb_size);
+            intra_prediction_unit_default_value(lc, x0, y0, log2_cb_size);
             switch (lc->cu.part_mode) {
             case PART_2Nx2N:
-                hls_prediction_unit(s, x0, y0, cb_size, cb_size, log2_cb_size, 0, idx);
+                hls_prediction_unit(lc, x0, y0, cb_size, cb_size, log2_cb_size, 0, idx);
                 break;
             case PART_2NxN:
-                hls_prediction_unit(s, x0, y0,               cb_size, cb_size / 2, log2_cb_size, 0, idx);
-                hls_prediction_unit(s, x0, y0 + cb_size / 2, cb_size, cb_size / 2, log2_cb_size, 1, idx);
+                hls_prediction_unit(lc, x0, y0,               cb_size, cb_size / 2, log2_cb_size, 0, idx);
+                hls_prediction_unit(lc, x0, y0 + cb_size / 2, cb_size, cb_size / 2, log2_cb_size, 1, idx);
                 break;
             case PART_Nx2N:
-                hls_prediction_unit(s, x0,               y0, cb_size / 2, cb_size, log2_cb_size, 0, idx - 1);
-                hls_prediction_unit(s, x0 + cb_size / 2, y0, cb_size / 2, cb_size, log2_cb_size, 1, idx - 1);
+                hls_prediction_unit(lc, x0,               y0, cb_size / 2, cb_size, log2_cb_size, 0, idx - 1);
+                hls_prediction_unit(lc, x0 + cb_size / 2, y0, cb_size / 2, cb_size, log2_cb_size, 1, idx - 1);
                 break;
             case PART_2NxnU:
-                hls_prediction_unit(s, x0, y0,               cb_size, cb_size     / 4, log2_cb_size, 0, idx);
-                hls_prediction_unit(s, x0, y0 + cb_size / 4, cb_size, cb_size * 3 / 4, log2_cb_size, 1, idx);
+                hls_prediction_unit(lc, x0, y0,               cb_size, cb_size     / 4, log2_cb_size, 0, idx);
+                hls_prediction_unit(lc, x0, y0 + cb_size / 4, cb_size, cb_size * 3 / 4, log2_cb_size, 1, idx);
                 break;
             case PART_2NxnD:
-                hls_prediction_unit(s, x0, y0,                   cb_size, cb_size * 3 / 4, log2_cb_size, 0, idx);
-                hls_prediction_unit(s, x0, y0 + cb_size * 3 / 4, cb_size, cb_size     / 4, log2_cb_size, 1, idx);
+                hls_prediction_unit(lc, x0, y0,                   cb_size, cb_size * 3 / 4, log2_cb_size, 0, idx);
+                hls_prediction_unit(lc, x0, y0 + cb_size * 3 / 4, cb_size, cb_size     / 4, log2_cb_size, 1, idx);
                 break;
             case PART_nLx2N:
-                hls_prediction_unit(s, x0,               y0, cb_size     / 4, cb_size, log2_cb_size, 0, idx - 2);
-                hls_prediction_unit(s, x0 + cb_size / 4, y0, cb_size * 3 / 4, cb_size, log2_cb_size, 1, idx - 2);
+                hls_prediction_unit(lc, x0,               y0, cb_size     / 4, cb_size, log2_cb_size, 0, idx - 2);
+                hls_prediction_unit(lc, x0 + cb_size / 4, y0, cb_size * 3 / 4, cb_size, log2_cb_size, 1, idx - 2);
                 break;
             case PART_nRx2N:
-                hls_prediction_unit(s, x0,                   y0, cb_size * 3 / 4, cb_size, log2_cb_size, 0, idx - 2);
-                hls_prediction_unit(s, x0 + cb_size * 3 / 4, y0, cb_size     / 4, cb_size, log2_cb_size, 1, idx - 2);
+                hls_prediction_unit(lc, x0,                   y0, cb_size * 3 / 4, cb_size, log2_cb_size, 0, idx - 2);
+                hls_prediction_unit(lc, x0 + cb_size * 3 / 4, y0, cb_size     / 4, cb_size, log2_cb_size, 1, idx - 2);
                 break;
             case PART_NxN:
-                hls_prediction_unit(s, x0,               y0,               cb_size / 2, cb_size / 2, log2_cb_size, 0, idx - 1);
-                hls_prediction_unit(s, x0 + cb_size / 2, y0,               cb_size / 2, cb_size / 2, log2_cb_size, 1, idx - 1);
-                hls_prediction_unit(s, x0,               y0 + cb_size / 2, cb_size / 2, cb_size / 2, log2_cb_size, 2, idx - 1);
-                hls_prediction_unit(s, x0 + cb_size / 2, y0 + cb_size / 2, cb_size / 2, cb_size / 2, log2_cb_size, 3, idx - 1);
+                hls_prediction_unit(lc, x0,               y0,               cb_size / 2, cb_size / 2, log2_cb_size, 0, idx - 1);
+                hls_prediction_unit(lc, x0 + cb_size / 2, y0,               cb_size / 2, cb_size / 2, log2_cb_size, 1, idx - 1);
+                hls_prediction_unit(lc, x0,               y0 + cb_size / 2, cb_size / 2, cb_size / 2, log2_cb_size, 2, idx - 1);
+                hls_prediction_unit(lc, x0 + cb_size / 2, y0 + cb_size / 2, cb_size / 2, cb_size / 2, log2_cb_size, 3, idx - 1);
                 break;
             }
         }
@@ -2305,7 +2305,7 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size)
                 lc->cu.max_trafo_depth = lc->cu.pred_mode == MODE_INTRA ?
                                          s->ps.sps->max_transform_hierarchy_depth_intra + lc->cu.intra_split_flag :
                                          s->ps.sps->max_transform_hierarchy_depth_inter;
-                ret = hls_transform_tree(s, x0, y0, x0, y0, x0, y0,
+                ret = hls_transform_tree(lc, x0, y0, x0, y0, x0, y0,
                                          log2_cb_size,
                                          log2_cb_size, 0, 0, cbf, cbf);
                 if (ret < 0)
@@ -2336,10 +2336,10 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size)
     return 0;
 }
 
-static int hls_coding_quadtree(HEVCContext *s, int x0, int y0,
+static int hls_coding_quadtree(HEVCLocalContext *lc, int x0, int y0,
                                int log2_cb_size, int cb_depth)
 {
-    HEVCLocalContext *lc = s->HEVClc;
+    const HEVCContext *const s = lc->parent;
     const int cb_size    = 1 << log2_cb_size;
     int ret;
     int split_cu;
@@ -2371,23 +2371,23 @@ static int hls_coding_quadtree(HEVCContext *s, int x0, int y0,
 
         int more_data = 0;
 
-        more_data = hls_coding_quadtree(s, x0, y0, log2_cb_size - 1, cb_depth + 1);
+        more_data = hls_coding_quadtree(lc, x0, y0, log2_cb_size - 1, cb_depth + 1);
         if (more_data < 0)
             return more_data;
 
         if (more_data && x1 < s->ps.sps->width) {
-            more_data = hls_coding_quadtree(s, x1, y0, log2_cb_size - 1, cb_depth + 1);
+            more_data = hls_coding_quadtree(lc, x1, y0, log2_cb_size - 1, cb_depth + 1);
             if (more_data < 0)
                 return more_data;
         }
         if (more_data && y1 < s->ps.sps->height) {
-            more_data = hls_coding_quadtree(s, x0, y1, log2_cb_size - 1, cb_depth + 1);
+            more_data = hls_coding_quadtree(lc, x0, y1, log2_cb_size - 1, cb_depth + 1);
             if (more_data < 0)
                 return more_data;
         }
         if (more_data && x1 < s->ps.sps->width &&
             y1 < s->ps.sps->height) {
-            more_data = hls_coding_quadtree(s, x1, y1, log2_cb_size - 1, cb_depth + 1);
+            more_data = hls_coding_quadtree(lc, x1, y1, log2_cb_size - 1, cb_depth + 1);
             if (more_data < 0)
                 return more_data;
         }
@@ -2402,7 +2402,7 @@ static int hls_coding_quadtree(HEVCContext *s, int x0, int y0,
         else
             return 0;
     } else {
-        ret = hls_coding_unit(s, x0, y0, log2_cb_size);
+        ret = hls_coding_unit(lc, s, x0, y0, log2_cb_size);
         if (ret < 0)
             return ret;
         if ((!((x0 + cb_size) %
@@ -2421,10 +2421,10 @@ static int hls_coding_quadtree(HEVCContext *s, int x0, int y0,
     return 0;
 }
 
-static void hls_decode_neighbour(HEVCContext *s, int x_ctb, int y_ctb,
+static void hls_decode_neighbour(HEVCLocalContext *lc, int x_ctb, int y_ctb,
                                  int ctb_addr_ts)
 {
-    HEVCLocalContext *lc  = s->HEVClc;
+    const HEVCContext *const s = lc->parent;
     int ctb_size          = 1 << s->ps.sps->log2_ctb_size;
     int ctb_addr_rs       = s->ps.pps->ctb_addr_ts_to_rs[ctb_addr_ts];
     int ctb_addr_in_slice = ctb_addr_rs - s->sh.slice_addr;
@@ -2499,7 +2499,7 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread)
 
         x_ctb = (ctb_addr_rs % ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size)) << s->ps.sps->log2_ctb_size;
         y_ctb = (ctb_addr_rs / ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size)) << s->ps.sps->log2_ctb_size;
-        hls_decode_neighbour(s, x_ctb, y_ctb, ctb_addr_ts);
+        hls_decode_neighbour(lc, x_ctb, y_ctb, ctb_addr_ts);
 
         ret = ff_hevc_cabac_init(lc, ctb_addr_ts);
         if (ret < 0) {
@@ -2507,13 +2507,13 @@ static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread)
             return ret;
         }
 
-        hls_sao_param(s, x_ctb >> s->ps.sps->log2_ctb_size, y_ctb >> s->ps.sps->log2_ctb_size);
+        hls_sao_param(lc, x_ctb >> s->ps.sps->log2_ctb_size, y_ctb >> s->ps.sps->log2_ctb_size);
 
         s->deblock[ctb_addr_rs].beta_offset = s->sh.beta_offset;
         s->deblock[ctb_addr_rs].tc_offset   = s->sh.tc_offset;
         s->filter_slice_edges[ctb_addr_rs]  = s->sh.slice_loop_filter_across_slices_enabled_flag;
 
-        more_data = hls_coding_quadtree(s, x_ctb, y_ctb, s->ps.sps->log2_ctb_size, 0);
+        more_data = hls_coding_quadtree(lc, x_ctb, y_ctb, s->ps.sps->log2_ctb_size, 0);
         if (more_data < 0) {
             s->tab_slice_address[ctb_addr_rs] = -1;
             return more_data;
@@ -2570,7 +2570,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *input_ctb_row, int
         int x_ctb = (ctb_addr_rs % s->ps.sps->ctb_width) << s->ps.sps->log2_ctb_size;
         int y_ctb = (ctb_addr_rs / s->ps.sps->ctb_width) << s->ps.sps->log2_ctb_size;
 
-        hls_decode_neighbour(s, x_ctb, y_ctb, ctb_addr_ts);
+        hls_decode_neighbour(lc, x_ctb, y_ctb, ctb_addr_ts);
 
         ff_thread_await_progress2(s->avctx, ctb_row, thread, SHIFT_CTB_WPP);
 
@@ -2582,8 +2582,8 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *input_ctb_row, int
         ret = ff_hevc_cabac_init(lc, ctb_addr_ts);
         if (ret < 0)
             goto error;
-        hls_sao_param(s, x_ctb >> s->ps.sps->log2_ctb_size, y_ctb >> s->ps.sps->log2_ctb_size);
-        more_data = hls_coding_quadtree(s, x_ctb, y_ctb, s->ps.sps->log2_ctb_size, 0);
+        hls_sao_param(lc, x_ctb >> s->ps.sps->log2_ctb_size, y_ctb >> s->ps.sps->log2_ctb_size);
+        more_data = hls_coding_quadtree(lc, x_ctb, y_ctb, s->ps.sps->log2_ctb_size, 0);
 
         if (more_data < 0) {
             ret = more_data;
-- 
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [FFmpeg-devel] [PATCH 13/18] avcodec/hevcdec: Pass HEVCLocalContext** via execute2
  2022-06-30 21:48 [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Andreas Rheinhardt
                   ` (10 preceding siblings ...)
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 12/18] avcodec/hevcdec: " Andreas Rheinhardt
@ 2022-06-30 22:29 ` Andreas Rheinhardt
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 14/18] avcodec/hevcdec: Don't allocate redundant HEVCContexts Andreas Rheinhardt
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-06-30 22:29 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andreas Rheinhardt

Right now the code passes a list of ints whose entry #i
is just i as opaque parameter to hls_decode_entry_wpp
via execute2; said list is even constantly allocated and freed.

This commit stops doing so and instead passes the list of
HEVCLocalContext* instead, so that the main HEVCContext
can be avoided in accessing the HEVCLocalContext.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/hevcdec.c | 24 ++++++++----------------
 1 file changed, 8 insertions(+), 16 deletions(-)

diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index 1d0b80ea48..9d1241f293 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -2543,22 +2543,20 @@ static int hls_slice_data(HEVCContext *s)
     s->avctx->execute(s->avctx, hls_decode_entry, arg, ret , 1, sizeof(int));
     return ret[0];
 }
-static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *input_ctb_row, int job, int self_id)
+static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
+                                int job, int self_id)
 {
-    HEVCContext *s1  = avctxt->priv_data, *s;
-    HEVCLocalContext *lc;
+    HEVCLocalContext *lc = ((HEVCLocalContext**)hevc_lclist)[self_id];
+    const HEVCContext *const s = lc->parent;
+    HEVCContext *s1  = avctxt->priv_data;
     int ctb_size    = 1<< s1->ps.sps->log2_ctb_size;
     int more_data   = 1;
-    int *ctb_row_p    = input_ctb_row;
-    int ctb_row = ctb_row_p[job];
+    int ctb_row = job;
     int ctb_addr_rs = s1->sh.slice_ctb_addr_rs + ctb_row * ((s1->ps.sps->width + ctb_size - 1) >> s1->ps.sps->log2_ctb_size);
     int ctb_addr_ts = s1->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
     int thread = ctb_row % s1->threads_number;
     int ret;
 
-    s = s1->sList[self_id];
-    lc = s->HEVClc;
-
     if(ctb_row) {
         ret = init_get_bits8(&lc->gb, s->data + s->sh.offset[ctb_row - 1], s->sh.size[ctb_row - 1]);
         if (ret < 0)
@@ -2630,16 +2628,12 @@ static int hls_slice_data_wpp(HEVCContext *s, const H2645NAL *nal)
     int length          = nal->size;
     HEVCLocalContext *lc = s->HEVClc;
     int *ret = av_malloc_array(s->sh.num_entry_point_offsets + 1, sizeof(int));
-    int *arg = av_malloc_array(s->sh.num_entry_point_offsets + 1, sizeof(int));
     int64_t offset;
     int64_t startheader, cmpt = 0;
     int i, j, res = 0;
 
-    if (!ret || !arg) {
-        av_free(ret);
-        av_free(arg);
+    if (!ret)
         return AVERROR(ENOMEM);
-    }
 
     if (s->sh.slice_ctb_addr_rs + s->sh.num_entry_point_offsets * s->ps.sps->ctb_width >= s->ps.sps->ctb_width * s->ps.sps->ctb_height) {
         av_log(s->avctx, AV_LOG_ERROR, "WPP ctb addresses are wrong (%d %d %d %d)\n",
@@ -2713,18 +2707,16 @@ static int hls_slice_data_wpp(HEVCContext *s, const H2645NAL *nal)
     ff_reset_entries(s->avctx);
 
     for (i = 0; i <= s->sh.num_entry_point_offsets; i++) {
-        arg[i] = i;
         ret[i] = 0;
     }
 
     if (s->ps.pps->entropy_coding_sync_enabled_flag)
-        s->avctx->execute2(s->avctx, hls_decode_entry_wpp, arg, ret, s->sh.num_entry_point_offsets + 1);
+        s->avctx->execute2(s->avctx, hls_decode_entry_wpp, s->HEVClcList, ret, s->sh.num_entry_point_offsets + 1);
 
     for (i = 0; i <= s->sh.num_entry_point_offsets; i++)
         res += ret[i];
 error:
     av_free(ret);
-    av_free(arg);
     return res;
 }
 
-- 
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [FFmpeg-devel] [PATCH 14/18] avcodec/hevcdec: Don't allocate redundant HEVCContexts
  2022-06-30 21:48 [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Andreas Rheinhardt
                   ` (11 preceding siblings ...)
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 13/18] avcodec/hevcdec: Pass HEVCLocalContext** via execute2 Andreas Rheinhardt
@ 2022-06-30 22:29 ` Andreas Rheinhardt
  2022-07-01 21:25   ` Michael Niedermayer
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 15/18] avcodec/hevcdec: Check allocation Andreas Rheinhardt
                   ` (4 subsequent siblings)
  17 siblings, 1 reply; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-06-30 22:29 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andreas Rheinhardt

The HEVC decoder has both HEVCContext and HEVCLocalContext
structures. The latter is supposed to be the structure
containing the per-slicethread state.

Yet up until now that is not how it is handled in practice:
Each HEVCLocalContext has a unique HEVCContext allocated for it
and each of these coincides except in exactly one field: The
corresponding HEVCLocalContext. This makes it possible to pass
the HEVCContext everywhere where logically a HEVCLocalContext
should be used. And up until recently, this is how it has been done.

Yet the preceding patches changed this, making it possible
to avoid allocating redundant HEVCContexts.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/hevcdec.c | 40 ++++++++++++++++------------------------
 libavcodec/hevcdec.h |  2 --
 2 files changed, 16 insertions(+), 26 deletions(-)

diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index 9d1241f293..048fcc76b4 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -2548,13 +2548,12 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
 {
     HEVCLocalContext *lc = ((HEVCLocalContext**)hevc_lclist)[self_id];
     const HEVCContext *const s = lc->parent;
-    HEVCContext *s1  = avctxt->priv_data;
-    int ctb_size    = 1<< s1->ps.sps->log2_ctb_size;
+    int ctb_size    = 1 << s->ps.sps->log2_ctb_size;
     int more_data   = 1;
     int ctb_row = job;
-    int ctb_addr_rs = s1->sh.slice_ctb_addr_rs + ctb_row * ((s1->ps.sps->width + ctb_size - 1) >> s1->ps.sps->log2_ctb_size);
-    int ctb_addr_ts = s1->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
-    int thread = ctb_row % s1->threads_number;
+    int ctb_addr_rs = s->sh.slice_ctb_addr_rs + ctb_row * ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size);
+    int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
+    int thread = ctb_row % s->threads_number;
     int ret;
 
     if(ctb_row) {
@@ -2572,7 +2571,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
 
         ff_thread_await_progress2(s->avctx, ctb_row, thread, SHIFT_CTB_WPP);
 
-        if (atomic_load(&s1->wpp_err)) {
+        if (atomic_load(&s->wpp_err)) {
             ff_thread_report_progress2(s->avctx, ctb_row , thread, SHIFT_CTB_WPP);
             return 0;
         }
@@ -2595,7 +2594,8 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
         ff_hevc_hls_filters(lc, x_ctb, y_ctb, ctb_size);
 
         if (!more_data && (x_ctb+ctb_size) < s->ps.sps->width && ctb_row != s->sh.num_entry_point_offsets) {
-            atomic_store(&s1->wpp_err, 1);
+            /* Casting const away here is safe, because it is an atomic operation. */
+            atomic_store((atomic_int*)&s->wpp_err, 1);
             ff_thread_report_progress2(s->avctx, ctb_row ,thread, SHIFT_CTB_WPP);
             return 0;
         }
@@ -2617,7 +2617,8 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
     return 0;
 error:
     s->tab_slice_address[ctb_addr_rs] = -1;
-    atomic_store(&s1->wpp_err, 1);
+    /* Casting const away here is safe, because it is an atomic operation. */
+    atomic_store((atomic_int*)&s->wpp_err, 1);
     ff_thread_report_progress2(s->avctx, ctb_row ,thread, SHIFT_CTB_WPP);
     return ret;
 }
@@ -2647,18 +2648,15 @@ static int hls_slice_data_wpp(HEVCContext *s, const H2645NAL *nal)
     ff_alloc_entries(s->avctx, s->sh.num_entry_point_offsets + 1);
 
     for (i = 1; i < s->threads_number; i++) {
-        if (s->sList[i] && s->HEVClcList[i])
+        if (s->HEVClcList[i])
             continue;
-        av_freep(&s->sList[i]);
-        av_freep(&s->HEVClcList[i]);
-        s->sList[i] = av_malloc(sizeof(HEVCContext));
         s->HEVClcList[i] = av_mallocz(sizeof(HEVCLocalContext));
-        if (!s->sList[i] || !s->HEVClcList[i]) {
+        if (!s->HEVClcList[i]) {
             res = AVERROR(ENOMEM);
             goto error;
         }
         s->HEVClcList[i]->logctx = s->avctx;
-        s->HEVClcList[i]->parent = s->sList[i];
+        s->HEVClcList[i]->parent = s;
     }
 
     offset = (lc->gb.index >> 3);
@@ -2697,10 +2695,8 @@ static int hls_slice_data_wpp(HEVCContext *s, const H2645NAL *nal)
     s->data = data;
 
     for (i = 1; i < s->threads_number; i++) {
-        memcpy(s->sList[i], s, sizeof(HEVCContext));
-        s->sList[i]->HEVClc = s->HEVClcList[i];
-        s->sList[i]->HEVClc->first_qp_group = 1;
-        s->sList[i]->HEVClc->qp_y = s->sList[0]->HEVClc->qp_y;
+        s->HEVClcList[i]->first_qp_group = 1;
+        s->HEVClcList[i]->qp_y = s->HEVClc->qp_y;
     }
 
     atomic_store(&s->wpp_err, 0);
@@ -3613,15 +3609,13 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx)
     av_freep(&s->sh.offset);
     av_freep(&s->sh.size);
 
-    if (s->HEVClcList && s->sList) {
+    if (s->HEVClcList) {
         for (i = 1; i < s->threads_number; i++) {
             av_freep(&s->HEVClcList[i]);
-            av_freep(&s->sList[i]);
         }
     }
     av_freep(&s->HEVClc);
     av_freep(&s->HEVClcList);
-    av_freep(&s->sList);
 
     ff_h2645_packet_uninit(&s->pkt);
 
@@ -3639,13 +3633,11 @@ static av_cold int hevc_init_context(AVCodecContext *avctx)
 
     s->HEVClc = av_mallocz(sizeof(HEVCLocalContext));
     s->HEVClcList = av_mallocz(sizeof(HEVCLocalContext*) * s->threads_number);
-    s->sList = av_mallocz(sizeof(HEVCContext*) * s->threads_number);
-    if (!s->HEVClc || !s->HEVClcList || !s->sList)
+    if (!s->HEVClc || !s->HEVClcList)
         return AVERROR(ENOMEM);
     s->HEVClc->parent = s;
     s->HEVClc->logctx = avctx;
     s->HEVClcList[0] = s->HEVClc;
-    s->sList[0] = s;
 
     s->cabac = av_malloc(sizeof(*s->cabac));
     if (!s->cabac)
diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h
index b33e8ae0f6..3367ee312a 100644
--- a/libavcodec/hevcdec.h
+++ b/libavcodec/hevcdec.h
@@ -476,8 +476,6 @@ typedef struct HEVCContext {
     const AVClass *c;  // needed by private avoptions
     AVCodecContext *avctx;
 
-    struct HEVCContext  **sList;
-
     HEVCLocalContext    **HEVClcList;
     HEVCLocalContext    *HEVClc;
 
-- 
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [FFmpeg-devel] [PATCH 15/18] avcodec/hevcdec: Check allocation
  2022-06-30 21:48 [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Andreas Rheinhardt
                   ` (12 preceding siblings ...)
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 14/18] avcodec/hevcdec: Don't allocate redundant HEVCContexts Andreas Rheinhardt
@ 2022-06-30 22:29 ` Andreas Rheinhardt
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 16/18] avcodec/pthread_slice: Combine allocating and zeroing entries Andreas Rheinhardt
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-06-30 22:29 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andreas Rheinhardt

Also postpone it after the checks for invalid input.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/hevcdec.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index 048fcc76b4..5215f06e31 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -2645,8 +2645,6 @@ static int hls_slice_data_wpp(HEVCContext *s, const H2645NAL *nal)
         goto error;
     }
 
-    ff_alloc_entries(s->avctx, s->sh.num_entry_point_offsets + 1);
-
     for (i = 1; i < s->threads_number; i++) {
         if (s->HEVClcList[i])
             continue;
@@ -2700,6 +2698,9 @@ static int hls_slice_data_wpp(HEVCContext *s, const H2645NAL *nal)
     }
 
     atomic_store(&s->wpp_err, 0);
+    res = ff_alloc_entries(s->avctx, s->sh.num_entry_point_offsets + 1);
+    if (res < 0)
+        goto error;
     ff_reset_entries(s->avctx);
 
     for (i = 0; i <= s->sh.num_entry_point_offsets; i++) {
-- 
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [FFmpeg-devel] [PATCH 16/18] avcodec/pthread_slice: Combine allocating and zeroing entries
  2022-06-30 21:48 [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Andreas Rheinhardt
                   ` (13 preceding siblings ...)
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 15/18] avcodec/hevcdec: Check allocation Andreas Rheinhardt
@ 2022-06-30 22:29 ` Andreas Rheinhardt
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 17/18] avcodec/pthread_slice: Reuse buffer if possible Andreas Rheinhardt
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-06-30 22:29 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andreas Rheinhardt

Actually, ff_slice_thread_allocz_entries() always already
allocates zeroed entries, so ff_reset_entries() was already
unnecessary. Make this more clear by renaming it to
ff_slice_thread_allocz_entries().

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/hevcdec.c       | 3 +--
 libavcodec/pthread_slice.c | 8 +-------
 libavcodec/thread.h        | 3 +--
 libavcodec/utils.c         | 6 +-----
 4 files changed, 4 insertions(+), 16 deletions(-)

diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index 5215f06e31..e2568c04c0 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -2698,10 +2698,9 @@ static int hls_slice_data_wpp(HEVCContext *s, const H2645NAL *nal)
     }
 
     atomic_store(&s->wpp_err, 0);
-    res = ff_alloc_entries(s->avctx, s->sh.num_entry_point_offsets + 1);
+    res = ff_slice_thread_allocz_entries(s->avctx, s->sh.num_entry_point_offsets + 1);
     if (res < 0)
         goto error;
-    ff_reset_entries(s->avctx);
 
     for (i = 0; i <= s->sh.num_entry_point_offsets; i++) {
         ret[i] = 0;
diff --git a/libavcodec/pthread_slice.c b/libavcodec/pthread_slice.c
index e34116116d..756cc59dbf 100644
--- a/libavcodec/pthread_slice.c
+++ b/libavcodec/pthread_slice.c
@@ -237,7 +237,7 @@ void ff_thread_await_progress2(AVCodecContext *avctx, int field, int thread, int
     pthread_mutex_unlock(&progress->mutex);
 }
 
-int ff_alloc_entries(AVCodecContext *avctx, int count)
+int ff_slice_thread_allocz_entries(AVCodecContext *avctx, int count)
 {
     if (avctx->active_thread_type & FF_THREAD_SLICE)  {
         SliceThreadContext *p = avctx->internal->thread_ctx;
@@ -256,9 +256,3 @@ int ff_alloc_entries(AVCodecContext *avctx, int count)
 
     return 0;
 }
-
-void ff_reset_entries(AVCodecContext *avctx)
-{
-    SliceThreadContext *p = avctx->internal->thread_ctx;
-    memset(p->entries, 0, p->entries_count * sizeof(int));
-}
diff --git a/libavcodec/thread.h b/libavcodec/thread.h
index 92cbd927f1..d5673f25ea 100644
--- a/libavcodec/thread.h
+++ b/libavcodec/thread.h
@@ -104,8 +104,7 @@ int ff_slice_thread_execute_with_mainfunc(AVCodecContext *avctx,
         int (*action_func2)(AVCodecContext *c, void *arg, int jobnr, int threadnr),
         int (*main_func)(AVCodecContext *c), void *arg, int *ret, int job_count);
 void ff_thread_free(AVCodecContext *s);
-int ff_alloc_entries(AVCodecContext *avctx, int count);
-void ff_reset_entries(AVCodecContext *avctx);
+int ff_slice_thread_allocz_entries(AVCodecContext *avctx, int count);
 int ff_slice_thread_init_progress(AVCodecContext *avctx);
 void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, int n);
 void ff_thread_await_progress2(AVCodecContext *avctx,  int field, int thread, int shift);
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index f78475d0ad..cae61d80ff 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -963,15 +963,11 @@ int ff_slice_thread_init_progress(AVCodecContext *avctx)
     return 0;
 }
 
-int ff_alloc_entries(AVCodecContext *avctx, int count)
+int ff_slice_thread_allocz_entries(AVCodecContext *avctx, int count)
 {
     return 0;
 }
 
-void ff_reset_entries(AVCodecContext *avctx)
-{
-}
-
 void ff_thread_await_progress2(AVCodecContext *avctx, int field, int thread, int shift)
 {
 }
-- 
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [FFmpeg-devel] [PATCH 17/18] avcodec/pthread_slice: Reuse buffer if possible
  2022-06-30 21:48 [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Andreas Rheinhardt
                   ` (14 preceding siblings ...)
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 16/18] avcodec/pthread_slice: Combine allocating and zeroing entries Andreas Rheinhardt
@ 2022-06-30 22:29 ` Andreas Rheinhardt
  2022-07-01 11:33   ` Paul B Mahol
  2022-07-01 13:21   ` Tomas Härdin
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 18/18] avcodec/hevcdec: Move allocation after error checks Andreas Rheinhardt
  2022-07-01 13:30 ` [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Tomas Härdin
  17 siblings, 2 replies; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-06-30 22:29 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andreas Rheinhardt

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/pthread_slice.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/libavcodec/pthread_slice.c b/libavcodec/pthread_slice.c
index 756cc59dbf..a4d31c6f4d 100644
--- a/libavcodec/pthread_slice.c
+++ b/libavcodec/pthread_slice.c
@@ -242,9 +242,11 @@ int ff_slice_thread_allocz_entries(AVCodecContext *avctx, int count)
     if (avctx->active_thread_type & FF_THREAD_SLICE)  {
         SliceThreadContext *p = avctx->internal->thread_ctx;
 
-        if (p->entries) {
-            av_freep(&p->entries);
+        if (p->entries_count == count) {
+            memset(p->entries, 0, p->entries_count * sizeof(*p->entries));
+            return 0;
         }
+        av_freep(&p->entries);
 
         p->entries       = av_calloc(count, sizeof(*p->entries));
         if (!p->entries) {
-- 
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [FFmpeg-devel] [PATCH 18/18] avcodec/hevcdec: Move allocation after error checks
  2022-06-30 21:48 [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Andreas Rheinhardt
                   ` (15 preceding siblings ...)
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 17/18] avcodec/pthread_slice: Reuse buffer if possible Andreas Rheinhardt
@ 2022-06-30 22:29 ` Andreas Rheinhardt
  2022-07-01 13:30 ` [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Tomas Härdin
  17 siblings, 0 replies; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-06-30 22:29 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Andreas Rheinhardt

While just at it, also use av_calloc() instead of zeroing
the array ourselves in a loop.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/hevcdec.c | 27 ++++++++++-----------------
 1 file changed, 10 insertions(+), 17 deletions(-)

diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index e2568c04c0..c61ae49be1 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -2628,31 +2628,25 @@ static int hls_slice_data_wpp(HEVCContext *s, const H2645NAL *nal)
     const uint8_t *data = nal->data;
     int length          = nal->size;
     HEVCLocalContext *lc = s->HEVClc;
-    int *ret = av_malloc_array(s->sh.num_entry_point_offsets + 1, sizeof(int));
+    int *ret;
     int64_t offset;
     int64_t startheader, cmpt = 0;
     int i, j, res = 0;
 
-    if (!ret)
-        return AVERROR(ENOMEM);
-
     if (s->sh.slice_ctb_addr_rs + s->sh.num_entry_point_offsets * s->ps.sps->ctb_width >= s->ps.sps->ctb_width * s->ps.sps->ctb_height) {
         av_log(s->avctx, AV_LOG_ERROR, "WPP ctb addresses are wrong (%d %d %d %d)\n",
             s->sh.slice_ctb_addr_rs, s->sh.num_entry_point_offsets,
             s->ps.sps->ctb_width, s->ps.sps->ctb_height
         );
-        res = AVERROR_INVALIDDATA;
-        goto error;
+        return AVERROR_INVALIDDATA;
     }
 
     for (i = 1; i < s->threads_number; i++) {
         if (s->HEVClcList[i])
             continue;
         s->HEVClcList[i] = av_mallocz(sizeof(HEVCLocalContext));
-        if (!s->HEVClcList[i]) {
-            res = AVERROR(ENOMEM);
-            goto error;
-        }
+        if (!s->HEVClcList[i])
+            return AVERROR(ENOMEM);
         s->HEVClcList[i]->logctx = s->avctx;
         s->HEVClcList[i]->parent = s;
     }
@@ -2683,8 +2677,7 @@ static int hls_slice_data_wpp(HEVCContext *s, const H2645NAL *nal)
         offset += s->sh.entry_point_offset[s->sh.num_entry_point_offsets - 1] - cmpt;
         if (length < offset) {
             av_log(s->avctx, AV_LOG_ERROR, "entry_point_offset table is corrupted\n");
-            res = AVERROR_INVALIDDATA;
-            goto error;
+            return AVERROR_INVALIDDATA;
         }
         s->sh.size[s->sh.num_entry_point_offsets - 1] = length - offset;
         s->sh.offset[s->sh.num_entry_point_offsets - 1] = offset;
@@ -2700,18 +2693,18 @@ static int hls_slice_data_wpp(HEVCContext *s, const H2645NAL *nal)
     atomic_store(&s->wpp_err, 0);
     res = ff_slice_thread_allocz_entries(s->avctx, s->sh.num_entry_point_offsets + 1);
     if (res < 0)
-        goto error;
+        return res;
 
-    for (i = 0; i <= s->sh.num_entry_point_offsets; i++) {
-        ret[i] = 0;
-    }
+    ret = av_calloc(s->sh.num_entry_point_offsets + 1, sizeof(*ret));
+    if (!ret)
+        return AVERROR(ENOMEM);
 
     if (s->ps.pps->entropy_coding_sync_enabled_flag)
         s->avctx->execute2(s->avctx, hls_decode_entry_wpp, s->HEVClcList, ret, s->sh.num_entry_point_offsets + 1);
 
     for (i = 0; i <= s->sh.num_entry_point_offsets; i++)
         res += ret[i];
-error:
+
     av_free(ret);
     return res;
 }
-- 
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [FFmpeg-devel] [PATCH 17/18] avcodec/pthread_slice: Reuse buffer if possible
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 17/18] avcodec/pthread_slice: Reuse buffer if possible Andreas Rheinhardt
@ 2022-07-01 11:33   ` Paul B Mahol
  2022-07-01 13:21   ` Tomas Härdin
  1 sibling, 0 replies; 37+ messages in thread
From: Paul B Mahol @ 2022-07-01 11:33 UTC (permalink / raw)
  To: FFmpeg development discussions and patches; +Cc: Andreas Rheinhardt

On Fri, Jul 1, 2022 at 12:32 AM Andreas Rheinhardt <
andreas.rheinhardt@outlook.com> wrote:

> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
> ---
>  libavcodec/pthread_slice.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/libavcodec/pthread_slice.c b/libavcodec/pthread_slice.c
> index 756cc59dbf..a4d31c6f4d 100644
> --- a/libavcodec/pthread_slice.c
> +++ b/libavcodec/pthread_slice.c
> @@ -242,9 +242,11 @@ int ff_slice_thread_allocz_entries(AVCodecContext
> *avctx, int count)
>      if (avctx->active_thread_type & FF_THREAD_SLICE)  {
>          SliceThreadContext *p = avctx->internal->thread_ctx;
>
> -        if (p->entries) {
> -            av_freep(&p->entries);
> +        if (p->entries_count == count) {
> +            memset(p->entries, 0, p->entries_count * sizeof(*p->entries));
> +            return 0;
>          }
> +        av_freep(&p->entries);
>
>          p->entries       = av_calloc(count, sizeof(*p->entries));
>          if (!p->entries) {
> --
> 2.34.1
>
>
LGTM

> _______________________________________________
> 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".
>
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [FFmpeg-devel] [PATCH 17/18] avcodec/pthread_slice: Reuse buffer if possible
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 17/18] avcodec/pthread_slice: Reuse buffer if possible Andreas Rheinhardt
  2022-07-01 11:33   ` Paul B Mahol
@ 2022-07-01 13:21   ` Tomas Härdin
  2022-07-22 20:04     ` Andreas Rheinhardt
  1 sibling, 1 reply; 37+ messages in thread
From: Tomas Härdin @ 2022-07-01 13:21 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

fre 2022-07-01 klockan 00:29 +0200 skrev Andreas Rheinhardt:
> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
> ---
>  libavcodec/pthread_slice.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/libavcodec/pthread_slice.c b/libavcodec/pthread_slice.c
> index 756cc59dbf..a4d31c6f4d 100644
> --- a/libavcodec/pthread_slice.c
> +++ b/libavcodec/pthread_slice.c
> @@ -242,9 +242,11 @@ int
> ff_slice_thread_allocz_entries(AVCodecContext *avctx, int count)
>      if (avctx->active_thread_type & FF_THREAD_SLICE)  {
>          SliceThreadContext *p = avctx->internal->thread_ctx;
>  
> -        if (p->entries) {
> -            av_freep(&p->entries);
> +        if (p->entries_count == count) {
> +            memset(p->entries, 0, p->entries_count * sizeof(*p-
> >entries));
> +            return 0;

Couldn't this trivially handle p->entries_count < count also?

>          }
> +        av_freep(&p->entries);
>  
>          p->entries       = av_calloc(count, sizeof(*p->entries));
>          if (!p->entries) {

Looks like we could use an av_fast_calloc()

/Tomas

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex
  2022-06-30 21:48 [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Andreas Rheinhardt
                   ` (16 preceding siblings ...)
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 18/18] avcodec/hevcdec: Move allocation after error checks Andreas Rheinhardt
@ 2022-07-01 13:30 ` Tomas Härdin
  17 siblings, 0 replies; 37+ messages in thread
From: Tomas Härdin @ 2022-07-01 13:30 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

tor 2022-06-30 klockan 23:48 +0200 skrev Andreas Rheinhardt:
> It results in undefined behaviour. Instead initialize the mutexes
> and condition variables once during init (and check these
> initializations).
> 
> Also combine the corresponding mutex and condition variable
> into one structure so that one can allocate their array
> jointly.
> 

Makes the code simpler to boot. Nice!

Passes FATE and works with the threading patch I have on here as well.
THREAD_TYPE=slice THREADS=4 and THREAD_TYPE=slice THREADS=1

/Tomas


_______________________________________________
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [FFmpeg-devel] [PATCH 14/18] avcodec/hevcdec: Don't allocate redundant HEVCContexts
  2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 14/18] avcodec/hevcdec: Don't allocate redundant HEVCContexts Andreas Rheinhardt
@ 2022-07-01 21:25   ` Michael Niedermayer
  2022-07-02  6:32     ` Andreas Rheinhardt
  0 siblings, 1 reply; 37+ messages in thread
From: Michael Niedermayer @ 2022-07-01 21:25 UTC (permalink / raw)
  To: FFmpeg development discussions and patches


[-- Attachment #1.1: Type: text/plain, Size: 3568 bytes --]

On Fri, Jul 01, 2022 at 12:29:45AM +0200, Andreas Rheinhardt wrote:
> The HEVC decoder has both HEVCContext and HEVCLocalContext
> structures. The latter is supposed to be the structure
> containing the per-slicethread state.
> 
> Yet up until now that is not how it is handled in practice:
> Each HEVCLocalContext has a unique HEVCContext allocated for it
> and each of these coincides except in exactly one field: The
> corresponding HEVCLocalContext. This makes it possible to pass
> the HEVCContext everywhere where logically a HEVCLocalContext
> should be used. And up until recently, this is how it has been done.
> 
> Yet the preceding patches changed this, making it possible
> to avoid allocating redundant HEVCContexts.
> 
> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
> ---
>  libavcodec/hevcdec.c | 40 ++++++++++++++++------------------------
>  libavcodec/hevcdec.h |  2 --
>  2 files changed, 16 insertions(+), 26 deletions(-)
> 
> diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
> index 9d1241f293..048fcc76b4 100644
> --- a/libavcodec/hevcdec.c
> +++ b/libavcodec/hevcdec.c
> @@ -2548,13 +2548,12 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
>  {
>      HEVCLocalContext *lc = ((HEVCLocalContext**)hevc_lclist)[self_id];
>      const HEVCContext *const s = lc->parent;
> -    HEVCContext *s1  = avctxt->priv_data;
> -    int ctb_size    = 1<< s1->ps.sps->log2_ctb_size;
> +    int ctb_size    = 1 << s->ps.sps->log2_ctb_size;
>      int more_data   = 1;
>      int ctb_row = job;
> -    int ctb_addr_rs = s1->sh.slice_ctb_addr_rs + ctb_row * ((s1->ps.sps->width + ctb_size - 1) >> s1->ps.sps->log2_ctb_size);
> -    int ctb_addr_ts = s1->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
> -    int thread = ctb_row % s1->threads_number;
> +    int ctb_addr_rs = s->sh.slice_ctb_addr_rs + ctb_row * ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size);
> +    int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
> +    int thread = ctb_row % s->threads_number;
>      int ret;
>  
>      if(ctb_row) {
> @@ -2572,7 +2571,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
>  
>          ff_thread_await_progress2(s->avctx, ctb_row, thread, SHIFT_CTB_WPP);
>  
> -        if (atomic_load(&s1->wpp_err)) {
> +        if (atomic_load(&s->wpp_err)) {
>              ff_thread_report_progress2(s->avctx, ctb_row , thread, SHIFT_CTB_WPP);

the consts in "const HEVCContext *const " make clang version 6.0.0-1ubuntu2 unhappy
(this was building shared libs)


CC	libavcodec/hevcdec.o
src/libavcodec/hevcdec.c:2574:13: error: address argument to atomic operation must be a pointer to non-const _Atomic type ('const atomic_int *' (aka 'const _Atomic(int) *') invalid)
        if (atomic_load(&s->wpp_err)) {
            ^           ~~~~~~~~~~~
/usr/lib/llvm-6.0/lib/clang/6.0.0/include/stdatomic.h:134:29: note: expanded from macro 'atomic_load'
#define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST)
                            ^                 ~~~~~~
1 error generated.
src/ffbuild/common.mak:81: recipe for target 'libavcodec/hevcdec.o' failed
make: *** [libavcodec/hevcdec.o] Error 1

thx

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

The real ebay dictionary, page 2
"100% positive feedback" - "All either got their money back or didnt complain"
"Best seller ever, very honest" - "Seller refunded buyer after failed scam"

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

[-- Attachment #2: Type: text/plain, Size: 251 bytes --]

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [FFmpeg-devel] [PATCH 14/18] avcodec/hevcdec: Don't allocate redundant HEVCContexts
  2022-07-01 21:25   ` Michael Niedermayer
@ 2022-07-02  6:32     ` Andreas Rheinhardt
  2022-07-05 22:24       ` Michael Niedermayer
  0 siblings, 1 reply; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-07-02  6:32 UTC (permalink / raw)
  To: ffmpeg-devel

Michael Niedermayer:
> On Fri, Jul 01, 2022 at 12:29:45AM +0200, Andreas Rheinhardt wrote:
>> The HEVC decoder has both HEVCContext and HEVCLocalContext
>> structures. The latter is supposed to be the structure
>> containing the per-slicethread state.
>>
>> Yet up until now that is not how it is handled in practice:
>> Each HEVCLocalContext has a unique HEVCContext allocated for it
>> and each of these coincides except in exactly one field: The
>> corresponding HEVCLocalContext. This makes it possible to pass
>> the HEVCContext everywhere where logically a HEVCLocalContext
>> should be used. And up until recently, this is how it has been done.
>>
>> Yet the preceding patches changed this, making it possible
>> to avoid allocating redundant HEVCContexts.
>>
>> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
>> ---
>>  libavcodec/hevcdec.c | 40 ++++++++++++++++------------------------
>>  libavcodec/hevcdec.h |  2 --
>>  2 files changed, 16 insertions(+), 26 deletions(-)
>>
>> diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
>> index 9d1241f293..048fcc76b4 100644
>> --- a/libavcodec/hevcdec.c
>> +++ b/libavcodec/hevcdec.c
>> @@ -2548,13 +2548,12 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
>>  {
>>      HEVCLocalContext *lc = ((HEVCLocalContext**)hevc_lclist)[self_id];
>>      const HEVCContext *const s = lc->parent;
>> -    HEVCContext *s1  = avctxt->priv_data;
>> -    int ctb_size    = 1<< s1->ps.sps->log2_ctb_size;
>> +    int ctb_size    = 1 << s->ps.sps->log2_ctb_size;
>>      int more_data   = 1;
>>      int ctb_row = job;
>> -    int ctb_addr_rs = s1->sh.slice_ctb_addr_rs + ctb_row * ((s1->ps.sps->width + ctb_size - 1) >> s1->ps.sps->log2_ctb_size);
>> -    int ctb_addr_ts = s1->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
>> -    int thread = ctb_row % s1->threads_number;
>> +    int ctb_addr_rs = s->sh.slice_ctb_addr_rs + ctb_row * ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size);
>> +    int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
>> +    int thread = ctb_row % s->threads_number;
>>      int ret;
>>  
>>      if(ctb_row) {
>> @@ -2572,7 +2571,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
>>  
>>          ff_thread_await_progress2(s->avctx, ctb_row, thread, SHIFT_CTB_WPP);
>>  
>> -        if (atomic_load(&s1->wpp_err)) {
>> +        if (atomic_load(&s->wpp_err)) {
>>              ff_thread_report_progress2(s->avctx, ctb_row , thread, SHIFT_CTB_WPP);
> 
> the consts in "const HEVCContext *const " make clang version 6.0.0-1ubuntu2 unhappy
> (this was building shared libs)
> 
> 
> CC	libavcodec/hevcdec.o
> src/libavcodec/hevcdec.c:2574:13: error: address argument to atomic operation must be a pointer to non-const _Atomic type ('const atomic_int *' (aka 'const _Atomic(int) *') invalid)
>         if (atomic_load(&s->wpp_err)) {
>             ^           ~~~~~~~~~~~
> /usr/lib/llvm-6.0/lib/clang/6.0.0/include/stdatomic.h:134:29: note: expanded from macro 'atomic_load'
> #define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST)
>                             ^                 ~~~~~~
> 1 error generated.
> src/ffbuild/common.mak:81: recipe for target 'libavcodec/hevcdec.o' failed
> make: *** [libavcodec/hevcdec.o] Error 1
> 
> thx
> 

Thanks for testing this. atomic_load is indeed declared without const in
7.17.7.2:

C atomic_load(volatile A *object);

Upon reflection this makes sense, because if atomics are implemented via
mutexes, even a read may involve a preceding write. So I'll cast const
away here, too, and add a comment. (It works when casting const away,
doesn't it?)

- Andreas
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [FFmpeg-devel] [PATCH 09/18] avcodec/hevcdec: Add stat_coeffs to HEVCABACState
@ 2022-07-02  8:34   ` Anton Khirnov
  2022-07-02 10:40     ` Andreas Rheinhardt
  0 siblings, 1 reply; 37+ messages in thread
From: Anton Khirnov @ 2022-07-02  8:34 UTC (permalink / raw)
  To: FFmpeg development discussions and patches; +Cc: Andreas Rheinhardt

Quoting Andreas Rheinhardt (2022-07-01 00:29:40)
> The HEVC decoder has both HEVCContext and HEVCLocalContext
> structures. The latter is supposed to be the structure
> containing the per-slicethread state.
> 
> Yet that is not how it is handled in practice: Each HEVCLocalContext
> has a unique HEVCContext allocated for it and each of these
> coincides with the main HEVCContext except in exactly one field:
> The corresponding HEVCLocalContext.
> This makes it possible to pass the HEVCContext everywhere where
> logically a HEVCLocalContext should be used.
> 
> This led to confusion in the first version of what eventually became
> commit c8bc0f66a875bc3708d8dc11b757f2198606ffd7:
> Before said commit, the initialization of the Rice parameter derivation
> state was incorrect; the fix for single-threaded as well as
> frame-threaded decoding was to add backup stats to HEVCContext
> that are used when the cabac state is updated*, see
> https://ffmpeg.org/pipermail/ffmpeg-devel/2020-August/268861.html
> Yet due to what has been said above, this does not work for
> slice-threading, because the each HEVCLocalContext has its own
> HEVCContext, so the Rice parameter state would not be transferred
> between threads.
> 
> This is fixed in c8bc0f66a875bc3708d8dc11b757f2198606ffd7
> by a hack: It rederives what the previous thread was and accesses
> the corresponding HEVCContext.
> 
> Fix this by treating the Rice parameter state the same way
> the ordinary CABAC parameters are shared between threads:
> Make them part of the same struct that is shared between
> slice threads. This does not cause races, because
> the parts of the code that access these Rice parameters
> are a subset of the parts of code that access the CABAC parameters.
> 
> *: And if the persistent_rice_adaptation_enabled_flag is set.
> 
> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
> ---
>  libavcodec/hevc_cabac.c | 17 ++++++++---------
>  libavcodec/hevcdec.c    | 10 +++++-----
>  libavcodec/hevcdec.h    | 10 +++++++---
>  3 files changed, 20 insertions(+), 17 deletions(-)
> 
> diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c
> index a194f8a02a..985c97ef2a 100644
> --- a/libavcodec/hevc_cabac.c
> +++ b/libavcodec/hevc_cabac.c
> @@ -453,19 +453,18 @@ void ff_hevc_save_states(HEVCContext *s, int ctb_addr_ts)
>          (ctb_addr_ts % s->ps.sps->ctb_width == 2 ||
>           (s->ps.sps->ctb_width == 2 &&
>            ctb_addr_ts % s->ps.sps->ctb_width == 0))) {
> -        memcpy(s->cabac_state, s->HEVClc->cabac_state, HEVC_CONTEXTS);
> +        memcpy(s->cabac->state, s->HEVClc->cabac_state, HEVC_CONTEXTS);

So if I'm reading this right, this copies the per-slice-context state
into the decoder-global state. And it's done from slice threads with no
locks. So how is this not racy?

-- 
Anton Khirnov
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [FFmpeg-devel] [PATCH 09/18] avcodec/hevcdec: Add stat_coeffs to HEVCABACState
  2022-07-02  8:34   ` Anton Khirnov
@ 2022-07-02 10:40     ` Andreas Rheinhardt
  2022-07-02 11:31       ` Andreas Rheinhardt
  0 siblings, 1 reply; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-07-02 10:40 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

Anton Khirnov:
> Quoting Andreas Rheinhardt (2022-07-01 00:29:40)
>> The HEVC decoder has both HEVCContext and HEVCLocalContext
>> structures. The latter is supposed to be the structure
>> containing the per-slicethread state.
>>
>> Yet that is not how it is handled in practice: Each HEVCLocalContext
>> has a unique HEVCContext allocated for it and each of these
>> coincides with the main HEVCContext except in exactly one field:
>> The corresponding HEVCLocalContext.
>> This makes it possible to pass the HEVCContext everywhere where
>> logically a HEVCLocalContext should be used.
>>
>> This led to confusion in the first version of what eventually became
>> commit c8bc0f66a875bc3708d8dc11b757f2198606ffd7:
>> Before said commit, the initialization of the Rice parameter derivation
>> state was incorrect; the fix for single-threaded as well as
>> frame-threaded decoding was to add backup stats to HEVCContext
>> that are used when the cabac state is updated*, see
>> https://ffmpeg.org/pipermail/ffmpeg-devel/2020-August/268861.html
>> Yet due to what has been said above, this does not work for
>> slice-threading, because the each HEVCLocalContext has its own
>> HEVCContext, so the Rice parameter state would not be transferred
>> between threads.
>>
>> This is fixed in c8bc0f66a875bc3708d8dc11b757f2198606ffd7
>> by a hack: It rederives what the previous thread was and accesses
>> the corresponding HEVCContext.
>>
>> Fix this by treating the Rice parameter state the same way
>> the ordinary CABAC parameters are shared between threads:
>> Make them part of the same struct that is shared between
>> slice threads. This does not cause races, because
>> the parts of the code that access these Rice parameters
>> are a subset of the parts of code that access the CABAC parameters.
>>
>> *: And if the persistent_rice_adaptation_enabled_flag is set.
>>
>> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
>> ---
>>  libavcodec/hevc_cabac.c | 17 ++++++++---------
>>  libavcodec/hevcdec.c    | 10 +++++-----
>>  libavcodec/hevcdec.h    | 10 +++++++---
>>  3 files changed, 20 insertions(+), 17 deletions(-)
>>
>> diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c
>> index a194f8a02a..985c97ef2a 100644
>> --- a/libavcodec/hevc_cabac.c
>> +++ b/libavcodec/hevc_cabac.c
>> @@ -453,19 +453,18 @@ void ff_hevc_save_states(HEVCContext *s, int ctb_addr_ts)
>>          (ctb_addr_ts % s->ps.sps->ctb_width == 2 ||
>>           (s->ps.sps->ctb_width == 2 &&
>>            ctb_addr_ts % s->ps.sps->ctb_width == 0))) {
>> -        memcpy(s->cabac_state, s->HEVClc->cabac_state, HEVC_CONTEXTS);
>> +        memcpy(s->cabac->state, s->HEVClc->cabac_state, HEVC_CONTEXTS);
> 
> So if I'm reading this right, this copies the per-slice-context state
> into the decoder-global state. And it's done from slice threads with no
> locks. So how is this not racy?
> 

a) I am not claiming that this is not racy; I am merely claiming that it
does not introduce a new race, because the parts of the code that access
these Rice parameters are a subset of the parts of code that access the
CABAC parameters and tsan has never shown a race for me when updating
cabac state or the rice parameters in general.

b) (i) I readily admit that HEVC is not my forte*. WPP is supposed to be
as follows: Given that HEVC needs the upper right and upper block/ctu
for prediction, each row can only start decoding after the first two
ctus of the row above it have been decoded. And then the cabac state of
the row below is initialized from the cabac state of the row above after
decoding its first two ctus. Therefore only one cabac state needs to be
cached at any given time.
(ii) You can see this in ff_hevc_save_states, where it is only saving
the state after the second row (this presumes that the initial
ctb_addr_ts in hls_decode_entry_wpp is a multiple of ctb_width which
seems to be the case when tiles are disabled; I don't know what happens
when both tiles and wpp are enabled. According to
https://github.com/ultravideo/kvazaar/issues/201#issuecomment-391329526
this is not even allowed in any currently legal profile, but I don't
think our decoder checks for that).
(iii) After having saved the state, it is signalling that it is done
with this ctu via ff_thread_report_progress2. The next thread waits for
this event via ff_thread_await_progress2 and initializes its cabac state
(if necessary). So there is your synchronization.
(iv) Looking at ff_hevc_cabac_init, one can see that the first branch is
always true when run from the first job; whereas ctb_addr_ts %
s->ps.sps->ctb_width == 0 is true when tiles are disabled and when one
is decoding the first ctu of a row (I don't know what happens in case
tiles are enabled; probably mayhem. It seems kvazaar can produce such
files, see above link.).

c) The current state of affairs is btw weird: Given that the secondary
HEVCContexts are overwritten by the main HEVCContext in
hls_slice_data_wpp, the rice state that every HEVCContext starts with is
given by the state of the first HEVCContext. And which row (of the last
picture) this corresponds to depends upon the number of slice threads in
use. This might cause problems if dependent_slice_segment_flag is enabled.

d) See also the comment to patch #2.

- Andreas

*: I only wanted to share the common SEI parts of H.264 and HEVC due to
softworkz's horrible way of sharing it.
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [FFmpeg-devel] [PATCH 09/18] avcodec/hevcdec: Add stat_coeffs to HEVCABACState
  2022-07-02 10:40     ` Andreas Rheinhardt
@ 2022-07-02 11:31       ` Andreas Rheinhardt
  2022-07-02 11:43         ` Andreas Rheinhardt
  0 siblings, 1 reply; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-07-02 11:31 UTC (permalink / raw)
  To: ffmpeg-devel

Andreas Rheinhardt:
> Anton Khirnov:
> c) The current state of affairs is btw weird: Given that the secondary
> HEVCContexts are overwritten by the main HEVCContext in
> hls_slice_data_wpp, the rice state that every HEVCContext starts with is
> given by the state of the first HEVCContext. And which row (of the last
> picture) this corresponds to depends upon the number of slice threads in
> use. This might cause problems if dependent_slice_segment_flag is enabled.
> 

kvazaar allows to create files with dependent_slice_segment_flag == 1;
but it puts one row into one slice and so the above issue would probably
not manifest itself. The caveat "probably" is necessary, because
decoding such files with slice threading leads to "entry_point_offset
table is corrupted" errors (which is probably a decoder bug).

- Andreas
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [FFmpeg-devel] [PATCH 09/18] avcodec/hevcdec: Add stat_coeffs to HEVCABACState
  2022-07-02 11:31       ` Andreas Rheinhardt
@ 2022-07-02 11:43         ` Andreas Rheinhardt
  0 siblings, 0 replies; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-07-02 11:43 UTC (permalink / raw)
  To: ffmpeg-devel

Andreas Rheinhardt:
> Andreas Rheinhardt:
>> Anton Khirnov:
>> c) The current state of affairs is btw weird: Given that the secondary
>> HEVCContexts are overwritten by the main HEVCContext in
>> hls_slice_data_wpp, the rice state that every HEVCContext starts with is
>> given by the state of the first HEVCContext. And which row (of the last
>> picture) this corresponds to depends upon the number of slice threads in
>> use. This might cause problems if dependent_slice_segment_flag is enabled.
>>
> 
> kvazaar allows to create files with dependent_slice_segment_flag == 1;
> but it puts one row into one slice and so the above issue would probably
> not manifest itself. The caveat "probably" is necessary, because
> decoding such files with slice threading leads to "entry_point_offset
> table is corrupted" errors (which is probably a decoder bug).
> 

The first slice segment header of a picture has entry points for all
rows, even for those that are actually in other slice segments. I don't
know whether this is how it is supposed to be.

- Andreas
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [FFmpeg-devel] [PATCH 14/18] avcodec/hevcdec: Don't allocate redundant HEVCContexts
  2022-07-02  6:32     ` Andreas Rheinhardt
@ 2022-07-05 22:24       ` Michael Niedermayer
  2022-07-06  8:21         ` Andreas Rheinhardt
  0 siblings, 1 reply; 37+ messages in thread
From: Michael Niedermayer @ 2022-07-05 22:24 UTC (permalink / raw)
  To: FFmpeg development discussions and patches


[-- Attachment #1.1: Type: text/plain, Size: 4354 bytes --]

On Sat, Jul 02, 2022 at 08:32:06AM +0200, Andreas Rheinhardt wrote:
> Michael Niedermayer:
> > On Fri, Jul 01, 2022 at 12:29:45AM +0200, Andreas Rheinhardt wrote:
> >> The HEVC decoder has both HEVCContext and HEVCLocalContext
> >> structures. The latter is supposed to be the structure
> >> containing the per-slicethread state.
> >>
> >> Yet up until now that is not how it is handled in practice:
> >> Each HEVCLocalContext has a unique HEVCContext allocated for it
> >> and each of these coincides except in exactly one field: The
> >> corresponding HEVCLocalContext. This makes it possible to pass
> >> the HEVCContext everywhere where logically a HEVCLocalContext
> >> should be used. And up until recently, this is how it has been done.
> >>
> >> Yet the preceding patches changed this, making it possible
> >> to avoid allocating redundant HEVCContexts.
> >>
> >> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
> >> ---
> >>  libavcodec/hevcdec.c | 40 ++++++++++++++++------------------------
> >>  libavcodec/hevcdec.h |  2 --
> >>  2 files changed, 16 insertions(+), 26 deletions(-)
> >>
> >> diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
> >> index 9d1241f293..048fcc76b4 100644
> >> --- a/libavcodec/hevcdec.c
> >> +++ b/libavcodec/hevcdec.c
> >> @@ -2548,13 +2548,12 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
> >>  {
> >>      HEVCLocalContext *lc = ((HEVCLocalContext**)hevc_lclist)[self_id];
> >>      const HEVCContext *const s = lc->parent;
> >> -    HEVCContext *s1  = avctxt->priv_data;
> >> -    int ctb_size    = 1<< s1->ps.sps->log2_ctb_size;
> >> +    int ctb_size    = 1 << s->ps.sps->log2_ctb_size;
> >>      int more_data   = 1;
> >>      int ctb_row = job;
> >> -    int ctb_addr_rs = s1->sh.slice_ctb_addr_rs + ctb_row * ((s1->ps.sps->width + ctb_size - 1) >> s1->ps.sps->log2_ctb_size);
> >> -    int ctb_addr_ts = s1->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
> >> -    int thread = ctb_row % s1->threads_number;
> >> +    int ctb_addr_rs = s->sh.slice_ctb_addr_rs + ctb_row * ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size);
> >> +    int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
> >> +    int thread = ctb_row % s->threads_number;
> >>      int ret;
> >>  
> >>      if(ctb_row) {
> >> @@ -2572,7 +2571,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
> >>  
> >>          ff_thread_await_progress2(s->avctx, ctb_row, thread, SHIFT_CTB_WPP);
> >>  
> >> -        if (atomic_load(&s1->wpp_err)) {
> >> +        if (atomic_load(&s->wpp_err)) {
> >>              ff_thread_report_progress2(s->avctx, ctb_row , thread, SHIFT_CTB_WPP);
> > 
> > the consts in "const HEVCContext *const " make clang version 6.0.0-1ubuntu2 unhappy
> > (this was building shared libs)
> > 
> > 
> > CC	libavcodec/hevcdec.o
> > src/libavcodec/hevcdec.c:2574:13: error: address argument to atomic operation must be a pointer to non-const _Atomic type ('const atomic_int *' (aka 'const _Atomic(int) *') invalid)
> >         if (atomic_load(&s->wpp_err)) {
> >             ^           ~~~~~~~~~~~
> > /usr/lib/llvm-6.0/lib/clang/6.0.0/include/stdatomic.h:134:29: note: expanded from macro 'atomic_load'
> > #define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST)
> >                             ^                 ~~~~~~
> > 1 error generated.
> > src/ffbuild/common.mak:81: recipe for target 'libavcodec/hevcdec.o' failed
> > make: *** [libavcodec/hevcdec.o] Error 1
> > 
> > thx
> > 
> 
> Thanks for testing this. atomic_load is indeed declared without const in
> 7.17.7.2:
> 
> C atomic_load(volatile A *object);
> 
> Upon reflection this makes sense, because if atomics are implemented via
> mutexes, even a read may involve a preceding write. So I'll cast const
> away here, too, and add a comment. (It works when casting const away,
> doesn't it?)

This doesnt feel "right". These pointers should not be coming from a const
if they are written to

The compiler accepts it with an explicit cast though. With an implicit cast
it produces a warning

thx


[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

He who knows, does not speak. He who speaks, does not know. -- Lao Tsu

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

[-- Attachment #2: Type: text/plain, Size: 251 bytes --]

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [FFmpeg-devel] [PATCH 14/18] avcodec/hevcdec: Don't allocate redundant HEVCContexts
  2022-07-05 22:24       ` Michael Niedermayer
@ 2022-07-06  8:21         ` Andreas Rheinhardt
  2022-07-23  5:44           ` Andreas Rheinhardt
  0 siblings, 1 reply; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-07-06  8:21 UTC (permalink / raw)
  To: ffmpeg-devel

Michael Niedermayer:
> On Sat, Jul 02, 2022 at 08:32:06AM +0200, Andreas Rheinhardt wrote:
>> Michael Niedermayer:
>>> On Fri, Jul 01, 2022 at 12:29:45AM +0200, Andreas Rheinhardt wrote:
>>>> The HEVC decoder has both HEVCContext and HEVCLocalContext
>>>> structures. The latter is supposed to be the structure
>>>> containing the per-slicethread state.
>>>>
>>>> Yet up until now that is not how it is handled in practice:
>>>> Each HEVCLocalContext has a unique HEVCContext allocated for it
>>>> and each of these coincides except in exactly one field: The
>>>> corresponding HEVCLocalContext. This makes it possible to pass
>>>> the HEVCContext everywhere where logically a HEVCLocalContext
>>>> should be used. And up until recently, this is how it has been done.
>>>>
>>>> Yet the preceding patches changed this, making it possible
>>>> to avoid allocating redundant HEVCContexts.
>>>>
>>>> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
>>>> ---
>>>>  libavcodec/hevcdec.c | 40 ++++++++++++++++------------------------
>>>>  libavcodec/hevcdec.h |  2 --
>>>>  2 files changed, 16 insertions(+), 26 deletions(-)
>>>>
>>>> diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
>>>> index 9d1241f293..048fcc76b4 100644
>>>> --- a/libavcodec/hevcdec.c
>>>> +++ b/libavcodec/hevcdec.c
>>>> @@ -2548,13 +2548,12 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
>>>>  {
>>>>      HEVCLocalContext *lc = ((HEVCLocalContext**)hevc_lclist)[self_id];
>>>>      const HEVCContext *const s = lc->parent;
>>>> -    HEVCContext *s1  = avctxt->priv_data;
>>>> -    int ctb_size    = 1<< s1->ps.sps->log2_ctb_size;
>>>> +    int ctb_size    = 1 << s->ps.sps->log2_ctb_size;
>>>>      int more_data   = 1;
>>>>      int ctb_row = job;
>>>> -    int ctb_addr_rs = s1->sh.slice_ctb_addr_rs + ctb_row * ((s1->ps.sps->width + ctb_size - 1) >> s1->ps.sps->log2_ctb_size);
>>>> -    int ctb_addr_ts = s1->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
>>>> -    int thread = ctb_row % s1->threads_number;
>>>> +    int ctb_addr_rs = s->sh.slice_ctb_addr_rs + ctb_row * ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size);
>>>> +    int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
>>>> +    int thread = ctb_row % s->threads_number;
>>>>      int ret;
>>>>  
>>>>      if(ctb_row) {
>>>> @@ -2572,7 +2571,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
>>>>  
>>>>          ff_thread_await_progress2(s->avctx, ctb_row, thread, SHIFT_CTB_WPP);
>>>>  
>>>> -        if (atomic_load(&s1->wpp_err)) {
>>>> +        if (atomic_load(&s->wpp_err)) {
>>>>              ff_thread_report_progress2(s->avctx, ctb_row , thread, SHIFT_CTB_WPP);
>>>
>>> the consts in "const HEVCContext *const " make clang version 6.0.0-1ubuntu2 unhappy
>>> (this was building shared libs)
>>>
>>>
>>> CC	libavcodec/hevcdec.o
>>> src/libavcodec/hevcdec.c:2574:13: error: address argument to atomic operation must be a pointer to non-const _Atomic type ('const atomic_int *' (aka 'const _Atomic(int) *') invalid)
>>>         if (atomic_load(&s->wpp_err)) {
>>>             ^           ~~~~~~~~~~~
>>> /usr/lib/llvm-6.0/lib/clang/6.0.0/include/stdatomic.h:134:29: note: expanded from macro 'atomic_load'
>>> #define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST)
>>>                             ^                 ~~~~~~
>>> 1 error generated.
>>> src/ffbuild/common.mak:81: recipe for target 'libavcodec/hevcdec.o' failed
>>> make: *** [libavcodec/hevcdec.o] Error 1
>>>
>>> thx
>>>
>>
>> Thanks for testing this. atomic_load is indeed declared without const in
>> 7.17.7.2:
>>
>> C atomic_load(volatile A *object);
>>
>> Upon reflection this makes sense, because if atomics are implemented via
>> mutexes, even a read may involve a preceding write. So I'll cast const
>> away here, too, and add a comment. (It works when casting const away,
>> doesn't it?)
> 
> This doesnt feel "right". These pointers should not be coming from a const
> if they are written to
> 

The HEVCContext is not const because the underlying object is const; the
HEVCContext is const when accessed from any part of the code that may be
run from slice threads, because if a slice thread modifies it, you have
a data race in case any of the other slice threads reads this field or
modifies it itself. But this is by definition not true for atomic
operations, so casting const away for them is fine.

> The compiler accepts it with an explicit cast though. With an implicit cast
> it produces a warning
> 
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [FFmpeg-devel] [PATCH 17/18] avcodec/pthread_slice: Reuse buffer if possible
  2022-07-01 13:21   ` Tomas Härdin
@ 2022-07-22 20:04     ` Andreas Rheinhardt
  0 siblings, 0 replies; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-07-22 20:04 UTC (permalink / raw)
  To: FFmpeg development discussions and patches, Tomas Härdin

Tomas Härdin:
> fre 2022-07-01 klockan 00:29 +0200 skrev Andreas Rheinhardt:
>> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
>> ---
>>  libavcodec/pthread_slice.c | 6 ++++--
>>  1 file changed, 4 insertions(+), 2 deletions(-)
>>
>> diff --git a/libavcodec/pthread_slice.c b/libavcodec/pthread_slice.c
>> index 756cc59dbf..a4d31c6f4d 100644
>> --- a/libavcodec/pthread_slice.c
>> +++ b/libavcodec/pthread_slice.c
>> @@ -242,9 +242,11 @@ int
>> ff_slice_thread_allocz_entries(AVCodecContext *avctx, int count)
>>      if (avctx->active_thread_type & FF_THREAD_SLICE)  {
>>          SliceThreadContext *p = avctx->internal->thread_ctx;
>>  
>> -        if (p->entries) {
>> -            av_freep(&p->entries);
>> +        if (p->entries_count == count) {
>> +            memset(p->entries, 0, p->entries_count * sizeof(*p-
>>> entries));
>> +            return 0;
> 
> Couldn't this trivially handle p->entries_count < count also?
> 

Yes, but then this would basically be yet another never-shrinking
buffer. And with every such never-shrinking buffer I fear that we might
allocate too much forever (e.g. because of a single invalid packet).

>>          }
>> +        av_freep(&p->entries);
>>  
>>          p->entries       = av_calloc(count, sizeof(*p->entries));
>>          if (!p->entries) {
> 
> Looks like we could use an av_fast_calloc()
> 
> /Tomas
> 

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [FFmpeg-devel] [PATCH 14/18] avcodec/hevcdec: Don't allocate redundant HEVCContexts
  2022-07-06  8:21         ` Andreas Rheinhardt
@ 2022-07-23  5:44           ` Andreas Rheinhardt
  2022-07-23 14:38             ` Michael Niedermayer
  0 siblings, 1 reply; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-07-23  5:44 UTC (permalink / raw)
  To: ffmpeg-devel

Andreas Rheinhardt:
> Michael Niedermayer:
>> On Sat, Jul 02, 2022 at 08:32:06AM +0200, Andreas Rheinhardt wrote:
>>> Michael Niedermayer:
>>>> On Fri, Jul 01, 2022 at 12:29:45AM +0200, Andreas Rheinhardt wrote:
>>>>> The HEVC decoder has both HEVCContext and HEVCLocalContext
>>>>> structures. The latter is supposed to be the structure
>>>>> containing the per-slicethread state.
>>>>>
>>>>> Yet up until now that is not how it is handled in practice:
>>>>> Each HEVCLocalContext has a unique HEVCContext allocated for it
>>>>> and each of these coincides except in exactly one field: The
>>>>> corresponding HEVCLocalContext. This makes it possible to pass
>>>>> the HEVCContext everywhere where logically a HEVCLocalContext
>>>>> should be used. And up until recently, this is how it has been done.
>>>>>
>>>>> Yet the preceding patches changed this, making it possible
>>>>> to avoid allocating redundant HEVCContexts.
>>>>>
>>>>> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
>>>>> ---
>>>>>  libavcodec/hevcdec.c | 40 ++++++++++++++++------------------------
>>>>>  libavcodec/hevcdec.h |  2 --
>>>>>  2 files changed, 16 insertions(+), 26 deletions(-)
>>>>>
>>>>> diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
>>>>> index 9d1241f293..048fcc76b4 100644
>>>>> --- a/libavcodec/hevcdec.c
>>>>> +++ b/libavcodec/hevcdec.c
>>>>> @@ -2548,13 +2548,12 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
>>>>>  {
>>>>>      HEVCLocalContext *lc = ((HEVCLocalContext**)hevc_lclist)[self_id];
>>>>>      const HEVCContext *const s = lc->parent;
>>>>> -    HEVCContext *s1  = avctxt->priv_data;
>>>>> -    int ctb_size    = 1<< s1->ps.sps->log2_ctb_size;
>>>>> +    int ctb_size    = 1 << s->ps.sps->log2_ctb_size;
>>>>>      int more_data   = 1;
>>>>>      int ctb_row = job;
>>>>> -    int ctb_addr_rs = s1->sh.slice_ctb_addr_rs + ctb_row * ((s1->ps.sps->width + ctb_size - 1) >> s1->ps.sps->log2_ctb_size);
>>>>> -    int ctb_addr_ts = s1->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
>>>>> -    int thread = ctb_row % s1->threads_number;
>>>>> +    int ctb_addr_rs = s->sh.slice_ctb_addr_rs + ctb_row * ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size);
>>>>> +    int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
>>>>> +    int thread = ctb_row % s->threads_number;
>>>>>      int ret;
>>>>>  
>>>>>      if(ctb_row) {
>>>>> @@ -2572,7 +2571,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
>>>>>  
>>>>>          ff_thread_await_progress2(s->avctx, ctb_row, thread, SHIFT_CTB_WPP);
>>>>>  
>>>>> -        if (atomic_load(&s1->wpp_err)) {
>>>>> +        if (atomic_load(&s->wpp_err)) {
>>>>>              ff_thread_report_progress2(s->avctx, ctb_row , thread, SHIFT_CTB_WPP);
>>>>
>>>> the consts in "const HEVCContext *const " make clang version 6.0.0-1ubuntu2 unhappy
>>>> (this was building shared libs)
>>>>
>>>>
>>>> CC	libavcodec/hevcdec.o
>>>> src/libavcodec/hevcdec.c:2574:13: error: address argument to atomic operation must be a pointer to non-const _Atomic type ('const atomic_int *' (aka 'const _Atomic(int) *') invalid)
>>>>         if (atomic_load(&s->wpp_err)) {
>>>>             ^           ~~~~~~~~~~~
>>>> /usr/lib/llvm-6.0/lib/clang/6.0.0/include/stdatomic.h:134:29: note: expanded from macro 'atomic_load'
>>>> #define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST)
>>>>                             ^                 ~~~~~~
>>>> 1 error generated.
>>>> src/ffbuild/common.mak:81: recipe for target 'libavcodec/hevcdec.o' failed
>>>> make: *** [libavcodec/hevcdec.o] Error 1
>>>>
>>>> thx
>>>>
>>>
>>> Thanks for testing this. atomic_load is indeed declared without const in
>>> 7.17.7.2:
>>>
>>> C atomic_load(volatile A *object);
>>>
>>> Upon reflection this makes sense, because if atomics are implemented via
>>> mutexes, even a read may involve a preceding write. So I'll cast const
>>> away here, too, and add a comment. (It works when casting const away,
>>> doesn't it?)
>>
>> This doesnt feel "right". These pointers should not be coming from a const
>> if they are written to
>>
> 
> The HEVCContext is not const because the underlying object is const; the
> HEVCContext is const when accessed from any part of the code that may be
> run from slice threads, because if a slice thread modifies it, you have
> a data race in case any of the other slice threads reads this field or
> modifies it itself. But this is by definition not true for atomic
> operations, so casting const away for them is fine.
> 
>> The compiler accepts it with an explicit cast though. With an implicit cast
>> it produces a warning
>>

Did the above explanation satisfy you? Or do you want something else?

- Andreas
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [FFmpeg-devel] [PATCH 14/18] avcodec/hevcdec: Don't allocate redundant HEVCContexts
  2022-07-23  5:44           ` Andreas Rheinhardt
@ 2022-07-23 14:38             ` Michael Niedermayer
  2022-07-23 21:42               ` Andreas Rheinhardt
  0 siblings, 1 reply; 37+ messages in thread
From: Michael Niedermayer @ 2022-07-23 14:38 UTC (permalink / raw)
  To: FFmpeg development discussions and patches


[-- Attachment #1.1: Type: text/plain, Size: 5319 bytes --]

On Sat, Jul 23, 2022 at 07:44:40AM +0200, Andreas Rheinhardt wrote:
> Andreas Rheinhardt:
> > Michael Niedermayer:
> >> On Sat, Jul 02, 2022 at 08:32:06AM +0200, Andreas Rheinhardt wrote:
> >>> Michael Niedermayer:
> >>>> On Fri, Jul 01, 2022 at 12:29:45AM +0200, Andreas Rheinhardt wrote:
> >>>>> The HEVC decoder has both HEVCContext and HEVCLocalContext
> >>>>> structures. The latter is supposed to be the structure
> >>>>> containing the per-slicethread state.
> >>>>>
> >>>>> Yet up until now that is not how it is handled in practice:
> >>>>> Each HEVCLocalContext has a unique HEVCContext allocated for it
> >>>>> and each of these coincides except in exactly one field: The
> >>>>> corresponding HEVCLocalContext. This makes it possible to pass
> >>>>> the HEVCContext everywhere where logically a HEVCLocalContext
> >>>>> should be used. And up until recently, this is how it has been done.
> >>>>>
> >>>>> Yet the preceding patches changed this, making it possible
> >>>>> to avoid allocating redundant HEVCContexts.
> >>>>>
> >>>>> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
> >>>>> ---
> >>>>>  libavcodec/hevcdec.c | 40 ++++++++++++++++------------------------
> >>>>>  libavcodec/hevcdec.h |  2 --
> >>>>>  2 files changed, 16 insertions(+), 26 deletions(-)
> >>>>>
> >>>>> diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
> >>>>> index 9d1241f293..048fcc76b4 100644
> >>>>> --- a/libavcodec/hevcdec.c
> >>>>> +++ b/libavcodec/hevcdec.c
> >>>>> @@ -2548,13 +2548,12 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
> >>>>>  {
> >>>>>      HEVCLocalContext *lc = ((HEVCLocalContext**)hevc_lclist)[self_id];
> >>>>>      const HEVCContext *const s = lc->parent;
> >>>>> -    HEVCContext *s1  = avctxt->priv_data;
> >>>>> -    int ctb_size    = 1<< s1->ps.sps->log2_ctb_size;
> >>>>> +    int ctb_size    = 1 << s->ps.sps->log2_ctb_size;
> >>>>>      int more_data   = 1;
> >>>>>      int ctb_row = job;
> >>>>> -    int ctb_addr_rs = s1->sh.slice_ctb_addr_rs + ctb_row * ((s1->ps.sps->width + ctb_size - 1) >> s1->ps.sps->log2_ctb_size);
> >>>>> -    int ctb_addr_ts = s1->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
> >>>>> -    int thread = ctb_row % s1->threads_number;
> >>>>> +    int ctb_addr_rs = s->sh.slice_ctb_addr_rs + ctb_row * ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size);
> >>>>> +    int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
> >>>>> +    int thread = ctb_row % s->threads_number;
> >>>>>      int ret;
> >>>>>  
> >>>>>      if(ctb_row) {
> >>>>> @@ -2572,7 +2571,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
> >>>>>  
> >>>>>          ff_thread_await_progress2(s->avctx, ctb_row, thread, SHIFT_CTB_WPP);
> >>>>>  
> >>>>> -        if (atomic_load(&s1->wpp_err)) {
> >>>>> +        if (atomic_load(&s->wpp_err)) {
> >>>>>              ff_thread_report_progress2(s->avctx, ctb_row , thread, SHIFT_CTB_WPP);
> >>>>
> >>>> the consts in "const HEVCContext *const " make clang version 6.0.0-1ubuntu2 unhappy
> >>>> (this was building shared libs)
> >>>>
> >>>>
> >>>> CC	libavcodec/hevcdec.o
> >>>> src/libavcodec/hevcdec.c:2574:13: error: address argument to atomic operation must be a pointer to non-const _Atomic type ('const atomic_int *' (aka 'const _Atomic(int) *') invalid)
> >>>>         if (atomic_load(&s->wpp_err)) {
> >>>>             ^           ~~~~~~~~~~~
> >>>> /usr/lib/llvm-6.0/lib/clang/6.0.0/include/stdatomic.h:134:29: note: expanded from macro 'atomic_load'
> >>>> #define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST)
> >>>>                             ^                 ~~~~~~
> >>>> 1 error generated.
> >>>> src/ffbuild/common.mak:81: recipe for target 'libavcodec/hevcdec.o' failed
> >>>> make: *** [libavcodec/hevcdec.o] Error 1
> >>>>
> >>>> thx
> >>>>
> >>>
> >>> Thanks for testing this. atomic_load is indeed declared without const in
> >>> 7.17.7.2:
> >>>
> >>> C atomic_load(volatile A *object);
> >>>
> >>> Upon reflection this makes sense, because if atomics are implemented via
> >>> mutexes, even a read may involve a preceding write. So I'll cast const
> >>> away here, too, and add a comment. (It works when casting const away,
> >>> doesn't it?)
> >>
> >> This doesnt feel "right". These pointers should not be coming from a const
> >> if they are written to
> >>
> > 
> > The HEVCContext is not const because the underlying object is const; the
> > HEVCContext is const when accessed from any part of the code that may be
> > run from slice threads, because if a slice thread modifies it, you have
> > a data race in case any of the other slice threads reads this field or
> > modifies it itself. But this is by definition not true for atomic
> > operations, so casting const away for them is fine.
> > 
> >> The compiler accepts it with an explicit cast though. With an implicit cast
> >> it produces a warning
> >>
> 
> Did the above explanation satisfy you? Or do you want something else?

sure, ok

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

If you think the mosad wants you dead since a long time then you are either
wrong or dead since a long time.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

[-- Attachment #2: Type: text/plain, Size: 251 bytes --]

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [FFmpeg-devel] [PATCH 14/18] avcodec/hevcdec: Don't allocate redundant HEVCContexts
  2022-07-23 14:38             ` Michael Niedermayer
@ 2022-07-23 21:42               ` Andreas Rheinhardt
  2022-07-24 21:23                 ` Michael Niedermayer
  0 siblings, 1 reply; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-07-23 21:42 UTC (permalink / raw)
  To: ffmpeg-devel

Michael Niedermayer:
> On Sat, Jul 23, 2022 at 07:44:40AM +0200, Andreas Rheinhardt wrote:
>> Andreas Rheinhardt:
>>> Michael Niedermayer:
>>>> On Sat, Jul 02, 2022 at 08:32:06AM +0200, Andreas Rheinhardt wrote:
>>>>> Michael Niedermayer:
>>>>>> On Fri, Jul 01, 2022 at 12:29:45AM +0200, Andreas Rheinhardt wrote:
>>>>>>> The HEVC decoder has both HEVCContext and HEVCLocalContext
>>>>>>> structures. The latter is supposed to be the structure
>>>>>>> containing the per-slicethread state.
>>>>>>>
>>>>>>> Yet up until now that is not how it is handled in practice:
>>>>>>> Each HEVCLocalContext has a unique HEVCContext allocated for it
>>>>>>> and each of these coincides except in exactly one field: The
>>>>>>> corresponding HEVCLocalContext. This makes it possible to pass
>>>>>>> the HEVCContext everywhere where logically a HEVCLocalContext
>>>>>>> should be used. And up until recently, this is how it has been done.
>>>>>>>
>>>>>>> Yet the preceding patches changed this, making it possible
>>>>>>> to avoid allocating redundant HEVCContexts.
>>>>>>>
>>>>>>> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
>>>>>>> ---
>>>>>>>  libavcodec/hevcdec.c | 40 ++++++++++++++++------------------------
>>>>>>>  libavcodec/hevcdec.h |  2 --
>>>>>>>  2 files changed, 16 insertions(+), 26 deletions(-)
>>>>>>>
>>>>>>> diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
>>>>>>> index 9d1241f293..048fcc76b4 100644
>>>>>>> --- a/libavcodec/hevcdec.c
>>>>>>> +++ b/libavcodec/hevcdec.c
>>>>>>> @@ -2548,13 +2548,12 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
>>>>>>>  {
>>>>>>>      HEVCLocalContext *lc = ((HEVCLocalContext**)hevc_lclist)[self_id];
>>>>>>>      const HEVCContext *const s = lc->parent;
>>>>>>> -    HEVCContext *s1  = avctxt->priv_data;
>>>>>>> -    int ctb_size    = 1<< s1->ps.sps->log2_ctb_size;
>>>>>>> +    int ctb_size    = 1 << s->ps.sps->log2_ctb_size;
>>>>>>>      int more_data   = 1;
>>>>>>>      int ctb_row = job;
>>>>>>> -    int ctb_addr_rs = s1->sh.slice_ctb_addr_rs + ctb_row * ((s1->ps.sps->width + ctb_size - 1) >> s1->ps.sps->log2_ctb_size);
>>>>>>> -    int ctb_addr_ts = s1->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
>>>>>>> -    int thread = ctb_row % s1->threads_number;
>>>>>>> +    int ctb_addr_rs = s->sh.slice_ctb_addr_rs + ctb_row * ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size);
>>>>>>> +    int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
>>>>>>> +    int thread = ctb_row % s->threads_number;
>>>>>>>      int ret;
>>>>>>>  
>>>>>>>      if(ctb_row) {
>>>>>>> @@ -2572,7 +2571,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
>>>>>>>  
>>>>>>>          ff_thread_await_progress2(s->avctx, ctb_row, thread, SHIFT_CTB_WPP);
>>>>>>>  
>>>>>>> -        if (atomic_load(&s1->wpp_err)) {
>>>>>>> +        if (atomic_load(&s->wpp_err)) {
>>>>>>>              ff_thread_report_progress2(s->avctx, ctb_row , thread, SHIFT_CTB_WPP);
>>>>>>
>>>>>> the consts in "const HEVCContext *const " make clang version 6.0.0-1ubuntu2 unhappy
>>>>>> (this was building shared libs)
>>>>>>
>>>>>>
>>>>>> CC	libavcodec/hevcdec.o
>>>>>> src/libavcodec/hevcdec.c:2574:13: error: address argument to atomic operation must be a pointer to non-const _Atomic type ('const atomic_int *' (aka 'const _Atomic(int) *') invalid)
>>>>>>         if (atomic_load(&s->wpp_err)) {
>>>>>>             ^           ~~~~~~~~~~~
>>>>>> /usr/lib/llvm-6.0/lib/clang/6.0.0/include/stdatomic.h:134:29: note: expanded from macro 'atomic_load'
>>>>>> #define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST)
>>>>>>                             ^                 ~~~~~~
>>>>>> 1 error generated.
>>>>>> src/ffbuild/common.mak:81: recipe for target 'libavcodec/hevcdec.o' failed
>>>>>> make: *** [libavcodec/hevcdec.o] Error 1
>>>>>>
>>>>>> thx
>>>>>>
>>>>>
>>>>> Thanks for testing this. atomic_load is indeed declared without const in
>>>>> 7.17.7.2:
>>>>>
>>>>> C atomic_load(volatile A *object);
>>>>>
>>>>> Upon reflection this makes sense, because if atomics are implemented via
>>>>> mutexes, even a read may involve a preceding write. So I'll cast const
>>>>> away here, too, and add a comment. (It works when casting const away,
>>>>> doesn't it?)
>>>>
>>>> This doesnt feel "right". These pointers should not be coming from a const
>>>> if they are written to
>>>>
>>>
>>> The HEVCContext is not const because the underlying object is const; the
>>> HEVCContext is const when accessed from any part of the code that may be
>>> run from slice threads, because if a slice thread modifies it, you have
>>> a data race in case any of the other slice threads reads this field or
>>> modifies it itself. But this is by definition not true for atomic
>>> operations, so casting const away for them is fine.
>>>
>>>> The compiler accepts it with an explicit cast though. With an implicit cast
>>>> it produces a warning
>>>>
>>
>> Did the above explanation satisfy you? Or do you want something else?
> 
> sure, ok
> 
> [...]
> 

Good to hear. This patchset (namely patch 11/18: "avcodec/hevcpred: Pass
HEVCLocalContext when slice-threading") includes modifications to mips
code that I created blindly. Can you please test it? Here is a branch of
this rebased on top of current git master:
https://github.com/mkver/FFmpeg/commits/hevc_wpp
(Said branch actually contains a bit of further work which also modifies
mips code (in particular,
https://github.com/mkver/FFmpeg/commit/cf441e559b8d4bf2c05c29483ccf49e82fc6b863
does so); you may also test this.)

- Andreas
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [FFmpeg-devel] [PATCH 14/18] avcodec/hevcdec: Don't allocate redundant HEVCContexts
  2022-07-23 21:42               ` Andreas Rheinhardt
@ 2022-07-24 21:23                 ` Michael Niedermayer
  2022-07-24 21:26                   ` Andreas Rheinhardt
  0 siblings, 1 reply; 37+ messages in thread
From: Michael Niedermayer @ 2022-07-24 21:23 UTC (permalink / raw)
  To: FFmpeg development discussions and patches


[-- Attachment #1.1: Type: text/plain, Size: 6453 bytes --]

On Sat, Jul 23, 2022 at 11:42:23PM +0200, Andreas Rheinhardt wrote:
> Michael Niedermayer:
> > On Sat, Jul 23, 2022 at 07:44:40AM +0200, Andreas Rheinhardt wrote:
> >> Andreas Rheinhardt:
> >>> Michael Niedermayer:
> >>>> On Sat, Jul 02, 2022 at 08:32:06AM +0200, Andreas Rheinhardt wrote:
> >>>>> Michael Niedermayer:
> >>>>>> On Fri, Jul 01, 2022 at 12:29:45AM +0200, Andreas Rheinhardt wrote:
> >>>>>>> The HEVC decoder has both HEVCContext and HEVCLocalContext
> >>>>>>> structures. The latter is supposed to be the structure
> >>>>>>> containing the per-slicethread state.
> >>>>>>>
> >>>>>>> Yet up until now that is not how it is handled in practice:
> >>>>>>> Each HEVCLocalContext has a unique HEVCContext allocated for it
> >>>>>>> and each of these coincides except in exactly one field: The
> >>>>>>> corresponding HEVCLocalContext. This makes it possible to pass
> >>>>>>> the HEVCContext everywhere where logically a HEVCLocalContext
> >>>>>>> should be used. And up until recently, this is how it has been done.
> >>>>>>>
> >>>>>>> Yet the preceding patches changed this, making it possible
> >>>>>>> to avoid allocating redundant HEVCContexts.
> >>>>>>>
> >>>>>>> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
> >>>>>>> ---
> >>>>>>>  libavcodec/hevcdec.c | 40 ++++++++++++++++------------------------
> >>>>>>>  libavcodec/hevcdec.h |  2 --
> >>>>>>>  2 files changed, 16 insertions(+), 26 deletions(-)
> >>>>>>>
> >>>>>>> diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
> >>>>>>> index 9d1241f293..048fcc76b4 100644
> >>>>>>> --- a/libavcodec/hevcdec.c
> >>>>>>> +++ b/libavcodec/hevcdec.c
> >>>>>>> @@ -2548,13 +2548,12 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
> >>>>>>>  {
> >>>>>>>      HEVCLocalContext *lc = ((HEVCLocalContext**)hevc_lclist)[self_id];
> >>>>>>>      const HEVCContext *const s = lc->parent;
> >>>>>>> -    HEVCContext *s1  = avctxt->priv_data;
> >>>>>>> -    int ctb_size    = 1<< s1->ps.sps->log2_ctb_size;
> >>>>>>> +    int ctb_size    = 1 << s->ps.sps->log2_ctb_size;
> >>>>>>>      int more_data   = 1;
> >>>>>>>      int ctb_row = job;
> >>>>>>> -    int ctb_addr_rs = s1->sh.slice_ctb_addr_rs + ctb_row * ((s1->ps.sps->width + ctb_size - 1) >> s1->ps.sps->log2_ctb_size);
> >>>>>>> -    int ctb_addr_ts = s1->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
> >>>>>>> -    int thread = ctb_row % s1->threads_number;
> >>>>>>> +    int ctb_addr_rs = s->sh.slice_ctb_addr_rs + ctb_row * ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size);
> >>>>>>> +    int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
> >>>>>>> +    int thread = ctb_row % s->threads_number;
> >>>>>>>      int ret;
> >>>>>>>  
> >>>>>>>      if(ctb_row) {
> >>>>>>> @@ -2572,7 +2571,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
> >>>>>>>  
> >>>>>>>          ff_thread_await_progress2(s->avctx, ctb_row, thread, SHIFT_CTB_WPP);
> >>>>>>>  
> >>>>>>> -        if (atomic_load(&s1->wpp_err)) {
> >>>>>>> +        if (atomic_load(&s->wpp_err)) {
> >>>>>>>              ff_thread_report_progress2(s->avctx, ctb_row , thread, SHIFT_CTB_WPP);
> >>>>>>
> >>>>>> the consts in "const HEVCContext *const " make clang version 6.0.0-1ubuntu2 unhappy
> >>>>>> (this was building shared libs)
> >>>>>>
> >>>>>>
> >>>>>> CC	libavcodec/hevcdec.o
> >>>>>> src/libavcodec/hevcdec.c:2574:13: error: address argument to atomic operation must be a pointer to non-const _Atomic type ('const atomic_int *' (aka 'const _Atomic(int) *') invalid)
> >>>>>>         if (atomic_load(&s->wpp_err)) {
> >>>>>>             ^           ~~~~~~~~~~~
> >>>>>> /usr/lib/llvm-6.0/lib/clang/6.0.0/include/stdatomic.h:134:29: note: expanded from macro 'atomic_load'
> >>>>>> #define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST)
> >>>>>>                             ^                 ~~~~~~
> >>>>>> 1 error generated.
> >>>>>> src/ffbuild/common.mak:81: recipe for target 'libavcodec/hevcdec.o' failed
> >>>>>> make: *** [libavcodec/hevcdec.o] Error 1
> >>>>>>
> >>>>>> thx
> >>>>>>
> >>>>>
> >>>>> Thanks for testing this. atomic_load is indeed declared without const in
> >>>>> 7.17.7.2:
> >>>>>
> >>>>> C atomic_load(volatile A *object);
> >>>>>
> >>>>> Upon reflection this makes sense, because if atomics are implemented via
> >>>>> mutexes, even a read may involve a preceding write. So I'll cast const
> >>>>> away here, too, and add a comment. (It works when casting const away,
> >>>>> doesn't it?)
> >>>>
> >>>> This doesnt feel "right". These pointers should not be coming from a const
> >>>> if they are written to
> >>>>
> >>>
> >>> The HEVCContext is not const because the underlying object is const; the
> >>> HEVCContext is const when accessed from any part of the code that may be
> >>> run from slice threads, because if a slice thread modifies it, you have
> >>> a data race in case any of the other slice threads reads this field or
> >>> modifies it itself. But this is by definition not true for atomic
> >>> operations, so casting const away for them is fine.
> >>>
> >>>> The compiler accepts it with an explicit cast though. With an implicit cast
> >>>> it produces a warning
> >>>>
> >>
> >> Did the above explanation satisfy you? Or do you want something else?
> > 
> > sure, ok
> > 
> > [...]
> > 
> 
> Good to hear. This patchset (namely patch 11/18: "avcodec/hevcpred: Pass
> HEVCLocalContext when slice-threading") includes modifications to mips
> code that I created blindly. Can you please test it? Here is a branch of
> this rebased on top of current git master:
> https://github.com/mkver/FFmpeg/commits/hevc_wpp
> (Said branch actually contains a bit of further work which also modifies
> mips code (in particular,
> https://github.com/mkver/FFmpeg/commit/cf441e559b8d4bf2c05c29483ccf49e82fc6b863
> does so); you may also test this.)

what exact tests do we need ?
simple fate ? any specific thread type count ?
also note i can only test qemu mips not real hw.
I stopped maintaining the MIPS hw and sofar noone volunteered to take its 
maintaince over

thx

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

The smallest minority on earth is the individual. Those who deny 
individual rights cannot claim to be defenders of minorities. - Ayn Rand

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

[-- Attachment #2: Type: text/plain, Size: 251 bytes --]

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [FFmpeg-devel] [PATCH 14/18] avcodec/hevcdec: Don't allocate redundant HEVCContexts
  2022-07-24 21:23                 ` Michael Niedermayer
@ 2022-07-24 21:26                   ` Andreas Rheinhardt
  2022-07-25 19:44                     ` Michael Niedermayer
  0 siblings, 1 reply; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-07-24 21:26 UTC (permalink / raw)
  To: ffmpeg-devel

Michael Niedermayer:
> On Sat, Jul 23, 2022 at 11:42:23PM +0200, Andreas Rheinhardt wrote:
>> Michael Niedermayer:
>>> On Sat, Jul 23, 2022 at 07:44:40AM +0200, Andreas Rheinhardt wrote:
>>>> Andreas Rheinhardt:
>>>>> Michael Niedermayer:
>>>>>> On Sat, Jul 02, 2022 at 08:32:06AM +0200, Andreas Rheinhardt wrote:
>>>>>>> Michael Niedermayer:
>>>>>>>> On Fri, Jul 01, 2022 at 12:29:45AM +0200, Andreas Rheinhardt wrote:
>>>>>>>>> The HEVC decoder has both HEVCContext and HEVCLocalContext
>>>>>>>>> structures. The latter is supposed to be the structure
>>>>>>>>> containing the per-slicethread state.
>>>>>>>>>
>>>>>>>>> Yet up until now that is not how it is handled in practice:
>>>>>>>>> Each HEVCLocalContext has a unique HEVCContext allocated for it
>>>>>>>>> and each of these coincides except in exactly one field: The
>>>>>>>>> corresponding HEVCLocalContext. This makes it possible to pass
>>>>>>>>> the HEVCContext everywhere where logically a HEVCLocalContext
>>>>>>>>> should be used. And up until recently, this is how it has been done.
>>>>>>>>>
>>>>>>>>> Yet the preceding patches changed this, making it possible
>>>>>>>>> to avoid allocating redundant HEVCContexts.
>>>>>>>>>
>>>>>>>>> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
>>>>>>>>> ---
>>>>>>>>>  libavcodec/hevcdec.c | 40 ++++++++++++++++------------------------
>>>>>>>>>  libavcodec/hevcdec.h |  2 --
>>>>>>>>>  2 files changed, 16 insertions(+), 26 deletions(-)
>>>>>>>>>
>>>>>>>>> diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
>>>>>>>>> index 9d1241f293..048fcc76b4 100644
>>>>>>>>> --- a/libavcodec/hevcdec.c
>>>>>>>>> +++ b/libavcodec/hevcdec.c
>>>>>>>>> @@ -2548,13 +2548,12 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
>>>>>>>>>  {
>>>>>>>>>      HEVCLocalContext *lc = ((HEVCLocalContext**)hevc_lclist)[self_id];
>>>>>>>>>      const HEVCContext *const s = lc->parent;
>>>>>>>>> -    HEVCContext *s1  = avctxt->priv_data;
>>>>>>>>> -    int ctb_size    = 1<< s1->ps.sps->log2_ctb_size;
>>>>>>>>> +    int ctb_size    = 1 << s->ps.sps->log2_ctb_size;
>>>>>>>>>      int more_data   = 1;
>>>>>>>>>      int ctb_row = job;
>>>>>>>>> -    int ctb_addr_rs = s1->sh.slice_ctb_addr_rs + ctb_row * ((s1->ps.sps->width + ctb_size - 1) >> s1->ps.sps->log2_ctb_size);
>>>>>>>>> -    int ctb_addr_ts = s1->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
>>>>>>>>> -    int thread = ctb_row % s1->threads_number;
>>>>>>>>> +    int ctb_addr_rs = s->sh.slice_ctb_addr_rs + ctb_row * ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size);
>>>>>>>>> +    int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
>>>>>>>>> +    int thread = ctb_row % s->threads_number;
>>>>>>>>>      int ret;
>>>>>>>>>  
>>>>>>>>>      if(ctb_row) {
>>>>>>>>> @@ -2572,7 +2571,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
>>>>>>>>>  
>>>>>>>>>          ff_thread_await_progress2(s->avctx, ctb_row, thread, SHIFT_CTB_WPP);
>>>>>>>>>  
>>>>>>>>> -        if (atomic_load(&s1->wpp_err)) {
>>>>>>>>> +        if (atomic_load(&s->wpp_err)) {
>>>>>>>>>              ff_thread_report_progress2(s->avctx, ctb_row , thread, SHIFT_CTB_WPP);
>>>>>>>>
>>>>>>>> the consts in "const HEVCContext *const " make clang version 6.0.0-1ubuntu2 unhappy
>>>>>>>> (this was building shared libs)
>>>>>>>>
>>>>>>>>
>>>>>>>> CC	libavcodec/hevcdec.o
>>>>>>>> src/libavcodec/hevcdec.c:2574:13: error: address argument to atomic operation must be a pointer to non-const _Atomic type ('const atomic_int *' (aka 'const _Atomic(int) *') invalid)
>>>>>>>>         if (atomic_load(&s->wpp_err)) {
>>>>>>>>             ^           ~~~~~~~~~~~
>>>>>>>> /usr/lib/llvm-6.0/lib/clang/6.0.0/include/stdatomic.h:134:29: note: expanded from macro 'atomic_load'
>>>>>>>> #define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST)
>>>>>>>>                             ^                 ~~~~~~
>>>>>>>> 1 error generated.
>>>>>>>> src/ffbuild/common.mak:81: recipe for target 'libavcodec/hevcdec.o' failed
>>>>>>>> make: *** [libavcodec/hevcdec.o] Error 1
>>>>>>>>
>>>>>>>> thx
>>>>>>>>
>>>>>>>
>>>>>>> Thanks for testing this. atomic_load is indeed declared without const in
>>>>>>> 7.17.7.2:
>>>>>>>
>>>>>>> C atomic_load(volatile A *object);
>>>>>>>
>>>>>>> Upon reflection this makes sense, because if atomics are implemented via
>>>>>>> mutexes, even a read may involve a preceding write. So I'll cast const
>>>>>>> away here, too, and add a comment. (It works when casting const away,
>>>>>>> doesn't it?)
>>>>>>
>>>>>> This doesnt feel "right". These pointers should not be coming from a const
>>>>>> if they are written to
>>>>>>
>>>>>
>>>>> The HEVCContext is not const because the underlying object is const; the
>>>>> HEVCContext is const when accessed from any part of the code that may be
>>>>> run from slice threads, because if a slice thread modifies it, you have
>>>>> a data race in case any of the other slice threads reads this field or
>>>>> modifies it itself. But this is by definition not true for atomic
>>>>> operations, so casting const away for them is fine.
>>>>>
>>>>>> The compiler accepts it with an explicit cast though. With an implicit cast
>>>>>> it produces a warning
>>>>>>
>>>>
>>>> Did the above explanation satisfy you? Or do you want something else?
>>>
>>> sure, ok
>>>
>>> [...]
>>>
>>
>> Good to hear. This patchset (namely patch 11/18: "avcodec/hevcpred: Pass
>> HEVCLocalContext when slice-threading") includes modifications to mips
>> code that I created blindly. Can you please test it? Here is a branch of
>> this rebased on top of current git master:
>> https://github.com/mkver/FFmpeg/commits/hevc_wpp
>> (Said branch actually contains a bit of further work which also modifies
>> mips code (in particular,
>> https://github.com/mkver/FFmpeg/commit/cf441e559b8d4bf2c05c29483ccf49e82fc6b863
>> does so); you may also test this.)
> 
> what exact tests do we need ?
> simple fate ? any specific thread type count ?
> also note i can only test qemu mips not real hw.
> I stopped maintaining the MIPS hw and sofar noone volunteered to take its 
> maintaince over
> 

Compiling (in particular being on the lookout for new warnings) and a
simple fate should be enough.

- Andreas
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [FFmpeg-devel] [PATCH 14/18] avcodec/hevcdec: Don't allocate redundant HEVCContexts
  2022-07-24 21:26                   ` Andreas Rheinhardt
@ 2022-07-25 19:44                     ` Michael Niedermayer
  2022-07-25 19:58                       ` Andreas Rheinhardt
  0 siblings, 1 reply; 37+ messages in thread
From: Michael Niedermayer @ 2022-07-25 19:44 UTC (permalink / raw)
  To: FFmpeg development discussions and patches


[-- Attachment #1.1: Type: text/plain, Size: 15070 bytes --]

On Sun, Jul 24, 2022 at 11:26:37PM +0200, Andreas Rheinhardt wrote:
> Michael Niedermayer:
> > On Sat, Jul 23, 2022 at 11:42:23PM +0200, Andreas Rheinhardt wrote:
> >> Michael Niedermayer:
> >>> On Sat, Jul 23, 2022 at 07:44:40AM +0200, Andreas Rheinhardt wrote:
> >>>> Andreas Rheinhardt:
> >>>>> Michael Niedermayer:
> >>>>>> On Sat, Jul 02, 2022 at 08:32:06AM +0200, Andreas Rheinhardt wrote:
> >>>>>>> Michael Niedermayer:
> >>>>>>>> On Fri, Jul 01, 2022 at 12:29:45AM +0200, Andreas Rheinhardt wrote:
> >>>>>>>>> The HEVC decoder has both HEVCContext and HEVCLocalContext
> >>>>>>>>> structures. The latter is supposed to be the structure
> >>>>>>>>> containing the per-slicethread state.
> >>>>>>>>>
> >>>>>>>>> Yet up until now that is not how it is handled in practice:
> >>>>>>>>> Each HEVCLocalContext has a unique HEVCContext allocated for it
> >>>>>>>>> and each of these coincides except in exactly one field: The
> >>>>>>>>> corresponding HEVCLocalContext. This makes it possible to pass
> >>>>>>>>> the HEVCContext everywhere where logically a HEVCLocalContext
> >>>>>>>>> should be used. And up until recently, this is how it has been done.
> >>>>>>>>>
> >>>>>>>>> Yet the preceding patches changed this, making it possible
> >>>>>>>>> to avoid allocating redundant HEVCContexts.
> >>>>>>>>>
> >>>>>>>>> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
> >>>>>>>>> ---
> >>>>>>>>>  libavcodec/hevcdec.c | 40 ++++++++++++++++------------------------
> >>>>>>>>>  libavcodec/hevcdec.h |  2 --
> >>>>>>>>>  2 files changed, 16 insertions(+), 26 deletions(-)
> >>>>>>>>>
> >>>>>>>>> diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
> >>>>>>>>> index 9d1241f293..048fcc76b4 100644
> >>>>>>>>> --- a/libavcodec/hevcdec.c
> >>>>>>>>> +++ b/libavcodec/hevcdec.c
> >>>>>>>>> @@ -2548,13 +2548,12 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
> >>>>>>>>>  {
> >>>>>>>>>      HEVCLocalContext *lc = ((HEVCLocalContext**)hevc_lclist)[self_id];
> >>>>>>>>>      const HEVCContext *const s = lc->parent;
> >>>>>>>>> -    HEVCContext *s1  = avctxt->priv_data;
> >>>>>>>>> -    int ctb_size    = 1<< s1->ps.sps->log2_ctb_size;
> >>>>>>>>> +    int ctb_size    = 1 << s->ps.sps->log2_ctb_size;
> >>>>>>>>>      int more_data   = 1;
> >>>>>>>>>      int ctb_row = job;
> >>>>>>>>> -    int ctb_addr_rs = s1->sh.slice_ctb_addr_rs + ctb_row * ((s1->ps.sps->width + ctb_size - 1) >> s1->ps.sps->log2_ctb_size);
> >>>>>>>>> -    int ctb_addr_ts = s1->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
> >>>>>>>>> -    int thread = ctb_row % s1->threads_number;
> >>>>>>>>> +    int ctb_addr_rs = s->sh.slice_ctb_addr_rs + ctb_row * ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size);
> >>>>>>>>> +    int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
> >>>>>>>>> +    int thread = ctb_row % s->threads_number;
> >>>>>>>>>      int ret;
> >>>>>>>>>  
> >>>>>>>>>      if(ctb_row) {
> >>>>>>>>> @@ -2572,7 +2571,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
> >>>>>>>>>  
> >>>>>>>>>          ff_thread_await_progress2(s->avctx, ctb_row, thread, SHIFT_CTB_WPP);
> >>>>>>>>>  
> >>>>>>>>> -        if (atomic_load(&s1->wpp_err)) {
> >>>>>>>>> +        if (atomic_load(&s->wpp_err)) {
> >>>>>>>>>              ff_thread_report_progress2(s->avctx, ctb_row , thread, SHIFT_CTB_WPP);
> >>>>>>>>
> >>>>>>>> the consts in "const HEVCContext *const " make clang version 6.0.0-1ubuntu2 unhappy
> >>>>>>>> (this was building shared libs)
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> CC	libavcodec/hevcdec.o
> >>>>>>>> src/libavcodec/hevcdec.c:2574:13: error: address argument to atomic operation must be a pointer to non-const _Atomic type ('const atomic_int *' (aka 'const _Atomic(int) *') invalid)
> >>>>>>>>         if (atomic_load(&s->wpp_err)) {
> >>>>>>>>             ^           ~~~~~~~~~~~
> >>>>>>>> /usr/lib/llvm-6.0/lib/clang/6.0.0/include/stdatomic.h:134:29: note: expanded from macro 'atomic_load'
> >>>>>>>> #define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST)
> >>>>>>>>                             ^                 ~~~~~~
> >>>>>>>> 1 error generated.
> >>>>>>>> src/ffbuild/common.mak:81: recipe for target 'libavcodec/hevcdec.o' failed
> >>>>>>>> make: *** [libavcodec/hevcdec.o] Error 1
> >>>>>>>>
> >>>>>>>> thx
> >>>>>>>>
> >>>>>>>
> >>>>>>> Thanks for testing this. atomic_load is indeed declared without const in
> >>>>>>> 7.17.7.2:
> >>>>>>>
> >>>>>>> C atomic_load(volatile A *object);
> >>>>>>>
> >>>>>>> Upon reflection this makes sense, because if atomics are implemented via
> >>>>>>> mutexes, even a read may involve a preceding write. So I'll cast const
> >>>>>>> away here, too, and add a comment. (It works when casting const away,
> >>>>>>> doesn't it?)
> >>>>>>
> >>>>>> This doesnt feel "right". These pointers should not be coming from a const
> >>>>>> if they are written to
> >>>>>>
> >>>>>
> >>>>> The HEVCContext is not const because the underlying object is const; the
> >>>>> HEVCContext is const when accessed from any part of the code that may be
> >>>>> run from slice threads, because if a slice thread modifies it, you have
> >>>>> a data race in case any of the other slice threads reads this field or
> >>>>> modifies it itself. But this is by definition not true for atomic
> >>>>> operations, so casting const away for them is fine.
> >>>>>
> >>>>>> The compiler accepts it with an explicit cast though. With an implicit cast
> >>>>>> it produces a warning
> >>>>>>
> >>>>
> >>>> Did the above explanation satisfy you? Or do you want something else?
> >>>
> >>> sure, ok
> >>>
> >>> [...]
> >>>
> >>
> >> Good to hear. This patchset (namely patch 11/18: "avcodec/hevcpred: Pass
> >> HEVCLocalContext when slice-threading") includes modifications to mips
> >> code that I created blindly. Can you please test it? Here is a branch of
> >> this rebased on top of current git master:
> >> https://github.com/mkver/FFmpeg/commits/hevc_wpp
> >> (Said branch actually contains a bit of further work which also modifies
> >> mips code (in particular,
> >> https://github.com/mkver/FFmpeg/commit/cf441e559b8d4bf2c05c29483ccf49e82fc6b863
> >> does so); you may also test this.)
> > 
> > what exact tests do we need ?
> > simple fate ? any specific thread type count ?
> > also note i can only test qemu mips not real hw.
> > I stopped maintaining the MIPS hw and sofar noone volunteered to take its 
> > maintaince over
> > 
> 
> Compiling (in particular being on the lookout for new warnings) and a
> simple fate should be enough.



I seethis: (NOT sanity checked and i also had some other patches from today applied)
Probably these are all unrelated nonsense

--- fatelist-oldw	2022-07-25 21:19:24.555885524 +0200
+++ fatelistw	2022-07-25 21:19:30.715956081 +0200
@@ -1,3 +1,5 @@
+src/tests/checkasm/synth_filter.c:66:42: warning: unused variable ‘offset_b’ [-Wunused-variable]
+src/tests/checkasm/sbrdsp.c:180:14: warning: unused variable ‘bw’ [-Wunused-variable]
 src/libavfilter/dnn/dnn_backend_common.c:94:11: warning: unused variable ‘status’ [-Wunused-variable]
 src/libavfilter/dnn/dnn_backend_common.c:114:11: warning: unused variable ‘status’ [-Wunused-variable]
 src/libavfilter/dnn/dnn_backend_common.c:80:14: warning: ‘async_thread_routine’ defined but not used [-Wunused-function]
@@ -7,20 +9,20 @@
 src/libavformat/dashenc.c:1960:63: warning: ‘%s’ directive output may be truncated writing up to 1023 bytes into a region of size between 1 and 1024 [-Wformat-truncation=]
 src/libavformat/dashenc.c:492:49: warning: ‘media_’ directive output may be truncated writing 6 bytes into a region of size between 1 and 1024 [-Wformat-truncation=]
 src/libavformat/dashenc.c:2257:59: warning: ‘%s’ directive output may be truncated writing up to 1023 bytes into a region of size between 1 and 1024 [-Wformat-truncation=]
-src/libavformat/matroskaenc.c:3074:58: warning: ‘%012.9f’ directive output may be truncated writing between 12 and 320 bytes into a region of size between 8 and 14 [-Wformat-truncation=]
 src/libavformat/mlvdec.c:361:63: warning: ‘__builtin___snprintf_chk’ output may be truncated before the last format character [-Wformat-truncation=]
-src/libavformat/movenc.c:1126:8: warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false [-Wstrict-overflow]
+src/libavformat/matroskaenc.c:3074:58: warning: ‘%012.9f’ directive output may be truncated writing between 12 and 320 bytes into a region of size between 8 and 14 [-Wformat-truncation=]
 src/libavformat/smoothstreamingenc.c:509:49: warning: ‘/temp’ directive output may be truncated writing 5 bytes into a region of size between 1 and 1024 [-Wformat-truncation=]
 src/libavformat/smoothstreamingenc.c:544:63: warning: ‘/FragmentInfo(’ directive output may be truncated writing 14 bytes into a region of size between 1 and 1024 [-Wformat-truncation=]
 src/libavformat/smoothstreamingenc.c:545:63: warning: ‘/Fragments(’ directive output may be truncated writing 11 bytes into a region of size between 1 and 1024 [-Wformat-truncation=]
 src/libavformat/smoothstreamingenc.c:537:53: warning: ‘/temp’ directive output may be truncated writing 5 bytes into a region of size between 1 and 1024 [-Wformat-truncation=]
 src/libavformat/vorbiscomment.c:103:63: warning: ‘%03d’ directive output may be truncated writing between 3 and 10 bytes into a region of size 4 [-Wformat-truncation=]
 src/libavformat/vorbiscomment.c:104:69: warning: ‘%02d’ directive output may be truncated writing between 2 and 3 bytes into a region of size between 1 and 7 [-Wformat-truncation=]
+src/libavformat/movenc.c:1126:8: warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false [-Wstrict-overflow]
 src/libavcodec/mips/aacsbr_mips.h:62:13: warning: ‘sbr_qmf_analysis_mips’ defined but not used [-Wunused-function]
 src/libavcodec/dvenc.c:786:81: warning: array subscript is above array bounds [-Warray-bounds]
 src/libavcodec/dvenc.c:786:81: warning: array subscript is above array bounds [-Warray-bounds]
 src/libavcodec/ffv1dec.c:999:13: warning: ‘copy_fields’ defined but not used [-Wunused-function]
-src/libavcodec/hevcdec.c:3540:12: warning: ‘hevc_ref_frame’ defined but not used [-Wunused-function]
+src/libavcodec/hevcdec.c:3529:12: warning: ‘hevc_ref_frame’ defined but not used [-Wunused-function]
 src/libavcodec/mobiclip.c:471:24: warning: array subscript is above array bounds [-Warray-bounds]
 src/libavcodec/mobiclip.c:475:16: warning: array subscript is above array bounds [-Warray-bounds]
 src/libavcodec/mobiclip.c:471:24: warning: array subscript is above array bounds [-Warray-bounds]
@@ -41,11 +43,11 @@
 src/libavcodec/pcm-bluray.c:190:49: warning: passing argument 2 of ‘bytestream2_get_buffer’ from incompatible pointer type [-Wincompatible-pointer-types]
 src/libavcodec/pcm-dvd.c:160:37: warning: passing argument 2 of ‘bytestream2_get_buffer’ from incompatible pointer type [-Wincompatible-pointer-types]
 src/libavcodec/qdm2.c:1002:47: warning: array subscript is above array bounds [-Warray-bounds]
-src/libavcodec/vp8.c:2373:30: warning: variable ‘next_td’ set but not used [-Wunused-but-set-variable]
-src/libavcodec/vp8.c:2586:37: warning: unused variable ‘prev_td’ [-Wunused-variable]
-src/libavcodec/vp8.c:2586:20: warning: unused variable ‘next_td’ [-Wunused-variable]
-src/libavcodec/vp8.c:109:12: warning: ‘vp8_ref_frame’ defined but not used [-Wunused-function]
-src/libavcodec/vp9.c:1795:9: warning: unused variable ‘ret’ [-Wunused-variable]
 src/libavutil/timecode.c:123:60: warning: ‘%0*d’ directive output may be truncated writing between 1 and 10 bytes into a region of size between 2 and 14 [-Wformat-truncation=]
+src/libavcodec/vp9.c:1795:9: warning: unused variable ‘ret’ [-Wunused-variable]
 src/fftools/ffprobe.c:333:11: warning: unused variable ‘new_log_buffer’ [-Wunused-variable]
 src/fftools/ffprobe.c:329:14: warning: unused variable ‘avc’ [-Wunused-variable]
+src/libavcodec/vp8.c:2373:30: warning: variable ‘next_td’ set but not used [-Wunused-but-set-variable]
+src/libavcodec/vp8.c:2587:37: warning: unused variable ‘prev_td’ [-Wunused-variable]
+src/libavcodec/vp8.c:2587:20: warning: unused variable ‘next_td’ [-Wunused-variable]
+src/libavcodec/vp8.c:109:12: warning: ‘vp8_ref_frame’ defined but not used [-Wunused-function]


There is also the fate-filter-metadata-signalstats-yuv420p10 test
which fails before and afterwards
-pts=0|tag:lavfi.signalstats.UBITDEPTH=2|tag:lavfi.signalstats.YMIN=943|tag:lavfi.signalstats.YLOW=943|tag:lavfi.signalstats.YAVG=943|tag:lavfi.signalstats.YHIGH=943|tag:lavfi.signalstats.YMAX=943|tag:lavfi.signalstats.UMIN=514|tag:lavfi.signalstats.ULOW=514|tag:lavfi.signalstats.UAVG=514|tag:lavfi.signalstats.UHIGH=514|tag:lavfi.signalstats.UMAX=514|tag:lavfi.signalstats.VMIN=514|tag:lavfi.signalstats.VLOW=514|tag:lavfi.signalstats.VAVG=514|tag:lavfi.signalstats.VHIGH=514|tag:lavfi.signalstats.VMAX=514|tag:lavfi.signalstats.SATMIN=2|tag:lavfi.signalstats.SATLOW=2|tag:lavfi.signalstats.SATAVG=2|tag:lavfi.signalstats.SATHIGH=2|tag:lavfi.signalstats.SATMAX=2|tag:lavfi.signalstats.HUEMED=225|tag:lavfi.signalstats.HUEAVG=225|tag:lavfi.signalstats.YDIF=0|tag:lavfi.signalstats.UDIF=0|tag:lavfi.signalstats.VDIF=0|tag:lavfi.signalstats.YBITDEPTH=8|tag:lavfi.signalstats.VBITDEPTH=2
+pts=0|tag:lavfi.signalstats.UBITDEPTH=1|tag:lavfi.signalstats.YMIN=940|tag:lavfi.signalstats.YLOW=940|tag:lavfi.signalstats.YAVG=940|tag:lavfi.signalstats.YHIGH=940|tag:lavfi.signalstats.YMAX=940|tag:lavfi.signalstats.UMIN=512|tag:lavfi.signalstats.ULOW=512|tag:lavfi.signalstats.UAVG=512|tag:lavfi.signalstats.UHIGH=512|tag:lavfi.signalstats.UMAX=512|tag:lavfi.signalstats.VMIN=512|tag:lavfi.signalstats.VLOW=512|tag:lavfi.signalstats.VAVG=512|tag:lavfi.signalstats.VHIGH=512|tag:lavfi.signalstats.VMAX=512|tag:lavfi.signalstats.SATMIN=0|tag:lavfi.signalstats.SATLOW=0|tag:lavfi.signalstats.SATAVG=0|tag:lavfi.signalstats.SATHIGH=0|tag:lavfi.signalstats.SATMAX=0|tag:lavfi.signalstats.HUEMED=180|tag:lavfi.signalstats.HUEAVG=180|tag:lavfi.signalstats.YDIF=0|tag:lavfi.signalstats.UDIF=0|tag:lavfi.signalstats.VDIF=0|tag:lavfi.signalstats.YBITDEPTH=6|tag:lavfi.signalstats.VBITDEPTH=1
Test filter-metadata-signalstats-yuv420p10 failed. Look at tests/data/fate/filter-metadata-signalstats-yuv420p10.err for details.


[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

If you drop bombs on a foreign country and kill a hundred thousand
innocent people, expect your government to call the consequence
"unprovoked inhuman terrorist attacks" and use it to justify dropping
more bombs and killing more people. The technology changed, the idea is old.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

[-- Attachment #2: Type: text/plain, Size: 251 bytes --]

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [FFmpeg-devel] [PATCH 14/18] avcodec/hevcdec: Don't allocate redundant HEVCContexts
  2022-07-25 19:44                     ` Michael Niedermayer
@ 2022-07-25 19:58                       ` Andreas Rheinhardt
  0 siblings, 0 replies; 37+ messages in thread
From: Andreas Rheinhardt @ 2022-07-25 19:58 UTC (permalink / raw)
  To: ffmpeg-devel

Michael Niedermayer:
> On Sun, Jul 24, 2022 at 11:26:37PM +0200, Andreas Rheinhardt wrote:
>> Michael Niedermayer:
>>> On Sat, Jul 23, 2022 at 11:42:23PM +0200, Andreas Rheinhardt wrote:
>>>> Michael Niedermayer:
>>>>> On Sat, Jul 23, 2022 at 07:44:40AM +0200, Andreas Rheinhardt wrote:
>>>>>> Andreas Rheinhardt:
>>>>>>> Michael Niedermayer:
>>>>>>>> On Sat, Jul 02, 2022 at 08:32:06AM +0200, Andreas Rheinhardt wrote:
>>>>>>>>> Michael Niedermayer:
>>>>>>>>>> On Fri, Jul 01, 2022 at 12:29:45AM +0200, Andreas Rheinhardt wrote:
>>>>>>>>>>> The HEVC decoder has both HEVCContext and HEVCLocalContext
>>>>>>>>>>> structures. The latter is supposed to be the structure
>>>>>>>>>>> containing the per-slicethread state.
>>>>>>>>>>>
>>>>>>>>>>> Yet up until now that is not how it is handled in practice:
>>>>>>>>>>> Each HEVCLocalContext has a unique HEVCContext allocated for it
>>>>>>>>>>> and each of these coincides except in exactly one field: The
>>>>>>>>>>> corresponding HEVCLocalContext. This makes it possible to pass
>>>>>>>>>>> the HEVCContext everywhere where logically a HEVCLocalContext
>>>>>>>>>>> should be used. And up until recently, this is how it has been done.
>>>>>>>>>>>
>>>>>>>>>>> Yet the preceding patches changed this, making it possible
>>>>>>>>>>> to avoid allocating redundant HEVCContexts.
>>>>>>>>>>>
>>>>>>>>>>> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
>>>>>>>>>>> ---
>>>>>>>>>>>  libavcodec/hevcdec.c | 40 ++++++++++++++++------------------------
>>>>>>>>>>>  libavcodec/hevcdec.h |  2 --
>>>>>>>>>>>  2 files changed, 16 insertions(+), 26 deletions(-)
>>>>>>>>>>>
>>>>>>>>>>> diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
>>>>>>>>>>> index 9d1241f293..048fcc76b4 100644
>>>>>>>>>>> --- a/libavcodec/hevcdec.c
>>>>>>>>>>> +++ b/libavcodec/hevcdec.c
>>>>>>>>>>> @@ -2548,13 +2548,12 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
>>>>>>>>>>>  {
>>>>>>>>>>>      HEVCLocalContext *lc = ((HEVCLocalContext**)hevc_lclist)[self_id];
>>>>>>>>>>>      const HEVCContext *const s = lc->parent;
>>>>>>>>>>> -    HEVCContext *s1  = avctxt->priv_data;
>>>>>>>>>>> -    int ctb_size    = 1<< s1->ps.sps->log2_ctb_size;
>>>>>>>>>>> +    int ctb_size    = 1 << s->ps.sps->log2_ctb_size;
>>>>>>>>>>>      int more_data   = 1;
>>>>>>>>>>>      int ctb_row = job;
>>>>>>>>>>> -    int ctb_addr_rs = s1->sh.slice_ctb_addr_rs + ctb_row * ((s1->ps.sps->width + ctb_size - 1) >> s1->ps.sps->log2_ctb_size);
>>>>>>>>>>> -    int ctb_addr_ts = s1->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
>>>>>>>>>>> -    int thread = ctb_row % s1->threads_number;
>>>>>>>>>>> +    int ctb_addr_rs = s->sh.slice_ctb_addr_rs + ctb_row * ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size);
>>>>>>>>>>> +    int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs];
>>>>>>>>>>> +    int thread = ctb_row % s->threads_number;
>>>>>>>>>>>      int ret;
>>>>>>>>>>>  
>>>>>>>>>>>      if(ctb_row) {
>>>>>>>>>>> @@ -2572,7 +2571,7 @@ static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *hevc_lclist,
>>>>>>>>>>>  
>>>>>>>>>>>          ff_thread_await_progress2(s->avctx, ctb_row, thread, SHIFT_CTB_WPP);
>>>>>>>>>>>  
>>>>>>>>>>> -        if (atomic_load(&s1->wpp_err)) {
>>>>>>>>>>> +        if (atomic_load(&s->wpp_err)) {
>>>>>>>>>>>              ff_thread_report_progress2(s->avctx, ctb_row , thread, SHIFT_CTB_WPP);
>>>>>>>>>>
>>>>>>>>>> the consts in "const HEVCContext *const " make clang version 6.0.0-1ubuntu2 unhappy
>>>>>>>>>> (this was building shared libs)
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> CC	libavcodec/hevcdec.o
>>>>>>>>>> src/libavcodec/hevcdec.c:2574:13: error: address argument to atomic operation must be a pointer to non-const _Atomic type ('const atomic_int *' (aka 'const _Atomic(int) *') invalid)
>>>>>>>>>>         if (atomic_load(&s->wpp_err)) {
>>>>>>>>>>             ^           ~~~~~~~~~~~
>>>>>>>>>> /usr/lib/llvm-6.0/lib/clang/6.0.0/include/stdatomic.h:134:29: note: expanded from macro 'atomic_load'
>>>>>>>>>> #define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST)
>>>>>>>>>>                             ^                 ~~~~~~
>>>>>>>>>> 1 error generated.
>>>>>>>>>> src/ffbuild/common.mak:81: recipe for target 'libavcodec/hevcdec.o' failed
>>>>>>>>>> make: *** [libavcodec/hevcdec.o] Error 1
>>>>>>>>>>
>>>>>>>>>> thx
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Thanks for testing this. atomic_load is indeed declared without const in
>>>>>>>>> 7.17.7.2:
>>>>>>>>>
>>>>>>>>> C atomic_load(volatile A *object);
>>>>>>>>>
>>>>>>>>> Upon reflection this makes sense, because if atomics are implemented via
>>>>>>>>> mutexes, even a read may involve a preceding write. So I'll cast const
>>>>>>>>> away here, too, and add a comment. (It works when casting const away,
>>>>>>>>> doesn't it?)
>>>>>>>>
>>>>>>>> This doesnt feel "right". These pointers should not be coming from a const
>>>>>>>> if they are written to
>>>>>>>>
>>>>>>>
>>>>>>> The HEVCContext is not const because the underlying object is const; the
>>>>>>> HEVCContext is const when accessed from any part of the code that may be
>>>>>>> run from slice threads, because if a slice thread modifies it, you have
>>>>>>> a data race in case any of the other slice threads reads this field or
>>>>>>> modifies it itself. But this is by definition not true for atomic
>>>>>>> operations, so casting const away for them is fine.
>>>>>>>
>>>>>>>> The compiler accepts it with an explicit cast though. With an implicit cast
>>>>>>>> it produces a warning
>>>>>>>>
>>>>>>
>>>>>> Did the above explanation satisfy you? Or do you want something else?
>>>>>
>>>>> sure, ok
>>>>>
>>>>> [...]
>>>>>
>>>>
>>>> Good to hear. This patchset (namely patch 11/18: "avcodec/hevcpred: Pass
>>>> HEVCLocalContext when slice-threading") includes modifications to mips
>>>> code that I created blindly. Can you please test it? Here is a branch of
>>>> this rebased on top of current git master:
>>>> https://github.com/mkver/FFmpeg/commits/hevc_wpp
>>>> (Said branch actually contains a bit of further work which also modifies
>>>> mips code (in particular,
>>>> https://github.com/mkver/FFmpeg/commit/cf441e559b8d4bf2c05c29483ccf49e82fc6b863
>>>> does so); you may also test this.)
>>>
>>> what exact tests do we need ?
>>> simple fate ? any specific thread type count ?
>>> also note i can only test qemu mips not real hw.
>>> I stopped maintaining the MIPS hw and sofar noone volunteered to take its 
>>> maintaince over
>>>
>>
>> Compiling (in particular being on the lookout for new warnings) and a
>> simple fate should be enough.
> 
> 
> 
> I seethis: (NOT sanity checked and i also had some other patches from today applied)
> Probably these are all unrelated nonsense
> 
> --- fatelist-oldw	2022-07-25 21:19:24.555885524 +0200
> +++ fatelistw	2022-07-25 21:19:30.715956081 +0200
> @@ -1,3 +1,5 @@
> +src/tests/checkasm/synth_filter.c:66:42: warning: unused variable ‘offset_b’ [-Wunused-variable]
> +src/tests/checkasm/sbrdsp.c:180:14: warning: unused variable ‘bw’ [-Wunused-variable]
>  src/libavfilter/dnn/dnn_backend_common.c:94:11: warning: unused variable ‘status’ [-Wunused-variable]
>  src/libavfilter/dnn/dnn_backend_common.c:114:11: warning: unused variable ‘status’ [-Wunused-variable]
>  src/libavfilter/dnn/dnn_backend_common.c:80:14: warning: ‘async_thread_routine’ defined but not used [-Wunused-function]
> @@ -7,20 +9,20 @@
>  src/libavformat/dashenc.c:1960:63: warning: ‘%s’ directive output may be truncated writing up to 1023 bytes into a region of size between 1 and 1024 [-Wformat-truncation=]
>  src/libavformat/dashenc.c:492:49: warning: ‘media_’ directive output may be truncated writing 6 bytes into a region of size between 1 and 1024 [-Wformat-truncation=]
>  src/libavformat/dashenc.c:2257:59: warning: ‘%s’ directive output may be truncated writing up to 1023 bytes into a region of size between 1 and 1024 [-Wformat-truncation=]
> -src/libavformat/matroskaenc.c:3074:58: warning: ‘%012.9f’ directive output may be truncated writing between 12 and 320 bytes into a region of size between 8 and 14 [-Wformat-truncation=]
>  src/libavformat/mlvdec.c:361:63: warning: ‘__builtin___snprintf_chk’ output may be truncated before the last format character [-Wformat-truncation=]
> -src/libavformat/movenc.c:1126:8: warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false [-Wstrict-overflow]
> +src/libavformat/matroskaenc.c:3074:58: warning: ‘%012.9f’ directive output may be truncated writing between 12 and 320 bytes into a region of size between 8 and 14 [-Wformat-truncation=]
>  src/libavformat/smoothstreamingenc.c:509:49: warning: ‘/temp’ directive output may be truncated writing 5 bytes into a region of size between 1 and 1024 [-Wformat-truncation=]
>  src/libavformat/smoothstreamingenc.c:544:63: warning: ‘/FragmentInfo(’ directive output may be truncated writing 14 bytes into a region of size between 1 and 1024 [-Wformat-truncation=]
>  src/libavformat/smoothstreamingenc.c:545:63: warning: ‘/Fragments(’ directive output may be truncated writing 11 bytes into a region of size between 1 and 1024 [-Wformat-truncation=]
>  src/libavformat/smoothstreamingenc.c:537:53: warning: ‘/temp’ directive output may be truncated writing 5 bytes into a region of size between 1 and 1024 [-Wformat-truncation=]
>  src/libavformat/vorbiscomment.c:103:63: warning: ‘%03d’ directive output may be truncated writing between 3 and 10 bytes into a region of size 4 [-Wformat-truncation=]
>  src/libavformat/vorbiscomment.c:104:69: warning: ‘%02d’ directive output may be truncated writing between 2 and 3 bytes into a region of size between 1 and 7 [-Wformat-truncation=]
> +src/libavformat/movenc.c:1126:8: warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false [-Wstrict-overflow]
>  src/libavcodec/mips/aacsbr_mips.h:62:13: warning: ‘sbr_qmf_analysis_mips’ defined but not used [-Wunused-function]
>  src/libavcodec/dvenc.c:786:81: warning: array subscript is above array bounds [-Warray-bounds]
>  src/libavcodec/dvenc.c:786:81: warning: array subscript is above array bounds [-Warray-bounds]
>  src/libavcodec/ffv1dec.c:999:13: warning: ‘copy_fields’ defined but not used [-Wunused-function]
> -src/libavcodec/hevcdec.c:3540:12: warning: ‘hevc_ref_frame’ defined but not used [-Wunused-function]
> +src/libavcodec/hevcdec.c:3529:12: warning: ‘hevc_ref_frame’ defined but not used [-Wunused-function]
>  src/libavcodec/mobiclip.c:471:24: warning: array subscript is above array bounds [-Warray-bounds]
>  src/libavcodec/mobiclip.c:475:16: warning: array subscript is above array bounds [-Warray-bounds]
>  src/libavcodec/mobiclip.c:471:24: warning: array subscript is above array bounds [-Warray-bounds]
> @@ -41,11 +43,11 @@
>  src/libavcodec/pcm-bluray.c:190:49: warning: passing argument 2 of ‘bytestream2_get_buffer’ from incompatible pointer type [-Wincompatible-pointer-types]
>  src/libavcodec/pcm-dvd.c:160:37: warning: passing argument 2 of ‘bytestream2_get_buffer’ from incompatible pointer type [-Wincompatible-pointer-types]
>  src/libavcodec/qdm2.c:1002:47: warning: array subscript is above array bounds [-Warray-bounds]
> -src/libavcodec/vp8.c:2373:30: warning: variable ‘next_td’ set but not used [-Wunused-but-set-variable]
> -src/libavcodec/vp8.c:2586:37: warning: unused variable ‘prev_td’ [-Wunused-variable]
> -src/libavcodec/vp8.c:2586:20: warning: unused variable ‘next_td’ [-Wunused-variable]
> -src/libavcodec/vp8.c:109:12: warning: ‘vp8_ref_frame’ defined but not used [-Wunused-function]
> -src/libavcodec/vp9.c:1795:9: warning: unused variable ‘ret’ [-Wunused-variable]
>  src/libavutil/timecode.c:123:60: warning: ‘%0*d’ directive output may be truncated writing between 1 and 10 bytes into a region of size between 2 and 14 [-Wformat-truncation=]
> +src/libavcodec/vp9.c:1795:9: warning: unused variable ‘ret’ [-Wunused-variable]
>  src/fftools/ffprobe.c:333:11: warning: unused variable ‘new_log_buffer’ [-Wunused-variable]
>  src/fftools/ffprobe.c:329:14: warning: unused variable ‘avc’ [-Wunused-variable]
> +src/libavcodec/vp8.c:2373:30: warning: variable ‘next_td’ set but not used [-Wunused-but-set-variable]
> +src/libavcodec/vp8.c:2587:37: warning: unused variable ‘prev_td’ [-Wunused-variable]
> +src/libavcodec/vp8.c:2587:20: warning: unused variable ‘next_td’ [-Wunused-variable]
> +src/libavcodec/vp8.c:109:12: warning: ‘vp8_ref_frame’ defined but not used [-Wunused-function]
> 
> 
> There is also the fate-filter-metadata-signalstats-yuv420p10 test
> which fails before and afterwards
> -pts=0|tag:lavfi.signalstats.UBITDEPTH=2|tag:lavfi.signalstats.YMIN=943|tag:lavfi.signalstats.YLOW=943|tag:lavfi.signalstats.YAVG=943|tag:lavfi.signalstats.YHIGH=943|tag:lavfi.signalstats.YMAX=943|tag:lavfi.signalstats.UMIN=514|tag:lavfi.signalstats.ULOW=514|tag:lavfi.signalstats.UAVG=514|tag:lavfi.signalstats.UHIGH=514|tag:lavfi.signalstats.UMAX=514|tag:lavfi.signalstats.VMIN=514|tag:lavfi.signalstats.VLOW=514|tag:lavfi.signalstats.VAVG=514|tag:lavfi.signalstats.VHIGH=514|tag:lavfi.signalstats.VMAX=514|tag:lavfi.signalstats.SATMIN=2|tag:lavfi.signalstats.SATLOW=2|tag:lavfi.signalstats.SATAVG=2|tag:lavfi.signalstats.SATHIGH=2|tag:lavfi.signalstats.SATMAX=2|tag:lavfi.signalstats.HUEMED=225|tag:lavfi.signalstats.HUEAVG=225|tag:lavfi.signalstats.YDIF=0|tag:lavfi.signalstats.UDIF=0|tag:lavfi.signalstats.VDIF=0|tag:lavfi.signalstats.YBITDEPTH=8|tag:lavfi.signalstats.VBITDEPTH=2
> +pts=0|tag:lavfi.signalstats.UBITDEPTH=1|tag:lavfi.signalstats.YMIN=940|tag:lavfi.signalstats.YLOW=940|tag:lavfi.signalstats.YAVG=940|tag:lavfi.signalstats.YHIGH=940|tag:lavfi.signalstats.YMAX=940|tag:lavfi.signalstats.UMIN=512|tag:lavfi.signalstats.ULOW=512|tag:lavfi.signalstats.UAVG=512|tag:lavfi.signalstats.UHIGH=512|tag:lavfi.signalstats.UMAX=512|tag:lavfi.signalstats.VMIN=512|tag:lavfi.signalstats.VLOW=512|tag:lavfi.signalstats.VAVG=512|tag:lavfi.signalstats.VHIGH=512|tag:lavfi.signalstats.VMAX=512|tag:lavfi.signalstats.SATMIN=0|tag:lavfi.signalstats.SATLOW=0|tag:lavfi.signalstats.SATAVG=0|tag:lavfi.signalstats.SATHIGH=0|tag:lavfi.signalstats.SATMAX=0|tag:lavfi.signalstats.HUEMED=180|tag:lavfi.signalstats.HUEAVG=180|tag:lavfi.signalstats.YDIF=0|tag:lavfi.signalstats.UDIF=0|tag:lavfi.signalstats.VDIF=0|tag:lavfi.signalstats.YBITDEPTH=6|tag:lavfi.signalstats.VBITDEPTH=1
> Test filter-metadata-signalstats-yuv420p10 failed. Look at tests/data/fate/filter-metadata-signalstats-yuv420p10.err for details.
> 
> 

Thanks for your work. Nothing of the above is related to my patches
(e.g. the hevcdec warning is due to you not having threads enabled). So
I will apply these patches now.

- Andreas
_______________________________________________
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".

^ permalink raw reply	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2022-07-25 19:58 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-30 21:48 [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Andreas Rheinhardt
2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 02/18] fate/hevc: add clip for persistent_rice_adaptation_enabled_flag Andreas Rheinhardt
2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 03/18] avcodec/hevcdec: Don't initialize HEVCContexts twice Andreas Rheinhardt
2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 04/18] avcodec/hevcdec: Add pointers to logctx and parent ctx to HEVCLocalCtx Andreas Rheinhardt
2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 05/18] avcodec/hevc_refs: Constify ff_hevc_get_ref_list() Andreas Rheinhardt
2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 06/18] avcodec/hevc_cabac: Don't cast const away unnecessarily Andreas Rheinhardt
2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 07/18] avcodec/hevc_mvs: Pass HEVCLocalContext when slice-threading Andreas Rheinhardt
2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 08/18] avcodec/hevc_filter: " Andreas Rheinhardt
2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 09/18] avcodec/hevcdec: Add stat_coeffs to HEVCABACState Andreas Rheinhardt
2022-07-02  8:34   ` Anton Khirnov
2022-07-02 10:40     ` Andreas Rheinhardt
2022-07-02 11:31       ` Andreas Rheinhardt
2022-07-02 11:43         ` Andreas Rheinhardt
2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 10/18] avcodec/hevc_cabac: Pass HEVCLocalContext when slice-threading Andreas Rheinhardt
2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 11/18] avcodec/hevcpred: " Andreas Rheinhardt
2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 12/18] avcodec/hevcdec: " Andreas Rheinhardt
2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 13/18] avcodec/hevcdec: Pass HEVCLocalContext** via execute2 Andreas Rheinhardt
2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 14/18] avcodec/hevcdec: Don't allocate redundant HEVCContexts Andreas Rheinhardt
2022-07-01 21:25   ` Michael Niedermayer
2022-07-02  6:32     ` Andreas Rheinhardt
2022-07-05 22:24       ` Michael Niedermayer
2022-07-06  8:21         ` Andreas Rheinhardt
2022-07-23  5:44           ` Andreas Rheinhardt
2022-07-23 14:38             ` Michael Niedermayer
2022-07-23 21:42               ` Andreas Rheinhardt
2022-07-24 21:23                 ` Michael Niedermayer
2022-07-24 21:26                   ` Andreas Rheinhardt
2022-07-25 19:44                     ` Michael Niedermayer
2022-07-25 19:58                       ` Andreas Rheinhardt
2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 15/18] avcodec/hevcdec: Check allocation Andreas Rheinhardt
2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 16/18] avcodec/pthread_slice: Combine allocating and zeroing entries Andreas Rheinhardt
2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 17/18] avcodec/pthread_slice: Reuse buffer if possible Andreas Rheinhardt
2022-07-01 11:33   ` Paul B Mahol
2022-07-01 13:21   ` Tomas Härdin
2022-07-22 20:04     ` Andreas Rheinhardt
2022-06-30 22:29 ` [FFmpeg-devel] [PATCH 18/18] avcodec/hevcdec: Move allocation after error checks Andreas Rheinhardt
2022-07-01 13:30 ` [FFmpeg-devel] [PATCH v2 01/18] avcodec/pthread_slice: Don't reinitialise initialised mutex Tomas Härdin

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