]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/pthread_frame.c
lavc: Remove deprecated XvMC support hacks
[ffmpeg] / libavcodec / pthread_frame.c
index fd35456f59c5718e53623983174ac78a6db51437..65a04d8e90949027c3455965a6fecef077292203 100644 (file)
@@ -34,6 +34,7 @@
 #endif
 
 #include "avcodec.h"
+#include "hwaccel.h"
 #include "internal.h"
 #include "pthread_internal.h"
 #include "thread.h"
@@ -101,6 +102,7 @@ typedef struct PerThreadContext {
     int die;                       ///< Set when the thread should exit.
 
     int hwaccel_serializing;
+    int async_serializing;
 } PerThreadContext;
 
 /**
@@ -116,6 +118,7 @@ typedef struct FrameThreadContext {
      * is used.
      */
     pthread_mutex_t hwaccel_mutex;
+    pthread_mutex_t async_mutex;
 
     int next_decoding;             ///< The next context to submit a packet to.
     int next_finished;             ///< The next context to return output from.
@@ -191,6 +194,11 @@ static attribute_align_arg void *frame_worker_thread(void *arg)
             pthread_mutex_unlock(&p->parent->hwaccel_mutex);
         }
 
+        if (p->async_serializing) {
+            p->async_serializing = 0;
+            pthread_mutex_unlock(&p->parent->async_mutex);
+        }
+
         atomic_store(&p->state, STATE_INPUT_READY);
 
         pthread_mutex_lock(&p->progress_mutex);
@@ -262,6 +270,8 @@ FF_ENABLE_DEPRECATION_WARNINGS
                     return AVERROR(ENOMEM);
             }
         }
+
+        dst->hwaccel_flags = src->hwaccel_flags;
     }
 
     if (for_user) {
@@ -414,7 +424,11 @@ int ff_thread_decode_frame(AVCodecContext *avctx,
     FrameThreadContext *fctx = avctx->internal->thread_ctx;
     int finished = fctx->next_finished;
     PerThreadContext *p;
-    int err;
+    int err, ret;
+
+    /* release the async lock, permitting blocked hwaccel threads to
+     * go forward while we are in this function */
+    pthread_mutex_unlock(&fctx->async_mutex);
 
     /*
      * Submit a packet to the next decoding thread.
@@ -422,9 +436,11 @@ int ff_thread_decode_frame(AVCodecContext *avctx,
 
     p = &fctx->threads[fctx->next_decoding];
     err = update_context_from_user(p->avctx, avctx);
-    if (err) return err;
+    if (err)
+        goto finish;
     err = submit_packet(p, avpkt);
-    if (err) return err;
+    if (err)
+        goto finish;
 
     /*
      * If we're still receiving the initial packets, don't return a frame.
@@ -434,8 +450,10 @@ int ff_thread_decode_frame(AVCodecContext *avctx,
         if (fctx->next_decoding >= (avctx->thread_count-1)) fctx->delaying = 0;
 
         *got_picture_ptr=0;
-        if (avpkt->size)
-            return avpkt->size;
+        if (avpkt->size) {
+            ret = avpkt->size;
+            goto finish;
+        }
     }
 
     /*
@@ -477,7 +495,12 @@ int ff_thread_decode_frame(AVCodecContext *avctx,
     fctx->next_finished = finished;
 
     /* return the size of the consumed packet if no error occurred */
-    return (p->result >= 0) ? avpkt->size : p->result;
+    ret = (p->result >= 0) ? avpkt->size : p->result;
+finish:
+    pthread_mutex_lock(&fctx->async_mutex);
+    if (err < 0)
+        return err;
+    return ret;
 }
 
 void ff_thread_report_progress(ThreadFrame *f, int n, int field)
@@ -532,6 +555,13 @@ void ff_thread_finish_setup(AVCodecContext *avctx) {
         p->hwaccel_serializing = 1;
     }
 
+    /* this assumes that no hwaccel calls happen before ff_thread_finish_setup() */
+    if (avctx->hwaccel &&
+        !(avctx->hwaccel->caps_internal & HWACCEL_CAP_ASYNC_SAFE)) {
+        p->async_serializing = 1;
+        pthread_mutex_lock(&p->parent->async_mutex);
+    }
+
     pthread_mutex_lock(&p->progress_mutex);
 
     atomic_store(&p->state, STATE_SETUP_FINISHED);
@@ -545,6 +575,8 @@ static void park_frame_worker_threads(FrameThreadContext *fctx, int thread_count
 {
     int i;
 
+    pthread_mutex_unlock(&fctx->async_mutex);
+
     for (i = 0; i < thread_count; i++) {
         PerThreadContext *p = &fctx->threads[i];
 
@@ -555,6 +587,8 @@ static void park_frame_worker_threads(FrameThreadContext *fctx, int thread_count
             pthread_mutex_unlock(&p->progress_mutex);
         }
     }
+
+    pthread_mutex_lock(&fctx->async_mutex);
 }
 
 void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
@@ -613,6 +647,10 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
     av_freep(&fctx->threads);
     pthread_mutex_destroy(&fctx->buffer_mutex);
     pthread_mutex_destroy(&fctx->hwaccel_mutex);
+
+    pthread_mutex_unlock(&fctx->async_mutex);
+    pthread_mutex_destroy(&fctx->async_mutex);
+
     av_freep(&avctx->internal->thread_ctx);
 }
 
@@ -655,6 +693,10 @@ int ff_frame_thread_init(AVCodecContext *avctx)
 
     pthread_mutex_init(&fctx->buffer_mutex, NULL);
     pthread_mutex_init(&fctx->hwaccel_mutex, NULL);
+
+    pthread_mutex_init(&fctx->async_mutex, NULL);
+    pthread_mutex_lock(&fctx->async_mutex);
+
     fctx->delaying = 1;
 
     for (i = 0; i < thread_count; i++) {