用C++ 帮那个我实现基于SDL2和最新版本的FFmpeg 6.0的窗口画面录制功能
时间: 2024-04-18 13:25:32 浏览: 109
以下是一个基于SDL2和最新版本的FFmpeg 6.0的窗口画面录制功能的示例代码:
```cpp
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}
#include <SDL2/SDL.h>
int main() {
// 初始化SDL2
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
printf("Failed to initialize SDL2: %s\n", SDL_GetError());
return -1;
}
// 创建窗口和渲染器
SDL_Window* window = SDL_CreateWindow("Screen Recorder",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640, 480,
SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
// 创建AVFormatContext结构体并设置输出文件名和输出格式
AVFormatContext* formatContext = nullptr;
avformat_alloc_output_context2(&formatContext, nullptr, nullptr, "output.mp4");
// 查找视频编码器
AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!codec) {
printf("Failed to find video encoder\n");
return -1;
}
// 创建视频流并设置编码器参数
AVStream* videoStream = avformat_new_stream(formatContext, codec);
if (!videoStream) {
printf("Failed to create video stream\n");
return -1;
}
AVCodecContext* codecContext = avcodec_alloc_context3(codec);
codecContext->width = 640;
codecContext->height = 480;
codecContext->pix_fmt = AV_PIX_FMT_YUV420P;
codecContext->time_base = AVRational{1, 30}; // 设置时间基准为 1/30 秒
// 打开编码器并初始化编码器上下文
avcodec_open2(codecContext, codec, nullptr);
avcodec_parameters_from_context(videoStream->codecpar, codecContext);
// 打开输出文件
if (avio_open(&formatContext->pb, "output.mp4", AVIO_FLAG_WRITE) < 0) {
printf("Failed to open output file\n");
return -1;
}
// 写入文件头
avformat_write_header(formatContext, nullptr);
// 分配视频帧内存
AVFrame* videoFrame = av_frame_alloc();
videoFrame->format = codecContext->pix_fmt;
videoFrame->width = codecContext->width;
videoFrame->height = codecContext->height;
av_frame_get_buffer(videoFrame, 0);
// 分配像素数据内存
int bufferSize = av_image_get_buffer_size(codecContext->pix_fmt, codecContext->width, codecContext->height, 1);
uint8_t* buffer = (uint8_t*)av_malloc(bufferSize);
av_image_fill_arrays(videoFrame->data, videoFrame->linesize, buffer, codecContext->pix_fmt, codecContext->width, codecContext->height, 1);
// 创建转换上下文
SwsContext* swsContext = sws_getContext(codecContext->width, codecContext->height,
AV_PIX_FMT_RGB24,
codecContext->width, codecContext->height,
codecContext->pix_fmt,
SWS_BICUBIC, nullptr, nullptr, nullptr);
// 录制窗口画面
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
break;
}
// 读取窗口像素数据
SDL_RenderClear(renderer);
// 在这里绘制你的窗口内容
SDL_RenderPresent(renderer);
SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_TARGET, 640, 480);
SDL_SetRenderTarget(renderer, texture);
SDL_RenderCopy(renderer, texture, nullptr, nullptr);
uint8_t* pixels = nullptr;
int pitch = 0;
SDL_LockTexture(texture, nullptr, (void**)&pixels, &pitch);
// 将像素数据转换为编码器所需格式
sws_scale(swsContext, (const uint8_t* const*)&pixels, &pitch, 0, codecContext->height, videoFrame->data, videoFrame->linesize);
// 编码并写入输出文件
AVPacket packet;
av_init_packet(&packet);
packet.data = nullptr;
packet.size = 0;
avcodec_send_frame(codecContext, videoFrame);
while (avcodec_receive_packet(codecContext, &packet) == 0) {
av_interleaved_write_frame(formatContext, &packet);
av_packet_unref(&packet);
}
SDL_UnlockTexture(texture);
SDL_DestroyTexture(texture);
}
// 写入文件尾
av_write_trailer(formatContext);
// 释放资源
av_frame_free(&videoFrame);
avcodec_close(codecContext);
avcodec_free_context(&codecContext);
avio_close(formatContext->pb);
avformat_free_context(formatContext);
// 销毁SDL2
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
```
上述示例代码基于SDL2和最新版本的FFmpeg 6.0,实现了窗口画面的录制功能。你可以根据需要修改窗口的宽度和高度,以及输出文件的名称。
请确保已正确安装和配置SDL2和FFmpeg库,并将其链接到你的项目中。在编译和运行代码之前,请根据你的操作系统和编译环境进行必要的调整。
希望这个示例对你有所帮助!如果有任何疑问,请随时提问。祝你成功实现窗口画面录制功能!
阅读全文