switch case in protected scope 异常解决

本文介绍了一种在Swift语言中解决UITabBar点击事件的方法,通过在switch-case语句中为每个case添加花括号{}

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

case添加{ }后,编译错误可解决。

- (void)tabBar:(UITabBar *)tb didSelectItem:(UITabBarItem *)item {

    switch(item.tag) {
        case 0:
        {
        }
            break;
        case 1:
        {
        }
            break;
        default:
            break;
    }
}
capturerunner.h 如下 #ifndef CAPTURERUNNER_H #define CAPTURERUNNER_H #include <thread> #include <atomic> #include "../common/XThreadPool.h" #include "../logger/logger.h" extern "C" { #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libavutil/fifo.h> } #define min_time_interval 40 struct CaptureRunnerParam { Capture* capt; // 视频捕获对象指针 AVFifo* fifo; // AVFifo帧数据队列 }; class CaptureRunner : public XTask { public: int Init(void* param); void Deinit(void); int Start(int time); int Stop(void); int Run(); private: std::atomic<bool> m_is_running; Logger::ptr m_logger; Capture* m_capt; AVFifo* m_fifo; int m_time_interval; }; #endif // CAPTURERUNNER_H capturerunner.cpp如下 #include "capturerunner.h" #include <chrono> using namespace std; int CaptureRunner::Init(void* param) { CaptureRunnerParam* c = (CaptureRunnerParam*)param; this->m_capt = c->capt; this->m_fifo = c->fifo; this->m_logger = DefaultLogger(); return 0; } void CaptureRunner::Deinit() { if(m_is_running) { this->Stop(); } return; } int CaptureRunner::Start(int time) { this->m_time_interval = time; Run(); return 0; } int CaptureRunner::Stop() { m_is_running = false; return 0; } int CaptureRunner::Run() { if(m_is_running) { m_logger->Error("Running now"); return -1; } m_is_running = true; int ret = 0; while(m_is_running) { AVFrame* frame = m_capt->CaptureFrame(); if(!frame) { m_logger->Error("readfile failed"); this_thread::sleep_for(chrono::seconds(1)); continue; } // 将帧写入AVFifo ret = av_fifo_write(m_fifo, &frame, 1); if(ret < 0) { m_logger->Error("write to fifo failed"); av_frame_free(&frame); continue; } if(m_time_interval > min_time_interval) { this_thread::sleep_for(chrono::milliseconds(m_time_interval)); } else { this_thread::sleep_for(chrono::milliseconds(min_time_interval)); } } return 0; } capt_test.cpp如下 #include <signal.h> #include <atomic> #include "../common/XThreadPool.h" #include "test.h" #include "../capt/capture.h" #include "../capt/capturerunner.h" extern "C" { #include <libavutil/fifo.h> #include <libavutil/imgutils.h> } using namespace std; Logger::ptr Logger2 = DefaultLogger(); class capt_write : public XTask { public: int Run(); void Stop(); int Init(CaptureRunnerParam* param); void Deinit(); atomic<bool> is_running; AVFifo* fifo; FILE* fp; AVPixelFormat pix_fmt; int width, height; }; int capt_write::Init(CaptureRunnerParam* par) { this->fifo = par->fifo; this->fp = fopen("/home/kylin/zxk/test20241029/output.yuv", "wb"); if(!fp) { Logger2->Error("Failed to open output file"); return -1; } // 从捕获对象获取参数 this->width = par->capt->m_width; this->height = par->capt->m_height; this->pix_fmt = par->capt->m_pixel_fmt; return 0; } int capt_write::Run() { if(is_running) { Logger2->Error("Running now"); return -1; } is_running = true; while(is_running) { if(av_fifo_can_read(fifo) <= 0) { Logger2->Warning("Fifo empty"); this_thread::sleep_for(chrono::seconds(1)); continue; } AVFrame* frame = nullptr; av_fifo_read(fifo, &frame, 1); if(!frame) { Logger2->Warning("frame is NULL"); continue; } // 计算各分量大小 size_t y_bytes = width * height; size_t u_bytes = 0, v_bytes = 0; switch(pix_fmt) { case AV_PIX_FMT_YUYV422: y_bytes = width * height * 2; // YUYV packed格式 break; case AV_PIX_FMT_YUV420P: u_bytes = width * height / 4; v_bytes = width * height / 4; break; case AV_PIX_FMT_BGR0: y_bytes = width * height * 4; // BGR0 packed格式 break; } // 写入文件 fwrite(frame->data[0], 1, y_bytes, fp); if(u_bytes > 0) fwrite(frame->data[1], 1, u_bytes, fp); if(v_bytes > 0) fwrite(frame->data[2], 1, v_bytes, fp); av_frame_free(&frame); } return 0; } void capt_write::Deinit() { if(is_running) { Stop(); } if(fp) { fclose(fp); } } void capt_write::Stop() { is_running = false; } bool stop2 = false; void sigint_handler02(int sig_num) { stop2 = true; } // 初始化V4L2捕获参数 void init_v4l2(CaptParam& c) { c.width = 1280; c.height = 720; c.file_name = "/dev/video0"; c.pixel_fmt = AV_PIX_FMT_YUYV422; c.v4l2_buffer_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; c.v4l2_memory_type = V4L2_MEMORY_MMAP; c.v4l2_pixel_fmt = V4L2_PIX_FMT_YUYV; } // 初始化文件捕获参数 void init_file(CaptParam& c) { c.file_name = "/home/kylin/zxk/test20241021/testyuv.yuv"; c.width = 1280; c.height = 720; c.pixel_fmt = AV_PIX_FMT_YUV420P; } // 初始化屏幕捕获参数 void init_screen(CaptParam& c) { c.width = 1920; c.height = 1080; c.pixel_fmt = AV_PIX_FMT_BGR0; } int capt_test() { CaptParam c; // 选择一种捕获方式初始化 (取消注释对应的行) //init_v4l2(c); // V4L2捕获 init_file(c); // 文件捕获 //init_screen(c); // 屏幕捕获 // 创建AVFifo AVFifo* fifo = av_fifo_alloc2(10 * 1024 * 1024, 1, 0); // 10MB缓冲区 // 创建捕获对象 (与上面选择的初始化方式对应) //Capture* capt = new V4L2Capture; Capture* capt = new FileCapture; //Capture* capt = new ScreenCapture; capt->Init(&c); // 设置任务参数 CaptureRunnerParam param; param.capt = capt; param.fifo = fifo; // 创建任务 auto c1 = make_shared<CaptureRunner>(); auto c2 = make_shared<capt_write>(); c1->Init(&param); c2->Init(&param); // 启动线程池 XThreadPool pool; pool.Init(2); pool.Start(); pool.AddTask(c1); pool.AddTask(c2); // 主循环 signal(SIGINT, sigint_handler02); signal(SIGKILL, sigint_handler02); while(!stop2) { this_thread::sleep_for(chrono::milliseconds(100)); } // 清理 c2->Deinit(); this_thread::sleep_for(chrono::milliseconds(1000)); c1->Deinit(); capt->Deinit(); av_fifo_freep2(&fifo); pool.Stop(); return 0; } CMakeLists.txt 如下 cmake_minimum_required(VERSION 3.15) project(CaptureTest) set(CMAKE_CXX_STANDARD 11) #添加头文件搜索路径 include_directories( ${CMAKE_SOURCE_DIR}/include /home/zhanghan/include /home/zhanghan/Log/Log-lib/include /usr/local/include ) #添加静态库路径 link_directories( /home/zhanghan/Log ) # 查找FFmpeg相关库 find_package(PkgConfig REQUIRED) pkg_check_modules(FFMPEG REQUIRED libavcodec libavformat libavutil libswscale libavdevice ) # 添加FFmpeg头文件 include_directories(${FFMPEG_INCLUDE_DIRS}) # 所有源文件 set(SOURCES main.cpp capt_test.cpp ../logger/logger.cpp ../logger/formatter.cpp ../logger/logsink.cpp ../logger/asynlopper.cpp ../capt/capturerunner.cpp ../capt/capture.cpp ../common/XThreadPool.cpp ../capt/ScreenCapture.cpp ../capt/V4L2Capture.cpp ../capt/FileCapture.cpp ) add_executable(capture_test ${SOURCES}) # 链接库 target_link_libraries(capture_test pthread ${FFMPEG_LIBRARIES} log ) 错误信息如下 zhanghan@zhanghan-virtual-machine:~/daima/2/test2/build$ make -- Configuring done -- Generating done -- Build files have been written to: /home/zhanghan/daima/2/test2/build Consolidate compiler generated dependencies of target capture_test [ 7%] Building CXX object CMakeFiles/capture_test.dir/capt_test.cpp.o In file included from /home/zhanghan/daima/2/test2/capt_test.cpp:6: /home/zhanghan/daima/2/test2/../capt/capturerunner.h:19:5: error: ‘AVFifo’ does not name a type 19 | AVFifo* fifo; // AVFifo帧数据队列 | ^~~~~~ /home/zhanghan/daima/2/test2/../capt/capturerunner.h:34:5: error: ‘AVFifo’ does not name a type 34 | AVFifo* m_fifo; | ^~~~~~ /home/zhanghan/daima/2/test2/capt_test.cpp:25:5: error: ‘AVFifo’ does not name a type 25 | AVFifo* fifo; | ^~~~~~ /home/zhanghan/daima/2/test2/capt_test.cpp: In member function ‘int capt_write::Init(CaptureRunnerParam*)’: /home/zhanghan/daima/2/test2/capt_test.cpp:32:11: error: ‘class capt_write’ has no member named ‘fifo’ 32 | this->fifo = par->fifo; | ^~~~ /home/zhanghan/daima/2/test2/capt_test.cpp:32:23: error: ‘struct CaptureRunnerParam’ has no member named ‘fifo’ 32 | this->fifo = par->fifo; | ^~~~ /home/zhanghan/daima/2/test2/capt_test.cpp:40:30: error: ‘int Capture::m_width’ is protected within this context 40 | this->width = par->capt->m_width; | ^~~~~~~ In file included from /home/zhanghan/daima/2/test2/capt_test.cpp:5: /home/zhanghan/daima/2/test2/../capt/capture.h:87:9: note: declared protected here 87 | int m_width; | ^~~~~~~ /home/zhanghan/daima/2/test2/capt_test.cpp:40:30: note: field ‘int Capture::m_width’ can be accessed via ‘int Capture::GetWidth() const’ 40 | this->width = par->capt->m_width; | ^~~~~~~ | GetWidth() /home/zhanghan/daima/2/test2/capt_test.cpp:41:31: error: ‘int Capture::m_height’ is protected within this context 41 | this->height = par->capt->m_height; | ^~~~~~~~ In file included from /home/zhanghan/daima/2/test2/capt_test.cpp:5: /home/zhanghan/daima/2/test2/../capt/capture.h:88:9: note: declared protected here 88 | int m_height; | ^~~~~~~~ /home/zhanghan/daima/2/test2/capt_test.cpp:41:31: note: field ‘int Capture::m_height’ can be accessed via ‘int Capture::GetHeight() const’ 41 | this->height = par->capt->m_height; | ^~~~~~~~ | GetHeight() /home/zhanghan/daima/2/test2/capt_test.cpp:42:32: error: ‘AVPixelFormat Capture::m_pixel_fmt’ is protected within this context 42 | this->pix_fmt = par->capt->m_pixel_fmt; | ^~~~~~~~~~~ In file included from /home/zhanghan/daima/2/test2/capt_test.cpp:5: /home/zhanghan/daima/2/test2/../capt/capture.h:89:19: note: declared protected here 89 | AVPixelFormat m_pixel_fmt; | ^~~~~~~~~~~ /home/zhanghan/daima/2/test2/capt_test.cpp:42:32: note: field ‘AVPixelFormat Capture::m_pixel_fmt’ can be accessed via ‘AVPixelFormat Capture::GetPixelFmt() const’ 42 | this->pix_fmt = par->capt->m_pixel_fmt; | ^~~~~~~~~~~ | GetPixelFmt() /home/zhanghan/daima/2/test2/capt_test.cpp: In member function ‘virtual int capt_write::Run()’: /home/zhanghan/daima/2/test2/capt_test.cpp:55:29: error: ‘fifo’ was not declared in this scope; did you mean ‘mkfifo’? 55 | if(av_fifo_can_read(fifo) <= 0) { | ^~~~ | mkfifo /home/zhanghan/daima/2/test2/capt_test.cpp:55:12: error: ‘av_fifo_can_read’ was not declared in this scope; did you mean ‘av_fifo_generic_read’? 55 | if(av_fifo_can_read(fifo) <= 0) { | ^~~~~~~~~~~~~~~~ | av_fifo_generic_read /home/zhanghan/daima/2/test2/capt_test.cpp:62:22: error: ‘fifo’ was not declared in this scope; did you mean ‘mkfifo’? 62 | av_fifo_read(fifo, &frame, 1); | ^~~~ | mkfifo /home/zhanghan/daima/2/test2/capt_test.cpp:62:9: error: ‘av_fifo_read’ was not declared in this scope; did you mean ‘avio_read’? 62 | av_fifo_read(fifo, &frame, 1); | ^~~~~~~~~~~~ | avio_read /home/zhanghan/daima/2/test2/capt_test.cpp: In function ‘int capt_test()’: /home/zhanghan/daima/2/test2/capt_test.cpp:149:5: error: ‘AVFifo’ was not declared in this scope 149 | AVFifo* fifo = av_fifo_alloc2(10 * 1024 * 1024, 1, 0); // 10MB缓冲区 | ^~~~~~ /home/zhanghan/daima/2/test2/capt_test.cpp:149:13: error: ‘fifo’ was not declared in this scope; did you mean ‘mkfifo’? 149 | AVFifo* fifo = av_fifo_alloc2(10 * 1024 * 1024, 1, 0); // 10MB缓冲区 | ^~~~ | mkfifo /home/zhanghan/daima/2/test2/capt_test.cpp:149:20: error: ‘av_fifo_alloc2’ was not declared in this scope; did you mean ‘av_fifo_alloc’? 149 | AVFifo* fifo = av_fifo_alloc2(10 * 1024 * 1024, 1, 0); // 10MB缓冲区 | ^~~~~~~~~~~~~~ | av_fifo_alloc /home/zhanghan/daima/2/test2/capt_test.cpp:161:11: error: ‘struct CaptureRunnerParam’ has no member named ‘fifo’ 161 | param.fifo = fifo; | ^~~~ /home/zhanghan/daima/2/test2/capt_test.cpp:188:5: error: ‘av_fifo_freep2’ was not declared in this scope; did you mean ‘av_fifo_freep’? 188 | av_fifo_freep2(&fifo); | ^~~~~~~~~~~~~~ | av_fifo_freep 如何解决
最新发布
06-06
<think>我们在处理FFmpeg相关的编译问题时,经常遇到类型未定义、访问权限问题以及函数未声明的问题。根据引用中提到的信息,我们可以采取以下步骤来修复:1.类型未定义(例如AVFifo):-确保包含正确的头文件。AVFifo类型通常在<libavutil/fifo.h>中定义。-检查FFmpeg库的版本,因为不同版本的FFmpeg可能有不同的API和结构定义。如果使用的是较旧的版本,可能没有AVFifo,而是使用AVFifoBuffer。2.保护成员访问错误:-这通常发生在试图访问一个结构体或类的私有(private)或保护(protected)成员时。在FFmpeg中,很多结构体的成员是不直接暴露给外部的。此时,应该使用FFmpeg提供的公共接口函数来访问或操作这些成员。-例如,如果遇到访问AVFormatContext中的保护成员,应该使用avformat_open_input()、avformat_find_stream_info()等函数来操作,而不是直接访问其内部成员。3.未声明的函数:-确保包含声明该函数的头文件。-检查链接库是否正确,确保在链接时包含了对应的库(例如-lavformat、-lavcodec等)。-如果函数是内部函数(在FFmpeg内部使用,未在公共头文件中导出),那么我们不能直接使用。需要查看官方文档或源代码,确认该函数是否属于公共API。具体解决步骤:步骤一:包含必要的头文件对于AVFifo,添加:```c#include<libavutil/fifo.h>```步骤二:检查FFmpeg版本在配置项目时,确保使用的FFmpeg版本支持你所使用的API。可以通过以下代码检查版本:```c#include<libavutil/avutil.h>printf("FFmpegversion:%d.%d.%d\n",AV_VERSION_MAJOR(avutil_version()),AV_VERSION_MINOR(avutil_version()),AV_VERSION_MICRO(avutil_version()));```步骤三:使用正确的API访问保护成员例如,如果你需要访问AVFormatContext中的一些保护成员,不要直接访问,而是使用FFmpeg提供的函数。例如:-打开输入文件使用`avformat_open_input`-读取数据包使用`av_read_frame`步骤四:处理未声明的函数如果遇到未声明的函数,首先查找该函数在哪个头文件中声明,并包含该头文件。如果该函数不是公共API,则可能需要考虑替代方案,或者重新编译FFmpeg以导出该函数(但通常不建议,因为会破坏兼容性)。步骤五:链接正确的库确保在编译命令中链接了所有必要的FFmpeg库。例如:```bashgcc-oprogramprogram.c-lavformat-lavcodec-lavutil-lswscale```步骤六:清理和重新编译如果之前编译过,可能存在冲突的目标文件,可以尝试清理项目并重新编译。示例代码:假设我们在代码中使用了AVFifo,我们可以这样使用:```c#include<libavutil/fifo.h>intmain(){//创建一个AVFifoBuffer(在较新版本中AVFifoBuffer被AVFifo替代)AVFifo*fifo=av_fifo_alloc(1024);if(!fifo){//错误处理}//...使用fifoav_fifo_freep(&fifo);return0;}```注意:在较新版本的FFmpeg(4.0之后)中,AVFifoBuffer已经被重构为AVFifo。但是如果你使用的旧版本,可能没有AVFifo,需要使用AVFifoBuffer。因此,请根据版本调整。另外,引用[3]中提到,建议在编译FFmpeg后执行`makeinstall`,这样可以方便地获取整理好的头文件和库。如果按照上述步骤仍然无法解决问题,请检查FFmpeg的编译配置是否正确,以及是否将头文件和库路径正确包含到项目中。相关问题:1.如何正确配置CMake项目以使用FFmpeg库?2.FFmpeg中的AVFifo和AVFifoBuffer有什么区别?3.如何在不同的操作系统(Windows/Linux/macOS)下编译FFmpeg?4.如何解决FFmpeg版本不兼容导致的API变化问题?</think> ### 修复 FFmpeg 编译问题的解决方案 #### 1. **AVFifo 类型未定义** **原因**:未包含正确的头文件或 FFmpeg 版本不匹配。 **修复步骤**: 1. 检查头文件包含: ```c #include <libavutil/fifo.h> // 确保包含此头文件 ``` 2. 验证 FFmpeg 版本: - AVFifo 在较新的 FFmpeg 版本中引入(推荐 >= 4.0) - 若使用旧版本,改用 `AVFifoBuffer`(已弃用): ```c #include <libavutil/fifo.h> AVFifoBuffer *fifo = av_fifo_alloc(buffer_size); ``` 3. 清理并重编译: ```bash make clean && make ``` #### 2. **保护成员访问错误** **原因**:直接访问 FFmpeg 内部结构体(如 `AVCodecContext` 的私有成员)。 **修复方法**: 1. 使用公共 API 替代直接访问: ```c // 错误示例:直接访问 protected 成员 ctx->bit_rate = 1000000; // 正确示例:使用 API 设置参数 av_opt_set_int(ctx, "b", 1000000, AV_OPT_SEARCH_CHILDREN); ``` 2. 检查结构体类型: - 优先使用 `AVCodecParameters` 而非 `AVCodecContext` 传参 3. 启用访问封装(仅限调试): ```c #define private public // 不推荐,仅临时测试 ``` #### 3. **未声明的函数** **原因**:缺少链接库或头文件包含错误。 **解决方案**: 1. 明确声明函数: ```c extern "C" { #include <libavformat/avformat.h> // 确保覆盖所需函数 } ``` 2. 检查链接库顺序: ```bash g++ main.cpp -lavformat -lavcodec -lavutil # 顺序必须是 libavformat 在前 ``` 3. 确认符号存在: ```bash nm -D libavformat.so | grep av_read_frame # 检查函数是否在库中导出 ``` #### 4. **引用问题** 若问题仅在调用自己编译的库时出现(如引用[2]描述): 1. 统一编译选项: ```bash # 确保 FFmpeg 和主工程使用相同的 -fPIC 等标志 ./configure --enable-shared --extra-cflags="-fPIC" ``` 2. 完整清理后重编译: ```bash make distclean && ./configure && make ``` ### 推荐完整修复流程 1. 更新 FFmpeg 到最新稳定版 2. 在 `CMakeLists.txt` 中精确配置: ```cmake find_package(PkgConfig REQUIRED) pkg_check_modules(FFMPEG REQUIRED libavformat libavcodec libavutil) include_directories(${FFMPEG_INCLUDE_DIRS}) target_link_libraries(your_target ${FFMPEG_LIBRARIES}) ``` 3. 验证代码访问规范: ```c AVFormatContext *fmt_ctx = nullptr; if (avformat_open_input(&fmt_ctx, "input.mp4", nullptr, nullptr) != 0) { char err_buf[64]; av_strerror(ret, err_buf, sizeof(err_buf)); // 使用API获取错误 } ``` > **关键提示**: > - 避免直接引用 FFmpeg 内部结构,优先使用 `av_opt_set()` 等公共 API[^1] > - 执行 `make install` 确保头文件和库路径正确[^3] > - 跨平台时需清理旧编译链(如重装 MinGW)[^3] --- ### 相关问题 1. 如何正确配置 CMake 项目链接 FFmpeg 动态库? 2. FFmpeg 中公共 API 和私有结构体有哪些使用界限? 3. 调试 FFmpeg 源码时如何避免内存读写错误? 4. 不同版本 FFmpeg 的 API 兼容性如何解决? [^1]: 函数封装可避免宏定义问题 [^2]: 符号未定义常因链接顺序不当 [^3]: 重装编译工具链可解决文件缺失
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值