question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Outgoing edges of nodes should be sorted based on when a call `.stream()` created them

See original GitHub issue
i = ffmpeg.input("f1.mp4")
ref = ffmpeg.input("f2.mp4")
# BTW `filter_multi_output` is not in __all__, needs #65
s2ref = ffmpeg.filter_([i, ref], "scale2ref").node
scaled = s2ref[0]
ref2 = s2ref[1]

https://ffmpeg.org/ffmpeg-all.html#scale2ref

Screenshot_from_2018-01-26_14-33-23.png

You would expect the output of scale2ref labeled 0 (scaled) to be the first output of scale2ref (because .stream() was called first), and 1 (ref2) to be the second. However, this doesn’t always happen: it’s totally up to topo_sort().

I’ll try to fix it and send a PR.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:10 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
komar007commented, Jul 1, 2019

Here’s a unit test which reproduces the issue:

def test__multi_output_edge_label_order():
    scale2ref = ffmpeg.filter_multi_output([ffmpeg.input('x'), ffmpeg.input('y')], 'scale2ref')
    out = (
        ffmpeg.merge_outputs(
            scale2ref[1].filter('scale').output('a'),
            scale2ref[10000].filter('hflip').output('b')
        )
    )

    args = out.get_args()
    assert args == [
        '-i',
        'x',
        '-i',
        'y',
        '-filter_complex',
        '[0][1]scale2ref[s0][s1];[s0]scale[s2];[s1]hflip[s3]',
        '-map',
        '[s2]',
        'a',
        '-map',
        '[s3]',
        'b'
    ]

Python has optimizations for small numbers and short strings, so it’s likely that dicts with keys like 1, 2 or 3 will enumerate in ascending order. Use 1 and 10000 and the order is no longer maintained.

@kkroening the simpler solution you proposed will not work (at least now, in 2019, because I haven’t traced the changes in the code since your comment), you’d also have to fix get_incoming_edges in the same way.

@Depau 's proposition fixes the issue by returning the edges sorted correctly from topo_sort. Assuming it’s okay to put that responsibility on topo_sort, I have a simpler solution, let’s return lists of tuples instead - I have to verify this, but it looks like the dicts are currently only iterated and never accessed randomly - so there should be no performance penalty. I can publish my changes tomorrow.

If you don’t think it should be topo_sort’s responsibility to sort multiple outgoing edges by label, then I have verified that iterating sorted items() both in _allocate_filter_stream_names and get_incoming_edges fixes the issue.

0reactions
komar007commented, Jul 2, 2019

@153957 Python 3.6 maintains insertion order of dict elements, not order based on comparison of keys. Still, it’s an implementation detail of python 3.6 and insertion order is only guaranteed by spec from python 3.7 onwards.

I think we agree that in case of nodes returned from .stream(x) we should not take order of any calls into consideration as that could case codes like:

out1, out2 = filter.stream(0), filter.stream(1)

to behave differently than:

out2, out1 = filter.stream(1), filter.stream(0)

It seems to me that label values are currently the only caller-provided source of information about the intentional order of outputs from multiple-output filters. Currently, the labels are never compared explicitly, making the order of outputs of multiple-output filters completely implementation-dependent, as shown by the example test I provided.

I hope this clears things up a bit.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Getting all edges going out from a node in jgrapht
You can access the outgoing edges of a node(vertex) with outgoingEdgesOf method of a graph object. Set<MyEdge> edges = myGraph.
Read more >
Java 8 – How to Sort List with Stream.sorted() - Stack Abuse
In this tutorial guide, we'll cover everything you need to know about the Stream.sorted() API. We'll sort integers, strings and custom ...
Read more >
Stream sorted() in Java - GeeksforGeeks
Stream sorted() returns a stream consisting of the elements of this stream, sorted according to natural order. For ordered streams, the sort ......
Read more >
Recipes - Apache TinkerPop
The vertex with identifier "1" has all outgoing edges, so it would also be acceptable to use the directional steps of outE() and...
Read more >
PRACTICAL GREMLIN: An Apache TinkerPop Tutorial
Edges represent connections between those vertices, and properties are information added to the vertices and edges as needed. The directed part ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found