生活随笔
收集整理的這篇文章主要介紹了
ffmpeg 推流MP4文件,采用rtmp协议
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
- 本程序ffmpeg版本是:ffmpeg version 3.2.4 Copyright ? 2000-2017 the FFmpeg developers。
- 不同ffmpeg版本會稍微有點不同,比如最明顯ffmpeg 4.0和ffmpeg 3.0少了一些注冊類函數(shù)(如:av_register_all())還有編解碼函數(shù)方式等。
- 本程序是經(jīng)過ffmpeg 推流FLV文件,采用rtmp協(xié)議這個例子修改而來的。
- 下面分二部分:
一、和上面例子有那些區(qū)分;
二、源代碼分享 - 一、和上面例子有那些區(qū)分;
1、賦值配置信息:把a(bǔ)vcodec_parameters_copy()替換成avcodec_copy_context()。
2、時間基轉(zhuǎn)換函數(shù):把a(bǔ)v_rescale_q_rnd()都替換成av_rescale_q()。
int64_t
av_rescale_q(int64_t a
, AVRational bq
, AVRational cq
)
{av_rescale_q_rnd(a
,bq
,cq
,AV_ROUND_NEAR_INF
);
}
3、pts計算:pts = pkt.pts * (1000 * 1000 * r2d(otime));
otime是輸出流,作為延遲推流使用。不延遲話,推流太快,會導(dǎo)致拉流播放有問題。
4、mp4的視頻時間基為{1,25};flv的視頻時間基為{1,1000}。因為輸出推流就是使用flv,所以必須進(jìn)行轉(zhuǎn)換才可以正常播放和推流。
5、推流部分只是涉及到解協(xié)議、解封裝的,然后一幀幀推流過去。想特殊處理比如加密,加入視頻中特效等,就需要解碼、過濾、編碼、推流這部分的邏輯。
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
= "D:/ghb/video_audio_dev/ffmpeg-udemy/FFMpeg實時美顏直播推流實戰(zhàn) ffmpeg,qt5,opencv/03 FFMpegSDK3529923553216442551227969/3.1第一個ffmpegVs2015項目代碼包含庫文件/src/3.6file_to_rtmp_控制推流速度/008_3.mp4";char *outUrl
= "rtmp://192.168.32.128/live";av_register_all();avformat_network_init();AVFormatContext
*ictx
= NULL;int re
= avformat_open_input(&ictx
, inUrl
, 0, 0);if (re
!= 0){return XError(re
);}cout
<< "open file " << inUrl
<< " Success." << endl
;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
;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);}re
= avcodec_copy_context(out
->codec
, ictx
->streams
[i
]->codec
);out
->codec
->codec_tag
= 0;}av_dump_format(octx
, 0, outUrl
, 1);re
= avio_open(&octx
->pb
, outUrl
, AVIO_FLAG_WRITE
);if (!octx
->pb
){return XError(re
);}re
= avformat_write_header(octx
, 0);printf("in code id = %d 。 out code id = %d\n", ictx
->streams
[0]->codecpar
->codec_id
, octx
->streams
[0]->codecpar
->codec_id
);printf("in code id = %d 。 out code id = %d\n", ictx
->streams
[1]->codecpar
->codec_id
, octx
->streams
[1]->codecpar
->codec_id
);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;}AVRational itime
= ictx
->streams
[pkt
.stream_index
]->time_base
;AVRational otime
= octx
->streams
[pkt
.stream_index
]->time_base
; pkt
.pts
= av_rescale_q(pkt
.pts
, itime
, otime
);pkt
.dts
= av_rescale_q(pkt
.dts
, itime
, otime
);pkt
.duration
= av_rescale_q(pkt
.duration
, itime
, otime
);pkt
.pos
= -1;if (ictx
->streams
[pkt
.stream_index
]->codecpar
->codec_type
== AVMEDIA_TYPE_VIDEO
){long long now
= av_gettime() - startTime
;long long pts
= 0;pts
= pkt
.pts
* (1000 * 1000 * r2d(otime
));if (pts
> now
){av_usleep(pts
- now
);cout
<< pts
- now
<<endl
;}}re
= av_interleaved_write_frame(octx
, &pkt
);if (re
<0){return XError(re
);}}cout
<< "file to rtmp test" << endl
;getchar();return 0;
}
(上面有錯誤,有問題話,請多多指教,謝謝。一起學(xué)習(xí),一起進(jìn)步,加油!)
總結(jié)
以上是生活随笔為你收集整理的ffmpeg 推流MP4文件,采用rtmp协议的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。