转载请标明出处,尊重原作者,https://blog.csdn.net/qq_36491519/article/details/86535967

做安防+AI的很多人都遇到过黑屏问题,这各问题在个平台又大不一样,这一次我分析了一下在win系统下rtsp协议情况下的断流黑屏问题(同样的在Android下就没有问题)。

是这样的,在断网等情况下拉流端会拉不到流造成黑屏,这样用户体验非常不好,后来我在播放段加了断流检测回调,简单的就是每10微妙检测一下网络,如果网络超时达到自己的设定值就回调通知上层,让上层弹框通知等。然而没想到此回调再win系统会有ones的不起作用,但是再Android等就完全没问题。

首先分析一下win问题的log。

log会频繁打印

"corrupted macroblock 8 10 (total_coeff=-1)\n"

这是什么情况那?来看看他的位置。

//转载请标明出处,尊敬原作者,https://blog.csdn.net/qq_36491519/article/details/86535967
/*** Decode a residual block.* @param n block index* @param scantable scantable* @param max_coeff number of coefficients in the block* @return <0 if an error occurred*/
static int decode_residual(const H264Context *h, H264SliceContext *sl,GetBitContext *gb, int16_t *block, int n,const uint8_t *scantable, const uint32_t *qmul,int max_coeff)
{static const int coeff_token_table_index[17]= {0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3};int level[16];int zeros_left, coeff_token, total_coeff, i, trailing_ones, run_before;//FIXME put trailing_onex into the contextif(max_coeff <= 8){if (max_coeff == 4)coeff_token = get_vlc2(gb, chroma_dc_coeff_token_vlc.table, CHROMA_DC_COEFF_TOKEN_VLC_BITS, 1);elsecoeff_token = get_vlc2(gb, chroma422_dc_coeff_token_vlc.table, CHROMA422_DC_COEFF_TOKEN_VLC_BITS, 1);total_coeff= coeff_token>>2;}else{if(n >= LUMA_DC_BLOCK_INDEX){total_coeff= pred_non_zero_count(h, sl, (n - LUMA_DC_BLOCK_INDEX)*16);coeff_token= get_vlc2(gb, coeff_token_vlc[ coeff_token_table_index[total_coeff] ].table, COEFF_TOKEN_VLC_BITS, 2);total_coeff= coeff_token>>2;}else{total_coeff= pred_non_zero_count(h, sl, n);coeff_token= get_vlc2(gb, coeff_token_vlc[ coeff_token_table_index[total_coeff] ].table, COEFF_TOKEN_VLC_BITS, 2);total_coeff= coeff_token>>2;}}sl->non_zero_count_cache[scan8[n]] = total_coeff;//FIXME set last_non_zero?if(total_coeff==0)return 0;if(total_coeff > (unsigned)max_coeff) {av_log(h->avctx, AV_LOG_ERROR, "corrupted macroblock %d %d (total_coeff=%d)\n", sl->mb_x, sl->mb_y, total_coeff);return -1;}trailing_ones= coeff_token&3;ff_tlog(h->avctx, "trailing:%d, total:%d\n", trailing_ones, total_coeff);av_assert2(total_coeff<=16);i = show_bits(gb, 3);skip_bits(gb, trailing_ones);level[0] = 1-((i&4)>>1);level[1] = 1-((i&2)   );level[2] = 1-((i&1)<<1);if(trailing_ones<total_coeff) {int mask, prefix;int suffix_length = total_coeff > 10 & trailing_ones < 3;int bitsi= show_bits(gb, LEVEL_TAB_BITS);int level_code= cavlc_level_tab[suffix_length][bitsi][0];skip_bits(gb, cavlc_level_tab[suffix_length][bitsi][1]);if(level_code >= 100){prefix= level_code - 100;if(prefix == LEVEL_TAB_BITS)prefix += get_level_prefix(gb);//first coefficient has suffix_length equal to 0 or 1if(prefix<14){ //FIXME try to build a large unified VLC table for all thisif(suffix_length)level_code= (prefix<<1) + get_bits1(gb); //partelselevel_code= prefix; //part}else if(prefix==14){if(suffix_length)level_code= (prefix<<1) + get_bits1(gb); //partelselevel_code= prefix + get_bits(gb, 4); //part}else{level_code= 30;if(prefix>=16){if(prefix > 25+3){av_log(h->avctx, AV_LOG_ERROR, "Invalid level prefix\n");return -1;}level_code += (1<<(prefix-3))-4096;}level_code += get_bits(gb, prefix-3); //part}if(trailing_ones < 3) level_code += 2;suffix_length = 2;mask= -(level_code&1);level[trailing_ones]= (((2+level_code)>>1) ^ mask) - mask;}else{level_code += ((level_code>>31)|1) & -(trailing_ones < 3);suffix_length = 1 + (level_code + 3U > 6U);level[trailing_ones]= level_code;}//remaining coefficients have suffix_length > 0for(i=trailing_ones+1;i<total_coeff;i++) {static const unsigned int suffix_limit[7] = {0,3,6,12,24,48,INT_MAX };int bitsi= show_bits(gb, LEVEL_TAB_BITS);level_code= cavlc_level_tab[suffix_length][bitsi][0];skip_bits(gb, cavlc_level_tab[suffix_length][bitsi][1]);if(level_code >= 100){prefix= level_code - 100;if(prefix == LEVEL_TAB_BITS){prefix += get_level_prefix(gb);}if(prefix<15){level_code = (prefix<<suffix_length) + get_bits(gb, suffix_length);}else{level_code = 15<<suffix_length;if (prefix>=16) {if(prefix > 25+3){av_log(h->avctx, AV_LOG_ERROR, "Invalid level prefix\n");return AVERROR_INVALIDDATA;}level_code += (1<<(prefix-3))-4096;}level_code += get_bits(gb, prefix-3);}mask= -(level_code&1);level_code= (((2+level_code)>>1) ^ mask) - mask;}level[i]= level_code;suffix_length+= suffix_limit[suffix_length] + level_code > 2U*suffix_limit[suffix_length];}}if(total_coeff == max_coeff)zeros_left=0;else{if (max_coeff <= 8) {if (max_coeff == 4)zeros_left = get_vlc2(gb, chroma_dc_total_zeros_vlc[total_coeff].table,CHROMA_DC_TOTAL_ZEROS_VLC_BITS, 1);elsezeros_left = get_vlc2(gb, chroma422_dc_total_zeros_vlc[total_coeff].table,CHROMA422_DC_TOTAL_ZEROS_VLC_BITS, 1);} else {zeros_left= get_vlc2(gb, total_zeros_vlc[ total_coeff ].table, TOTAL_ZEROS_VLC_BITS, 1);}}#define STORE_BLOCK(type) \scantable += zeros_left + total_coeff - 1; \if(n >= LUMA_DC_BLOCK_INDEX){ \((type*)block)[*scantable] = level[0]; \for(i=1;i<total_coeff && zeros_left > 0;i++) { \if(zeros_left < 7) \run_before= get_vlc2(gb, run_vlc[zeros_left].table, RUN_VLC_BITS, 1); \else \run_before= get_vlc2(gb, run7_vlc.table, RUN7_VLC_BITS, 2); \zeros_left -= run_before; \scantable -= 1 + run_before; \((type*)block)[*scantable]= level[i]; \} \for(;i<total_coeff;i++) { \scantable--; \((type*)block)[*scantable]= level[i]; \} \}else{ \((type*)block)[*scantable] = ((int)(level[0] * qmul[*scantable] + 32))>>6; \for(i=1;i<total_coeff && zeros_left > 0;i++) { \if(zeros_left < 7) \run_before= get_vlc2(gb, run_vlc[zeros_left].table, RUN_VLC_BITS, 1); \else \run_before= get_vlc2(gb, run7_vlc.table, RUN7_VLC_BITS, 2); \zeros_left -= run_before; \scantable -= 1 + run_before; \((type*)block)[*scantable]= ((int)(level[i] * qmul[*scantable] + 32))>>6; \} \for(;i<total_coeff;i++) { \scantable--; \((type*)block)[*scantable]= ((int)(level[i] * qmul[*scantable] + 32))>>6; \} \}if (h->pixel_shift) {STORE_BLOCK(int32_t)} else {STORE_BLOCK(int16_t)}if(zeros_left<0){av_log(h->avctx, AV_LOG_ERROR, "negative number of zero coeffs at %d %d\n", sl->mb_x, sl->mb_y);return -1;}return 0;
}

