gtkd-developers / GtkD

GtkD is a D binding and OO wrapper of GTK+ originally created by Antonio Monteiro
http://gtkd.org
Other
322 stars 71 forks source link

GStreamer hello world fails #166

Closed deviator closed 7 years ago

deviator commented 7 years ago

I try rewrite gstreamers hello world to D, using gtk-d and get strange error about not linked pads.

My source code on D:

import std.stdio;
import std.exception;
import std.string;

import gstreamer.GStreamer;
import gstreamer.Pipeline;
import gstreamer.Element;
import gstreamer.ElementFactory;
import gstreamer.Pad;
import gstreamer.Message;

import glib.MainContext;
import glib.ErrorG;
import glib.MainLoop;

void main(string[] args)
{
    enforce(args.length == 2, format("Usage: %s <Ogg/Vorbis filename>", args[0]));

    GStreamer.init(args);
    auto loop = new MainLoop(cast(MainContext)null, false);

    bool bus_call(Message msg)
    {
        switch (msg.type)
        {
            case GstMessageType.EOS:
                stdout.writeln("End of stream");
                loop.quit();
                break;
            case GstMessageType.ERROR:
                string dbg;
                ErrorG error;
                msg.parseError(error, dbg);
                stderr.writefln("Error: %s", error.getErrorGStruct.message.fromStringz);
                stderr.writeln("Debug info: ", dbg);
                loop.quit();
                break;
            default:
                break;
        }
        return true;
    }

    auto pipeline = new Pipeline("audio-player");
    auto source   = enforce(ElementFactory.make("filesrc",       "file-source"));
    auto demuxer  = enforce(ElementFactory.make("oggdemux",      "ogg-demuxer"));
    auto decoder  = enforce(ElementFactory.make("vorbisdec",     "vorbis-decoder"));
    auto conv     = enforce(ElementFactory.make("audioconvert",  "converter"));
    auto sink     = enforce(ElementFactory.make("autoaudiosink", "audio-output"));

    source.location(args[1]);

    /* we add a message handler */
    auto bus = pipeline.getBus();
    auto bus_watch_id = bus.addWatch(&bus_call);
    bus.unref();

    pipeline.addMany(source, demuxer, decoder, conv, sink);

    /* file-source -> ogg-demuxer ~> vorbis-decoder -> converter -> alsa-output */
    source.link(demuxer);

    demuxer.addOnPadAdded((pad, decoder)
    {
        stderr.writeln("Dynamic pad created, linking demuxer/decoder");
        auto sink = decoder.getStaticPad("sink");
        stderr.writeln("sink: ", sink); // not null
        stderr.writeln(pad.link(sink)); // WAS_LINKED
    });

    decoder.link(conv);
    conv.link(sink);

    stderr.writefln("Now playing: %s", args[1]);
    pipeline.setState(GstState.PLAYING);

    stderr.writeln("Running...");
    loop.run();

    stderr.writeln("Returned, stopping playback");
    pipeline.setState(GstState.NULL);

    stderr.writeln("Deleting pipeline");
    pipeline.unref();
    loop.unref();
}

I get this output:

Now playing: neutrino.ogg
Running...
Dynamic pad created, linking demuxer/decoder
sink: gstreamer.Pad.Pad
WAS_LINKED
Error: Internal data stream error.
Debug info: gstoggdemux.c(4849): gst_ogg_demux_loop (): /GstPipeline:audio-player/GstOggDemux:ogg-demuxer:
stream stopped, reason not-linked
Returned, stopping playback
Deleting pipeline

If I don't use dynamic linking pads all works fine (audiotestsrc -> autoaudiosink). If I compile C hello world all works fine (from gstreamer.freedesktop.org/documentation/).

uname -a
Linux lenovo 4.8.10-200.fc24.x86_64
dmd --version
DMD64 D Compiler v2.072.1
dub --version
DUB version 1.1.1, built on Nov 30 2016

dub.sdl

name "audiodisint"
description "Audio test"
authors "deviator"
copyright "Copyright © 2016, deviator"
license "MIT"
dependency "gtk-d:gstreamer" version="~>3.3.1"

build as dub build

MikeWey commented 7 years ago

In the addOnPadAdded callback you will need to use the decoder from the outer scope. Change the name of the element passed to the callback en it will work.

Like this:

demuxer.addOnPadAdded((pad, element)
{
    stderr.writeln("Dynamic pad created, linking demuxer/decoder");
    auto sink = decoder.getStaticPad("sink");
    stderr.writeln("sink: ", sink); // not null
    stderr.writeln(pad.link(sink)); // WAS_LINKED
});
deviator commented 7 years ago

Ohh... element in callback is a demuxer... Thanks!