关键步骤
avformat_open_input
avformat_find_stream_info
avformat_alloc_output_context2
avformat_new_stream
avcodec_copy_context
avio_open
avformat_write_header
av_interleaved_write_frame
av_write_trailer(octx);
大致过程:打开(/配置)输入、创建输出(上下文/流)、配置输出流、打开输出IO、循环推流。推流本地文件的时候要计算一下pts、dts,并作延时推送。
Code
#include <stdio.h>
extern "C"
{
#include "libavformat\avformat.h"
#include "libavutil\time.h"
}
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "avcodec.lib")
int Error(
int res)
{
char buf[
1024] = {
0 };
av_strerror(res, buf,
sizeof(buf));
printf(
"error : %s.\n", buf);
return res;
}
int main(
int argc,
char* argv[])
{
char* inUrl =
"rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov";
char* outUrl =
"rtmp://123.207.71.137/live/test";
av_register_all();
avformat_network_init();
int res =
0;
AVFormatContext* ictx =
NULL;
AVDictionary *opts =
NULL;
av_dict_set(&opts,
"max_delay",
"500",
0);
if ((res = avformat_open_input(&ictx, inUrl,
NULL, &opts)) !=
0)
return Error(res);
if ((res = avformat_find_stream_info(ictx,
NULL)) <
0)
return Error(res);
av_dump_format(ictx,
0, inUrl,
0);
AVFormatContext* octx =
NULL;
if ((res = avformat_alloc_output_context2(&octx,
NULL,
"flv", outUrl) <
0))
return Error(res);
for (
int i =
0; i < ictx->nb_streams; ++i)
{
AVStream* out = avformat_new_stream(octx, ictx->streams[i]->codec->codec);
if (out ==
NULL)
{
printf(
"new stream error.\n");
return -
1;
}
if ((res = avcodec_copy_context(out->codec, ictx->streams[i]->codec)) !=
0)
return Error(res);
}
av_dump_format(octx,
0, outUrl,
1);
res = avio_open(&octx->pb, outUrl, AVIO_FLAG_WRITE);
if (octx->pb ==
NULL)
return Error(res);
if ((res = avformat_write_header(octx,
NULL)) <
0)
return Error(res);
long long begintime = av_gettime();
long long realdts =
0;
long long caldts =
0;
AVPacket pkt;
while (
true)
{
if ((res = av_read_frame(ictx, &pkt)) !=
0)
break;
if(pkt
.size <=
0)
continue;
pkt
.pts = pkt
.pts * av_q2d(ictx->streams[pkt
.stream_index]->time_base) / av_q2d(octx->streams[pkt
.stream_index]->time_base);
pkt
.dts = pkt
.dts * av_q2d(ictx->streams[pkt
.stream_index]->time_base) / av_q2d(octx->streams[pkt
.stream_index]->time_base);
pkt
.duration = pkt
.duration * av_q2d(ictx->streams[pkt
.stream_index]->time_base) / av_q2d(octx->streams[pkt
.stream_index]->time_base);
pkt
.pos = -
1;
if ((res = av_interleaved_write_frame(octx, &pkt)) <
0)
Error(res);
av_free_packet(&pkt);
}
av_write_trailer(octx);
system(
"pause");
return 0;
}
Github
https://github.com/gongluck/FFmpegTest.git