static assertion failed: std::thread arguments must be invocable after conversion to rvalues

定义一个thread变量,如果传递的线程函数是包含参数的,但是定义thread变量时并没有传递参数,则会报错误:“static assertion failed: std::thread arguments must be invocable after conversion to rvalues”。调用一个仅仅是声明的函数,没有实际定义则会抛出异常"std::bad_function_call"。

参考了csdn文章<#、##、__VA_ARGS__和##__VA_ARGS__的作用>:VA_ARGS 是一个可变参数的宏,这个可变参数的宏是新的C99规范中新增的,实现思想就是宏定义中参数列表的最后一个参数为省略号(也就是三个点)。##__VA_ARGS:宏前面加上##的作用在于,当可变参数的个数为0时,这里的##起到把前面多余的","去掉的作用,否则会编译出错。一般这个用在调试信息上多一点。

程序运行报错如下,是因为Ffmpeg_Player类都析构了,但是对象运行时创建的线程虽然执行完,但是并没有join掉
PC: @ 0x7fc84c7b4438 gsignal
SIGABRT (@0x20) received by PID 32 (TID 0x7fc6c5fff700) from PID 32; stack trace:
@ 0x7fc853245390 (unknown)
@ 0x7fc84c7b4438 gsignal
@ 0x7fc84c7b603a abort
@ 0x7fc84d0f784d __gnu_cxx::__verbose_terminate_handler()
@ 0x7fc84d0f56b6 (unknown)
@ 0x7fc84d0f5701 std::terminate()
@ 0x7fc84fad1f7c Ffmpeg_Player::~Ffmpeg_Player()
@ 0x456a78 CFfmpegPlyer::~CFfmpegPlyer()
@ 0x456ab4 CFfmpegPlyer::~CFfmpegPlyer()
@ 0x444c15 CCameraManage::clearPlayers()
@ 0x4442c8 CCameraManage::StopCameraManage()
@ 0x4257b0 CManage::prepareNextGroupCameras()
@ 0x427b14 CManage::procMultiCamera()
@ 0x425a21 CManage::procLoop()
@ 0x41f283 _ZZN7CManage5startERK12run_config_tENKUlvE_clEv
@ 0x431270 _ZNSt12_Bind_simpleIFZN7CManage5startERK12run_config_tEUlvE_vEE9_M_invokeIJEEEvSt12_Index_tupleIJXspT_EEE
@ 0x430fb4 _ZNSt12_Bind_simpleIFZN7CManage5startERK12run_config_tEUlvE_vEEclEv
@ 0x430d32 _ZNSt6thread5_ImplISt12_Bind_simpleIFZN7CManage5startERK12run_config_tEUlvE_vEEE6_M_runEv
@ 0x7fc84d120c80 (unknown)
@ 0x7fc85323b6ba start_thread
@ 0x7fc84c8864dd clone
@ 0x0 (unknown)

解压srs-0.1.0.tar.gz编译,结果./configure时报错"./configure: line 99: $ {MODULE_OBJS[@].o}: bad substitution",然后参考CORE_OBJS的定义,将MAIN_OBJS=“${MODULE_OBJS[@].o}“中的”.o"去掉就可以了。成功编译后运行,通过ffmpeg命令推流,然后用vlc直接拉流播放结果报错:“您的输入无法被打开:VLC 无法打开 MRL「rtmp://192.168.163.129:1935/livestream/abc_123」。详情请检查日志”,然后就用ffplay命令打开,然后查看服务端日志报错”[handshake] read c2 failed. ret=208 errno=104(Connection reset by peer)“,然后关键字"ffplay rtmp"搜到"ffplay播放的RTMP URL最好使用双引号括起来,并在后面添加live=1参数,代表实时流。实际上这个参数是传给了ffmpeg的libRTMP的。”,然后就可以正常弹出播放窗口了,然后关闭后再用vlc播放同样的地址也可以正常播放了,但是同时播放就播不了。

