Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Customizable FFmpeg logs #45

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion SeeShark.Example.Ascii/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@

using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using SeeShark.Decode;
using SeeShark.Device;
using SeeShark.FFmpeg;
using static SeeShark.FFmpeg.FFmpegManager;

namespace SeeShark.Example.Ascii;
Expand All @@ -18,6 +20,16 @@ class Program
static CameraManager? manager;
static FrameConverter? converter;

static StreamWriter logFile = new StreamWriter("ffmpeg.log");

/// <summary>
/// A custom FFmpeg logging callback. There is already a default one baked in which just writes to the console, so you don't need to make one yourself if that's what you want.
/// </summary>
static void ffmpegLog(FFmpegLogLevel logLevel, ConsoleColor _logColor, string? message)
{
logFile.Write($"[{logLevel}] {message}");
}

static void Main(string[] args)
{
// Casually displaying "Oof :(" when exiting the program with force.
Expand All @@ -32,8 +44,9 @@ static void Main(string[] args)

// You can add your own path for FFmpeg libraries here!
SetupFFmpeg(
FFmpeg.FFmpegLogLevel.Info,
FFmpegLogLevel.Debug,
ConsoleColor.Yellow,
ffmpegLog,
AppDomain.CurrentDomain.BaseDirectory,
"/usr/lib",
"/usr/lib64"
Expand Down
51 changes: 40 additions & 11 deletions SeeShark/FFmpeg/FFmpegManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,38 @@ public static string FFmpegRootPath
/// <summary>
/// Setup FFmpeg: root path and logging.
/// <br/>
/// It will only setup FFmpeg once. Any non-first call will do nothing.
/// It will only setup FFmpeg once. Any non-first call to this method will do nothing.
/// <br/>
/// SeeShark is designed such that this method is called whenever it is
/// necessary to have FFmpeg ready.
/// <br/>
/// However, if you want to, you can still call it at the beginning of
/// your program to customize your FFmpeg setup.
/// </summary>
/// <param name="rootPath">Root path for loading FFmpeg libraries.</param>
/// <param name="logLevel">Log level for FFmpeg.</param>
/// <param name="logColor">Color of the FFmpeg logs.</param>
/// <param name="paths">List of valid paths for loading FFmpeg libraries.</param>
public static void SetupFFmpeg(FFmpegLogLevel logLevel, ConsoleColor logColor, params string[] paths)
{
SetupFFmpeg(logLevel, logColor, null, paths);
}

/// <summary>
/// Setup FFmpeg: root path and logging, with custom log delegate.
/// <br/>
/// It will only setup FFmpeg once. Any non-first call to this method will do nothing.
/// <br/>
/// SeeShark is designed such that this method is called whenever it is
/// necessary to have FFmpeg ready.
/// <br/>
/// However, if you want to, you can still call it at the beginning of
/// your program to customize your FFmpeg setup.
/// </summary>
/// <param name="logLevel">Log level for FFmpeg.</param>
/// <param name="logColor">Color of the FFmpeg logs.</param>
/// <param name="ffmpegLog">Custom delegate to redirect FFmpeg logs.</param>
/// <param name="paths">List of valid paths for loading FFmpeg libraries.</param>
public static void SetupFFmpeg(FFmpegLogLevel logLevel, ConsoleColor logColor, FFmpegLog? ffmpegLog, params string[] paths)
{
if (IsFFmpegSetup)
return;
Expand All @@ -91,35 +111,44 @@ public static void SetupFFmpeg(FFmpegLogLevel logLevel, ConsoleColor logColor, p
TrySetRootPath(requiredLibs, AppDomain.CurrentDomain.BaseDirectory);
else
TrySetRootPath(requiredLibs, paths);
SetupFFmpegLogging(logLevel, logColor);
SetupFFmpegLogging(logLevel, logColor, ffmpegLog);
ffmpeg.avdevice_register_all();

IsFFmpegSetup = true;
}

public static void SetupFFmpeg(params string[] paths) => SetupFFmpeg(FFmpegLogLevel.Panic, ConsoleColor.Yellow, paths);

internal static unsafe void SetupFFmpegLogging(FFmpegLogLevel logLevel, ConsoleColor logColor)
public delegate void FFmpegLog(FFmpegLogLevel logLevel, ConsoleColor logColor, string? message);

private static void defaultFFmpegLog(FFmpegLogLevel logLevel, ConsoleColor logColor, string? message)
{
Console.ForegroundColor = logColor;
Console.Error.Write(message);
Console.ResetColor();
}

internal static unsafe void SetupFFmpegLogging(FFmpegLogLevel logLevel, ConsoleColor logColor, FFmpegLog? ffmpegLog = null)
{
ffmpeg.av_log_set_level((int)logLevel);

ffmpegLog ??= new FFmpegLog(defaultFFmpegLog);

// Do not convert to local function!
logCallback = (p0, level, format, vl) =>
{
if (level > ffmpeg.av_log_get_level())
return;

var lineSize = 1024;
var lineBuffer = stackalloc byte[lineSize];
var printPrefix = 1;
int lineSize = 1024;
byte* lineBuffer = stackalloc byte[lineSize];
int printPrefix = 1;

ffmpeg.av_log_format_line(p0, level, format, vl, lineBuffer, lineSize, &printPrefix);
var line = Marshal.PtrToStringAnsi((IntPtr)lineBuffer);
string? message = Marshal.PtrToStringAnsi((IntPtr)lineBuffer);

// TODO: maybe make it possible to log this in any stream?
Console.ForegroundColor = logColor;
Console.Write(line);
Console.ResetColor();
ffmpegLog(logLevel, logColor, message);
};

ffmpeg.av_log_set_callback(logCallback);
Expand Down