首页 > 编程语言 >ffmpeg开发程序的实例代码

ffmpeg开发程序的实例代码

时间:2023-06-26 16:31:51浏览次数:70  
标签:index ffmpeg 代码 ctx ret 实例 codec NULL frame

以下是一个使用ffmpeg库解码视频文件并输出每个帧的示例代码:

```c++

include
include
include
ifdef __cplusplus
extern "C" {
 
endif
include <libavcodec/avcodec.h>
include <libavformat/avformat.h>
include <libswscale/swscale.h>
ifdef __cplusplus
}

endif

using namespace std;

int main(int argc, char* argv[]) { if (argc != 2) { cout << "Usage: " << argv[0] << " " << endl; return 1; }

// 注册所有的编解码器和格式
av_register_all();
 
// 打开输入文件
AVFormatContext* format_ctx = NULL;
if (avformat_open_input(&format_ctx, argv[1], NULL, NULL) != 0) {
    cerr << "Failed to open input file " << argv[1] << endl;
    return 1;
}
 
// 查找流信息
if (avformat_find_stream_info(format_ctx, NULL) < 0) {
    cerr << "Failed to find stream information" << endl;
    return 1;
}
 
// 打印视频信息
int video_stream_index = -1;
for (unsigned int i = 0; i < format_ctx->nb_streams; i++) {
    if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
        video_stream_index = i;
        break;
    }
}
if (video_stream_index == -1) {
    cerr << "No video stream found in the input file" << endl;
    return 1;
}
AVCodecParameters* codec_params = format_ctx->streams[video_stream_index]->codecpar;
cout << "Video codec: " << avcodec_get_name(codec_params->codec_id) << endl;
cout << "Resolution: " << codec_params->width << "x" << codec_params->height << endl;
cout << "Frame rate: " << av_q2d(format_ctx->streams[video_stream_index]->avg_frame_rate) << " fps" << endl;
 
// 查找视频解码器
AVCodec* codec = avcodec_find_decoder(codec_params->codec_id);
if (codec == NULL) {
    cerr << "Unsupported codec: " << avcodec_get_name(codec_params->codec_id) << endl;
    return 1;
}
 
// 打开解码器
AVCodecContext* codec_ctx = avcodec_alloc_context3(codec);
if (avcodec_parameters_to_context(codec_ctx, codec_params) < 0) {
    cerr << "Failed to copy codec parameters to decoder context" << endl;
    return 1;
}
if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
    cerr << "Failed to open codec" << endl;
    return 1;
}
 
// 创建图像转换器
AVFrame* frame = av_frame_alloc();
AVFrame* frame_rgb = av_frame_alloc();
struct SwsContext* sws_ctx = sws_getContext(codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt,
                                            codec_ctx->width, codec_ctx->height, AV_PIX_FMT_RGB24,
                                            SWS_BILINEAR, NULL, NULL, NULL);
int num_bytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, codec_ctx->width, codec_ctx->height, 1);
uint8_t* buffer = (uint8_t*)av_malloc(num_bytes * sizeof(uint8_t));
av_image_fill_arrays(frame_rgb->data, frame_rgb->linesize, buffer, AV_PIX_FMT_RGB24,
                      codec_ctx->width, codec_ctx->height, 1);
 
// 解码视频并输出每一帧
AVPacket pkt;
int frame_count = 0;
while (av_read_frame(format_ctx, &pkt) >= 0) {
    if (pkt.stream_index == video_stream_index) {
        int ret = avcodec_send_packet(codec_ctx, &pkt);
        if (ret < 0) {
            cerr << "Failed to send packet to decoder" << endl;
            return 1;
        }
        while (ret >= 0) {
            ret = avcodec_receive_frame(codec_ctx, frame);
            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
                break;
            else if (ret < 0) {
                cerr << "Failed to decode frame" << endl;
                return 1;
            }
 
            // 转换图像格式
            sws_scale(sws_ctx, frame->data, frame->linesize, 0, codec_ctx->height,
                      frame_rgb->data, frame_rgb->linesize);
 
            // 输出帧信息
            cout << "Frame " << frame_count++ << ": " << flush;
            cout << "pts=" << frame->pts << ", " << flush;
            cout << "dts=" << frame->pkt_dts << ", " << flush;
            cout << "keyframe=" << boolalpha << (frame->key_frame != 0) << endl;
        }
    }
    av_packet_unref(&pkt);
}
 
// 清理内存
av_free(buffer);
av_frame_free(&frame_rgb);
av_frame_free(&frame);
avcodec_free_context(&codec_ctx);
avformat_close_input(&format_ctx);
avformat_free_context(format_ctx);
 
return 0;

该程序首先打开输入视频文件,并查找视频流信息。然后它寻找适合于该视频编解码器的解码器,并使用该解码器打开视频流。


接下来,程序创建一个图像转换器,该转换器将每个解码帧从其原始格式(例如YUV)转换为RGB24格式。程序使用此图像转换器解码每个视频帧,并输出关于该帧的一些信息(如时间戳和关键帧标志)。


最后,程序清理所有分配的内存并关闭输入视频文件。


请注意,该程序仅限于演示目的,可能不适用于所有类型的视频文件和编解码器。它可以通过添加错误检查和处理程序等额外功能进行扩展。


标签:index,ffmpeg,代码,ctx,ret,实例,codec,NULL,frame
From: https://blog.51cto.com/u_16159766/6555728

相关文章

  • VSCode-代码运行相关
    快捷键Ctrl+Shift+P搜索Ctrl+F5运行代码Ctrl+,打开设置Ctrl+Shift+E打开文件Ctrl+Alt+C打开博客园功能设置文件:settings.json隐藏以及排除git相关文件设置界面字体Go语言Go运行->教程->测试安装Go语言https://www.cnblogs.com/nrocky/p/14449987.html......
  • Python爬虫完整代码模版
    以下是一个基本的Python爬虫代码模板,可以根据需要进行修改:importrequestsfrombs4importBeautifulSoup#设置请求头,模拟浏览器访问headers={'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/58.0.3029.110......
  • 一个同步机无传感滑膜观测器模型加代码,该模型基于28035芯片,采用了典型的smo+pll方案
    一个同步机无传感滑膜观测器模型加代码,该模型基于28035芯片,采用了典型的smo+pll方案。这段代码是实际应用代码,而不是一般的玩票代码,因此具有较高的可比性(不同于ti例程)。需要注意的是,少数文件中的中文注释可能存在乱码问题。至于m文件,它并没有太多用处,直接运行simulink模型即可。知......
  • 个包含电动四轮车控制器代码的资源,其中包括PCB文件、pdf原理图和完整的代码
    一个包含电动四轮车控制器代码的资源,其中包括PCB文件、pdf原理图和完整的代码。这些资源来自一个知名厂家,代码的编写风格非常出色。从这段话中,我们可以提取出以下知识点和领域范围:电动四轮车、控制器、PCB设计、原理图、代码编写。关于电动四轮车,它是一种使用电力驱动的车辆,通常......
  • 福昕Foxit PDF远程代码执行漏洞CVE-2023-27363分析与复现
    漏洞概述福建福昕软件开发股份有限公司是一家国际化运营的PDF电子文档解决方案提供厂商,提供文档的生成、转换、显示、编辑、搜索、打印、存储、签章、表单、保护、安全分发管理等涵盖文档生命周期的产品技术与解决方案。其下产品FoxitPDFReader和FoxitPDFEditor的javascript函......
  • Lua 是怎么执行代码的?初识 Lua
    楔子下面我们来一起学习一下Lua语言,相信很多人都听说过它,Lua是一种可嵌入、轻量、快速、功能强大的脚本语言,使用较为广泛,主要用在游戏领域。另外,基于Nginx的OpenResty也是使用Lua来编写脚本的,很多存储框架(如Redis)也支持使用Lua来编写脚本。作为一门诞生已经超过20......
  • Nodepad ++ 运行JAVA代码
    前提:环境已经配置完毕(具体步骤可自行在必应,百度等平台搜索)jdk版本:jdk1.8.0_202notepad++已安装方法:notepad不添加插件,使用CMD终端命令运行1.使用notepad++,新建文本输入以下代码,并另存为HelloWorld.javapublicclassHelloWorld{ publicstaticvoidmain(String......
  • 代码随想录算法训练营第十七天| 654.最大二叉树 617.合并二叉树 700.二叉搜索树中
     654.最大二叉树 比较简单,直接上代码1TreeNode*constructMax_cursor(vector<int>&nums)2{3if(nums.size()==0)returnNULL;4//getMaxNum5intindex=0;6intmax_=INT_MIN;7for(inti=0;i<nums.size();i++)8......
  • 发布一个Visual Studio 2022 插件,可以自动完成构造函数依赖注入代码
    赖注入(DI)在开发中既是常见的也是必需的技术。它帮助我们优化了代码结构,使得应用更加灵活、易于扩展,同时也降低了各个模块之间的耦合度,更容易进行单元测试,提高了编码效率和质量。不过,手动注入依赖项也可能会成为我们开发过程中的瓶颈。通常情况下,当我们需要注入大量依赖对象时,我......
  • 课程设计飞机大战————代码大全
    #include<graphics.h>//easyx图形库#include<iostream>#include<conio.h>usingnamespacestd;IMAGEbk;//指向背景图IMAGEimg_player[2];//指向飞机IMAGEimg_bullet[2];//指向子弹IMAGEimg_enemy[2][2];//指向敌机intthecount=0;intthatcount=0;enumtheWin......