音视频BUG学习

news2024/11/20 14:26:47

找Bug流程

1、首先看出现概率是偶现还是必现
2、如果是必现,则复现整个bug过程,看Bug是否出现
如果是偶现,则分析问题视频
3、

问题一 【欧立】【远程抓拍】安卓-远程抓拍的视频,下载到手机本地相册,声音慢放

一、额外知识学习

在复现问题过程中,刚开始没下载到本地,直接点击播放发生慢放,因为流量网速较低,15s,40Mb 平均网速要超过2.7Mb/s,因此误以为复现了bug

二、解决过程

0 问题复现

找设备抓拍,下载,发现视频没有问题,Bug无法复现

0 简单分析

分析源文件
在这里插入图片描述

可能在本地转码过程(转码过程可能发生在本地也可能发生在服务器端)中 数据丢失,也可能是ADTS头部,通道数自动转换

1 mp4文件提取出h264/h265

播放没问题

ffmpeg -i test.mp4 -map 0:v:1 -c:v copy video.h264
ffmpeg -i test.mp4 -map 0:v:0 -c:v copy video.h265

-i test.mp4: 指定输入文件为 test.mp4。-i 是指定输入文件的选项,后面跟着输入文件的路径。
-map 0:v:0: 使用 -map 选项选择输入文件中的第一个视频流。0 表示第一个输入文件,v 表示视频流,0 表示第一个视频流。
-c:v copy: 使用 -c:v 选项指定视频流的编码方式为 “copy”,表示直接复制视频流而不进行重新编码。这意味着输出文件将与输入文件的视频流完全相同,不会更改编码格式或参数。

2 mp4文件中提取aac

ffmpeg -i test1.mp4 -vn -acodec copy test1.aac

3 aac转码为pcm

ffmpeg -i BadAAC.aac -acodec pcm_s16le -ar 32000 -f s16le Bad.pcm

4 分析pcm

在这里插入图片描述

数据被置0,正常应该是较为连续的
因为是必现,估计是pcm数据拷贝,长度计算不对,只拷贝了一半数据,剩下的一半是内存中初始化的0值

三、解决方案

无法复现Bug,Bug已不存在

问题二 【欧立】【本地录像】本地视频偶现轻微花屏

一、额外知识学习

花屏出现可能原因

(1)丢帧会报错

模拟过程,在aac和h264复用为mp4的过程中,故意丢没100帧丢一帧,用ffplay播放出现报错

复用代码

#include <stdio.h>
#include <iostream>
extern "C"
{
#include "libavformat/avformat.h"
};