参考了csdn上的文章<Openwrt ubus: 进程间通信的例子>,看文章的Makefile,注意要用gcc进行编译,不能用g++,否则代码会报错"sorry, unimplemented: non-trivial designated initializers not supported",该错误主要"因为C和C++结构体初始化不同造成的"。

使用命令"/ffmpeg.exe -re -i H264_AAC_1080P.mp4 -vcodec copy -f flv rtmp://192.168.1.100:1935/livestream/abc_123"推流到rtmp服务器上,结果报错:
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from ‘H264_AAC_1080P.mp4’:
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.29.100
Duration: 00:03:39.08, start: 0.000000, bitrate: 2493 kb/s
Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1920x1080, 2457 kb/s, SAR 1:1 DAR 16:9, 25 fps, 25 tbr, 1000k tbn, 50 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 16000 Hz, mono, fltp, 32 kb/s (default)
Metadata:
handler_name : SoundHandler
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Stream #0:1 -> #0:1 (aac (native) -> mp3 (libmp3lame))
Press [q] to stop, [?] for help
[flv @ 00000267c89fe980] FLV does not support sample rate 16000, choose from (44100, 22050, 11025)
[flv @ 00000267c89fe980] Audio codec mp3 not compatible with flv
Could not write header for output file #0 (incorrect codec parameters ?): Function not implemented
Error initializing output stream 0:1 –
Conversion failed!
后面修改命令"/ffmpeg.exe -re -i H264_AAC_1080P.mp4 -vcodec copy -acodec copy -f flv rtmp://192.168.1.100:1935/livestream/abc_123"就可以正常推流了。

测试FFmpeg-n4.4.1的transcoding.c,结果目标视频的帧率直接减半,目标视频时长是原视频的两倍,然后就搜到csdn上的文章<ffmpeg 4.2.1版本,样例代码 transcoding.c 转码后帧率减半bug>,但是写成固定的不好,我看了https://stackoverflow.com/questions/23098080/transcode-of-h-264-to-vp8-using-libav-has-incorrect-frame-rate这个链接,然后修改stream->dec_frame->pts 赋值的这句代码为下面的这条,然后就可以了。
stream->dec_frame->pts = av_rescale_q(stream->dec_frame->best_effort_timestamp, stream->dec_ctx->time_base, stream->enc_ctx->time_base);
ret = filter_encode_write_frame(stream->dec_frame, stream_index);

在ubuntu中编译ffmpeg,结果报错"nasm/yasm not found or too old. Use --disable-x86asm for a crippled build",然后下载yasm-1.3.0.tar.gz编译安装后就可以了。后面加了选项–enable-libopencv后configure报错"ERROR: opencv not found using pkg-config",然后google关键字"ubuntu ffmpeg --enable-libopencv"搜到<need solution for “libopencv not found”>,然后dioptre/transform360工程的readme中有具体的"Install opencv"和"Build ffmpeg"步骤。然后–enable-libx264又导致报错"ERROR: libx264 not found",然后"apt-get install libx264-dev"再执行就可以了。报错"ERROR: x265 not found using pkg-config",类似264,执行"apt-get install libx265-dev"。此次configure的命令是"./configure --prefix=/usr/local --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --disable-stripping --enable-avresample --enable-libfreetype --enable-libx265 --enable-libopencv --enable-libx264 --enable-shared",由于设置了libdir、incdir,所以prefix被重置忽略了。

打开wireshark抓包,发现有很多过滤器,然后就打开网络连接-“更改适配器选项”,或者"控制面板\网络和 Internet\网络连接",然后将“VMware Network Adapter VMnet8”这个选项右键"禁用",从"已启用"修改成"已禁用",结果xshell到本地vmware虚拟机的连接就自动断开了。抓包使用"ip.addr192.168.1.100 && tcp.port5566 && http"过滤了http的协议。

