3 * Copyright (c) 2003 Michel Bardiaux
5 * This file is part of FFmpeg.
7 * FFmpeg 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.
12 * FFmpeg 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.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
45 static pthread_mutex_t mutex
= PTHREAD_MUTEX_INITIALIZER
;
50 static int av_log_level
= AV_LOG_INFO
;
53 #if defined(_WIN32) && !defined(__MINGW32CE__) && HAVE_SETCONSOLETEXTATTRIBUTE
55 static const uint8_t color
[16 + AV_CLASS_CATEGORY_NB
] = {
56 [AV_LOG_PANIC
/8] = 12,
57 [AV_LOG_FATAL
/8] = 12,
58 [AV_LOG_ERROR
/8] = 12,
59 [AV_LOG_WARNING
/8] = 14,
61 [AV_LOG_VERBOSE
/8] = 10,
62 [AV_LOG_DEBUG
/8] = 10,
63 [16+AV_CLASS_CATEGORY_NA
] = 7,
64 [16+AV_CLASS_CATEGORY_INPUT
] = 13,
65 [16+AV_CLASS_CATEGORY_OUTPUT
] = 5,
66 [16+AV_CLASS_CATEGORY_MUXER
] = 13,
67 [16+AV_CLASS_CATEGORY_DEMUXER
] = 5,
68 [16+AV_CLASS_CATEGORY_ENCODER
] = 11,
69 [16+AV_CLASS_CATEGORY_DECODER
] = 3,
70 [16+AV_CLASS_CATEGORY_FILTER
] = 10,
71 [16+AV_CLASS_CATEGORY_BITSTREAM_FILTER
] = 9,
72 [16+AV_CLASS_CATEGORY_SWSCALER
] = 7,
73 [16+AV_CLASS_CATEGORY_SWRESAMPLER
] = 7,
74 [16+AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT
] = 13,
75 [16+AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT
] = 5,
76 [16+AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT
] = 13,
77 [16+AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT
] = 5,
78 [16+AV_CLASS_CATEGORY_DEVICE_OUTPUT
] = 13,
79 [16+AV_CLASS_CATEGORY_DEVICE_INPUT
] = 5,
82 static int16_t background
, attr_orig
;
86 static const uint32_t color
[16 + AV_CLASS_CATEGORY_NB
] = {
87 [AV_LOG_PANIC
/8] = 52 << 16 | 196 << 8 | 0x41,
88 [AV_LOG_FATAL
/8] = 208 << 8 | 0x41,
89 [AV_LOG_ERROR
/8] = 196 << 8 | 0x11,
90 [AV_LOG_WARNING
/8] = 226 << 8 | 0x03,
91 [AV_LOG_INFO
/8] = 253 << 8 | 0x09,
92 [AV_LOG_VERBOSE
/8] = 40 << 8 | 0x02,
93 [AV_LOG_DEBUG
/8] = 34 << 8 | 0x02,
94 [16+AV_CLASS_CATEGORY_NA
] = 250 << 8 | 0x09,
95 [16+AV_CLASS_CATEGORY_INPUT
] = 219 << 8 | 0x15,
96 [16+AV_CLASS_CATEGORY_OUTPUT
] = 201 << 8 | 0x05,
97 [16+AV_CLASS_CATEGORY_MUXER
] = 213 << 8 | 0x15,
98 [16+AV_CLASS_CATEGORY_DEMUXER
] = 207 << 8 | 0x05,
99 [16+AV_CLASS_CATEGORY_ENCODER
] = 51 << 8 | 0x16,
100 [16+AV_CLASS_CATEGORY_DECODER
] = 39 << 8 | 0x06,
101 [16+AV_CLASS_CATEGORY_FILTER
] = 155 << 8 | 0x12,
102 [16+AV_CLASS_CATEGORY_BITSTREAM_FILTER
] = 192 << 8 | 0x14,
103 [16+AV_CLASS_CATEGORY_SWSCALER
] = 153 << 8 | 0x14,
104 [16+AV_CLASS_CATEGORY_SWRESAMPLER
] = 147 << 8 | 0x14,
105 [16+AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT
] = 213 << 8 | 0x15,
106 [16+AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT
] = 207 << 8 | 0x05,
107 [16+AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT
] = 213 << 8 | 0x15,
108 [16+AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT
] = 207 << 8 | 0x05,
109 [16+AV_CLASS_CATEGORY_DEVICE_OUTPUT
] = 213 << 8 | 0x15,
110 [16+AV_CLASS_CATEGORY_DEVICE_INPUT
] = 207 << 8 | 0x05,
114 static int use_color
= -1;
116 static void check_color_terminal(void)
118 #if defined(_WIN32) && !defined(__MINGW32CE__) && HAVE_SETCONSOLETEXTATTRIBUTE
119 CONSOLE_SCREEN_BUFFER_INFO con_info
;
120 con
= GetStdHandle(STD_ERROR_HANDLE
);
121 use_color
= (con
!= INVALID_HANDLE_VALUE
) && !getenv("NO_COLOR") &&
122 !getenv("AV_LOG_FORCE_NOCOLOR");
124 GetConsoleScreenBufferInfo(con
, &con_info
);
125 attr_orig
= con_info
.wAttributes
;
126 background
= attr_orig
& 0xF0;
129 char *term
= getenv("TERM");
130 use_color
= !getenv("NO_COLOR") && !getenv("AV_LOG_FORCE_NOCOLOR") &&
131 (getenv("TERM") && isatty(2) || getenv("AV_LOG_FORCE_COLOR"));
132 if ( getenv("AV_LOG_FORCE_256COLOR")
133 || (term
&& strstr(term
, "256color")))
136 use_color
= getenv("AV_LOG_FORCE_COLOR") && !getenv("NO_COLOR") &&
137 !getenv("AV_LOG_FORCE_NOCOLOR");
141 static void colored_fputs(int level
, int tint
, const char *str
)
148 check_color_terminal();
150 if (level
== AV_LOG_INFO
/8) local_use_color
= 0;
151 else local_use_color
= use_color
;
153 #if defined(_WIN32) && !defined(__MINGW32CE__) && HAVE_SETCONSOLETEXTATTRIBUTE
155 SetConsoleTextAttribute(con
, background
| color
[level
]);
158 SetConsoleTextAttribute(con
, attr_orig
);
160 if (local_use_color
== 1) {
162 "\033[%d;3%dm%s\033[0m",
163 (color
[level
] >> 4) & 15,
166 } else if (tint
&& use_color
== 256) {
168 "\033[48;5;%dm\033[38;5;%dm%s\033[0m",
169 (color
[level
] >> 16) & 0xff,
172 } else if (local_use_color
== 256) {
174 "\033[48;5;%dm\033[38;5;%dm%s\033[0m",
175 (color
[level
] >> 16) & 0xff,
176 (color
[level
] >> 8) & 0xff,
184 const char *av_default_item_name(void *ptr
)
186 return (*(AVClass
**) ptr
)->class_name
;
189 AVClassCategory
av_default_get_category(void *ptr
)
191 return (*(AVClass
**) ptr
)->category
;
194 static void sanitize(uint8_t *line
){
196 if(*line
< 0x08 || (*line
> 0x0D && *line
< 0x20))
202 static int get_category(void *ptr
){
203 AVClass
*avc
= *(AVClass
**) ptr
;
205 || (avc
->version
&0xFF)<100
206 || avc
->version
< (51 << 16 | 59 << 8)
207 || avc
->category
>= AV_CLASS_CATEGORY_NB
) return AV_CLASS_CATEGORY_NA
+ 16;
209 if(avc
->get_category
)
210 return avc
->get_category(ptr
) + 16;
212 return avc
->category
+ 16;
215 static const char *get_level_str(int level
)
239 static void format_line(void *avcl
, int level
, const char *fmt
, va_list vl
,
240 AVBPrint part
[4], int *print_prefix
, int type
[2])
242 AVClass
* avc
= avcl
? *(AVClass
**) avcl
: NULL
;
243 av_bprint_init(part
+0, 0, 1);
244 av_bprint_init(part
+1, 0, 1);
245 av_bprint_init(part
+2, 0, 1);
246 av_bprint_init(part
+3, 0, 65536);
248 if(type
) type
[0] = type
[1] = AV_CLASS_CATEGORY_NA
+ 16;
249 if (*print_prefix
&& avc
) {
250 if (avc
->parent_log_context_offset
) {
251 AVClass
** parent
= *(AVClass
***) (((uint8_t *) avcl
) +
252 avc
->parent_log_context_offset
);
253 if (parent
&& *parent
) {
254 av_bprintf(part
+0, "[%s @ %p] ",
255 (*parent
)->item_name(parent
), parent
);
256 if(type
) type
[0] = get_category(parent
);
259 av_bprintf(part
+1, "[%s @ %p] ",
260 avc
->item_name(avcl
), avcl
);
261 if(type
) type
[1] = get_category(avcl
);
263 if (flags
& AV_LOG_PRINT_LEVEL
)
264 av_bprintf(part
+2, "[%s] ", get_level_str(level
));
267 av_vbprintf(part
+3, fmt
, vl
);
269 if(*part
[0].str
|| *part
[1].str
|| *part
[2].str
|| *part
[3].str
) {
270 char lastc
= part
[3].len
&& part
[3].len
<= part
[3].size
? part
[3].str
[part
[3].len
- 1] : 0;
271 *print_prefix
= lastc
== '\n' || lastc
== '\r';
275 void av_log_format_line(void *ptr
, int level
, const char *fmt
, va_list vl
,
276 char *line
, int line_size
, int *print_prefix
)
279 format_line(ptr
, level
, fmt
, vl
, part
, print_prefix
, NULL
);
280 snprintf(line
, line_size
, "%s%s%s%s", part
[0].str
, part
[1].str
, part
[2].str
, part
[3].str
);
281 av_bprint_finalize(part
+3, NULL
);
284 void av_log_default_callback(void* ptr
, int level
, const char* fmt
, va_list vl
)
286 static int print_prefix
= 1;
288 static char prev
[LINE_SZ
];
296 tint
= level
& 0xff00;
300 if (level
> av_log_level
)
303 pthread_mutex_lock(&mutex
);
306 format_line(ptr
, level
, fmt
, vl
, part
, &print_prefix
, type
);
307 snprintf(line
, sizeof(line
), "%s%s%s%s", part
[0].str
, part
[1].str
, part
[2].str
, part
[3].str
);
311 is_atty
= isatty(2) ? 1 : -1;
314 if (print_prefix
&& (flags
& AV_LOG_SKIP_REPEATED
) && !strcmp(line
, prev
) &&
315 *line
&& line
[strlen(line
) - 1] != '\r'){
318 fprintf(stderr
, " Last message repeated %d times\r", count
);
322 fprintf(stderr
, " Last message repeated %d times\n", count
);
326 sanitize(part
[0].str
);
327 colored_fputs(type
[0], 0, part
[0].str
);
328 sanitize(part
[1].str
);
329 colored_fputs(type
[1], 0, part
[1].str
);
330 sanitize(part
[2].str
);
331 colored_fputs(av_clip(level
>> 3, 0, 6), tint
>> 8, part
[2].str
);
332 sanitize(part
[3].str
);
333 colored_fputs(av_clip(level
>> 3, 0, 6), tint
>> 8, part
[3].str
);
335 av_bprint_finalize(part
+3, NULL
);
337 pthread_mutex_unlock(&mutex
);
341 static void (*av_log_callback
)(void*, int, const char*, va_list) =
342 av_log_default_callback
;
344 void av_log(void* avcl
, int level
, const char *fmt
, ...)
346 AVClass
* avc
= avcl
? *(AVClass
**) avcl
: NULL
;
349 if (avc
&& avc
->version
>= (50 << 16 | 15 << 8 | 2) &&
350 avc
->log_level_offset_offset
&& level
>= AV_LOG_FATAL
)
351 level
+= *(int *) (((uint8_t *) avcl
) + avc
->log_level_offset_offset
);
352 av_vlog(avcl
, level
, fmt
, vl
);
356 void av_vlog(void* avcl
, int level
, const char *fmt
, va_list vl
)
358 void (*log_callback
)(void*, int, const char*, va_list) = av_log_callback
;
360 log_callback(avcl
, level
, fmt
, vl
);
363 int av_log_get_level(void)
368 void av_log_set_level(int level
)
370 av_log_level
= level
;
373 void av_log_set_flags(int arg
)
378 int av_log_get_flags(void)
383 void av_log_set_callback(void (*callback
)(void*, int, const char*, va_list))
385 av_log_callback
= callback
;
388 static void missing_feature_sample(int sample
, void *avc
, const char *msg
,
389 va_list argument_list
)
391 av_vlog(avc
, AV_LOG_WARNING
, msg
, argument_list
);
392 av_log(avc
, AV_LOG_WARNING
, " is not implemented. Update your FFmpeg "
393 "version to the newest one from Git. If the problem still "
394 "occurs, it means that your file has a feature which has not "
395 "been implemented.\n");
397 av_log(avc
, AV_LOG_WARNING
, "If you want to help, upload a sample "
398 "of this file to ftp://upload.ffmpeg.org/incoming/ "
399 "and contact the ffmpeg-devel mailing list. (ffmpeg-devel@ffmpeg.org)\n");
402 void avpriv_request_sample(void *avc
, const char *msg
, ...)
404 va_list argument_list
;
406 va_start(argument_list
, msg
);
407 missing_feature_sample(1, avc
, msg
, argument_list
);
408 va_end(argument_list
);
411 void avpriv_report_missing_feature(void *avc
, const char *msg
, ...)
413 va_list argument_list
;
415 va_start(argument_list
, msg
);
416 missing_feature_sample(0, avc
, msg
, argument_list
);
417 va_end(argument_list
);
424 int main(int argc
, char **argv
)
427 av_log_set_level(AV_LOG_DEBUG
);
428 for (use_color
=0; use_color
<=256; use_color
= 255*use_color
+1) {
429 av_log(NULL
, AV_LOG_FATAL
, "use_color: %d\n", use_color
);
430 for (i
= AV_LOG_DEBUG
; i
>=AV_LOG_QUIET
; i
-=8) {
431 av_log(NULL
, i
, " %d", i
);
432 av_log(NULL
, AV_LOG_INFO
, "e ");
433 av_log(NULL
, i
+ 256*123, "C%d", i
);
434 av_log(NULL
, AV_LOG_INFO
, "e");
436 av_log(NULL
, AV_LOG_PANIC
, "\n");