這邊從 stdout 或 stderr 流輸入給 ffmpeg 做壓縮,主要就是利用 pipe 做 IPC
寫個小程式順便比較 javascript (nodejs) 和 C 語言的速度差異,最佳化的結果是 javascript 輸出到 stderr 幾乎等速於 C 語言,令人有點意外XD;反而直出到 stdout 的速度比 C 語言慢了 30%,這不太科學 。
題外話是 stderr 通常不會有 buffer 的問題,大多數時候都不用擔心沒有 flush 乾淨
演算法筆記
壓縮時該選哪個? 看目的是要做什麼,基本上一句話: 開發用 QP ,觀賞用CRF
CRF 或 QP=0 都是 loseless 這邊就不討論了,也沒有什麼實用價值。基本上在相同的設定值下,CRF 的檔案大小會比較小,但這是在於 CRF > 25 (平均畫質) 以上才比較有價值,否則差異不大。
就 MEMC (Frame Rate Conversion) 演算法開發我還是習慣用QP=18,因為同樣用 CRF=18,可能在快速移動物體邊緣出現些許 blocky ,但這是 CRF 壓縮造成的,不是演算法瑕疵,尤其我們在斤斤計較的就是這些快速移動的區域。
#include <fcntl.h> #include <io.h> setmode(1, _O_BINARY);
example use in ffmpeg pipe encoding mode
a.exe | ffmpeg -f rawvideo -pixel_format rgb24 -video_size 1920x1080 -i - -pix_fmt yuv420p output.mp4
#include <stdio.h> // includes for setmode #include <fcntl.h> #include <io.h> int imgSizeX = 1920; int imgSizeY = 1080; int imgNum = 100; int main() { // change to binary stdout mode (avoid 0x0A be changed into 0x0D 0x0A) setmode(1, _O_BINARY); for (int i = 0; i < imgNum; ++i) { for (int y = 0; y < imgSizeY; ++y) { for (int x = 0; x < imgSizeX; ++x) { unsigned char color[3] = {0x00, (x+i*5) & 0xFF, 0x00}; fwrite(color, 1, 3, stdout); } } } fflush(stdout); return 0; }
有了 libx264 當然要試編一下影片,encode 出的檔案只是為 h264 的 bitstream ,並不是直接封裝成可直接撥放的檔案,還需要一些 wrapper 程序封裝成常見的影片格式如 ( mp4, mkv …)
不過也可以懶人用 ffmpeg 封裝 XD
ffmpeg -i in_file.h264 -vcodec copy out_file.mp4
這基本上就是一連串的繼承寄生關係,階層越高越笨重,也越複雜,這邊就第一步 codec 層來做個小實驗。
Reference: h264/h265 bit stream 分析工具,可以幫助理解檔案格式
後面附上程式碼
完全是參考,注意 YASM 可能要另外下載丟到 mingw/bin/
但是如果這麼簡單就不用寫一篇文章了
MSYS 死活找不到 Mingw-w64,一直顯示找不到 gcc
直到我下載了 MSYS2 ,對,就是多個 2 而已。然後乖乖把mingw32和64放到 C:\msys64底下,執行對應的 msys 環境 (如 mingw64.exe ),就可以正常編譯了!
附上編譯好的懶人包 for mingw-w64