如何修复此"borrowed value does not live long enough"错误?



我正在编写一个程序,用于检测h264编码视频中的重复帧。我使用的是ac-ffmpegcrate,下面是我的代码:

use std::fs::File;
use ac_ffmpeg::{
codec::{
video::{frame::Planes, VideoDecoder},
CodecParameters, Decoder,
},
format::{
demuxer::{Demuxer, DemuxerWithStreamInfo},
io::IO,
muxer::{Muxer, OutputFormat},
},
Error,
};
fn open_input(path: &str) -> Result<DemuxerWithStreamInfo<File>, Error> {
let input = File::open(path)
.map_err(|err| Error::new(format!("unable to open input file {}: {}", path, err)))?;
let io = IO::from_seekable_read_stream(input);
Demuxer::builder()
.build(io)?
.find_stream_info(None)
.map_err(|(_, err)| err)
}
fn open_output(path: &str, elementary_streams: &[CodecParameters]) -> Result<Muxer<File>, Error> {
let output_format = OutputFormat::guess_from_file_name(path)
.ok_or_else(|| Error::new(format!("unable to guess output format for file: {}", path)))?;
let output = File::create(path)
.map_err(|err| Error::new(format!("unable to create output file {}: {}", path, err)))?;
let io = IO::from_seekable_write_stream(output);
let mut muxer_builder = Muxer::builder();
for codec_parameters in elementary_streams {
muxer_builder.add_stream(codec_parameters)?;
}
muxer_builder.build(io, output_format)
}
fn plane_difference(planes1: &Planes, planes2: &Planes) -> u64 {
6
}
fn remove_duplicate_frames(input: &str, output: &str) -> Result<(), Error> {
let mut demuxer = open_input(input)?;
let (stream_index, (stream, _)) = demuxer
.streams()
.iter()
.map(|stream| (stream, stream.codec_parameters()))
.enumerate()
.find(|(_, (_, params))| params.is_video_codec())
.ok_or_else(|| Error::new("no video stream"))?;
let mut decoder = VideoDecoder::from_stream(stream)?.build()?;
let mut packet_count = 0;
let mut prev_planes: Option<Planes> = None;
let mut diffs = Vec::<(i64, u64)>::new();
while let Some(packet) = demuxer.take()? {
if packet.stream_index() != stream_index {
continue;
}
decoder.push(packet.clone())?;
if let Some(frame) = decoder.take()? {
let planes = frame.planes();
match prev_planes {
Some(prev) => {
let diff = plane_difference(&planes, &prev);
diffs.push((packet.dts().timestamp() / 1000, diff));
}
None => (),
};
prev_planes = Some(planes);
}
if packet_count > 2000 {
break;
}
packet_count += 1;
}
diffs.sort_by(|a, b| b.1.cmp(&a.1));
dbg!(diffs);
Ok(())
}

与依赖关系ac-ffmpeg = "0.17.4"

问题是这给出了一个错误,frame不存在足够长的时间:

error[E0597]: `frame` does not live long enough
--> src/main.rs:106:26
|
106 |             let planes = frame.planes();
|                          ^^^^^^^^^^^^^^ borrowed value does not live long enough
107 | 
108 |             match prev_planes {
|                   ----------- borrow later used here
...
117 |         }
|         - `frame` dropped here while still borrowed

我对这个错误的理解是frame是借的,它通过planes最终在prev_planes。但是在每次循环结束时,该值将被删除,因此在下一次迭代时它将不存在。对吗?怎么解呢?我试着在这段代码中克隆各种东西,但我无法修复这个错误。

VideoFrame不允许你采取飞机,它只允许你他们从frame

你可以看到,因为一生都与平面有关:

pub fn planes(&self) -> Planes<'_>

'_的生命周期表示它与&self引用的生命周期相同,这意味着它是从self借用的。

如果要存储planes,则存储包含它们的frame:

