/*
* RtmpPublishManager.cpp
*
* Created on: 2019年1月11日
* Author: wtxu
*/
#include "RtmpPublishManager.h"
RtmpPublishManager::RtmpPublishManager(char* url, int readfd) {
// TODO Auto-generated constructor stub
this->readfd = readfd;
memset(out_filename, 0, sizeof(out_filename));
memcpy(out_filename, url, strlen(url));
}
RtmpPublishManager::~RtmpPublishManager() {
// TODO Auto-generated destructor stub
pthread_cancel(tid);
av_freep(avio_in);
av_free(inbuffer);
avformat_close_input(&ifmt_ctx);
close(this->readfd);
}
int RtmpPublishManager::read_buffer(void *opaque, uint8_t *buf, int buf_size){
int read_fd = *(int*)opaque;
if(read_fd > 0){
int true_size= read(read_fd, buf, buf_size);
return true_size;
}else{
return -1;
}
}
int RtmpPublishManager::ffmpeg_init(char* rtmpurl){
int ret = -1, i = 0;
av_register_all();
//Network
avformat_network_init();
inbuffer=(unsigned char*)av_malloc(32768*4);
ifmt_ctx=avformat_alloc_context();
avio_in =avio_alloc_context(inbuffer, 32768*4,0,(void*)&readfd,read_buffer,NULL,NULL);
if(avio_in==NULL){
printf( "Could not open file.");
}
ifmt_ctx->pb=avio_in;
ifmt_ctx->flags=AVFMT_FLAG_CUSTOM_IO;
//Input
if ((ret = avformat_open_input(&ifmt_ctx, "whatever", NULL, NULL)) < 0) {
printf( "Could not open input file.");
return ret;
}
if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
printf( "Failed to retrieve input stream information");
return ret;
}
for(i=0; i<ifmt_ctx->nb_streams; i++)
if(ifmt_ctx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){
videoindex=i;
break;
}
av_dump_format(ifmt_ctx, 0, "nothting", 0);
//Output
avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", out_filename); //RTMP
//avformat_alloc_output_context2(&ofmt_ctx, NULL, "mpegts", out_filename);//UDP
if (!ofmt_ctx) {
printf( "Could not create output context\n");
ret = AVERROR_UNKNOWN;
return ret;
}
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;
return ret;
}
//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");
return ret;
}
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);
//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);
return ret;
}
}
//Write file header
ret = avformat_write_header(ofmt_ctx, NULL);
if (ret < 0) {
printf( "Error occurred when opening output URL\n");
return ret;
}
start_time=av_gettime();
}
void* RtmpPublishManager::publishRtmpThread(void* arg){
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
RtmpPublishManager* rmp = (RtmpPublishManager*)arg;
char thread_name[100] = {0};
sprintf(thread_name, "publishRtmpThread");
prctl(PR_SET_NAME, thread_name, 0,0,0);
int ret = -1;
AVPacket pkt;
int64_t start_time = av_gettime();
int videoindex = rmp->videoindex;
int frame_index = rmp->frame_index;
AVStream *in_stream, *out_stream;
AVFormatContext *ifmt_ctx = rmp->ifmt_ctx;
AVFormatContext *ofmt_ctx = rmp->ofmt_ctx;
while (1) {
pthread_testcancel();
//Get an AVPacket
ret = av_read_frame(ifmt_ctx, &pkt);
if (ret < 0){
printf("av_read_frame failed.\n");
break;
}
//FIX:No PTS (Example: Raw H.264)
//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 */
//Convert PTS/DTS
pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, (AVRounding)(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){
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);
}
//Write file trailer
av_write_trailer(ofmt_ctx);
}
bool RtmpPublishManager::start(){
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&tid, &attr, publishRtmpThread, (void*)this);
pthread_detach(tid);
}
基于ffmpeg实现的rtmp推流模块
1星 需积分: 46 52 浏览量
2019-02-28
11:44:02
上传
评论 2
收藏 3KB RAR 举报
xwt_chn
- 粉丝: 0
- 资源: 1
最新资源
- 基于jsp+mysql的JSP九宫格日记本源码.zip
- 基于jsp+mysql的JSP会员卡积分管理系统源码.zip
- 仿小米商城微信小程序源码+项目说明.zip
- 基于jsp+mysql的JSP个人日记本源码.zip
- 南溪CN No1 fps网络断网工具.zip
- 基于jsp+mysql的JSP宠物商城源码.zip
- C++开发基于Qt的音乐播放器的设计与实现项目源码+项目使用说明(毕业设计).zip
- 基于jsp+mysql+servlet的JSP图书馆图书管理系统源码.zip
- C++开发基于Qt的音乐播放器的设计与实现项目源码+项目使用说明(毕业设计).zip
- 【2024win11软件启动速度反应慢解决方法附工具】
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