Subversion Repositories Kolibri OS

Rev

Rev 4349 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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