[go: up one dir, main page]

rtp 0.4.0

A pure Rust implementation of RTP
Documentation
use super::*;

#[test]
fn test_vp9_packet_unmarshal() -> Result<()> {
    let tests = vec![
        (
            "Empty",
            Bytes::from_static(&[]),
            Vp9Packet::default(),
            Some(Error::ErrShortPacket),
        ),
        (
            "NonFlexible",
            Bytes::from_static(&[0x00, 0xAA]),
            Vp9Packet {
                payload: Bytes::from_static(&[0xAA]),
                ..Default::default()
            },
            None,
        ),
        (
            "NonFlexiblePictureID",
            Bytes::from_static(&[0x80, 0x02, 0xAA]),
            Vp9Packet {
                i: true,
                picture_id: 0x02,
                payload: Bytes::from_static(&[0xAA]),
                ..Default::default()
            },
            None,
        ),
        (
            "NonFlexiblePictureIDExt",
            Bytes::from_static(&[0x80, 0x81, 0xFF, 0xAA]),
            Vp9Packet {
                i: true,
                picture_id: 0x01FF,
                payload: Bytes::from_static(&[0xAA]),
                ..Default::default()
            },
            None,
        ),
        (
            "NonFlexiblePictureIDExt_ShortPacket0",
            Bytes::from_static(&[0x80, 0x81]),
            Vp9Packet::default(),
            Some(Error::ErrShortPacket),
        ),
        (
            "NonFlexiblePictureIDExt_ShortPacket1",
            Bytes::from_static(&[0x80]),
            Vp9Packet::default(),
            Some(Error::ErrShortPacket),
        ),
        (
            "NonFlexibleLayerIndicePictureID",
            Bytes::from_static(&[0xA0, 0x02, 0x23, 0x01, 0xAA]),
            Vp9Packet {
                i: true,
                l: true,
                picture_id: 0x02,
                tid: 0x01,
                sid: 0x01,
                d: true,
                tl0picidx: 0x01,
                payload: Bytes::from_static(&[0xAA]),
                ..Default::default()
            },
            None,
        ),
        (
            "FlexibleLayerIndicePictureID",
            Bytes::from_static(&[0xB0, 0x02, 0x23, 0x01, 0xAA]),
            Vp9Packet {
                f: true,
                i: true,
                l: true,
                picture_id: 0x02,
                tid: 0x01,
                sid: 0x01,
                d: true,
                payload: Bytes::from_static(&[0x01, 0xAA]),
                ..Default::default()
            },
            None,
        ),
        (
            "NonFlexibleLayerIndicePictureID_ShortPacket0",
            Bytes::from_static(&[0xA0, 0x02, 0x23]),
            Vp9Packet::default(),
            Some(Error::ErrShortPacket),
        ),
        (
            "NonFlexibleLayerIndicePictureID_ShortPacket1",
            Bytes::from_static(&[0xA0, 0x02]),
            Vp9Packet::default(),
            Some(Error::ErrShortPacket),
        ),
        (
            "FlexiblePictureIDRefIndex",
            Bytes::from_static(&[0xD0, 0x02, 0x03, 0x04, 0xAA]),
            Vp9Packet {
                i: true,
                p: true,
                f: true,
                picture_id: 0x02,
                pdiff: vec![0x01, 0x02],
                payload: Bytes::from_static(&[0xAA]),
                ..Default::default()
            },
            None,
        ),
        (
            "FlexiblePictureIDRefIndex_TooManyPDiff",
            Bytes::from_static(&[0xD0, 0x02, 0x03, 0x05, 0x07, 0x09, 0x10, 0xAA]),
            Vp9Packet::default(),
            Some(Error::ErrTooManyPDiff),
        ),
        (
            "FlexiblePictureIDRefIndexNoPayload",
            Bytes::from_static(&[0xD0, 0x02, 0x03, 0x04]),
            Vp9Packet {
                i: true,
                p: true,
                f: true,
                picture_id: 0x02,
                pdiff: vec![0x01, 0x02],
                payload: Bytes::from_static(&[]),
                ..Default::default()
            },
            None,
        ),
        (
            "FlexiblePictureIDRefIndex_ShortPacket0",
            Bytes::from_static(&[0xD0, 0x02, 0x03]),
            Vp9Packet::default(),
            Some(Error::ErrShortPacket),
        ),
        (
            "FlexiblePictureIDRefIndex_ShortPacket1",
            Bytes::from_static(&[0xD0, 0x02]),
            Vp9Packet::default(),
            Some(Error::ErrShortPacket),
        ),
        (
            "FlexiblePictureIDRefIndex_ShortPacket2",
            Bytes::from_static(&[0xD0]),
            Vp9Packet::default(),
            Some(Error::ErrShortPacket),
        ),
        (
            "ScalabilityStructureResolutionsNoPayload",
            Bytes::from_static(&[
                0x0A,
                (1 << 5) | (1 << 4), // NS:1 Y:1 G:0
                (640 >> 8) as u8,
                (640 & 0xff) as u8,
                (360 >> 8) as u8,
                (360 & 0xff) as u8,
                (1280 >> 8) as u8,
                (1280 & 0xff) as u8,
                (720 >> 8) as u8,
                (720 & 0xff) as u8,
            ]),
            Vp9Packet {
                b: true,
                v: true,
                ns: 1,
                y: true,
                g: false,
                ng: 0,
                width: vec![640, 1280],
                height: vec![360, 720],
                payload: Bytes::from_static(&[]),
                ..Default::default()
            },
            None,
        ),
        (
            "ScalabilityStructureNoPayload",
            Bytes::from_static(&[
                0x0A,
                (1 << 5) | (0 << 4) | (1 << 3), // NS:1 Y:0 G:1
                2,
                (0 << 5) | (1 << 4) | (0 << 2), // T:0 U:1 R:0 -
                (2 << 5) | (0 << 4) | (1 << 2), // T:2 U:0 R:1 -
                33,
            ]),
            Vp9Packet {
                b: true,
                v: true,
                ns: 1,
                y: false,
                g: true,
                ng: 2,
                pgtid: vec![0, 2],
                pgu: vec![true, false],
                pgpdiff: vec![vec![], vec![33]],
                payload: Bytes::from_static(&[]),
                ..Default::default()
            },
            None,
        ),
    ];

    for (name, b, pkt, err) in tests {
        let mut p = Vp9Packet::default();

        if let Some(expected) = err {
            if let Err(actual) = p.depacketize(&b) {
                assert!(
                    expected.equal(&actual),
                    "{}: expected {}, but got {}",
                    name,
                    expected,
                    actual
                );
            } else {
                assert!(false, "{}: expected error, but got passed", name);
            }
        } else {
            p.depacketize(&b)?;
            assert_eq!(pkt, p, "{}: expected {:?}, but got {:?}", name, pkt, p);
        }
    }

    Ok(())
}

