??遇到的問題:使用ffmpeg直接讀取avc1編碼的mp4視頻,將讀取到的幀寫下來(H264碼流),播放失敗。 ??原因: ffmpeg解碼獲取的AVPacket只包含視頻壓縮數據,并沒有包含相關的解碼信息(比如:h264的sps,pps頭信息),這些解碼信息包括編碼的profile,level,圖像的寬和高,deblock濾波器等。沒有這些編碼頭信息解碼器就不能進行解碼。
??mp4封裝的avc1編碼(不帶起始碼的H264編碼格式)視頻如果直接用av_read_frame接口讀取然后播放是不能播放成功的。因為讀取出來的數據不帶PPS/SPS、起始碼這三種信息。 必須添加上后才能播放。
sps,pps之后就是I幀的數據起始碼為00 00 00 01或00 00 01
上圖中黑框內就是sps和psp數據,藍色框為起始碼(00 00 00 01)及I幀標志碼(06 50)
??H.264碼流的SPS和pps信息存儲在AVCidecContext結構體的extradata中,添加這些信息需要使用ffmpeg中名稱為”h264_mp4toannexb”的bitstream filter處理。 查看ffmpeg工具支持的Bitstream Filter類型命令
ffmpeg -bsfs
int ParseH264ExtraDataInMp4(int stream_id, AVPacket* packet) {uint8_t *dummy = NULL; int dummy_size;AVBitStreamFilterContext* bsfc = av_bitstream_filter_init("h264_mp4toannexb");if (bsfc == NULL) { envir() << "cannot open the h264_mp4toannexbn"; return -1;} av_bitstream_filter_filter(bsfc, format_ctx_->streams[stream_id]->codec, NULL, &dummy, &dummy_size, NULL, 0, 0); av_bitstream_filter_close(bsfc);}
舊接口使用時需要特別注意,否則很容易導致內存泄漏。
int ParseH264ExtraDataInMp4(int stream_id, AVPacket* packet) {const AVBitStreamFilter * absFilter = NULL; AVBSFContext *absCtx = NULL; AVCodecParameters *codecpar = NULL; absFilter = av_bsf_get_by_name("h264_mp4toannexb"); //過濾器分配內存 av_bsf_alloc(absFilter, &absCtx); //添加解碼器屬性 codecpar = format_ctx_->streams[stream_id]->codecpar; avcodec_parameters_copy(absCtx->par_in, codecpar); absCtx->time_base_in = format_ctx_->streams[stream_id]->time_base; //初始化過濾器上下文 av_bsf_init(absCtx); //AVPacket處理 if (av_bsf_send_packet(absCtx, packet) < 0) { printf("av_bsf_send_packet faile n"); av_bsf_free(&absCtx); absCtx = NULL; return -1; } if (av_bsf_receive_packet(absCtx, packet) == 0) { //printf("av_bsf_receive_packet faile n"); //av_bsf_free(&absCtx); //absCtx = NULL; return 0; } av_bsf_free(&absCtx); absCtx = NULL;}
int main(){ //ffmpeg的open接口打開MP4封裝的avc1碼流視頻 , AVFormatContext *format_ctx_ //讀取一幀av_read_frame,讀取到AVPacket packet中 if(視頻幀) //只處理視頻幀,音頻不處理 { int stream_id = packet->stream_index; AVCodecContext *codec = NULL; codec = format_ctx_->streams[stream_id]->codec; if (codec->codec_id == AV_CODEC_ID_H264) { //pps and sps //const char start_code[4] = { 0, 0, 0, 1 }; //memcpy(packet->data, start_code, 4); if ((codec->extradata[0] != 0) && (ParseH264ExtraDataInMp4(stream_id, packet) == 0)) { has_extra_data = True; }#if 0 { FILE* wfd = fopen("out.h264", "ab+"); if (wfd) { if (has_extra_data) { fwrite(codec->extradata, 1, codec->extradata_size, wfd); } fwrite(packet->data, 1, packet->size, wfd); fflush(wfd); fclose(wfd); wfd = NULL; } }#endif } }}
《1》、https://www.jianshu.com/p/e5e021ccc980 《2》、https://blogs.gentoo.org/lu_zero/2016/03/21/bitstream-filtering/ 《3》、http://www.xuhj.top/2018/06/26/ffmpeg-convert-to-ts-stream/ 《4》、https://cloud.tencent.com/developer/article/1333501 《5》、sps/pps數據結構 《6》、avc1余h264區別
版權聲明:本文內容由互聯網用戶自發貢獻,該文觀點僅代表作者本人。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如發現本站有涉嫌侵權/違法違規的內容, 請發送郵件至 舉報,一經查實,本站將立刻刪除。
181038.html
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...
在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...
在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...
dota深淵領主出裝?Dota2深淵領主裝備推薦:早期核心裝備:秘法靈魂之淚,大魔杖,圣殿戒指,魔法抵抗斗篷,骨灰盒中核心裝備:達梅肯·迪齊,小人犧牲,鼓刃甲勛章后裝:飛鞋冰甲攻羊刀龍心BKB天戟大屁股是dota2中典型的肉心功能型3號位置。還有很多方法可以瞄準他山上有蝴蝶,巨魔買羊刀;妖精和大炮讓神發光!黑暗游俠刷新球,深淵領主輸出流。他是一個憂郁的大公火槍手。這一時期在dota1時期廣泛流傳。...
怎樣使ppt中的文字兩端都對齊,不用分散對齊?謝謝您的邀請通配符替換和文字轉換表功能很容易完成。只需幾個簡單的步驟,如圖所示:原文在第一個單詞后添加一個符號(我用“”),這個符號不會出現在單詞或譯文中。在“替換”對話框中,如圖所示輸入并設置。注意搜索內容第二個括號中的空格。如果文檔的空間為全角度,請輸入全角度空間和半角度空間。替換所有點后,每個單詞后的第一個空格將替換為。選擇所有文本,然后使用“插...
17號線站點明細北京?北京地鐵17號線車站信息:未來科技城北站、未來科技城南站、天通苑東站、清和營站、永世營站、望京西站(換乘)、太陽宮站(換乘)、西壩河站(換乘)、香河園站、工人體育場站(換乘)、東大橋站(換乘)、李永安站(換乘)、廣渠門外站(換乘)車站21座,均為地下車站;a型列車由8列列車組成。17號線站點明細北京?北京地鐵17號線車站詳情:未來科技城北區——亦莊站南區,共21座車站,全線長...