FFMPEG H264

一、H264壓縮編碼

1.1 H264 中的 I 幀、P幀和 B幀

H264 使用幀內壓縮和幀間壓縮的方式提高編碼壓縮率;H264 采用了獨特的 I 幀、P 幀和 B 幀策略來實現,連續幀之間的壓縮;

1.2 其他概念

GOP(圖像組):一個IDR幀到下一個IDR幀之間間隔了多少個幀

IDR:一個序列的第一個圖像叫做IDR圖像(立即刷新圖像),IDR圖像都是I幀圖像。I幀不用參考任何幀,但之后的P幀和B幀是有可能參考這個I幀之前的幀。IDR幀不允許后面PB參考前面的幀。IDR的核心作用是為了序列出現重大錯誤后重新同步,不用參考IDR之前的圖像的數據來解碼

1.3 NLU

視頻流至少發從一幀SPS和一幀PPS來告訴客戶端視頻流信息

H.264原始碼流(裸流)是由?個接?個NALU組成。它的功能分為兩層,VCL (視頻編碼層) 和
NAL (?絡提取層)。VCL:負責壓縮視頻;NAL:把VCL壓縮的視頻封裝成NLU幀

1、NLU幀包括三個部分

[StartCode] [NALU Header] [NALU Payload]

StartCode必須是?"00 00 00 01"?或?"00 00 01"

NALU Header是NALU的頭部

RBSP是I、P、B幀的數據。

NLU幀的結束也是根據00 00 00 01或00 00 01來判斷的

3字節的0x000001只有?種場合下使?,就是?個完整的幀被編為多個slice(?)的時
候,包含這些sliceNALU 使?3字節起始碼。其余場合都是4字節0x00000001的。前面的I幀就是分別存儲在兩個NALU中,這兩個NALU的開頭就是00 00 01

2、NLU Header第一個字節

其中:
T為負荷數據類型,占5bit
nal_unit_type:這個NALU單元的類型,112H.264使?,2431H.264以外的應?
使?
R為重要性指示位,占2bit
nal_ref_idc.:取00~11,似乎指示這個NALU的重要性,00NALU解碼器可以丟棄它?不
影響圖像的回放,03,取值越?,表示當前NAL越重要,需要優先受到保護。如果當前
NAL是屬于參考幀的?,或是序列參數集,或是圖像參數集這些重要的單位時,本句法元
素必需?于0
最后的F為禁?位,占1bit
forbidden_zero_bit: 在 H.264 規范中規定了這?位必須為 0.

3、NLU的類型

0x00 00 00 01 67
67
?進制:0110 0111? ?
00111 = 7(?進制)
nal_unit_typeNAL單元和RBSP語法結構的內容
0未指定
1一個非IDR圖像的編碼條帶slice_layer_without_partitioning_rbsp( )
2
編碼條帶數據分割塊A slice_data_partition_a_layer_rbsp( )
3
編碼條帶數據分割塊B slice_data_partition_b_layer_rbsp( )
4
編碼條帶數據分割塊C slice_data_partition_c_layer_rbsp( )
5
IDR圖像的編碼條帶(?) slice_layer_without_partitioning_rbsp ( )
6
輔助增強信息 (SEI)?sei_rbsp( )
7
序列參數集 seq_parameter_set_rbsp( )
8
圖像參數集 pic_parameter_set_rbsp( )
9
訪問單元分隔符 access_unit_delimiter_rbsp( )
10
序列結尾 end_of_seq_rbsp( )
11
流結尾? end_of_stream_rbsp( )
12
填充數據 filler_data_rbsp( )
13
序列參數集擴展9 seq_parameter_set_extension_rbsp( )
14...18
保留
19
未分割的輔助編碼圖像的編碼條帶 slice_layer_without_partitioning_rbsp( )
20...23
保留
24...31
未指定

1.4?H264 annexb模式

H264有兩種封裝

?種是Annex B模式,傳統模式,有startcodeSPSPPS是在ES
?種是mp4模式,?般mp4 mkv都是mp4模式,沒有startcodeSPSPPS以及其它信息
被封裝在container中,每?個frame前?4個字節是這個frame的?度。很多解碼器只?持Annex B這種模式,因此需要將mp4做轉換:ffmpeg中? h264_mp4toannexb_filter可以做轉換
實現:
const AVBitStreamFilter *bsfilter = av_bsf_get_by_name("h264_mp4toannexb");
AVBSFContext *bsf_ctx = NULL;
// 2 初始化過濾器上下?
av_bsf_alloc(bsfilter, &bsf_ctx); //AVBSFContext;
// 3 添加解碼器屬性
avcodec_parameters_copy(bsf_ctx->par_in, ifmt_ctx->streams[videoindex]->codecpar);
av_bsf_init(bsf_ctx);

