/* 合并音频和视频,形成音视频 */ extern "C" { #include "libavutil/avutil.h" #include "libavformat/avformat.h" #include "libavformat/avio.h" #include "libavcodec/avcodec.h" } #pragma warning(disable:4996) int main() { // const char *srcMedia1 = "out/t2Video.h264"; const char *srcMedia2 = "out/T2audio.aac"; const char *destMedia = "out/T2.mp4"; char errors[200] = {0}; AVFormatContext *inFormatContext1 = NULL; AVFormatContext *inFormatContext2 = NULL; AVFormatContext *outFormatContext = NULL; //输入上下文1-视频 int ret = 0; av_log_set_level(AV_LOG_INFO); av_register_all(); ret = avformat_open_input(&inFormatContext1, srcMedia1, NULL, NULL); if (ret != 0) { av_strerror(ret, errors, 200); av_log(NULL, AV_LOG_WARNING, "error, ret=%d, msg=%s\n", ret, errors); return -1; } avformat_find_stream_info(inFormatContext1, NULL); av_dump_format(inFormatContext1, -1, srcMedia1, 0); //输入上下文1-音频 ret = avformat_open_input(&inFormatContext2, srcMedia2, NULL, NULL); avformat_find_stream_info(inFormatContext2, NULL); av_dump_format(inFormatContext2, -1, srcMedia2, 0); //输出上下文 avformat_alloc_output_context2(&outFormatContext, NULL, NULL, destMedia); AVOutputFormat *outFormat = outFormatContext->oformat; int stream1 = 0; AVStream *inStream1 = NULL; //复制流信息 if (inFormatContext1->nb_streams > 0) { stream1 = 1; inStream1 = inFormatContext1->streams[0]; AVStream *outStream = avformat_new_stream(outFormatContext, NULL); avcodec_parameters_copy(outStream->codecpar, inStream1->codecpar); outStream->codecpar->codec_tag = 0; } int stream2 = 0; AVStream *inStream2 = NULL; if (inFormatContext2->nb_streams > 0) { stream2 = 1; inStream2 = inFormatContext2->streams[0]; AVStream *outStream = avformat_new_stream(outFormatContext, NULL); avcodec_parameters_copy(outStream->codecpar, inStream2->codecpar); outStream->codecpar->codec_tag = 0; } av_dump_format(outFormatContext, -1, destMedia, 1); //打开文件 avio_open(&outFormatContext->pb, destMedia, AVIO_FLAG_WRITE); avformat_write_header(outFormatContext, NULL); int64_t curPts1 = 0; int64_t curPts2 = 0; AVPacket avPacket; av_init_packet(&avPacket); //输入流时间基 AVRational inStream1time = inStream1->time_base; AVRational inStream2time = inStream2->time_base; int frameIndex = 0; //交替写入音频和视频数据 while (stream1 || stream2) { if (stream1 && (!stream2 || av_compare_ts(curPts1, inStream1time, curPts2, inStream2time) < = 0)) { ret = av_read_frame(inFormatContext1, &avPacket); if (ret & lt; 0) { stream1 = 0; continue; } // raw h264无pts,手动添加 if (avPacket.pts == AV_NOPTS_VALUE) { AVRational timeBase = inStream1time; int64_t calcDuration = AV_TIME_BASE / av_q2d(inStream1->r_frame_rate); avPacket.pts = (double)(frameIndex * calcDuration) / (av_q2d(timeBase) * AV_TIME_BASE); avPacket.dts = avPacket.pts; avPacket.duration = (double)calcDuration / (av_q2d(timeBase) * AV_TIME_BASE); frameIndex++; } curPts1 = avPacket.pts; AVStream *outStream = outFormatContext->streams[0]; avPacket.pts = av_rescale_q_rnd(avPacket.pts, inStream1time, outStream->time_base, AVRounding(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); avPacket.dts = avPacket.pts; avPacket.duration = av_rescale_q(avPacket.duration, inStream1time, outStream->time_base); avPacket.pos = -1; avPacket.stream_index = 0; // av_log(NULL, AV_LOG_INFO, "xxxxxxxxx%d, dts=%lld, pts=%lld, duration=%lld\n", frameIndex, avPacket.dts, avPacket.pts, avPacket.duration); stream1 = !av_interleaved_write_frame(outFormatContext, &avPacket); } else if (stream2) { ret = av_read_frame(inFormatContext2, &avPacket); if (ret & lt; 0) { stream2 = 0; continue; } // raw aac无pts,手动添加 if (avPacket.pts == AV_NOPTS_VALUE) { AVRational timeBase = inStream2time; int64_t calcDuration = AV_TIME_BASE / av_q2d(inStream2->r_frame_rate); avPacket.pts = (double)(frameIndex * calcDuration) / (av_q2d(timeBase) * AV_TIME_BASE); avPacket.dts = avPacket.pts; avPacket.duration = (double)calcDuration / (av_q2d(timeBase) * AV_TIME_BASE); frameIndex++; } curPts2 = avPacket.pts; AVStream *outStream = outFormatContext->streams[1]; avPacket.pts = av_rescale_q_rnd(avPacket.pts, inStream2time, outStream->time_base, AVRounding(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); avPacket.dts = avPacket.pts; avPacket.duration = av_rescale_q(avPacket.duration, inStream2time, outStream->time_base); avPacket.pos = -1; avPacket.stream_index = 1; av_log(NULL, AV_LOG_INFO, "xxxxxxxxx%d, size:%5d, dts=%lld, pts=%lld, duration=%lld\n", frameIndex, avPacket.size, avPacket.dts, avPacket.pts, avPacket.duration); stream2 = !av_interleaved_write_frame(outFormatContext, &avPacket); } av_packet_unref(&avPacket); } ret = av_write_trailer(outFormatContext); if (ret != 0) { av_strerror(ret, errors, 200); av_log(NULL, AV_LOG_WARNING, "av_write_trailer error: ret=%d, msg=%s\n", ret, errors); } //释放资源 avformat_close_input(&inFormatContext1); avformat_close_input(&inFormatContext2); avio_close(outFormatContext->pb); return 0; }