我正在使用Rust中的FFMPEG Api來從視頻檔案中獲取RGB影像。
盡管有些視頻作業正常,并且我獲得了預期的幀數,但有些視頻作業不正常。或者至少結果不是我所期望的那樣。
我在Rust中使用的代碼:
我在Rust中使用的代碼:
ffmpeg::init().unwrap()。
let in_ctx = input(&Path::new(Source)). unwrap()。
let input = in_ctx
.streams()
.best(Type::Video)
.ok_or(ffmpeg::Error::StreamNotFound)?
let decoder = input.codec()。 decoder().video()?
let scaler = Context::get (
decoder.format()。
decoder.width()。
decoder.height()。
Pixel::RGB24,
decoder.width()。
decoder.height()。
Flags::FULL_CHR_H_INT | Flags::ACCURATE_RND,
)? ;// <--- 基本上是sws_getContext。
//后來得到實際的框架。
let mut decoded = Video::empty()。
if self.Decoder. receive_frame(&mut decoded).is_ok() {
let mut rgb_frame = Video::empty()。
self.scaler.run(&decoded, &mut rgb_frame)?; // <-- Does sws_scale
println!("轉換的像素格式。{}", rgb_frame.format() as i32) 。
Ok(Some(rgb_frame))
這應該大致可以翻譯成C語言,比如:
// Get the context and video stream.
SwsContext * ctx = sws_getContext(imgWidth, imgHeight,
imgFormat, imgWidth, imgHeight,
AV_PIX_FMT_RGB24, 0, 0, 0, 0)。)
sws_scale(ctx, decoded.data, decoded.linesize, 0, decoded.height, rgb_frame.data, rbg_frame.lineize)。
就像我之前說的,有時它作業得很好,我得到了預期的框架。但有時我會得到類似這樣的東西。 奇怪的結果圖片
我把影像保存為.ppm檔案,以便快速進行視覺比較。我使用了這種方法,它基本上是將位元組寫入一個帶有簡單的.ppm頭的檔案:
fn save_file( frame: &Video, index: usize) -> std::result::Result<(), std::io::Error>
{
let mut file = File::create(format! ("frame{}.ppm", index))。
file.write_all(format! ("P6
{} {}
255
", frame.width(), frame.height().as_bytes() ?)
file.write_all(frame.data(0) ?)
Ok(())
}
在這里你可以看到,在左邊有一個好的影像結果與在右邊有一個壞的影像結果。 .ppm檔案的比較
現在來談談這個問題:
為什么會發生這種情況?
為什么會發生這種情況。我測驗了我這邊的所有東西,唯一剩下的就是ffmpeg轉換。FFMPEG似乎對這兩個測驗檔案進行了不同的轉換,盡管它對兩個檔案都報告了YUV420P的格式。我無法找出其中的差別......
這里是這兩個檔案的資訊。
下面是我使用的兩個視頻檔案的資訊:
好的視頻檔案:普通
完整名稱 : /mnt/smb/Snapchat-174933781.mp4
格式。MPEG-4
格式組態檔 : 基礎媒體/版本2
編解碼器ID : mp42 (isom/mp42)
檔案大小 : 1.90 MiB
片長 : 9秒612毫秒
總位元率 : 1 661 kb/s
編碼的日期 : UTC 2021-07-28 22:09:36
標記日期 : UTC 2021-07-28 22:09:36
英語 : -180.00
視頻
ID : 512
格式 : AVC
格式/資訊 : 高級視頻編解碼器
格式組態檔 : [email protected]
格式設定 : CABAC/1 Ref Frames
格式設定, CABAC : 是
格式設定, 參考幀 : 1幀
格式設定, GOP : M=1, N=30
編解碼器ID : avc1
編解碼器ID/資訊 : 高級視頻編碼
持續時間 : 9秒598毫秒
位元率 : 1 597 kb/s
寬度 : 480像素
高度 : 944像素
顯示長寬比 : 0.508
幀率模式 : 可變的
幀率 : 29.797 FPS
最小幀率 : 15.000 FPS
最大幀率:30.000 FPS
色彩空間 : YUV
色度子取樣:4:2:0
位深度:8位
掃描型別。逐行掃描
位元/(像素*幀) : 0.118
流大小 : 1.83 MiB (96%)
標題 : 捕捉視頻
語言 : 英語
編碼日期 : UTC 2021-07-28 22:09:36
標簽日期 : UTC 2021-07-28 22:09:36
顏色范圍 : 全部
原色范圍 : 有限
顏色原色 : BT.709
傳輸特性 : BT.601
轉移特性_原件:BT.709
矩陣系數 : BT.709
編解碼器配置框:avcC
音頻
ID : 256
格式 : AAC LC
格式/資訊 : 低復雜度高級音頻編解碼器
編解碼器ID : mp4a-40-2
持續時間 : 9秒612毫秒
位元率模式 : 恒定
位元率 : 62.0 kb/s
通道 : 1個通道
通道布局 : C
采樣率 : 44.1 kHz
幀率 : 43.066 FPS (1024 SPF)
壓縮模式 : 有損的
流大小 : 73.3 KiB (4%)
標題 : Snap Audio
語言 : 英語
編碼日期 : UTC 2021-07-28 22:09:36
標簽日期 : UTC 2021-07-28 22:09:36
壞的視頻檔案:
普通
完整名稱 : /mnt/smb/Snapchat-1989594918.mp4
格式。MPEG-4
格式組態檔 : 基礎媒體/版本2
編解碼器ID : mp42 (isom/mp42)
檔案大小 : 2.97 MiB
時長 : 6 s 313 ms
總位元率 : 3 948 kb/s
編碼的日期 : UTC 2019-07-11 06:43:04
標記日期 : UTC 2019-07-11 06:43:04
com.android.version : 9
視頻
ID : 1
格式。AVC
格式/資訊 : 高級視頻編解碼器
格式組態檔 : [email protected]
格式設定 : 1個參考幀
格式設定, CABAC : 沒有
格式設定, 參考幀 : 1幀
格式設定, GOP : M=1, N=30
編解碼器ID : avc1
編解碼器ID/資訊 : 高級視頻編碼
持續時間 : 6 s 313 ms
位元率 : 3 945 kb/s
寬度 : 496 像素
高度 : 960像素
顯示長寬比 : 0.517
幀率模式 : 可變的
幀率 : 29.306 FPS
最小幀率 : 19.767 FPS
最大幀率 : 39.508 FPS
色彩空間 : YUV
色度子取樣:4:2:0
位深度 : 8位
掃描型別 : 逐行掃描
位元/(像素*幀) : 0.283
流大小 : 2.97 MiB (100%)
標題 : VideoHandle
語言 : 英語
編碼日期 : UTC 2019-07-11 06:43:04
標簽日期 : UTC 2019-07-11 06:43:04
顏色范圍 : 有限
顏色原色 : BT.709
傳輸特性 : BT.709
矩陣系數 : BT.709
編解碼器配置框:avcC
或者作為一個差異影像。image diff
問題是,我對ffmpeg不是很熟悉,但我不知道它的所有怪癖。
我希望有人能為我指出正確的方向。
uj5u.com熱心網友回復:
感謝@SuRGeoNix和@Jmb的建議,我對輸入的行距和寬度進行了調整。
經過一段時間,我了解到ffmpeg需要32位對齊的資料才能發揮最佳效果。所以我調整了縮放器,將其調整為32位對齊的寬度,現在輸出很好。
ffmpeg::init()。unwrap()。
let in_ctx = input(&Path::new(Source)). unwrap()。
let input = in_ctx
.streams()
.best(Type::Video)
.ok_or(ffmpeg::Error::StreamNotFound)?
let decoder = input.codec()。 decoder().video()?
// Round to the next 32bit divisible width.
let width = if解碼器。 width() % 32 != 0 {
decoder.width() 32 - (decoder.width() % 32)
} else {
decoder.width()
};
let scaler = Context::get (
decoder.format()。
decoder.width()。
decoder.height()。
Pixel::RGB24,
width, //使用這里的計算寬度。
decoder.height()。
Flags::FULL_CHR_H_INT | Flags::ACCURATE_RND,
)?;
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/320318.html
標籤:
上一篇:如何在按鈕被按下時做一個動作
下一篇:從共享布局中檢索資料庫值
