互联网上有一些关于它的教程,其中大部分是使用已弃用的功能,不幸的是,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;
}