rsmpeg icon indicating copy to clipboard operation
rsmpeg copied to clipboard

Can the AVformatContextInput::from_io_context interface add an optional AVdictionary parameter?

Open ZKBL opened this issue 1 year ago • 2 comments

pub fn open_memory_file(data: Arc<Vec<u8>>) -> Result<AVFormatContextInput> {
    let mut current = 0;
    let io_context = AVIOContextCustom::alloc_context(
        AVMem::new(1048576),
        false,
        vec![],
        Some(Box::new(move |_, buf| {
            let right = data.len().min(current + buf.len());
            if right <= current {
                return ffi::AVERROR_EOF;
            }
            let read_len = right - current;
            buf[0..read_len].copy_from_slice(&data[current..right]);
            current = right;
            read_len as i32
        })),
        None,
        None,
    );
    let input_format_context = match AVFormatContextInput::from_io_context(
        rsmpeg::avformat::AVIOContextContainer::Custom(io_context),
    ) {
        Ok(x) => x,
        Err(e) => {
            bail!("open file default:{}", e);
        }
    };
    Ok(input_format_context)
}

The above code will have the following output for some files

[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7ffff0000f40] stream 0, offset 0x30: partial file
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x7ffff0000f40] Could not find codec parameters for stream 0 (Video: h264 (avc1 / 0x31637661), none(tv, bt709), 720x1280, 11185 kb/s): unspecified pixel format
Consider increasing the value for the 'analyzeduration' (0) and 'probesize' (5000000) options

But if I use AVformatContextInput::open() to open a file that exists on disk it works fine.

ZKBL avatar Jan 23 '24 07:01 ZKBL

Hi, just wondering if there's been any progress on this, since I've got a similar use case?

sw-vish avatar Oct 07 '24 09:10 sw-vish

Just a sharing ! Thank you! Please test as follows;

#[test]
fn test1() -> Result<()> {
    unsafe {
        ffi::avdevice_register_all();
        // ffi::av_log_set_level(ffi::AV_LOG_TRACE as i32);
    }

    let name = cstr!("lavfi");
    let filter_ref = AVInputFormat::find(name).unwrap();
    println!("long_name: {:?}", unsafe {
        CStr::from_ptr(filter_ref.long_name)
    });
    assert_eq!(
        unsafe { CStr::from_ptr(filter_ref.long_name) },
        cstr!("Libavfilter virtual input device")
    );

    let mut dict: Option<_> =
        Some(AVDictionary::new(cstr!("probesize"), cstr!("1000000"), 0).into());

    let mut lavfi_ic = AVFormatContextInput::open(
        cstr!("color=c=black:s=640x480:r=1:duration=10"),
        Some(&filter_ref),
        &mut dict,
    )?;

    let (stream_index, dec) = lavfi_ic.find_best_stream(ffi::AVMEDIA_TYPE_VIDEO)?.unwrap();
    println!("lavfi_ic:{:#?}", lavfi_ic.clone());
    println!("stream_index:{}", stream_index);
    println!("dec:{:?}", dec.name());

    println!("duration:{}", lavfi_ic.duration);
    println!("bit_rate:{}", lavfi_ic.bit_rate);
    println!("nb_streams:{}", lavfi_ic.nb_streams);
    println!("fps_probe_size:{}", lavfi_ic.fps_probe_size);
    let mut v_dec_ctx = AVCodecContext::new(&dec);
    v_dec_ctx.apply_codecpar(&lavfi_ic.streams()[stream_index as usize].codecpar())?;

    v_dec_ctx.open(None)?;

    while let Ok(Some(packet)) = lavfi_ic.read_packet() {
        if packet.stream_index == stream_index as i32 {
            v_dec_ctx.send_packet(Some(&packet))?;
            while let Ok(virtual_frame) = v_dec_ctx.receive_frame() {
                println!("frame {:?}", virtual_frame);
            }
        }
    }

    Ok(())
}

-WENPIN

WENPIN1 avatar Apr 01 '25 05:04 WENPIN1