From 5b93c38c2cf2e22f25b07155d90f3da492706cf4 Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Mon, 22 Jun 2015 18:34:38 +0200 Subject: [PATCH] Libavcodec: option to enable/disable thread mode For compatibility between old and new libavcodec (latter supports JPEG slices). --- src/video_compress/libavcodec.cpp | 51 +++++++++++++++++++------------ src/video_decompress/libavcodec.c | 23 ++++++++------ 2 files changed, 44 insertions(+), 30 deletions(-) diff --git a/src/video_compress/libavcodec.cpp b/src/video_compress/libavcodec.cpp index 4ad20e107..ad0d1ea40 100644 --- a/src/video_compress/libavcodec.cpp +++ b/src/video_compress/libavcodec.cpp @@ -58,16 +58,17 @@ #include "video.h" #include "video_compress.h" +#include #include #include #define DEFAULT_CODEC MJPG #define DEFAULT_X264_PRESET "superfast" -namespace { - using namespace std; +namespace { + struct setparam_param { AVCodec *codec; bool have_preset; @@ -75,6 +76,7 @@ struct setparam_param { bool interlaced; bool h264_no_periodic_intra; int cpu_count; + string threads; }; typedef struct { @@ -180,7 +182,7 @@ static void usage() { printf("Libavcodec encoder usage:\n"); printf("\t-c libavcodec[:codec=][:bitrate=|:bpp=]" "[:subsampling=][:preset=]" - "[:h264_no_periodic_intra]\n"); + "[:h264_no_periodic_intra][:threads=]\n"); printf("\t\t may be specified codec name (default MJPEG), supported codecs:\n"); for (auto && param : codec_params) { if(param.second.av_codec != 0) { @@ -194,9 +196,10 @@ static void usage() { } printf("\t\th264_no_periodic_intra - do not use Periodic Intra Refresh with H.264\n"); printf("\t\t specifies requested bitrate\n"); + printf("\t\t\t0 means codec default (same as when parameter omitted)\n"); printf("\t\t may be one of 444, 422, or 420, default 420 for progresive, 422 for interlaced\n"); printf("\t\t codec preset options, eg. ultrafast, superfast, medium etc. for H.264\n"); - printf("\t\t\t0 means codec default (same as when parameter omitted)\n"); + printf("\t\t can be one of \"no\", \"frame\" or \"slice\"\n"); } static int parse_fmt(struct state_video_compress_libav *s, char *fmt) { @@ -233,6 +236,9 @@ static int parse_fmt(struct state_video_compress_libav *s, char *fmt) { s->preset = strdup(preset); } else if (strcasecmp("h264_no_periodic_intra", item) == 0) { s->params.h264_no_periodic_intra = true; + } else if(strncasecmp("threads=", item, strlen("threads=")) == 0) { + char *threads = item + strlen("threads="); + s->params.threads = threads; } else { fprintf(stderr, "[lavc] Error: unknown option %s.\n", item); @@ -259,7 +265,7 @@ struct module * libavcodec_compress_init(struct module *parent, const struct vid struct state_video_compress_libav *s; const char *opts = params->cfg; - s = (struct state_video_compress_libav *) calloc(1, sizeof(struct state_video_compress_libav)); + s = new state_video_compress_libav(); s->lavcd_global_lock = rm_acquire_shared_lock(LAVCD_LOCK_NAME); if (verbose) { av_log_set_level(AV_LOG_VERBOSE); @@ -283,7 +289,7 @@ struct module * libavcodec_compress_init(struct module *parent, const struct vid int ret = parse_fmt(s, fmt); free(fmt); if(ret != 0) { - free(s); + delete s; if(ret > 0) return &compress_init_noerr; else @@ -791,26 +797,31 @@ static void libavcodec_compress_done(struct module *mod) av_free(s->in_frame_part[i]); } free(s->in_frame_part); - free(s); + delete s; } static void setparam_default(AVCodecContext *codec_ctx, struct setparam_param *param) { - UNUSED(param); - // zero should mean count equal to the number of virtual cores - if(param->codec->capabilities & CODEC_CAP_SLICE_THREADS) { - codec_ctx->thread_count = 0; - codec_ctx->thread_type = FF_THREAD_SLICE; - } else { - fprintf(stderr, "[Lavc] Warning: Codec doesn't support slice-based multithreading.\n"); -#if 0 - if(codec->capabilities & CODEC_CAP_FRAME_THREADS) { - codec_ctx->thread_count = 0; - codec_ctx->thread_type = FF_THREAD_FRAME; + if (param->threads != "no") { + if (param->threads.empty() // default mode + || param->threads == "slice") { + // zero should mean count equal to the number of virtual cores + if (param->codec->capabilities & CODEC_CAP_SLICE_THREADS) { + codec_ctx->thread_count = 0; + codec_ctx->thread_type = FF_THREAD_SLICE; + } else { + fprintf(stderr, "[Lavc] Warning: Codec doesn't support slice-based multithreading.\n"); + } + } else if (param->threads == "frame") { + if (param->codec->capabilities & CODEC_CAP_FRAME_THREADS) { + codec_ctx->thread_count = 0; + codec_ctx->thread_type = FF_THREAD_FRAME; + } else { + fprintf(stderr, "[Lavc] Warning: Codec doesn't support frame-based multithreading.\n"); + } } else { - fprintf(stderr, "[Lavc] Warning: Codec doesn't support frame-based multithreading.\n"); + fprintf(stderr, "[Lavc] Warning: unknown thread mode: %s.\n", param->threads.c_str()); } -#endif } } diff --git a/src/video_decompress/libavcodec.c b/src/video_decompress/libavcodec.c index 51e42f39e..223eea2f6 100644 --- a/src/video_decompress/libavcodec.c +++ b/src/video_decompress/libavcodec.c @@ -481,19 +481,22 @@ int libavcodec_decompress(void *state, unsigned char *dst, unsigned char *src, * correctly. So we assume that the decompression went good even with the * reported error. */ - if(len < 0 && s->in_codec == JPEG) { - // this hack doesn;t seem to work in recent Libav versions + if (len < 0) { + if (s->in_codec == JPEG) { + // this hack doesn;t seem to work in recent Libav versions #if 0 - return change_pixfmt(s->frame, dst, s->codec_ctx->pix_fmt, - s->out_codec, s->width, s->height, s->pitch); + return change_pixfmt(s->frame, dst, s->codec_ctx->pix_fmt, + s->out_codec, s->width, s->height, s->pitch); #else - fprintf(stderr, "[lavd] Perhaps JPEG restart interval >0 set? (Not supported by lavd, try '-c JPEG:90:0' on sender).\n"); + fprintf(stderr, "[lavd] Perhaps JPEG restart interval >0 set? (Not supported by lavd, try '-c JPEG:90:0' on sender).\n"); #endif - } - - if(len < 0) { - fprintf(stderr, "[lavd] Error while decoding frame.\n"); - return FALSE; + } else if (s->in_codec == MJPG) { + fprintf(stderr, "[lavd] Perhaps old libavcodec without slices support? (Try '-c libavcodec:codec=MJPEG:threads=no' on sender).\n"); + return FALSE; + } else { + fprintf(stderr, "[lavd] Error while decoding frame.\n"); + return FALSE; + } } if(got_frame) {