最近編碼的時候發現生成的視頻不能用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,我就不誤導了。