[FFmpeg-cvslog] Add thread-safe wrapper for get_format().
Reimar Döffinger
git at videolan.org
Mon Apr 15 09:04:40 CEST 2013
ffmpeg | branch: master | Reimar Döffinger <Reimar.Doeffinger at gmx.de> | Sun Apr 7 10:17:09 2013 +0200| [c10d498bfd246a40cc7830838b74e18a79418839] | committer: Reimar Döffinger
Add thread-safe wrapper for get_format().
Just like get_buffer, get_format should not be called from a different
thread if thread_safe_callbacks is not set.
Signed-off-by: Reimar Döffinger <Reimar.Doeffinger at gmx.de>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=c10d498bfd246a40cc7830838b74e18a79418839
---
libavcodec/h263dec.c | 2 +-
libavcodec/h264.c | 2 +-
libavcodec/mpeg12dec.c | 2 +-
libavcodec/pthread.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
libavcodec/thread.h | 10 ++++++++++
libavcodec/utils.c | 5 +++++
6 files changed, 64 insertions(+), 4 deletions(-)
diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c
index 405d3c6..cc87bc7 100644
--- a/libavcodec/h263dec.c
+++ b/libavcodec/h263dec.c
@@ -64,7 +64,7 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx)
if (avctx->codec->id == AV_CODEC_ID_MSS2)
avctx->pix_fmt = AV_PIX_FMT_YUV420P;
else
- avctx->pix_fmt = avctx->get_format(avctx, avctx->codec->pix_fmts);
+ avctx->pix_fmt = ff_thread_get_format(avctx, avctx->codec->pix_fmts);
s->unrestricted_mv= 1;
/* select sub codec */
diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index b4df424..e5bab1b 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -3043,7 +3043,7 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
for (i=0; fmt[i] != AV_PIX_FMT_NONE; i++)
if (fmt[i] == h->avctx->pix_fmt && !force_callback)
return fmt[i];
- return h->avctx->get_format(h->avctx, fmt);
+ return ff_thread_get_format(h->avctx, fmt);
}
break;
default:
diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c
index 9221fc3..e969893 100644
--- a/libavcodec/mpeg12dec.c
+++ b/libavcodec/mpeg12dec.c
@@ -1131,7 +1131,7 @@ static enum AVPixelFormat mpeg_get_pixelformat(AVCodecContext *avctx)
MpegEncContext *s = &s1->mpeg_enc_ctx;
if(s->chroma_format < 2) {
- return avctx->get_format(avctx,
+ return ff_thread_get_format(avctx,
avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO ?
mpeg1_hwaccel_pixfmt_list_420 :
mpeg2_hwaccel_pixfmt_list_420);
diff --git a/libavcodec/pthread.c b/libavcodec/pthread.c
index 29a2308..7e33ba5 100644
--- a/libavcodec/pthread.c
+++ b/libavcodec/pthread.c
@@ -119,6 +119,10 @@ typedef struct PerThreadContext {
* Set when the codec calls get_buffer().
* State is returned to STATE_SETTING_UP afterwards.
*/
+ STATE_GET_FORMAT, /**<
+ * 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;
@@ -132,6 +136,9 @@ typedef struct PerThreadContext {
AVFrame *requested_frame; ///< AVFrame the codec passed to get_buffer()
int requested_flags; ///< flags passed to get_buffer() for requested_frame
+
+ const enum AVPixelFormat *available_formats; ///< Format array for get_format()
+ enum AVPixelFormat result_format; ///< get_format() result
} PerThreadContext;
/**
@@ -586,17 +593,29 @@ static int submit_packet(PerThreadContext *p, AVPacket *avpkt)
*/
if (!p->avctx->thread_safe_callbacks && (
+ p->avctx->get_format != avcodec_default_get_format ||
#if FF_API_GET_BUFFER
p->avctx->get_buffer ||
#endif
p->avctx->get_buffer2 != avcodec_default_get_buffer2)) {
while (p->state != STATE_SETUP_FINISHED && p->state != STATE_INPUT_READY) {
+ int call_done = 1;
pthread_mutex_lock(&p->progress_mutex);
while (p->state == STATE_SETTING_UP)
pthread_cond_wait(&p->progress_cond, &p->progress_mutex);
- if (p->state == STATE_GET_BUFFER) {
+ switch (p->state) {
+ case STATE_GET_BUFFER:
p->result = ff_get_buffer(p->avctx, p->requested_frame, p->requested_flags);
+ break;
+ case STATE_GET_FORMAT:
+ p->result_format = p->avctx->get_format(p->avctx, p->available_formats);
+ break;
+ default:
+ call_done = 0;
+ break;
+ }
+ if (call_done) {
p->state = STATE_SETTING_UP;
pthread_cond_signal(&p->progress_cond);
}
@@ -1018,6 +1037,32 @@ static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int
return err;
}
+enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt)
+{
+ enum AVPixelFormat res;
+ PerThreadContext *p = avctx->thread_opaque;
+ if (!(avctx->active_thread_type & FF_THREAD_FRAME) || avctx->thread_safe_callbacks ||
+ avctx->get_format == avcodec_default_get_format)
+ return avctx->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");
+ return -1;
+ }
+ pthread_mutex_lock(&p->progress_mutex);
+ p->available_formats = fmt;
+ p->state = STATE_GET_FORMAT;
+ pthread_cond_broadcast(&p->progress_cond);
+
+ while (p->state != STATE_SETTING_UP)
+ pthread_cond_wait(&p->progress_cond, &p->progress_mutex);
+
+ res = p->result_format;
+
+ pthread_mutex_unlock(&p->progress_mutex);
+
+ return res;
+}
+
int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags)
{
int ret = thread_get_buffer_internal(avctx, f, flags);
diff --git a/libavcodec/thread.h b/libavcodec/thread.h
index 24e62b4..0dc04e0 100644
--- a/libavcodec/thread.h
+++ b/libavcodec/thread.h
@@ -98,6 +98,16 @@ void ff_thread_report_progress(ThreadFrame *f, int progress, int field);
void ff_thread_await_progress(ThreadFrame *f, int progress, int field);
/**
+ * Wrapper around get_format() for frame-multithreaded codecs.
+ * Call this function instead of avctx->get_format().
+ * Cannot be called after the codec has called ff_thread_finish_setup().
+ *
+ * @param avctx The current context.
+ * @param fmt The list of available formats.
+ */
+enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt);
+
+/**
* Wrapper around get_buffer() for frame-multithreaded codecs.
* Call this function instead of ff_get_buffer(f).
* Cannot be called after the codec has called ff_thread_finish_setup().
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index e4ea325..034b54a 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -3034,6 +3034,11 @@ int ff_thread_ref_frame(ThreadFrame *dst, ThreadFrame *src)
#if !HAVE_THREADS
+enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt)
+{
+ return avctx->get_format(avctx, fmt);
+}
+
int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags)
{
f->owner = avctx;
More information about the ffmpeg-cvslog
mailing list