#include<iostream>
#include <cstring>
#include <cstdlib>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/opt.h>
#include <libavutil/time.h>
#include <libavutil/imgutils.h>
}
using namespace std;
const char* input_file = "/mnt/hgfs/shareVM/welcom_to_beijing.h264";
// const char* input_file = "/mnt/hgfs/shareVM/welcom_to_beijing.mp4";
const char* output_rtmp_url = "rtmp://10.10.18.94:1935/live/test";
#define CODEC_FLAG_GLOBAL_HEADER 0x00400000
int main() {
cout << "Hello World!" << endl;
AVOutputFormat *ofmt = NULL;
AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
AVPacket pkt;
int videoindex = -1;
int frame_index = 0;
int64_t start_time = 0;
av_register_all();
avformat_network_init();
if(avformat_open_input(&ifmt_ctx, input_file, 0, 0) < 0) {
cout<<"could not open input file."<<endl;
goto end;
}
if(avformat_find_stream_info(ifmt_ctx, 0) < 0) {
cout<<"failed to retrieve input stream information"<<endl;
goto end;
}
for(int 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, input_file, 0);
avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", output_rtmp_url);
if(!ofmt_ctx) {
cout<<"could not create output context"<<endl;
goto end;
}
ofmt = ofmt_ctx->oformat;
for(int i=0;i<ifmt_ctx->nb_streams;i++) {
AVStream *in_stream = ifmt_ctx->streams[i];
AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);
if(!out_stream) {
cout<<"failed allocating output stream"<<endl;
goto end;
}
if(avcodec_copy_context(out_stream->codec, in_stream->codec) < 0) {
cout<<"failed to copy context from input to output stream codec context"<<endl;
goto end;
}
out_stream->codec->codec_tag = 0;
if(ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
av_dump_format(ofmt_ctx, 0, output_rtmp_url, 1);
if(!(ofmt->flags & AVFMT_NOFILE)) {
if(avio_open(&ofmt_ctx->pb, output_rtmp_url, AVIO_FLAG_WRITE) < 0) {
cout<<"could not open output rtmp url."<<endl;
goto end;
}
}
if(avformat_write_header(ofmt_ctx, NULL) < 0) {
cout<<"error occurred when opening output rtmp url."<<endl;
goto end;
}
start_time = av_gettime();
while (1) {
AVStream *in_stream, *out_stream;
if(av_read_frame(ifmt_ctx, &pkt) < 0)
break;
if(pkt.pts == AV_NOPTS_VALUE) {
AVRational time_base1 = ifmt_ctx->streams[videoindex]->time_base;
int64_t calc_duration = (double)AV_TIME_BASE/av_q2d(ifmt_ctx->streams[videoindex]->r_frame_rate);
pkt.dts = pkt.pts = (double)(frame_index*calc_duration)/(double)(av_q2d(time_base1)*AV_TIME_BASE);
pkt.duration = (double)calc_duration/(double)(av_q2d(time_base1)*AV_TIME_BASE);
}
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];
pkt.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.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);
pkt.pos = -1;
if(pkt.stream_index == videoindex) {
cout<<"send "<<frame_index<<" video frame to output rtmp url."<<endl;
frame_index++;
}
if(av_interleaved_write_frame(ofmt_ctx, &pkt) < 0) {
cout<<"error muxing packet."<<endl;
break;
}
av_free_packet(&pkt);
}
av_write_trailer(ofmt_ctx);
end:
avformat_close_input(&ifmt_ctx);
if(ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))
avio_close(ofmt_ctx->pb);
avformat_free_context(ofmt_ctx);
return 0;
}
FFMpeg rtmp 推送本地H264文件或mp4文件
于 2024-05-30 11:29:12 首次发布