1. Annex B內部數據,對應的了前面講解的內容

[4字節起始碼] + [SPS NALU數據] 
[4字節起始碼] + [PPS NALU數據] 
[3字節起始碼] + [I幀NALU數據] 
[3字節起始碼] + [P幀NALU數據] 
[3字節起始碼] + [B幀NALU數據] 
...(后續NALU以此類推)

輸出的文件是H.264視頻文件

2. MP4直接的碼流對應下圖右邊,開頭記錄的是NALU幀的長度,都是4字節

二、MP4->H.264代碼

#include <iostream>extern "C"{#include <libavutil/log.h>#include <libavformat/avio.h>#include <libavformat/avformat.h>#include <libavcodec/bsf.h> 
}using namespace std;static char err_buf[128] = {0};
static char* av_get_err(int errnum)
{av_strerror(errnum, err_buf, 128);return err_buf;
}int main(int argc, char **argv) {string inputFile = "believe.mp4";string outputFile = "believe.h264"; FILE * outfp = fopen(outputFile.c_str(),"wb");printf("in:%s out:%s\n", inputFile.c_str(), outputFile.c_str());// 創建AVFormatContext上下文AVFormatContext * ifmt_ctx = avformat_alloc_context();if (!ifmt_ctx) {printf("[error] Could not allocate context.\n");return -1;}int ret = avformat_open_input(&ifmt_ctx, inputFile.c_str(), NULL, NULL);if (ret != 0) {printf("[error] avformat_open_input: %s\n", av_get_err(ret));return -1;}ret = avformat_find_stream_info(ifmt_ctx, NULL);if (ret < 0) {printf("[error] avformat_find_stream_info: %s\n", av_get_err(ret));avformat_close_input(&ifmt_ctx);return -1;}// 查找出哪個碼流是video/audio/subtitlesint videoindex = -1;videoindex = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);if(videoindex == -1) {printf("[error] Didn't find a video stream.\n");avformat_close_input(&ifmt_ctx);return -1;}// 創建AVPacket包AVPacket * pkt = av_packet_alloc();av_init_packet(pkt);// 1 獲取一個名為"h264_mp4toannexb"的比特流過濾器// 用于將MP4容器中的H.264視頻流轉換為Annex B格式的H.264流const AVBitStreamFilter * bsfilter = av_bsf_get_by_name("h264_mp4toannexb");AVBSFContext * bsf_ctx = NULL;// 2 初始化過濾器上下文av_bsf_alloc(bsfilter, &bsf_ctx); //AVBSFContext;// 3 復制視頻流的編解碼參數到過濾器上下文avcodec_parameters_copy(bsf_ctx->par_in, ifmt_ctx->streams[videoindex]->codecpar);av_bsf_init(bsf_ctx);int file_end = 0;while (0 == file_end) {if((ret = av_read_frame(ifmt_ctx, pkt)) < 0) {// 沒有更多包可讀file_end = 1;printf("read file end: ret:%d\n", ret);}if(ret == 0 && pkt->stream_index == videoindex) {int input_size = pkt->size;int out_pkt_count = 0;if (av_bsf_send_packet(bsf_ctx, pkt) != 0) // bitstreamfilter內部去維護內存空間{av_packet_unref(pkt);   // 你不用了就把資源釋放掉continue;       // 繼續送}av_packet_unref(pkt);   // 釋放資源while(av_bsf_receive_packet(bsf_ctx, pkt) == 0) {out_pkt_count++;// printf("fwrite size:%d\n", pkt->size);size_t size = fwrite(pkt->data, 1, pkt->size, outfp);if(size != pkt->size){printf("fwrite failed-> write:%u, pkt_size:%u\n", size, pkt->size);}av_packet_unref(pkt);}if(out_pkt_count >= 2){printf("cur pkt(size:%d) only get 1 out pkt, it get %d pkts\n", input_size, out_pkt_count);}// 注釋掉前面代碼,可以直接保存mp4流// size_t size = fwrite(pkt->data, 1, pkt->size, outfp);// if(size != pkt->size)// {//     printf("fwrite failed-> write:%u, pkt_size:%u\n", size, pkt->size);// }// av_packet_unref(pkt);}else {if(ret == 0) av_packet_unref(pkt); // 釋放內存}}if (outfp) fclose(outfp);if (bsf_ctx) av_bsf_free(&bsf_ctx);if (pkt) av_packet_free(&pkt);if (ifmt_ctx) avformat_close_input(&ifmt_ctx);printf("finish\n");return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/95757.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/95757.shtml
英文地址,請注明出處:http://en.pswp.cn/web/95757.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Unity 解決天空盒中間出現一條線

問題解決找到天空盒對應貼圖&#xff0c;在Inspector 面板中找到Advanced →Generate Mip Maps 并取消勾選即可。效果動態修改天空盒RenderSettings.skybox targetSkyboxMaterial; DynamicGI.UpdateEnvironment();

Python爬蟲實戰:研究Showcase模塊,構建電商平臺銷售數據采集和分析系統

1. 引言 1.1 研究背景 在數字經濟快速發展的今天,電商平臺積累了海量的商品信息、交易數據和用戶反饋,這些數據蘊含著豐富的市場洞察。根據中國電子商務研究中心數據,2024 年我國網絡零售市場規模突破 15 萬億元,平臺商品數據呈現指數級增長。如何高效提取這些數據并轉化…

C++中的Reactor和Proactor模型進行系統性解析

<摘要> 本解析系統闡述了網絡編程中Reactor與Proactor兩種高性能I/O模型的核心概念。Reactor基于同步I/O多路復用&#xff0c;通過事件循環分發通知&#xff0c;由應用層自行完成I/O操作&#xff1b;而Proactor則基于異步I/O&#xff0c;由操作系統完成I/O操作后主動回調…

【技術教程】如何將文檔編輯器集成至基于Node.js的網頁應用程序中

當今數字化時代&#xff0c;Web應用對在線文檔編輯的需求日益增長。無論是構建在線辦公系統、內容管理平臺還是協作工具&#xff0c;讓用戶能夠直接在瀏覽器中編輯和處理文檔已成為基本需求。 想知道如何為你的 Node.js 應用添加強大的在線文檔編輯功能嗎&#xff1f;本文手把…

[論文閱讀] 人工智能 + 軟件工程 | 別讓AI寫的代碼帶“漏洞”!無觸發投毒攻擊的防御困境與啟示

別讓AI寫的代碼帶“漏洞”&#xff01;無觸發投毒攻擊的防御困境與啟示 論文信息 原標題&#xff1a;Evaluating Defenses Against Trigger-Free Data Poisoning Attacks on NL-to-Code Models&#xff08;評估NL-to-Code模型應對無觸發數據投毒攻擊的防御方法&#xff09;主要…

【Windows】通過 runas 命令實現多用戶權限測試的完整流程

? 目錄 ?&#x1f6eb; 導讀需求1?? 前期準備&#xff1a;創建管理員/普通測試用戶1.1 創建普通用戶Test&#xff08;無管理員權限&#xff09;1.2 創建管理員用戶Admin&#xff08;含管理員權限&#xff09;2?? 核心操作&#xff1a;通過runas命令切換用戶命令行環境2.1…

新后端漏洞(上)- H2 Database Console 未授權訪問

漏洞介紹&#xff1a; H2 database是一款Java內存數據庫&#xff0c;多用于單元測試。 H2 database自帶一個Web管理頁面&#xff0c;在Spirng開發中&#xff0c;如果我們設置如下選項&#xff0c;即可允許外部用戶訪問Web管理頁面&#xff0c;且沒有鑒權&#xff1a; spring.h2…

2025-09-04 HTML3——區塊布局與表單

文章目錄1 塊元素與行內元素1.1 塊元素 (Block-level Element)1.2 行內元素 (Inline Element)2 HTML 布局2.1 使用 <div> 元素2.2 使用 <table> 元素3 表單 (<form>)3.1 輸入域&#xff08;<input>&#xff09;3.1.1 文本域&#xff08;Text Fields&am…

云數據庫服務(參考自騰訊云計算工程師認證課程)更新中......

數據庫基礎介紹面臨的挑戰&#xff1a;數據庫系統架構&#xff1a; 數據庫DB、數據庫管理系統DBMS&#xff08;負責數據庫的搭建、使用和維護的系統軟件&#xff0c;通過組織、索引、查詢、修改數據庫文件、實現數據定義、組織、存儲、管理以及數據庫操作、運行和維護等主要功能…

源滾滾AI編程SillyTavern酒館配置Claude Code API教程

什么是酒館 SillyTavern&#xff08;簡稱 ST&#xff09;是一款本地安裝的用戶界面&#xff0c;讓你能夠與文本生成大模型&#xff08;LLM&#xff09;、圖像生成引擎以及語音合成&#xff08;TTS&#xff09;模型進行交互。我們的目標是盡可能賦予用戶對 LLM 提示詞的最大掌控…

軟件設計師——軟件工程學習筆記

軟件工程 一、軟件工程基礎知識 1. 軟件的生存周期&#xff08;1&#xff09;可行性分析與項目開發計劃。這個階段主要確定軟件的開發目標及其可行性。參與該階段的人員有用戶、項目負責人、系統分析師。產生的文檔有 可行性分析報告、項目開發計劃。 &#xff08;2&#xff09…

阿里云ecs 2h2g 實際可用內存不足的情況

Kdump是Linux系統的一種內核崩潰轉儲機制&#xff0c;它允許在系統發生內核崩潰&#xff08;例如內核panic&#xff09;時&#xff0c;捕獲內存的轉儲信息&#xff0c;從而幫助事后分析故障原因。該過程需要一塊預留內存&#xff08;稱為crashkernel內存&#xff09;&#xff0…

MySQL拋出的Public Key Retrieval is not allowed

有時候在連接實例的時候會遇到這樣的報錯Public Key Retrieval is not allowed問題分析這是因為賬號使用了sha256_password或者caching_sha2_password 密碼插件而sha256_password或者caching_sha2_password 插件為了加快認證過程&#xff0c;在服務端維護了一個密碼哈希緩存。當…

ICP可能有用的

可以訓練GICP WGICP: Differentiable Weighted GICP-Based Lidar Odometry | GAMMA CT ICP (99 封私信 / 80 條消息) KITTI里程計排行榜上第五&#xff01;CT-ICP&#xff1a;實時彈性激光雷達里程計與回環檢測 - 知乎 Faster GICP github.com

nextcyber——Shells和Payloads

Shells和Payloads Shell的基礎知識 正向Shells Tom可以在一個Linux目標上發出nc -lvnp 443的命令。他需要從他的攻擊機連接到哪個端口&#xff0c;才能成功建立一個shell會話&#xff1f; 443SSH到目標&#xff0c;創建一個bind shell&#xff0c;然后用netcat連接到目標&a…

筆記:現代操作系統:原理與實現(2)

第三章 操作系統結構 操作系統的機制與策略 操作系統乃至計算機系統中控制復雜度的—個重要設計原則是:將策略與機制相分離&#xff0c;其中策略&#xff08;policy&#xff09;表示要‘‘做什么”&#xff0c;機制&#xff08;mechanjsm&#xff09;表示該“如何做”。 操作系…

c++ 壓縮與解壓縮

1、使用zip開源庫&#xff0c;引入比較簡單&#xff0c;只需要包含四個頭文件&#xff0c;不需要編譯成庫文件&#xff1a;zip.h、zip.cpp、unzip.h、unzip.cpp。2、壓縮使用到的主要函數&#xff1a;CreateZip 創建zip文件ZipAdd 添加文件ZipAddFolder 添加文件夾CloseZip 關閉…

水下無線光通信(UWOC)TDD系統:光收發端編解碼與信號處理分析與方案(數字版)

在光收發模塊中添加編解碼與信號處理模塊,核心目標是提升水下信道抗干擾能力(對抗后向散射、環境光、信號衰減)、降低誤碼率,同時兼容原有TDD時隙控制邏輯。以下從“編碼方案選型”“光發送端信號處理”“光接收端信號處理”“與原有系統集成”四部分展開,形成完整技術閉環…

Seat 事務@GlobalTransactional傳播行為

一&#xff0c;分布式事務傳播行為調用鏈描述一個普通事務注解的方法&#xff0c;調用一個分布式事務注解方法分布式事務注解方法&#xff1a;包含一個本地更新&#xff0c;和兩個外部服務更新操作&#xff0c;涉及三個服務問題1&#xff0c;普通事務注解方法&#xff0c;在全局…

美團龍貓利用expat庫實現的保存xml指定范圍數據到csv的C程序

用自己代碼逐個字符解析的速度較慢&#xff0c;嘗試了libxml2也比較慢&#xff0c;它需要一次性讀入內存&#xff0c;而expat庫支持流式讀取。就讓龍貓寫了一個程序&#xff0c;畢竟是久經考驗的庫&#xff0c;程序很快就調試通過了。要不是我一開始沒信心&#xff0c;讓他先輸…