From 5892b60e1f3a7c143b96fb55160df48113e45cd8 Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Mon, 22 Apr 2013 11:28:20 +0200 Subject: [PATCH] Lavd: use single-threaded decoder if MT broken --- src/libavcodec_common.h | 2 ++ src/video_decompress/libavcodec.c | 38 ++++++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/libavcodec_common.h b/src/libavcodec_common.h index 4a2cd3693..40532c153 100644 --- a/src/libavcodec_common.h +++ b/src/libavcodec_common.h @@ -22,6 +22,8 @@ #define AV_CODEC_ID_H264 CODEC_ID_H264 #define AV_CODEC_ID_MJPEG CODEC_ID_MJPEG #define AV_CODEC_ID_VP8 CODEC_ID_VP8 +#define AVPixelFormat PixelFormat +#define AVCodecID CodecID #endif #define LAVCD_LOCK_NAME "lavcd_lock" diff --git a/src/video_decompress/libavcodec.c b/src/video_decompress/libavcodec.c index b47e1049d..73fa556f9 100644 --- a/src/video_decompress/libavcodec.c +++ b/src/video_decompress/libavcodec.c @@ -73,6 +73,10 @@ struct state_libavcodec_decompress { codec_t out_codec; int last_frame_seq; + + struct video_desc saved_desc; + unsigned int warning_displayed; + bool uses_single_threaded_decoder; }; static void yuv420p_to_yuv422(char *dst_buffer, AVFrame *in_frame, @@ -85,6 +89,9 @@ static void yuv420p_to_rgb24(char *dst_buffer, AVFrame *in_frame, int width, int height, int pitch); static int change_pixfmt(AVFrame *frame, unsigned char *dst, int av_codec, codec_t out_codec, int width, int height, int pitch); +static void error_callback(void *, int, const char *, va_list); + +static bool broken_h264_mt_decoding = false; static void deconfigure(struct state_libavcodec_decompress *s) { @@ -135,13 +142,12 @@ static bool configure_with(struct state_libavcodec_decompress *s, // zero should mean count equal to the number of virtual cores if(s->codec->capabilities & CODEC_CAP_SLICE_THREADS) { - if(desc.color_spec == H264 && avcodec_version() >> 16 == 53 && - ((avcodec_version() >> 8) & 0xff) == 35) { - fprintf(stderr, "Libavcodec 53.35 has some issues with multithreaded H.264 " - "decoding. Disabling it. Please upgrade your libavcodec.\n"); - } else { + if(!broken_h264_mt_decoding) { s->codec_ctx->thread_count = 0; // == X264_THREADS_AUTO, perhaps same for other codecs s->codec_ctx->thread_type = FF_THREAD_SLICE; + s->uses_single_threaded_decoder = false; + } else { + s->uses_single_threaded_decoder = true; } } else { fprintf(stderr, "[lavd] Warning: Codec doesn't support slice-based multithreading.\n"); @@ -175,6 +181,7 @@ static bool configure_with(struct state_libavcodec_decompress *s, av_init_packet(&s->pkt); s->last_frame_seq = -1; + s->saved_desc = desc; return true; } @@ -184,7 +191,7 @@ void * libavcodec_decompress_init(void) struct state_libavcodec_decompress *s; s = (struct state_libavcodec_decompress *) - malloc(sizeof(struct state_libavcodec_decompress)); + calloc(1, sizeof(struct state_libavcodec_decompress)); s->global_lavcd_lock = rm_acquire_shared_lock(LAVCD_LOCK_NAME); @@ -199,6 +206,8 @@ void * libavcodec_decompress_init(void) s->pkt.data = NULL; s->pkt.size = 0; + av_log_set_callback(error_callback); + return s; } @@ -397,6 +406,13 @@ static int change_pixfmt(AVFrame *frame, unsigned char *dst, int av_codec, return TRUE; } +static void error_callback(void *ptr, int level, const char *fmt, va_list vl) { + if(strcmp("unset current_picture_ptr on %d. slice\n", fmt) == 0) + broken_h264_mt_decoding = true; + av_log_default_callback(ptr, level, fmt, vl); +} + + int libavcodec_decompress(void *state, unsigned char *dst, unsigned char *src, unsigned int src_len, int frame_seq) { @@ -463,6 +479,16 @@ int libavcodec_decompress(void *state, unsigned char *dst, unsigned char *src, } } + if(broken_h264_mt_decoding) { + if(!s->uses_single_threaded_decoder) { + libavcodec_decompress_reconfigure(s, s->saved_desc, + s->rshift, s->gshift, s->bshift, s->pitch, s->out_codec); + } + if(s->warning_displayed++ % 100 == 0) + av_log(NULL, AV_LOG_WARNING, "Broken multi-threaded decoder detected, " + "switching to a single-threaded one! Consider upgrading your Libavcodec.\n"); + } + return res; }