@ltlovezh
2019-08-21T02:10:52.000000Z
字数 11988
阅读 4557
ffmpeg
ffprobe是ffmpeg提供的三大工具之一,用来查看音视频文件的各种信息,比如:封装格式、音频/视频流信息、数据包信息等。
ffprobe的源码是ffprobe.c,开发过程中如果想获取ffprobe查看的信息,可以通过分析源码,获得对应字段。 本文主要介绍format、stream、Packet和Frame信息,包含每个字段的说明以及对应的ffmpeg字段。
ffprobe -show_format inputFile
输出如下信息:
[FORMAT]// 文件名filename=VID_20190811_113717.mp4// 容器中流的个数,即AVFormatContext->nb_streamsnb_streams=2// 即AVFormatContext->nb_programsnb_programs=0// 封装格式,即AVFormatContext->iformat->nameformat_name=mov,mp4,m4a,3gp,3g2,mj2// 即AVFormatContext->iformat->long_nameformat_long_name=QuickTime / MOV// 即AVFormatContext->start_time,基于AV_TIME_BASE_Q,换算为秒start_time=0.000000// 即AVFormatContext->duration,基于AV_TIME_BASE_Q,换算为秒duration=10.508000// 单位字节,即avio_size(AVFormatContext->pb)size=27263322// 码率,即AVFormatContext->bit_ratebit_rate=20756240// 即AVFormatContext->probe_scoreprobe_score=100[/FORMAT]
ffprobe -show_streams inputFile
输出如下信息:
[STREAM]// 当前流的索引信息,对应于AVStream->indexindex=0// AVCodecDescriptor * cd = avcodec_descriptor_get(AVStream->codecpar->codec_id)// 编码名称,即cd->namecodec_name=h264// 编码全称,即cd->long_namecodec_long_name=H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10// 一个编码参数,可以为Baseline、Main、High等,Baseline无B帧,Main及以后可以包含B帧// 通过avcodec_profile_name(AVStream->codecpar->codec_id, AVStream->codecpar->profile)获得profile=High// 流类型,即av_get_media_type_string(AVStream->codecpar->codec_type)codec_type=video// 即AVStream->codec->time_basecodec_time_base=14777/877500// 通过宏av_fourcc2str(AVStream->codecpar->codec_tag)获得codec_tag_string=avc1// 对应AVStream->codecpar->codec_tagcodec_tag=0x31637661// 有效区域的宽度,即AVStream->codecpar->widthwidth=1920// 有效区域的高度,即AVStream->codecpar->heightheight=1080// 视频帧宽度,可能与上面的宽度不同,即AVStream->codec->coded_width,例如:当解码帧在输出前裁剪或启用低分辨率时coded_width=1920// 视频帧高度,可能与上面的高度不同,即AVStream->codec->coded_height,例如:当解码帧在输出前裁剪或启用低分辨率时coded_height=1088// 视频的延迟帧数,即AVStream->codecpar->video_delayhas_b_frames=0// sar,图像采集时,横向采集点数与纵向采集点数的比例// FFmpeg提供了多个sar:AVStream->sample_aspect_ratio、AVStream->codecpar->sample_aspect_ratio、AVFrame->sample_aspect_ratio// 通过av_guess_sample_aspect_ratio获取最终的sarsample_aspect_ratio=1:1// dar,真正展示的图像宽高比,在渲染视频时,必须根据这个比例进行缩放// 通过av_reduce计算得到,par * sar = dardisplay_aspect_ratio=16:9// 像素格式,即av_get_pix_fmt_name(AVStream->codecpar->format)pix_fmt=yuvj420p// 编码参数,即AVStream->codecpar->levellevel=40// 额外的色彩空间特征,即av_color_range_name(AVStream->codecpar->color_range),AVCOL_RANGE_MPEG对应tv,AVCOL_RANGE_JPEG对应pccolor_range=pc// YUV彩色空间类型,即av_color_space_name(AVStream->codecpar->color_space)color_space=bt470bg// 颜色传输特性,即av_color_transfer_name(AVStream->codecpar->color_trc)color_transfer=smpte170m// 即av_color_primaries_name(AVStream->codecpar->color_primaries)color_primaries=bt470bg// 色度样品的位置,即av_chroma_location_name(AVStream->codecpar->chroma_location)chroma_location=left// 交错视频中字段的顺序,即AVStream->codecpar->field_orderfield_order=unknown// av_timecode_make_mpeg_tc_string处理AVStream->codec->timecode_frame_start获得timecode=N/A// 参考帧数量,即AVStream->codec->refsrefs=1is_avc=true// 表示用几个字节表示NALU的长度nal_length_size=4id=N/A// 当前流的基本帧率,这个值仅是一个猜测,对应于AVStream->r_frame_rater_frame_rate=30/1// 平均帧率,对应于AVStream->avg_frame_rateavg_frame_rate=438750/14777// AVStream的时间基准,即AVStream->time_basetime_base=1/90000// 流开始时间,基于time_base,即AVStream->start_timestart_pts=0// 转换(start_pts * time_base)之后的开始时间,单位秒start_time=0.000000// 流时长,基于time_base,即AVStream->durationduration_ts=945728// 转换(duration_ts * time_base)之后的时长,单位秒duration=10.508089// 码率,即AVStream->codecpar->bit_ratebit_rate=19983544// 最大码率,即AVStream->codec->rc_max_ratemax_bit_rate=N/A// Bits per sample/pixel,即AVStream->codec->bits_per_raw_samplebits_per_raw_sample=8// 视频流中的帧数,即AVStream->nb_framesnb_frames=312nb_read_frames=N/Anb_read_packets=N/A// 下面TAG为AVStream->metadata中的信息// 逆时针的旋转角度(相当于正常视频的逆时针旋转角度)TAG:rotate=90// 创建时间TAG:creation_time=2019-08-11T03:37:28.000000Z// 语言TAG:language=engTAG:handler_name=VideoHandle// SIDE_DATA为AVStream->side_data数据[SIDE_DATA]// side_data数据类型,Display Matrix表示一个3*3的矩阵,这个矩阵需要应用到解码后的视频帧上,才能正确展示side_data_type=Display Matrixdisplaymatrix=00000000: 0 65536 000000001: -65536 0 000000002: 0 0 1073741824// 顺时针旋转90度还原视频rotation=-90[/SIDE_DATA][/STREAM][STREAM]// 当前流的索引信息,对应于AVStream->indexindex=1// AVCodecDescriptor * cd = avcodec_descriptor_get(AVStream->codecpar->codec_id)// 编码名称,即cd->namecodec_name=aac// 编码全称,即cd->long_namecodec_long_name=AAC (Advanced Audio Coding)// 通过avcodec_profile_name(AVStream->codecpar->codec_id, AVStream->codecpar->profile)获得profile=LC// 流类型,即av_get_media_type_string(AVStream->codecpar->codec_type)codec_type=audio// 即AVStream->codec->time_basecodec_time_base=1/48000// 通过宏av_fourcc2str(AVStream->codecpar->codec_tag)获得codec_tag_string=mp4a// 对应AVStream->codecpar->codec_tagcodec_tag=0x6134706d// 采样点格式,通过av_get_sample_fmt_name(AVStream->codecpar->format)获取sample_fmt=fltp// 采样率,即AVStream->codecpar->sample_ratesample_rate=48000// 通道数,即AVStream->codecpar->channelschannels=2// 通道布局,与channels是相对应,通过av_bprint_channel_layout获取,stereo表示立体声channel_layout=stereo// 每个采样点占用多少bit,即av_get_bits_per_sample(par->codec_id)bits_per_sample=0id=N/Ar_frame_rate=0/0avg_frame_rate=0/0// AVStream的时间基准,即AVStream->time_basetime_base=1/48000// 流开始时间,基于time_base,即AVStream->start_timestart_pts=0// 转换(start_pts * time_base)之后的开始时间,单位秒start_time=0.000000// 流时长,基于time_base,即AVStream->durationduration_ts=502776// 转换(duration_ts * time_base)之后的时长,单位秒duration=10.474500// 码率,即AVStream->codecpar->bit_ratebit_rate=156002// 最大码率,即AVStream->codec->rc_max_ratemax_bit_rate=156000// Bits per sample/pixel,即AVStream->codec->bits_per_raw_samplebits_per_raw_sample=N/A// 音频流中的帧数,即AVStream->nb_framesnb_frames=491nb_read_frames=N/Anb_read_packets=N/ATAG:creation_time=2019-08-11T03:37:28.000000ZTAG:language=engTAG:handler_name=SoundHandle[/STREAM]
SAR(Sample Aspect Ratio): 采样数宽高比,图像的横向采集点数与纵向采集点数的比值,即像素个数的比值。
PAR(Pixel Aspect Ratio): 像素宽高比,即每个像素的宽度与高度的比值,所以可以认为像素不是正方形的。
DAR(Display Aspect Ratio): 显示宽高比,图像最终展示的宽高比,播放器在渲染视频帧时,需要保持DAR的比例。
它们之间的关系:PAR * SAR = DAR
![]()
如上图所示:每个方格代表一个像素,宽度为5像素,高度为4像素,即SAR=5 : 4
假设图像的显示宽度为160,高度为120,即DAR=4 : 3
那么可以计算出PAR = DAR / SAR = 16 : 15,表示像素方格是一个长方形。FFmpeg提供了多个SAR:
AVStream->sample_aspect_ratio
AVStream->codecpar->sample_aspect_ratio
AVFrame->sample_aspect_ratio
最终的SAR是通过av_guess_sample_aspect_ratio获取的。对于DAR,AVStream->display_aspect_ratio的值始终为0:0,参考ffprobe代码,可知DAR是通过av_reduce计算得到的,如下所示:
AVRational sar, dar;// parAVCodecParameters *par = AVStream->codecpar;// 计算出sarsar = av_guess_sample_aspect_ratio(AVFormatContext, AVStream, NULL);// 根据par和sar计算出darav_reduce(&dar.num, &dar.den,par->width * sar.num,par->height * sar.den,1024*1024);
// -select_streams表示选择音频或者视频ffprobe -show_format [-select_streams audio | video] inputFile
首先看下视频流的第一个Packet和第二个Packet:
[PACKET]//Packet类型,即av_get_media_type_string(AVStream->codecpar->codec_type)codec_type=video// 当前帧所属流的索引信息,对应于AVStream->indexstream_index=0// 帧展示时间,即AVPacket->pts,基于AVStream->time_base时间基准pts=0// 换算为秒pts_time=0.000000// 帧解码时间,即AVPacket->dts,基于AVStream->time_base时间基准dts=0// 换算为秒dts_time=0.000000// 当前帧的时长,等于下一帧的pts - 当前帧pts,即AVPacket->duration,基于AVStream->time_base时间基准duration=12972// 换算为秒duration_time=0.144133// AVPacket->convergence_duration,也是基于AVStream->time_base时间基准convergence_duration=N/A// 换算为秒convergence_duration_time=N/A// 当前帧的Size,字节,即AVPacket->sizesize=187872// 当前帧地址偏移量,即AVPacket->pospos=830842flags=K_[/PACKET][PACKET]codec_type=videostream_index=0pts=12972// 即 12972 / 90000pts_time=0.144133dts=12972dts_time=0.144133duration=2999duration_time=0.033322convergence_duration=N/Aconvergence_duration_time=N/Asize=31200// 上一帧的pos + sizepos=1018714flags=__[/PACKET]
然后看下音频流的第一个Packet和第二个Packet:
[PACKET]// 音频帧codec_type=audio// 当前帧所属流的索引信息,对应于AVStream->indexstream_index=1// 帧展示时间,即AVPacket->pts,基于AVStream->time_base时间基准pts=0pts_time=0.000000// 帧解码时间,即AVPacket->dts,基于AVStream->time_base时间基准dts=0dts_time=0.000000// 当前帧的时长,等于下一帧的pts - 当前帧pts,即AVPacket->duration,基于AVStream->time_base时间基准duration=1024// 1024 / 48000duration_time=0.021333convergence_duration=N/Aconvergence_duration_time=N/Asize=416pos=810458flags=K_[/PACKET][PACKET]// 音频帧codec_type=audiostream_index=1pts=1024// 1024 / 48000pts_time=0.021333dts=1024dts_time=0.021333duration=1024duration_time=0.021333convergence_duration=N/Aconvergence_duration_time=N/Asize=416// 上一帧的pos + sizepos=810874flags=K_[/PACKET]
// -select_streams表示选择音频或者视频ffprobe -show_frames [-select_streams audio | video] inputFile
首先看下视频流的第一帧和第二帧:
[FRAME]// 帧类型,即av_get_media_type_string(AVStream->codecpar->codec_type)media_type=video// 当前帧所属流的索引信息, 对应于AVStream->indexstream_index=0// 是否关键帧,1:关键帧,0:非关键帧,即AVFrame->key_framekey_frame=1// 帧展示时间, 即AVFrame->pts, 基于AVStream->time_base时间基准pkt_pts=0// 换算为秒pkt_pts_time=0.000000// 帧解码时间,从对应的AVPacket copy而来,即AVFrame->pkt_dts,基于AVStream->time_base时间基准pkt_dts=0// 换算为秒pkt_dts_time=0.000000// 帧时间戳,基本与pts相同,即AVFrame->best_effort_timestamp,基于AVStream->time_base时间基准best_effort_timestamp=0// 换算为秒best_effort_timestamp_time=0.000000// 对应的AVPacket的帧时长,即AVFrame->pkt_duration,基于AVStream->time_base时间基准pkt_duration=12972// 换算为秒pkt_duration_time=0.144133// 从最后一个已输入解码器的AVPacket重新排序的pos,即AVFrame->pkt_pospkt_pos=830842// 对应的AVPacket的帧size,即AVFrame->pkt_sizepkt_size=187872// 旋转之前的帧宽度,即AVFrame->widthwidth=1920// 旋转之前的帧高度,即AVFrame->heightheight=1080// 视频帧的像素格式,即av_get_pix_fmt_name(AVFrame->format)pix_fmt=yuvj420p// sar,图像采集时,横向采集点数与纵向采集点数的比例// FFmpeg提供了多个sar:AVStream->sample_aspect_ratio、AVStream->codecpar->sample_aspect_ratio、AVFrame->sample_aspect_ratio// 通过av_guess_sample_aspect_ratio获取最终的sarsample_aspect_ratio=1:1// 视频帧的图片类型,此处为I帧,即av_get_picture_type_char(frame->pict_type)pict_type=I// picture number in bitstream order, 即AVFrame->coded_picture_numbercoded_picture_number=0// picture number in display order, 即AVFrame->display_picture_numberdisplay_picture_number=0// 视频帧内容是否是交错的, 即AVFrame->interlaced_frameinterlaced_frame=0// 若视频帧内容是交错的,表示首先展示的顶部字段,即AVFrame->top_field_firsttop_field_first=0// 当解码时,这个信号表明视频帧必须延迟多少。extra_delay = repeat_pict / (2*fps), 即AVFrame->repeat_pictrepeat_pict=0// 额外的色彩空间特征,即av_color_range_name(AVFrame->color_range),AVCOL_RANGE_MPEG对应tv,AVCOL_RANGE_JPEG对应pccolor_range=pc// YUV彩色空间类型,即av_color_space_name(AVFrame->colorspace)color_space=bt470bg// 即av_color_primaries_name(AVFrame->color_primaries)color_primaries=bt470bg// 颜色传输特性,即av_color_transfer_name(AVFrame->color_trc)color_transfer=smpte170m// 色度样品的位置,即av_chroma_location_name(AVFrame->chroma_location)chroma_location=left[/FRAME][FRAME]media_type=videostream_index=0// 非关键帧key_frame=0pkt_pts=12972// 12972 / 90000pkt_pts_time=0.144133pkt_dts=12972pkt_dts_time=0.144133best_effort_timestamp=12972best_effort_timestamp_time=0.144133pkt_duration=2999pkt_duration_time=0.033322pkt_pos=1018714pkt_size=31200width=1920height=1080pix_fmt=yuvj420psample_aspect_ratio=1:1// 视频帧的图片类型,此处为P帧,即av_get_picture_type_char(frame->pict_type)pict_type=Pcoded_picture_number=1display_picture_number=0interlaced_frame=0top_field_first=0repeat_pict=0color_range=pccolor_space=bt470bgcolor_primaries=bt470bgcolor_transfer=smpte170mchroma_location=left[/FRAME]
然后看下音频流的第一帧和第二帧:
[FRAME]// 帧类型,即av_get_media_type_string(AVStream->codecpar->codec_type)media_type=audio// 当前帧所属流的索引信息, 对应于AVStream->indexstream_index=1// 是否关键帧key_frame=1// 帧展示时间, 即AVFrame->pts, 基于AVStream->time_base时间基准pkt_pts=0// 换算为秒pkt_pts_time=0.000000// 帧解码时间,从对应的AVPacket copy而来,即AVFrame->pkt_dts,基于AVStream->time_base时间基准pkt_dts=0// 换算为秒pkt_dts_time=0.000000// 帧时间戳,基本与pts相同,即AVFrame->best_effort_timestamp,基于AVStream->time_base时间基准best_effort_timestamp=0// 换算为秒best_effort_timestamp_time=0.000000// 对应的AVPacket的帧时长,即AVFrame->pkt_duration,基于AVStream->time_base时间基准pkt_duration=1024// 换算为秒pkt_duration_time=0.021333// 从最后一个已输入解码器的AVPacket重新排序的pos,即AVFrame->pkt_pospkt_pos=810458// 对应的AVPacket的帧size,即AVFrame->pkt_sizepkt_size=416// 音频采样点格式,即av_get_sample_fmt_name(AVFrame->format)sample_fmt=fltp// 当前音频帧的采样点数,即AVFrame->nb_samplesnb_samples=1024// 通道数,即AVFrame->channelschannels=2// 通道布局,通过av_bprint_channel_layout得到,与channels对应channel_layout=stereo[/FRAME][FRAME]media_type=audiostream_index=1key_frame=1pkt_pts=1024pkt_pts_time=0.021333pkt_dts=1024pkt_dts_time=0.021333best_effort_timestamp=1024best_effort_timestamp_time=0.021333pkt_duration=1024pkt_duration_time=0.021333pkt_pos=810874pkt_size=416sample_fmt=fltpnb_samples=1024channels=2channel_layout=stereo[/FRAME]
后续继续补充更多音视频信息。