问题就发生再H264解码的时候,在解码残余部分的时候发生。

   //转载请标明出处,尊重原作者,https://blog.csdn.net/qq_36491519/article/details/86535967//FIXME set last_non_zero?if(total_coeff==0)return 0;if(total_coeff > (unsigned)max_coeff) {av_log(h->avctx, AV_LOG_ERROR, "corrupted macroblock %d %d (total_coeff=%d)\n", sl->mb_x, sl->mb_y, total_coeff);return -1;}

在这里由于total_coeff值没有传入,造成total_coeff为-1,进而造成total_coeff<max_coeff。

而decode_residual函数是在下面的h264解码函数调用的。函数如下:

int ff_h264_decode_mb_cavlc(const H264Context *h, H264SliceContext *sl)

那上面的函数又在static int decode_slice(struct AVCodecContext *avctx, void *arg)

static int decode_slice(struct AVCodecContext *avctx, void *arg)

static int decode_slice(struct AVCodecContext *avctx, void *arg)中有一个无限循环,讲到这里大家就知道该怎么处理了吧,在这个无限循环里处理,比如超时判断,增加回调等等。

ffmpeg断流黑屏问题分析相关推荐

  1. FFmpeg 直播黑屏问题分析解决

    背景 分析思路 解决思路 背景 FFmpeg是非常优秀的开源框架,在使用其进行二次开发及适配的过程中,难免会遇到各种各样的问题. 这次记录的是基于FFmpeg开发的播放器中,直播黑屏问题分析思路及解决 ...

  2. IJKPlayer播放视频在iOS部分机型黑屏原因分析

    一.背景 1.问题视频在iphone7p等机型上:视频无法正常播放(黑屏),音频正常播放. 2.问题视频在iphone XR机型上:音视频均能正常播放. 二.断点分析 1.问题视频在iphone7p上 ...

  3. RTMP直播黑屏问题分析与解决

    问题发现 一客户直播环境为ffmpeg进行rtsp拉流,然后转换为rtmp推流.最近ffmpeg版本进行更新后发现后端进行rtmp播放时会出现黑屏现象,但是有数据流.如果使用老版本的ffmpeg则没有 ...

  4. Android中Google Drive显示黑屏问题分析

    一.问题现象 在contacts中添加一个新的联系人,为新的联系人选择一个icon,在弹出的documents窗口中选择drive,在drive中选择一个图片,然后出现一段时间的黑屏. Platfor ...

  5. Android5.0L因SystemUI ANR导致的黑屏问题分析

    一.问题现象 1.用户直观看到的现象是黑屏. 2.出问题时StatusBar.NavigationBar和墙纸消失. 3.大部分发生在FOTA重启之后,出现概率很低. Platform:MSM8916 ...

  6. 如果计算机黑屏请分析原因是什么原因,电脑系统黑屏死机故障原因分析处理

    电脑黑屏的问题经常发生,其中的原因涉及到很多方面,网罗计算机里面所有的软件与硬件,系统死机故障多半表现为黑屏,这类故障与显示器.显示卡关系很密切,同时系统主板.CPU.CACHE.内存条,电源等部件的 ...

  7. ubuntu-开机黑屏问题分析

    1.问题 ubuntu开机黑屏 2.原因 开机黑屏一般是由于显卡驱动出现问题导致. 3.解决方法 通过ubuntu高级选项->recovery模式->resume->按esc即可进入 ...

  8. 解决Centos 7 VNC黑屏

    在配置Centos 7下VNC时发现root用户可以正常登陆VNC桌面,而普通用户VNC桌面黑屏,分析~/.vnc/xstarup 后发现是普通用户没有执行/etc/X11/xinit/xinitrc ...

  9. 戴尔G15伪黑屏(细看显示屏仍能看到电脑屏幕上的内容)的处理方式

    以下记录我戴尔电脑处理伪黑屏的一路历程,记录得有点繁琐,可以直接看问题分析思路,都根据自己情况尝试下,判断自己伪黑屏可能出的问题:也可以直接尝试我显卡驱动解决方式来处理伪黑屏. 背景 伪黑屏历程 第一 ...

