V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lingeo
V2EX  ›  程序员

求助, ffmpeg 符号文件报错

  •  
  •   lingeo · 2023-05-17 16:40:12 +08:00 · 816 次点击
    这是一个创建于 547 天前的主题,其中的信息可能已经有所发展或是发生改变。

    代码是使用 ffmpeg 捕获 10 秒 rtsp 流,平台是 windows ,IDE 使用 visual studio 。代码是让 chatgpt 写的 demo,执行到avcodec_receive_frame时,报错如下。 报错 1 报错 2

    ffmpeg 使用的编译版本:ffmpeg-6.0-full_build-shared.7z

    c++代码:

    #include <iostream>
    #include <chrono>
    extern "C" {
    #include <libavformat/avformat.h>
    #include <libavcodec/avcodec.h>
    }
    
    int main(int argc, char *argv[]) {
        std::string url = "rtsp://example.com/stream";
        int duration = 10; // 获取 10 秒视频
    
        av_register_all();
    
        AVFormatContext *format_ctx = nullptr;
        AVCodecContext *codec_ctx = nullptr;
        AVPacket packet = { 0 };
        AVFrame *frame = nullptr;
    
        // 打开 RTSP 流并读取视频流信息
        if (avformat_open_input(&format_ctx, url.c_str(), nullptr, nullptr) < 0) {
            std::cerr << "Error: Could not open input file: " << url << std::endl;
            return -1;
        }
    
        if (avformat_find_stream_info(format_ctx, nullptr) < 0) {
            std::cerr << "Error: Could not find stream information" << std::endl;
            return -1;
        }
    
        // 查找视频流索引
        int video_stream_index = av_find_best_stream(format_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
        if (video_stream_index < 0) {
            std::cerr << "Error: Could not find video stream in input file" << std::endl;
            return -1;
        }
    
        // 根据视频流索引获取视频解码器上下文
        codec_ctx = avcodec_alloc_context3(nullptr);
        if (!codec_ctx) {
            std::cerr << "Error: Could not allocate video codec context" << std::endl;
            return -1;
        }
    
        if (avcodec_parameters_to_context(codec_ctx, format_ctx->streams[video_stream_index]->codecpar) < 0) {
            std::cerr << "Error: Could not initialize video codec parameters" << std::endl;
            return -1;
        }
    
        AVCodec *codec = avcodec_find_decoder(codec_ctx->codec_id);
        if (!codec) {
            std::cerr << "Error: Could not find video codec" << std::endl;
            return -1;
        }
    
        if (avcodec_open2(codec_ctx, codec, nullptr) < 0) {
            std::cerr << "Error: Could not open video codec" << std::endl;
            return -1;
        }
    
        // 分配视频帧内存
        frame = av_frame_alloc();
        if (!frame) {
            std::cerr << "Error: Could not allocate video frame" << std::endl;
            return -1;
        }
    
        // 读取视频帧直到达到指定的时长
        int64_t start_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
        while (true) {
            if (av_read_frame(format_ctx, &packet) >= 0) {
                if (packet.stream_index == video_stream_index) {
                    int ret = avcodec_send_packet(codec_ctx, &packet);
                    if (ret < 0) {
                        std::cerr << "Error: Could not send packet to video codec" << std::endl;
                        break;
                    }
    
                    while (ret >= 0) {
                        ret = avcodec_receive_frame(codec_ctx, frame);
                        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                            break;
                        } else if (ret < 0) {
                            std::cerr << "Error: Could not receive frame from video codec" << std::endl;
                            break;
                        }
    
                        int64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
                        if (now - start_time >= duration * 1000) { // 达到指定时长,退出循环
                            break;
                        }
    
                        // 处理视频帧,例如保存到文件或显示到屏幕上
                        // ...
    
                        av_frame_unref(frame);
                    }
    
                    av_packet_unref(&packet);
                }
            } else {
                break;
            }
        }
    
        // 清理资源
        avcodec_free_context(&codec_ctx);
        avformat_close_input(&format_ctx);
        av_frame_free(&frame);
    
        return 0;
    }
    

    环境搭建后,成功执行了官方源码doc/examples中的remux.c示例。 正在学习 c++,对于这个报错实在是没有头绪。

    第 1 条附言  ·  2023-05-17 17:46:37 +08:00

    原因找到了,在官方文档中有说明,使用AVFrame必须先调用av_frame_alloc()为它分配内存,而chatgpt给的demo中只定义了一个空指针。
    解决

    4 条回复    2023-05-17 23:14:03 +08:00
    newmlp
        1
    newmlp  
       2023-05-17 17:48:43 +08:00   ❤️ 1
    C0000005 异常就是内存访问异常,一般就是空指针和野指针
    lingeo
        2
    lingeo  
    OP
       2023-05-17 17:55:08 +08:00
    @newmlp C++才写没多久,这方面的经验不足,今天学到了。
    loken2020
        3
    loken2020  
       2023-05-17 19:31:04 +08:00   ❤️ 1
    我写过一本书《 FFmpeg 原理》,希望对你有帮助。
    ffmpeg.xianwaizhiyin.net
    lingeo
        4
    lingeo  
    OP
       2023-05-17 23:14:03 +08:00
    @loken2020 万分感谢!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3942 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 04:12 · PVG 12:12 · LAX 20:12 · JFK 23:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.