/**
* 最简单的基于FFmpeg的视音频复用器
* Simplest FFmpeg Muxer
*
* 雷霄骅 Lei Xiaohua
* leixiaohua1020@126.com
* 中国传媒大学/数字电视技术
* Communication University of China / Digital TV Technology
* http://blog.csdn.net/leixiaohua1020
*
* 本程序可以将视频码流和音频码流打包到一种封装格式中。
* 程序中将AAC编码的音频码流和H.264编码的视频码流打包成
* MPEG2TS封装格式的文件。
* 需要注意的是本程序并不改变视音频的编码格式。
*
* This software mux a video bitstream and a audio bitstream
* together into a file.
* In this example, it mux a H.264 bitstream (in MPEG2TS) and
* a AAC bitstream file together into MP4 format file.
*
*/
#include <stdio.h>
extern "C"
{
#include "libavformat/avformat.h"
};
/*
FIX: H.264 in some container format (FLV, MP4, MKV etc.) need
"h264_mp4toannexb" bitstream filter (BSF)
*Add SPS,PPS in front of IDR frame
*Add start code ("0,0,0,1") in front of NALU
H.264 in some container (MPEG2TS) don't need this BSF.
*/
//'1': Use H.264 Bitstream Filter
#define USE_H264BSF 0
/*
FIX:AAC in some container format (FLV, MP4, MKV etc.) need
"aac_adtstoasc" bitstream filter (BSF)
*/
//'1': Use AAC Bitstream Filter
#define USE_AACBSF 0
int main(int argc, char* argv[])
{
AVOutputFormat *ofmt = NULL;
//输入对应一个AVFormatContext,输出对应一个AVFormatContext
//(Input AVFormatContext and Output AVFormatContext)
AVFormatContext *ifmt_ctx_v = NULL, *ifmt_ctx_a = NULL,*ofmt_ctx = NULL;
AVPacket pkt;
int ret, i;
char *in_filename_v = "cuc_ieschool.ts";//输入文件名(Input file URL)
//char *in_filename_v = "cuc_ieschool.h264";
//char *in_filename_a = "cuc_ieschool.mp3";
//char *in_filename_a = "gowest.m4a";
//char *in_filename_a = "gowest.aac";
char *in_filename_a = "huoyuanjia.mp3";
char *out_filename = "cuc_ieschool.mp4";//输出文件名(Output file URL)
av_register_all();
//输入(Input)
if ((ret = avformat_open_input(&ifmt_ctx_v, in_filename_v, 0, 0)) < 0) {
printf( "Could not open input file.");
goto end;
}
if ((ret = avformat_find_stream_info(ifmt_ctx_v, 0)) < 0) {
printf( "Failed to retrieve input stream information");
goto end;
}
if ((ret = avformat_open_input(&ifmt_ctx_a, in_filename_a, 0, 0)) < 0) {
printf( "Could not open input file.");
goto end;
}
if ((ret = avformat_find_stream_info(ifmt_ctx_a, 0)) < 0) {
printf( "Failed to retrieve input stream information");
goto end;
}
printf("Input Information=====================\n");
av_dump_format(ifmt_ctx_v, 0, in_filename_v, 0);
av_dump_format(ifmt_ctx_a, 0, in_filename_a, 0);
printf("======================================\n");
//输出(Output)
avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename);
if (!ofmt_ctx) {
printf( "Could not create output context\n");
ret = AVERROR_UNKNOWN;
goto end;
}
ofmt = ofmt_ctx->oformat;
int videoindex_v=-1,videoindex_out=-1;
for (i = 0; i < ifmt_ctx_v->nb_streams; i++) {
//根据输入流创建输出流(Create output AVStream according to input AVStream)
if(ifmt_ctx_v->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){
videoindex_v=i;
AVStream *in_stream = ifmt_ctx_v->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;
goto end;
}
videoindex_out=out_stream->index;
//复制AVCodecContext的设置(Copy the settings of AVCodecContext)
if (avcodec_copy_context(out_stream->codec, in_stream->codec) < 0) {
printf( "Failed to copy context from input to output stream codec context\n");
goto end;
}
out_stream->codec->codec_tag = 0;
if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
break;
}
}
int audioindex_a=-1,audioindex_out=-1;
for (i = 0; i < ifmt_ctx_a->nb_streams; i++) {
//根据输入流创建输出流(Create output AVStream according to input AVStream)
if(ifmt_ctx_a->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO){
audioindex_a=i;
AVStream *in_stream = ifmt_ctx_a->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;
goto end;
}
audioindex_out=out_stream->index;
//复制AVCodecContext的设置(Copy the settings of AVCodecContext)
if (avcodec_copy_context(out_stream->codec, in_stream->codec) < 0) {
printf( "Failed to copy context from input to output stream codec context\n");
goto end;
}
out_stream->codec->codec_tag = 0;
if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
break;
}
}
//输出一下格式------------------
printf("Output Information====================\n");
av_dump_format(ofmt_ctx, 0, out_filename, 1);
printf("======================================\n");
//打开输出文件(Open output file)
if (!(ofmt->flags & AVFMT_NOFILE)) {
if (avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE) < 0) {
printf( "Could not open output file '%s'", out_filename);
goto end;
}
}
//写文件头(Write file header)
if (avformat_write_header(ofmt_ctx, NULL) < 0) {
printf( "Error occurred when opening output file\n");
goto end;
}
int frame_index=0;
int64_t cur_pts_v=0,cur_pts_a=0;
//FIX
#if USE_H264BSF
AVBitStreamFilterContext* h264bsfc = av_bitstream_filter_init("h264_mp4toannexb");
#endif
#if USE_AACBSF
AVBitStreamFilterContext* aacbsfc = av_bitstream_filter_init("aac_adtstoasc");
#endif
while (1) {
AVFormatContext *ifmt_ctx;
int stream_index=0;
AVStream *in_stream, *out_stream;
//获取一个AVPacket(Get an AVPacket)
if(av_compare_ts(cur_pts_v,ifmt_ctx_v->streams[videoindex_v]->time_base,cur_pts_a,ifmt_ctx_a->streams[audioindex_a]->time_base) <= 0){
ifmt_ctx=ifmt_ctx_v;
stream_index=videoindex_out;
if(av_read_frame(ifmt_ctx, &pkt) >= 0){
do{
if(pkt.stream_index==videoindex_v){
cur_pts_v=pkt.pts;
break;
}
}while(av_read_frame(ifmt_ctx, &pkt) >= 0);
}else{
break;
}
}else{
ifmt_ctx=ifmt_ctx_a;
stream_index=audioindex_out;
if(av_read_frame(ifmt_ctx, &pkt) >= 0){
do{
if(pkt.stream_index==audioindex_a){
cur_pts_a=pkt.pts;
break;
}
}while(av_read_frame(ifmt_ctx, &pkt) >= 0);
}else{
break;
}
}
in_stream = ifmt_ctx->streams[pkt.stream_index];
out_stream = ofmt_ctx->streams[stream_index];
//FIX
#if USE_H264BSF
av_bitstream_filter_filter(h264bsfc, in_stream->codec, NULL, &pkt.data, &pkt.size, pkt.data, pkt.size, 0);
#endif
#if USE_AACBSF
av_bitstream_filter_filter(aacbsfc, in_stream->codec, NULL, &pkt.data, &pkt.size, pkt.data, pkt.size, 0);
#endif
//FIX:No PTS (Example: Raw H.264)
//Simple Write PTS
if(pkt.pts==AV_NOPTS_VALUE){
//Write PTS
AVRational time_base1=in_stream->time_base;
//Duration between 2 frames (us)
int64_t calc_duration=(double)AV_TIME_BASE/av_q2d(in_stream->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);
frame_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;
pkt.stream_index=stream_index;
printf("Write 1 Packet. size:%5d\tpts:%8d\n
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
该解决方案包含了使用FFmpeg进行封装格式处理的各种例子: simplest_ffmpeg_demuxer:视音频分离器。 simplest_ffmpeg_demuxer_simple:视音频分离器(简化版)。 simplest_ffmpeg_muxer:视音频复用器。 simplest_ffmpeg_remuxer:封装格式转换器。
资源推荐
资源详情
资源评论
收起资源包目录
最简单的基于FFmpeg的封装格式处理的例子 (453个子文件)
gowest.aac 296KB
simplest_ffmpeg_muxer.cpp 8KB
simplest_ffmpeg_demuxer.cpp 7KB
simplest_ffmpeg_remuxer.cpp 4KB
simplest_ffmpeg_demuxer_simple.cpp 4KB
avcodec-55.dll 18.06MB
avcodec-55.dll 18.06MB
avcodec-55.dll 18.06MB
avcodec-55.dll 18.06MB
avformat-55.dll 5.1MB
avformat-55.dll 5.1MB
avformat-55.dll 5.1MB
avformat-55.dll 5.1MB
avfilter-4.dll 1.94MB
avfilter-4.dll 1.94MB
avfilter-4.dll 1.94MB
avfilter-4.dll 1.94MB
avdevice-55.dll 1.28MB
avdevice-55.dll 1.28MB
avdevice-55.dll 1.28MB
avdevice-55.dll 1.28MB
swscale-2.dll 424KB
swscale-2.dll 424KB
swscale-2.dll 424KB
swscale-2.dll 424KB
avutil-52.dll 409KB
avutil-52.dll 409KB
avutil-52.dll 409KB
avutil-52.dll 409KB
swresample-0.dll 270KB
swresample-0.dll 270KB
swresample-0.dll 270KB
swresample-0.dll 270KB
postproc-52.dll 119KB
postproc-52.dll 119KB
postproc-52.dll 119KB
postproc-52.dll 119KB
simplest_ffmpeg_demuxer_simple.vcxproj.filters 1KB
simplest_ffmpeg_demuxer.vcxproj.filters 1KB
simplest_ffmpeg_muxer.vcxproj.filters 1KB
simplest_ffmpeg_remuxer.vcxproj.filters 961B
cuc_ieschool1.flv 1.61MB
cuc_ieschool.flv 1.25MB
.gitignore 46B
.gitignore 18B
.gitignore 18B
.gitignore 18B
.gitignore 18B
avcodec.h 171KB
avcodec.h 171KB
avcodec.h 171KB
avcodec.h 171KB
avformat.h 97KB
avformat.h 97KB
avformat.h 97KB
avformat.h 97KB
avfilter.h 56KB
avfilter.h 56KB
avfilter.h 56KB
avfilter.h 56KB
opt.h 34KB
opt.h 34KB
opt.h 34KB
opt.h 34KB
pixfmt.h 28KB
pixfmt.h 28KB
pixfmt.h 28KB
pixfmt.h 28KB
frame.h 22KB
frame.h 22KB
frame.h 22KB
frame.h 22KB
avio.h 18KB
avio.h 18KB
avio.h 18KB
avio.h 18KB
intreadwrite.h 18KB
intreadwrite.h 18KB
intreadwrite.h 18KB
intreadwrite.h 18KB
avdevice.h 16KB
avdevice.h 16KB
avdevice.h 16KB
avdevice.h 16KB
old_pix_fmts.h 14KB
old_pix_fmts.h 14KB
old_pix_fmts.h 14KB
old_pix_fmts.h 14KB
mem.h 14KB
mem.h 14KB
mem.h 14KB
mem.h 14KB
common.h 14KB
common.h 14KB
common.h 14KB
common.h 14KB
pixdesc.h 13KB
pixdesc.h 13KB
pixdesc.h 13KB
pixdesc.h 13KB
共 453 条
- 1
- 2
- 3
- 4
- 5
雷霄骅
- 粉丝: 4w+
- 资源: 141
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
- 3
- 4
- 5
- 6
前往页