如何将 AVFrame 写出为 JPEG 图像。

4
我正在编写一个程序来从视频流中提取图像。到目前为止,我已经弄清如何寻找到正确的帧、解码视频流并将相关数据收集到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 Gist页面来看,一个评论者声称JPEG图像中的元数据没有被写入,但是我应该如何编写这些元数据呢?我已经设置了编码上下文的宽度和高度,所以我不确定为什么它声称尺寸未设置。


如果您打印出宽度和高度,输出的值是否合理?另外,您是否做过任何检查以确保传入的帧是正确的? - Chris
1个回答

6

JPEG2000不是JPEG。要编码JPEG图像,请使用AV_CODEC_ID_MJPEG。MJPEG代表“动态JPEG”,这通常是由一系列组成视频流的JPEG图片序列的称呼。


谢谢!我最终使用了MJPEG并使其正常工作。 - John Allard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接