ffmpeg 推流檔案,採用rtmp協議
- 想看懂這個程式碼需要掌握以下音視訊基礎知識
1、音視訊時間基是什麼?
FFMPEG之TimeBase成員理解
補充:封裝/解封裝、編碼/解碼、採集/顯示這三個層面中的taimeBase是代表不同的意思的,需要通過轉換才可以進行上下層的互動。
2、ffmpeg中對AVRational結構體理解
ffmpeg # AVRational
假如一秒25幀就是1/25;那麼換算成每毫秒25幀就是1000* 1 /25 = 1000/25;換算成每微妙25幀話就是1000*1000/25(每一毫秒等於1000微妙)。
3、PTS和DTS是什麼?
PTS:顯示的時間;
DTS:編碼/解碼時間;
音訊在時間軸是連續的,所以PTS和DTS是一樣的;
視訊中因為有I、B、P幀,I是關鍵幀,P是向前預測,B是向前向後預測所以當沒有B幀時候PTS和DTS在時間軸是一樣的,為什麼有了B幀就就不一樣的呢,因為B幀要等待其他幀解碼出來後才知道這個B幀是 多少。
I、B、P幀主要是為了更拼命努力壓縮空間的。
4、rtmp協議
rtmp協議詳細內容
rtmp協議詳細內容2
絕大多數的流媒體推流都會採用rtmp協議的。
5、flv格式
flv格式解析
檔案推流時候有的格式不支援,是因為伺服器那邊解析不了這種格式。想推流特殊的格式可以在伺服器裡面新增特殊檔案的解析。
extern "C"
{
#include "libavformat/avformat.h"
#include "libavutil/time.h"
}
#include <iostream>
using namespace std;
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"avcodec.lib")
int XError(int errNum)
{
char buf[1024] = { 0 };
av_strerror(errNum, buf, sizeof(buf));
cout << buf << endl;
getchar();
return -1;
}
static double r2d(AVRational r)
{
return r.num == 0 || r.den == 0 ? 0. : (double)r.num / (double)r.den;
}
int main(int argc, char *argv[])
{
char *inUrl = "test.flv";
char *outUrl = "rtmp://192.168.1.102/live";
//初始化所有封裝和解封裝 flv mp4 mov mp3
av_register_all();
//初始化網路庫
avformat_network_init();
//
//輸入流 1 開啟檔案,解封裝
//輸入封裝上下文
AVFormatContext *ictx = NULL;
//開啟檔案,解封檔案頭
int re = avformat_open_input(&ictx, inUrl, 0, 0);
if (re != 0)
{
return XError(re);
}
cout << "open file " << inUrl << " Success." << endl;
//獲取音訊視訊流資訊 ,h264 flv
re = avformat_find_stream_info(ictx, 0);
if (re != 0)
{
return XError(re);
}
av_dump_format(ictx, 0, inUrl, 0);
//
//
//輸出流
//建立輸出流上下文
AVFormatContext *octx = NULL;
re = avformat_alloc_output_context2(&octx, 0, "flv", outUrl);
if (!octx)
{
return XError(re);
}
cout << "octx create success!" << endl;
//配置輸出流
//遍歷輸入的AVStream
for (int i = 0; i < ictx->nb_streams; i++)
{
//建立輸出流
AVStream *out = avformat_new_stream(octx, ictx->streams[i]->codec->codec);
if (!out)
{
return XError(0);
}
//複製配置資訊,同於MP4
//re = avcodec_copy_context(out->codec, ictx->streams[i]->codec);
re = avcodec_parameters_copy(out->codecpar, ictx->streams[i]->codecpar);
out->codec->codec_tag = 0;
}
av_dump_format(octx, 0, outUrl, 1);
//
//rtmp推流
//開啟io
re = avio_open(&octx->pb, outUrl, AVIO_FLAG_WRITE);
if (!octx->pb)
{
return XError(re);
}
//寫入頭資訊
re = avformat_write_header(octx, 0);
if (re < 0)
{
return XError(re);
}
cout << "avformat_write_header " << re << endl;
AVPacket pkt;
long long startTime = av_gettime();
for (;;)
{
re = av_read_frame(ictx, &pkt);
if (re != 0)
{
break;
}
cout << pkt.pts << " " << flush;
//計算轉換pts dts
AVRational itime = ictx->streams[pkt.stream_index]->time_base;
AVRational otime = octx->streams[pkt.stream_index]->time_base;
pkt.pts = av_rescale_q_rnd(pkt.pts, itime, otime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_NEAR_INF));
pkt.dts = av_rescale_q_rnd(pkt.dts, itime, otime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_NEAR_INF));
pkt.duration = av_rescale_q_rnd(pkt.duration, itime, otime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_NEAR_INF));
pkt.pos = -1;
//視訊幀推送速度
if (ictx->streams[pkt.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
AVRational tb = ictx->streams[pkt.stream_index]->time_base;
//已經過去的時間
long long now = av_gettime() - startTime;
long long pts = 0;
pts = pkt.pts * (1000 * 1000 * r2d(tb));
if (pts > now)
av_usleep(pts - now);
}
re = av_interleaved_write_frame(octx, &pkt);
if (re<0)
{
return XError(re);
}
}
cout << "file to rtmp test" << endl;
getchar();
return 0;
}
相關文章
- ffmpeg+rtmp推流/拉流(十)
- python利用ffmpeg進行rtmp推流直播Python
- Android中使用ffmpeg編碼進行rtmp推流Android
- 影片直播原始碼開發中的流媒體協議:rtmp協議原始碼協議
- FFmpeg開發筆記(三十一)使用RTMP Streamer開啟APP直播推流筆記APP
- Nginx-RTMP推流(audio)Nginx
- Nginx-RTMP推流(video)NginxIDE
- 自建rtmp服務推流
- FFmpeg開發筆記(四十)Nginx整合rtmp模組實現RTMP推拉流筆記Nginx
- FFmpeg開發筆記(三十八)APP如何訪問SRS推流的RTMP直播地址筆記APP
- RTMP協議相關知識協議
- rtsp->rtmp 推流直播 Plan B
- 【開源專案】向Nginx-RTMP伺服器推流Nginx伺服器
- NGINX如何實現rtmp推流服務Nginx
- 通過 wireshark 抓包瞭解直播流媒體 RTMP 協議基本過程協議
- 在Linux中,我們都知道,dns採用了tcp協議,又採用了udp協議,什麼時候採用tcp協議?什麼 時候採用udp協議?為什麼要這麼設計?LinuxDNSTCP協議UDP
- ffmpeg第8篇:使用ffprobe採集檔案資訊
- ffmpeg/ffplay rtmp 推拉測試
- Swift採用語言伺服器協議Swift伺服器協議
- RTMP協議學習——Message與Chunk解讀協議
- 檔案傳輸協議介紹協議
- Raysync檔案傳輸協議(FTP)協議FTP
- 匯流排協議系列——USART協議初探協議
- 音視訊通訊——直播協議和視訊推流協議
- OBS 配合 nginx_rtmp_module 模組 可以多路推流Nginx
- ffmpeg+nginx將rtsp轉為rtmpNginx
- Nginx+FFmpeg實現RTSP轉RTMPNginx
- 為什麼ChatGPT採用SSE協議而不是Websocket?ChatGPT協議Web
- 直播協議詳解 RTMP、HLS、HTTP-FLV、WebRTC、RTSP協議HTTPWeb
- ARM 匯流排協議協議
- JavaCV推流實戰(MP4檔案)Java
- Bigfile 用新的方式管理檔案,支援 HTTP,RPC 以及 FTP 協議HTTPRPCFTP協議
- 4種傳輸協議設定,檔案傳輸協議如何選擇?協議
- TCP/IP協議及配置、檔案系統TCP協議
- 一個私有協議檔案DB 的解析.協議
- jftp通過sftp協議上傳檔案FTP協議
- 音視訊學習 (十一) Android 端實現 rtmp 推流Android
- NGINX如何實現rtmp推流服務--視訊快取Nginx快取