安装依赖库
yum -y install gcc gcc-c++ gdb automake nasm
下载源代码并编译
git clone https://gitee.com/mirrors/ffmpeg.git
cd ffmpeg
./configure --prefix=/usr/local/ffmpeg
make
make install
写测试程序
复制雷霄骅的代码:https://blog.csdn.net/leixiaohua1020/article/details/25422685
修改之后如下:
/*
*最简单的基于FFmpeg的封装格式转换器
*Simplest FFmpeg Remuxer
*
*雷霄骅 Lei Xiaohua
*leixiaohua1020@126.com
*中国传媒大学/数字电视技术
*Communication University of China / Digital TV Technology
*http://blog.csdn.net/leixiaohua1020
*
*本程序实现了视频封装格式之间的转换。
*需要注意的是本程序并不改变视音频的编码格式。
*
* This software converts a media file from one container format
* to another container format without encoding/decoding video files.
*/
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <stdint.h>
#if HAVE_IO_H
#include <io.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
extern "C"
{
#include "libavformat/avformat.h"
};
int main(int argc, char* argv[])
{
AVOutputFormat *ofmt = NULL;
//输入对应一个AVFormatContext,输出对应一个AVFormatContext
//(Input AVFormatContext and Output AVFormatContext)
AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
AVPacket pkt;
const char *in_filename, *out_filename;
int ret, i;
if (argc < 3) {
printf("usage: %s input output
"
"Remux a media file with libavformat and libavcodec.
"
"The output format is guessed according to the file extension.
"
"Modified by Lei Xiaohua, leixiaohua1020@126.com
"
"Communication University of China / Digital TV Technology
"
"http://blog.csdn.net/leixiaohua1020", argv[0]);
return 1;
}
in_filename = argv[1];//输入文件名(Input file URL)
out_filename = argv[2];//输出文件名(Output file URL)
av_register_all();
do{
//输入(Input)
if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {
printf( "Could not open input file.");
break;
}
if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
printf( "Failed to retrieve input stream information");
break;
}
av_dump_format(ifmt_ctx, 0, in_filename, 0);
//输出(Output)
//avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", out_filename);
avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename);
if (!ofmt_ctx) {
printf( "Could not create output context
");
ret = AVERROR_UNKNOWN;
break;
}
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
");
ret = AVERROR_UNKNOWN;
break;
}
//复制AVCodecContext的设置(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
");
break;
}
out_stream->codec->codec_tag = 0;
if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
if (ret < 0){
break;
}
//输出一下格式------------------
av_dump_format(ofmt_ctx, 0, out_filename, 1);
//打开输出文件(Open output file)
if (!(ofmt->flags & AVFMT_NOFILE)) {
ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
if (ret < 0) {
printf( "Could not open output file '%s'", out_filename);
break;
}
}
//写文件头(Write file header)
ret = avformat_write_header(ofmt_ctx, NULL);
if (ret < 0) {
printf( "Error occurred when opening output file
");
break;
}
int frame_index=0;
while (1) {
AVStream *in_stream, *out_stream;
//获取一个AVPacket(Get an AVPacket)
ret = av_read_frame(ifmt_ctx, &pkt);
if (ret < 0)
break;
in_stream = ifmt_ctx->streams[pkt.stream_index];
out_stream = ofmt_ctx->streams[pkt.stream_index];
/* copy packet */
//转换PTS/DTS(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;
//写入(Write)
ret = av_interleaved_write_frame(ofmt_ctx, &pkt);
if (ret < 0) {
printf( "Error muxing packet
");
continue;
}
printf("Write %8d frames to output file
",frame_index);
av_free_packet(&pkt);
frame_index++;
}
//写文件尾(Write file trailer)
av_write_trailer(ofmt_ctx);
}while(0);
avformat_close_input(&ifmt_ctx);
/* close output */
if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))
avio_close(ofmt_ctx->pb);
avformat_free_context(ofmt_ctx);
if (ret < 0 && ret != AVERROR_EOF) {
printf( "Error occurred.
");
return -1;
}
return 0;
}
编译
g++ simplest_ffmpeg_remuxer.cpp -g -o simplest_ffmpeg_remuxer -I /usr/local/ffmpeg/include -L /usr/local/ffmpeg/lib -lavformat -lavcodec -lavutil -lswscale -lswresample -lavfilter -lpthread
运行
./simplest_ffmpeg_remuxer "udp://127.0.0.1:1234" "rtmp://192.168.0.33:1935/hls/testcp"
出现的问题
1.编译过程中会报一些错"undefined reference"
/usr/local/ffmpeg/lib/libavformat.a(avienc.o): In function `avi_write_header':
/home/ffmpeg/ffmpeg/libavformat/avienc.c:317: undefined reference to `ceil'
/usr/local/ffmpeg/lib/libavformat.a(matroskaenc.o): In function `mkv_write_trailer':
/home/ffmpeg/ffmpeg/libavformat/matroskaenc.c:2591: undefined reference to `fmod'
/usr/local/ffmpeg/lib/libavcodec.a(aaccoder.o): In function `quantize_and_encode_band_cost_template':
/home/ffmpeg/ffmpeg/libavcodec/aacenc_quantization.h:108: undefined reference to `cbrtf'
/home/ffmpeg/ffmpeg/libavutil/display.c:38: undefined reference to `hypot'
.......
解决方法:
检查编译参数是否写全,"-lavformat -lavcodec -lavutil -lswscale -lswresample -lavfilter -lpthread"