Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Image 从MPEG-2传输流(H.264-附录B)字节流中提取原始I帧图像数据 上下文_Image_Rust_Frame_H.264_Mpeg - Fatal编程技术网

Image 从MPEG-2传输流(H.264-附录B)字节流中提取原始I帧图像数据 上下文

Image 从MPEG-2传输流(H.264-附录B)字节流中提取原始I帧图像数据 上下文,image,rust,frame,h.264,mpeg,Image,Rust,Frame,H.264,Mpeg,我试图用H.264附录B编解码器从MPEG-2传输流中提取每个I帧的原始图像数据。此视频每2秒包含一个I帧。我已经了解到,在类型为5的NALu开始代码(例如IDR图片的编码片段)之后可以找到I帧。这些NALu的字节有效负载包含构造完整帧所需的所有数据。据我所知,这是一种H.264编码格式 我想构建一个解决方案,从传入的字节流中提取这些I帧,方法是找到包含I帧的NALu,保存有效负载,并将有效负载解码为某种普遍存在的原始图像格式,以访问像素数据等 注意:如果可能,我希望避免使用文件系统依赖性二进制

我试图用H.264附录B编解码器从MPEG-2传输流中提取每个I帧的原始图像数据。此视频每2秒包含一个I帧。我已经了解到,在类型为5的NALu开始代码(例如IDR图片的编码片段)之后可以找到I帧。这些NALu的字节有效负载包含构造完整帧所需的所有数据。据我所知,这是一种H.264编码格式

我想构建一个解决方案,从传入的字节流中提取这些I帧,方法是找到包含I帧的NALu,保存有效负载,并将有效负载解码为某种普遍存在的原始图像格式,以访问像素数据等

注意:如果可能,我希望避免使用文件系统依赖性二进制文件,如ffmpeg,更重要的是,如果可行的话

PoC 到目前为止,我已经在rust中构建了一个PoC来查找I帧的字节偏移量和字节大小:

use std::fs::File;
use std::io::{prelude::*, BufReader};
extern crate image;

fn main() {
    let file = File::open("vodpart-0.ts").unwrap();
    let reader = BufReader::new(file);

    let mut idr_payload = Vec::<u8>::new();
    let mut total_idr_frame_count = 0;
    let mut is_idr_payload = false;
    let mut is_nalu_type_code = false;
    let mut start_code_vec = Vec::<u8>::new();

    for (pos, byte_result) in reader.bytes().enumerate() {
        let byte = byte_result.unwrap();
        if is_nalu_type_code {
            is_idr_payload = false;
            is_nalu_type_code = false;
            start_code_vec.clear();
            if byte == 101 {
                is_idr_payload = true;
                total_idr_frame_count += 1;
                println!("Found IDR picture at byte offset {}", pos);
            }
            continue;
        }
        if is_idr_payload {
            idr_payload.push(byte);
        }
        if byte == 0 {
            start_code_vec.push(byte);
            continue;
        }
        if byte == 1 && start_code_vec.len() >= 2 {
            if is_idr_payload {
                let payload = idr_payload.len() - start_code_vec.len() + 1;
                println!("Previous NALu payload is {} bytes long\n", payload);
                save_image(&idr_payload.as_slice(), total_idr_frame_count);
                idr_payload.clear();
            }
            is_nalu_type_code = true;
            continue;
        }
        start_code_vec.clear();
    }

    println!();
    println!("total i frame count: {}", total_idr_frame_count);

    println!();
    println!("done!");
}

fn save_image(buffer: &[u8], index: u16) {
    let image_name = format!("image-{}.jpg", index);
    image::save_buffer(image_name, buffer, 858, 480, image::ColorType::Rgb8).unwrap()
}
这是正确的,基于我使用H.264比特流查看器等进行的研究。在这些字节偏移量下肯定有5个I帧

问题是我不明白如何将H.264 ByTestStream有效负载转换为原始图像RBG数据格式。一旦转换成jpg,生成的图像只是一团模糊的乱麻,大约占图像面积的10%

例如:

问题
  • 是否需要执行解码步骤
  • 我是否正确地处理了这一点,并且尝试自己是可行的,还是应该依赖另一个lib

  • 任何帮助都将不胜感激

    “是否需要执行解码步骤?”

    对。从头开始编写解码器是极其复杂的。描述它的文件(ISO 14496-10)超过750页。你应该使用图书馆。ffmpeg中的Libavcodec实际上是您唯一的选择。(除非您只需要基线配置文件,您可以在其中使用android的开源解码器)


    您可以编译自定义版本的libavcodec,以排除不需要的内容

    谢谢你的澄清!我看到了一个类似问题的答案,该问题警告ISO文档的大小。后续问题:解码I帧NALu有效载荷后,图像数据将以什么格式表示?像libavcodec这样的lib能够只接受单帧字节的有效载荷吗?“像libavcodec这样的lib能够只接受单帧字节的有效载荷吗?”这取决于格式,如果其附录B和“帧”包括SPS/PPS和IDR,则是。“解码I帧NALu有效载荷后,图像数据将以何种格式表示?”取决于它的编码方式,但最常见的是YUV和4:2:0色度二次采样平面。
    Found IDR picture at byte offset 870
    Previous NALu payload is 202929 bytes long
    
    Found IDR picture at byte offset 1699826
    Previous NALu payload is 185069 bytes long
    
    Found IDR picture at byte offset 3268686
    Previous NALu payload is 145218 bytes long
    
    Found IDR picture at byte offset 4898270
    Previous NALu payload is 106114 bytes long
    
    Found IDR picture at byte offset 6482358
    Previous NALu payload is 185638 bytes long
    
    
    total i frame count: 5
    
    done!