How do I determine which GStreamer plugin decodebin3 selected? - c++

I need to determine which decoder plugin decodebin3 has selected.
I've found that I can't always link it to certain downstream elements after it spawns the source pad. But if I "disable" (change the rank) of a given unusable plugin, I can make my pipeline linkable/functional. I want to dynamically switch the selection, in the event the downstream elements can't link.
The older decodebin had signals like autoplug-select, which looks to have been a means for figuring out the plugins in play. But decodebin3 doesn't have equivalent signals?
When I have debug logging enabled, I have seen the name of the child plugin (which is how can manually disable a "bad" one in POC manner to test my concept). Is there a way to iterate through the children inside a decodebin3?

I figured it out myself. Basically, the element created by this plugin is a "bin" (which is why it's called decodeBIN3!), and therefore one can use gst_bin_iterate_elements to iterate through the child elements within it. Then, it's possible to get the factory an element was produced by, and from there check the type of factory e.g. being a decoder. You can can also get the unique id of the "factory type".
Here are the major functions to use when formulating your own solution for a similar issue. (Sorry it would be a pain, and perhaps confusing, if I posted all the code for my exact use case...)
gst_bin_iterate_elements( GST_BIN( decoder ) );
GstElement *element( GST_ELEMENT_CAST( g_value_peek_pointer( &value ) ) );
GstElementFactory *factory( gst_element_get_factory( element ) );
const gboolean isDecoder( gst_element_factory_list_is_type( factory, GST_ELEMENT_FACTORY_TYPE_DECODER ) );
const GType factoryType( gst_element_factory_get_element_type( factory ) );

Related

How to exchange custom data between Ops in Nuke?

This questions is addressed to developers using C++ and the NDK of Nuke.
Context: Assume a custom Op which implements the interfaces of DD::Image::NoIop and
DD::Image::Executable. The node iterates of a range of frames extracting information at
each frame, which is stored in a custom data structure. An custom knob, which is a member
variable of the above Op (but invisible in the UI), handles the loading and saving
(serialization) of the data structure.
Now I want to exchange that data structure between Ops.
So far I have come up with the following ideas:
Expression linking
Knobs can share information (matrices, etc.) using expression linking.
Can this feature be exploited for custom data as well?
Serialization to image data
The custom data would be serialized and written into a (new) channel. A
node further down the processing tree could grab that and de-serialize
again. Of course, the channel must not be altered between serialization
and de-serialization or else ... this is a hack, I know, but, hey, any port
in a storm!
GeoOp + renderer
In cases where the custom data is purely point-based (which, unfortunately,
it isn't in my case), I could turn the above node into a 3D node and pass
point data to other 3D nodes. At some point a render node would be required
to come back to 2D.
I am going into the correct direction with this? If not, what is a sensible
approach to make this data structure available to other nodes, which rely on the
information contained in it?
This question has been answered on the Nuke-dev mailing list:
If you know the actual class of your Op's input, it's possible to cast the
input to that class type and access it directly. A simple example could be
this snippet below:
//! #file DownstreamOp.cpp
#include "UpstreamOp.h" // The Op that contains your custom data.
// ...
UpstreamOp * upstreamOp = dynamic_cast< UpstreamOp * >( input( 0 ) );
if ( upstreamOp )
{
YourCustomData * data = yourOp->getData();
// ...
}
// ...
UPDATE
Update with reference to a question that I received via email:
I am trying to do this exact same thing, pass custom data from one Iop
plugin to another.
But these two plugins are defined in different dso/dll files.
How did you get this to work ?
Short answer:
Compile your Ops into a single shared object.
Long answer:
Say
UpstreamOp.cpp
DownstreamOp.cpp
define the depending Ops.
In a first attempt I compiled the first plugin using only UpstreamOp.cpp,
as usual. For the second plugin I compiled both DownstreamOp.cpp and
UpstreamOp.cpp into that plugin.
Strangely enough that worked (on Linux; didn't test Windows).
However, by overriding
bool Op::test_input( int input, Op * op ) const;
things will break. Creating and saving a Comp using the above plugins still
works. But loading that same Comp again breaks the connection in the node graph
between UpstreamOp and DownstreamOp and it is no longer possible to connect
them again.
My hypothesis is this: since both plugins contain symbols for UpstreamOp it
depends on the load order of the plugins if a node uses instances of UpstreamOp
from the first or from the second plugin. So, if UpstreamOp from the first plugin
is used then any dynamic_cast in Op::test_input() will fail and the two Op cannot
be connected anymore.
It is still surprising that Nuke would even bother to start at all with the above
configuration, since it can be rather picky about symbols from plugins, e.g if they
are missing.
Anyway, to get around this problem I did the following:
compile both Ops into a single shared object, e.g. myplugins.so, and
add TCL script or Python script (init.py/menu.py)which instructs Nuke how to load
the Ops correctly.
An example for a TCL scripts can be found in the dev guide and the instructions
for your menu.py could be something like this
menu = nuke.menu( 'Nodes' ).addMenu( 'my-plugins' )
menu.addCommand('UpstreamOp', lambda: nuke.createNode('UpstreamOp'))
menu.addCommand('DownstreamOp', lambda: nuke.createNode('DownstreamOp'))
nuke.load('myplugins')
So far, this works reliably for us (on Linux & Windows, haven't tested Mac).

Gstreamer element properties that depend on another property

I am writing a gstreamer element, and I want to add a property that selects the algorithm that the element will use to perform its function.
gst-launch ... ! myelement algo=1 ! ...
Now, suppose I have two alghoritms, and I need to be able to specify different parameters for each algorithm, and naturally I would want that the user is able to set these parameters through properties.
For example, algorithm 1 would use a property named x:
gst-launch ... ! myelement algo=1 x=10 ! ...
But algorithm 2 would use a property named y (and it doesn't need x):
gst-launch ... ! myelement algo=2 y=20 ! ...
Essentially, some properties will have meaning only depending on the value of another property.
What is the standard way of handling this? Should I add properties 'x' and 'y' and document that 'x' only works when algo=1 and 'y' only works when algo=2?
Or, should I forget about the 'algo' property and make two different elements?
To look for a standard way to handle things in gstreamer is always a good idea to check what other elements do. A great example for this case could be the element 'multifilesink' which has several ways to handle file segmentation; looking at the properties (running gst-inspect multifilesink on the cmdline) you can see that the property "max-file-size" only makes sense if the "next-file" property is set to 4, thus its description is used to specify it :
" max-file-size : Maximum file size before starting a new file in max-size mode "

Boost.Log: how to filter by current thread id

I'm using Boost.Log, which is a part of Boost v1.54. I have a sink, which I want to only accept log messages from the current thread. How can I achieve that?
BOOST_LOG_ATTRIBUTE_KEYWORD(thread_id, "ThreadID", logging::attributes::current_thread_id::value_type)
std::stringstream stream;
logging::add_common_attributes();
boost::shared_ptr<text_sink> sink = boost::make_shared<text_sink>();
sink->locked_backend()->add_stream(stream);
logging::core::get()->add_sink(sink);
boost::thread::id currentThreadId = boost::this_thread::get_id();
// At this line compiler complains about the '==' operator.
sink->set_filter(thread_id == currentThreadId);
Without the last line everything works fine, and when I configure sink formatter, it outputs the calling thread ID. What is the proper way to compare thread_id attribute with the currentThreadId?
I know I can use some custom attribute to tag messages with the current thread ID, and then filter them by that attribute, but what about the default boost's current_thread_id attribute? Is it usable for such a purpose?
Well, after spending half the night digging around I came across the (undocumented?) boost::log::aux namespace, where I found boost::log::aux::this_thread::get_id() function. It returns an object of the proper type which I am now able to compare with the thread_id keyword.
Now I wonder if the boost::log::aux namespace is meant for boost internal use only? Some time ago I used to utilize some internal features of boost mutexes/locks, and after the next library update they changed everything and I couldn't even compile my code against that new version of the library. So now I don't want to repeat my past mistakes :)

How to protect DLL functionality, or getting where it has been imported?

I would like to limit who/what can use my C++ DLL. I have an .mq4 script ( or it can be anything else I guess ) and I use DLL-#import-ed functions in it.
How I want to do the limitation is: there is a static filepath in the DLL, and at the begining of every function I just calculate a new checksum ( sha1 ) of the file ( where filepath points to ) and compare it to the original checksum ( also static ). It's good, because if someone modify the .mq4, the function will not work.
My problem is: If I just leave the original .mq4 there, and I create a new one, importing the DLL in there, I can use the DLL with no problem, because in the DLL I'm checking the original .mq4, ( where the static filepath points to ) not where I have used it from.
So somehow I should figure it out, where the DLL has been imported and check the sum of that file. Or maybe there is another technique, I don't know.
A principal solution: ( without a relation to the dilemma of "License or not License?" )
for the purpose of knowing who-imported / who-called a DLL-function, the conventional #import mechanics are too lightweight and principally open-source'd to potentional attacker.
The strongest and smartest and hardly paralleled protection ever seen is, by design, in occam parallel execution language ( used for transputers ), where caller and callee either have an agreement on communication protocol or not. So no one can hijack and use remote service just by sending an "un-solicited" call.
The second closest are ( occam-legacy followers ) languages with support for a CSP-based scheme - be it python, Go or other CSP-conformant engine.
( life-long victims of their own methods exposed to public )
The rest of world get used to live in an environment, where objects and DLL-s are endlessly vulnerable to attackers who may at any moment overload / mis-use any DLL-service or object method, while the DLL-side or the object instance has no way to protect itself and reject / deny a service once a caller is not permitted / allowed to ask for such a service.
MQL4 has an ability to communicate with CSP-"safe" environments, so if you indeed have such need, make your MQL4-side connected to the remote-side and benefit the CSP-safety to avoid unauthorised use of a service.
Proxy-mediator
In case you do not want to move that far, try to mediate your C++ DLL with a proxy, that:
enforces caller-identity per-call self-presentation
mediates caller-identity bound per-call reference-counting / checks
prevents fake-caller from hijacking the mediator node to gain target DLL access
preserves the mediator<->target handshaking details hidden from MQL4 side

Webkit GTK: Using the DOM Tree Walker

So, I'm experimenting with Webkit GTK DOM functions. It's pretty straightforward, except for one thing: there's a useful part of the API called the WebKitDOMTreeWalker which, I assume, lets you walk over each node in the DOM, just like the TreeWalker object in Javascript.
Now, in Javascript a TreeWalker is created by calling:
document.createTreeWalker(root, nodesToShow, filter, entityExpandBol)
So, in WebKit GTK, there is an obvious counterpart in the API - a function called webkit_dom_document_create_tree_walker. The function signature is:
WebKitDOMTreeWalker* webkit_dom_document_create_tree_walker(WebKitDOMDocument* self, WebKitDOMNode* root, gulong what_to_show, WebKitDOMNodeFilter* filter, gboolean expand_entity_references, GError **error);
So creating a TreeWalker with WebKit GTK seems pretty straightforward - except for one big problem: the fourth argument in the webkit_dom_document_create_tree_walker expects a filter object, that is, it wants an instance of WebKitDOMNodeFilter. Well, the Javascript function also takes a filter, but you can pass null if you don't want to use a filter. With the Webkit API, passing NULL doesn't work. If you call:
WebKitDOMTreeWalker* walker = webkit_dom_document_create_tree_walker(doc, root, SHOW_ALL, NULL, false, err)
You get the error message:
** (webkit:3367): CRITICAL : WebKitDOMTreeWalker* webkit_dom_document_create_tree_walker(WebKitDOMDocument*,
WebKitDOMNode*, gulong, WebKitDOMNodeFilter*, gboolean, GError):
assertion `filter' failed
So, the WebKit API won't accept a NULL pointer for the filter argument. Evidently you need to pass an instance of a WebKitDOMNodeFilter. Okay, again - this wouldn't be a problem either, except I've searched far and wide through the WebKit API, as well as Google, and I can't find anyway to create a WebKitDOMNodeFilter object! The header file for WebKitDOMNodeFilter.h doesn't expose any constructor for WebKitDOMNodeFilter. It seems like the API doesn't ever expose anyway to actually construct a WebKitDOMNodeFilter object at all.
Yet... the API exposes many functions (like webkit_dom_document_create_tree_walker, and webkit_dom_document_create_node_iterator) which require a WebKitDOMNodeFilter. So... is the API just incomplete right now? Or, is there some way to create a Filter object which I'm just not seeing?
Can you try casting your null to the WebKitDOMNodeFilter type by calling
WEBKIT_DOM_NODE_FILTER(null)?