[haiku-development] Streaming infrastructure design

  • From: Dario Casalinuovo <b.vitruvio@xxxxxxxxx>
  • To: haiku-development@xxxxxxxxxxxxx
  • Date: Thu, 26 May 2016 20:43:12 +0200

Hello,
I looked another time at discussions relating how to implement correctly
the internals needed for streaming. To summarize the major problems pointed
out at the time are the following :

a) Avoid fetching downloaded data twice
b) Differentiate between true seekable/forwardable and only remotely
positionable streams
c) Add ways to identify endless streams

Additional problems I want to point out :

d) For network streaming we don't have other options than having a
background thread receive the data and the client thread read it when it's
available.
e) The point before imply that we need some kind of backend-write/wait and
client-read/wait
f) Since ideally we want to support streaming for both client and server
mode, it makes things more complex, BMediaFile is basically what the name
suggests and will need a serious review to safely support these modes.

Then my considerations / how I solved the problem :

a) The internal MediaIOWrapper can read from that object, to say, the first
2048 kb and pause any other caching until some plugin recognized the
format. When this happened it can move to another modality, where the first
reads determine the block size and subsequent behavior. As pointed out,
it's not easy to define how much data to cache and for how much time it
should be cached, I think we can take this decision depending on the data
kind and maybe the streamer directives. At this point I don't consider this
issue a priority, then I'm planning to just cache everything for now.

b) If I understand correctly, the point isn't just to identify if something
is seekable, but if it can be fastly seeked or not. I added the
IsSeekable() method to BMediaIO, but I'm not sure it fits completely the
problem, read above.

c) I added BMediaIO::IsEndless(), for this purpose I think it's enough.

But thinking of the whole global thing and to make it more future proof, I
formulated the following BMediaIO flags scheme, I'm not 100% sure it's
completely right, that's why I'm submitting it here so that it can be
discussed :

enum media_io_flags {

// Same as IsEndless()
B_MEDIA_IS_ENDLESS

// Used to recognize non local sources or big data sources
B_MEDIA_IS_SLOW

// The BMediaIO can seek forward, can we have an B_MEDIA_ENDLESS stream
that is also seekable forward?
B_MEDIA_SEEK_FORWARD

// Can seek backward
B_MEDIA_SEEK_BACKWARD

B_MEDIA_IS_SEEKABLE = B_MEDIA_SEEK_FORWARD | B_MEDIA_SEEK_BACKWARD
}


Continuing on other points :

d/e) The problem here is that I don't think BMediaIO should provide support
for all things. Basically we have the following situation common to almost
all the network streams :

* client Read() (eventually lock if there's no data, ReadLock() before
reading the buffer)
* backend Write() (and WriteUnlock())

For servers we have the opposite situation :

* backend(s) Read()
* client(s) Write()

First problem: one of the two entities will need to have the position
restored after a write or a read.

We want this functionality to don't be duplicated, and I can think of two
ways to work with it :

* Have the BMediaIO to support this directly and transparently using just
the BPositionIO methods, provide lock/unlock methods, set in server or
client modality where respectively read or write position is restored after
a backend operation. (Well we might support for blocks and contemporary R/W
if there are not conflicts so provide a BMultiIO, but let's keep it simple
for now). In this case a BMediaIO will have to implement both Read and
Write methods and understand in which situation it's operating, that might
make room for disaster. Similar considerations apply abot how to implement
a Position() method.

* Have the BMediaIO support a sort of consumer/supplier modality that
losely corresponds to client/server, maybe providing two additional classes
for doing that. Ergo, provide two R/W protected methods, accessible only by
a plugin that solves the problem I've exposed before in a "protected" way.
In that case the BMediaIO is free to implement BPositionIO methods as he
want, for example a client can just refuse WriteAt as the backend will use
the protected functionality to write data.

* One of the two but implement it only in the BMediaIOWrapper is the third
side of the coin.

f) What I'm thinking is that a streamer can provide two flags and the
sniffing process deal with it to decide if what BMediaFile is asking is
doable :

B_CLIENT_STREAMER

B_SERVER_STREAMER

That's all I think.

-- 
Best Regards,
Dario

Other related posts:

  • » [haiku-development] Streaming infrastructure design - Dario Casalinuovo