C++使用ffmpeg编写将原始视频进行编码、解码得到重建视频的代码
时间: 2024-06-08 08:11:58 浏览: 156
Visual C++音视频编解码技术及实践,音视频编解码基础知识,C/C++
以下是一个简单的示例代码,使用ffmpeg库对原始视频进行编码和解码:
```c++
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
}
int main(int argc, char* argv[]) {
const char* input_filename = "input_video.raw";
const char* output_filename = "output_video.mp4";
// Open input file
FILE* input_file = fopen(input_filename, "rb");
if (!input_file) {
fprintf(stderr, "Failed to open input file.\n");
return -1;
}
// Initialize AVFormatContext
AVFormatContext* input_format_context = avformat_alloc_context();
if (!input_format_context) {
fprintf(stderr, "Failed to allocate input AVFormatContext.\n");
fclose(input_file);
return -1;
}
// Set input format
AVInputFormat* input_format = av_find_input_format("rawvideo");
if (!input_format) {
fprintf(stderr, "Failed to find input format.\n");
avformat_free_context(input_format_context);
fclose(input_file);
return -1;
}
// Set input AVIOContext
uint8_t* input_buffer = (uint8_t*)av_malloc(4096);
if (!input_buffer) {
fprintf(stderr, "Failed to allocate input AVIOContext buffer.\n");
avformat_free_context(input_format_context);
fclose(input_file);
return -1;
}
AVIOContext* input_avio_context = avio_alloc_context(input_buffer, 4096, 0, input_file, NULL, NULL, NULL);
if (!input_avio_context) {
fprintf(stderr, "Failed to allocate input AVIOContext.\n");
avformat_free_context(input_format_context);
fclose(input_file);
return -1;
}
input_format_context->pb = input_avio_context;
// Open input format
if (avformat_open_input(&input_format_context, "", input_format, NULL) != 0) {
fprintf(stderr, "Failed to open input format.\n");
avformat_free_context(input_format_context);
fclose(input_file);
return -1;
}
// Find input codec
AVCodec* input_codec = avcodec_find_decoder(AV_CODEC_ID_RAWVIDEO);
if (!input_codec) {
fprintf(stderr, "Failed to find input codec.\n");
avformat_close_input(&input_format_context);
fclose(input_file);
return -1;
}
// Initialize input codec context
AVCodecContext* input_codec_context = avcodec_alloc_context3(input_codec);
if (!input_codec_context) {
fprintf(stderr, "Failed to allocate input codec context.\n");
avformat_close_input(&input_format_context);
fclose(input_file);
return -1;
}
if (avcodec_parameters_to_context(input_codec_context, input_format_context->streams[0]->codecpar) < 0) {
fprintf(stderr, "Failed to copy input codec parameters to context.\n");
avcodec_free_context(&input_codec_context);
avformat_close_input(&input_format_context);
fclose(input_file);
return -1;
}
if (avcodec_open2(input_codec_context, input_codec, NULL) != 0) {
fprintf(stderr, "Failed to open input codec.\n");
avcodec_free_context(&input_codec_context);
avformat_close_input(&input_format_context);
fclose(input_file);
return -1;
}
// Open output file
AVFormatContext* output_format_context = NULL;
if (avformat_alloc_output_context2(&output_format_context, NULL, "mp4", NULL) < 0) {
fprintf(stderr, "Failed to allocate output AVFormatContext.\n");
avcodec_free_context(&input_codec_context);
avformat_close_input(&input_format_context);
fclose(input_file);
return -1;
}
// Find output codec
AVCodec* output_codec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!output_codec) {
fprintf(stderr, "Failed to find output codec.\n");
avcodec_free_context(&input_codec_context);
avformat_close_input(&input_format_context);
avformat_free_context(output_format_context);
fclose(input_file);
return -1;
}
// Add output stream
AVStream* output_stream = avformat_new_stream(output_format_context, output_codec);
if (!output_stream) {
fprintf(stderr, "Failed to allocate output stream.\n");
avcodec_free_context(&input_codec_context);
avformat_close_input(&input_format_context);
avformat_free_context(output_format_context);
fclose(input_file);
return -1;
}
output_stream->id = output_format_context->nb_streams - 1;
// Initialize output codec context
AVCodecContext* output_codec_context = avcodec_alloc_context3(output_codec);
if (!output_codec_context) {
fprintf(stderr, "Failed to allocate output codec context.\n");
avcodec_free_context(&input_codec_context);
avformat_close_input(&input_format_context);
avformat_free_context(output_format_context);
fclose(input_file);
return -1;
}
output_codec_context->width = input_codec_context->width;
output_codec_context->height = input_codec_context->height;
output_codec_context->pix_fmt = AV_PIX_FMT_YUV420P;
output_codec_context->time_base = (AVRational){1, 25};
output_codec_context->framerate = (AVRational){25, 1};
output_codec_context->bit_rate = 4000000;
if (avcodec_open2(output_codec_context, output_codec, NULL) != 0) {
fprintf(stderr, "Failed to open output codec.\n");
avcodec_free_context(&input_codec_context);
avformat_close_input(&input_format_context);
avformat_free_context(output_format_context);
fclose(input_file);
return -1;
}
// Write output header
if (avformat_write_header(output_format_context, NULL) != 0) {
fprintf(stderr, "Failed to write output header.\n");
avcodec_free_context(&output_codec_context);
avcodec_free_context(&input_codec_context);
avformat_close_input(&input_format_context);
avformat_free_context(output_format_context);
fclose(input_file);
return -1;
}
// Read input packet
AVPacket input_packet;
av_init_packet(&input_packet);
input_packet.data = NULL;
input_packet.size = 0;
while (av_read_frame(input_format_context, &input_packet) == 0) {
// Decode input packet
AVFrame* input_frame = av_frame_alloc();
if (!input_frame) {
fprintf(stderr, "Failed to allocate input frame.\n");
av_packet_unref(&input_packet);
avcodec_free_context(&output_codec_context);
avcodec_free_context(&input_codec_context);
avformat_close_input(&input_format_context);
avformat_free_context(output_format_context);
fclose(input_file);
return -1;
}
int input_frame_finished = 0;
if (avcodec_send_packet(input_codec_context, &input_packet) != 0) {
fprintf(stderr, "Failed to send input packet.\n");
av_frame_free(&input_frame);
av_packet_unref(&input_packet);
avcodec_free_context(&output_codec_context);
avcodec_free_context(&input_codec_context);
avformat_close_input(&input_format_context);
avformat_free_context(output_format_context);
fclose(input_file);
return -1;
}
while (avcodec_receive_frame(input_codec_context, input_frame) == 0) {
// Encode input frame
AVPacket output_packet;
av_init_packet(&output_packet);
output_packet.data = NULL;
output_packet.size = 0;
int output_packet_finished = 0;
if (avcodec_send_frame(output_codec_context, input_frame) != 0) {
fprintf(stderr, "Failed to send output frame.\n");
av_packet_unref(&output_packet);
av_frame_free(&input_frame);
av_packet_unref(&input_packet);
avcodec_free_context(&output_codec_context);
avcodec_free_context(&input_codec_context);
avformat_close_input(&input_format_context);
avformat_free_context(output_format_context);
fclose(input_file);
return -1;
}
while (avcodec_receive_packet(output_codec_context, &output_packet) == 0) {
// Write output packet
output_packet.stream_index = output_stream->index;
if (av_write_frame(output_format_context, &output_packet) != 0) {
fprintf(stderr, "Failed to write output packet.\n");
av_packet_unref(&output_packet);
av_frame_free(&input_frame);
av_packet_unref(&input_packet);
avcodec_free_context(&output_codec_context);
avcodec_free_context(&input_codec_context);
avformat_close_input(&input_format_context);
avformat_free_context(output_format_context);
fclose(input_file);
return -1;
}
av_packet_unref(&output_packet);
output_packet_finished = 1;
}
if (!output_packet_finished) {
av_packet_unref(&output_packet);
}
av_frame_unref(input_frame);
input_frame_finished = 1;
}
if (!input_frame_finished) {
av_frame_free(&input_frame);
}
av_packet_unref(&input_packet);
}
// Write output trailer
if (av_write_trailer(output_format_context) != 0) {
fprintf(stderr, "Failed to write output trailer.\n");
avcodec_free_context(&output_codec_context);
avcodec_free_context(&input_codec_context);
avformat_close_input(&input_format_context);
avformat_free_context(output_format_context);
fclose(input_file);
return -1;
}
// Clean up
avcodec_free_context(&output_codec_context);
avcodec_free_context(&input_codec_context);
avformat_close_input(&input_format_context);
avformat_free_context(output_format_context);
fclose(input_file);
return 0;
}
```
这个示例代码读取名为input_video.raw的原始视频文件,并将其编码为H.264格式的MP4文件,输出为output_video.mp4。你可以根据需要修改输入和输出文件的名称和格式,以及编解码器的参数。
阅读全文