version
#define FFMPEG_VERSION "6.1.1"
note
x11视频采集结构:AVInputFormat ff_xcbgrab_demuxer
code
void CFfmpegOps::CaptureVideo(const char *outFileName)
{
const AVInputFormat *iFmt = nullptr;
size_t n = 0;
AVFormatContext *iFmtCtx = nullptr;
AVDictionary *iFmtCtxOps = nullptr;
AVStream *video_stream = nullptr;
int video_stream_index = 0;
const AVPixFmtDescriptor *pix_fmt_desc = nullptr;
int bits_per_pixel = 0; // 像素数据
int padding_bits_per_pixel = 0; // 像素数据+附加数据
int pixel_fmt_is_planar = 0;
int width = 0;
int height = 0;
int img_buffer_size = 0;
int ret = -1;
int i = 0;
AVPacket* avpacket = nullptr;
int capture_cnt = 1000;
FILE *out_fp = nullptr;
if (!outFileName)
{
printf("return for !outFileName\n");
return;
}
iFmt = av_find_input_format("x11grab");
if (!iFmt)
{
printf("av_find_input_format error\n");
goto end;
}
#if 0
// 设置x11grab输入格式的可选参数
ret = av_dict_set(&iFmtCtxOps, "framerate", "60", 0);
if (ret < 0)
{
printf("av_dict_set framerate error:%s\n", GetFfmpegERR(ret));
goto end;
}
#endif
ret = avformat_open_input(&iFmtCtx, nullptr, iFmt, &iFmtCtxOps);
if (ret < 0)
{
printf("avformat_open_input error:%s\n", GetFfmpegERR(ret));
goto end;
}
if (iFmtCtx->nb_streams < 1)
{
printf("no stream\n");
goto end;
}
video_stream = iFmtCtx->streams[video_stream_index];
width = video_stream->codecpar->width;
height = video_stream->codecpar->height;
// bgr0:b g r 0
pix_fmt_desc = av_pix_fmt_desc_get((AVPixelFormat)(video_stream->codecpar->format));
bits_per_pixel = av_get_bits_per_pixel(pix_fmt_desc);
padding_bits_per_pixel = av_get_padded_bits_per_pixel(pix_fmt_desc);
pixel_fmt_is_planar = (AV_PIX_FMT_FLAG_PLANAR & pix_fmt_desc->flags) ? 1 : 0;
img_buffer_size = av_image_get_buffer_size((AVPixelFormat)(video_stream->codecpar->format), width, height, 1);
if (img_buffer_size == (bits_per_pixel / 8 * width * height))
{
printf("img_buffer_size with bits_per_pixel\n");
}
else if (img_buffer_size == (padding_bits_per_pixel / 8 * width * height))
{
printf("img_buffer_size with padding_bits_per_pixel\n");
}
avpacket = av_packet_alloc();
if (!avpacket)
{
printf("av_packet_alloc error\n");
goto end;
}
out_fp = fopen(outFileName, "wb");
if (!out_fp)
{
printf("fopen error\n");
goto end;
}
while (capture_cnt)
{
ret = av_read_frame(iFmtCtx, avpacket);
if (ret < 0)
{
printf("av_read_frame error\n");
continue;
}
if (avpacket->stream_index != video_stream_index)
{
av_packet_unref(avpacket);
continue;
}
if (avpacket->size == img_buffer_size)
{
for (i = 0; i < width * height; i++)
{
// write bgr of bgr0
n = fwrite(avpacket->data + i * 4, sizeof(uint8_t), 3, out_fp);
}
}
av_packet_unref(avpacket);
--capture_cnt;
}
end:
if (out_fp)
{
fclose(out_fp);
out_fp = nullptr;
}
if (avpacket)
{
av_packet_free(&avpacket);
avpacket = nullptr;
}
if (iFmtCtxOps)
{
av_dict_free(&iFmtCtxOps);
iFmtCtxOps = nullptr;
}
if (iFmtCtx)
{
avformat_close_input(&iFmtCtx);
}
}