summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavcodec/avcodec.h5
-rw-r--r--libavcodec/hwaccel.h24
-rw-r--r--libavcodec/pthread_frame.c54
-rw-r--r--libavcodec/vaapi_h264.c2
-rw-r--r--libavcodec/vaapi_mpeg2.c2
-rw-r--r--libavcodec/vaapi_mpeg4.c3
-rw-r--r--libavcodec/vaapi_vc1.c3
-rw-r--r--libavcodec/vdpau_h264.c2
-rw-r--r--libavcodec/vdpau_hevc.c2
-rw-r--r--libavcodec/vdpau_mpeg12.c3
-rw-r--r--libavcodec/vdpau_mpeg4.c2
-rw-r--r--libavcodec/vdpau_vc1.c3
12 files changed, 98 insertions, 7 deletions
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index fbdf89216d..f9ebd14a7e 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -3905,6 +3905,11 @@ typedef struct AVHWAccel {
* AVCodecInternal.hwaccel_priv_data.
*/
int priv_data_size;
+
+ /**
+ * Internal hwaccel capabilities.
+ */
+ int caps_internal;
} AVHWAccel;
/**
diff --git a/libavcodec/hwaccel.h b/libavcodec/hwaccel.h
new file mode 100644
index 0000000000..17af43707c
--- /dev/null
+++ b/libavcodec/hwaccel.h
@@ -0,0 +1,24 @@
+/*
+ * This file is part of FFmpeg and was stolen from Libav.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_HWACCEL_H
+#define AVCODEC_HWACCEL_H
+
+#define HWACCEL_CAP_ASYNC_SAFE (1 << 0)
+
+#endif /* AVCODEC_HWACCEL_H */
diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index e3bfbab872..f959175db3 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -28,6 +28,7 @@
#include <stdint.h>
#include "avcodec.h"
+#include "hwaccel.h"
#include "internal.h"
#include "pthread_internal.h"
#include "thread.h"
@@ -105,6 +106,7 @@ typedef struct PerThreadContext {
int die; ///< Set when the thread should exit.
int hwaccel_serializing;
+ int async_serializing;
} PerThreadContext;
/**
@@ -120,6 +122,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.
@@ -190,6 +193,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);
+ }
+
pthread_mutex_lock(&p->progress_mutex);
#if 0 //BUFREF-FIXME
for (i = 0; i < MAX_BUFFERS; i++)
@@ -443,7 +451,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.
@@ -451,9 +463,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.
@@ -464,8 +478,10 @@ int ff_thread_decode_frame(AVCodecContext *avctx,
if (fctx->delaying) {
*got_picture_ptr=0;
- if (avpkt->size)
- return avpkt->size;
+ if (avpkt->size) {
+ ret = avpkt->size;
+ goto finish;
+ }
}
/*
@@ -515,10 +531,15 @@ int ff_thread_decode_frame(AVCodecContext *avctx,
* Otherwise the error can get lost.
*/
if (!avpkt->size && !*got_picture_ptr)
- return err;
+ goto finish;
/* 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)
@@ -573,6 +594,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);
if(atomic_load(&p->state) == STATE_SETUP_FINISHED){
av_log(avctx, AV_LOG_WARNING, "Multiple ff_thread_finish_setup() calls\n");
@@ -589,6 +617,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];
@@ -600,6 +630,8 @@ static void park_frame_worker_threads(FrameThreadContext *fctx, int thread_count
}
p->got_frame = 0;
}
+
+ pthread_mutex_lock(&fctx->async_mutex);
}
void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
@@ -663,6 +695,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);
if (avctx->priv_data && avctx->codec && avctx->codec->priv_class)
@@ -710,6 +746,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++) {
diff --git a/libavcodec/vaapi_h264.c b/libavcodec/vaapi_h264.c
index 44e8462522..30e7026ccf 100644
--- a/libavcodec/vaapi_h264.c
+++ b/libavcodec/vaapi_h264.c
@@ -22,6 +22,7 @@
#include "h264dec.h"
#include "h264_ps.h"
+#include "hwaccel.h"
#include "vaapi_decode.h"
/**
@@ -399,4 +400,5 @@ AVHWAccel ff_h264_vaapi_hwaccel = {
.init = &ff_vaapi_decode_init,
.uninit = &ff_vaapi_decode_uninit,
.priv_data_size = sizeof(VAAPIDecodeContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
diff --git a/libavcodec/vaapi_mpeg2.c b/libavcodec/vaapi_mpeg2.c
index b2417ee830..0d197c9692 100644
--- a/libavcodec/vaapi_mpeg2.c
+++ b/libavcodec/vaapi_mpeg2.c
@@ -20,6 +20,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "hwaccel.h"
#include "mpegutils.h"
#include "mpegvideo.h"
#include "internal.h"
@@ -183,4 +184,5 @@ AVHWAccel ff_mpeg2_vaapi_hwaccel = {
.init = &ff_vaapi_decode_init,
.uninit = &ff_vaapi_decode_uninit,
.priv_data_size = sizeof(VAAPIDecodeContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
diff --git a/libavcodec/vaapi_mpeg4.c b/libavcodec/vaapi_mpeg4.c
index b00f73dce1..f8c5ddf209 100644
--- a/libavcodec/vaapi_mpeg4.c
+++ b/libavcodec/vaapi_mpeg4.c
@@ -21,6 +21,7 @@
*/
#include "h263.h"
+#include "hwaccel.h"
#include "internal.h"
#include "mpeg4video.h"
#include "mpegvideo.h"
@@ -189,6 +190,7 @@ AVHWAccel ff_mpeg4_vaapi_hwaccel = {
.init = &ff_vaapi_decode_init,
.uninit = &ff_vaapi_decode_uninit,
.priv_data_size = sizeof(VAAPIDecodeContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
#endif
@@ -205,5 +207,6 @@ AVHWAccel ff_h263_vaapi_hwaccel = {
.init = &ff_vaapi_decode_init,
.uninit = &ff_vaapi_decode_uninit,
.priv_data_size = sizeof(VAAPIDecodeContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
#endif
diff --git a/libavcodec/vaapi_vc1.c b/libavcodec/vaapi_vc1.c
index a456149e6e..30c9ed3c8b 100644
--- a/libavcodec/vaapi_vc1.c
+++ b/libavcodec/vaapi_vc1.c
@@ -20,6 +20,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "hwaccel.h"
#include "internal.h"
#include "vaapi_decode.h"
#include "vc1.h"
@@ -399,6 +400,7 @@ AVHWAccel ff_wmv3_vaapi_hwaccel = {
.init = &ff_vaapi_decode_init,
.uninit = &ff_vaapi_decode_uninit,
.priv_data_size = sizeof(VAAPIDecodeContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
#endif
@@ -414,4 +416,5 @@ AVHWAccel ff_vc1_vaapi_hwaccel = {
.init = &ff_vaapi_decode_init,
.uninit = &ff_vaapi_decode_uninit,
.priv_data_size = sizeof(VAAPIDecodeContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
diff --git a/libavcodec/vdpau_h264.c b/libavcodec/vdpau_h264.c
index 7265af2890..be6ba71433 100644
--- a/libavcodec/vdpau_h264.c
+++ b/libavcodec/vdpau_h264.c
@@ -27,6 +27,7 @@
#include "internal.h"
#include "h264dec.h"
#include "h264_ps.h"
+#include "hwaccel.h"
#include "mpegutils.h"
#include "vdpau.h"
#include "vdpau_internal.h"
@@ -273,4 +274,5 @@ AVHWAccel ff_h264_vdpau_hwaccel = {
.init = vdpau_h264_init,
.uninit = ff_vdpau_common_uninit,
.priv_data_size = sizeof(VDPAUContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
diff --git a/libavcodec/vdpau_hevc.c b/libavcodec/vdpau_hevc.c
index ce2610f67f..ee93b3a5e8 100644
--- a/libavcodec/vdpau_hevc.c
+++ b/libavcodec/vdpau_hevc.c
@@ -25,6 +25,7 @@
#include "avcodec.h"
#include "internal.h"
#include "hevc.h"
+#include "hwaccel.h"
#include "vdpau.h"
#include "vdpau_internal.h"
@@ -423,4 +424,5 @@ AVHWAccel ff_hevc_vdpau_hwaccel = {
.init = vdpau_hevc_init,
.uninit = ff_vdpau_common_uninit,
.priv_data_size = sizeof(VDPAUContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
diff --git a/libavcodec/vdpau_mpeg12.c b/libavcodec/vdpau_mpeg12.c
index 3ac2cb827d..b657007ee7 100644
--- a/libavcodec/vdpau_mpeg12.c
+++ b/libavcodec/vdpau_mpeg12.c
@@ -24,6 +24,7 @@
#include <vdpau/vdpau.h>
#include "avcodec.h"
+#include "hwaccel.h"
#include "mpegvideo.h"
#include "vdpau.h"
#include "vdpau_internal.h"
@@ -114,6 +115,7 @@ AVHWAccel ff_mpeg1_vdpau_hwaccel = {
.init = vdpau_mpeg1_init,
.uninit = ff_vdpau_common_uninit,
.priv_data_size = sizeof(VDPAUContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
#endif
@@ -148,5 +150,6 @@ AVHWAccel ff_mpeg2_vdpau_hwaccel = {
.init = vdpau_mpeg2_init,
.uninit = ff_vdpau_common_uninit,
.priv_data_size = sizeof(VDPAUContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
#endif
diff --git a/libavcodec/vdpau_mpeg4.c b/libavcodec/vdpau_mpeg4.c
index 46a00cb27c..bbdd843a44 100644
--- a/libavcodec/vdpau_mpeg4.c
+++ b/libavcodec/vdpau_mpeg4.c
@@ -24,6 +24,7 @@
#include <vdpau/vdpau.h>
#include "avcodec.h"
+#include "hwaccel.h"
#include "mpeg4video.h"
#include "vdpau.h"
#include "vdpau_internal.h"
@@ -121,4 +122,5 @@ AVHWAccel ff_mpeg4_vdpau_hwaccel = {
.init = vdpau_mpeg4_init,
.uninit = ff_vdpau_common_uninit,
.priv_data_size = sizeof(VDPAUContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
diff --git a/libavcodec/vdpau_vc1.c b/libavcodec/vdpau_vc1.c
index ffd6505d13..665a2333f4 100644
--- a/libavcodec/vdpau_vc1.c
+++ b/libavcodec/vdpau_vc1.c
@@ -24,6 +24,7 @@
#include <vdpau/vdpau.h>
#include "avcodec.h"
+#include "hwaccel.h"
#include "vc1.h"
#include "vdpau.h"
#include "vdpau_internal.h"
@@ -147,6 +148,7 @@ AVHWAccel ff_wmv3_vdpau_hwaccel = {
.init = vdpau_vc1_init,
.uninit = ff_vdpau_common_uninit,
.priv_data_size = sizeof(VDPAUContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
#endif
@@ -162,4 +164,5 @@ AVHWAccel ff_vc1_vdpau_hwaccel = {
.init = vdpau_vc1_init,
.uninit = ff_vdpau_common_uninit,
.priv_data_size = sizeof(VDPAUContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};