使用X264编码器编码及ijkplayer解码时如何查看I/P/B帧序列
嗨,我来帮你搞定这两个问题,下面分两部分详细说明:
你可以用以下几种工具快速查看编码后视频的帧类型序列:
用ffprobe命令行工具
这是最便捷的方法,直接用ffprobe解析视频文件的帧信息:ffprobe -show_frames -select_streams v:0 你的输出文件名 | grep pict_type执行后会逐行输出每一帧的类型,比如
pict_type=I、pict_type=P、pict_type=B,按顺序排列就是完整的帧序列。编码时让x264输出详细日志
你可以在原编码命令里加上--verbose参数,让x264在编码过程中输出帧的详细信息:x264 --crf 23 --tune fastdecode --fps 64 --keyint 1 --min-keyint 1 --no-scenecut --input-res 4096*2048 --bframes 3 --verbose -o filename 你的输入文件日志里会包含每帧的类型记录,你可以直接在控制台查看,或者把输出重定向到文件里后续分析:
x264 ... --verbose 2>&1 | tee encode_log.txt之后在
encode_log.txt里搜索frame type就能找到逐帧的类型信息。用MediaInfo工具
如果偏好图形界面,MediaInfo可以直观展示帧类型的分布和序列。安装后打开你的视频文件,切换到“帧”选项卡就能看到完整的帧类型序列;如果用命令行版本,执行:mediainfo --Output="Video;%FrameCount% frames: %FrameTypeList%" 你的输出文件名会输出所有帧类型的列表。
ijkplayer默认没有直接提供查看帧类型的接口,不过可以通过两种方式实现:
修改ijkplayer源码输出日志
找到ijkplayer中调用ffmpeg解码的代码段(通常在ijkplayer/ffmpeg/相关目录下),当解码得到AVFrame后,通过av_frame_get_pict_type(frame)获取帧类型,然后将其转换成对应的字符输出日志。比如在Android端可以用__android_log_print,示例代码大概是:enum AVPictureType pict_type = av_frame_get_pict_type(frame); char type_char = '?'; switch(pict_type) { case AV_PICTURE_TYPE_I: type_char = 'I'; break; case AV_PICTURE_TYPE_P: type_char = 'P'; break; case AV_PICTURE_TYPE_B: type_char = 'B'; break; default: break; } __android_log_print(ANDROID_LOG_INFO, "ijkplayer-frame", "Frame type: %c", type_char);重新编译ijkplayer后,就能在Logcat里看到每帧的类型了。
上层封装API获取帧类型
如果不想修改底层源码,你可以在应用层通过ijkplayer的渲染回调来间接获取。比如在Android的IjkMediaPlayer中设置OnFrameAvailableListener,在回调里拿到帧数据后,通过JNI调用底层的方法获取帧类型(需要自己写JNI桥接代码),不过这种方式相对麻烦一些,不如直接修改源码来得直接。
内容的提问来源于stack exchange,提问作者MSD Paul




