[FFmpeg] 輸入輸出訪問 | 管道系統 | AVIOContext 與 URLProtocol | 門面模式

鏈接:https://trac.ffmpeg.org/

docs:FFmpeg

在這里插入圖片描述
FFmpeg 是一個強大的多媒體框架,旨在處理媒體處理的各個階段。

它就像一個數字媒體工廠,包含以下部門:打包/解包(容器處理)、
轉譯/壓縮(編解碼器處理)、管理原始視頻幀壓縮數據包
連接輸入/輸出源(輸入輸出訪問)、執行編輯和特效(過濾與處理)、
保持所有內容的同步性(時間與速率管理),并提供靈活定制(配置選項)。

概覽

在這里插入圖片描述

章節列表

  1. 輸入輸出訪問
  2. 容器處理
  3. 壓縮媒體數據包
  4. 原始媒體幀
  5. 編解碼器處理
  6. 過濾與處理
  7. 時間與速率管理
  8. 配置選項

第一章:輸入輸出訪問

歡迎來到FFmpeg的第一章~

在FFmpeg能夠執行諸如轉換視頻或提取音頻等酷炫操作之前,它需要從某處獲取多媒體數據并將其發送到另一處。這個首要關鍵步驟由FFmpeg的輸入輸出訪問層處理。

可將輸入輸出訪問視為連接FFmpeg與外部世界的"管道系統"。

就像房屋需要管道來進出水一樣,FFmpeg需要一種方式來輸入輸出視頻、音頻和其他數據。該層提供了處理數據流的標準化方式,無論數據是來自計算機本地文件、網絡視頻流,甚至是網絡攝像頭等實時捕獲設備。

如果沒有這種抽象層,FFmpeg將需要完全不同的代碼來讀取本地.mp4文件(與從網站下載視頻或從麥克風捕獲相比)。輸入輸出訪問層隱藏了這些差異,提供了一致的接口。

讓我們從一個常見用例開始:將視頻文件從一種格式轉換為另一種格式。假設您有一個名為input.mp4的視頻文件,希望另存為output.avi

在命令行中使用ffmpeg工具(底層使用FFmpeg庫)時,通常執行如下操作:

ffmpeg -i input.mp4 output.avi

從輸入輸出角度分析此命令:

  • -i input.mp4:告知FFmpeg使用input.mp4作為輸入源,-i選項是標準輸入文件或URL指定參數
  • output.avi:指定輸出目標,FFmpeg將其識別為文件名并準備寫入數據

在此簡單命令中,FFmpeg的輸入輸出訪問層負責:

  1. 打開input.mp4進行讀取
  2. 分塊讀取input.mp4數據
  3. 打開output.avi進行寫入
  4. 將處理后的數據寫入output.avi

-f選項(-format縮寫)可顯式指定輸入輸出格式,這對于沒有明確頭部的原始視頻數據等輸入尤為重要:

ffmpeg -f rawvideo -video_size 640x480 -pixel_format yuv420p -i input.yuv output.mp4

此處-f rawvideo告知FFmpeg將input.yuv視為原始視頻數據,因為.yuv文件本身不包含尺寸或像素格式等格式信息。輸入輸出層仍負責打開和讀取文件,但需要這些額外參數(-video_size, -pixel_format)來理解讀取數據的結構。

因此,輸入輸出訪問層的核心職責是獲取字節輸入發送字節輸出

內部機制:管道系統

當運行ffmpeg -i input.mp4 output.avi時,FFmpeg如何處理文件讀取?

FFmpeg使用稱為協議(或URLProtocol)的組件來了解如何與不同類型數據源和目的地交互。

當提供input.mp4時,FFmpeg識別其為本地文件,內部通常視為file://input.mp4 URL。

隨后FFmpeg查找能處理file:// URL的"協議處理器"——即file協議。同理,output.avi也由file協議處理寫入。

這些協議處理器抽象了底層細節

FFmpeg主引擎只需要求輸入輸出層"打開此URL"、“讀取數據”、“寫入數據"或"關閉URL”,相應協議處理器執行實際工作,無論是調用文件系統函數、發起網絡請求還是與設備驅動交互。

FFmpeg I/O處理流程:

在這里插入圖片描述

  • FFmpeg告知輸入輸出層打開目標,輸入輸出層使用正確協議(如本例的file協議)與外部資源交互。
  • 隨后FFmpeg循環請求輸入數據并提供輸出數據直至完成,最終關閉所有資源。

超越本地文件:多樣化數據源與目的地

輸入輸出訪問層的強大之處在于其通過統一方式處理多種不同類型數據源和目的地的能力。