想用vs2019来编译ffmpeg,然后参考了csdn上的文章<vs2019编译ffmpeg源码为静态库动态库(完整步骤、亲测可行)>,就是"ffmpeg依赖库下载"有点麻烦,因为中间网络总是不好,后来多尝试几次终于在FFmpeg的平级目录下下载了依赖的库代码。wireshark抓包,结果消息太长被截断了,“truncated"的消息部分显示的都是…,不过左侧显示的都是16进制,然后就找到"汉字二进制转换器”,将16进制先转换为二进制,然后再转换成汉字,一个汉字根据编码不同,可能占3个字节。

交叉编译x265,需要修改CMakeLists.txt,设置CC链set(CC ${TOOLCHAIN}/toolchain-x86_64_gcc-8.4.0_glibc/bin/x86_64-openwrt-linux-gcc),类似的还需要设置CPP、CXX、OBJDUMP、STRIP、AR、LD、RANLIB;然后set(CMAKE_C_COMPILER ${CC})设置CMAKE_C_COMPILER,类似的设置CMAKE_CXX_COMPILER、CMAKE_AR、CMAKE_STRIP、CMAKE_RANLIB,然后成功编译。但是想make install到指定目录,设置了CMAKE_INSTALL_LIBDIR、CMAKE_INSTALL_INCLUDEDIR并没有起作用,然后设置CMAKE_INSTALL_PREFIX后再编译安装,结果成功安装到了指定的目录下。configure的时候总是报错"configure: error: C compiler cannot create executables",然后看了config.log,修改了下configure文件,根据提示,把"for ac_option in --version -v -V -qversion; do"中的"-V -qversion"去掉,然后再configure成功。

关键字"git pull每次都要输入用户名和密码怎么办"搜到百度文库<Git默认用户名和密码设置>,“git bash进入项目目录,执行’git config --global credential.helper store’,然后会在本地生成一个文本,记录账号和密码,当然可以不用关心,然后再git pull,会提示输入账号密码,以后就不会了”。操作后"git config --list",发现设置了user.email、user.name。不过切换到其他用户后再config --list会发现是其他用户设置的登录信息。

查看epoll源码,SYSCALL_DEFINE1的定义中,宏"#define __SC_DECL(t, a) t a"实现了参数中逗号的消除。

std::thread 对象在线程函数运行期间必须是有效的,否则程序会崩溃。解决这个问题的方法是,std::thread 对象提供了一个 detach 方法,这个方法让线程对象与线程函数脱离关系,这样即使线程对象被销毁,仍然不影响线程函数的运行。然而,在实际编码中,这也是一个不推荐的做法,原因是我们需要使用线程对象去控制和管理线程的运行和生命周期。所以,我们的代码应该尽量保证线程对象在线程运行期间有效,而不是单纯地调用 detach 方法使线程对象与线程函数的运行分离。

Linux 系统中可以通过 pstack 来命令查看一个进程的线程数量和每个线程的调用堆栈情况。注意:pstack 命令查看的程序必须携带调试符号,且你所使用的用户必须具有相应的查看权限。top 命令的 -H 选项的作用是显示每个一个进程的各个线程运行状态(线程模式)。

pthread_self()获取线程ID,它是pthread_t 类型,本质上是一块内存空间地址。由于不同的进程可能有同样地址的内存块,因此pthread_self()获取的线程 ID 可能不是全系统唯一的,一般是一个很大的数字(内存地址)。
通过系统调用获取线程 ID:int tid = syscall(SYS_gettid); 该方法获取的线程 ID 是系统范围内全局唯一的,一般是一个不会太大的整数。这个数字也是就是所谓的 LWP (Light Weight Process,轻量级进程,早期的 Linux 系统的线程是通过进程来实现的,这种线程被称为轻量级线程)的 ID。

Linux下的信号量、条件变量一样,Linux 互斥体都实现在 NPTL(Native POSIX Thread Library)。编译并使用 gdb 将程序运行起来,按 Ctrl + C (下文中 ^C 字符)将 gdb 中断下来,然后使用 bt 命令发现程序的执行情况(比如卡在什么地方等)。

ubuntu下命令"apt-get update"一直报错,需要去切换一下源:csdn上的<ubuntu换源>图形方法会更简单一些。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值