ffmpeg 解码文件时的时间戳问题

实时流和普通文件

1 实时流

实时流编码时,我们一般不进行b帧编码,但是文件存储时为了减小大小,会增加b帧,实时流只带了I,P帧,那就会好很多
2 普通文件

很多文件带了b帧,所以要使用解码时间去同步,如果使用pts,很多人一定会被其时间搞混。

我们可以正确使用AVFrame 的pts 和pkt-dts 去保存正常的时间,如果不给其正确赋值,那么值就如下所示,是novalue。

那么获取pts和dts 去赋值给avframe就行了,注意时间基。如果不进行时间延时,那么文件会被cpu 快速读完,这就看cpu有多强了,当然,为了仅仅是测试,当然可以直接使用帧率,间隔时间延时就行,如果做播放器就不能这样了,我们要严格掐时间,按照秒表去对。

c 复制代码
int main()
{
	c_test test;
	std::thread t([&test]() {
		// 在这里编写你的匿名函数的代码
		std::cout << "Hello from the new thread!" << std::endl;
		test.func_init("G:/record/A1_.mp4");
		test.Start();
	});
	while (1)
	{
		AVFrame* f = test.GetData();
		if (f != NULL)
		{

			int h = f->height;
			int w = f->width;
			
			cv::Mat mat(h, w, CV_8UC3,f->data[0]);
			cv::Mat matBGR;
			cv::cvtColor(mat, matBGR,cv::COLOR_RGB2BGR/* cv::COLOR_BGR2YUV_I420*/);
			cv::imshow("show", matBGR);
			std::cout << "the pts is :" << f->pts<<std::endl;
			av_freep(&f->data[0]);
			av_frame_free(&f);
		}
		if (cv::waitKey(30) == 'q')
			break;
	}
	test.Stop();
	std::cout << "end of this thread" << std::endl;
	//test.func_seek(10);
	t.join();
}

以上代码的RGB到BGR的转化其实没有必要使用, 实际播放的时候,我们直接渲染RGB24,RGBA,甚至YUV,NV12 都可以,这里为了方便,把这个转化成了BGR24,不过是想让opencv 直接渲染,由于opencv 中 bgr的rgb的颜色交换,播放时看起来不舒服,所以转化一下更符合实际,不转化也没什么。如果不想转化,甚至直接使用nv12,yuv420,rgb24,为了方便演示可以使用sdl去播放,如果对opengl熟悉,自己就写一段代码去播放。文章可以到我其他的文章里面找,我应该都写过。

正确的播放延时

获取时间基

c 复制代码
	AVRational time_base = input_ctx->streams[video_stream]->time_base;
	AVRational time_base_q = { 1,AV_TIME_BASE }; // AV_TIME_BASE_Q;

要正确播放,一定要使用dts,也就是解码时间,而非pts,对于带b帧的视频来说一定是如此。

c 复制代码
if (v_isrealtime == false && video_stream == packet.stream_index)
{
	//这里需要更加精确的计算
	if (v_starttime == -1)
		v_starttime = av_gettime();
	//av_usleep(30 * 1000);
	int64_t pts_time = av_rescale_q(packet.dts, time_base, time_base_q);
	if (v_startptstime == -1)
		v_startptstime = pts_time;
	int64_t N = av_gettime() - v_starttime;
	int64_t S = pts_time - v_startptstime;
	if (S > N)
	{
		av_usleep(S-N);
		std::cout << "sleep:" << S - N << std::endl;
	}
}

播放测试的时候可以使用pc上有秒表卡住时间,没有就使用手机也可以,两个相差一直是同样的描述,持续时间长一点

正确的同步

同步时一定要使用系统时间和播放时间相对应,如果文件有跳帧拖拉进度条和快放的需求,更加要注意,其实以上代码已经包含了跳帧和快放的基本需求,研究一下就知道了。

相关推荐
hjjdebug2 天前
ffplay6 播放器关键技术点分析 1/2
c++·ffmpeg·音视频
泰勒朗斯2 天前
ffmpeg 中config 文件一些理解
windows·microsoft·ffmpeg
泰勒朗斯2 天前
ffmpeg下编译tsan
ffmpeg
xmode4 天前
centos7.9安装ffmpeg6.1和NASM、Yasm、x264、x265、fdk-aac、lame、opus解码器
ffmpeg·centos
王江奎4 天前
FFmpeg 升级指北
ffmpeg
雨夜和阳晨4 天前
FFmpeg录制屏幕及声音
ffmpeg
吴声子夜歌4 天前
FFmpeg——基础知识及FFmpeg框架
ffmpeg
aqi005 天前
FFmpeg开发笔记(七十二)Linux给FFmpeg集成MPEG-5视频编解码器EVC
android·ffmpeg·音视频·流媒体
不太会编程的IT男6 天前
在 Jetson Orin 开发套件上使用 Hardware Encoder / Decoder 构建 FFmpeg
ffmpeg·视频编解码·h.264
m0_687399846 天前
写一个Ununtu C++ 程序,调用ffmpeg API, 来判断一个数字电影的视频文件mxf 是不是Jpeg2000?
开发语言·c++·ffmpeg