自己動手寫RTP服務器——傳輸所有格式的視頻


上一篇文章我們介紹了如何用一個簡單的UDP socket搭建一個RTP服務器。我把這份80行的代碼呈現到客戶面前的時候,就有人不滿意了。
還有人在參考的時候會問:“樓主你的TS格式的文件是哪里來的?應該去哪里下載?”
“這也太簡單了吧,不就是用UDP把TS文件發過去么?就這么幾十行代碼也算個大作業?”
“平時看的視頻格式哪有TS的呀,不是avi就是mp4、rmvb什么的,根本不實用啊!”
 
首先回答問題1:
如果你用過強大的ffmpeg,就可以用一行簡單的命令
[plain]  view plain copy
 
 
  1. ffmpeg -i INPUTFILE.XXX OUTPUTFILE.ts  
把幾乎任何格式的文件轉換成TS文件。
 
再回答問題2:
如果能實現同樣的功能,我確實更傾向使用簡單的方法。說我偷懶也好,沒有技術含量也好。我覺得,很多時候最簡單直接的方法最有效。
 
這篇帖子主要的內容就是來回答問題3:如何用RTP協議傳輸各種格式的視頻。

預備知識

我們是否可以調用別人的分流器或者解碼器?
不要告訴我不可以。如果真的不可以,那么我們豈不是要把各種格式的視頻解碼器實現一遍?也就是說我們要自己重新寫一個ffmpeg工程!
當然是可以的,關鍵是看如何使用。有幾種選擇:借用別人的源碼然后集成到我們的工程;或是調用別人的接口來使用已經編譯好的庫;還是直接使用別人的程序?這就是復用粒度大小的選擇。很少有人會用第一種方法,因為別人的源碼不見得拿來就能編譯通過並且成功使用。多數人會選擇第二種方法,看起來順理成章,也是可以適應一定需求變化的。(這是做軟件最需要考慮的地方)
不過鑒於這個項目是一個課堂的作業,加上我比較喜歡偷懶,就選擇了最簡單的第三種方法。

參考代碼

第一步

首先需要對上一篇中的代碼做一些簡單的修改:
把原先的
[cpp]  view plain copy
 
 
  1. int main(){  
改為
[cpp]  view plain copy
 
 
  1. int main(int argc, char **argv){  
再把原先的
[cpp]  view plain copy
 
 
  1. FILE *ts_file = fopen("/home/baby/Videos/480p.ts", "r+");  
改為
[cpp]  view plain copy
 
 
  1. if (argc != 2){  
  2.     puts("Usage: ./rtp_server INPUTFILE");  
  3.     return 0;  
  4. }  
  5. FILE *ts_file = fopen(argv[1], "r+");  
可以看出我們這次不讀取固定文件,而是根據用戶自己的輸入讀取文件,這樣就靈活了許多。

第二步

源代碼編譯通過后,只需寫一個簡單的shell腳本mk_rtp_server.sh。
[plain]  view plain copy
 
 
  1. #!/bin/sh  
  2. mkfifo fifo.ts  
  3. ffmpeg -i $1 -y fifo.ts &  
  4. ./rtp_server fifo.ts  
只有四行有木有,很簡單有木有!
其實就是利用了ffmpeg的分流與解碼,然后利用命名管道把ffmpeg的輸出到處到一個管道中,然后再用我們前面寫好的rtp_server去讀這個文件。
(切記ffmpeg參數里面的-y是必不可少的)
OK,大功告成。chmod之后執行這個腳本文件./mk_rtp_server.sh INPUTFILE.XXX,拿個播放器測試一下。”嗯~果然不錯~“
只要你的ffmpeg裝的夠完整,那么幾乎所有的格式都可以變成rtp流。包括avi之類的非實時流文件格式。
 
大功告成!並且遠遠超過了當初的需求,但是客戶的需求善變如人心,下一步又是什么呢?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM