小米手機(jī)做網(wǎng)站服務(wù)器嗎網(wǎng)站排名優(yōu)化公司
一、引言
通過FFmpeg命令可以獲取到H.264裸流文件的色彩格式(又譯作色度采樣結(jié)構(gòu)、像素格式):
在vlc中也可以獲取到色彩格式(vlc底層也使用了FFmpeg進(jìn)行解碼):
這個色彩格式就是之前的文章《音視頻入門基礎(chǔ):像素格式專題(4)——YUV簡介》中描述的像素格式。所以FFmpeg和vlc是怎樣獲取到H.264編碼的視頻的色彩格式呢?它們其實是通過SPS中的屬性chroma_format_idc獲取的。
二、H.264官方文檔對chroma_format_idc的描述
chroma_format_idc屬性在H.264官方文檔《T-REC-H.264-202108-I!!PDF-E.pdf》第44頁中定義:
根據(jù)H.264官方文檔《T-REC-H.264-202108-I!!PDF-E.pdf》第22頁,當(dāng)chroma_format_idc = 0時,色彩格式為單色;chroma_format_idc = 1時,色彩格式為YUV 4:2:0;chroma_format_idc = 2時,色彩格式為YUV 4:2:2;chroma_format_idc = 3時,色彩格式為YUV 4:4:4:
根據(jù)H.264官方文檔第74頁,chroma_format_idc的值應(yīng)該在0到3的范圍內(nèi)(包括0和3)。當(dāng)chroma_format_idc不存在時,應(yīng)推斷其值為1(4:2:0的色度格式)。
也就是說,只有當(dāng)profile_idc等于下面紅框里的這些值時,chroma_format_idc才會存在。如果profile_idc不是這些值,chroma_format_idc的值就是1,表示色彩格式為YUV 4:2:0:
三、計算色彩格式的例子
下面以某個視頻文件為例,講述怎么計算它的色彩格式。用Elecard Stream Analyzer工具打開一個用H.264編碼的視頻文件,看到其profile_idc值為77。由于profile_idc不是上圖紅框里的那些值,所以chroma_format_idc值為1,所以該視頻的色彩格式為YUV 4:2:0:
用Elecard StreamEye工具可以看到該視頻的色彩格式確實為YUV 4:2:0,證明我們的計算是正確的:
四、FFmpeg源碼中獲取色彩格式的實現(xiàn)
從文章《音視頻入門基礎(chǔ):H.264專題(10)——FFmpeg源碼中,存放SPS屬性的結(jié)構(gòu)體和解碼SPS的函數(shù)分析》中,我們可以知道,FFmpeg源碼中通過ff_h264_decode_seq_parameter_set函數(shù)解碼SPS,從而拿到SPS中的屬性。
在ff_h264_decode_seq_parameter_set函數(shù)中有如下代碼,通過下面的這部分代碼拿到SPS中的chroma_format_idc:
int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx,H264ParamSets *ps, int ignore_truncation)
{//...if (sps->profile_idc == 100 || // High profilesps->profile_idc == 110 || // High10 profilesps->profile_idc == 122 || // High422 profilesps->profile_idc == 244 || // High444 Predictive profilesps->profile_idc == 44 || // Cavlc444 profilesps->profile_idc == 83 || // Scalable Constrained High profile (SVC)sps->profile_idc == 86 || // Scalable High Intra profile (SVC)sps->profile_idc == 118 || // Stereo High profile (MVC)sps->profile_idc == 128 || // Multiview High profile (MVC)sps->profile_idc == 138 || // Multiview Depth High profile (MVCD)sps->profile_idc == 144) { // old High444 profilesps->chroma_format_idc = get_ue_golomb_31(gb);//...}else {sps->chroma_format_idc = 1;//...}//...
}
然后在FFmpeg源碼的源文件libavcodec/h264_parser.c的parse_nal_units函數(shù)中,通過如下代碼,得到色彩格式:
static inline int parse_nal_units(AVCodecParserContext *s,AVCodecContext *avctx,const uint8_t * const buf, int buf_size)
{//...for (;;) {switch (nal.type) {case H264_NAL_SPS:ff_h264_decode_seq_parameter_set(&nal.gb, avctx, &p->ps, 0);break;//...case H264_NAL_IDR_SLICE://...switch (sps->bit_depth_luma) {case 9:if (sps->chroma_format_idc == 3) s->format = AV_PIX_FMT_YUV444P9;else if (sps->chroma_format_idc == 2) s->format = AV_PIX_FMT_YUV422P9;else s->format = AV_PIX_FMT_YUV420P9;break;case 10:if (sps->chroma_format_idc == 3) s->format = AV_PIX_FMT_YUV444P10;else if (sps->chroma_format_idc == 2) s->format = AV_PIX_FMT_YUV422P10;else s->format = AV_PIX_FMT_YUV420P10;break;case 8:if (sps->chroma_format_idc == 3) s->format = AV_PIX_FMT_YUV444P;else if (sps->chroma_format_idc == 2) s->format = AV_PIX_FMT_YUV422P;else s->format = AV_PIX_FMT_YUV420P;break;default:s->format = AV_PIX_FMT_NONE;}//... }//...}
}