How do you push data after initialization, i.e. while streaming?
The same way. Get the read position, read and push data until we get the samples we want. We don't need a thread here, especially not in MF case where everything is or can be done asynchronously already, including the reads.
Ah, so you do it from RequestSample() [well, wait_on_sample() really, but anyway.]
So it's worth noting that if that approach works, there's actually nothing preventing you from doing the same thing for pull mode. It would require API change, because now you need to wait for *either* a getrange *or* a sample, but it's possible. It would probably mean a return to something closer to the old winegstreamer design, which was a more generic form of RPC that marshalled all manner of internal calls onto the main thread.
Do we want this change? Well... maybe? I'm not sure that just getting rid of a thread is going to reduce complexity, but I'd have to see the code.
One problem, though, is that now you can't buffer as easily. I think this is less of a problem for mfplat, which has a weird API that results in always buffering anyway, but it's definitely a problem for quartz (and wmvcore for that matter, but see below). If all the streaming threads are currently in Receive() downstream, nothing will be processing getrange requests upstream, which means that as soon as we have a sample available we may not be buffering any more. This may or may not be a problem in practice, it depends on a lot of unknowns, but it at least makes me nervous.
Another thing worth mentioning is that native quartz doesn't work that way. I haven't checked all parsers, but mpegsplit at least creates a read thread internally. We could change native quartz to avoid the read thread anyway, but... I hesitate to move away from native behaviour for what right now seems like a questionable change in code simplicity.
(On the other hand, native wmvcore *does* work that way—it doesn't seem to have a separate read thread. So that's something to consider if anything changes.)
So while getting rid of the read thread would make things simpler in some ways, it seems a questionable benefit to me if we can't get rid of it everywhere. It's still a problem that has to be solved, and once it's solved in one frontend the solution can be (and is!) copy-pasted to the others.
Actually, along those lines, one thing I've considered, but never gotten around to doing, is writing some common PE-side code that would take care of the read thread abstraction, including abstracting create/connect and disconnect/destroy as a single function (since right now those only exist in two pieces for the sake of the read thread).
Ah, sure, but we also don't *need* to autoplug immediately. I don't know if I described this idea before, but what we can do is defer stream autoplugging to later. This should be quite simple, just a matter of moving some code from pad_added_cb() to a function lazily called by wg_parser_stream_enable() or wg_parser_stream_get_preferred_format() [I think those are the only places that matter].
More importantly, though, if we're going to be outputting compressed formats for those videos that need fast media source initialization, then we don't even need to worry about autoplugging overhead, because we won't need to autoplug. Currently we do anyway, in order to support toggling at runtime between encoded and unencoded video, but I have my doubts about the utility of that feature.
We still need it because we put everything in the same pipeline. Building the pipeline lazily by adding some decoding elements later will require it to be stopped and started again. This adds even more complexity to wg_parser only for the purpose of making it optionally do something simpler. Instead, we should do always something simple, by decoupling the demuxing from the decoding, like it's also supposed to be.
Indeed you're right, I was under the mistaken impression that you could hotplug in GStreamer. While gst_pad_unlink() allows it (unlike the equivalent function in DirectShow), the parser will subsequently get GST_FLOW_RETURN and yield an error. Even if things work anyway after that, that's not something we should depend on.
We can still just skip demuxing for those formats, though, and I imagine that'll be enough. We needed to do that for other reasons, and that happily should solve the application bug for free.
Sure, that's understandable. But the right thing to do isn't always the least risky thing to do. I think in this case the right thing to do is keep the wg_parser interface, making incremental changes to it and its backends if necessary.
I'm not saying that the wg_parser interface is perfect and doesn't need changes, far from it. There are things I don't like about it currently, though I haven't yet come up with a satisfactory way to improve them. But those changes can be done without rewriting the whole thing.
Maybe it's not satisfactory because it tries to do everything at the same time. I don't think that's a good idea, and instead we should compose simple elements together. For MF, the composition is already done on the PE side because we needed it, so now it's just a matter of implementing the simple demuxer element.
I completely understand why it feels like wg_parser is trying to do everything at once—after all, it wraps a whole GstPipeline, it autoplugs decoders and demuxers, and in general it's not a simple piece of code.
The problem is that you can't really just break up wg_parser. Almost all of the complexity of wg_parser (including pull mode) really inheres to the *parser* side of things. The only real difference between a parser and a complete pipeline is the specific formats they output. You can really tell this by comparing avi_parser_init_gst() to decodebin_parser_init_gst().
If we were, hypothetically, to remove decodebin support from wg_parser, the only thing we'd be able to simplify is that we'd be able to remove videoconvert and audioconvert, and get rid of the logic that allows us to pick the output format from sink_query_cb(). That's all. [And that's assuming that demuxers never output multiple formats, which... I assume is the case, but I don't know for sure.]
There is one piece of wg_parser that can be broken off in some sense, which is the stream decodebin. And, as I've mentioned, my inclination is that we should indeed break this off. I don't think it's solving a problem that matters, and frankly, even if it was, I'd prefer a less iffy way to do it.