use std::fs::File;
use ac_ffmpeg::{
codec::{
video::{frame::Planes, VideoDecoder, VideoFrame},
CodecParameters, Decoder,
},
format::{
demuxer::{Demuxer, DemuxerWithStreamInfo},
io::IO,
muxer::{Muxer, OutputFormat},
},
Error,
};
fn open_input(path: &str) -> Result<DemuxerWithStreamInfo<File>, Error> {
let input = File::open(path)
.map_err(|err| Error::new(format!("unable to open input file {}: {}", path, err)))?;
let io = IO::from_seekable_read_stream(input);
Demuxer::builder()
.build(io)?
.find_stream_info(None)
.map_err(|(_, err)| err)
}
fn open_output(path: &str, elementary_streams: &[CodecParameters]) -> Result<Muxer<File>, Error> {
let output_format = OutputFormat::guess_from_file_name(path)
.ok_or_else(|| Error::new(format!("unable to guess output format for file: {}", path)))?;
let output = File::create(path)
.map_err(|err| Error::new(format!("unable to create output file {}: {}", path, err)))?;
let io = IO::from_seekable_write_stream(output);
let mut muxer_builder = Muxer::builder();
for codec_parameters in elementary_streams {
muxer_builder.add_stream(codec_parameters)?;
}
muxer_builder.build(io, output_format)
}
fn plane_difference(planes1: &Planes, planes2: &Planes) -> u64 {
6
}
fn remove_duplicate_frames(input: &str, output: &str) -> Result<(), Error> {
let mut demuxer = open_input(input)?;
let (stream_index, (stream, _)) = demuxer
.streams()
.iter()
.map(|stream| (stream, stream.codec_parameters()))
.enumerate()
.find(|(_, (_, params))| params.is_video_codec())
.ok_or_else(|| Error::new("no video stream"))?;
let mut decoder = VideoDecoder::from_stream(stream)?.build()?;
let mut packet_count = 0;
let mut prev_frame: Option<VideoFrame> = None;
let mut diffs = Vec::<(i64, u64)>::new();
while let Some(packet) = demuxer.take()? {
if packet.stream_index() != stream_index {
continue;
}
decoder.push(packet.clone())?;
if let Some(frame) = decoder.take()? {
let planes = frame.planes();
match prev_frame {
Some(prev) => {
let diff = plane_difference(&planes, &prev.planes());
diffs.push((packet.dts().timestamp() / 1000, diff));
}
None => (),
};
prev_frame = Some(frame);
}
if packet_count > 2000 {
break;
}
packet_count += 1;
}
diffs.sort_by(|a, b| b.1.cmp(&a.1));
dbg!(diffs);
Ok(())
}

您需要保持框架本身从一个循环迭代到下一个而不是平面。所以用prev_frame变量代替prev_planes:

let mut prev_frame = None;
let mut diffs = Vec::<(i64, u64)>::new();
while let Some(packet) = demuxer.take()? {
if packet.stream_index() != stream_index {
continue;
}
decoder.push(packet.clone())?;
if let Some(frame) = decoder.take()? {
let planes = frame.planes();
match prev_frame {
Some(prev) => {
let diff = plane_difference(&planes, &prev.planes());
diffs.push((packet.dts().timestamp() / 1000, diff));
}
None => (),
};
prev_frame = Some(frame);
}
}

复制这个有点棘手,所以我将试着从我的头脑中回答。

Did you try:

let planes = frame.planes().to_owned();

主要是你给planes(即孩子)的所有权,而父(frame)超出范围。

为什么是to_owned?(如果子类型是ref, clone将返回ref,所以我们使用to_owned,因为它将ref类型转换为允许转移所有权的拥有类型。

解决方案应该是

let planes = frame.planes().to_owned();   // line 106

prev_planes = Some(planes.clone());       // line 116

如果这些都不起作用,试着用它们的输出更新你的问题。这会让你更容易回答。

相关内容

最新更新