C++ 视频压缩算法及FFmpeg库实现示例
"C++ 视频压缩算法及FFmpeg库实现示例"\n\n本文介绍了C++中常用的视频压缩算法,包括H.264/AVC、HEVC/H.265、MPEG-2和VP9。\n\n1. H.264/AVC:一种最常用的视频压缩算法,也是现代视频编码中最为流行的标准之一。\n\n2. HEVC/H.265:是H.264的升级版,采用更高效的编码算法,能够在相同视频质量下实现更高的压缩比。\n\n3. MPEG-2:一种广泛应用于DVD和数字电视广播的压缩算法。\n\n4. VP9:由Google开发的开源视频压缩算法,常用于WebM格式的视频。\n\n\n并提供使用FFmpeg库实现视频压缩的示例代码。\n\nc++\n#include <iostream>\n#include <string>\n\nextern \"C\" {\n#include <libavcodec/avcodec.h>\n#include <libavformat/avformat.h>\n#include <libavutil/imgutils.h>\n}\n\nint compressVideo(const std::string& inputPath, const std::string& outputPath) {\n av_register_all();\n\n AVFormatContext* inputFormatContext = nullptr;\n int ret = avformat_open_input(&inputFormatContext, inputPath.c_str(), nullptr, nullptr);\n if (ret < 0) {\n std::cerr << \"Failed to open input file\" << std::endl;\n return ret;\n }\n\n ret = avformat_find_stream_info(inputFormatContext, nullptr);\n if (ret < 0) {\n std::cerr << \"Failed to find stream information\" << std::endl;\n avformat_close_input(&inputFormatContext);\n return ret;\n }\n\n int videoStreamIndex = -1;\n AVCodecParameters* videoCodecParameters = nullptr;\n for (unsigned int i = 0; i < inputFormatContext->nb_streams; ++i) {\n if (inputFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {\n videoStreamIndex = i;\n videoCodecParameters = inputFormatContext->streams[i]->codecpar;\n break;\n }\n }\n\n if (videoStreamIndex == -1) {\n std::cerr << \"Failed to find video stream\" << std::endl;\n avformat_close_input(&inputFormatContext);\n return -1;\n }\n\n AVCodec* codec = avcodec_find_decoder(videoCodecParameters->codec_id);\n if (!codec) {\n std::cerr << \"Failed to find decoder\" << std::endl;\n avformat_close_input(&inputFormatContext);\n return -1;\n }\n\n AVCodecContext* codecContext = avcodec_alloc_context3(codec);\n if (!codecContext) {\n std::cerr << \"Failed to allocate codec context\" << std::endl;\n avformat_close_input(&inputFormatContext);\n return -1;\n }\n\n ret = avcodec_parameters_to_context(codecContext, videoCodecParameters);\n if (ret < 0) {\n std::cerr << \"Failed to copy codec parameters to codec context\" << std::endl;\n avcodec_close(codecContext);\n avformat_close_input(&inputFormatContext);\n return ret;\n }\n\n ret = avcodec_open2(codecContext, codec, nullptr);\n if (ret < 0) {\n std::cerr << \"Failed to open codec\" << std::endl;\n avcodec_close(codecContext);\n avformat_close_input(&inputFormatContext);\n return ret;\n }\n\n AVFormatContext* outputFormatContext = nullptr;\n ret = avformat_alloc_output_context2(&outputFormatContext, nullptr, nullptr, outputPath.c_str());\n if (ret < 0) {\n std::cerr << \"Failed to allocate output format context\" << std::endl;\n avcodec_close(codecContext);\n avformat_close_input(&inputFormatContext);\n return ret;\n }\n\n AVStream* outputStream = avformat_new_stream(outputFormatContext, codec);\n if (!outputStream) {\n std::cerr << \"Failed to create output stream\" << std::endl;\n avcodec_close(codecContext);\n avformat_close_input(&inputFormatContext);\n avformat_free_context(outputFormatContext);\n return -1;\n }\n\n ret = avcodec_parameters_from_context(outputStream->codecpar, codecContext);\n if (ret < 0) {\n std::cerr << \"Failed to copy codec context to codec parameters\" << std::endl;\n avcodec_close(codecContext);\n avformat_close_input(&inputFormatContext);\n avformat_free_context(outputFormatContext);\n return ret;\n }\n\n ret = avio_open(&outputFormatContext->pb, outputPath.c_str(), AVIO_FLAG_WRITE);\n if (ret < 0) {\n std::cerr << \"Failed to open output file\" << std::endl;\n avcodec_close(codecContext);\n avformat_close_input(&inputFormatContext);\n avformat_free_context(outputFormatContext);\n return ret;\n }\n\n ret = avformat_write_header(outputFormatContext, nullptr);\n if (ret < 0) {\n std::cerr << \"Failed to write output file header\" << std::endl;\n avcodec_close(codecContext);\n avformat_close_input(&inputFormatContext);\n avformat_free_context(outputFormatContext);\n return ret;\n }\n\n AVPacket* packet = av_packet_alloc();\n while (av_read_frame(inputFormatContext, packet) >= 0) {\n if (packet->stream_index == videoStreamIndex) {\n ret = avcodec_send_packet(codecContext, packet);\n if (ret < 0) {\n std::cerr << \"Failed to send packet to decoder\" << std::endl;\n av_packet_unref(packet);\n break;\n }\n\n while (ret >= 0) {\n AVFrame* frame = av_frame_alloc();\n ret = avcodec_receive_frame(codecContext, frame);\n if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {\n av_frame_free(&frame);\n break;\n } else if (ret < 0) {\n std::cerr << \"Failed to receive frame from decoder\" << std::endl;\n av_frame_free(&frame);\n av_packet_unref(packet);\n avcodec_close(codecContext);\n avformat_close_input(&inputFormatContext);\n avformat_free_context(outputFormatContext);\n return ret;\n }\n\n ret = avcodec_send_frame(codecContext, frame);\n if (ret < 0) {\n std::cerr << \"Failed to send frame to encoder\" << std::endl;\n av_frame_free(&frame);\n av_packet_unref(packet);\n avcodec_close(codecContext);\n avformat_close_input(&inputFormatContext);\n avformat_free_context(outputFormatContext);\n return ret;\n }\n\n AVPacket* outputPacket = av_packet_alloc();\n ret = avcodec_receive_packet(codecContext, outputPacket);\n if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {\n av_packet_unref(outputPacket);\n av_frame_free(&frame);\n continue;\n } else if (ret < 0) {\n std::cerr << \"Failed to receive packet from encoder\" << std::endl;\n av_packet_unref(outputPacket);\n av_frame_free(&frame);\n av_packet_unref(packet);\n avcodec_close(codecContext);\n avformat_close_input(&inputFormatContext);\n avformat_free_context(outputFormatContext);\n return ret;\n }\n\n outputPacket->pts = av_rescale_q(outputPacket->pts, codecContext->time_base, outputStream->time_base);\n outputPacket->dts = av_rescale_q(outputPacket->dts, codecContext->time_base, outputStream->time_base);\n outputPacket->duration = av_rescale_q(outputPacket->duration, codecContext->time_base, outputStream->time_base);\n outputPacket->stream_index = outputStream->index;\n\n ret = av_write_frame(outputFormatContext, outputPacket);\n if (ret < 0) {\n std::cerr << \"Failed to write packet to output file\" << std::endl;\n av_packet_unref(outputPacket);\n av_frame_free(&frame);\n av_packet_unref(packet);\n avcodec_close(codecContext);\n avformat_close_input(&inputFormatContext);\n avformat_free_context(outputFormatContext);\n return ret;\n }\n\n av_packet_unref(outputPacket);\n av_frame_free(&frame);\n }\n }\n\n av_packet_unref(packet);\n }\n\n av_write_trailer(outputFormatContext);\n\n av_packet_free(&packet);\n avcodec_close(codecContext);\n avcodec_free_context(&codecContext);\n avformat_close_input(&inputFormatContext);\n avformat_free_context(outputFormatContext);\n\n return 0;\n}\n\nint main() {\n std::string inputPath = \"input.mp4\";\n std::string outputPath = \"output.mp4\";\n\n int ret = compressVideo(inputPath, outputPath);\n if (ret < 0) {\n std::cerr << \"Failed to compress video\" << std::endl;\n return ret;\n }\n\n std::cout << \"Video compression completed successfully\" << std::endl;\n\n return 0;\n}\n\n\n以上代码使用FFmpeg库实现了将输入视频文件压缩为输出视频文件的功能。需要注意的是,运行该代码需要先安装FFmpeg库,并将其链接到项目中。\n
原文地址: https://www.cveoy.top/t/topic/p66L 著作权归作者所有。请勿转载和采集!