我使用SDL2制作了一个小动画,我想使用ffmpeg将其转换为h264编码的视频。我使用
SDL_RenderReadPixels
获取纹理 RGBA 像素并将它们发送到 ffmpeg 进行渲染。视频确实渲染了,但一切都乱七八糟。以下是我的代码
生成 ffmpeg
int child_pipe[2];
if (pipe(child_pipe) < 0) {
perror("child_pipe");
}
printf("child_pipe[0]: %d, child_pipe[1]: %d\n", child_pipe[0], child_pipe[1]);
args.ffmpeg = &(FFMpeg){.std_in = child_pipe[WRITE_END]};
child_pid = fork();
printf("child: %d\n", child_pid);
if (child_pid == 0) {
close(child_pipe[WRITE_END]);
if (dup2(child_pipe[READ_END], STDIN_FILENO) < 0) {
perror("dup2");
return -1;
}
char *argv[] = {"ffmpeg", "-loglevel", "verbose", "-y", "-f", "rawvideo", "-pixel_format", "rgba", "-s",
"894x702", "-i", "-", "-c:v", "libx264", "-pix_fmt", "yuv420p", "thing.mp4", NULL};
int x = execvp("ffmpeg", argv);
if (x != 0) {
perror("execv");
return x;
}
return -1;
}
以下是我如何渲染到 SDL2 渲染器中。 SDL2 上的渲染没有问题。在这里我获取渲染像素并将它们发送到 ffmpeg。
void render_image(SDL_Renderer *renderer, int array[], size_t array_size, Image *image, FFMpeg *ffmpeg) {
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
for (int i = 0; i < array_size; i++) {
paint_image_strip(renderer, image, i, array[i]);
}
if (ANIMATION_DELAY_MS > 0) {
SDL_Delay(ANIMATION_DELAY_MS);
}
if (ffmpeg != NULL) {
int size = image->width * image->height * sizeof(Uint32);
Uint32 *pixels = (Uint32 *)malloc(size);
if (pixels == NULL) {
printf("Malloc failed. Buy more ram\n");
return;
}
int ret = SDL_RenderReadPixels(renderer, NULL, SDL_PIXELFORMAT_RGBA8888, pixels, image->width * sizeof(Uint32));
if (ret != 0) {
fprintf(stderr, "SDL_RenderReadPixels failed: %s\n", SDL_GetError());
free(pixels);
}
int n = write(ffmpeg->std_in, image->img_data, size);
if (n < 0) {
perror("write failed");
}
free(pixels);
}
SDL_RenderPresent(renderer);
}
问题来了。这是我在 SDL2 窗口中看到的内容
这里有原始图像的痕迹。我以为这是 RGBA 与 ARGB 的问题,但仔细检查后发现事实并非如此。
期待正确的 ffmpeg 渲染。
这是一个极其愚蠢的问题。在这条线上
int n = write(ffmpeg->std_in, image->img_data, size);
我正在写入图像数据,而不是从 SDL2 获取的数据