網(wǎng)站建設排名奉節(jié)縣關鍵詞seo排名優(yōu)化
文章目錄
- 一、av_packet_ref 函數(shù)
- 1、函數(shù)原型
- 2、函數(shù)源碼分析
- 3、函數(shù)使用代碼示例
- 二、av_packet_clone 函數(shù)
- 1、函數(shù)原型
- 2、函數(shù)源碼分析
FFmpeg 4.0 版本源碼地址 :
- GitHub : https://github.com/FFmpeg/FFmpeg/tree/release/4.0
- GitCode : https://gitcode.com/gh_mirrors/ff/FFmpeg/tree/release/4.0
- FFmpeg/libavcodec/avpacket.c 源碼 : https://gitcode.com/gh_mirrors/ff/FFmpeg/blob/release/4.0/libavcodec/avpacket.c
一、av_packet_ref 函數(shù)
1、函數(shù)原型
av_packet_ref 函數(shù) 用于 將 源 AVPacket 結構體的屬性 和 buf 數(shù)據(jù)引用 拷貝復制給 目標 AVPacket 結構體 , AVPacket 中的 實際數(shù)據(jù) 不會進行復制 , 新創(chuàng)建的 AVPacket 只會復制 實際音視頻數(shù)據(jù)的 指針地址 , 函數(shù)原型如下 :
int av_packet_ref(AVPacket *dst, const AVPacket *src)
-
函數(shù)功能 :
- 將 src 的 結構體字段 復制到 dst ;
- 拷貝 數(shù)據(jù)的引用 , 并增加 src 中底層數(shù)據(jù)的引用計數(shù) ; 拷貝的是引用 , 不會對 src 中的實際數(shù)據(jù)緩沖區(qū)進行內(nèi)存復制 , 避免不必要的性能開銷 ;
-
參數(shù)解析 :
- AVPacket *dst 參數(shù) : 指向 目標 AVPacket 的指針 , 被賦值的對象 ;
- const AVPacket *src 參數(shù) : 指向 源 AVPacket 的指針 , 數(shù)據(jù)源 , 被拷貝的對象 ;
-
返回值 :
- 拷貝成功 , 返回 0 ;
- 拷貝失敗 , 返回 負值 , 該負值表示錯誤碼 ;
2、函數(shù)源碼分析
av_packet_ref 函數(shù)的源碼如下 :
- 分析該函數(shù)的源碼可知 , 該函數(shù)執(zhí)行兩個操作 , 分別是 :
- 第一步 : 復制 源 結構體 中的 字段值 到 目標結構體 中 ;
- 第二步 : 將 原結構體 的 數(shù)據(jù)緩沖區(qū) 引用 賦值給 目標 數(shù)據(jù)緩沖區(qū) 引用 , 注意 這里 只 復制引用 , 不復制數(shù)據(jù) ;
- 該函數(shù)中直接為 AVPacket 結構體字段輔助 , 因此執(zhí)行該函數(shù)之前 , 目標 AVPacket 必須是已經(jīng)分配好內(nèi)存 ;
int av_packet_ref(AVPacket *dst, const AVPacket *src)
{int ret;// 復制源包(src)的屬性到目標包(dst),包括時間戳、流索引等元數(shù)據(jù)。ret = av_packet_copy_props(dst, src);if (ret < 0) // 如果屬性復制失敗,則返回錯誤碼。return ret;// 檢查源包是否有緩沖區(qū) (buf),如果沒有,說明需要分配新的緩沖區(qū)。if (!src->buf) {// 為目標包分配緩沖區(qū),大小為源包的數(shù)據(jù)大小。ret = packet_alloc(&dst->buf, src->size);if (ret < 0) // 如果緩沖區(qū)分配失敗,跳轉到錯誤處理。goto fail;// 如果源包的數(shù)據(jù)大小不為 0,將數(shù)據(jù)從源包復制到目標包的緩沖區(qū)。if (src->size)memcpy(dst->buf->data, src->data, src->size);// 將目標包的 data 指針指向分配的緩沖區(qū)。dst->data = dst->buf->data;} else {// 如果源包有緩沖區(qū),通過引用計數(shù)創(chuàng)建緩沖區(qū)的引用。dst->buf = av_buffer_ref(src->buf);if (!dst->buf) { // 如果引用創(chuàng)建失敗,返回內(nèi)存分配錯誤。ret = AVERROR(ENOMEM);goto fail;}// 目標包的 data 指針直接指向源包的 data。dst->data = src->data;}// 將源包的大小復制到目標包。dst->size = src->size;// 如果執(zhí)行成功,返回 0。return 0;fail:// 如果發(fā)生錯誤,釋放目標包的附加數(shù)據(jù)(如 side data)以防止資源泄漏。av_packet_free_side_data(dst);return ret; // 返回錯誤碼。
}
3、函數(shù)使用代碼示例
代碼示例 :
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>int main() {AVPacket src_pkt, dst_pkt;// 初始化源包和目標包// av_init_packet 初始化 AVPacket 結構體,為其成員賦初始值。av_init_packet(&src_pkt);av_init_packet(&dst_pkt);// 為源包分配內(nèi)存并假設數(shù)據(jù)已填充// src_pkt.data 指向分配的 100 字節(jié)內(nèi)存,用于模擬填充數(shù)據(jù)。src_pkt.data = av_malloc(100);src_pkt.size = 100; // 數(shù)據(jù)大小設置為 100 字節(jié)。// 創(chuàng)建引用// av_packet_ref 創(chuàng)建目標包 dst_pkt 對源包 src_pkt 的引用。// 如果失敗,打印錯誤信息并返回 -1。if (av_packet_ref(&dst_pkt, &src_pkt) < 0) {fprintf(stderr, "Failed to create packet reference.\n");return -1;}// 此時,src_pkt 和 dst_pkt 共享同一底層數(shù)據(jù)// 打印源包和目標包的數(shù)據(jù)大小以驗證共享關系。printf("src size: %d, dst size: %d\n", src_pkt.size, dst_pkt.size);// 釋放引用// 使用 av_packet_unref 釋放源包和目標包的引用,減少引用計數(shù)。av_packet_unref(&src_pkt);av_packet_unref(&dst_pkt);return 0;
}
二、av_packet_clone 函數(shù)
1、函數(shù)原型
av_packet_clone 函數(shù) 用于 克隆一個完整的 AVPacket , 該函數(shù)實際上相當于 av_packet_alloc 函數(shù) + av_packet_ref 函數(shù) ;
AVPacket *av_packet_clone(const AVPacket *src)
- const AVPacket *src 參數(shù) : 指向 需要克隆的源 AVPacket 的指針 ;
- 返回值 :
- 拷貝成功 : 返回一個指向 新克隆的 AVPacket 的指針 ;
- 拷貝失敗 : 返回 NULL , 通常是因為內(nèi)存分配失敗 ;
2、函數(shù)源碼分析
在下面的 av_packet_clone 函數(shù)源碼中可以分析處 , av_packet_clone 函數(shù)相當于
av_packet_alloc 函數(shù) 和 av_packet_ref 函數(shù) 的總體效果 ;
在 av_packet_clone 函數(shù)中 , 先調(diào)用了 av_packet_alloc 函數(shù) , 創(chuàng)建 目標 AVPacket ,
然后調(diào)用 av_packet_ref 函數(shù) , 將 源 AVPacket 的 數(shù)據(jù)拷貝給 目標 AVPacket ;
AVPacket *av_packet_clone(const AVPacket *src)
{// 為克隆的包分配內(nèi)存并初始化。// 調(diào)用 av_packet_alloc 返回一個新的 AVPacket 指針,默認值為初始狀態(tài)。AVPacket *ret = av_packet_alloc();// 如果分配失敗,直接返回 NULL。if (!ret)return ret;// 使用 av_packet_ref 函數(shù)將源包 src 的數(shù)據(jù)和元信息復制到新包 ret 中。// av_packet_ref 返回非零值表示復制失敗。if (av_packet_ref(ret, src))// 如果復制失敗,釋放已分配的 AVPacket,并將 ret 置為 NULL。av_packet_free(&ret);// 返回克隆后的 AVPacket 指針(成功)或 NULL(失敗)。return ret;
}