ffmepg cpp dav转mp4
时间: 2024-01-09 15:42:11 浏览: 135
FFmepg播放MP4
使用FFmpeg库可以将DAV文件转换为MP4格式。以下是C++代码示例:
```cpp
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
}
int main()
{
const char* input_filename = "input.dav";
const char* output_filename = "output.mp4";
AVFormatContext* input_format_context = nullptr;
AVFormatContext* output_format_context = nullptr;
AVCodec* codec = nullptr;
AVCodecContext* codec_context = nullptr;
AVStream* stream = nullptr;
AVPacket packet;
AVFrame* frame = nullptr;
SwsContext* sws_context = nullptr;
uint8_t* buffer = nullptr;
int video_stream_index = -1;
int ret = 0;
// Open input file
ret = avformat_open_input(&input_format_context, input_filename, nullptr, nullptr);
if (ret < 0)
{
printf("Error opening input file\n");
return -1;
}
// Get stream information
ret = avformat_find_stream_info(input_format_context, nullptr);
if (ret < 0)
{
printf("Error getting stream information\n");
return -1;
}
// Find video stream
for (unsigned int i = 0; i < input_format_context->nb_streams; i++)
{
if (input_format_context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
video_stream_index = i;
break;
}
}
if (video_stream_index == -1)
{
printf("Error finding video stream\n");
return -1;
}
// Open codec
codec = avcodec_find_decoder(input_format_context->streams[video_stream_index]->codecpar->codec_id);
if (!codec)
{
printf("Error finding decoder\n");
return -1;
}
codec_context = avcodec_alloc_context3(codec);
if (!codec_context)
{
printf("Error allocating codec context\n");
return -1;
}
ret = avcodec_parameters_to_context(codec_context, input_format_context->streams[video_stream_index]->codecpar);
if (ret < 0)
{
printf("Error setting codec parameters\n");
return -1;
}
ret = avcodec_open2(codec_context, codec, nullptr);
if (ret < 0)
{
printf("Error opening codec\n");
return -1;
}
// Open output file
avformat_alloc_output_context2(&output_format_context, nullptr, nullptr, output_filename);
if (!output_format_context)
{
printf("Error allocating output context\n");
return -1;
}
codec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!codec)
{
printf("Error finding encoder\n");
return -1;
}
stream = avformat_new_stream(output_format_context, codec);
if (!stream)
{
printf("Error creating new stream\n");
return -1;
}
codec_context = avcodec_alloc_context3(codec);
if (!codec_context)
{
printf("Error allocating codec context\n");
return -1;
}
codec_context->codec_id = codec->id;
codec_context->codec_type = AVMEDIA_TYPE_VIDEO;
codec_context->width = input_format_context->streams[video_stream_index]->codecpar->width;
codec_context->height = input_format_context->streams[video_stream_index]->codecpar->height;
codec_context->time_base = input_format_context->streams[video_stream_index]->time_base;
codec_context->pix_fmt = AV_PIX_FMT_YUV420P;
ret = avcodec_parameters_from_context(stream->codecpar, codec_context);
if (ret < 0)
{
printf("Error setting codec parameters\n");
return -1;
}
ret = avcodec_open2(codec_context, codec, nullptr);
if (ret < 0)
{
printf("Error opening codec\n");
return -1;
}
ret = avio_open(&output_format_context->pb, output_filename, AVIO_FLAG_WRITE);
if (ret < 0)
{
printf("Error opening output file\n");
return -1;
}
ret = avformat_write_header(output_format_context, nullptr);
if (ret < 0)
{
printf("Error writing header\n");
return -1;
}
// Allocate frame and buffer
frame = av_frame_alloc();
if (!frame)
{
printf("Error allocating frame\n");
return -1;
}
int buffer_size = av_image_get_buffer_size(codec_context->pix_fmt, codec_context->width, codec_context->height, 1);
buffer = (uint8_t*)av_malloc(buffer_size * sizeof(uint8_t));
av_image_fill_arrays(frame->data, frame->linesize, buffer, codec_context->pix_fmt, codec_context->width, codec_context->height, 1);
sws_context = sws_getContext(input_format_context->streams[video_stream_index]->codecpar->width, input_format_context->streams[video_stream_index]->codecpar->height, input_format_context->streams[video_stream_index]->codecpar->format, codec_context->width, codec_context->height, codec_context->pix_fmt, SWS_BICUBIC, nullptr, nullptr, nullptr);
// Read frames and write to output file
while (av_read_frame(input_format_context, &packet) >= 0)
{
if (packet.stream_index == video_stream_index)
{
ret = avcodec_send_packet(codec_context, &packet);
if (ret < 0)
{
printf("Error sending packet to decoder\n");
return -1;
}
while (ret >= 0)
{
ret = avcodec_receive_frame(codec_context, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
else if (ret < 0)
{
printf("Error receiving frame from decoder\n");
return -1;
}
sws_scale(sws_context, frame->data, frame->linesize, 0, input_format_context->streams[video_stream_index]->codecpar->height, frame->data, frame->linesize);
frame->pts = av_rescale_q(frame->pts, input_format_context->streams[video_stream_index]->time_base, stream->time_base);
frame->pkt_dts = av_rescale_q(frame->pkt_dts, input_format_context->streams[video_stream_index]->time_base, stream->time_base);
frame->pkt_duration = av_rescale_q(frame->pkt_duration, input_format_context->streams[video_stream_index]->time_base, stream->time_base);
frame->pkt_pos = -1;
ret = avcodec_send_frame(codec_context, frame);
if (ret < 0)
{
printf("Error sending frame to encoder\n");
return -1;
}
while (ret >= 0)
{
ret = avcodec_receive_packet(codec_context, &packet);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
else if (ret < 0)
{
printf("Error receiving packet from encoder\n");
return -1;
}
packet.stream_index = stream->index;
packet.pts = av_rescale_q(packet.pts, codec_context->time_base, stream->time_base);
packet.dts = av_rescale_q(packet.dts, codec_context->time_base, stream->time_base);
packet.duration = av_rescale_q(packet.duration, codec_context->time_base, stream->time_base);
packet.pos = -1;
ret = av_interleaved_write_frame(output_format_context, &packet);
if (ret < 0)
{
printf("Error writing packet\n");
return -1;
}
av_packet_unref(&packet);
}
}
}
av_packet_unref(&packet);
}
// Flush encoder
ret = avcodec_send_frame(codec_context, nullptr);
if (ret < 0)
{
printf("Error flushing encoder\n");
return -1;
}
while (ret >= 0)
{
ret = avcodec_receive_packet(codec_context, &packet);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
else if (ret < 0)
{
printf("Error receiving packet from encoder\n");
return -1;
}
packet.stream_index = stream->index;
packet.pts = av_rescale_q(packet.pts, codec_context->time_base, stream->time_base);
packet.dts = av_rescale_q(packet.dts, codec_context->time_base, stream->time_base);
packet.duration = av_rescale_q(packet.duration, codec_context->time_base, stream->time_base);
packet.pos = -1;
ret = av_interleaved_write_frame(output_format_context, &packet);
if (ret < 0)
{
printf("Error writing packet\n");
return -1;
}
av_packet_unref(&packet);
}
av_write_trailer(output_format_context);
// Free memory
if (input_format_context)
avformat_close_input(&input_format_context);
if (output_format_context)
{
if (output_format_context->pb)
avio_closep(&output_format_context->pb);
avformat_free_context(output_format_context);
}
if (codec_context)
avcodec_free_context(&codec_context);
if (frame)
av_frame_free(&frame);
if (buffer)
av_free(buffer);
if (sws_context)
sws_freeContext(sws_context);
return 0;
}
```
上述代码使用了FFmpeg库中的许多功能,例如打开文件、解码视频、编码视频、写入文件等。如果您不熟悉FFmpeg,建议先了解一些基本的概念和用法。
阅读全文