如何使用 FFmpeg 在 C++ 中将 AVFrame 保存为图像

Iva*_*van 3 c++ ffmpeg decode libav hevc

在我的项目中,我想保存 Hevc 文件中的一帧。我在源代码中使用 FFmpeg 来解码 Hevc 文件并获取 AVFrame 和 AVCodecContext。我需要的是将框架保存为图片(全彩)。

我尝试将其保存为 *.pgm 文件,因此图片只是灰色的,这并不是我真正需要的。

有什么建议吗?谢谢!

void HevcDecoder::Images_Save(char* filename, AVFrame *frame)
{
    FILE* file;
    int i;

    fopen_s(&file, filename, "wb");
    fprintf(file, "P5\n%d %d\n%d\n", frame->width, frame->height, 255);
    for (i = 0; i < frame->height; i++)
        fwrite(frame->data[0] + i * frame->linesize[0], 1, frame->width, file);

    fclose(file);
}

void HevcDecoder::Decode(AVCodecContext* dec_ctx, AVFrame* frame, AVPacket* pkt, const char* filename)
{
    char buf[1024];
    int ret;

    ret = avcodec_send_packet(dec_ctx, pkt);
    if (ret < 0) {
        fprintf(stderr, "Error sending a packet for decoding\n");
        exit(1);
    }

    while (ret >= 0) {
        ret = avcodec_receive_frame(dec_ctx, frame);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
            return;
        else if (ret < 0) {
            fprintf(stderr, "Error during decoding\n");
            exit(1);
        }

        printf("saving frame %3d\n", dec_ctx->frame_number);
        fflush(stdout);

        /* the picture is allocated by the decoder. no need to
           free it */
        snprintf(buf, sizeof(buf), "%s-%d.pgm", filename, dec_ctx->frame_number);
        Images_Save(buf, frame/*, dec_ctx*/);
    }
}
Run Code Online (Sandbox Code Playgroud)

Rot*_*tem 8

使用 FFmpeg CLI 将原始 HEVC 文件转换为图像序列非常简单。

假设input.265是输入文件(原始 HEVC 视频流):
转换为 PNG 图像:

ffmpeg -i input.265 %05d.png
Run Code Online (Sandbox Code Playgroud)

转换为 PPM 图像:

ffmpeg -i input.265 %05d.ppm
Run Code Online (Sandbox Code Playgroud)

如果输入视频使用 MP4 容器并且您想要 JPEG 图像:

ffmpeg -i input.265 %05d.jpg
Run Code Online (Sandbox Code Playgroud)

使用 FFmpeg C 接口(Libav):

为了使事情可重现,首先使用 FFmpeg CLI 创建输入视频文件:

ffmpeg -i input.265 %05d.png
Run Code Online (Sandbox Code Playgroud)

上述命令创建 HEVC (H.265) 编码流 - 10 帧,分辨率为 192x108,像素格式为 YUV420(合成模式)。
编码流是原始视频流(没有容器)。

笔记:

  • RAW HEVC (H.265) 视频流不是常用的文件格式。
    通常流由容器包装(如 MP4 / MKV / AVI ...)。
    我们将原始视频流用于教育目的 - 用于解码的代码更简单。

将图像保存为彩色图像:

该代码示例重用了这篇文章中的代码。

  • PGM 是一种灰度格式,对于等效的颜色格式,我们可以使用PPM 格式
  • 我们可以使用SWS Scale将格式从YUV420转换为RGB。

我们可以使用这篇文章中的代码示例

这是代码示例:

ffmpeg -i input.265 %05d.ppm
Run Code Online (Sandbox Code Playgroud)

使用 OpenCV 显示图像:

显示图像最简单的方法之一是使用OpenCV库。

首次设置同时使用 FFmpeg 和 OpenCV 的项目可能具有挑战性。

  • 我们需要 BGR 格式的图像。
  • 要显示图像,请使用:cv::imshow后接cv::waitKey

代码示例:

ffmpeg -i input.265 %05d.jpg
Run Code Online (Sandbox Code Playgroud)

示例输出:

output_001.jpg:
在此输入图像描述

output_002.jpg:
在此输入图像描述

output_003.jpg:
在此输入图像描述