最新文章

  1. .exe已停止工作_这几天我遇到了前所未有的问题windows10 1809 explorer.exe资源管理器频繁崩溃...
  2. 第 30 章 lvs-rrd
  3. NYOJ-523 亡命逃窜(三维立体的BFS)
  4. linux内核杂记(3)-进程(1)
  5. kubernetes常用对象
  6. java证明ArrayList是线程不安全的
  7. 提高ASP.NET首页性能的十大方法
  8. 吐血整理:C#顺序、选择、循环结构用法与案例,这一篇就够了!
  9. RDLC报表下载的权限问题
  10. mos管开关电路_【电路】MOS管开关电路图详解(一)
  11. PMP-全书知识重点图
  12. BAT机器学习面试题
  13. java 继承抽象类_java基础之继承,抽象类
  14. Lattice diamond 编程时工具报出 ID错误问题的解决
  15. 2018年北京信息科技大学第十届程序设计竞赛暨ACM选拔赛 C:计算几何
  16. C#窗口程序 UI模板【简约风、去边框】
  17. arm服务器安装docker及docker-compose
  18. 黑马程序员-logback.xml配置文件
  19. 餐饮酒店的存酒卡怎么使用,开发一款存酒卡的微信小程序,var d = new Date(“2021-03-12“);
  20. 【思维进阶】这些年给学员的毕业赠言(一)

热门文章

  1. 【荐】DIV+CSS仿360buy京东商城导航条
  2. win10系统修改hosts文件无法保存
  3. win10系统保存文件到桌面需要刷新才显示解决办法
  4. Text Kit框架——动态字体及cell动态高度
  5. 浮动(Floats)原理与清除浮动
  6. Cornerstone忽略不必要的文件
  7. 快来围观,又一个大厂首席架构师真正财务了
  8. 计算机领域经典故事,[转载]计算机的工作原理(1):一个经典的故事
  9. XShell使用rz上传文件 乱码
  10. matlab 贪吃的蛇,贪吃的小蛇绘本教案