RustAudio / ogg

Ogg container decoder and encoder written in pure Rust
Other
113 stars 21 forks source link

`Packet::last_in_page` returns wrong value #21

Closed TonalidadeHidrica closed 3 years ago

TonalidadeHidrica commented 3 years ago

I'm not sure enough when it happens, but it seems that Packet::last_in_page returns wrong values in most cases. Here is NON-minimum code that reproduces the error:

use std::fs::File;
use std::io::{BufReader, Read, SeekFrom, Seek};
use std::fmt::Debug;

use ogg::reading::{PacketReader, OggReadError};
use ogg::Packet;
use itertools::Itertools;

fn iter_packet<'a, R: Read + Seek>(reader: &'a mut PacketReader<R>) -> impl Iterator<Item=(u64, u64, Result<Packet, OggReadError>)> + 'a {
    std::iter::repeat_with(move || {
        let begin_pos = reader.seek_bytes(SeekFrom::Current(0)).unwrap();
        let packet = reader.read_packet().transpose();
        let end_pos = reader.seek_bytes(SeekFrom::Current(0)).unwrap();
        packet.map(|p| (begin_pos, end_pos, p))
    })
        .take_while(|x| x.is_some())
        .flatten()
}

fn packet_tuple(p: &Packet) -> impl Debug {
    (
        p.stream_serial(),
        p.first_in_stream(),
        p.first_in_page(),
        p.last_in_page(),
        p.last_in_stream(),
        p.absgp_page(),
        {
            let mut data_iter = p.data.iter();
            let first = data_iter.by_ref().take(16).map(|x| format!("{:02x}", x)).collect::<String>();
            let remain = match data_iter.next() {
                Some(_) => "...",
                None => "",
            };
            format!("{}{}", first, remain)
        }
    )
}

fn main() -> anyhow::Result<()> {
    let file = File::open("song.ogg")?;
    let mut reader = PacketReader::new(BufReader::new(file));
    let packets = iter_packet(&mut reader).map(|x| x.2).collect::<Result<Vec<_>, _>>()?;
    for (absgp, mut packets) in &packets.iter().group_by(|p| p.absgp_page()) {
        let first = packets.next().expect("There are at least one element in a group");
        let last = packets.last().unwrap_or(first);
        println!("{}\t{:?}\t{:?}", absgp, packet_tuple(first), packet_tuple(last));
    }

    Ok(())
}

It outputs:

0       (26084, true, true, true, false, 0, "01766f72626973000000000244ac0000...")      (26084, false, true, false, false, 0, "03766f7262697338000000414f3b2061...")
20032   (26084, false, true, false, false, 20032, "00") (26084, false, true, false, false, 20032, "00")
23104   (26084, false, true, false, false, 23104, "fe96fb32477ad68898405bee431c6969...")        (26084, false, true, false, false, 23104, "fe96fb32477ad68898405bee431c6969...")
27392   (26084, false, true, false, false, 27392, "3e887ba13dcb170058c4fdd0358d0300...")        (26084, false, true, false, false, 27392, "3e887ba13dcb170058c4fdd0358d0300...")
30080   (26084, false, true, false, false, 30080, "34dad6bdc84b922f6f3cac3d2a5991ed...")        (26084, false, true, false, false, 30080, "34dad6bdc84b922f6f3cac3d2a5991ed...")
31808   (26084, false, true, false, false, 31808, "2cca5644aacaa6902c58c42d90ed2ec9...")        (26084, false, true, false, false, 31808, "2cca5644aacaa6902c58c42d90ed2ec9...")
34880   (26084, false, true, false, false, 34880, "dee9da0202700080ced92c18c839a91b...")        (26084, false, true, false, false, 34880, "dee9da0202700080ced92c18c839a91b...")
37952   (26084, false, true, false, false, 37952, "fee9da350743000084b6668180823600...")        (26084, false, true, false, false, 37952, "fee9da350743000084b6668180823600...")
41024   (26084, false, true, false, false, 41024, "1e1aeb0ec0e080d9e0e5b4b5681270f0...")        (26084, false, true, false, false, 41024, "1e1aeb0ec0e080d9e0e5b4b5681270f0...")
45120   (26084, false, true, false, false, 45120, "9eb914328239071c602edd25c380d6c1...")        (26084, false, true, false, false, 45120, "9eb914328239071c602edd25c380d6c1...")

In the sample code above, each the packet are grouped according to the absgp indicated by the page that it belongs, then the first and the last packet in each group is outputted. It is expected that last packet in each group returns true for last_in_page, but it returns false.

Any idea why it happens?

TonalidadeHidrica commented 3 years ago

Sorry, it was my fault.