使用 H.264/AVC 压缩格式对视频流进行压缩,请详细写一下流程以及具体代码实现
时间: 2024-04-15 17:26:57 浏览: 156
新一代视频压缩编码标准—H.264/AVC
5星 · 资源好评率100%
使用H.264/AVC压缩格式对视频流进行压缩,你可以使用FFmpeg库来实现。下面是一个基本的示例,展示了如何使用FFmpeg库对视频流进行压缩:
1. 安装FFmpeg库:首先,确保你已经安装了FFmpeg库。你可以从官方网站下载并按照说明进行安装。
2. 编写C++代码:创建一个C++源文件,并使用以下代码来实现视频流的压缩:
```cpp
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <fstream>
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
}
int main() {
AVFormatContext* inputContext = nullptr;
AVFormatContext* outputContext = nullptr;
AVCodecContext* codecContext = nullptr;
AVStream* stream = nullptr;
AVPacket packet;
const char* inputFilename = "your_input_video_file"; // 输入视频文件名
const char* outputFilename = "your_output_compressed_video_file.h264"; // 输出压缩后的视频文件名
av_register_all();
// 打开输入视频文件
if (avformat_open_input(&inputContext, inputFilename, nullptr, nullptr) != 0) {
std::cerr << "Failed to open input video file!" << std::endl;
return -1;
}
// 获取输入视频流信息
if (avformat_find_stream_info(inputContext, nullptr) < 0) {
std::cerr << "Failed to retrieve input video stream information!" << std::endl;
return -1;
}
// 查找视频流
int videoStreamIndex = -1;
for (unsigned int i = 0; i < inputContext->nb_streams; i++) {
if (inputContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStreamIndex = i;
break;
}
}
if (videoStreamIndex == -1) {
std::cerr << "Failed to find video stream in input video file!" << std::endl;
return -1;
}
// 获取视频流编解码器参数
AVCodecParameters* codecParameters = inputContext->streams[videoStreamIndex]->codecpar;
// 查找视频流编解码器
AVCodec* codec = avcodec_find_decoder(codecParameters->codec_id);
if (codec == nullptr) {
std::cerr << "Failed to find video decoder codec!" << std::endl;
return -1;
}
// 创建编解码器上下文
codecContext = avcodec_alloc_context3(codec);
if (codecContext == nullptr) {
std::cerr << "Failed to allocate video decoder context!" << std::endl;
return -1;
}
// 设置编解码器上下文参数
if (avcodec_parameters_to_context(codecContext, codecParameters) < 0) {
std::cerr << "Failed to copy video decoder parameters to context!" << std::endl;
return -1;
}
// 打开视频编解码器
if (avcodec_open2(codecContext, codec, nullptr) < 0) {
std::cerr << "Failed to open video decoder!" << std::endl;
return -1;
}
// 创建输出视频文件
if (avformat_alloc_output_context2(&outputContext, nullptr, nullptr, outputFilename) < 0) {
std::cerr << "Failed to allocate output video file context!" << std::endl;
return -1;
}
// 添加视频流到输出视频文件
stream = avformat_new_stream(outputContext, codec);
if (stream == nullptr) {
std::cerr << "Failed to create output video stream!" << std::endl;
return -1;
}
// 复制视频流参数
if (avcodec_parameters_copy(stream->codecpar, codecParameters) < 0) {
std::cerr << "Failed to copy video stream parameters!" << std::endl;
return -1;
}
// 打开输出视频文件
if (!(outputContext->oformat->flags & AVFMT_NOFILE)) {
if (avio_open(&outputContext->pb, outputFilename, AVIO_FLAG_WRITE) < 0) {
std::cerr << "Failed to open output video file!" << std::endl;
return -1;
}
}
// 写视频文件头部信息
if (avformat_write_header(outputContext, nullptr) < 0) {
std::cerr << "Failed to write output video file header!" << std::endl;
return -1;
}
// 初始化视频帧
AVFrame* frame = av_frame_alloc();
if (frame == nullptr) {
std::cerr << "Failed to allocate video frame!" << std::endl;
return -1;
}
int frameNumber = 0;
// 逐帧读取输入视频文件并进行压缩
while (av_read_frame(inputContext, &packet) >= 0) {
if (packet.stream_index == videoStreamIndex) {
// 发送解码器数据包
if (avcodec_send_packet(codecContext, &packet) < 0) {
std::cerr << "Failed to send packet to video decoder!" << std::endl;
return -1;
}
// 接收解码器输出帧
int ret = avcodec_receive_frame(codecContext, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
av_packet_unref(&packet);
continue;
} else if (ret < 0) {
std::cerr << "Failed to receive frame from video decoder!" << std::endl;
return -1;
}
// 压缩帧数据
AVPacket compressedPacket;
av_init_packet(&compressedPacket);
compressedPacket.data = nullptr;
compressedPacket.size = 0;
if (avcodec_encode_video2(codecContext, &compressedPacket, frame, nullptr) < 0) {
std::cerr << "Failed to encode video frame!" << std::endl;
return -1;
}
// 写入压缩后的帧数据到输出视频文件
if (av_write_frame(outputContext, &compressedPacket) < 0) {
std::cerr << "Failed to write compressed video frame!" << std::endl;
return -1;
}
av_packet_unref(&compressedPacket);
frameNumber++;
}
av_packet_unref(&packet);
}
// 写视频文件尾部信息
av_write_trailer(outputContext);
// 清理资源
avcodec_free_context(&codecContext);
avformat_close_input(&inputContext);
avformat_free_context(outputContext);
av_frame_free(&frame);
return 0;
}
```
请将"your_input_video_file"替换为你想要压缩的输入视频文件的路径,将"your_output_compressed_video_file.h264"替换为你想要保存的压缩后的视频文件路径。
3. 编译和运行:使用C++编译器(如g++)编译源文件,并链接FFmpeg库。
```bash
g++ your_source_file.cpp -o compress_video `pkg-config --cflags --libs libavformat libavcodec libswscale`
```
然后运行可执行文件:
```bash
./compress_video
```
这样,程序将读取输入视频文件并使用H.264/AVC压缩格式对视频流进行压缩,并将压缩后的视频保存到输出文件中。
请注意,上述代码仅提供了基本的功能实现,你可能需要根据具体需求进行更复杂的视频处理或参数设置。此外,确保你有适当的权限来读取输入视频文件并保存输出视频文件。
阅读全文