FFmpeg-rtmp推流例子(著重解析函式,剖析FFmpeg流程)
致敬雷霄驊師兄,感謝他的引領入門,以下都是他的筆記的個人補充。
本文,記錄在根據雷霄驊的RTMP推流demo原始碼,學習FFmpeg的執行流程。
記錄如下:
1. 首先是記錄demo並做一點修改,同時推送audio和video至rtmp-server。
2.對此程式碼的關鍵函式執行流程進行分析,或者說是關鍵結構體的賦值與複製的執行過程。
3.rtmp推流的簡單流程圖
rtmp-demo程式碼
#include <stdio.h> #include <libavformat/avformat.h> #include <libavutil/mathematics.h> #include <libavutil/time.h> #include <libavcodec/avcodec.h> int main(int argc, char* argv[]) { AVOutputFormat *ofmt = NULL; //輸入對應一個AVFormatContext,輸出對應一個AVFormatContext //(Input AVFormatContext and Output AVFormatContext) AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL; AVPacket pkt,pkt1; const char *in_filename, *out_filename; int ret, i; int videoindex=-1; int audioindex=-1; int frame_index=0; int64_t start_time=0; in_filename = "test.h264";//輸入URL(Input file URL) out_filename = "rtmp://192.168.1.190/live/livestream";//輸出 URL(Output URL)[RTMP] av_register_all(); //Network avformat_network_init(); //輸入(Input) if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) { printf( "Could not open input file."); goto end; } if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) { printf( "Failed to retrieve input stream information"); goto end; } for(i=0; i<ifmt_ctx->nb_streams; i++){ if(ifmt_ctx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO){ audioindex=i; } if(ifmt_ctx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){ videoindex = i; break;} } av_dump_format(ifmt_ctx, 0, in_filename, 0); //輸出(Output) avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", NULL); //RTMP //avformat_alloc_output_context2(&ofmt_ctx, NULL, "rtp", NULL);// RTP/RTCP於UDP傳輸,VLC播放需要SDP檔案 printf("filename0: %s\n",ofmt_ctx->filename ); if (!ofmt_ctx) { printf( "Could not create output context\n"); ret = AVERROR_UNKNOWN; goto end; } ofmt = ofmt_ctx->oformat; for (i = 0; i < ifmt_ctx->nb_streams; i++) { //根據輸入流建立輸出流(Create output AVStream according to input AVStream) AVStream *in_stream = ifmt_ctx->streams[i]; AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec); if (!out_stream) { printf( "Failed allocating output stream\n"); ret = AVERROR_UNKNOWN; goto end; } //複製AVCodecContext的設定(Copy the settings of AVCodecContext) ret = avcodec_copy_context(out_stream->codec, in_stream->codec); if (ret < 0) { printf( "Failed to copy context from input to output stream codec context\n"); goto end; } out_stream->codec->codec_tag = 0; if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; } //Dump Format------------------ av_dump_format(ofmt_ctx, 0, out_filename, 1); //開啟輸出URL(Open output URL) if (!(ofmt->flags & AVFMT_NOFILE)) { ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE); if (ret < 0) { printf( "Could not open output URL '%s'", out_filename); goto end; } } //寫檔案頭(Write file header) ret= avformat_write_header(ofmt_ctx, NULL); if (ret < 0) { printf( "Error occurred when opening output URL\n"); goto end; } start_time=av_gettime(); //av_new_packet(&pkt,2000); while (1) { AVStream *in_stream, *out_stream; //av_packet_ref(&pkt,&pkt1); //獲取一個AVPacket(Get an AVPacket) ret = av_read_frame(ifmt_ctx, &pkt); if (ret < 0) break; //Simple Write PTS if(pkt.pts==AV_NOPTS_VALUE){ //Write PTS AVRational time_base1=ifmt_ctx->streams[videoindex]->time_base; //Duration between 2 frames (us) int64_t calc_duration=(double)AV_TIME_BASE/av_q2d(ifmt_ctx->streams[videoindex]->r_frame_rate); //Parameters pkt.pts=(double)(frame_index*calc_duration)/(double)(av_q2d(time_base1)*AV_TIME_BASE); pkt.dts=pkt.pts; pkt.duration=(double)calc_duration/(double)(av_q2d(time_base1)*AV_TIME_BASE); } //Important:Delay if(pkt.stream_index==videoindex){ AVRational time_base=ifmt_ctx->streams[videoindex]->time_base; AVRational time_base_q={1,AV_TIME_BASE}; int64_t pts_time = av_rescale_q(pkt.dts, time_base, time_base_q); int64_t now_time = av_gettime() - start_time; if (pts_time > now_time) av_usleep(pts_time - now_time); } in_stream = ifmt_ctx->streams[pkt.stream_index]; out_stream = ofmt_ctx->streams[pkt.stream_index]; /* copy packet */ //轉換PTS/DTS(Convert PTS/DTS) pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, (AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX)); pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, (AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX)); pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base); pkt.pos = -1; //Print to Screen if(pkt.stream_index==videoindex){ printf("Send %8d video frames to output URL\n",frame_index); frame_index++; } ret = av_write_frame(ofmt_ctx, &pkt); //ret = av_interleaved_write_frame(ofmt_ctx, &pkt); if (ret < 0){ printf( "Error muxing packet\n"); break; } av_free_packet(&pkt); //av_packet_unref(&pkt1); } //寫檔案尾(Write file trailer) av_write_trailer(ofmt_ctx); end: avformat_close_input(&ifmt_ctx); /* close output */ if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE)) avio_close(ofmt_ctx->pb); avformat_free_context(ofmt_ctx); if (ret < 0 && ret != AVERROR_EOF) { printf( "Error occurred.\n"); return -1; } return 0; }
av_register_all()
函式作用:
參考連結:
avformat_network_init()
函式作用:參考連結:
avformat_open_input
函式作用:參考連結:
av_dump_format
函式作用:參考連結:
avformat_alloc_output_context2
函式作用:參考連結:
avformat_new_stream
函式作用:參考連結:
avcodec_copy_context
函式作用:參考連結:
avio_open
函式作用:參考連結:
avformat_write_header
函式作用:參考連結:
av_gettime
函式作用:參考連結:
av_read_frame
函式作用:參考連結:
av_interleaved_write_frame
函式作用:參考連結:
av_write_trailer
函式作用:參考連結:
rtmp推流的簡單流程圖
相關推薦
FFmpeg-rtmp推流例子(著重解析函式,剖析FFmpeg流程)
致敬雷霄驊師兄,感謝他的引領入門,以下都是他的筆記的個人補充。 本文,記錄在根據雷霄驊的RTMP推流demo原始碼,學習FFmpeg的執行流程。 記錄如下: 1. 首先是記錄demo並做一點修改,同時推送audio和video至rtmp-server。 2.對此程式碼的關鍵
最簡單的基於FFmpeg的推流器(以推送RTMP為例)
由於工作一部分工作是作為流媒體伺服器的程式設計師。所以自己那塊也算是處理了推流器的一塊程式碼吧。 這邊是從網上轉載的文章,原文:http://blog.csdn.net/leixiaohua1020/article/details/46890487 =========
ffmpeg rtmp推流 nginx搭建的rtmp伺服器
1、利用nginx搭建的rtmp伺服器 下載nginx-rtmp-module模組,解壓 下載nginx,解壓 進入nginx目錄下,編譯安裝nginx支援rtmp流媒體配置 ./configure
FFMPEG RTMP推流分析
簡介 RTMP推流器(Streamer)的在流媒體系統中的作用可以用下圖表示。首先將視訊資料以RTMP的形式傳送到流媒體伺服器端(Server,比如FMS,Red5,Wowza等),然後客戶端(一般為Flash Player)通過訪問流媒體伺服器就可以收看實時流了。
第七章——Windows核心基礎-核心理論基礎(0環通訊,核心函式,驅動載入流程)
windowsR3與R0通訊 當我們呼叫某個API的時候,這個API是被封裝在某個DLL庫中,而DLL庫中的函式則是在更底層的ntdll.dll檔案中,而相對應的則是呼叫ntdll中的Native API函式ntdll中的
C++模板類內友元(友元函式,友元類)宣告的三種情況
根據《C++ Primer》第三版16.4節的敘述,C++類模板友元分為以下幾種情況1.非模板友元類或友元函式。 書上給了一個例子:class Foo{ void bar();};template <class T>class QueueItem{
Nginx-RTMP推流(video)
Camera 採集資料 Camera負責採集資料,把採集來的資料交給 X264進行編碼打包給RTMP進行推流, Camera採集來的資料是NV21, 而X264編碼的輸入資料格式為I420格式。 NV21和I420都是屬於YUV420格式。而NV21是一種two-plane模式,即Y和UV分為兩個Pla
Nginx-RTMP推流(audio)
需要文中完整程式碼的可以前往Github上獲取,順便給個star唄。 AAC編碼 推送音訊跟推送視訊差不多,經過資料採集,編碼,然後通過RTMP推流。資料採集通常有兩種方式,一種是Java層的AudioRecord,另一種是native層opensl es;採集完後就是編碼,相比視訊比較簡單,編碼庫這
ffmpeg多執行緒本地mp4 rtmp推流,h264+aac編碼
程式說明:使用了c++11的std執行緒,鎖,訊號量等東西,替換了pthread多執行緒。主要之前用windows下移植的linux發現多執行緒始終有問題,所以決定用原生的試試。不過現在想來,應該問題還是我佇列的設計問題。主要這裡有個坑,就是c語言for迴圈內部
ffmpeg-設定推流,拉流使用的協議型別(TCP/UDP)
如有錯誤,請指正,謝謝。 拉流(設定TCP/UDP) //設定引數 AVDictionary *format_opts = NULL; av_dict_set(&format_opts, "stimeout", std::to_string( 2* 1000000).c_
java封裝FFmpeg命令,支援原生ffmpeg全部命令,實現FFmpeg多程序處理與多執行緒輸出控制(開啟、關閉、查詢),rtsp/rtmp推流、拉流
前言: 之前已經對FFmpeg命令進行了封裝http://blog.csdn.net/eguid_1/article/details/51787646,但是當時沒有考慮到擴充套件性,所以總體設計不是太好,需要改動的地方也比較多,也不支援原生ffmpeg命令,所以本次版本推翻
FFmpeg RTMP推HEVC/H265流
直播流媒體協議中,HLS和RTMP協議是兩大主流協議。而眾所周知的原因,RTMP在許多年前就已經停止拓展和更新,因此標準一直無法支援HEVC的編碼格式。目前國內的CDN還有金山雲等已經對RTMP進行了標準擴充套件,播放器上ijkplayer也擴充套件了該修改。
使用ffmpeg迴圈推流(迴圈讀取視訊檔案)推送EasyDSS RTMP流媒體伺服器的方法
需求 在做EasyDSS開發時,總是在測試推流效果。 有時候,我們想使用OBS進行推流測試,也可以,這很好。 以及其他RTMP推流工具。 但是,別忘了,還有ffmpeg這個神器。ffmpeg可以獲取各種視訊流,並推送給EasyDSS RTMP流媒體伺
視訊監控安防平臺-國標GB28181轉RTSP和RTMP推流進行H5(RTMP/HLS)直播(支援GB28181-2016版本、支援公網碼流傳輸)
視訊監控安防平臺-國標GB28181轉RTSP、RTMP和HLS管理平臺(支援GB28181-2016版本、支援公網碼流傳輸) 最近抽了點時間把國標GB28181轉RTSP、RTMP和HLS管理平臺做了簡單的整理,把相應的Demo也整理好了,
Docker(六)安裝Red5進行rtmp推流
red5 detail 啟動 推流 .net tail style 安裝 dai 1、pull鏡像 docker pull mondain/red5 2、啟動原版red5 docker run --name red5 -d -p 5080:5080 -p 1935:19
使用ffmpeg 測試rtmp推流和拉流
記錄簡單使用ffmpeg的使用: 環境:ubuntu16.04 推流操作: ffmpeg -f x11grab -i :0.0+0,0 -s 640x480 -r 10 -vcodec libx264 -preset ultrafast -acodec libmp3la
SRS服務器搭建,ffmpeg 本地推流
wiki config amp run 參考 figure with oot eos 參考: https://github.com/ossrs/srs/wiki/v2_CN_SampleFFMPEG git clone https://github.com/o
Android Studio 第六十期 - Android推流直播(鬥魚部分頁面功能)
直播 鬥魚 推流 代碼已經整理好,效果如下圖: 地址:https://github.com/geeklx/myapplication2018/tree/master/p004_livedemo Android Studio 第六十期 - Android推流直播(鬥魚部分頁面功能)
android全平臺編譯ffmpeg視訊推流實踐
ffmpeg實踐學習 android全平臺編譯ffmpeg以及x264與fdk-aac實踐 ubuntu下使用nginx和nginx-rtmp-module配置直播推流伺服器 android全平臺編譯ffmpeg合併為單個庫實踐 android-studio
基於c++實現RTSP/RTMP推流元件PushStream簡介
技術在於交流、溝通,轉載請註明出處並保持作品的完整性。 原文:https://blog.csdn.net/hiwubihe/article/details/84639975 [本系列相關文章] 本篇介紹一個基於C++開發的RTSP/RTMP推流元件Pus