除本地文件外,FFmpeg還能讀寫:

  • 網絡流媒體:HTTP、RTMP、RTSP、TCP、UDP等,只需提供不同URL:

    ffmpeg -i http://example.com/video.mp4 output.avi
    ffmpeg -i input.mp4 rtmp://publish.example.com/app/streamkey
    

    此類情況使用httprtmp等專用協議,詳見FFmpeg文檔協議選項。

  • 捕獲/播放設備:攝像頭、麥克風、屏幕捕獲、視頻/音頻卡,通過操作系統特定的設備名或URL訪問:

    ffmpeg -f video4linux2 -i /dev/video0 output.mp4 # Linux攝像頭
    ffmpeg -f dshow -i video="集成攝像頭":audio="麥克風" output.mp4 # Windows攝像頭+麥克風
    

    使用設備特定的輸入輸出處理器(參見輸入設備和輸出設備)。

  • 標準輸入/輸出(管道):通過stdin讀取、stdout寫入,實現命令行工具鏈式調用:

    cat input.ts | ffmpeg -i pipe:0 output.mp4 # 從stdin讀取
    ffmpeg -i input.mp4 -f avi pipe:1 | ffplay pipe:0 # 寫入stdout
    

    通常使用pipefd協議。

核心思想保持不變:FFmpeg通過輸入輸出層獲取原始數據字節,無需關心字節獲取方式(通過各種上層協議的制定,實現了很好的抽象),只需確保可讀寫。


🎢協議解析結構體:AVIOContext與自定義數據源處理

在這里插入圖片描述

AVIOContext 與 URLProtocol

  • AVIOContext 是 FFmpeg 中用于抽象 I/O 操作的核心結構體,負責數據的讀寫緩沖和協議處理。

  • 它通過 URLProtocol 實現與具體協議(如文件、HTTP、RTMP等)的交互。

URLProtocol 是協議實現的接口,定義了一組標準函數(如打開、讀取、寫入、關閉等)。每種協議(如 file、http)需要實現自己的 URLProtocol 實例

協作流程

AVIOContext 初始化時綁定一個 URLProtocol

當用戶通過 AVIOContext 讀寫數據時,AVIOContext 會調用對應 URLProtocol 的函數。

例如,讀取 HTTP 數據時:

  1. AVIOContext 處理緩沖狀態管理
  2. 實際網絡請求由 HTTP 協議的 URLProtocol 實現完成。

聯系

  • AVIOContext 是上層抽象,提供統一的 I/O 接口。
  • URLProtocol 是底層實現,處理具體協議的細節。
  • 開發者通常只需操作 AVIOContext,無需直接調用 URLProtocol。

FFmpeg支持多種協議(HTTP、RTMP、RTSP、文件等)的多媒體數據獲取。其協議解析模塊通過三個核心結構體實現靈活的數據處理:

在這里插入圖片描述

核心結構體解析

1. AVIOContext

頭文件libavformat/avio.h
https://github.com/FFmpeg/FFmpeg/blob/master/libavformat/avio.h

關鍵字段

  • buffer:數據緩沖區
  • buffer_size:緩沖區容量
  • pos:當前讀取偏移量
  • opaque:指向用戶數據或URLContext
  • read_packet/write_packet讀寫回調函數

緩沖區關系
在這里插入圖片描述

2. URLContext

典型實現(以RTP協議為例):

typedef struct RTPContext 
{URLContext *rtp_hd, *rtcp_hd;int ttl;int buffer_size;// ...其他協議特定字段
} RTPContext;const URLProtocol ff_rtp_protocol = 
{.name = "rtp",.url_open = rtp_open,.url_read = rtp_read,.priv_data_size = sizeof(RTPContext),// ...其他回調函數
};

3. URLProtocol

作為協議實現的基類,定義標準操作接口:

  • url_open:建立協議連接
  • url_read/url_write:數據讀寫
  • priv_data_size:協議私有數據大小

URLProtocol是FFMPEG操作文件的結構(包括文件,網絡數據流等等),包括open、close、read、write、seek等操作。

定義了協議相關的回調函數,類似于url協議的虛函數定義

也類似門面模式,具體的回調函數的方法實現在ff_rtp_protocol等具體的對象中。

  • 門面模式通過一個統一的高層接口簡化復雜子系統調用,像前臺接待一樣隱藏內部細節

應用場景

標準協議處理

使用avformat_open_input即可完成:

AVFormatContext *fmt_ctx = NULL;
avformat_open_input(&fmt_ctx, "rtsp://example.com/stream", NULL, NULL);

自定義數據源處理

