使用FFL的精灵截图BMP以编程方式使用FFmpeg创建视频

时间:2016-10-27 08:15:43

标签: c++ c bitmap ffmpeg sdl

我在SDL2库中使用C ++开发了一个动画/精灵(基于this answer)。位图保存到某个路径。它们的尺寸为640x480,格式由SDL常量distutils给出。

我在FFmpeg libs上面有一个用C语言编写的第二个程序,它从上面的路径中读取一个图像(暂时只有一个,当它只适用于一个时会读取整个系列)。 这样做会有以下几点(简要介绍 - 跳过验证和简明评论)

SDL_PIXELFORMAT_ARGB8888

由于上面的代码(编译没有问题),我可以得到一个播放1秒钟的视频 - 这部分按预期工作。问题是看到的图像是绿色全屏,如下所示。enter how video looks

使用AVCodec *codec; AVCodecContext *c = NULL; int i, ret, x, y, got_output; FILE *f; AVFrame *frame; AVPacket pkt; uint8_t endcode[] = { 0, 0, 1, 0xb7 }; codec = avcodec_find_encoder(codec_id); c = avcodec_alloc_context3(codec); c->bit_rate = 400000; /* resolution must be a multiple of two */ c->width = 640; c->height = 480; c->time_base = (AVRational ) { 1, 25 }; c->gop_size = 5; c->max_b_frames = 1; c->pix_fmt = AV_PIX_FMT_YUV420P; av_opt_set(c->priv_data, "preset", "slow", 0); avcodec_open2(c, codec, NULL); fopen(filename, "wb"); frame = av_frame_alloc(); av_image_alloc(frame->data, frame->linesize, c->width, c->height, c->pix_fmt, 32); for (i = 0; i < 25; ++i) { readSingleFile("/tmp/alok1/ss099.bmp", &frame->data);//Read the saved BMP into frame->data frame->pts = i; frame->width = 640; frame->height = 480; frame->format = -1; av_init_packet(&pkt); pkt.data = NULL; // packet data will be allocated by the encoder pkt.size = 0; ret = avcodec_encode_video2(c, &pkt, frame, &got_output); if (got_output) { printf("Write frame %3d (size=%5d)\n", i, pkt.size); fwrite(pkt.data, 1, pkt.size, f); } av_packet_unref(&pkt); } for (got_output = 1; got_output; i++) { fflush(stdout); ret = avcodec_encode_video2(c, &pkt, NULL, &got_output); if (ret < 0) { fprintf(stderr, "Error encoding frame\n"); exit(1); } if (got_output) { printf("[DELAYED]Write frame %3d (size=%5d)\n", i, pkt.size); fwrite(pkt.data, 1, pkt.size, f); av_packet_unref(&pkt); } } fwrite(endcode, 1, sizeof(endcode), f); //cleanup 函数读取的图像由图像查看器(linux,gwenview和okular)呈现,如下所示:original bitmap image

关于可能出现什么问题的任何指示?

1 个答案:

答案 0 :(得分:2)

总结评论:

  • 编码器需要打开时指定格式的原始图像数据;它不会尝试转换任何东西
  • 色彩空间/格式转换必须手动完成;使用swscale
  • 如果您使用Windows API加载图片:它使用BGR,而不是RGB
  • BMP文件通常但不总是存储图像自下而上,而不是FFmpeg使用的自上而下;如果是自下而上,则必须翻转(如果与颜色空间转换结合使用,可能有一种方法可以做到这一点而不会产生太多或任何性能损失)。
  • 还要注意线条。图像中的每一行可以占用比其宽度更多的字节。这既适用于ffmpeg分配的图像,也适用于从BMP加载的图像 - 必须注意始终为每个API调用提供有效的线条。


除上述内容外,以下是最终解决方案的“必读”:
1. Taking a screenshot with SDL
2. RGB to YUV conversion
3. FFmpeg-related source code was written with this as base