diff --git a/ffmpeg/callback.go b/ffmpeg/callback.go index dd3f318..1fcee64 100644 --- a/ffmpeg/callback.go +++ b/ffmpeg/callback.go @@ -52,3 +52,8 @@ func goInterrupt(opaque unsafe.Pointer) C.int { } return 0 } + +//export goAVLoggingHandler +func goAVLoggingHandler(level C.int, cstr *C.char) { + log(AVLogLevel(level), C.GoString(cstr)) +} diff --git a/ffmpeg/ffmpeg.h b/ffmpeg/ffmpeg.h index a0d33b6..2c8acf2 100644 --- a/ffmpeg/ffmpeg.h +++ b/ffmpeg/ffmpeg.h @@ -69,4 +69,4 @@ extern int goPacketRead(void *opaque, uint8_t *buf, int buf_size); extern int64_t goPacketSeek(void *opaque, int64_t seek, int whence); -extern int goInterrupt(void *opaque); \ No newline at end of file +extern int goInterrupt(void *opaque); diff --git a/ffmpeg/logging.c b/ffmpeg/logging.c new file mode 100644 index 0000000..45865e8 --- /dev/null +++ b/ffmpeg/logging.c @@ -0,0 +1,12 @@ +#include "logging.h" + +void goavLogCallback(void *class_ptr, int level, const char *fmt, va_list vl) { + char line[LINE_SZ]; + int print_prefix = 1; + av_log_format_line(class_ptr, level, fmt, vl, line, LINE_SZ, &print_prefix); + goAVLoggingHandler(level, line); +} + +void goavLogSetup() { + av_log_set_callback(goavLogCallback); +} diff --git a/ffmpeg/logging.go b/ffmpeg/logging.go index 9be4697..ffa5a05 100644 --- a/ffmpeg/logging.go +++ b/ffmpeg/logging.go @@ -1,7 +1,9 @@ package ffmpeg // #include "ffmpeg.h" +// #include "logging.h" import "C" +import "sync" // AVLogLevel defines the ffmpeg threshold for dumping information to stderr. type AVLogLevel int @@ -19,6 +21,12 @@ const ( AVLogTrace ) +var ( + currentLoggingHandlerFunction = noopLoggingHandler + currentLoggingVerbosity AVLogLevel + onceLogging sync.Once +) + func logLevel() AVLogLevel { return AVLogLevel(C.av_log_get_level()) } @@ -26,4 +34,25 @@ func logLevel() AVLogLevel { // SetFFmpegLogLevel allows you to change the log level from the default (AVLogInfo). func SetFFmpegLogLevel(logLevel AVLogLevel) { C.av_log_set_level(C.int(logLevel)) + currentLoggingVerbosity = logLevel +} + +type LoggingHandlerFunction func(messageLevel AVLogLevel, message string) + +func SetLogging(handler LoggingHandlerFunction) { + onceLogging.Do(func() { + C.goavLogSetup() + }) + if handler != nil { + currentLoggingHandlerFunction = handler + } +} + +func noopLoggingHandler(_ AVLogLevel, _ string) { +} + +func log(level AVLogLevel, message string) { + if level <= currentLoggingVerbosity { + currentLoggingHandlerFunction(level, message) + } } diff --git a/ffmpeg/logging.h b/ffmpeg/logging.h new file mode 100644 index 0000000..ec6d4c9 --- /dev/null +++ b/ffmpeg/logging.h @@ -0,0 +1,11 @@ +#include + +#define LINE_SZ 1024 + +extern void goAVLoggingHandler(int level, char *str); +extern void av_log_set_callback(void (*callback)(void *, int, const char *, va_list)); +extern void av_log_format_line(void *ptr, int level, const char *fmt, va_list vl, char *line, int line_size, int *print_prefix); + +void goavLogCallback(void *class_ptr, int level, const char *fmt, va_list vl); + +void goavLogSetup(); diff --git a/processor.go b/processor.go index 1aa82e5..9e31b72 100644 --- a/processor.go +++ b/processor.go @@ -29,6 +29,19 @@ func NewProcessor(options ...Option) *Processor { } func (p *Processor) Startup(_ context.Context) error { + ffmpeg.SetLogging(func(level ffmpeg.AVLogLevel, message string) { + message = strings.TrimSuffix(message, "\n") + switch level { + case ffmpeg.AVLogTrace, ffmpeg.AVLogDebug, ffmpeg.AVLogVerbose: + p.Logger.Debug("ffmpeg", zap.String("msg", message)) + case ffmpeg.AVLogInfo: + p.Logger.Info("ffmpeg", zap.String("msg", message)) + case ffmpeg.AVLogWarning: + p.Logger.Warn("ffmpeg", zap.String("msg", message)) + case ffmpeg.AVLogError, ffmpeg.AVLogFatal, ffmpeg.AVLogPanic: + p.Logger.Error("ffmpeg", zap.String("msg", message)) + } + }) if p.Debug { ffmpeg.SetFFmpegLogLevel(ffmpeg.AVLogDebug) } else {