Closed sak96 closed 1 year ago
there is currently no easy way to read, you have to do it a bit manually, unfortunately the project was put on hold before i got there.
You ned two things: A reader that is AsyncRead + AsyncSeek + Unpin + Send + Sync
like an AsyncSTD cursor
and then simply:
let header = BoxHeader::read(&mut reader).await?; // The Mp4Readable read
let ftyp = FtypBox::read(header, &mut reader).await?; // The BoxRead trait read
// read other boxes like the previous, ideally with an enum based on the ID of what you expect.
one of the tests goes like this:
let base = Box::default();
let mut buf = vec![];
let mut cursor = std::io::Cursor::new(&mut buf);
let pos = base.write(&mut cursor)?;
assert_eq!(pos, base.byte_size());
assert_eq!(pos as u64, cursor.position());
let mut cursor = futures::io::Cursor::new(&mut buf);
let header = BoxHeader::read(&mut cursor).await?;
assert_eq!(header.id, Box::ID);
let new = Box::read(header, &mut cursor).await?;
assert_eq!(base, new);
Ok(())
Creating a proper easy to use reader wouldn't be too complicated, either with dyn Any + Other traits, or an enum. That would be a great PR if it's something you enjoy :)
Hi,
Thanks for reply. I will go through the test cases then. I am not in good term with trait, but i can try that is, if i am comfortable
my reader was std::net::TcpStream
i moved to use futures_net::TcpStream
.
But that one implements futures_io::AsyncRead
and not futures::io::AsyncRead
.
Do you have any idea of crate which has TcpStream
and implements futures::AsyncRead
and is lightweight.
You have async_std::net::TcpStream, but since you need seek wrap it in a async_std::io::BufReader. You may also need to pin it, in that case use Box::pin() Hope it helps :)
Hey i think i am getting hang of stuff now.
Looks like Bufreader doesn't provide asyncSeek.
i am assuming seek if like fseek
systemcall.
The issue i see is that there is no way of know how much buffer is required. you might do seek of 0 that means go to the beginning of stream. Do i have to store all the data from start of stream ?
In principle, to be sure you can parse all kinds of MP4 you need to store the whole stream, even if you can start parsing before the end. But if you know where the mdats are and store the data separately with their proper offsets like in a fragmented mp4 then you don't really need to seek i think. Maybe it would be wise to create a reader made for the use. To be fair i didn't use the read part of the library much, i mostly used it to convert from mkv to mp4.
ah i see, here is the use: it's quite necessary to keep track of the position... https://github.com/Wicpar/async-mp4/blob/902ddff30e8fd55e7966054f119b53ac98db37e2/src/mp4box/box_root.rs#L64-L91
To be fair, reading linearly could still be possible, but a bug in one of the boxes implementation could corrupt the whole parsing... I deemed it too much of a risk back then, but seek is indeed quite a constraint, maybe it's time to rework that...
futures::io::BufReader is AsyncRead and AsyncSeek
The AsyncSeek
is only implemented if it also exists for inner Type R
.
The TcpStream
doesn't impl AsyncSeek
.
What is see is the if the data is stored for header size then we don't really need seek. Will try to see if the seek can be avoided.
Can you explain PartialBoxRead
Trait ?
May be you are write mp4 cannot be streamable. https://github.com/alfg/mp4-rust/issues/53
if we implement things around a content aware context it should be possible to stream. Seek isn't used very often, it's mostly used to make sure there are no mistakes. To bad for the seek, didn't see the constraint :/ for the PartialBoxRead, it is necessary for PartialBox, which handles the inheritance of the boxes. Full box is the final form of a complete box. The partialBoxRead needs to read the header and the data separately as it may be split depending on the parent, where the fullBox always is sequential.
I want to read frame from tcp stream. how to use the crate to do the same ?
I don't see any struct or new method which might be helpful for the same.