使用FFmpeg将帧保存为图像

时间:2014-10-25 14:24:37

标签: c++ c ffmpeg

互联网上有一些关于它的教程,其中大部分是使用已弃用的功能,不幸的是,API用来打破它,它弄得一团糟,我真的很困惑。

我遵循教程,学习文档并查看当前版本的示例(即使某些示例不起作用)。

我尝试做的是在.png中保存帧,按照示例并阅读我这样做,但我对将帧转换为RBG并保存它感到困惑:

#include <iostream>

extern "C"
{
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libavutil/avutil.h>
}

int main(int argc, char ** argv)
{
    if (argc < 2)
    {
        av_log(0, AV_LOG_FATAL, "Usage: %s <input>", argv[0]);
        return -1;
    }

    const char * filename = argv[1];

    // register all codecs and formats
    av_register_all();

    // open input file, and allocate format context
    AVFormatContext *avFormatContext = avformat_alloc_context();

    if (avformat_open_input(&avFormatContext, filename, 0, 0) < 0)
    {
        av_log(0, AV_LOG_FATAL, "Could not open source file %s", filename);
        return -1;
    }

    // retrieve stream information
    if (avformat_find_stream_info(avFormatContext, 0) < 0)
    {
        av_log(0, AV_LOG_FATAL, "Could not find stream information");
        return -1;
    }

    // dump information about file onto standard error
    av_dump_format(avFormatContext, 0, filename, 0);

    // find the "best" video stream in the file.
    int result = av_find_best_stream(avFormatContext, AVMEDIA_TYPE_VIDEO, -1, -1, 0, 0);

    if (result < 0)
    {
        av_log(0, AV_LOG_FATAL, "Could not find %s stream in input file '%s'", av_get_media_type_string(AVMEDIA_TYPE_VIDEO), filename);
        return -1;
    }

    int stream = result;
    AVStream *avStream = avFormatContext->streams[stream];
    AVCodecContext *avCodecContext = avStream->codec;

    // find decoder for the stream
    AVCodec *avCodec = avcodec_find_decoder(avCodecContext->codec_id);

    if (! avCodec)
    {
        av_log(0, AV_LOG_FATAL, "Failed to find %s codec", av_get_media_type_string(AVMEDIA_TYPE_VIDEO));
        return -1;
    }

    // init the decoders, with reference counting
    AVDictionary *avDictionary = 0;
    av_dict_set(&avDictionary, "refcounted_frames", "1", 0);

    if (result = avcodec_open2(avCodecContext, avCodec, &avDictionary) < 0)
    {
        av_log(0, AV_LOG_FATAL, "Failed to open %s codec", av_get_media_type_string(AVMEDIA_TYPE_VIDEO));
        return -1;
    }

    AVFrame *avFrame = av_frame_alloc();

    if (! avFrame)
    {
        av_log(0, AV_LOG_FATAL, "Could not allocate frame");
        return -1;
    }

    // initialize packet, set data to null, let the demuxer fill it
    AVPacket avPacket;
    av_init_packet(&avPacket);
    avPacket.data = 0;
    avPacket.size = 0;

    while (av_read_frame(avFormatContext, &avPacket) >= 0)
    {
        if (avPacket.stream_index == stream)
        {
            int success = avcodec_decode_video2(avCodecContext, avFrame, &success, &avPacket);

            if (success <= 0)
            {
                av_log(0, AV_LOG_FATAL, "Error decoding video frame");
                return -1;
            }

            // ... saving...
        }
    }

    avcodec_close(avCodecContext);
    avformat_close_input(&avFormatContext);
    av_frame_free(&avFrame);

    return 0;
}

0 个答案:

没有答案