Hi,
I'm replying to message 1/8, but it really applies to whole set. Could you explain how this works without going into details too much, e.g. some questions that I got so far:
- top level function first identifies pairs of {source, sink} paths as branches, and that seems reasonable for trivial cases of 1:1 transforms, and no tee nodes.
How could this be used in generic case when you have some of the above? For tee node case for example, with single source and two sinks that will give two paths/pairs, while in fact, assuming sinks use same type for now, you only need to resolve from source to tee node. Same for n:m transform (is that even supported in default loader?), that gives (n x m) branches when n sources are connected to m sinks?
I think generic way would be to resolve connections, independently or as independently as transforms allow, not from every source to sink, but from {node1, output_index} -> {node2, input_index}.
- resolution seems to start with source nodes (and I apologize if I got it wrong), is that correct? Is there an evidence that it works that way?
AFAIK user is expected to specify sink types, and that's the goal - to construct a graph that delivers such output type, if possible. Wouldn't it make sense to start from output types instead, and follow paths upstream? Sink could only be connected to source directly, transform output, or a tee. First case is trivial, transform will give you a list of what it can output to choose from, you can then add more transforms if necessary. For tee node, it will likely be dictated by primary output type.
Source nodes however could be in theory more flexible, capture sources might provide several output format and you can pick best suited one, to avoid conversion/resampling/etc.
- why is it useful to have lists of whole topology instances?
- what does connection method really do. I didn't get this part in particular:
2780 hr = IMFAttributes_GetUINT32(attrs_src, &MF_TOPONODE_CONNECT_METHOD, &method); 2781 if (!enum_src_types || (hr == S_OK && !(method & MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES))) 2782 { 2783 for (method = MF_CONNECT_DIRECT; method < MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES; method++) 2784 { 2785 for (i = 0; i < num_media_types; i++) 2786 { 2787 IMFMediaTypeHandler_SetCurrentMediaType(mth_src, src_mediatypes[i]); 2788 if (SUCCEEDED(hr = topology_loader_resolve_branch_connect_nodes(full_topology, src->id, method))) 2789 goto out; 2790 } 2791 } 2792 } 2793 else 2794 { 2795 for (i = 0; i < num_media_types; i++) 2796 { 2797 for (method = MF_CONNECT_DIRECT; method < MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES; method++) 2798 { 2799 IMFMediaTypeHandler_SetCurrentMediaType(mth_src, src_mediatypes[i]); 2800 if (SUCCEEDED(hr = topology_loader_resolve_branch_connect_nodes(full_topology, src->id, method))) 2801 goto out; 2802 } 2803 } 2804 }
First source attribute is checked with MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES as a mask, and its actual value then is never used; and second - following loops iterate in [0,4), when only defined values are 0,1,3, and 4, plus some higher bits for OPTIONAL flags.
I can understand that DIRECT means that no decoders and no converters are allowed, and branch is not optional, so if direct connect fails, whole resolution fails. But what happens with method == 2? It's clear what loop reordering does here, and that's how it's documented, but going back to previous point, you can do that as last step too, after sinks are connected and configured.
Also, does MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES actually apply to sources only as docs say? Do we apply other methods set with MF_TOPONODE_CONNECT_METHOD for other node types?