You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

251 lines
7.0KB

  1. /*
  2. * log functions
  3. * Copyright (c) 2003 Michel Bardiaux
  4. *
  5. * This file is part of Libav.
  6. *
  7. * Libav is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * Libav is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with Libav; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. /**
  22. * @file
  23. * logging functions
  24. */
  25. #include "config.h"
  26. #if HAVE_UNISTD_H
  27. #include <unistd.h>
  28. #endif
  29. #if HAVE_IO_H
  30. #include <io.h>
  31. #endif
  32. #include <stdarg.h>
  33. #include <stdlib.h>
  34. #include "avstring.h"
  35. #include "avutil.h"
  36. #include "common.h"
  37. #include "internal.h"
  38. #include "log.h"
  39. #if HAVE_VALGRIND_VALGRIND_H
  40. #include <valgrind/valgrind.h>
  41. /* this is the log level at which valgrind will output a full backtrace */
  42. #define BACKTRACE_LOGLEVEL AV_LOG_ERROR
  43. #endif
  44. static int av_log_level = AV_LOG_INFO;
  45. static int flags;
  46. #define NB_LEVELS 8
  47. #if HAVE_SETCONSOLETEXTATTRIBUTE
  48. #include <windows.h>
  49. static const uint8_t color[NB_LEVELS] = { 12, 12, 12, 14, 7, 10, 11, 8};
  50. static int16_t background, attr_orig;
  51. static HANDLE con;
  52. #define set_color(x) SetConsoleTextAttribute(con, background | color[x])
  53. #define reset_color() SetConsoleTextAttribute(con, attr_orig)
  54. #define print_256color(x)
  55. #else
  56. static const uint8_t color[NB_LEVELS] = {
  57. 0x41, 0x41, 0x11, 0x03, 9, 0x02, 0x06, 0x07
  58. };
  59. #define set_color(x) fprintf(stderr, "\033[%d;3%dm", color[x] >> 4, color[x]&15)
  60. #define print_256color(x) fprintf(stderr, "\033[38;5;%dm", x)
  61. #define reset_color() fprintf(stderr, "\033[0m")
  62. #endif
  63. static int use_color = -1;
  64. static void check_color_terminal(void)
  65. {
  66. #if HAVE_SETCONSOLETEXTATTRIBUTE
  67. CONSOLE_SCREEN_BUFFER_INFO con_info;
  68. con = GetStdHandle(STD_ERROR_HANDLE);
  69. use_color = (con != INVALID_HANDLE_VALUE) && !getenv("NO_COLOR") &&
  70. !getenv("AV_LOG_FORCE_NOCOLOR");
  71. if (use_color) {
  72. GetConsoleScreenBufferInfo(con, &con_info);
  73. attr_orig = con_info.wAttributes;
  74. background = attr_orig & 0xF0;
  75. }
  76. #elif HAVE_ISATTY
  77. char *term = getenv("TERM");
  78. use_color = !getenv("NO_COLOR") && !getenv("AV_LOG_FORCE_NOCOLOR") &&
  79. (getenv("TERM") && isatty(2) || getenv("AV_LOG_FORCE_COLOR"));
  80. if (use_color)
  81. use_color += term && strstr(term, "256color");
  82. #else
  83. use_color = getenv("AV_LOG_FORCE_COLOR") && !getenv("NO_COLOR") &&
  84. !getenv("AV_LOG_FORCE_NOCOLOR");
  85. #endif
  86. }
  87. static void colored_fputs(int level, int tint, const char *str)
  88. {
  89. if (use_color < 0)
  90. check_color_terminal();
  91. switch (use_color) {
  92. case 1:
  93. set_color(level);
  94. break;
  95. case 2:
  96. set_color(level);
  97. if (tint)
  98. print_256color(tint);
  99. break;
  100. default:
  101. break;
  102. }
  103. fputs(str, stderr);
  104. if (use_color) {
  105. reset_color();
  106. }
  107. }
  108. const char *av_default_item_name(void *ptr)
  109. {
  110. return (*(AVClass **) ptr)->class_name;
  111. }
  112. void av_log_default_callback(void *avcl, int level, const char *fmt, va_list vl)
  113. {
  114. static int print_prefix = 1;
  115. static int count;
  116. static char prev[1024];
  117. char line[1024];
  118. static int is_atty;
  119. AVClass* avc = avcl ? *(AVClass **) avcl : NULL;
  120. unsigned tint = level & 0xff00;
  121. level &= 0xff;
  122. if (level > av_log_level)
  123. return;
  124. line[0] = 0;
  125. if (print_prefix && avc) {
  126. if (avc->parent_log_context_offset) {
  127. AVClass** parent = *(AVClass ***) (((uint8_t *) avcl) +
  128. avc->parent_log_context_offset);
  129. if (parent && *parent) {
  130. snprintf(line, sizeof(line), "[%s @ %p] ",
  131. (*parent)->item_name(parent), parent);
  132. }
  133. }
  134. snprintf(line + strlen(line), sizeof(line) - strlen(line), "[%s @ %p] ",
  135. avc->item_name(avcl), avcl);
  136. }
  137. vsnprintf(line + strlen(line), sizeof(line) - strlen(line), fmt, vl);
  138. print_prefix = strlen(line) && line[strlen(line) - 1] == '\n';
  139. #if HAVE_ISATTY
  140. if (!is_atty)
  141. is_atty = isatty(2) ? 1 : -1;
  142. #endif
  143. if (print_prefix && (flags & AV_LOG_SKIP_REPEATED) &&
  144. !strncmp(line, prev, sizeof line)) {
  145. count++;
  146. if (is_atty == 1)
  147. fprintf(stderr, " Last message repeated %d times\r", count);
  148. return;
  149. }
  150. if (count > 0) {
  151. fprintf(stderr, " Last message repeated %d times\n", count);
  152. count = 0;
  153. }
  154. colored_fputs(av_clip(level >> 3, 0, NB_LEVELS - 1), tint >> 8, line);
  155. av_strlcpy(prev, line, sizeof line);
  156. #if CONFIG_VALGRIND_BACKTRACE
  157. if (level <= BACKTRACE_LOGLEVEL)
  158. VALGRIND_PRINTF_BACKTRACE("");
  159. #endif
  160. }
  161. static void (*av_log_callback)(void*, int, const char*, va_list) =
  162. av_log_default_callback;
  163. void av_log(void* avcl, int level, const char *fmt, ...)
  164. {
  165. AVClass* avc = avcl ? *(AVClass **) avcl : NULL;
  166. va_list vl;
  167. va_start(vl, fmt);
  168. if (avc && avc->version >= (50 << 16 | 15 << 8 | 2) &&
  169. avc->log_level_offset_offset && level >= AV_LOG_FATAL)
  170. level += *(int *) (((uint8_t *) avcl) + avc->log_level_offset_offset);
  171. av_vlog(avcl, level, fmt, vl);
  172. va_end(vl);
  173. }
  174. void av_vlog(void* avcl, int level, const char *fmt, va_list vl)
  175. {
  176. av_log_callback(avcl, level, fmt, vl);
  177. }
  178. int av_log_get_level(void)
  179. {
  180. return av_log_level;
  181. }
  182. void av_log_set_level(int level)
  183. {
  184. av_log_level = level;
  185. }
  186. void av_log_set_flags(int arg)
  187. {
  188. flags = arg;
  189. }
  190. void av_log_set_callback(void (*callback)(void*, int, const char*, va_list))
  191. {
  192. av_log_callback = callback;
  193. }
  194. static void missing_feature_sample(int sample, void *avc, const char *msg,
  195. va_list argument_list)
  196. {
  197. av_vlog(avc, AV_LOG_WARNING, msg, argument_list);
  198. av_log(avc, AV_LOG_WARNING, " is not implemented. Update your Libav "
  199. "version to the newest one from Git. If the problem still "
  200. "occurs, it means that your file has a feature which has not "
  201. "been implemented.\n");
  202. if (sample)
  203. av_log(avc, AV_LOG_WARNING, "If you want to help, upload a sample "
  204. "of this file to ftp://upload.libav.org/incoming/ "
  205. "and contact the libav-devel mailing list.\n");
  206. }
  207. void avpriv_request_sample(void *avc, const char *msg, ...)
  208. {
  209. va_list argument_list;
  210. va_start(argument_list, msg);
  211. missing_feature_sample(1, avc, msg, argument_list);
  212. va_end(argument_list);
  213. }
  214. void avpriv_report_missing_feature(void *avc, const char *msg, ...)
  215. {
  216. va_list argument_list;
  217. va_start(argument_list, msg);
  218. missing_feature_sample(0, avc, msg, argument_list);
  219. va_end(argument_list);
  220. }