iT邦幫忙

2025 iThome 鐵人賽

DAY 14
0

Hello, 各位 iT 邦幫忙 的粉絲們大家好~~~

在本系列文因為工作上的產品應用需求,進而探索到很多層面的點滴事。透過每篇 EP 的分享把這些點滴整理,看起來或許像是個獨立的小品抒發文、也或許是一系列技術研究文!?

總之,就當作的隨手雜記文吧!

本篇是 莫名其妙就跟世界等級的 OpenSource 專案攪和了!? 系列文的 EP14。


好了,所以本回進入重頭戲。

如果想回應 EP01 所提及的,完全透過 C# 程式來執行出 EP13 的 gstreamer 轉檔處理,而不是透過命令的方式來讓 gstreamer 完成呢?!

那這時候就得仰賴 gstreamer-sharp 的使用了。


插個花。

如果是要在 Windows 上使用 Gstreamer 的話,注意 Gstreamer 官網有特別提及的安裝版本為 msvc 版本:
gstreamer-install-msvc-01
(取自 gstreamer 官網 Windows 安裝)

並且在 Download Gstreamer 的網頁上也有特別標註兩點 Note:
gstreamer-install-msvc-02
(取自 gstreamer 官網 Download)

各位不要用錯囉!


接著再把上一回所使用的 gstreamer pipeline 指令:

filesrc location="c:/tmp/bbb_sunflower.mp4" ! qtdemux ! avdec_h264 ! clockoverlay time-format="%Y-%m-%d %H:%M:%S" valignment=top halignment=right xpad=12 ypad=6 shaded-background=true font-desc="Sans, 12" ! videoconvert ! qsvh264enc ! h264parse ! mp4mux ! filesink location="c:/tmp/new_bbb_sunflower.mp4"

而透過 gstreamer-sharp 的使用,就能透過以下 C# 程式敘述碼達成上述指令效果:

Gst.Application.Init();
GtkSharp.GstreamerSharp.ObjectManager.Initialize();

var mediaFilePath = System.IO.Path.Combine(OperatingSystem.IsWindows() ? "c:/" : "/", "tmp");

var input = $"{mediaFilePath}/bbb_sunflower.mp4";
var output = $"{mediaFilePath}/new_bbb_sunflower.mp4";

var pipeline = new Pipeline("convert-file-pipeline");

var filesrc = ElementFactory.Make("filesrc", "src");
var demux = ElementFactory.Make("qtdemux", "demux");
var dec = ElementFactory.Make("avdec_h264", "dec");
var overlay = ElementFactory.Make("clockoverlay", "overlay");
var convert = ElementFactory.Make("videoconvert", "convert");
var enc = ElementFactory.Make("qsvh264enc", "enc") ?? ElementFactory.Make("x264enc", "enc");
var parse = ElementFactory.Make("h264parse", "parse");
var mux = ElementFactory.Make("mp4mux", "mux");
var sink = ElementFactory.Make("filesink", "sink");

if (filesrc == null || demux == null || dec == null || overlay == null ||
    convert == null || enc == null || parse == null || mux == null || sink == null)
{
    Console.Error.WriteLine("Failed to create one or more elements.");
    return;
}

filesrc.SetProperty("location", new GLib.Value(input));
overlay.SetProperty("time-format", new GLib.Value("%Y-%m-%d %H:%M:%S"));
overlay.SetProperty("valignment", new GLib.Value(2));
overlay.SetProperty("halignment", new GLib.Value(2));
overlay.SetProperty("xpad", new GLib.Value(12));
overlay.SetProperty("ypad", new GLib.Value(6));
overlay.SetProperty("shaded-background", new GLib.Value(true));
overlay.SetProperty("font-desc", new GLib.Value("Sans, 12"));
sink.SetProperty("location", new GLib.Value(output));

pipeline.Add(filesrc, demux, dec, overlay, convert, enc, parse, mux, sink);
filesrc.Link(demux);
dec.Link(overlay);
overlay.Link(convert);
convert.Link(enc);
enc.Link(parse);
parse.Link(mux);
mux.Link(sink);

demux.PadAdded += (o, e) =>
{
    var sinkPad = dec.GetStaticPad("sink");
    if (sinkPad == null || sinkPad.IsLinked) 
        return;

    var caps = e.NewPad.CurrentCaps ?? e.NewPad.QueryCaps(null);
    var name = caps?.ToString() ?? "";
    if (!name.Contains("video")) 
        return;

    var res = e.NewPad.Link(sinkPad);
    Console.WriteLine($"Linked demux:{e.NewPad.Name} -> dec:sink = {res}");
};

var loop = new GLib.MainLoop();
var bus = pipeline.Bus;
bus.AddSignalWatch();
bus.Message += (o, e) =>
{
    switch (e.Message.Type)
    {
        case MessageType.Error:
            e.Message.ParseError(out var err, out var dbg);
			Console.Error.WriteLine($"Error: {err.Message}{Environment.NewLine}{dbg}");
            loop.Quit();
            break;
        case MessageType.Eos:
            Console.WriteLine("Done.");
            loop.Quit();
            break;
    }
};

pipeline.SetState(State.Playing);
loop.Run();
pipeline.SetState(State.Null);

(上述 C# 程式敘述經 "咒語" 產生,再經過人工初步校閱修改後完成)

透過 LINQPad 的直接執行:
gstreamer-sharp-01

透過 LINQPad 的執行完成:
gstreamer-sharp-02


上一篇
EP 13
系列文
莫名其妙就跟世界等級的 OpenSource 專案攪和了!?14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言