當需要處理以下特殊場景時需直接操作AVIOContext:

  1. 內存數據源
struct buffer_data {uint8_t *ptr; size_t size;
};static int read_packet(void *opaque, uint8_t *buf, int buf_size) {struct buffer_data *bd = opaque;// 實現自定義讀取邏輯
}
  1. 實時流處理(代碼示例)
// 創建自定義AVIOContext
avio_ctx = avio_alloc_context(avio_ctx_buffer, avio_ctx_buffer_size,0, &bd, &read_packet, NULL, NULL);// 關聯到FormatContext
fmt_ctx->pb = avio_ctx;
avformat_open_input(&fmt_ctx, NULL, NULL, NULL);
  1. 加密傳輸
static int decrypt_packet(void *opaque, uint8_t *buf, int buf_size) {// 解密邏輯實現return decrypt_data(buf, buf_size);
}

示例代碼

#include <libavformat/avformat.h>struct buffer_data {uint8_t *ptr;size_t size; 
};static int read_packet(void *opaque, uint8_t *buf, int buf_size) {struct buffer_data *bd = opaque;// 實現內存到緩沖區的拷貝邏輯
}int main() {// 初始化AVFormatContextAVFormatContext *fmt_ctx = avformat_alloc_context();// 創建自定義IO上下文AVIOContext *avio_ctx = avio_alloc_context(av_malloc(4096), 4096, 0, &bd, &read_packet, NULL, NULL);fmt_ctx->pb = avio_ctx;avformat_open_input(&fmt_ctx, NULL, NULL, NULL);// 后續處理流程...
}

運行測試前置條件:

sudo apt-get update
sudo apt-get install libavformat-dev libavutil-dev

運行:

gcc -o ffmpeg_buffer_test ffmpeg_buffer_test.c -lavformat -lavutil

在這里插入圖片描述

架構設計思想

FFmpeg通過分層設計實現協議處理的靈活性:

  1. 高層接口avformat_open_input封裝常規操作
  2. 擴展層AVIOContext提供自定義I/O接入點
  3. 協議實現層URLProtocol定義標準協議接口

這種設計使得開發者既能快速處理標準協議,又能通過自定義AVIOContext實現特殊需求,在易用性和靈活性之間取得平衡。


C語言API:AVIOContext與URLProtocol

對于使用FFmpeg庫(libavformat、libavcodec等)的開發人員,輸入輸出訪問層主要通過AVIOContext結構體和URLProtocol相關函數管理。

  • AVIOContext:表示I/O操作上下文,包含讀寫緩沖區及指向底層I/O函數的指針
  • URLProtocol:定義特定協議處理器,包含協議名("file""http""rtmp")及實現打開、讀寫、尋址、關閉等操作的函數指針

多數應用不直接操作URLProtocol,而是通過avio_open2等函數為給定URL創建AVIOContext

// API函數使用示例(非完整代碼)
AVFormatContext* fmt_ctx = avformat_alloc_context(); // 媒體文件格式上下文
AVIOContext* avio_ctx = NULL; // I/O操作上下文
char* input_url = "input.mp4";
int ret;// 使用avio_open2打開輸入URL并創建AVIOContext
ret = avio_open2(&avio_ctx, input_url, AVIO_FLAG_READ, NULL, NULL);
if (ret < 0) {// 錯誤處理
}fmt_ctx->pb = avio_ctx; // 將AVIOContext關聯到格式上下文// ...后續讀取數據...
uint8_t buffer[4096];
int bytes_read = avio_read(avio_ctx, buffer, sizeof(buffer));// ...關閉資源...
avio_close(avio_ctx);
// 注意:avio_context_free在關閉后釋放AVIOContext本身

該代碼段展示了核心函數:

  • avio_open2初始化
  • avio_read/avio_write數據傳輸
  • avio_close終止操作。

doc/APIchanges文件記錄了庫接口變更,包含諸多AVIOContext相關更新,例如avio_open2的引入、支持更多參數等。

示例代碼如

  • avio_list_dir.c展示了目錄協議交互
  • avio_read_callback.c演示了自定義I/O上下文

這些API細節主要面向使用FFmpeg庫的開發人員,證實輸入輸出訪問層(AVIOContextURLProtocol)是FFmpeg架構的基礎組成部分,專門負責原始數據字節的輸入輸出。

平時調api,最多用到avio,具體的數據結構和urlprotocol的實現我們并不關心,我們只需要調用,并且能輸入和輸出數據


總結

本章我們了解到,在FFmpeg解碼、編碼或處理多媒體數據前,必須首先讀取數據,處理完成后寫出數據。

