Wicpar / async-mp4

Asynchronous reader and writer for MP4 in pure rust
2 stars 2 forks source link

Example to use the crate. #1

Closed sak96 closed 1 year ago

sak96 commented 1 year ago

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.

Wicpar commented 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 :)

sak96 commented 1 year ago

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

sak96 commented 1 year ago

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.

Wicpar commented 1 year ago

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 :)

sak96 commented 1 year ago

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 ?

Wicpar commented 1 year ago

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.

Wicpar commented 1 year ago

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

Wicpar commented 1 year ago

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...

Wicpar commented 1 year ago

futures::io::BufReader is AsyncRead and AsyncSeek

sak96 commented 1 year ago

The AsyncSeek is only implemented if it also exists for inner Type R. The TcpStream doesn't impl AsyncSeek.

https://github.com/rust-lang/futures-rs/blob/4e210b8cedc2fda2e3c8b8a1aab93e4c668ba9af/futures-util/src/io/buf_reader.rs#L178

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

Wicpar commented 1 year ago

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.

sak96 commented 1 year ago

I just went through this video looks like there is lot of stuff to video decoding.

Will close this issue as i am not going to pick this immediate but thanks for the guidance was really helpful.