@@ -513,6 +513,36 @@ ranged_stod(const char *val, double min, double max) noexcept(false)
513513 return dbl;
514514}
515515
516+ /* *
517+ * @returns codec_t representation of val and ensures that the codec
518+ * will be possible to compress (known+encoder present)
519+ * @retval VC_NONE if either of above was not fulfilled (error already print)
520+ */
521+ static codec_t
522+ lavc_get_codec_check (const char *val)
523+ {
524+ codec_t ugc = get_codec_from_name (val);
525+ if (ugc == VC_NONE ) {
526+ MSG (ERROR , " Unable to find codec: \" %s\"\n " , val);
527+ return ugc;
528+ }
529+ enum AVCodecID avc = get_ug_to_av_codec (ugc);
530+ if (avc == AV_CODEC_ID_NONE ) {
531+ MSG (ERROR ,
532+ " No known mapping from %s to FFmpeg compression (either "
533+ " unsupporetd by FF or unimplemented by UG)!\n " ,
534+ get_codec_name (ugc));
535+ return VC_NONE ;
536+ }
537+ const AVCodec *codec = avcodec_find_encoder (avc);
538+ if (codec != nullptr ) {
539+ return ugc;
540+ }
541+ MSG (ERROR , " Codec %s supported by FFmpeg but no encoder found!\n " ,
542+ avcodec_get_name (avc));
543+ return VC_NONE ;
544+ }
545+
516546int
517547parse_fmt (struct state_video_compress_libav *s, char *fmt) noexcept (false )
518548{
@@ -531,21 +561,23 @@ parse_fmt(struct state_video_compress_libav *s, char *fmt) noexcept(false)
531561 char *item, *save_ptr = NULL ;
532562
533563 while ((item = strtok_r (fmt, " :" , &save_ptr)) != NULL ) {
564+ char *val = strchr (item, ' =' );
565+ if (val != nullptr ) {
566+ val += 1 ;
567+ }
534568 if (strcasecmp (" help" , item) == 0 || strcmp (item, " fullhelp" ) == 0 ) {
535569 show_help = strcmp (item, " fullhelp" ) == 0 ? HELP_FULL
536570 : HELP_NORMAL ;
537571 } else if (IS_KEY_PREFIX (item, " codec" )) {
538- const char *const codec = strchr (item, ' =' ) + 1 ;
539- s->requested_codec_id = get_codec_from_name (codec);
572+ s->requested_codec_id = lavc_get_codec_check (val);
540573 if (s->requested_codec_id == VIDEO_CODEC_NONE ) {
541- log_msg (LOG_LEVEL_ERROR , " [lavc] Unable to find codec: \" %s\"\n " , codec);
542574 return -1 ;
543575 }
544576 } else if (IS_KEY_PREFIX (item, " encoder" )) {
545- s->req_encoder = strchr (item, ' = ' ) + 1 ;
577+ s->req_encoder = val ;
546578 } else if (IS_KEY_PREFIX (item, " bitrate" )) {
547579 s->params .requested_bitrate =
548- unit_evaluate (strchr (item, ' = ' ) + 1 , nullptr );
580+ unit_evaluate (val , nullptr );
549581 if (s->params .requested_bitrate < 0 ) {
550582 return -1 ;
551583 }
@@ -564,10 +596,9 @@ parse_fmt(struct state_video_compress_libav *s, char *fmt) noexcept(false)
564596 if (strstr (item, " q=" ) == item) {
565597 log_msg (LOG_LEVEL_WARNING , MOD_NAME " Option \" q=\" is deprecated, use \" cqp=\" instead.\n " );
566598 }
567- s->params .requested_cqp = stoi (strchr (item, ' = ' ) + 1 );
599+ s->params .requested_cqp = stoi (val );
568600 } else if (IS_KEY_PREFIX (item, " subsampling" )) {
569- s->req_conv_prop .subsampling =
570- atoi (strchr (item, ' =' ) + 1 );
601+ s->req_conv_prop .subsampling = atoi (val);
571602 if (s->req_conv_prop .subsampling < 1000 ) {
572603 s->req_conv_prop .subsampling *= 10 ; // 420->4200
573604 }
@@ -578,23 +609,22 @@ parse_fmt(struct state_video_compress_libav *s, char *fmt) noexcept(false)
578609 return -1 ;
579610 }
580611 } else if (IS_KEY_PREFIX (item, " depth" )) {
581- s->req_conv_prop .depth = atoi (strchr (item, ' = ' ) + 1 );
612+ s->req_conv_prop .depth = atoi (val );
582613 } else if (strcasecmp (item, " rgb" ) == 0 || strcasecmp (item, " yuv" ) == 0 ) {
583614 s->req_conv_prop .rgb = strcasecmp (item, " rgb" ) == 0 ;
584615 } else if (strstr (item, " intra_refresh" ) != nullptr ) {
585616 s->params .periodic_intra = (int ) (strstr (item, " intra_refresh" ) == item);
586617 } else if (strstr (item, " interlaced_dct" ) != nullptr ) {
587618 s->params .interlaced_dct = (int ) (strstr (item, " interlaced_dct" ) == item);
588619 } else if (IS_KEY_PREFIX (item, " threads" )) {
589- char *threads = strchr (item, ' = ' ) + 1 ;
620+ char *threads = val ;
590621 if (strchr (threads, ' ,' )) {
591622 s->conv_thread_count = stoi (strchr (threads, ' ,' ) + 1 );
592623 *strchr (threads, ' ,' ) = ' \0 ' ;
593624 }
594625 s->params .thread_mode = threads;
595626 } else if (strncasecmp (" slices=" , item, strlen (" slices=" )) == 0 ) {
596- char *slices = strchr (item, ' =' ) + 1 ;
597- s->params .slices = stoi (slices);
627+ s->params .slices = stoi (val);
598628 } else if (strncasecmp (" gop=" , item, strlen (" gop=" )) == 0 ) {
599629 char *gop = item + strlen (" gop=" );
600630 s->requested_gop = atoi (gop);
@@ -1124,7 +1154,10 @@ const AVCodec *get_av_codec(struct state_video_compress_libav *s, codec_t *ug_co
11241154 return codec;
11251155 }
11261156 // Finally, try to open any encoder for requested codec
1127- return avcodec_find_encoder (get_ug_to_av_codec (*ug_codec));
1157+ const AVCodec *codec =
1158+ avcodec_find_encoder (get_ug_to_av_codec (*ug_codec));
1159+ assert (codec != nullptr ); // asserted by lavc_get_codec_check
1160+ return codec;
11281161}
11291162
11301163static bool configure_swscale (struct state_video_compress_libav *s, struct video_desc desc, enum AVPixelFormat sws_out_pixfmt) {
@@ -1218,7 +1251,6 @@ static bool configure_with(struct state_video_compress_libav *s, struct video_de
12181251 s->saved_desc = {};
12191252 codec_t ug_codec = s->requested_codec_id == VIDEO_CODEC_NONE ? DEFAULT_CODEC : s->requested_codec_id ;
12201253 AVPixelFormat pix_fmt = AV_PIX_FMT_NONE ;
1221- const AVCodec *codec = nullptr ;
12221254#ifdef HAVE_SWSCALE
12231255 sws_freeContext (s->sws_ctx );
12241256 s->sws_ctx = nullptr ;
@@ -1227,7 +1259,9 @@ static bool configure_with(struct state_video_compress_libav *s, struct video_de
12271259
12281260 s->params .desc = desc;
12291261
1230- if ((codec = get_av_codec (s, &ug_codec, codec_is_a_rgb (desc.color_spec ))) == nullptr ) {
1262+ const AVCodec *codec =
1263+ get_av_codec (s, &ug_codec, codec_is_a_rgb (desc.color_spec ));
1264+ if (codec == nullptr ) {
12311265 return false ;
12321266 }
12331267 log_msg (LOG_LEVEL_NOTICE , " [lavc] Using codec: %s, encoder: %s\n " ,
@@ -2438,16 +2472,18 @@ static void libavcodec_check_messages(struct state_video_compress_libav *s)
24382472 while ((msg = check_message (&s->module_data ))) {
24392473 struct msg_change_compress_data *data =
24402474 (struct msg_change_compress_data *) msg;
2441- struct response *r;
2442- if (parse_fmt (s, data->config_string ) == 0 ) {
2443- log_msg (LOG_LEVEL_NOTICE , " [Libavcodec] Compression successfully changed.\n " );
2444- r = new_response (RESPONSE_OK , NULL );
2445- } else {
2446- log_msg (LOG_LEVEL_ERROR , " [Libavcodec] Unable to change compression!\n " );
2447- r = new_response (RESPONSE_INT_SERV_ERR , NULL );
2475+ if (parse_fmt (s, data->config_string ) != 0 ) {
2476+ // NOTE: s->req_XY may not be now consistent with
2477+ // factual state, but we will not configure...
2478+ MSG (ERROR , " Unable to change compression!\n " );
2479+ free_message (msg,
2480+ new_response (RESPONSE_INT_SERV_ERR ,
2481+ " wrong compress setting!" ));
2482+ continue ;
24482483 }
2484+ MSG (NOTICE , " Compression successfully changed.\n " );
24492485 memset (&s->saved_desc , 0 , sizeof (s->saved_desc ));
2450- free_message (msg, r );
2486+ free_message (msg, new_response ( RESPONSE_OK , nullptr ) );
24512487 }
24522488
24532489}
0 commit comments