ffmepg cpp dav转mp4 vs代码
时间: 2024-05-07 16:18:26 浏览: 5
以下是使用ffmpeg和C++将dav格式转换为mp4的示例代码:
```cpp
#include <iostream>
#include <string>
#include <cstdlib>
#include <cstdio>
// FFmpeg libraries
extern "C" {
#include <libavutil/avutil.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
#include <libavutil/opt.h>
}
int main(int argc, char* argv[])
{
if(argc < 3) {
std::cout << "Usage: " << argv[0] << " <input_file> <output_file>" << std::endl;
return 0;
}
const char* input_file = argv[1];
const char* output_file = argv[2];
// Register all the codecs, formats and protocols.
av_register_all();
AVFormatContext* input_ctx = nullptr;
AVFormatContext* output_ctx = nullptr;
// Open input file.
if(avformat_open_input(&input_ctx, input_file, nullptr, nullptr) < 0) {
std::cerr << "Could not open input file: " << input_file << std::endl;
return -1;
}
// Retrieve stream information.
if(avformat_find_stream_info(input_ctx, nullptr) < 0) {
std::cerr << "Could not find stream information." << std::endl;
return -1;
}
// Open output file.
if(avformat_alloc_output_context2(&output_ctx, nullptr, nullptr, output_file) < 0) {
std::cerr << "Could not create output context." << std::endl;
return -1;
}
// Get the output format.
AVOutputFormat* output_fmt = output_ctx->oformat;
// Create a new stream in the output file.
AVStream* out_stream = avformat_new_stream(output_ctx, nullptr);
if(!out_stream) {
std::cerr << "Could not create output stream." << std::endl;
return -1;
}
// Get the input codec parameters.
AVCodecParameters* in_codecpar = input_ctx->streams[0]->codecpar;
// Get the codec for the output format.
AVCodec* codec = avcodec_find_encoder(output_fmt->video_codec);
if(!codec) {
std::cerr << "Could not find encoder." << std::endl;
return -1;
}
// Create a new codec context for the output file.
AVCodecContext* codec_ctx = avcodec_alloc_context3(codec);
if(!codec_ctx) {
std::cerr << "Could not allocate codec context." << std::endl;
return -1;
}
// Set the codec parameters.
if(avcodec_parameters_to_context(codec_ctx, in_codecpar) < 0) {
std::cerr << "Could not set codec parameters." << std::endl;
return -1;
}
// Set the codec context options.
av_opt_set(codec_ctx->priv_data, "preset", "slow", 0);
av_opt_set(codec_ctx->priv_data, "crf", "20", 0);
// Open the codec.
if(avcodec_open2(codec_ctx, codec, nullptr) < 0) {
std::cerr << "Could not open codec." << std::endl;
return -1;
}
// Copy the stream parameters to the output stream.
if(avcodec_parameters_from_context(out_stream->codecpar, codec_ctx) < 0) {
std::cerr << "Could not copy codec parameters." << std::endl;
return -1;
}
// Write the file header.
if(avformat_write_header(output_ctx, nullptr) < 0) {
std::cerr << "Could not write header." << std::endl;
return -1;
}
// Allocate frame for decoding.
AVFrame* frame = av_frame_alloc();
if(!frame) {
std::cerr << "Could not allocate frame." << std::endl;
return -1;
}
// Allocate frame for encoding.
AVFrame* enc_frame = av_frame_alloc();
if(!enc_frame) {
std::cerr << "Could not allocate frame." << std::endl;
return -1;
}
// Determine required buffer size and allocate.
int num_bytes = av_image_get_buffer_size(codec_ctx->pix_fmt, codec_ctx->width, codec_ctx->height, 1);
uint8_t* buffer = (uint8_t*)av_malloc(num_bytes * sizeof(uint8_t));
// Assign appropriate parts of buffer to image planes in enc_frame.
av_image_fill_arrays(enc_frame->data, enc_frame->linesize, buffer, codec_ctx->pix_fmt, codec_ctx->width, codec_ctx->height, 1);
// Initialize the scaler context.
SwsContext* scaler_ctx = sws_getContext(in_codecpar->width, in_codecpar->height, (AVPixelFormat)in_codecpar->format, codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt, SWS_BICUBIC, nullptr, nullptr, nullptr);
// Initialize the packet.
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = nullptr;
pkt.size = 0;
// Read packets from the input file.
while(av_read_frame(input_ctx, &pkt) >= 0) {
// Decode the packet into a frame.
int ret = avcodec_send_packet(codec_ctx, &pkt);
if(ret < 0) {
std::cerr << "Error decoding packet." << std::endl;
return -1;
}
while(ret >= 0) {
ret = avcodec_receive_frame(codec_ctx, frame);
if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
} else if(ret < 0) {
std::cerr << "Error during decoding." << std::endl;
return -1;
}
// Scale the frame.
sws_scale(scaler_ctx, frame->data, frame->linesize, 0, in_codecpar->height, enc_frame->data, enc_frame->linesize);
// Encode the frame into a packet.
ret = avcodec_send_frame(codec_ctx, enc_frame);
if(ret < 0) {
std::cerr << "Error encoding frame." << std::endl;
return -1;
}
while(ret >= 0) {
ret = avcodec_receive_packet(codec_ctx, &pkt);
if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
} else if(ret < 0) {
std::cerr << "Error during encoding." << std::endl;
return -1;
}
// Write the packet to the output file.
if(av_write_frame(output_ctx, &pkt) < 0) {
std::cerr << "Error writing packet." << std::endl;
return -1;
}
// Free the packet.
av_packet_unref(&pkt);
}
av_frame_unref(frame);
}
av_packet_unref(&pkt);
}
// Flush the encoder.
int ret = avcodec_send_frame(codec_ctx, nullptr);
if(ret < 0) {
std::cerr << "Error flushing encoder." << std::endl;
return -1;
}
while(ret >= 0) {
ret = avcodec_receive_packet(codec_ctx, &pkt);
if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
} else if(ret < 0) {
std::cerr << "Error during encoding." << std::endl;
return -1;
}
// Write the packet to the output file.
if(av_write_frame(output_ctx, &pkt) < 0) {
std::cerr << "Error writing packet." << std::endl;
return -1;
}
// Free the packet.
av_packet_unref(&pkt);
}
// Write the file trailer.
if(av_write_trailer(output_ctx) < 0) {
std::cerr << "Could not write trailer." << std::endl;
return -1;
}
// Free the scaler context.
sws_freeContext(scaler_ctx);
// Free the frame.
av_frame_free(&frame);
// Free the encoded frame.
av_frame_free(&enc_frame);
// Free the buffer.
av_free(buffer);
// Close the codec.
avcodec_close(codec_ctx);
// Free the codec context.
avcodec_free_context(&codec_ctx);
// Close the output file.
avformat_close_input(&input_ctx);
// Free the output context.
avformat_free_context(output_ctx);
return 0;
}
```
这是一个基本的示例代码,它使用FFmpeg库和C++编写。在转换期间,它使用SWScale来缩放帧,并使用AVPacket来处理编码和解码。它还使用AVFormatContext来打开输入文件和创建输出文件。