h264手動添加sps和pps到AVCodecContext->extradata

最近編碼的時候發現生成的視頻不能用Windows Media Player等系統自帶的播放器播放,也沒有縮略圖。找了很久,最後才發現在avcodec_open2之前添加一行代碼就行了:

codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

調用該行代碼後,FFmpeg會在調用avcodec_open2裏,在寫header時填充sps,pps等信息。不填充編碼出來的視頻就不能正常解碼,當然使用專業的播放器(potplayer等)還是可以。

在沒發現添加這行代碼就可以之前,我是直接嘗試手動添加sps/pps到extradata的。

在avcodec_open2之前添加如下代碼,生成的視屏就能用系統自帶播放器播放,也有了縮略圖。但是Windows資源管理器看的幀高度和寬度不正確,所以還要修改sps_pps數組。

 

unsigned char sps_pps[23] = { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x0a, 0xf8, 0x0f, 0x00, 0x44, 0xbe, 0x8,
			      0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x38, 0x80 }; 
		codec_ctx->extradata_size = 23;
		codec_ctx->extradata = (uint8_t*)av_malloc(23 + AV_INPUT_BUFFER_PADDING_SIZE);
		if (codec_ctx->extradata == NULL) {
			printf("could not av_malloc the video params extradata!\n");
			return -1;
		}
		memcpy(codec_ctx->extradata, sps_pps, 23);


sps和pps的結構參考:h264編碼 裏面的Sequence parameter set RBSP syntax

 

0x00000001或者0x000001是起始碼,0x67是sps的開頭,0x68是pps的開頭。

0x42代表profile_idc,後面八位是constraint_set0_flag和reserved_zero_4bits,都設爲0,0x0a是level_idc,接着後面爲圖方便能用0表示的都用了。這裏要注意是ue(v)表示該域是可變位,使用的指數-哥倫布編碼 我的目的主要是設置正確幀高度和幀高度,所以只要填充   pic_width_in_mbs_minus1和  pic_height_in_map_units_minus1,將它們的十六進制數寫入sps_pps,如果寬度和高度不是16的倍數,可能要填frame_cropping_flag,具體的做法參考大神博客和SO,我就不誤導了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章