int main(int argc, char* argv[])
{
	AVFormatContext* ifmtCtxVideo = NULL, * ifmtCtxAudio = NULL, * ofmtCtx = NULL;
	AVCodecContext* video_ctx = NULL;
	AVPacket packet;
	AVCodec* video_codec = NULL;
	//AVBSFContext* bsf_ctx = nullptr;
	const AVBitStreamFilter* pfilter = av_bsf_get_by_name("h264_mp4toannexb");
	AVBitStreamFilterContext* h264bsfc = av_bitstream_filter_init("h264_mp4toannexb");
	//av_bsf_alloc(pfilter, &bsf_ctx);

	int inVideoIndex = -1, inAudioIndex = -1;
	int outVideoIndex = -1, outAudioIndex = -1;

	int audioindex = 0;
	int videoindex = 0;
	int idx = 0;
	
	int64_t curPstVideo = 0, curPstAudio = 0;

	int ret = 0;
	unsigned int i = 0;

	const char* inFilenameVideo = "Titanic.h264";
	const char* inFilenameAudio = "Titanic.aac";
	const char* outFilename = "MissFrame.mp4";

	//打开输入视频文件
	ret = avformat_open_input(&ifmtCtxVideo, inFilenameVideo, 0, 0);
	if (ret < 0)
	{
		printf("can't open input video file\n");
		goto end;
	}

	//查找输入流
	ret = avformat_find_stream_info(ifmtCtxVideo, 0);
	if (ret < 0)
	{
		printf("failed to retrieve input video stream information\n");
		goto end;
	}

	//打开输入音频文件
	ret = avformat_open_input(&ifmtCtxAudio, inFilenameAudio, 0, 0);
	if (ret < 0)
	{
		printf("can't open input audio file\n");
		goto end;
	}

	//查找输入流
	ret = avformat_find_stream_info(ifmtCtxAudio, 0);
	if (ret < 0)
	{
		printf("failed to retrieve input audio stream information\n");
		goto end;
	}

	printf("===========Input Information==========\n");
	av_dump_format(ifmtCtxVideo, 0, inFilenameVideo, 0);
	av_dump_format(ifmtCtxAudio, 0, inFilenameAudio, 0);
	printf("======================================\n");

	//新建输出上下文
	avformat_alloc_output_context2(&ofmtCtx, NULL, NULL, outFilename);
	if (!ofmtCtx)
	{
		printf("can't create output context\n");
		goto end;
	}

	//视频输入流
	for (i = 0; i < ifmtCtxVideo->nb_streams; ++i)
	{
		if (ifmtCtxVideo->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
		{
			AVStream* inStream = ifmtCtxVideo->streams[i];
			AVStream* outStream = avformat_new_stream(ofmtCtx, NULL);
			//av_dump_format(ofmtCtx, 0, outFilename, 1);
			inVideoIndex = i;

			if (!outStream)
			{
				printf("failed to allocate output stream\n");
				goto end;
			}

			outVideoIndex = outStream->index;

			if (avcodec_parameters_copy(outStream->codecpar, inStream->codecpar) < 0)
			{
				printf("faild to copy context from input to output stream");
				goto end;
			}

			outStream->codecpar->codec_tag = 0;
			//av_dump_format(ofmtCtx, 0, outFilename, 1);
			break;
		}
	}
	video_ctx = avcodec_alloc_context3(video_codec);
	video_codec = avcodec_find_decoder(ifmtCtxVideo->streams[0]->codecpar->codec_id);

	video_ctx = ifmtCtxVideo->streams[0]->codec;
	//音频输入流
	for (i = 0; i < ifmtCtxAudio->nb_streams; ++i)
	{
		if (ifmtCtxAudio->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
		{
			AVStream* inStream = ifmtCtxAudio->streams[i];
			AVStream* outStream = avformat_new_stream(ofmtCtx, NULL);
			inAudioIndex = i;

			if (!outStream)
			{
				printf("failed to allocate output stream\n");
				goto end;
			}

			if (avcodec_parameters_copy(outStream->codecpar, inStream->codecpar) < 0)
			{
				printf("faild to copy context from input to output stream");
				goto end;
			}
			outAudioIndex = outStream->index;

			break;
		}
	}

	printf("==========Output Information==========\n");
	av_dump_format(ofmtCtx, 0, outFilename, 1);
	printf("======================================\n");
	//打开输入文件
	if (!(ofmtCtx->oformat->flags & AVFMT_NOFILE))
	{
		if (avio_open(&ofmtCtx->pb, outFilename, AVIO_FLAG_WRITE) < 0)
		{
			printf("can't open out file\n");
			goto end;
		}
	}

	//写文件头
	if (avformat_write_header(ofmtCtx, NULL) < 0)
	{
		printf("Error occurred when opening output file\n");
		goto end;
	}

	while (1)
	{
		AVFormatContext* ifmtCtx = NULL;
		AVStream* inStream, * outStream;
		int streamIndex = 0;
		if (av_compare_ts(curPstVideo, ifmtCtxVideo->streams[inVideoIndex]->time_base, curPstAudio, ifmtCtxAudio->streams[inAudioIndex]->time_base) < 0)
		{
			ifmtCtx = ifmtCtxVideo;
			streamIndex = outVideoIndex;

			if (av_read_frame(ifmtCtx, &packet) >= 0)
			{
				//printf("Video start packet.pts = %d \n\n", packet.pts);
				inStream = ifmtCtx->streams[packet.stream_index];
				//printf("Video sample_rate = %\n", inStream->codecpar->sample_rate);
				outStream = ofmtCtx->streams[streamIndex];
				if (packet.stream_index == inVideoIndex)
				{
					av_bitstream_filter_filter(h264bsfc, ifmtCtxVideo->streams[0]->codec, NULL, &packet.data, &packet.size, packet.data, packet.size, 0);
					// Fix: No PTS(Example: Raw H.264
					// Simple Write PTS
					//printf("Video PTS: %ld\n", packet.pts);
					//printf("Video DTS: %ld\n", packet.dts);
					if (packet.pts == AV_NOPTS_VALUE)
					{
						//write PTS
						AVRational timeBase1 = inStream->time_base;
						//Duration between 2 frames
						double calcDuration = (double)1.0 / av_q2d(inStream->r_frame_rate);
						//Parameters 转化为
						//printf("Video calcDuration =  %lf\n", calcDuration);
						packet.pts = (double)(videoindex * calcDuration) / (double)(av_q2d(timeBase1));
						packet.dts = packet.pts;
						packet.duration = (double)calcDuration / (double)(av_q2d(timeBase1));
						videoindex++;
						//printf("Video PTS: %ld\n", packet.pts);
						//printf("Video DTS: %ld\n", packet.dts);
					}
					curPstVideo = packet.pts;
				}
			}
			else
			{
				break;
			}
		}
		else
		{
			ifmtCtx = ifmtCtxAudio;
			streamIndex = outAudioIndex;
			if (av_read_frame(ifmtCtx, &packet) >= 0)
			{
				//printf("Audio start packet.pts = %d \n\n", packet.pts);
				inStream = ifmtCtx->streams[packet.stream_index];
				outStream = ofmtCtx->streams[streamIndex];
				//printf("Audio PTS: %ld\n", packet.pts);
				//printf("Audio DTS: %ld\n", packet.dts);
				if (packet.stream_index == inAudioIndex)
				{
					//Fix: No PTS(Example: Raw H.264
					//Simple Write PTS
					AVRational timeBase1 = inStream->time_base;
					//printf("timeBase = %.15lf\n", (double)(av_q2d(timeBase1)));
					//Duration between 2 frames

					double calcDuration =  (double)1024.0 / inStream->codecpar->sample_rate;
					//printf("Audio calcDuration =  %lf\n", calcDuration);
					packet.pts = (double)(audioindex * calcDuration) / (double)(av_q2d(timeBase1));
					packet.dts = packet.pts;
					packet.duration = (double)calcDuration / (double)(av_q2d(timeBase1));
					audioindex ++;
					//printf("Audio PTS: %ld\n", packet.pts);
					//printf("Audio DTS: %ld\n", packet.dts);
					curPstAudio = packet.pts;
				}
			}
			else
			{
				break;
			}
		}
		//FIX:Bitstream Filter

		//Convert PTS/DTS
		packet.pts = av_rescale_q_rnd(packet.pts, inStream->time_base, outStream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
		packet.dts = av_rescale_q_rnd(packet.dts, inStream->time_base, outStream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
		packet.duration = av_rescale_q(packet.duration, inStream->time_base, outStream->time_base);
		packet.pos = -1;
		packet.stream_index = streamIndex;
		//write
		// printf("Audio sample_rate =  %d \n\n", inStream->codecpar->sample_rate);
		if (streamIndex == outVideoIndex)++idx;
		if(streamIndex == outVideoIndex && (idx % 100 == 0))  continue;

		if (av_interleaved_write_frame(ofmtCtx, &packet) < 0)
		{
			printf("error muxing packet");
			break;
		}
		av_packet_unref(&packet);
		
	}
	printf("idx = %d\n", idx);
	av_write_trailer(ofmtCtx);//写文件尾

end:
	avformat_close_input(&ifmtCtxVideo);
	avformat_close_input(&ifmtCtxAudio);
	if (ofmtCtx && !(ofmtCtx->oformat->flags & AVFMT_NOFILE))
		avio_close(ofmtCtx->pb);
	avformat_free_context(ofmtCtx);

	return 0;
}

结果

ffplay C:\Users\Administrator\Desktop\VideoDemo\MissFrame.mp4

在这里插入图片描述

(2)无丢帧不会报错

据没有报错但是有花屏的情况,推断是动态画面采样时,码率没有上去造成数据采样不足出现马赛克。需要设备在编码动态画面时把码率动态(vbr码率,静态是cbr,均衡生abr)搞上去。

二、解决过程

三、解决方案

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/686344.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【前端笔记】如何更新项目依赖

Node 软件包管理器&#xff08;NPM&#xff09;提供了各种功能来帮助你安装和维护项目的依赖关系。 由于错误修复、新功能和其他更新&#xff0c;依赖关系可能会随着时间的推移而变得过时。你的项目依赖越多&#xff0c;就越难跟上这些更新。 有时&#xff0c;新的软件包并不…

vm安装使用centos-7安装linux

1. 安装源&#xff0c;选择默认 2. 将网络和主机名&#xff08;以太网&#xff09;打开 3. 设置DHCP的租约 注&#xff1a;如果修改不了那么点击更改设置即可 4. 服务端口号&#xff1a;22 5. 常见报错以及解决方法 6. 安装目录 7. ip位置 8. 换源步骤&#xff08;乌班图的版…

machine code中的条件控制control flow和switch语句,循环Loop

上篇写了machine code基本知识概念&#xff0c;这篇再总结一下其中的流控制、条件判断&#xff0c;循环等实现。 一段machine code引出 在machine code中&#xff0c;通场使用jmp指令来跳转到某个代码块。比如一个机器码可能长这样&#xff1a; decision:subq $8, %rsptestl…

Synchronized锁

概览 锁的实现基于对象头重的MarkWord&#xff0c;分为 无锁 -> 偏向锁 -> 轻量锁 -> 重量锁 四个状态 状态转换 锁的获取与释放 模型&#xff1a; Markword&#xff1a;指向Monitor的指针Monitor&#xff1a;_cxq&#xff0c;_EntryList,_WaitSet,owner,_recurs…

提高透明LED屏幕显示效果设计指南

设计透明LED屏幕时&#xff0c;可以考虑以下几个因素来提高显示效果&#xff1a; 透明度和亮度&#xff1a;透明LED屏幕的设计目标是实现高透明度和足够的亮度。透明度取决于使用的材料和LED的布局方式。选择高透明度的材料&#xff0c;并确保LED的亮度足够高&#xff0c;以确保…

写给毕业季的学生们|我的五次 offer 选择经历

最近临近毕业季&#xff0c;群里有好多朋友在问面试和 offer 选择的问题&#xff0c;我分享下我过往的相关经历&#xff0c;希望能给各位朋友有所启发。 我是谁&#xff1f; 大家好&#xff0c;我是拭心&#xff0c;内蒙古人&#xff0c;16 年本科毕业于西安电子科技大学&#…

AWTK学习笔记

编译&#xff1a;scons 运行&#xff1a;.\bin\demo.exe xml文件存放在工程的design\default\ui文件夹内 c文件存放在工程的src文件夹内 如果代码没有指定修改&#xff0c;默认按照AWTK Designer设置的控件属性动作运行 API函数查看使用说明&#xff1a;https://awtk.zlg.cn/ap…

Pytorch ----注意力机制与自注意力机制的代码详解与使用

注意力机制的核心重点就是让网络关注到它更需要关注的地方 。 当我们使用卷积神经网络去处理图片的时候&#xff0c; 我们会更希望卷积神经网络去注意应该注意的地方&#xff0c;而不是什么都关注 &#xff0c;我们不可能手动去调节需要注意的地方&#xff0c;这个时候&#x…

centos 7.9离线下载安装vscode,以及插件安装下载

文章目录 一、软件的下载1.采取的方法2.下载相应压缩包3.安装过程4.相关知识 二、插件的安装和下载1.查看vscode的版本号2.查找插件的版本号3.安装vscode插件 三、vscode以及依赖安装包&#xff0c;常用插件百度云&#xff1a; 一、软件的下载 1.采取的方法 从一台联网的cento…

SpringBoot2概览-开发实用篇

知识点 热部署 概念&#xff1a;项目刚启动时需要完成重启重载&#xff0c;而热部署只要重启即可(即仅加载当前开发者自定义开发的资源&#xff0c;不加载jar资源) 重启&#xff1a;加载自定义开发代码&#xff0c;包含类、页面、配置文件等&#xff0c;加载位置在restart类加载…

springboot项目如何将配置文件外挂

为什么要将配置文件外挂 因为springboot项目一般打出来的是jar包&#xff0c;如果要对里面的配置做修改&#xff0c;会比较麻烦&#xff0c;所以需要将配置文件外挂&#xff0c;方便操作哦 怎么做呢 我们先看一个常见的springboot项目的配置文件结构&#xff1a; 分为四个配…

InnoDB的三种行锁(提供具体sql执行案例分析)

InnoDB存储引擎有3种行锁的算法&#xff0c;其分别是&#xff1a; Record Lock&#xff08;记录锁&#xff09;&#xff1a;单个行记录上的范围 (锁住某一行记录)Gap Lock&#xff08;间隙锁&#xff09;&#xff1a;间隙锁&#xff0c;锁定一个范围&#xff0c;但不包含记录本…

十大公认音质好的骨传导耳机,几款音质排行靠前的骨传导耳机

骨传导耳机是通过头部骨迷路传递声音&#xff0c;而不是直接通过耳膜的振动来传递声音。与传统的入耳式耳机相比&#xff0c;骨传导耳机不会堵耳朵&#xff0c;在跑步、骑车等运动时可以更好的接收外界环境音&#xff0c;保护听力&#xff0c;提升安全性。此外&#xff0c;骨传…

Canvas基本使用

1.canvas基本使用 1.1.说明&#xff1a; canvas是双标签,h5中新增的属性默认宽高为300*150浏览器默认canvas展示的是一张图片给canvas添加文字内容是没有任何意义的canvas画布&#xff1a;绘制图形&#xff0c;显示一个文字&#xff0c;必须通过js操作 不要通过样式去设置画…

15.OCR

15.1 OCR流水线及七工作原理 Photo OCR&#xff1a;照片 光学字符识别(photo optical character recognition) Photo OCR注重的问题&#xff1a;如何让计算机都出图片中的文字信息&#xff0c;它有以下步骤&#xff1a; 首先给定某张图片&#xff0c;它将图像扫描一遍&#…

基于小程序的用户服务技术研究

目录 1. 小程序开发技术原理 2. 用户服务设计3. 数据库设计和管理4. 安全和隐私保护5. 性能优化和测试总结 关于基于小程序的用户服务技术研究&#xff0c;这是一个非常广泛和复杂的领域&#xff0c;需要涉及多个方面的知识和技术。一般来说&#xff0c;基于小程序的用户服务技…

零基础想入门网安行业,看这一篇就够了!!!

由于我之前写了不少网络安全技术相关的故事文章&#xff0c;不少读者朋友知道我是从事网络安全相关的工作&#xff0c;于是经常有人在微信里问我&#xff1a; 我刚入门网络安全&#xff0c;该怎么学&#xff1f;要学哪些东西&#xff1f;有哪些方向&#xff1f;怎么选&#xff…

跟着AIGC学Linux:简介(一)

文章目录 1.Linux内核的历史2.基本概念3.发行版4.Linux应用领域5.Linux VS Windows横向对比表格&#xff1a; 1.Linux内核的历史 Linux内核最初由一位名叫Linus Torvalds的芬兰计算机科学家于1991年创建。当时&#xff0c;Torvalds是一名赫尔辛基大学的学生&#xff0c;他在寻…

ROS:话题通信机制详解

目录 ROS&#xff1a;通信机制一、话题通信简介二、话题通信实操&#xff08;C&#xff09;2.1分析2.2发布方代码2.3订阅方代码2.4配置CMakeLists.txt2.5执行2.6注意 三、话题通信实操&#xff08;python&#xff09;3.1分析3.2发布方代码3.3订阅方代码3.4添加可执行权限3.5配置…

Apache Log4j2 漏洞原理

Apache Log4j 远程代码执行漏洞 1.漏洞危害 Apache Log4j被发现存在一处任意代码执行漏洞&#xff0c;由于Apache Log4j2某些功能存在递归解析功能&#xff0c;攻击者可直接构造恶意请求&#xff0c;触发远程代码执行漏洞。经验证&#xff0c;Apache Struts2、Apache Solr、Ap…