From 926295449a12b8fb51632b1823f0ce6995031254 Mon Sep 17 00:00:00 2001
From: Davide Depau <davide@depau.eu>
Date: Fri, 26 Jan 2018 15:38:14 +0100
Subject: [PATCH 1/4] Ensure outgoing edge map is sorted by upstream label

---
 ffmpeg/dag.py | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/ffmpeg/dag.py b/ffmpeg/dag.py
index 3ce3891..86c695f 100644
--- a/ffmpeg/dag.py
+++ b/ffmpeg/dag.py
@@ -2,7 +2,7 @@ from __future__ import unicode_literals
 
 from ._utils import get_hash, get_hash_int
 from builtins import object
-from collections import namedtuple
+from collections import namedtuple, OrderedDict
 
 
 class DagNode(object):
@@ -157,7 +157,7 @@ def topo_sort(downstream_nodes):
             raise RuntimeError('Graph is not a DAG')
 
         if downstream_node is not None:
-            outgoing_edge_map = outgoing_edge_maps.get(upstream_node, {})
+            outgoing_edge_map = outgoing_edge_maps.get(upstream_node, OrderedDict())
             outgoing_edge_infos = outgoing_edge_map.get(upstream_label, [])
             outgoing_edge_infos += [(downstream_node, downstream_label)]
             outgoing_edge_map[upstream_label] = outgoing_edge_infos
@@ -174,4 +174,10 @@ def topo_sort(downstream_nodes):
     while unmarked_nodes:
         upstream_node, upstream_label = unmarked_nodes.pop()
         visit(upstream_node, upstream_label, None, None)
+
+    # Sort outgoing edge maps by upstream label
+    for map in outgoing_edge_maps.values():
+        for label in sorted(map.keys()):
+            map.move_to_end(label)
+
     return sorted_nodes, outgoing_edge_maps

From b7455d3261033c202fc78fb53a3391b1d3924b81 Mon Sep 17 00:00:00 2001
From: Davide Depau <davide@depau.eu>
Date: Fri, 26 Jan 2018 16:02:31 +0100
Subject: [PATCH 2/4] Move OrderedDict sorting code to own function

---
 ffmpeg/_utils.py | 6 ++++++
 ffmpeg/dag.py    | 5 ++---
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/ffmpeg/_utils.py b/ffmpeg/_utils.py
index 9b575a0..d3acc4c 100644
--- a/ffmpeg/_utils.py
+++ b/ffmpeg/_utils.py
@@ -27,6 +27,7 @@ def get_hash(item):
     repr_ = _recursive_repr(item).encode('utf-8')
     return hashlib.md5(repr_).hexdigest()
 
+
 def get_hash_int(item):
     return int(get_hash(item), base=16)
 
@@ -41,3 +42,8 @@ def escape_chars(text, chars):
     for ch in chars:
         text = text.replace(ch, '\\' + ch)
     return text
+
+
+def sort_ordereddict(d):
+    for key in sorted(d.keys()):
+        d.move_to_end(key)
diff --git a/ffmpeg/dag.py b/ffmpeg/dag.py
index 86c695f..7e6b91e 100644
--- a/ffmpeg/dag.py
+++ b/ffmpeg/dag.py
@@ -1,6 +1,6 @@
 from __future__ import unicode_literals
 
-from ._utils import get_hash, get_hash_int
+from ._utils import get_hash, get_hash_int, sort_ordereddict
 from builtins import object
 from collections import namedtuple, OrderedDict
 
@@ -177,7 +177,6 @@ def topo_sort(downstream_nodes):
 
     # Sort outgoing edge maps by upstream label
     for map in outgoing_edge_maps.values():
-        for label in sorted(map.keys()):
-            map.move_to_end(label)
+        sort_ordereddict(map)
 
     return sorted_nodes, outgoing_edge_maps

From b4e8c38b68402f15d6a74ef56fe4c6843669115d Mon Sep 17 00:00:00 2001
From: Davide Depau <davide@depau.eu>
Date: Fri, 26 Jan 2018 16:05:56 +0100
Subject: [PATCH 3/4] Also ensure sortedness of incoming edge map

---
 ffmpeg/nodes.py | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/ffmpeg/nodes.py b/ffmpeg/nodes.py
index 2b4c94f..749cc74 100644
--- a/ffmpeg/nodes.py
+++ b/ffmpeg/nodes.py
@@ -1,5 +1,7 @@
 from __future__ import unicode_literals
 
+from collections import OrderedDict
+
 from .dag import KwargReprNode
 from ._utils import escape_chars, get_hash_int
 from builtins import object
@@ -46,7 +48,7 @@ def get_stream_map(stream_spec):
     elif isinstance(stream_spec, Stream):
         stream_map = {None: stream_spec}
     elif isinstance(stream_spec, (list, tuple)):
-        stream_map = dict(enumerate(stream_spec))
+        stream_map = OrderedDict(enumerate(stream_spec))
     elif isinstance(stream_spec, dict):
         stream_map = stream_spec
     return stream_map
@@ -84,7 +86,7 @@ class Node(KwargReprNode):
 
     @classmethod
     def __get_incoming_edge_map(cls, stream_map):
-        incoming_edge_map = {}
+        incoming_edge_map = OrderedDict()
         for downstream_label, upstream in list(stream_map.items()):
             incoming_edge_map[downstream_label] = (upstream.node, upstream.label)
         return incoming_edge_map

From 34cc51d95d915fb2400e50c1c04e088520f41c75 Mon Sep 17 00:00:00 2001
From: Davide Depau <davide@depau.eu>
Date: Fri, 26 Jan 2018 16:13:39 +0100
Subject: [PATCH 4/4] Replace OrderedDict.move_to_end with Python2-compatible
 alternative

---
 ffmpeg/_utils.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ffmpeg/_utils.py b/ffmpeg/_utils.py
index d3acc4c..0c10d4f 100644
--- a/ffmpeg/_utils.py
+++ b/ffmpeg/_utils.py
@@ -46,4 +46,4 @@ def escape_chars(text, chars):
 
 def sort_ordereddict(d):
     for key in sorted(d.keys()):
-        d.move_to_end(key)
+        d[key] = d.pop(key)