dav转mp4用ffmpeg的cpp代码 visual studio
时间: 2023-12-20 20:07:57 浏览: 95
以下是使用FFmpeg进行dav转mp4的cpp代码(在Visual Studio环境下):
```
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
#include <libavutil/dict.h>
#include <libavutil/error.h>
#include <libavutil/mathematics.h>
#include <libavutil/opt.h>
#include <libavutil/samplefmt.h>
#include <libswscale/swscale.h>
}
int main()
{
const char* input_file_path = "input.dav";
const char* output_file_path = "output.mp4";
// Open input file
AVFormatContext* format_ctx = nullptr;
if (avformat_open_input(&format_ctx, input_file_path, nullptr, nullptr) < 0) {
av_log(nullptr, AV_LOG_ERROR, "Could not open input file %s\n", input_file_path);
return -1;
}
// Get stream info
if (avformat_find_stream_info(format_ctx, nullptr) < 0) {
av_log(nullptr, AV_LOG_ERROR, "Could not find stream information\n");
return -1;
}
// Find video and audio stream
AVCodec* video_codec = nullptr;
AVCodec* audio_codec = nullptr;
int video_stream_index = -1;
int audio_stream_index = -1;
for (int i = 0; i < format_ctx->nb_streams; ++i) {
if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
video_stream_index = i;
video_codec = avcodec_find_decoder(format_ctx->streams[i]->codecpar->codec_id);
}
else if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
audio_stream_index = i;
audio_codec = avcodec_find_decoder(format_ctx->streams[i]->codecpar->codec_id);
}
}
if (video_stream_index == -1 && audio_stream_index == -1) {
av_log(nullptr, AV_LOG_ERROR, "Could not find any video or audio stream\n");
return -1;
}
// Open video codec
AVCodecContext* video_codec_ctx = nullptr;
if (video_codec != nullptr) {
video_codec_ctx = avcodec_alloc_context3(video_codec);
if (avcodec_parameters_to_context(video_codec_ctx, format_ctx->streams[video_stream_index]->codecpar) < 0) {
av_log(nullptr, AV_LOG_ERROR, "Could not copy video codec parameters to context\n");
return -1;
}
if (avcodec_open2(video_codec_ctx, video_codec, nullptr) < 0) {
av_log(nullptr, AV_LOG_ERROR, "Could not open video codec\n");
return -1;
}
}
// Open audio codec
AVCodecContext* audio_codec_ctx = nullptr;
if (audio_codec != nullptr) {
audio_codec_ctx = avcodec_alloc_context3(audio_codec);
if (avcodec_parameters_to_context(audio_codec_ctx, format_ctx->streams[audio_stream_index]->codecpar) < 0) {
av_log(nullptr, AV_LOG_ERROR, "Could not copy audio codec parameters to context\n");
return -1;
}
if (avcodec_open2(audio_codec_ctx, audio_codec, nullptr) < 0) {
av_log(nullptr, AV_LOG_ERROR, "Could not open audio codec\n");
return -1;
}
}
// Open output file
AVFormatContext* output_format_ctx = nullptr;
if (avformat_alloc_output_context2(&output_format_ctx, nullptr, nullptr, output_file_path) < 0) {
av_log(nullptr, AV_LOG_ERROR, "Could not create output context\n");
return -1;
}
// Add video stream to output file
AVStream* video_stream = nullptr;
if (video_codec_ctx != nullptr) {
video_stream = avformat_new_stream(output_format_ctx, video_codec);
if (video_stream == nullptr) {
av_log(nullptr, AV_LOG_ERROR, "Could not create video stream\n");
return -1;
}
if (avcodec_parameters_copy(video_stream->codecpar, format_ctx->streams[video_stream_index]->codecpar) < 0) {
av_log(nullptr, AV_LOG_ERROR, "Could not copy video codec parameters to output stream\n");
return -1;
}
if (avcodec_parameters_to_context(video_stream->codec, video_stream->codecpar) < 0) {
av_log(nullptr, AV_LOG_ERROR, "Could not copy video codec parameters to output stream context\n");
return -1;
}
video_stream->codec->codec_tag = 0;
video_stream->time_base = format_ctx->streams[video_stream_index]->time_base;
}
// Add audio stream to output file
AVStream* audio_stream = nullptr;
if (audio_codec_ctx != nullptr) {
audio_stream = avformat_new_stream(output_format_ctx, audio_codec);
if (audio_stream == nullptr) {
av_log(nullptr, AV_LOG_ERROR, "Could not create audio stream\n");
return -1;
}
if (avcodec_parameters_copy(audio_stream->codecpar, format_ctx->streams[audio_stream_index]->codecpar) < 0) {
av_log(nullptr, AV_LOG_ERROR, "Could not copy audio codec parameters to output stream\n");
return -1;
}
if (avcodec_parameters_to_context(audio_stream->codec, audio_stream->codecpar) < 0) {
av_log(nullptr, AV_LOG_ERROR, "Could not copy audio codec parameters to output stream context\n");
return -1;
}
audio_stream->codec->codec_tag = 0;
audio_stream->time_base = format_ctx->streams[audio_stream_index]->time_base;
}
// Open output file for writing
if (!(output_format_ctx->oformat->flags & AVFMT_NOFILE)) {
if (avio_open(&output_format_ctx->pb, output_file_path, AVIO_FLAG_WRITE) < 0) {
av_log(nullptr, AV_LOG_ERROR, "Could not open output file %s\n", output_file_path);
return -1;
}
}
// Write header to output file
if (avformat_write_header(output_format_ctx, nullptr) < 0) {
av_log(nullptr, AV_LOG_ERROR, "Could not write header to output file\n");
return -1;
}
// Convert video frames
AVFrame* video_frame = av_frame_alloc();
AVFrame* video_frame_rgb = av_frame_alloc();
if (video_codec_ctx != nullptr) {
SwsContext* sws_ctx = sws_getContext(video_codec_ctx->width, video_codec_ctx->height,
video_codec_ctx->pix_fmt, video_codec_ctx->width, video_codec_ctx->height,
AV_PIX_FMT_RGB24, SWS_BILINEAR, nullptr, nullptr, nullptr);
if (sws_ctx == nullptr) {
av_log(nullptr, AV_LOG_ERROR, "Could not create SwsContext\n");
return -1;
}
av_image_alloc(video_frame_rgb->data, video_frame_rgb->linesize, video_codec_ctx->width, video_codec_ctx->height,
AV_PIX_FMT_RGB24, 1);
AVPacket packet;
av_init_packet(&packet);
while (av_read_frame(format_ctx, &packet) >= 0) {
if (packet.stream_index == video_stream_index) {
if (avcodec_send_packet(video_codec_ctx, &packet) == 0) {
while (avcodec_receive_frame(video_codec_ctx, video_frame) == 0) {
sws_scale(sws_ctx, video_frame->data, video_frame->linesize, 0,
video_codec_ctx->height, video_frame_rgb->data, video_frame_rgb->linesize);
video_frame_rgb->pts = video_frame->pts;
if (avcodec_send_frame(video_stream->codec, video_frame_rgb) < 0) {
av_log(nullptr, AV_LOG_ERROR, "Could not send video frame to output stream\n");
return -1;
}
while (avcodec_receive_packet(video_stream->codec, &packet) == 0) {
if (av_write_frame(output_format_ctx, &packet) < 0) {
av_log(nullptr, AV_LOG_ERROR, "Could not write video packet to output file\n");
return -1;
}
av_packet_unref(&packet);
}
}
}
}
av_packet_unref(&packet);
}
avcodec_send_frame(video_stream->codec, nullptr);
while (avcodec_receive_packet(video_stream->codec, &packet) == 0) {
if (av_write_frame(output_format_ctx, &packet) < 0) {
av_log(nullptr, AV_LOG_ERROR, "Could not write video packet to output file\n");
return -1;
}
av_packet_unref(&packet);
}
sws_freeContext(sws_ctx);
}
// Convert audio frames
AVFrame* audio_frame = av_frame_alloc();
if (audio_codec_ctx != nullptr) {
AVPacket packet;
av_init_packet(&packet);
while (av_read_frame(format_ctx, &packet) >= 0) {
if (packet.stream_index == audio_stream_index) {
if (avcodec_send_packet(audio_codec_ctx, &packet) == 0) {
while (avcodec_receive_frame(audio_codec_ctx, audio_frame) == 0) {
audio_frame->pts = audio_frame->best_effort_timestamp;
if (avcodec_send_frame(audio_stream->codec, audio_frame) < 0) {
av_log(nullptr, AV_LOG_ERROR, "Could not send audio frame to output stream\n");
return -1;
}
while (avcodec_receive_packet(audio_stream->codec, &packet) == 0) {
if (av_write_frame(output_format_ctx, &packet) < 0) {
av_log(nullptr, AV_LOG_ERROR, "Could not write audio packet to output file\n");
return -1;
}
av_packet_unref(&packet);
}
}
}
}
av_packet_unref(&packet);
}
avcodec_send_frame(audio_stream->codec, nullptr);
while (avcodec_receive_packet(audio_stream->codec, &packet) == 0) {
if (av_write_frame(output_format_ctx, &packet) < 0) {
av_log(nullptr, AV_LOG_ERROR, "Could not write audio packet to output file\n");
return -1;
}
av_packet_unref(&packet);
}
}
// Write trailer to output file
if (av_write_trailer(output_format_ctx) < 0) {
av_log(nullptr, AV_LOG_ERROR, "Could not write trailer to output file\n");
return -1;
}
// Close output file
if (!(output_format_ctx->oformat->flags & AVFMT_NOFILE)) {
avio_close(output_format_ctx->pb);
}
// Free resources
avcodec_free_context(&video_codec_ctx);
avcodec_free_context(&audio_codec_ctx);
avformat_close_input(&format_ctx);
avformat_free_context(output_format_ctx);
av_frame_free(&video_frame);
av_frame_free(&video_frame_rgb);
av_frame_free(&audio_frame);
return 0;
}
```
这段代码使用了FFmpeg的多个库来进行视频和音频的解码、转换和编码,具体实现细节可以参考FFmpeg的官方文档。
阅读全文