summaryrefslogtreecommitdiffstats
path: root/package/ffmpeg/0014-fix-ff-thread-get-format.patch
blob: 8e7e3395137a5f1e07e744a8e32e114854f6d2e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
From b52c216539bdbee830e0d306b372037d4e0cb35f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Reimar=20D=C3=B6ffinger?= <Reimar.Doeffinger@gmx.de>
Date: Sun, 8 Mar 2015 19:44:12 +0100
Subject: [PATCH] pthread: Fix ff_thread_get_format issues when called outside
 frame decode

Patch part of the XBMC patch set for ffmpeg, downloaded from
https://github.com/xbmc/FFmpeg/.

Signed-off-by: Bernd Kuhls <bernd.kuhls@t-online.de>
---
 libavcodec/pthread_frame.c | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index 5a4ab84..c29d0a9 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -53,6 +53,7 @@
  * Context used by codec threads and stored in their AVCodecInternal thread_ctx.
  */
 typedef struct PerThreadContext {
+    int main_thread;
     struct FrameThreadContext *parent;
 
     pthread_t      thread;
@@ -83,7 +84,8 @@ typedef struct PerThreadContext {
                                      * Set when the codec calls get_format().
                                      * State is returned to STATE_SETTING_UP afterwards.
                                      */
-        STATE_SETUP_FINISHED        ///< Set after the codec has called ff_thread_finish_setup().
+        STATE_SETUP_FINISHED,       ///< Set after the codec has called ff_thread_finish_setup().
+        STATE_UPDATE_CONTEXT,       ///< Main thread is updating its context
     } state;
 
     /**
@@ -105,6 +107,7 @@ typedef struct PerThreadContext {
  * Context stored in the client AVCodecInternal thread_ctx.
  */
 typedef struct FrameThreadContext {
+    int main_thread;
     PerThreadContext *threads;     ///< The contexts for each thread.
     PerThreadContext *prev_thread; ///< The last thread submit_packet() was called on.
 
@@ -143,6 +146,7 @@ static attribute_align_arg void *frame_worker_thread(void *arg)
     AVCodecContext *avctx = p->avctx;
     const AVCodec *codec = avctx->codec;
 
+    av_assert0(!p->main_thread);
     pthread_mutex_lock(&p->mutex);
     while (1) {
             while (p->state == STATE_INPUT_READY && !fctx->die)
@@ -330,6 +334,8 @@ static int submit_packet(PerThreadContext *p, AVPacket *avpkt)
 
     pthread_mutex_lock(&p->mutex);
 
+    p->state = STATE_UPDATE_CONTEXT;
+
     release_delayed_buffers(p);
 
     if (prev_thread) {
@@ -408,6 +414,7 @@ int ff_thread_decode_frame(AVCodecContext *avctx,
     int finished = fctx->next_finished;
     PerThreadContext *p;
     int err;
+    av_assert0(fctx->main_thread);
 
     /*
      * Submit a packet to the next decoding thread.
@@ -515,6 +522,7 @@ void ff_thread_finish_setup(AVCodecContext *avctx) {
 
     if (!(avctx->active_thread_type&FF_THREAD_FRAME)) return;
 
+    av_assert0(!p->main_thread);
     if(p->state == STATE_SETUP_FINISHED){
         av_log(avctx, AV_LOG_WARNING, "Multiple ff_thread_finish_setup() calls\n");
     }
@@ -549,6 +557,7 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
     const AVCodec *codec = avctx->codec;
     int i;
 
+    av_assert0(fctx->main_thread);
     park_frame_worker_threads(fctx, thread_count);
 
     if (fctx->prev_thread && fctx->prev_thread != fctx->threads)
@@ -634,6 +643,7 @@ int ff_frame_thread_init(AVCodecContext *avctx)
     }
 
     avctx->internal->thread_ctx = fctx = av_mallocz(sizeof(FrameThreadContext));
+    fctx->main_thread = 1;
 
     fctx->threads = av_mallocz_array(thread_count, sizeof(PerThreadContext));
     pthread_mutex_init(&fctx->buffer_mutex, NULL);
@@ -718,6 +728,7 @@ void ff_thread_flush(AVCodecContext *avctx)
 
     if (!fctx) return;
 
+    av_assert0(fctx->main_thread);
     park_frame_worker_threads(fctx, avctx->thread_count);
     if (fctx->prev_thread) {
         if (fctx->prev_thread != &fctx->threads[0])
@@ -743,7 +754,10 @@ void ff_thread_flush(AVCodecContext *avctx)
 int ff_thread_can_start_frame(AVCodecContext *avctx)
 {
     PerThreadContext *p = avctx->internal->thread_ctx;
-    if ((avctx->active_thread_type&FF_THREAD_FRAME) && p->state != STATE_SETTING_UP &&
+    if (!(avctx->active_thread_type&FF_THREAD_FRAME))
+        return 1;
+    av_assert0(!p->main_thread);
+    if (p->state != STATE_SETTING_UP &&
         (avctx->codec->update_thread_context || !THREAD_SAFE_CALLBACKS(avctx))) {
         return 0;
     }
@@ -762,6 +776,7 @@ static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int
     if (!(avctx->active_thread_type & FF_THREAD_FRAME))
         return ff_get_buffer(avctx, f->f, flags);
 
+    av_assert0(!p->main_thread);
     if (p->state != STATE_SETTING_UP &&
         (avctx->codec->update_thread_context || !THREAD_SAFE_CALLBACKS(avctx))) {
         av_log(avctx, AV_LOG_ERROR, "get_buffer() cannot be called after ff_thread_finish_setup()\n");
@@ -819,7 +834,8 @@ enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixe
     enum AVPixelFormat res;
     PerThreadContext *p = avctx->internal->thread_ctx;
     if (!(avctx->active_thread_type & FF_THREAD_FRAME) || avctx->thread_safe_callbacks ||
-        avctx->get_format == avcodec_default_get_format)
+        avctx->get_format == avcodec_default_get_format ||
+        p->main_thread || p->state == STATE_UPDATE_CONTEXT)
         return ff_get_format(avctx, fmt);
     if (p->state != STATE_SETTING_UP) {
         av_log(avctx, AV_LOG_ERROR, "get_format() cannot be called after ff_thread_finish_setup()\n");
OpenPOWER on IntegriCloud