#[test]
fn test_vp9_payloader_payload() -> Result<()> {
    let mut r0 = 8692;
    let mut rands = vec![];
    for _ in 0..10 {
        rands.push(vec![(r0 >> 8) as u8 | 0x80, (r0 & 0xFF) as u8]);
        r0 += 1;
    }

    let tests = vec![
        ("NilPayload", vec![Bytes::new()], 100, vec![]),
        ("SmallMTU", vec![Bytes::from(vec![0x00, 0x00])], 1, vec![]),
        (
            "NegativeMTU",
            vec![Bytes::from(vec![0x00, 0x00])],
            0,
            vec![],
        ),
        (
            "OnePacket",
            vec![Bytes::from(vec![0x01, 0x02])],
            10,
            vec![Bytes::from(vec![
                0x9C,
                rands[0][0],
                rands[0][1],
                0x01,
                0x02,
            ])],
        ),
        (
            "TwoPackets",
            vec![Bytes::from(vec![0x01, 0x02])],
            4,
            vec![
                Bytes::from(vec![0x98, rands[0][0], rands[0][1], 0x01]),
                Bytes::from(vec![0x94, rands[0][0], rands[0][1], 0x02]),
            ],
        ),
        (
            "ThreePackets",
            vec![Bytes::from(vec![0x01, 0x02, 0x03])],
            4,
            vec![
                Bytes::from(vec![0x98, rands[0][0], rands[0][1], 0x01]),
                Bytes::from(vec![0x90, rands[0][0], rands[0][1], 0x02]),
                Bytes::from(vec![0x94, rands[0][0], rands[0][1], 0x03]),
            ],
        ),
        (
            "TwoFramesFourPackets",
            vec![Bytes::from(vec![0x01, 0x02, 0x03]), Bytes::from(vec![0x04])],
            5,
            vec![
                Bytes::from(vec![0x98, rands[0][0], rands[0][1], 0x01, 0x02]),
                Bytes::from(vec![0x94, rands[0][0], rands[0][1], 0x03]),
                Bytes::from(vec![0x9C, rands[1][0], rands[1][1], 0x04]),
            ],
        ),
    ];

    for (name, bs, mtu, expected) in tests {
        let mut pck = Vp9Payloader {
            initial_picture_id_fn: Some(Arc::new(|| -> u16 { 8692 })),
            ..Default::default()
        };

        let mut actual = vec![];
        for b in &bs {
            actual.extend(pck.payload(mtu, b)?);
        }
        assert_eq!(expected, actual, "{}: Payloaded packet", name);
    }

    //"PictureIDOverflow"
    {
        let mut pck = Vp9Payloader {
            initial_picture_id_fn: Some(Arc::new(|| -> u16 { 8692 })),
            ..Default::default()
        };
        let mut p_prev = Vp9Packet::default();
        for i in 0..0x8000 {
            let res = pck.payload(4, &Bytes::from_static(&[0x01]))?;
            let mut p = Vp9Packet::default();
            p.depacketize(&res[0])?;

            if i > 0 {
                if p_prev.picture_id == 0x7FFF {
                    assert_eq!(
                        p.picture_id, 0,
                        "Picture ID next to 0x7FFF must be 0, got {}",
                        p.picture_id
                    );
                } else if p_prev.picture_id + 1 != p.picture_id {
                    assert!(
                        false,
                        "Picture ID next must be incremented by 1: {} -> {}",
                        p_prev.picture_id, p.picture_id,
                    );
                }
            }

            p_prev = p;
        }
    }

    Ok(())
}

#[test]
fn test_vp9_partition_head_checker_is_partition_head() -> Result<()> {
    //"SmallPacket"
    assert!(
        !Vp9PartitionHeadChecker::is_partition_head(&Bytes::new()),
        "Small packet should not be the head of a new partition"
    );

    //"NormalPacket"
    assert!(
        Vp9PartitionHeadChecker::is_partition_head(&Bytes::from_static(&[0x18, 0x00, 0x00])),
        "VP9 RTP packet with B flag should be head of a new partition"
    );
    assert!(
        !Vp9PartitionHeadChecker::is_partition_head(&Bytes::from_static(&[0x10, 0x00, 0x00])),
        "VP9 RTP packet without B flag should not be head of a new partition"
    );

    Ok(())
}