yading@11
|
1 /*
|
yading@11
|
2 * log functions
|
yading@11
|
3 * Copyright (c) 2003 Michel Bardiaux
|
yading@11
|
4 *
|
yading@11
|
5 * This file is part of FFmpeg.
|
yading@11
|
6 *
|
yading@11
|
7 * FFmpeg is free software; you can redistribute it and/or
|
yading@11
|
8 * modify it under the terms of the GNU Lesser General Public
|
yading@11
|
9 * License as published by the Free Software Foundation; either
|
yading@11
|
10 * version 2.1 of the License, or (at your option) any later version.
|
yading@11
|
11 *
|
yading@11
|
12 * FFmpeg is distributed in the hope that it will be useful,
|
yading@11
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@11
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@11
|
15 * Lesser General Public License for more details.
|
yading@11
|
16 *
|
yading@11
|
17 * You should have received a copy of the GNU Lesser General Public
|
yading@11
|
18 * License along with FFmpeg; if not, write to the Free Software
|
yading@11
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@11
|
20 */
|
yading@11
|
21
|
yading@11
|
22 /**
|
yading@11
|
23 * @file
|
yading@11
|
24 * logging functions
|
yading@11
|
25 */
|
yading@11
|
26
|
yading@11
|
27 #include "config.h"
|
yading@11
|
28
|
yading@11
|
29 #if HAVE_UNISTD_H
|
yading@11
|
30 #include <unistd.h>
|
yading@11
|
31 #endif
|
yading@11
|
32 #if HAVE_IO_H
|
yading@11
|
33 #include <io.h>
|
yading@11
|
34 #endif
|
yading@11
|
35 #include <stdarg.h>
|
yading@11
|
36 #include <stdlib.h>
|
yading@11
|
37 #include "avutil.h"
|
yading@11
|
38 #include "common.h"
|
yading@11
|
39 #include "internal.h"
|
yading@11
|
40 #include "log.h"
|
yading@11
|
41
|
yading@11
|
42 #define LINE_SZ 1024
|
yading@11
|
43
|
yading@11
|
44 static int av_log_level = AV_LOG_INFO;
|
yading@11
|
45 static int flags;
|
yading@11
|
46
|
yading@11
|
47 #if HAVE_SETCONSOLETEXTATTRIBUTE
|
yading@11
|
48 #include <windows.h>
|
yading@11
|
49 static const uint8_t color[16 + AV_CLASS_CATEGORY_NB] = {
|
yading@11
|
50 [AV_LOG_PANIC /8] = 12,
|
yading@11
|
51 [AV_LOG_FATAL /8] = 12,
|
yading@11
|
52 [AV_LOG_ERROR /8] = 12,
|
yading@11
|
53 [AV_LOG_WARNING/8] = 14,
|
yading@11
|
54 [AV_LOG_INFO /8] = 7,
|
yading@11
|
55 [AV_LOG_VERBOSE/8] = 10,
|
yading@11
|
56 [AV_LOG_DEBUG /8] = 10,
|
yading@11
|
57 [16+AV_CLASS_CATEGORY_NA ] = 7,
|
yading@11
|
58 [16+AV_CLASS_CATEGORY_INPUT ] = 13,
|
yading@11
|
59 [16+AV_CLASS_CATEGORY_OUTPUT ] = 5,
|
yading@11
|
60 [16+AV_CLASS_CATEGORY_MUXER ] = 13,
|
yading@11
|
61 [16+AV_CLASS_CATEGORY_DEMUXER ] = 5,
|
yading@11
|
62 [16+AV_CLASS_CATEGORY_ENCODER ] = 11,
|
yading@11
|
63 [16+AV_CLASS_CATEGORY_DECODER ] = 3,
|
yading@11
|
64 [16+AV_CLASS_CATEGORY_FILTER ] = 10,
|
yading@11
|
65 [16+AV_CLASS_CATEGORY_BITSTREAM_FILTER] = 9,
|
yading@11
|
66 [16+AV_CLASS_CATEGORY_SWSCALER ] = 7,
|
yading@11
|
67 [16+AV_CLASS_CATEGORY_SWRESAMPLER ] = 7,
|
yading@11
|
68 };
|
yading@11
|
69
|
yading@11
|
70 static int16_t background, attr_orig;
|
yading@11
|
71 static HANDLE con;
|
yading@11
|
72 #define set_color(x) SetConsoleTextAttribute(con, background | color[x])
|
yading@11
|
73 #define set_256color set_color
|
yading@11
|
74 #define reset_color() SetConsoleTextAttribute(con, attr_orig)
|
yading@11
|
75 #else
|
yading@11
|
76
|
yading@11
|
77 static const uint32_t color[16 + AV_CLASS_CATEGORY_NB] = {
|
yading@11
|
78 [AV_LOG_PANIC /8] = 52 << 16 | 196 << 8 | 0x41,
|
yading@11
|
79 [AV_LOG_FATAL /8] = 208 << 8 | 0x41,
|
yading@11
|
80 [AV_LOG_ERROR /8] = 196 << 8 | 0x11,
|
yading@11
|
81 [AV_LOG_WARNING/8] = 226 << 8 | 0x03,
|
yading@11
|
82 [AV_LOG_INFO /8] = 253 << 8 | 0x09,
|
yading@11
|
83 [AV_LOG_VERBOSE/8] = 40 << 8 | 0x02,
|
yading@11
|
84 [AV_LOG_DEBUG /8] = 34 << 8 | 0x02,
|
yading@11
|
85 [16+AV_CLASS_CATEGORY_NA ] = 250 << 8 | 0x09,
|
yading@11
|
86 [16+AV_CLASS_CATEGORY_INPUT ] = 219 << 8 | 0x15,
|
yading@11
|
87 [16+AV_CLASS_CATEGORY_OUTPUT ] = 201 << 8 | 0x05,
|
yading@11
|
88 [16+AV_CLASS_CATEGORY_MUXER ] = 213 << 8 | 0x15,
|
yading@11
|
89 [16+AV_CLASS_CATEGORY_DEMUXER ] = 207 << 8 | 0x05,
|
yading@11
|
90 [16+AV_CLASS_CATEGORY_ENCODER ] = 51 << 8 | 0x16,
|
yading@11
|
91 [16+AV_CLASS_CATEGORY_DECODER ] = 39 << 8 | 0x06,
|
yading@11
|
92 [16+AV_CLASS_CATEGORY_FILTER ] = 155 << 8 | 0x12,
|
yading@11
|
93 [16+AV_CLASS_CATEGORY_BITSTREAM_FILTER] = 192 << 8 | 0x14,
|
yading@11
|
94 [16+AV_CLASS_CATEGORY_SWSCALER ] = 153 << 8 | 0x14,
|
yading@11
|
95 [16+AV_CLASS_CATEGORY_SWRESAMPLER ] = 147 << 8 | 0x14,
|
yading@11
|
96 };
|
yading@11
|
97
|
yading@11
|
98 #define set_color(x) fprintf(stderr, "\033[%d;3%dm", (color[x] >> 4) & 15, color[x] & 15)
|
yading@11
|
99 #define set_256color(x) fprintf(stderr, "\033[48;5;%dm\033[38;5;%dm", (color[x] >> 16) & 0xff, (color[x] >> 8) & 0xff)
|
yading@11
|
100 #define reset_color() fprintf(stderr, "\033[0m")
|
yading@11
|
101 #endif
|
yading@11
|
102 static int use_color = -1;
|
yading@11
|
103
|
yading@11
|
104 static void colored_fputs(int level, const char *str)
|
yading@11
|
105 {
|
yading@11
|
106 if (use_color < 0) {
|
yading@11
|
107 #if HAVE_SETCONSOLETEXTATTRIBUTE
|
yading@11
|
108 CONSOLE_SCREEN_BUFFER_INFO con_info;
|
yading@11
|
109 con = GetStdHandle(STD_ERROR_HANDLE);
|
yading@11
|
110 use_color = (con != INVALID_HANDLE_VALUE) && !getenv("NO_COLOR") &&
|
yading@11
|
111 !getenv("AV_LOG_FORCE_NOCOLOR");
|
yading@11
|
112 if (use_color) {
|
yading@11
|
113 GetConsoleScreenBufferInfo(con, &con_info);
|
yading@11
|
114 attr_orig = con_info.wAttributes;
|
yading@11
|
115 background = attr_orig & 0xF0;
|
yading@11
|
116 }
|
yading@11
|
117 #elif HAVE_ISATTY
|
yading@11
|
118 use_color = !getenv("NO_COLOR") && !getenv("AV_LOG_FORCE_NOCOLOR") &&
|
yading@11
|
119 (getenv("TERM") && isatty(2) ||
|
yading@11
|
120 getenv("AV_LOG_FORCE_COLOR"));
|
yading@11
|
121 if (getenv("AV_LOG_FORCE_256COLOR"))
|
yading@11
|
122 use_color *= 256;
|
yading@11
|
123 #else
|
yading@11
|
124 use_color = getenv("AV_LOG_FORCE_COLOR") && !getenv("NO_COLOR") &&
|
yading@11
|
125 !getenv("AV_LOG_FORCE_NOCOLOR");
|
yading@11
|
126 #endif
|
yading@11
|
127 }
|
yading@11
|
128
|
yading@11
|
129 if (use_color == 1) {
|
yading@11
|
130 set_color(level);
|
yading@11
|
131 } else if (use_color == 256)
|
yading@11
|
132 set_256color(level);
|
yading@11
|
133 fputs(str, stderr);
|
yading@11
|
134 if (use_color) {
|
yading@11
|
135 reset_color();
|
yading@11
|
136 }
|
yading@11
|
137 }
|
yading@11
|
138
|
yading@11
|
139 const char *av_default_item_name(void *ptr)
|
yading@11
|
140 {
|
yading@11
|
141 return (*(AVClass **) ptr)->class_name;
|
yading@11
|
142 }
|
yading@11
|
143
|
yading@11
|
144 AVClassCategory av_default_get_category(void *ptr)
|
yading@11
|
145 {
|
yading@11
|
146 return (*(AVClass **) ptr)->category;
|
yading@11
|
147 }
|
yading@11
|
148
|
yading@11
|
149 static void sanitize(uint8_t *line){
|
yading@11
|
150 while(*line){
|
yading@11
|
151 if(*line < 0x08 || (*line > 0x0D && *line < 0x20))
|
yading@11
|
152 *line='?';
|
yading@11
|
153 line++;
|
yading@11
|
154 }
|
yading@11
|
155 }
|
yading@11
|
156
|
yading@11
|
157 static int get_category(void *ptr){
|
yading@11
|
158 AVClass *avc = *(AVClass **) ptr;
|
yading@11
|
159 if( !avc
|
yading@11
|
160 || (avc->version&0xFF)<100
|
yading@11
|
161 || avc->version < (51 << 16 | 59 << 8)
|
yading@11
|
162 || avc->category >= AV_CLASS_CATEGORY_NB) return AV_CLASS_CATEGORY_NA + 16;
|
yading@11
|
163
|
yading@11
|
164 if(avc->get_category)
|
yading@11
|
165 return avc->get_category(ptr) + 16;
|
yading@11
|
166
|
yading@11
|
167 return avc->category + 16;
|
yading@11
|
168 }
|
yading@11
|
169
|
yading@11
|
170 static void format_line(void *ptr, int level, const char *fmt, va_list vl,
|
yading@11
|
171 char part[3][LINE_SZ], int part_size, int *print_prefix, int type[2])
|
yading@11
|
172 {
|
yading@11
|
173 AVClass* avc = ptr ? *(AVClass **) ptr : NULL;
|
yading@11
|
174 part[0][0] = part[1][0] = part[2][0] = 0;
|
yading@11
|
175 if(type) type[0] = type[1] = AV_CLASS_CATEGORY_NA + 16;
|
yading@11
|
176 if (*print_prefix && avc) {
|
yading@11
|
177 if (avc->parent_log_context_offset) {
|
yading@11
|
178 AVClass** parent = *(AVClass ***) (((uint8_t *) ptr) +
|
yading@11
|
179 avc->parent_log_context_offset);
|
yading@11
|
180 if (parent && *parent) {
|
yading@11
|
181 snprintf(part[0], part_size, "[%s @ %p] ",
|
yading@11
|
182 (*parent)->item_name(parent), parent);
|
yading@11
|
183 if(type) type[0] = get_category(((uint8_t *) ptr) + avc->parent_log_context_offset);
|
yading@11
|
184 }
|
yading@11
|
185 }
|
yading@11
|
186 snprintf(part[1], part_size, "[%s @ %p] ",
|
yading@11
|
187 avc->item_name(ptr), ptr);
|
yading@11
|
188 if(type) type[1] = get_category(ptr);
|
yading@11
|
189 }
|
yading@11
|
190
|
yading@11
|
191 vsnprintf(part[2], part_size, fmt, vl);
|
yading@11
|
192
|
yading@11
|
193 *print_prefix = strlen(part[2]) && part[2][strlen(part[2]) - 1] == '\n';
|
yading@11
|
194 }
|
yading@11
|
195
|
yading@11
|
196 void av_log_format_line(void *ptr, int level, const char *fmt, va_list vl,
|
yading@11
|
197 char *line, int line_size, int *print_prefix)
|
yading@11
|
198 {
|
yading@11
|
199 char part[3][LINE_SZ];
|
yading@11
|
200 format_line(ptr, level, fmt, vl, part, sizeof(part[0]), print_prefix, NULL);
|
yading@11
|
201 snprintf(line, line_size, "%s%s%s", part[0], part[1], part[2]);
|
yading@11
|
202 }
|
yading@11
|
203
|
yading@11
|
204 void av_log_default_callback(void* ptr, int level, const char* fmt, va_list vl)
|
yading@11
|
205 {
|
yading@11
|
206 static int print_prefix = 1;
|
yading@11
|
207 static int count;
|
yading@11
|
208 static char prev[LINE_SZ];
|
yading@11
|
209 char part[3][LINE_SZ];
|
yading@11
|
210 char line[LINE_SZ];
|
yading@11
|
211 static int is_atty;
|
yading@11
|
212 int type[2];
|
yading@11
|
213
|
yading@11
|
214 if (level > av_log_level)
|
yading@11
|
215 return;
|
yading@11
|
216 format_line(ptr, level, fmt, vl, part, sizeof(part[0]), &print_prefix, type);
|
yading@11
|
217 snprintf(line, sizeof(line), "%s%s%s", part[0], part[1], part[2]);
|
yading@11
|
218
|
yading@11
|
219 #if HAVE_ISATTY
|
yading@11
|
220 if (!is_atty)
|
yading@11
|
221 is_atty = isatty(2) ? 1 : -1;
|
yading@11
|
222 #endif
|
yading@11
|
223
|
yading@11
|
224 if (print_prefix && (flags & AV_LOG_SKIP_REPEATED) && !strcmp(line, prev)){
|
yading@11
|
225 count++;
|
yading@11
|
226 if (is_atty == 1)
|
yading@11
|
227 fprintf(stderr, " Last message repeated %d times\r", count);
|
yading@11
|
228 return;
|
yading@11
|
229 }
|
yading@11
|
230 if (count > 0) {
|
yading@11
|
231 fprintf(stderr, " Last message repeated %d times\n", count);
|
yading@11
|
232 count = 0;
|
yading@11
|
233 }
|
yading@11
|
234 strcpy(prev, line);
|
yading@11
|
235 sanitize(part[0]);
|
yading@11
|
236 colored_fputs(type[0], part[0]);
|
yading@11
|
237 sanitize(part[1]);
|
yading@11
|
238 colored_fputs(type[1], part[1]);
|
yading@11
|
239 sanitize(part[2]);
|
yading@11
|
240 colored_fputs(av_clip(level >> 3, 0, 6), part[2]);
|
yading@11
|
241 }
|
yading@11
|
242
|
yading@11
|
243 static void (*av_log_callback)(void*, int, const char*, va_list) =
|
yading@11
|
244 av_log_default_callback;
|
yading@11
|
245
|
yading@11
|
246 void av_log(void* avcl, int level, const char *fmt, ...)
|
yading@11
|
247 {
|
yading@11
|
248 AVClass* avc = avcl ? *(AVClass **) avcl : NULL;
|
yading@11
|
249 va_list vl;
|
yading@11
|
250 va_start(vl, fmt);
|
yading@11
|
251 if (avc && avc->version >= (50 << 16 | 15 << 8 | 2) &&
|
yading@11
|
252 avc->log_level_offset_offset && level >= AV_LOG_FATAL)
|
yading@11
|
253 level += *(int *) (((uint8_t *) avcl) + avc->log_level_offset_offset);
|
yading@11
|
254 av_vlog(avcl, level, fmt, vl);
|
yading@11
|
255 va_end(vl);
|
yading@11
|
256 }
|
yading@11
|
257
|
yading@11
|
258 void av_vlog(void* avcl, int level, const char *fmt, va_list vl)
|
yading@11
|
259 {
|
yading@11
|
260 if(av_log_callback)
|
yading@11
|
261 av_log_callback(avcl, level, fmt, vl);
|
yading@11
|
262 }
|
yading@11
|
263
|
yading@11
|
264 int av_log_get_level(void)
|
yading@11
|
265 {
|
yading@11
|
266 return av_log_level;
|
yading@11
|
267 }
|
yading@11
|
268
|
yading@11
|
269 void av_log_set_level(int level)
|
yading@11
|
270 {
|
yading@11
|
271 av_log_level = level;
|
yading@11
|
272 }
|
yading@11
|
273
|
yading@11
|
274 void av_log_set_flags(int arg)
|
yading@11
|
275 {
|
yading@11
|
276 flags = arg;
|
yading@11
|
277 }
|
yading@11
|
278
|
yading@11
|
279 void av_log_set_callback(void (*callback)(void*, int, const char*, va_list))
|
yading@11
|
280 {
|
yading@11
|
281 av_log_callback = callback;
|
yading@11
|
282 }
|
yading@11
|
283
|
yading@11
|
284 static void missing_feature_sample(int sample, void *avc, const char *msg, va_list argument_list)
|
yading@11
|
285 {
|
yading@11
|
286 av_vlog(avc, AV_LOG_WARNING, msg, argument_list);
|
yading@11
|
287 av_log(avc, AV_LOG_WARNING, " is not implemented. Update your FFmpeg "
|
yading@11
|
288 "version to the newest one from Git. If the problem still "
|
yading@11
|
289 "occurs, it means that your file has a feature which has not "
|
yading@11
|
290 "been implemented.\n");
|
yading@11
|
291 if (sample)
|
yading@11
|
292 av_log(avc, AV_LOG_WARNING, "If you want to help, upload a sample "
|
yading@11
|
293 "of this file to ftp://upload.ffmpeg.org/MPlayer/incoming/ "
|
yading@11
|
294 "and contact the ffmpeg-devel mailing list.\n");
|
yading@11
|
295 }
|
yading@11
|
296
|
yading@11
|
297 void avpriv_request_sample(void *avc, const char *msg, ...)
|
yading@11
|
298 {
|
yading@11
|
299 va_list argument_list;
|
yading@11
|
300
|
yading@11
|
301 va_start(argument_list, msg);
|
yading@11
|
302 missing_feature_sample(1, avc, msg, argument_list);
|
yading@11
|
303 va_end(argument_list);
|
yading@11
|
304 }
|
yading@11
|
305
|
yading@11
|
306 void avpriv_report_missing_feature(void *avc, const char *msg, ...)
|
yading@11
|
307 {
|
yading@11
|
308 va_list argument_list;
|
yading@11
|
309
|
yading@11
|
310 va_start(argument_list, msg);
|
yading@11
|
311 missing_feature_sample(0, avc, msg, argument_list);
|
yading@11
|
312 va_end(argument_list);
|
yading@11
|
313 }
|