本篇測評由電子發燒友的優秀測評者“ALSET”提供。
電子發燒友網發布了一款產品:米爾 MYD-Y6ULX-V2 開發板,基于 NXP i.MX6UL/i.MX6ULL處理器,該開發板被米爾稱之為經典王牌產品。也是是一款嵌入式Linux入門級的開發板。本次測試目標是在此開發板上進行視頻工具FFmpeg的移植與測試開發,測試FFmpeg在此開發板上的視頻應用效果。
01.
FFmpeg是什么
FFmpeg是一套開源的音視頻代庫,具有非常強大的功能包括視頻采集功能、視頻格式轉換、視頻抓圖、給視頻加水印等。
FFmpeg視頻采集功能非常強大,不僅可以采集視頻采集卡或USB攝像頭的圖像,還可以進行屏幕錄制,同時還支持以RTP方式將視頻流傳送給支持RTSP/RTMP 的流媒體服務器,支持直播應用。采用LGPL或GPL許可證。它提供了錄制、轉換以及流化音視頻的完整解決方案。它包含了非常先進的音頻/視頻編解碼庫libavcodec,具有高可移植性和編解碼質量。它幾乎實現了所有當下常見的數據封裝格式、多媒體傳輸協議以及音視頻編解碼器。
很多Linux桌面環境中的開源播放器VLC、MPlayer,Windows下的KMPlayer、暴風影音以及Android下幾乎全部第三方播放器都是基于FFmpeg的,可見它的應用非常廣泛,也是嵌入式系統中音視頻使用最多的代碼庫。
FFmpeg工程的幾個主要目錄:libavformat:用于各種音視頻封裝格式的生成和解析,包括獲取解碼所需信息以生成解碼上下文結構和讀取音視頻幀等功能;libavcodec:用于各種類型聲音/圖像編解碼;libavutil:包含一些公共的工具函數;libswscale:用于視頻場景比例縮放、色彩映射轉換;libpostproc:用于后期效果處理;ffmpeg:該項目提供的一個工具,可用于格式轉換、解碼或電視卡即時編碼等;ffsever:一個 HTTP 多媒體即時廣播串流服務器;ffplay:是一個簡單的播放器,使用ffmpeg 庫解析和解碼,通過SDL顯示。
02.
FFmpeg移植編譯
1. 首先切換為交叉編譯環境
2.從github 上拉取ffmpeg源碼,考慮ffmpeg版本比較多,最新的版本增加了許多的擴展功能,同時也增加了對硬件資源的需求。考慮該開發板為ARMv7的初級開發版,因此這里不使用最新的版本,而是使用一個兩年前的版本。使用 ffmpeg-4.1.3版本。
3. 寫配置執行腳本
FFmpeg代碼編譯配置有非常多的選項,為了更好的進行配置,這里寫一個腳本用來進行配置執行。
腳本內容如下:
腳本文件名:config_for_mx6ull.sh放到ffmpeg工程根目錄下這里特別注意,因為項目放到是主機的虛擬機外掛的共享目錄里,共享目錄的文件系統是fat32,它不支持軟鏈接,因此需要設置鏈接命令為硬復制,即如下:--ln_s="cp-R"4. 執行配置執行腳本編寫好文配置腳本后,然后可以直接執行,執行完畢,輸出結果如下:
5.開始多線程編譯配置腳本執行完畢后,會產生makefile文件,然后就可以進行編譯,執行make–j4
編譯需要大概30分鐘左右,整體編譯順利,最后編譯出結果:
6.檢查編譯的庫文件使用命令 file檢查編譯輸出的動態庫文件和ffmpeg文件,可見是armv7執行文件。
經過檢查,目標文件已經編譯成功。7. 編譯FFmpeg附帶的測試例子程序編譯完ffmpeg 庫后,就可以編譯附帶的例子程序,可以更好的定制開發ffmpeg. 先編譯例子程序。例子帶的makefile 文件是x86 平臺的,需要修改一下才能編譯開發板上的版本,進入目錄 /mnt/hgfs/MYD-Y6ULX/Proj/ffmpeg.4.1.3/ffmpeg/doc/examples下,修改Makefile.example修改如下:
修改完,就可以執行編譯,命令如下:make-f Makefile.example
編譯很順利,一次通過。8. 瘦身動態庫文件和ffmpeg執行文件編譯完的庫文件體積都比較大,像| libavcodecs.so 文件達40M+,所有文件一起傳到開發板上,將非常占用開發板文件空間,因此可以對動態庫和ffmepg執行文件進行瘦身一下。所謂瘦身,就是把執行文件帶的gdb符號信息全部去掉,即可大大減少文件的體積。
9.把編譯瘦身后的文件傳送到開發板然后就可以把編譯好的庫文件和執行文件全部傳送到開發板上,執行命令:scplibavcodec/libavcodec.so.58root@192.168.50.150:/home/rootscplibavformat/libavformat.so.58 root@192.168.50.150:/home/rootscplibavdevice/libavdevice.so.58root@192.168.50.150:/home/rootscplibavfilter/libavfilter.so.7 root@192.168.50.150:/home/rootscplibavutil/libavutil.so.56 root@192.168.50.150:/home/rootscplibswresample/libswresample.so.3root@192.168.50.150:/home/rootscplibswscale/libswscale.so.5 root@192.168.50.150:/home/root
03.
測試FFmpeg程序
因此把FFmpeg的動態庫和主程序都復制到板上的/home/root目錄下了,因此執行FFmpeg時,會提示找不到依賴的運行庫,因此在開發板環境下首先設置一個動態連接庫的路徑。
export LD_LIBRARY_PATH=/home/root
1.查看FFmpeg運行輸出信息
然后執行ffmpeg –version ,看一下版本信息;
可見輸出了FFmpeg版本庫正確的信息。
2. 使用FFmpeg采集視頻
執行命令:
./ffmpeg-f v4l2 -s 320*240 -r 10 -i /dev/video2 output.yuv
把從攝像頭采集到的yuv數據,使用yuvview播放器上播放,播放如圖:
顯示采集視頻成功。
3. 使用FFmpeg采集編碼視頻
板上執行命令:
./ffmpeg -f v4l2 -s 640*360 -r 10 -i /dev/video2output1.mp4
傳輸到主機上,查看采集編碼的視頻內容。
可見,能夠正確的采集并編碼出視頻文件了。
3. 使用FFmpeg采集編碼并進行推送rtsp視頻流
因為在編譯ffmpeg時,沒加入X264編碼庫,因此這里只能使用mpeg4編碼器,因此執行命令如下:
./ffmpeg -t 10 -f video4linux2 -s176*144 -r 8 -i /dev/video2 -vcodec mpeg4 -f rtp rtp://192.168.50.171:554 >/ffmpeg.sdp
Rtsp推流測試,需要一個rtsp服務,推流軟件先使用rtsp協議把流推送到rtsp服務上,然后播放器通過連接rtsp服務器進行拉流播放。Rtsp服務這里使用了 RtspServer 開源rtsp服務器,地址為:
https://github.com/PHZ76/RtspServer.git
在ubuntu主機上編譯成rtsp服務程序,添加接收上行的流,再進行進入隊列,并進行分發即可。操作為啟動rtsp服務后,等待ffmpeg推流,在ffmpeg推流后,即可通過VLC 進行播放測試。
04.
測試FFmpeg例子程序
再測試一下基于FFmpeg庫的例子程序,這里測試一下example下的幾個例程,把例程copy到板子上:
然后進入開發板執行一個視頻合成例程 muxing,這個例程是調用ffmpeg庫,來生成一段機器合成視頻文件。
看一下輸出的視頻文件:
05.
開發FFmpeg應用程序
也可以基于FFmpeg庫進行視頻應用的開發,這里從網上下載一段FFmpeg的應用程序內容,來測試一下基于上面編譯的FFmpeg庫,來開發應用程序。
代碼如下:
int main(int argc, char **argv){ uint8_t *src_data[4], *dst_data[4]; int src_linesize[4], dst_linesize[4]; int src_w = 320, src_h = 240, dst_w, dst_h; enum AVPixelFormat src_pix_fmt = AV_PIX_FMT_YUV420P, dst_pix_fmt = AV_PIX_FMT_RGB24; const char *dst_size = NULL; const char *dst_filename = NULL; FILE *dst_file; int dst_bufsize; struct SwsContext *sws_ctx; int i, ret;
if (argc != 3) { fprintf(stderr, "Usage: %s output_file output_size\n" "API example program to show how to scale an image with libswscale.\n" "This program generates a series of pictures, rescales them to the given " "output_size and saves them to an output file named output_file\n." "\n", argv[0]); exit(1); } dst_filename = argv[1]; dst_size = argv[2];
if (av_parse_video_size(&dst_w, &dst_h, dst_size) < 0) { fprintf(stderr, "Invalid size '%s', must be in the form WxH or a valid size abbreviation\n", dst_size); exit(1); }
dst_file = fopen(dst_filename, "wb"); if (!dst_file) { fprintf(stderr, "Could not open destination file %s\n", dst_filename); exit(1); }
/* create scaling context */ sws_ctx = sws_getContext(src_w, src_h, src_pix_fmt, dst_w, dst_h, dst_pix_fmt, SWS_BILINEAR, NULL, NULL, NULL); if (!sws_ctx) { fprintf(stderr, "Impossible to create scale context for the conversion " "fmt:%s s:%dx%d -> fmt:%s s:%dx%d\n", av_get_pix_fmt_name(src_pix_fmt), src_w, src_h, av_get_pix_fmt_name(dst_pix_fmt), dst_w, dst_h); ret = AVERROR(EINVAL); goto end; }
/* allocate source and destination image buffers */ if ((ret = av_image_alloc(src_data, src_linesize, src_w, src_h, src_pix_fmt, 16)) < 0) { fprintf(stderr, "Could not allocate source image\n"); goto end; }
/* buffer is going to be written to rawvideo file, no alignment */ if ((ret = av_image_alloc(dst_data, dst_linesize, dst_w, dst_h, dst_pix_fmt, 1)) < 0) { fprintf(stderr, "Could not allocate destination image\n"); goto end; } dst_bufsize = ret;
for (i = 0; i < 100; i++) { /* generate synthetic video */ fill_yuv_image(src_data, src_linesize, src_w, src_h, i);
/* convert to destination format */ sws_scale(sws_ctx, (const uint8_t * const*)src_data, src_linesize, 0, src_h, dst_data, dst_linesize);
/* write scaled image to file */ fwrite(dst_data[0], 1, dst_bufsize, dst_file); }
fprintf(stderr, "Scaling succeeded. Play the output file with the command:\n" "ffplay -f rawvideo -pix_fmt %s -video_size %dx%d %s\n", av_get_pix_fmt_name(dst_pix_fmt), dst_w, dst_h, dst_filename);
end: fclose(dst_file); av_freep(&src_data[0]); av_freep(&dst_data[0]); sws_freeContext(sws_ctx); return ret < 0;}
編譯后,板上運行:
成功地輸出 rgb 格式的原始視頻文件,傳輸到PC上,使用yuvplayer 播放,可以看到生成的內容:
06.
Y6ULX板上FFmpeg移植測試開發總結
通過從這次在MYD-Y6ULL開發板上進行FFmpeg的移植編譯與應用開發測試過程看,FFmpeg在該開發板上移植非常容易,而且基本上代碼不做任何改動,能夠一次編譯通過。也說明了該開發板的C/C++的開發工具與庫支持比較完善,對這樣復雜的工程也有很好的支持。 這也大大方便了試用該方案進行音視頻開發的可能性,能夠利用開源社區大量的音視頻應用資源,開發出多種嵌入式的音視頻應用。
-
嵌入式
+關注
關注
5072文章
19026瀏覽量
303516 -
開發板
+關注
關注
25文章
4959瀏覽量
97214 -
米爾
+關注
關注
0文章
49瀏覽量
7921
發布評論請先 登錄
相關推薦
評論