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@gmx.de>
This commit is contained in:
parent
8067f55edf
commit
c10d498bfd
@ -64,7 +64,7 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx)
|
|||||||
if (avctx->codec->id == AV_CODEC_ID_MSS2)
|
if (avctx->codec->id == AV_CODEC_ID_MSS2)
|
||||||
avctx->pix_fmt = AV_PIX_FMT_YUV420P;
|
avctx->pix_fmt = AV_PIX_FMT_YUV420P;
|
||||||
else
|
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;
|
s->unrestricted_mv= 1;
|
||||||
|
|
||||||
/* select sub codec */
|
/* select sub codec */
|
||||||
|
@ -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++)
|
for (i=0; fmt[i] != AV_PIX_FMT_NONE; i++)
|
||||||
if (fmt[i] == h->avctx->pix_fmt && !force_callback)
|
if (fmt[i] == h->avctx->pix_fmt && !force_callback)
|
||||||
return fmt[i];
|
return fmt[i];
|
||||||
return h->avctx->get_format(h->avctx, fmt);
|
return ff_thread_get_format(h->avctx, fmt);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1131,7 +1131,7 @@ static enum AVPixelFormat mpeg_get_pixelformat(AVCodecContext *avctx)
|
|||||||
MpegEncContext *s = &s1->mpeg_enc_ctx;
|
MpegEncContext *s = &s1->mpeg_enc_ctx;
|
||||||
|
|
||||||
if(s->chroma_format < 2) {
|
if(s->chroma_format < 2) {
|
||||||
return avctx->get_format(avctx,
|
return ff_thread_get_format(avctx,
|
||||||
avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO ?
|
avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO ?
|
||||||
mpeg1_hwaccel_pixfmt_list_420 :
|
mpeg1_hwaccel_pixfmt_list_420 :
|
||||||
mpeg2_hwaccel_pixfmt_list_420);
|
mpeg2_hwaccel_pixfmt_list_420);
|
||||||
|
@ -119,6 +119,10 @@ typedef struct PerThreadContext {
|
|||||||
* Set when the codec calls get_buffer().
|
* Set when the codec calls get_buffer().
|
||||||
* State is returned to STATE_SETTING_UP afterwards.
|
* 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_SETUP_FINISHED ///< Set after the codec has called ff_thread_finish_setup().
|
||||||
} state;
|
} state;
|
||||||
|
|
||||||
@ -132,6 +136,9 @@ typedef struct PerThreadContext {
|
|||||||
|
|
||||||
AVFrame *requested_frame; ///< AVFrame the codec passed to get_buffer()
|
AVFrame *requested_frame; ///< AVFrame the codec passed to get_buffer()
|
||||||
int requested_flags; ///< flags passed to get_buffer() for requested_frame
|
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;
|
} PerThreadContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -586,17 +593,29 @@ static int submit_packet(PerThreadContext *p, AVPacket *avpkt)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (!p->avctx->thread_safe_callbacks && (
|
if (!p->avctx->thread_safe_callbacks && (
|
||||||
|
p->avctx->get_format != avcodec_default_get_format ||
|
||||||
#if FF_API_GET_BUFFER
|
#if FF_API_GET_BUFFER
|
||||||
p->avctx->get_buffer ||
|
p->avctx->get_buffer ||
|
||||||
#endif
|
#endif
|
||||||
p->avctx->get_buffer2 != avcodec_default_get_buffer2)) {
|
p->avctx->get_buffer2 != avcodec_default_get_buffer2)) {
|
||||||
while (p->state != STATE_SETUP_FINISHED && p->state != STATE_INPUT_READY) {
|
while (p->state != STATE_SETUP_FINISHED && p->state != STATE_INPUT_READY) {
|
||||||
|
int call_done = 1;
|
||||||
pthread_mutex_lock(&p->progress_mutex);
|
pthread_mutex_lock(&p->progress_mutex);
|
||||||
while (p->state == STATE_SETTING_UP)
|
while (p->state == STATE_SETTING_UP)
|
||||||
pthread_cond_wait(&p->progress_cond, &p->progress_mutex);
|
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);
|
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;
|
p->state = STATE_SETTING_UP;
|
||||||
pthread_cond_signal(&p->progress_cond);
|
pthread_cond_signal(&p->progress_cond);
|
||||||
}
|
}
|
||||||
@ -1018,6 +1037,32 @@ static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int
|
|||||||
return err;
|
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 ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags)
|
||||||
{
|
{
|
||||||
int ret = thread_get_buffer_internal(avctx, f, flags);
|
int ret = thread_get_buffer_internal(avctx, f, flags);
|
||||||
|
@ -97,6 +97,16 @@ void ff_thread_report_progress(ThreadFrame *f, int progress, int field);
|
|||||||
*/
|
*/
|
||||||
void ff_thread_await_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.
|
* Wrapper around get_buffer() for frame-multithreaded codecs.
|
||||||
* Call this function instead of ff_get_buffer(f).
|
* Call this function instead of ff_get_buffer(f).
|
||||||
|
@ -3034,6 +3034,11 @@ int ff_thread_ref_frame(ThreadFrame *dst, ThreadFrame *src)
|
|||||||
|
|
||||||
#if !HAVE_THREADS
|
#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)
|
int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags)
|
||||||
{
|
{
|
||||||
f->owner = avctx;
|
f->owner = avctx;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user