如何将 AVFrame 写成 JPEG 图像
How to write AVFrame out as JPEG image
我正在编写一个程序来从视频流中提取图像。到目前为止,我已经弄清楚如何寻找正确的帧、解码视频流并将相关数据收集到 AVFrame 结构中。我现在正尝试将数据写成 JPEG 图像,但我的代码无法正常工作。我得到的代码来自这里:https://gist.github.com/RLovelett/67856c5bfdf5739944ed
int save_frame_as_jpeg(AVCodecContext *pCodecCtx, AVFrame *pFrame, int FrameNo) {
AVCodec *jpegCodec = avcodec_find_encoder(AV_CODEC_ID_JPEG2000);
if (!jpegCodec) {
return -1;
}
AVCodecContext *jpegContext = avcodec_alloc_context3(jpegCodec);
if (!jpegContext) {
return -1;
}
jpegContext->pix_fmt = pCodecCtx->pix_fmt;
jpegContext->height = pFrame->height;
jpegContext->width = pFrame->width;
if (avcodec_open2(jpegContext, jpegCodec, NULL) < 0) {
return -1;
}
FILE *JPEGFile;
char JPEGFName[256];
AVPacket packet = {.data = NULL, .size = 0};
av_init_packet(&packet);
int gotFrame;
if (avcodec_encode_video2(jpegContext, &packet, pFrame, &gotFrame) < 0) {
return -1;
}
sprintf(JPEGFName, "dvr-%06d.jpg", FrameNo);
JPEGFile = fopen(JPEGFName, "wb");
fwrite(packet.data, 1, packet.size, JPEGFile);
fclose(JPEGFile);
av_free_packet(&packet);
avcodec_close(jpegContext);
return 0;
}
如果我使用该代码,我遇到的第一个错误是 AVCodecContext
上的 time_base
未设置。我将其设置为我的视频解码 AVCodecContext
结构的时基。现在我收到另一个错误
[jpeg2000 @ 0x7fd6a4015200] dimensions not set
[jpeg2000 @ 0x7fd6a307c400] dimensions not set
[jpeg2000 @ 0x7fd6a5800000] dimensions not set
[jpeg2000 @ 0x7fd6a307ca00] dimensions not set
[jpeg2000 @ 0x7fd6a3092400] dimensions not set
图像仍然没有被写入。根据 Github 要点,一位评论者声称元数据未写入 JPEG 图像,但我应该如何写入此元数据?我确实设置了编码上下文的宽度和高度,所以我不确定为什么它声称没有设置尺寸。
JPEG2000 不是 jpeg。要对 JPEG 图像进行编码,请使用 AV_CODEC_ID_MJPEG。 MJPEG 代表 "motion JPEG",这是构成视频流的 JPEG 图片序列的通常称呼方式。
我正在编写一个程序来从视频流中提取图像。到目前为止,我已经弄清楚如何寻找正确的帧、解码视频流并将相关数据收集到 AVFrame 结构中。我现在正尝试将数据写成 JPEG 图像,但我的代码无法正常工作。我得到的代码来自这里:https://gist.github.com/RLovelett/67856c5bfdf5739944ed
int save_frame_as_jpeg(AVCodecContext *pCodecCtx, AVFrame *pFrame, int FrameNo) {
AVCodec *jpegCodec = avcodec_find_encoder(AV_CODEC_ID_JPEG2000);
if (!jpegCodec) {
return -1;
}
AVCodecContext *jpegContext = avcodec_alloc_context3(jpegCodec);
if (!jpegContext) {
return -1;
}
jpegContext->pix_fmt = pCodecCtx->pix_fmt;
jpegContext->height = pFrame->height;
jpegContext->width = pFrame->width;
if (avcodec_open2(jpegContext, jpegCodec, NULL) < 0) {
return -1;
}
FILE *JPEGFile;
char JPEGFName[256];
AVPacket packet = {.data = NULL, .size = 0};
av_init_packet(&packet);
int gotFrame;
if (avcodec_encode_video2(jpegContext, &packet, pFrame, &gotFrame) < 0) {
return -1;
}
sprintf(JPEGFName, "dvr-%06d.jpg", FrameNo);
JPEGFile = fopen(JPEGFName, "wb");
fwrite(packet.data, 1, packet.size, JPEGFile);
fclose(JPEGFile);
av_free_packet(&packet);
avcodec_close(jpegContext);
return 0;
}
如果我使用该代码,我遇到的第一个错误是 AVCodecContext
上的 time_base
未设置。我将其设置为我的视频解码 AVCodecContext
结构的时基。现在我收到另一个错误
[jpeg2000 @ 0x7fd6a4015200] dimensions not set
[jpeg2000 @ 0x7fd6a307c400] dimensions not set
[jpeg2000 @ 0x7fd6a5800000] dimensions not set
[jpeg2000 @ 0x7fd6a307ca00] dimensions not set
[jpeg2000 @ 0x7fd6a3092400] dimensions not set
图像仍然没有被写入。根据 Github 要点,一位评论者声称元数据未写入 JPEG 图像,但我应该如何写入此元数据?我确实设置了编码上下文的宽度和高度,所以我不确定为什么它声称没有设置尺寸。
JPEG2000 不是 jpeg。要对 JPEG 图像进行编码,请使用 AV_CODEC_ID_MJPEG。 MJPEG 代表 "motion JPEG",这是构成视频流的 JPEG 图片序列的通常称呼方式。