1 /*
2  * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3  *
4  * This source code is subject to the terms of the BSD 2 Clause License and
5  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6  * was not distributed with this source code in the LICENSE file, you can
7  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8  * Media Patent License 1.0 was not distributed with this source code in the
9  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10  */
11 
12 #include "common/warnings.h"
13 
14 #include <assert.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 
19 #include "aom/aom_encoder.h"
20 #include "apps/aomenc.h"
21 #include "common/tools_common.h"
22 
23 static const char quantizer_warning_string[] =
24     "Bad quantizer values. Quantizer values should not be equal, and should "
25     "differ by at least 8.";
26 
27 struct WarningListNode {
28   const char *warning_string;
29   struct WarningListNode *next_warning;
30 };
31 
32 struct WarningList {
33   struct WarningListNode *warning_node;
34 };
35 
add_warning(const char * warning_string,struct WarningList * warning_list)36 static void add_warning(const char *warning_string,
37                         struct WarningList *warning_list) {
38   struct WarningListNode **node = &warning_list->warning_node;
39 
40   struct WarningListNode *new_node = malloc(sizeof(*new_node));
41   if (new_node == NULL) {
42     fatal("Unable to allocate warning node.");
43   }
44 
45   new_node->warning_string = warning_string;
46   new_node->next_warning = NULL;
47 
48   while (*node != NULL) node = &(*node)->next_warning;
49 
50   *node = new_node;
51 }
52 
free_warning_list(struct WarningList * warning_list)53 static void free_warning_list(struct WarningList *warning_list) {
54   while (warning_list->warning_node != NULL) {
55     struct WarningListNode *const node = warning_list->warning_node;
56     warning_list->warning_node = node->next_warning;
57     free(node);
58   }
59 }
60 
continue_prompt(int num_warnings)61 static int continue_prompt(int num_warnings) {
62   int c;
63   fprintf(stderr,
64           "%d encoder configuration warning(s). Continue? (y to continue) ",
65           num_warnings);
66   c = getchar();
67   return c == 'y';
68 }
69 
check_quantizer(int min_q,int max_q,struct WarningList * warning_list)70 static void check_quantizer(int min_q, int max_q,
71                             struct WarningList *warning_list) {
72   const int lossless = min_q == 0 && max_q == 0;
73   if (!lossless && (min_q == max_q || abs(max_q - min_q) < 8))
74     add_warning(quantizer_warning_string, warning_list);
75 }
76 
check_encoder_config(int disable_prompt,const struct AvxEncoderConfig * global_config,const struct aom_codec_enc_cfg * stream_config)77 void check_encoder_config(int disable_prompt,
78                           const struct AvxEncoderConfig *global_config,
79                           const struct aom_codec_enc_cfg *stream_config) {
80   int num_warnings = 0;
81   struct WarningListNode *warning = NULL;
82   struct WarningList warning_list = { 0 };
83   (void)global_config;
84   check_quantizer(stream_config->rc_min_quantizer,
85                   stream_config->rc_max_quantizer, &warning_list);
86   /* Count and print warnings. */
87   for (warning = warning_list.warning_node; warning != NULL;
88        warning = warning->next_warning, ++num_warnings) {
89     warn(warning->warning_string);
90   }
91 
92   free_warning_list(&warning_list);
93 
94   if (num_warnings) {
95     if (!disable_prompt && !continue_prompt(num_warnings)) exit(EXIT_FAILURE);
96   }
97 }
98