ffmpeg dav转mp4 cpp示例
时间: 2023-10-09 22:06:02 浏览: 50
下面是一个基于FFmpeg的C++示例代码,用于将Dav文件转换为MP4格式:
```cpp
#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/mathematics.h>
#include <libavutil/time.h>
}
int main(int argc, char** argv) {
AVOutputFormat* ofmt = NULL;
AVFormatContext* ifmt_ctx = NULL, * ofmt_ctx = NULL;
AVPacket pkt;
int ret, i;
int64_t start_time = 0;
int video_index = -1;
std::string input_file = "input.dav";
std::string output_file = "output.mp4";
// Initialize FFmpeg libraries
av_register_all();
avcodec_register_all();
// Open input file
if ((ret = avformat_open_input(&ifmt_ctx, input_file.c_str(), 0, 0)) < 0) {
std::cerr << "Cannot open input file" << std::endl;
return ret;
}
// Retrieve stream information
if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
std::cerr << "Cannot find stream information" << std::endl;
return ret;
}
// Open output file
if ((ret = avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, output_file.c_str())) < 0) {
std::cerr << "Cannot create output context" << std::endl;
return ret;
}
ofmt = ofmt_ctx->oformat;
// Find video stream index
for (i = 0; i < ifmt_ctx->nb_streams; i++) {
AVStream* in_stream = ifmt_ctx->streams[i];
AVCodecParameters* in_codecpar = in_stream->codecpar;
if (in_codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
video_index = i;
break;
}
}
// Copy input codec parameters to output codec context
AVStream* in_stream = ifmt_ctx->streams[video_index];
AVCodecParameters* in_codecpar = in_stream->codecpar;
AVStream* out_stream = avformat_new_stream(ofmt_ctx, NULL);
if (!out_stream) {
std::cerr << "Failed allocating output stream" << std::endl;
return AVERROR_UNKNOWN;
}
if ((ret = avcodec_parameters_copy(out_stream->codecpar, in_codecpar)) < 0) {
std::cerr << "Failed to copy codec parameters" << std::endl;
return ret;
}
out_stream->codecpar->codec_tag = 0;
// Open output file for writing
if (!(ofmt->flags & AVFMT_NOFILE)) {
if ((ret = avio_open(&ofmt_ctx->pb, output_file.c_str(), AVIO_FLAG_WRITE)) < 0) {
std::cerr << "Cannot open output file" << std::endl;
return ret;
}
}
// Write file header
if ((ret = avformat_write_header(ofmt_ctx, NULL)) < 0) {
std::cerr << "Error occurred when opening output file" << std::endl;
return ret;
}
// Read frames from input file and write to output file
while (1) {
AVStream* in_stream, * out_stream;
// Get next packet from input file
if ((ret = av_read_frame(ifmt_ctx, &pkt)) < 0)
break;
// Adjust packet timestamps
if (pkt.pts == AV_NOPTS_VALUE) {
// Write PTS based on frame number
AVRational time_base1 = ifmt_ctx->streams[video_index]->time_base;
int64_t calc_duration = (double)AV_TIME_BASE / av_q2d(ifmt_ctx->streams[video_index]->r_frame_rate);
pkt.pts = (double)(start_time * time_base1.den) / time_base1.num / (double)(calc_duration);
pkt.dts = pkt.pts;
pkt.duration = (double)calc_duration / (double)(time_base1.den) * time_base1.num;
}
// Find corresponding output stream
in_stream = ifmt_ctx->streams[pkt.stream_index];
out_stream = ofmt_ctx->streams[pkt.stream_index];
// Copy packet metadata
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 packet to output file
if ((ret = av_interleaved_write_frame(ofmt_ctx, &pkt)) < 0) {
std::cerr << "Error muxing packet" << std::endl;
break;
}
av_packet_unref(&pkt);
}
// Write file trailer
av_write_trailer(ofmt_ctx);
// Clean up
if (ifmt_ctx && !(ifmt_ctx->flags & AVFMT_NOFILE))
avformat_close_input(&ifmt_ctx);
if (ofmt_ctx && !(ofmt_ctx->flags & AVFMT_NOFILE))
avio_closep(&ofmt_ctx->pb);
avformat_free_context(ofmt_ctx);
return 0;
}
```
这段代码做了以下几件事情:
1. 初始化FFmpeg库并打开输入文件。
2. 查找视频流索引并将输入编解码器参数复制到输出编解码器上下文中。
3. 创建输出文件并将其写入头。
4. 从输入文件中读取帧并将其写入输出文件中。
5. 写入输出文件尾并清理内存。
要使用此代码,请确保已经将FFmpeg库正确安装并将其头文件和库文件路径添加到项目中。
相关推荐
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)