動態

詳情 返回 返回

FFmpeg開發筆記(八十一)FFmpeg代碼對RTSP和RTMP的推流區別 - 動態 詳情

《FFmpeg開發實戰:從零基礎到短視頻上線》一書的“10.2.2  FFmpeg向網絡推流”介紹瞭如何使用FFmpeg代碼向網絡推送視頻流,當時的例程採用了RTSP方式推流,在向RTSP地址時推流是正常的,但向RTMP地址推流時出現了問題,下面就介紹瞭如何使用FFmpeg代碼向RTMP地址推送視頻流。

一、FFmpeg推流環境的區別

首先注意RTSP推流地址以“ rtsp:// ”開頭,且RTSP地址的默認端口號為8554。而RTMP推流地址以“ rtmp:// ”開頭,且RTMP地址的默認端口號為1935。
其次注意FFmpeg從6.1開始對RTMP協議做了增強支持,主要是支持HEVC、VP9和AV1等編碼格式通過RTMP協議進行推流,所以建議將編譯環境的FFmpeg版本升級到6.1或者更高版本。 

二、FFmpeg推流代碼的適配

FFmpeg推流代碼對於RTSP地址和RTMP地址主要有下列兩點適配區別:
1、調用avformat_alloc_output_context2函數分配音視頻文件封裝實例的時候,第三個輸入參數對於RTSP地址而言要填rtsp,對於RTMP地址而言要填flv。比如以下代碼通過判斷推流地址的協議類型來決定avformat_alloc_output_context2的第三個參數要填何值。

int ret = 0;
// 分配音視頻文件的封裝實例(注意rtmp協議的第三個參數填flv,rtsp協議的第三個參數填rtsp)
if (strstr(dest_name, "rtmp") != NULL) {
    ret = avformat_alloc_output_context2(&out_fmt_ctx, NULL, "flv", dest_name);
} else {
    ret = avformat_alloc_output_context2(&out_fmt_ctx, NULL, "rtsp", dest_name);
}
if (ret < 0) {
    av_log(NULL, AV_LOG_ERROR, "Can't alloc output_file %s.\n", dest_name);
    return -1;
}
av_log(NULL, AV_LOG_INFO, "Success open push url %s.\n", dest_name);

2、調用avformat_alloc_output_context2函數之後,還要依據推流地址的協議類型來決定是否接着調用avio_open函數打開輸出流,對於RTSP地址而言不必調用avio_open,對於RTMP地址而言必須調用avio_open。具體的判斷與調用代碼如下所示:

// 打開輸出流(注意rtsp推流不要調用avio_open,但rtmp推流要調用avio_open)
if (strstr(dest_name, "rtmp") != NULL) {
    ret = avio_open(&out_fmt_ctx->pb, dest_name, AVIO_FLAG_READ_WRITE);
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "Can't open output_file %s.\n", dest_name);
        return -1;
    }
}

按照以上兩點代碼修改了《FFmpeg開發實戰:從零基礎到短視頻上線》隨書源碼第十章的推流程序代碼chapter10/pushvideo.c後,先按照之前的文章《詳解MediaMTX的推拉流》啓動電腦本地的流媒體服務器MediaMTX,再執行下面的編譯命令。

gcc pushvideo.c -o pushvideo -I/usr/local/ffmpeg/include -L/usr/local/ffmpeg/lib -lavformat -lavdevice -lavfilter -lavcodec -lavutil -lswscale -lswresample -lpostproc -lm

編譯完成後執行以下命令啓動測試程序,期望把2018.mp4推給RTMP協議的推流地址rtmp://127.0.0.1:1935/stream。

./pushvideo ../file/2018.mp4 rtmp://127.0.0.1:1935/stream

接着打開另一個MSYS窗口,同樣進入該書第十章的源碼目錄chapter10,執行下面的編譯命令。

gcc pullvideo.c -o pullvideo -I/usr/local/ffmpeg/include -L/usr/local/ffmpeg/lib -I/usr/local/sdl2/include -L/usr/local/sdl2/lib -lsdl2 -lavformat -lavdevice -lavfilter -lavcodec -lavutil -lswscale -lswresample -lpostproc -lm

編譯完成後執行以下命令啓動測試程序,期望從 http://127.0.0.1:8888/stream/index.m3u8 拉取視頻流並彈窗播放。

./pullvideo http://127.0.0.1:8888/stream/index.m3u8

然後果真彈出一個SDL窗口,正在播放從HLS服務拉取的視頻畫面,説明修改後的推流代碼成功支持了RTMP協議。

更多詳細的FFmpeg開發知識參見《FFmpeg開發實戰:從零基礎到短視頻上線》一書。

user avatar uwatechnologies 頭像 kindledawn 頭像 tong_6816038415d24 頭像
點贊 3 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.