這是輸入輸出訪問層的職責,它通過特定協議處理器為本地文件、網絡流和硬件設備等多樣化數據源/目的地提供統一處理方式

現在我們理解FFmpeg如何獲取原始字節,下一步是解析這些字節

多媒體數據通常封裝在容器格式(如MP4MKVAVI)中,這些容器提供結構和元數據。

下一章我們將探討FFmpeg如何處理這些容器。

容器處理


(抽象和協議的重要性)

統一接口設計 --前文傳送:

[xiaozhi-esp32] 應用層(9種state) | 音頻編解碼層 | 雙循環架構

[xiaozhi-esp32] 音頻處理 | Display | 純虛鎖的抽象思想

[Subtitle Edit] 字幕數據模型Paragraph | 核心邏輯庫(libse)

[shadPS4] 內存管理 | 權限管理 |文件系統 | 掛載和句柄

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

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

相關文章

微服務的編程測評系統2

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄前言工程創建創建ck-oj創建oj-modules創建具體微服務oj-system推送碼云管理員登錄邏輯分析docker安裝mysqldocker客戶端docker desktop安裝安裝mysqlmysql-plus和數據…

AR智能巡檢:電力運維的數字化變革

在電力行業快速發展的當下&#xff0c;傳統運維方式已難以滿足現代電網對高效、安全的需求。近年來&#xff0c;增強現實&#xff08;AR www.teamhelper.cn &#xff09;技術的興起為電力巡檢帶來了全新的解決方案。通過實時數據可視化、遠程協作和智能分析&#xff0c;AR技術…

NeRF和3DGS原理詳細

NeRF和3DGS一、傳統三維表征方法1.1 顯示表征1.2 隱式表征二、NeRF&#xff08;Nerual Radiance Field&#xff09;2.1 NeRF場景表示2.2 NeRF訓練流程2.3 NeRF體渲染2.4 NeRF位置編碼2.5 NeRF體素分層采樣&#xff08;Volume Hierarchical Sampling&#xff09;2.6 NeRF網絡結構…

035_ClaudeCode_MCP_介紹

035_ClaudeCode_MCP_介紹 摘要 Model Context Protocol&#xff08;MCP&#xff09;是一個開放的標準化協議&#xff0c;專為大型語言模型提供上下文數據而設計。作為Claude Code生態系統的重要組成部分&#xff0c;MCP如同"AI應用程序的USB-C端口"&#xff0c;提供…

Python 程序無法找到 Oracle 的 64 位客戶端庫 (libclntsh.so)

數據庫錯誤: DPI-1047: Cannot locate a 64-bit Oracle Client library: "libclntsh.so: cannot open shared object file: No such file or directory". See https://oracle.github.io/odpi/doc/installation.html#linux for help 這個錯誤表明 Python 程序無法找到…

Kubernetes常用命令總結

文章目錄Kubernetes常用命令總結1. 集群管理命令kubectl cluster-infokubectl get nodeskubectl describe node <node-name>kubectl top nodes2. Pod相關命令kubectl get podskubectl get pods -o widekubectl describe pod <pod-name>kubectl logs <pod-name&g…

roboflow使用教程

如何利用roboflow標注自己的訓練集、調用開源數據集 官網&#xff1a;Roboflow: Computer vision tools for developers and enterprises&#xff08;國內代理進不去&#xff09; 先注冊登陸進去 訓練自己的數據集 點擊“New Project”,名字按照自己的需求來 我不想寫了&am…

IDEA中使用Tomcat兩種方式

Catalogue1 集成本地Tomcat2 Tomcat Maven插件&#xff08;推薦&#xff09;1 集成本地Tomcat 將本地Tomcat集成到Idea中&#xff0c;然后進行項目部署即可 點擊編輯配置 點擊加號 添加local的Tomcat 配置Application Server 可以修改一下Name 至此&#xff0c;配置完成 …

服務器上的文件復制到本地 Windows 系統

在 Windows 上通過 SSH 連接到 Linux 服務器后&#xff0c;如果需要將服務器上的文件復制到本地 Windows 系統&#xff0c;可以使用以下幾種方法&#xff1a;方法 1&#xff1a;使用 scp&#xff08;Secure Copy&#xff09;命令 scp&#xff08;基于 SSH 的安全復制&#xff0…

大語言模型置信度增強實戰指南

LLM怎么簡單增強置信度 在大語言模型(LLM)的應用中,“置信度增強”核心目標是提升模型輸出的可靠性(減少錯誤/幻覺) 并讓模型更清晰地表達自身的不確定性(避免“一本正經地胡說”)。常用方式可分為“輸出優化”“知識補充”“校準調整”三大類, 一、基于“推理過程優…

