本节介绍如何通过第三方工具浏览视频画面和分析视频格式,首先描述通用音视频播放器VLC media player的详细安装过程,以及如何使用VLC media player播放视频文件;然后叙述视频格式分析工具Elecard StreamEye的详细安装过程,以及如何使用Elecard StreamEye分析视频格式;最后阐述如何把原始的H264文件封装为MP4格式的视频文件。
VLC media player是一款跨平台的音视频播放器,它不但跨平台,而且开源,还兼容多语言,且与FFmpeg深度融合,几乎支持所有的音视频格式。除常见的音视频文件外,VLC media player也能播放未经MP4封装的H.264裸流,以及RTSP、RTMP等网络串流,实属音视频开发者的必备工具。
有两个途径可以获取VLC media player的安装包及其源码资源,其中一个是VideoLAN官方网站,另一个是VLC的GitHub主页。VideoLAN的官方网站地址是https://www.videolan.org/vlc/,各版本VLC安装包的下载入口在https://download.videolan.org/pub/videolan/vlc/,VLC最新源码的下载页面是https://www.videolan.org/vlc/download-sources.html。VLC的GitHub主页地址是https://github.com/videolan/vlc,该地址也是VLC的最新源码入口页面,各版本VLC安装包的下载入口在https://github.com/videolan/vlc/tags。由于GitHub网络不稳定,主页时常打不开,因此推荐到VideoLAN官方网站下载VLC的安装包及其最新源码。
VLC的安装包分为Win32、Win64、Mac OS X、Linux等多个系统版本,注意下载与自己计算机系统吻合的VLC安装包。以Win64版本为例,VLC media player 3.0.18 在2022年11月发布,它的下载地址是https://download.videolan.org/pub/videolan/vlc/3.0.18/win64/vlc-3.0.18-win64.exe,使用浏览器打开该地址,会自动定位到最佳网络的镜像地址下载。等待VLC下载完成,双击打开安装包,弹出语言选择窗口,如图3-4所示。
图3-4 VLC的语言选择窗口
语言选择窗口保持默认的“中文(简体)”,单击窗口下方的OK按钮,打开安装向导窗口,如图3-5所示。单击向导窗口右下角的“下一步”按钮,跳转到许可协议窗口,如图3-6所示。
图3-5 VLC的安装向导窗口
图3-6 VLC的许可协议窗口
单击许可协议窗口右下角的“下一步”按钮,跳转到选择组件窗口,如图3-7所示。单击选择组件窗口右下角的“下一步”按钮,跳转到选择安装位置窗口,如图3-8所示,在此可更改VLC的安装路径。
单击选择位置窗口右下角的“安装”按钮,跳转到正在安装窗口,如图3-9所示。等待安装完毕,自动跳到安装结束窗口,如图3-10所示。
图3-7 VLC的选择组件窗口
图3-8 VLC的选择安装位置窗口
图3-9 VLC的正在安装窗口
图3-10 VLC的安装结束窗口
单击结束窗口右下角的“完成”按钮,即可启动安装完成的VLC media player,该播放器的初始界面如图3-11所示。依次选择VLC的菜单“媒体”→“打开文件”,在弹出的“文件”对话框中选择某个视频文件(比如output_recode.mp4),即可观看视频的播放画面,如图3-12所示。
图3-11 VLC的初始界面
图3-12 VLC的播放画面
除通过VLC的顶部菜单打开视频文件外,还可以在计算机的文件保存目录下右击某个视频文件,并在弹出的快捷菜单中依次选择“打开方式”→VLC media player,如图3-13所示,也能启动VLC media player播放该视频。
图3-13 在快捷菜单中打开VLC
虽然通过播放器可以检查视频文件能否正常播放,但是播放器毕竟不是分析工具,无法逐帧分析视频的每个画面。对于采用H.264编码的视频而言,可使用专门的视频格式分析工具Elecard StreamEye,该工具的官方网站地址是https://www.elecard.com/products/video-analysis/streameye,国内软件站收录的下载页面为https://www.onlinedown.net/soft/51003.htm。
Elecard StreamEye的安装包下载之后,双击安装包弹出如图3-14所示的安装向导窗口。单击窗口右下角的Next按钮,跳转到重要信息窗口,如图3-15所示。
图3-14 StreamEye的安装向导窗口
图3-15 StreamEye的重要信息窗口
单击重要信息窗口右下角的Next按钮,跳转到许可协议窗口,如图3-16所示。勾选该窗口左下角的Yes...复选框,再单击窗口右下角的Next按钮,跳转到安装位置窗口,如图3-17所示,在此可更改Elecard StreamEye的安装路径。
图3-16 StreamEye的许可协议窗口
图3-17 StreamEye的安装位置窗口
单击安装位置窗口右下角的Next按钮,跳转到程序组窗口,如图3-18所示。单击程序组窗口右下角的Next按钮,跳转到准备开始窗口,如图3-19所示。
图3-18 StreamEye的程序组窗口
图3-19 StreamEye的准备开始窗口
单击准备开始窗口右下角的Next按钮,Elecard StreamEye就开始安装操作,等待安装完毕,会跳转到如图3-20所示的安装结束窗口,单击右下角的Finish按钮结束安装过程。
图3-20 StreamEye的安装结束窗口
双击Elecard StreamEye安装路径下的可执行程序eseye_u.exe,打开Elecard StreamEye的初始界面,如图3-21所示。
图3-21 StreamEye的初始界面
依次选择顶部菜单File→Open,在弹出的“文件”对话框中选择某个视频文件(比如output_recode2.mp4),即可打开视频分析界面,如图3-22所示。
图3-22 StreamEye的视频分析界面
同时Elecard StreamEye打开两个窗口,如图3-23和图3-24所示,其中图3-23为视频帧的预览窗口,在主界面单击选择某个柱子,预览窗口就会切换到该柱子对应的帧画面。图3-24是信息窗口,展示该视频的规格参数,比如文件类型(file type)、视频编码标准(video stream type)、分辨率(resolution)、帧数量(frames count)等。
图3-23 StreamEye的视频预览窗口
图3-24 StreamEye的视频信息窗口
现在有了Elecard StreamEye能够分析H.264视频,还有H.265视频可通过Elecard HEVC Analyzer分析。HEVC Analyzer的GitHub源码地址为https://github.com/lheric/GitlHEVCAnalyzer,有兴趣的读者可自行体验。
从摄像头传出的视频流往往是未被封装的H264数据,这类视频流保存为文件的话,其扩展名通常为.264或者.h264。像这种尚未封装的原始264文件,大部分视频播放器都不能正常打开,只有使用VLC media player才能正常播放。
.h264裸流文件之所以无法被其他播放器打开,是因为原始的H264数据缺少时间戳,播放器不知道该在哪个时间点显示哪幅视频画面。为了让播放器能够正确识别各帧的时间位置,要通过FFmpeg代码对未定义的时间戳重新赋值,将pts、dts、duration等字段按照时间基重新计算。根据3.2.2节推出来的时间戳转换式子,假设某个以秒为单位的时间点为A,则其对应的时间戳=A÷av_q2d(time_base)。那么各个视频包的时间戳即可根据对应的序号计算而来,下面是对视频包重新赋值时间戳的FFmpeg代码片段(完整代码见chapter03/mux264.c)。
int packet_index = 0; // 数据包的索引序号 AVStream *in_stream = NULL, *out_stream = NULL; AVPacket *packet = av_packet_alloc(); // 分配一个数据包 while (av_read_frame(in_fmt_ctx, packet) >= 0) { // 轮询数据包 if (packet->stream_index == video_index) { // 视频包 packet->stream_index = 0; in_stream = in_fmt_ctx->streams[video_index]; out_stream = out_fmt_ctx->streams[video_index]; } else if (packet->stream_index == audio_index) { // 音频包 packet->stream_index = 1; in_stream = in_fmt_ctx->streams[audio_index]; out_stream = out_fmt_ctx->streams[audio_index]; } // 摄像头直接保存的.h264文件,重新编码时得另外加时间戳 if (packet->stream_index == 0 && packet->pts == AV_NOPTS_VALUE) { // 未定义的时间戳 // 计算两帧之间的间隔。如果帧率为25,那么两帧间隔0.04秒 double interval = 1.0 / av_q2d(in_stream->r_frame_rate); // 给各帧的时间戳重新赋值 packet->pts = packet_index*interval / av_q2d(in_stream->time_base); packet->dts = packet->pts; packet->duration = interval / av_q2d(in_stream->time_base); packet_index++; } // 把数据包的时间戳从一个时间基转换为另一个时间基 av_packet_rescale_ts(packet, in_stream->time_base, out_stream->time_base); ret = av_write_frame(out_fmt_ctx, packet); // 往文件写入一个数据包 if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "write frame occur error %d.\n", ret); break; } av_packet_unref(packet); // 清除数据包 } av_write_trailer(out_fmt_ctx); // 写文件尾
接着执行下面的编译命令:
gcc mux264.c -o mux264 -I/usr/local/ffmpeg/include -L/usr/local/ffmpeg/lib -lavformat -lavdevice -lavfilter -lavcodec -lavutil -lswscale -lswresample -lpostproc -lm
编译完成后,执行以下命令启动测试程序,期望把H264裸流文件封装为MP4文件。
./mux264 ../test.264
程序运行完毕,发现控制台输出以下日志信息,说明完成了给H264文件添加时间戳的操作。
Success open input_file ../test.264. Success open output_file output_mux264.mp4. Success mux file.
最后打开影音播放器可以正常播放output_mux264.mp4,表明上述代码正确实现了将H264文件封装为MP4文件的功能。
运行下面的ffmpeg命令也可以把H.264编码的视频裸流封装为MP4格式。命令中的-f h264表示输入源为H.264格式的文件。
ffmpeg -f h264 -i ../test.264 -vcodec copy ff_package.mp4