NLP:人名分類器案例分享

本文目錄&#xff1a;一、案例介紹&#xff08;一&#xff09;關于人名分類&#xff08;二&#xff09;人名分類數據預覽二、案例步驟&#xff08;一&#xff09;導入工具包&#xff08;二&#xff09;數據預處理1. 獲取常用的字符數量2. 國家名種類數和個數3.讀數據到內存4.構…

3分鐘實戰!用DeepSeek+墨刀AI生成智能對話APP原型圖

如今&#xff0c;AI生成原型圖已經逐漸成為產品經理的一項常用輔助技能&#xff0c;不僅能加快設計進程&#xff0c;還能顯著提升前期溝通效率。最近我嘗試將大語言模型工具與AI原型工具結合測試&#xff0c;目標是看看是否能生成更高質量的原型頁面。直到我使用DeepSeek墨刀AI…

CentOS網絡配置與LAMP環境搭建指南

一、CentOS配置網絡1、查看網卡名稱ifconfig2、找到網卡對應配置文件網卡存放路徑 &#xff1a;/etc/sysconfig/network-scriptscd /etc/sysconfig/network-scripts3、修改網卡對應配置文件使用 vi/vim 打開文件&#xff0c;查看以下內容vim ifcfg-ens33將ONBOOTno 改為 ONBOOT…

TinyMCE 富文本編輯器在 vue2 中的使用 @tinymce/tinymce-vue

TinyMCE是一款功能強大、高度可定制的富文本編輯器。官方文檔 TinyMCE DOCS tinymce-vue包的版本4及更高版本支持Vue.js 3。但不支持Vue.js 2.x。對于Vue.js 2。X應用程序&#xff0c;使用tinymce-vue版本3。 安裝TinyMCE和Vue集成包 npm install tinymce/tinymce-vue3 tiny…

LP-MSPM0G3507學習--04GPIO控制

關鍵函數&#xff1a; DL_GPIO_readPins(GPIO_Regs* gpio, uint32_t pins):同時讀一組端口DL_GPIO_writePins(GPIO_Regs* gpio, uint32_t pins)&#xff1a;同時寫一組端口DL_GPIO_setPins(GPIO_Regs* gpio, uint32_t pins)&#xff1a;對指定某組端口的某管腳置高DL_GPIO_cle…

LVS(Linux virtual server)-實現四層負載均衡

一、簡介LVS:Linux Virtual Server&#xff0c;負載調度器&#xff0c;內核集成&#xff0c;章文嵩&#xff0c;阿里的四層SLB(Server LoadBalance)是基 于LVSkeepalived實現LVS 官網: http://www.linuxvirtualserver.org/二、LVS運行原理2.1LVS 的集群結構2.2lvs相關概念RS&am…

Kubernetes CNI網絡插件性能瓶頸排查與優化實踐

Kubernetes CNI網絡插件性能瓶頸排查與優化實踐 CNI&#xff08;Container Network Interface&#xff09;是 Kubernetes 網絡層的核心組件&#xff0c;不同 CNI 插件實現了容器間網絡通信、多租戶隔離、流量限速等功能。然而在大規模集群或高并發業務場景下&#xff0c;CNI 插…

20250720-6-Kubernetes 調度-nodeName字段,DaemonS_筆記

一、污點與容忍&#xfeff;1. 給節點添加污點&#xfeff;1&#xff09;命令格式基本語法&#xff1a;kubectl taint node [node] keyvalue:[effect]示例&#xff1a;kubectl taint node k8s-node1 gpuyes:NoSchedule操作說明&#xff1a;與打標簽命令類似&#xff0c;將"…

微軟開源項目 Detours 詳細介紹與使用實例分享

目錄 1、Detours概述 2、Detours功能特性 3、Detours工作原理 4、Detours應用場景 5、Detours兼容性 6、Detours具體使用方法 7、Detours使用實例 - 使用Detours攔截系統庫中的UnhandledExceptionFilter接口,實現對程序異常的攔截 C++軟件異常排查從入門到精通系列教程…

研發知識系統選型實戰:從 Notion 到 Gitee Wiki 的迭代經驗

關鍵詞&#xff1a;知識管理、版本控制、協作編輯、國產平臺、研發效能 在日常研發管理中&#xff0c;知識管理平臺往往被視為“非核心工具”&#xff0c;但它的好壞直接影響著團隊交接效率、文檔可用性以及協作深度。過去幾年&#xff0c;我們團隊先后使用過 Notion、Confluen…