本文將詳細(xì)介紹如何使用ffmpeg 4.4在C++中解碼多種格式的媒體文件,這些媒體文件可以是視頻、視頻流、圖片,或是桌面截屏或USB攝像頭的實時圖片。解碼文件后,還將每幀圖片轉(zhuǎn)換為OpenCV的Mat格式以供后續(xù)使用。
-
1 基于ffmpeg的媒體文件解碼
- 1.1 簡介
- 1.2 詳細(xì)代碼
-
2 ffmpeg函數(shù)解釋
-
2.1 解封裝
- AVFormatContext
- AVInputFormat
-
2.2 解碼
- AVStream
- AVCodecContext
- AVCodec
- AVCodecParameters
-
2.3 數(shù)據(jù)存儲
- AVPacket
- AVFrame
-
2.4 功能結(jié)構(gòu)
- AVRational
- SwsContext
- AVDictionary
- 其他函數(shù)
-
2.1 解封裝
-
3 參考
- 3.1 參考文章
- 3.2 ffmpeg結(jié)構(gòu)體
- 3.3 ffmpeg函數(shù)
1 基于ffmpeg的媒體文件解碼
1.1 簡介
在開始之前,需要先安裝FFmpeg。對于Windows用戶,可以參考FFmpeg + Visual studio 開發(fā)環(huán)境搭建;對于Linux用戶,可以參考FFmpeg4.4編譯。
本文主要參考了ffmpeg-libav-tutorial/0_hello_world.c提供的代碼。值得注意的是,由于FFmpeg版本變化較大,本文所使用的FFmpeg接口和以往有所不同。如果想進(jìn)一步學(xué)習(xí)FFmpeg代碼的使用,可以閱讀FFmpeg-libav-tutorial、ffmpeg-learning-indexes和視音頻編解碼技術(shù)零基礎(chǔ)學(xué)習(xí)方法(由于作者雷霄驊不幸英年早逝,哀悼!該文主要基于舊ffmpeg版本,但是仍然有很好的學(xué)習(xí)價值)。
涉及的步驟如下圖所示:
解封裝
在音視頻處理過程中,解封裝是指將輸入的音視頻文件進(jìn)行解析,提取出音頻流和視頻流等多種流媒體數(shù)據(jù),以便后續(xù)的數(shù)據(jù)處理和解碼。在解封裝過程中,首先需要判斷輸入源的格式,即判斷輸入的音視頻文件是屬于哪種格式。然后打開文件,查找流信息和視頻索引。
解碼
解碼是指將音視頻數(shù)據(jù)進(jìn)行解碼,將壓縮后的數(shù)據(jù)轉(zhuǎn)換成原始的音視頻數(shù)據(jù),以便后續(xù)的數(shù)據(jù)處理和播放。在解碼過程中,需要初始化解碼器,并打開解碼器。本文只解碼視頻,音頻則不進(jìn)行處理。
取數(shù)據(jù)
在取數(shù)據(jù)過程中,需要初始化數(shù)據(jù)結(jié)構(gòu),讀取視頻幀,并將視頻幀發(fā)送給解碼器。隨后,從解碼器獲取解碼結(jié)果。
數(shù)據(jù)處理
數(shù)據(jù)處理是指對音視頻數(shù)據(jù)進(jìn)行各種處理,比如色彩空間轉(zhuǎn)換、圖像尺寸變換、圖像格式轉(zhuǎn)換等。
釋放資源
在完成解碼和數(shù)據(jù)處理后,需要釋放結(jié)構(gòu)體,以釋放資源。釋放資源是指對音視頻處理過程中占用的各種資源進(jìn)行釋放,包括解碼器、數(shù)據(jù)結(jié)構(gòu)、緩沖區(qū)等。
1.2 詳細(xì)代碼
詳細(xì)代碼如下:
/**
* @brief 代碼主要參考https://github.com/leandromoreira/ffmpeg-libav-tutorial/blob/master/0_hello_world.c
*
*/
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavfilter/avfilter.h"
#include "libavformat/avformat.h"
#include "libavutil/avutil.h"
#include "libavutil/ffversion.h"
#include "libavutil/opt.h"
#include "libavutil/imgutils.h"
#include "libavutil/time.h"
#include "libswresample/swresample.h"
#include "libswscale/swscale.h"
#include "libavdevice/avdevice.h"
}
#include <stdio.h>
#include <stdlib.h>
#include <chrono>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <stdarg.h>
#include <string.h>
#include <inttypes.h>
// 日志打印宏
#define LOG(msg, ...)\
fprintf(stderr,"LOG [line %d] ",__LINE__);\
fprintf(stderr,msg, ##__VA_ARGS__);\
fprintf(stderr, "\n");
// 支持的輸入文件形式
enum URLType { file, usbcam, desktop, yuvfile };
// usb攝像頭讀取函數(shù)
void usbcam_get(const char * url, AVInputFormat ** ifmt);
// 解碼函數(shù)
static int decode_packet(AVPacket *pPacket, AVCodecContext *pCodecContext, AVFrame *pFrame, int skip = 0);
/**
* 涉及到結(jié)構(gòu)體
* AVFormatContext 存儲媒體文件所有信息的結(jié)構(gòu)體
* AVInputFormat 存儲媒體文件的格式信息
* AVStream 表示音視頻流信息的結(jié)構(gòu)體
* AVCodecContext 存儲解碼音視頻所有信息的結(jié)構(gòu)體
* AVCodec 存儲視頻或音頻的編解碼器的結(jié)構(gòu)體
* AVCodecParameters 存儲音視頻編解碼器的相關(guān)參數(shù)信息的結(jié)構(gòu)體
* AVPacket 儲存解碼前數(shù)據(jù)的結(jié)構(gòu)體
* AVFrame 存儲解碼后數(shù)據(jù)的結(jié)構(gòu)體
* AVRational 表示有理數(shù)的結(jié)構(gòu)體
* SwsContext 用于圖像轉(zhuǎn)換的結(jié)構(gòu)體
*/
int main()
{
// 設(shè)置數(shù)據(jù)類型
URLType urltype = yuvfile;
// 初始化結(jié)構(gòu)體
const char *url = NULL;
AVFormatContext *pFormatContext = NULL;
AVInputFormat *ifmt = NULL;
AVDictionary *options = NULL;
// AVCodec負(fù)責(zé)編解碼音視頻流
AVCodecContext *pCodecContext = NULL;
AVCodec *pCodec = NULL;
AVCodecParameters *pCodecParameters = NULL;
// 負(fù)責(zé)保存數(shù)據(jù)
AVPacket *pPacket = NULL;
AVFrame *pFrame = NULL;
LOG("FFMPEG VERSION: %s", av_version_info());
LOG("開始運行");
// 存儲音視頻封裝格式中包含的信息
// avformat_alloc_context初始化AVFormatContext結(jié)構(gòu)體
pFormatContext = avformat_alloc_context();
if (!pFormatContext)
{
LOG("pFormatContext分配內(nèi)存失敗");
return -1;
}
// 注冊能操作的輸入輸出設(shè)備
avdevice_register_all();
if (urltype == file)
{
// rtsp流
//url = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mp4";
// 輸入圖片
// url = "demo.png";
// 輸入視頻
url = "demo.mp4";
// 設(shè)置超時時間為5秒
av_dict_set(&options, "stimeout", "5000000", 0);
}
else if (urltype == usbcam)
{
url = "0";
// 如果使用以下方式讀取本機攝像頭,需要自行獲得攝像頭名稱
// 使用指令:ffmpeg -list_devices true -f dshow -i dummy
//url = "video=HD WebCam";
// 輸出ffmpeg版本
usbcam_get(url, &ifmt);
// 設(shè)置圖片尺寸
av_dict_set(&options, "video_size", "640x480", 0);
av_dict_set(&options, "framerate", "30", 0);
}
else if (urltype == desktop)
{
// Windows
#ifdef _WIN32
// 根據(jù)不同的url選擇不同的格式
url = "desktop";
ifmt = av_find_input_format("gdigrab");
// linux處理
#elif defined linux
// linux命令行輸入echo $DISPALY獲得
url = ":1";
ifmt = av_find_input_format("x11grab");
#endif
av_dict_set(&options, "video_size", "1920x1080", 0);
av_dict_set(&options, "framerate", "15", 0);
}
else if (urltype == yuvfile)
{
url = "akiyo_cif.yuv";
// yuv圖像尺寸需要提前設(shè)置
av_dict_set(&options, "video_size", "352x288", 0);
}
// avformat_open_input打開輸入的媒體文件
if (avformat_open_input(&pFormatContext, url, ifmt, &options) != 0)
{
LOG("打開文件失敗");
return -1;
}
LOG("打開文件 %s", url);
// 讀取文件音視頻編解碼器的信息
LOG("文件格式 %s, 文件時長 %lld us, 比特率 %lld bit/s",
pFormatContext->iformat->name,
pFormatContext->duration,
pFormatContext->bit_rate);
LOG("獲取輸入音視頻文件的流信息");
// avformat_find_stream_info獲取輸入音視頻文件的流信息
if (avformat_find_stream_info(pFormatContext, NULL) < 0)
{
LOG("無法獲取流信息");
return -1;
}
// 設(shè)置是否讀取到視頻流
int video_stream_index = -1;
// 循環(huán)瀏覽所有流并打印其主要信息
for (int i = 0; i < int(pFormatContext->nb_streams); i++)
{
AVCodecParameters *pLocalCodecParameters = NULL;
// 提取當(dāng)前流的編解碼器參數(shù)
pLocalCodecParameters = pFormatContext->streams[i]->codecpar;
AVCodec *pLocalCodec = NULL;
// 查找指定編解碼器的解碼器
pLocalCodec = avcodec_find_decoder(pLocalCodecParameters->codec_id);
if (pLocalCodec == NULL)
{
LOG("不支持該解碼器!");
continue;
}
// 當(dāng)流是視頻時,我們存儲其索引、解碼器和編解碼器參數(shù)
if (pLocalCodecParameters->codec_type == AVMEDIA_TYPE_VIDEO)
{
if (video_stream_index == -1)
{
video_stream_index = i;
pCodec = pLocalCodec;
pCodecParameters = pLocalCodecParameters;
}
LOG("視頻編解碼器類型: %s ID: %d", pLocalCodec->name, pLocalCodec->id);
LOG("視頻流幀率為:%f", av_q2d(pFormatContext->streams[i]->r_frame_rate));
LOG("視頻流共有:%d幀", pFormatContext->streams[i]->nb_frames);
LOG("視頻圖像分辨率為:(%d,%d)", pLocalCodecParameters->width, pLocalCodecParameters->height);
}
else if (pLocalCodecParameters->codec_type == AVMEDIA_TYPE_AUDIO)
{
LOG("音頻編解碼器類型: %s ID: %d", pLocalCodec->name, pLocalCodec->id);
LOG("音頻通道數(shù):%d channels, 采樣率:%d", pLocalCodecParameters->channels, pLocalCodecParameters->sample_rate);
}
}
if (video_stream_index == -1)
{
LOG("%s文件不包含視頻流!", url);
return -1;
}
// 分配AVCodecContext結(jié)構(gòu)體并進(jìn)行初始化
pCodecContext = avcodec_alloc_context3(pCodec);
if (!pCodecContext)
{
LOG("AVCodecContext初始失敗");
return -1;
}
// 將AVCodecParameters中的參數(shù)設(shè)置到AVCodecContext中
if (avcodec_parameters_to_context(pCodecContext, pCodecParameters) < 0)
{
LOG("AVCodecParameters參數(shù)拷貝失敗");
return -1;
}
// 打開解碼器
if (avcodec_open2(pCodecContext, pCodec, NULL) < 0)
{
LOG("打開解碼器失敗");
return -1;
}
// 創(chuàng)建AVPacket
pPacket = av_packet_alloc();
if (!pPacket)
{
LOG("AVPacket初始化失敗");
return -1;
}
// 創(chuàng)建AVFrame
pFrame = av_frame_alloc();
if (!pFrame)
{
LOG("AVFrame初始化失敗");
return -1;
}
int response = 0;
// 最多讀取幀數(shù)
int how_many_packets_to_process = 500;
// 幀處理跨度
int skip_span = 50;
// 讀取媒體文件中的音視頻幀
while (av_read_frame(pFormatContext, pPacket) >= 0)
{
// 判斷是否為視頻幀
if (pPacket->stream_index == video_stream_index)
{
// 只解碼關(guān)鍵幀,關(guān)鍵幀不依賴于其他幀進(jìn)行解碼,所以可以跳過其他幀
// 關(guān)鍵幀間隔由媒體流數(shù)據(jù)源決定
// if (!(pPacket->flags & AV_PKT_FLAG_KEY)) {
// continue;
//}
int skip = 1;
// 如果已讀取幀數(shù)除以skip_span為0,則下一幀進(jìn)行處理
if (pCodecContext->frame_number % skip_span == 0)
{
skip = 0;
}
// 計算時間
auto start = std::chrono::system_clock::now();
// 圖像解碼函數(shù)
response = decode_packet(pPacket, pCodecContext, pFrame, skip);
auto end = std::chrono::system_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
if (skip == 0)
{
LOG("解碼和處理一幀圖像耗時:%d ms", duration);
}
else
{
LOG("僅解碼一幀圖像耗時:%d ms", duration);
}
// 圖像解碼狀態(tài)判定
if (response < 0)
break;
// 超過讀取圖像上限
if (--how_many_packets_to_process <= 0)
{
LOG("讀圖完畢!");
break;
}
}
// 釋放AVPacket結(jié)構(gòu)體中的內(nèi)存
av_packet_unref(pPacket);
}
LOG("銷毀所有結(jié)構(gòu)體");
// 銷毀結(jié)構(gòu)體
avformat_close_input(&pFormatContext);
av_packet_free(&pPacket);
av_frame_free(&pFrame);
avcodec_free_context(&pCodecContext);
av_dict_free(&options);
system("pause");
return 0;
}
void usbcam_get(const char * url, AVInputFormat ** ifmt)
{
// Windows
#ifdef _WIN32
// 根據(jù)不同的url選擇不同的格式
if (url == "0")
*ifmt = av_find_input_format("vfwcap");
else
*ifmt = av_find_input_format("dshow");
// linux
#elif defined linux
url = "/dev/video0";
*ifmt = av_find_input_format("video4linux2");
#endif
}
static int decode_packet(AVPacket *pPacket, AVCodecContext *pCodecContext, AVFrame *pFrame, int skip)
{
// 將pPacket數(shù)據(jù)送入pCodecContext進(jìn)行解碼
int response = avcodec_send_packet(pCodecContext, pPacket);
if (response < 0)
{
return response;
}
while (response >= 0)
{
// 用于從解碼器中獲取解碼后的視頻幀
response = avcodec_receive_frame(pCodecContext, pFrame);
if (response == AVERROR(EAGAIN) || response == AVERROR_EOF)
{
break;
}
else if (response < 0)
{
LOG("讀圖出錯: %d", response);
return response;
}
// 僅讀取當(dāng)前幀
if (skip != 0)
{
return 0;
}
if (response >= 0)
{
LOG("Frame %d,幀類型=%c,視頻格式=%d,pts=%d,是否為關(guān)鍵幀=%d",
pCodecContext->frame_number,
av_get_picture_type_char(pFrame->pict_type),
pFrame->format,
pFrame->pts,
pFrame->key_frame);
// 圖像保存名
char frame_filename[1024];
snprintf(frame_filename, sizeof(frame_filename), "%s-%d.jpg", "frame", pCodecContext->frame_number);
// 將解碼后的幀轉(zhuǎn)換為BGR格式
// 創(chuàng)建圖像轉(zhuǎn)換器,設(shè)置圖像尺寸縮小一倍
int dst_w = int(pCodecContext->width / 2);
int dst_h = int(pCodecContext->height / 2);
SwsContext *swsCtx = sws_getContext(
pCodecContext->width, pCodecContext->height, (AVPixelFormat)pCodecContext->pix_fmt,
dst_w, dst_h, AV_PIX_FMT_BGR24,
SWS_POINT, NULL, NULL, NULL);
cv::Mat bgrMat(dst_h, dst_w, CV_8UC3);
// 拿出opencv的數(shù)據(jù)
uint8_t *dest[1] = { bgrMat.data };
int destStride[1] = { int(bgrMat.step) };
// 執(zhí)行格式轉(zhuǎn)換
sws_scale(swsCtx, pFrame->data, pFrame->linesize, 0, pFrame->height, dest, destStride);
// 保存圖片
cv::imwrite(frame_filename, bgrMat);
// 釋放swsCtx數(shù)據(jù)
sws_freeContext(swsCtx);
}
}
return 0;
}
以上代碼參考下圖閱讀最好。圖片來自ffmpeg-libav-tutorial/decoding.png。
如果是linux下使用該代碼文件還需編寫CMakeLists.txt,CMakeLists.txt內(nèi)容如下:
# 最低cmake版本
cmake_minimum_required(VERSION 3.2)
# 工程名
project(ffmpeg_demo)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR})
# --- opencv
find_package(OpenCV REQUIRED)
# --- ffmpeg
set(FFMPEG_INCLUDE_DIRS "/usr/local/include/")
set(FFMPEG_LIB_DIRS "/usr/local/lib/")
set(FFMPEG_LIBS "avcodec;avformat;avutil;swresample;avdevice;swscale")
include_directories(${FFMPEG_INCLUDE_DIRS})
link_directories(${FFMPEG_LIB_DIRS})
# 生成可執(zhí)行文件
add_executable(ffmpeg_demo demo.cpp)
target_link_libraries(ffmpeg_demo ${FFMPEG_LIBS} ${OpenCV_LIBS} pthread)
2 ffmpeg函數(shù)解釋
2.1 解封裝
解封裝的作用是從輸入的封裝格式數(shù)據(jù)(例如MP4、AVI、MKV)中提取視頻流壓縮編碼數(shù)據(jù)和音頻流壓縮編碼數(shù)據(jù)。封裝格式的作用是將已經(jīng)壓縮編碼的視頻數(shù)據(jù)和音頻數(shù)據(jù)按照一定的格式放在一起。例如,將MP4封裝格式的數(shù)據(jù)輸出H.264編碼格式的視頻流和AAC格式的音頻流。一般解封裝的流程如下:
- 在使用FFmpeg解碼音視頻文件時,需要通過AVFormatContext來獲取文件信息和流信息。AVFormatContext中包含AVInputFormat結(jié)構(gòu)體指針,指向當(dāng)前媒體文件的輸入格式。
- AVInputFormat結(jié)構(gòu)體描述了媒體文件的封裝格式,如MP4、AVI、MKV等。
- avformat_alloc_context用于創(chuàng)建并初始化AVFormatContext結(jié)構(gòu)體,為后續(xù)的音視頻文件解碼或編碼做好準(zhǔn)備。
- avformat_open_input用于打開音視頻文件并讀取文件信息到AVFormatContext結(jié)構(gòu)體中。
- avformat_find_stream_info用于獲取音視頻流信息并存儲到AVFormatContext結(jié)構(gòu)體中。
- avformat_close_input用于關(guān)閉音視頻文件并釋放AVFormatContext結(jié)構(gòu)體占用的內(nèi)存空間。
AVFormatContext
AVFormatContext是一個存儲流媒體相關(guān)信息的上下文結(jié)構(gòu)體(統(tǒng)領(lǐng)相關(guān)操作全局的結(jié)構(gòu)體)。幾乎所有的音視頻操作都需要先創(chuàng)建一個AVFormatContext對象。AVFormatContext使用完畢需要手動釋放內(nèi)存。AVFormatContext的主要屬性及使用說明:
-
AVInputFormat *iformat
:輸入格式結(jié)構(gòu)體指針,用于指定輸入文件的格式,一般由FFmpeg自動探測獲取。 -
AVOutputFormat *oformat
:輸出封裝格式的結(jié)構(gòu)體指針。 -
AVIOContext *pb
:輸入輸出的AVIOContext結(jié)構(gòu)體指針。 -
unsigned int nb_streams
:音視頻流個數(shù)。 -
int64_t duration
:音視頻文件的時長,單位為微秒(μs),一般由FFmpeg解析后賦值。 -
int64_t bit_rate
:音視頻文件的碼率,單位為bit/s,一般由FFmpeg解析后賦值。 -
AVStream **streams
:音視頻流列表的指針數(shù)組。 -
AVDictionary *metadata
:元數(shù)據(jù)信息,例如標(biāo)題、作者、描述等等。
該結(jié)構(gòu)體涉及以下函數(shù):
avformat_alloc_context
avformat_alloc_context用于分配AVFormatContext結(jié)構(gòu)體并初始化。該函數(shù)返回一個指向AVFormatContext結(jié)構(gòu)體的指針,如果分配失敗則返回NULL。
AVFormatContext *avformat_alloc_context(void);
avformat_open_input
avformat_open_input用于打開輸入的媒體文件,將音視頻文件的元數(shù)據(jù)信息讀取到AVFormatContext結(jié)構(gòu)體中。函數(shù)返回0表示成功打開文件。
int avformat_open_input(AVFormatContext ** ps,
const char * url,
const AVInputFormat * fmt,
AVDictionary ** options )
-
**ps
:指向AVFormatContext結(jié)構(gòu)體指針的指針,用于存放打開的媒體文件的相關(guān)信息。 -
*url
:輸入媒體文件的URL地址。可以是本地文件路徑或者網(wǎng)絡(luò)地址。 -
*fmt
:輸入媒體文件的格式,如果為NULL,則根據(jù)URL自動探測輸入媒體的格式。 -
**options
:輸入媒體文件的選項參數(shù)。
avformat_find_stream_info
avformat_find_stream_info用于獲取輸入文件的流信息。它會讀取輸入文件的所有數(shù)據(jù)包,并嘗試從中獲取流的參數(shù),如流的編解碼器、幀率、分辨率等等。在調(diào)用avformat_find_stream_info之后,可以通過 AVFormatContext結(jié)構(gòu)體中的streams字段訪問到每個流的詳細(xì)信息。函數(shù)返回值大于等于0表示成功。
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
-
ic
:指向AVFormatContext
結(jié)構(gòu)體的指針。 -
options
:指向AVDictionary
結(jié)構(gòu)體指針的指針,用于傳遞選項給解復(fù)用器。
avformat_close_input
avformat_close_input用于關(guān)閉AVFormatContext文件并釋放相關(guān)資源。一般情況下avformat_close_input和avformat_open_input成對使用,該函數(shù)也在內(nèi)部會調(diào)用avformat_free_context函數(shù)釋放AVFormatContext結(jié)構(gòu)體。
void avformat_close_input(AVFormatContext **ps);
-
ps
:指向AVFormatContext結(jié)構(gòu)體指針的指針,該指針會在函數(shù)執(zhí)行完畢后被置為NULL。
avformat_free_context
avformat_free_context用于釋放AVFormatContext結(jié)構(gòu)體。
void avformat_free_context(AVFormatContext * s)
-
ps
:指向AVFormatContext結(jié)構(gòu)體的指針。
AVInputFormat
AVInputFormat用于表示輸入的媒體文件的格式。主要作用為通過解析輸入的媒體文件,并將其轉(zhuǎn)換成FFmpeg內(nèi)部所使用的數(shù)據(jù)結(jié)構(gòu)。AVInputFormat結(jié)構(gòu)體的內(nèi)存由FFmpeg庫自動分配和釋放,在調(diào)用avformat_close_input函數(shù)后,F(xiàn)Fmpeg庫將自動釋放AVInputFormat結(jié)構(gòu)體。AVInputFormat的主要屬性及使用說明:
-
const char * name
:輸入文件類型的名稱。 -
const char * long_name
:輸入文件類型的詳細(xì)描述。 -
const char * extensions
:輸入文件類型的擴展名列表。
2.2 解碼
解碼的作用是將視頻或音頻壓縮編碼數(shù)據(jù)轉(zhuǎn)換成為非壓縮的視頻或音頻原始數(shù)據(jù)。例如將H.264的視頻壓縮數(shù)據(jù)解碼為逐幀YUV圖像數(shù)據(jù)。一般解碼的流程如下:
- 每個AVStream結(jié)構(gòu)都存儲一個視頻/音頻流的相關(guān)數(shù)據(jù),例如流的編號、流的類型、流的碼率等等。AVStream結(jié)構(gòu)中還包含一個指向?qū)?yīng)AVCodecContext結(jié)構(gòu)的指針,該結(jié)構(gòu)用于存儲該視頻/音頻流解碼方式的所有信息,如編碼器的名稱、編碼器的屬性、編碼器的狀態(tài)等等。
- AVCodecContext結(jié)構(gòu)中又包含一個指向?qū)?yīng)AVCodec結(jié)構(gòu)的指針,AVCodec結(jié)構(gòu)包含該視頻/音頻對應(yīng)的解碼器的基本信息,如編碼器的名稱、編碼器的類型、編碼器的能力等。當(dāng)需要使用某個編解碼器時,需要先通過編解碼器的名稱來查找對應(yīng)的AVCodec結(jié)構(gòu)體,然后再將這個結(jié)構(gòu)體中的信息賦值給AVCodecContext結(jié)構(gòu)體中的相應(yīng)字段。
- AVCodecParameters結(jié)構(gòu)體是一個描述編解碼器參數(shù)結(jié)構(gòu)體,它包含了一個編解碼器的參數(shù)信息,如編碼器的寬度、編碼器的高度、編碼器的碼率等等。對一個視頻或音頻流進(jìn)行編解碼時,需要使用AVCodecParameters結(jié)構(gòu)體來描述這個流的參數(shù)信息,然后再將這個結(jié)構(gòu)體中的信息賦值給AVCodecContext結(jié)構(gòu)體中的相應(yīng)字段。
AVStream
AVStream是FFmpeg中表示音視頻流的結(jié)構(gòu)體,每個AVStream結(jié)構(gòu)體都對應(yīng)一個視頻或音頻流的相關(guān)數(shù)據(jù)。AVStream結(jié)構(gòu)體的內(nèi)存由FFmpeg庫自動分配和釋放。AVStream的主要屬性及使用說明:
-
AVCodecParameters *codecpar
:指向AVCodecParameters結(jié)構(gòu)體的指針,存儲了該流的編解碼器參數(shù)。 -
AVRational ime_base
:時間基準(zhǔn),表示每個采樣的持續(xù)時間,以分?jǐn)?shù)形式表示。 -
int64_t start_time
:流的開始時間,以時間戳的形式表示。 -
int64_t duration
:流的持續(xù)時間,以時間戳的形式表示。 -
int64_t nb_frames
:該流中的幀數(shù)。 -
AVRational r_frame_rate
:用于表示實際幀率的AVRational結(jié)構(gòu)體。 -
AVRational avg_frame_rate
: 用于表示平均幀率的AVRational結(jié)構(gòu)體。
AVCodecContext
AVCodecContext包含解碼音視頻所有信息的上下文結(jié)構(gòu)體。在進(jìn)行音視頻編解碼時,通過對AVCodecContext的相關(guān)參數(shù)進(jìn)行設(shè)置,來控制編解碼器的行為。AVCodecContext使用完畢需要手動釋放內(nèi)存。AVCodecContext的一些常用參數(shù)包括:
-
enum AVCodecID codec_id
:指定音視頻編解碼器的ID。 -
AVRational time_base
:音視頻幀的時間基準(zhǔn),用于計算時間戳等。 -
int64_t bit_rate
:音視頻的比特率,影響編碼后的文件大小和質(zhì)量。 -
int width
和int height
:視頻的寬高。 -
int sample_rate
和int channels
:音頻的采樣率和聲道數(shù)。 -
enum AVPixelFormat pix_fmt
:視頻的像素格式,如YUV420P、RGB24等。 -
attribute_deprecated int frame_number
:獲得已處理幀數(shù),但是該屬性已經(jīng)被廢棄,因為如果編碼/解碼導(dǎo)致錯誤,則計數(shù)器不遞增。
該結(jié)構(gòu)體涉及以下函數(shù):
avcodec_alloc_context3
avcodec_alloc_context3函數(shù)用于分配AVCodecContext結(jié)構(gòu)體并進(jìn)行初始化。該函數(shù)返回一個指向AVCodecContext結(jié)構(gòu)體的指針,如果分配失敗則返回NULL。
AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);
-
codec
:指向AVCodec結(jié)構(gòu)體的指針,表示要使用的解碼器。
avcodec_parameters_to_context
avcodec_parameters_to_context函數(shù)的作用是將AVCodecParameters中的參數(shù)設(shè)置到AVCodecContext中。返回值小于0表示設(shè)置失敗。
int avcodec_parameters_to_context(AVCodecContext *codec, const AVCodecParameters *par);
-
AVCodecContext *codec
:需要設(shè)置參數(shù)的AVCodecContext結(jié)構(gòu)體指針。 -
const AVCodecParameters *par
:需要從中獲取參數(shù)的AVCodecParameters結(jié)構(gòu)體指針。
avcodec_open2
avcodec_open2用于打開AVCodec并初始化AVCodecContext。返回0表示成功,否則表示失敗。
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
-
avctx
:指向一個已經(jīng)分配好內(nèi)存的AVCodecContext
結(jié)構(gòu)體。 -
codec
:指向一個已經(jīng)注冊好的編碼器或解碼器的AVCodec
結(jié)構(gòu)體。 -
options
:指向一個AVDictionary
類型的指針,用于傳遞打開編碼器或解碼器時的參數(shù),可以為NULL。
avcodec_send_packet
avcodec_send_packet函數(shù)用于將一個未解碼的AVPacket數(shù)據(jù)送入解碼器AVCodecContext進(jìn)行解碼。該函數(shù)執(zhí)行成功后,解碼器AVCodecContext內(nèi)部的緩存將會被填充上相應(yīng)的數(shù)據(jù),可以通過調(diào)用avcodec_receive_frame函數(shù)來獲取解碼結(jié)果。返回值為0表示成功,否則表示失敗。
int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
-
avctx
:已經(jīng)被打開的編解碼器。 -
avpkt
:待解碼的AVPacket。
avcodec_receive_frame
avcodec_receive_frame用于從解碼器中獲取解碼后的視頻幀。avcodec_receive_frame一般會外嵌while循環(huán),可以保證在沒有接收到可用幀之前不會退出循環(huán),從而避免數(shù)據(jù)包丟失或者解碼錯誤的情況發(fā)生。
int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);
-
avctx
:解碼器對象。 -
frame
:存放解碼后的視頻幀的AVFrame對象。
返回值表示獲取到的視頻幀的狀態(tài),具體取值如下:
-
0
:成功獲取到一幀視頻幀。 -
AVERROR(EAGAIN)
:緩沖區(qū)中沒有可用的視頻幀,需要再次調(diào)用該函數(shù)。 -
AVERROR_EOF
:解碼器中的所有視頻幀都已經(jīng)讀取完成。
avcodec_free_context
avcodec_free_context函數(shù)用于釋放AVCodecContext結(jié)構(gòu)體所占用的內(nèi)存。
void avcodec_free_context(AVCodecContext **avctx);
-
avctx
: 指向需要釋放的AVCodecContext結(jié)構(gòu)體指針。`
AVCodec
AVCodec用于表示視頻或音頻的編解碼器。AVCodec數(shù)據(jù)結(jié)構(gòu)的內(nèi)存由FFmpeg庫自動分配和釋放。AVCodec的主要屬性及使用說明:
-
const char * name
:編解碼器的名稱。 -
const char * long_name
:編解碼器的詳細(xì)描述。 -
enum AVMediaType type
:表示編解碼器的類型,可以是視頻、音頻或其他類型。 -
enum AVCodecID id
:表示編解碼器的ID。 -
int capabilities
:表示編解碼器的功能特性,例如是否支持多線程等。 -
const AVRational * supported_framerates
:表示編解碼器支持的幀率列表。 -
enum AVPixelFormat * pix_fmts
:表示編解碼器支持的像素格式列表。 -
const int * supported_samplerates
:表示編解碼器支持的采樣率列表。 -
enum AVSampleFormat * sample_fmts
:表示編解碼器支持的采樣格式列表。
該結(jié)構(gòu)體涉及以下函數(shù):
avcodec_find_decoder
avcodec_find_decoder用于通過codec_id查找指定已經(jīng)注冊的解碼器。 如果找到了指定的解碼器,返回指向該解碼器的AVCodec指針。如果未找到指定的解碼器,返回 NULL。
AVCodec *avcodec_find_decoder(enum AVCodecID id);
-
id
:要查找的解碼器的AVCodecID格式codec_id,AVCodecID 是一個枚舉類型表示不同的編解碼器。。
AVCodecParameters
AVCodecParameters主要用于存儲音視頻編解碼器的相關(guān)參數(shù)信息。AVCodecParameters數(shù)據(jù)結(jié)構(gòu)的內(nèi)存由FFmpeg庫自動分配和釋放。AVCodecParameters常用屬性介紹:
-
enum AVMediaType codec_type
:音視頻流類型。 -
enum AVCodecID codec_id
:指定解碼器的ID,如AV_CODEC_ID_H264表示使用H.264解碼器。 -
int64_t bit_rate
:指定音視頻的比特率,單位為bps。 -
int width
和int height
:指定視頻的寬度和高度。 -
int channels
:表示聲道數(shù) -
int sample_rate
:指定音頻采樣率,單位為Hz。 -
uint8_t * extradata/int extradata_size
:指定音視頻流的附加數(shù)據(jù)和附加數(shù)據(jù)的大小。
2.3 數(shù)據(jù)存儲
AVPacket用于保存解碼前的數(shù)據(jù),AVFrame則用于保存解碼后的數(shù)據(jù)。在解碼器中,AVPacket中的數(shù)據(jù)會被解碼成AVFrame。在編碼器中,AVFrame中的數(shù)據(jù)會被編碼成AVPacket。
AVPacket
AVPacket是用于存儲壓縮音頻或視頻數(shù)據(jù)的結(jié)構(gòu)體。它包含了一段壓縮后的數(shù)據(jù)和對應(yīng)的時間戳信息,以及一些其他的附加信息,如數(shù)據(jù)流索引、關(guān)鍵幀標(biāo)識等。在解碼過程中,AVPacket會被送到解碼器中進(jìn)行解碼,得到AVFrame。AVPacket使用完畢需要手動釋放內(nèi)存。AVPacket的主要屬性如下:
-
uint8_t* data
:指向音視頻數(shù)據(jù)幀的指針。 -
int size
:音視頻數(shù)據(jù)幀的大小。 -
int64_t pts
:音視頻數(shù)據(jù)幀的顯示時間。 -
int64_t dts
:音視頻數(shù)據(jù)幀的解碼時間。 -
int stream_index
:音視頻數(shù)據(jù)幀所屬的流的索引。 -
int flags
:用于描述AVPacket的一些特性。常見選項如下:- AV_PKT_FLAG_KEY:表示該AVPacket所包含的數(shù)據(jù)是一個關(guān)鍵幀。
- AV_PKT_FLAG_CORRUPT:表示該AVPacket所包含的數(shù)據(jù)可能已經(jīng)損壞。當(dāng)解碼器無法正確解碼一個AVPacket時,就會設(shè)置該標(biāo)志位,通知應(yīng)用程序此AVPacket已經(jīng)損壞。
- AV_PKT_FLAG_DISCARD:表示該AVPacket所包含的數(shù)據(jù)可以被丟棄。當(dāng)解碼器對于某些時刻無法解碼出正確的圖像時,就會設(shè)置該標(biāo)志位??梢赃x擇丟棄該AVPacket,以保證視頻的流暢性。
- AV_PKT_FLAG_TRUSTED:表示該AVPacket所包含的數(shù)據(jù)是可信的。當(dāng)解碼器在解碼AVPacket時,會校驗AVPacket的CRC校驗碼,如果校驗碼正確,則會設(shè)置該標(biāo)志位。這個標(biāo)志位通常用于保證視頻的完整性,以防止篡改或者損壞。
該結(jié)構(gòu)體涉及以下函數(shù):
av_packet_alloc
av_packet_alloc用于創(chuàng)建AVPacket結(jié)構(gòu)體并為其分配內(nèi)存空間。函數(shù)返回一個指向新分配的AVPacket結(jié)構(gòu)體的指針。如果分配失敗,則返回NULL。
AVPacket *av_packet_alloc(void);
av_packet_unref
av_packet_unref函數(shù)用于清除AVPacket結(jié)構(gòu)體中的數(shù)據(jù),但是并不會釋放這個結(jié)構(gòu)體本身,以便可以重新使用或銷毀AVPacket結(jié)構(gòu)體。
void av_packet_unref(AVPacket *pkt);
-
pkt
:AVPacket結(jié)構(gòu)體指針。
av_packet_free
av_packet_free用于釋放AVPacket結(jié)構(gòu)體所占用內(nèi)存。
void av_packet_free(AVPacket **pkt);
-
pkt
:指向AVPacket結(jié)構(gòu)體指針的指針。
AVFrame
AVFrame是用于存儲解碼后的數(shù)據(jù)的結(jié)構(gòu)體。它包含了一幀圖像或音頻解碼后的數(shù)據(jù),以及一些相關(guān)的信息,如寬度、高度、像素格式等。在解碼過程中,AVFrame是解碼器輸出的數(shù)據(jù),它可以被送到渲染器中進(jìn)行渲染,也可以被編碼器編碼成新的AVPacket。AVFrame使用完畢需要手動釋放內(nèi)存。AVFrame結(jié)構(gòu)體中常用的屬性介紹和說明:
-
uint8_t * data
:指向一個指針數(shù)組,其中包含了這一幀的所有數(shù)據(jù)。對于視頻幀,通常包含了YUV或RGB數(shù)據(jù);對于音頻幀,通常包含了PCM數(shù)據(jù)。具體的數(shù)據(jù)格式和分布,可以通過其他參數(shù)進(jìn)行描述。 -
int linesize
:指向一個整型數(shù)組,用于描述每個數(shù)據(jù)平面的行大小(即每一行占用的字節(jié)數(shù))。對于視頻幀,通常會有三個數(shù)據(jù)平面(分別對應(yīng)Y、U、V或R、G、B三個分量);對于音頻幀,通常只有一個數(shù)據(jù)平面。linesize數(shù)組的大小應(yīng)該與data數(shù)組的大小相同。 -
uint8_t ** extended_data
:指向一個指針數(shù)組,其中包含了所有數(shù)據(jù)平面的指針。對于一些特殊的數(shù)據(jù)格式,data數(shù)組可能無法直接描述所有數(shù)據(jù)平面。這時,extended_data可以用于補充缺失的數(shù)據(jù)平面。 -
int width
和int height
:分別表示這一幀的寬度和高度。對于音頻幀,這兩個參數(shù)均為0。 -
int format
:表示這一幀的數(shù)據(jù)格式。對于視頻幀,常用的格式有YUV420、YUV422、YUV444、RGB24等;對于音頻幀,常用的格式有PCM_S16LE、PCM_S16BE、PCM_F32LE等。 -
int64_t pts
:表示這一幀在整個多媒體流中的時間戳(Presentation Time Stamp)。它通常以視頻幀率或音頻采樣率為單位,用于確定這一幀的播放時間。 -
int64_t pkt_pts
和int64_t pkt_dts
:分別表示這一幀所屬的AVPacket中的時間戳和解碼時間戳(Decode Time Stamp)。它們與pts的含義類似,但是它們是從AVPacket中直接獲取的,可能會存在一些偏差或不準(zhǔn)確的情況。 -
int sample_rate
和int channel_layout
:僅用于音頻幀,分別表示采樣率和聲道布局。其中,channel_layout可以用于指定聲道數(shù)和聲道位置的具體信息。 -
enum AVPictureType pict_type
:表示幀的圖像類型是I幀、P幀、B幀還是S幀。關(guān)鍵幀(I幀)是一種特殊的幀,它包含完整的圖像信息,不依賴于前面或后面的幀。P幀(預(yù)測幀)和B幀(雙向預(yù)測幀)則只包含部分圖像信息,需要參考前面或后面的幀才能正確解碼。通過使用關(guān)鍵幀,可以提高視頻的壓縮比以及解碼效率。S幀是跳幀,它直接復(fù)制前一幀的圖像,用于視頻壓縮。 -
int key_frame
:表示當(dāng)前幀是否為關(guān)鍵幀。
該結(jié)構(gòu)體涉及以下函數(shù):
av_frame_alloc
av_frame_alloc用于創(chuàng)建AVFrame結(jié)構(gòu)體并為其分配內(nèi)存空間。函數(shù)返回一個指向新分配的AVFrame結(jié)構(gòu)體的指針。如果分配失敗,則返回NULL。
AVFrame *av_frame_alloc(void);
av_read_frame
av_read_frame用于從AVFormatContext中讀取媒體文件中的音頻或視頻幀,并將數(shù)據(jù)存儲到AVPacket中。返回值為0表示讀取成功,為負(fù)數(shù)表示讀取失敗。
int av_read_frame(AVFormatContext *s, AVPacket *pkt);
-
s
: 指向表示媒體文件AVFormatContext結(jié)構(gòu)體的指針。 -
pkt
: 指向AVPacket結(jié)構(gòu)體的指針,用于存儲讀取到的音視頻幀的數(shù)據(jù)。
av_frame_free
av_frame_free函數(shù)用于釋放AVFrame結(jié)構(gòu)體占用的內(nèi)存空間。
void av_frame_free(AVFrame **frame);
-
frame
:需要釋放的AVFrame結(jié)構(gòu)體指針的地址。
2.4 功能結(jié)構(gòu)
AVRational
AVRational結(jié)構(gòu)體是FFmpeg中表示有理數(shù)的結(jié)構(gòu)體,用于表示時間戳、幀率、采樣率等一些基本的時間和頻率相關(guān)的屬性。AVRational結(jié)構(gòu)體包含兩個整型成員,num和den,分別表示分子和分母。用AVRational結(jié)構(gòu)體表示的有理數(shù)值為num/den。AVRational結(jié)構(gòu)體中的成員變量由FFmpeg內(nèi)部自動分配和釋放。AVRational屬性如下:
-
int num
: 有理數(shù)值的分子 -
int den
: 有理數(shù)值的分母
該結(jié)構(gòu)體涉及以下函數(shù):
av_q2d
av_q2d是一個用于將AVRational轉(zhuǎn)換為double類型的函數(shù),也就是將AVRational中的分子和分母相除。
double av_q2d(AVRational a);
-
a
:需要轉(zhuǎn)換的AVRational類型的數(shù)值。
SwsContext
SwsContext是FFmpeg中用于圖像轉(zhuǎn)換的數(shù)據(jù)結(jié)構(gòu),它包含了圖像轉(zhuǎn)換所需的所有參數(shù)。要注意的是該結(jié)構(gòu)體的原始定義在swscale_internal.h
文件中,普通編譯的ffmpeg工程沒有該文件。所以該結(jié)構(gòu)體一般僅僅是使用。SwsContext使用完畢需要手動釋放內(nèi)存。SwsContext的主要參數(shù)如下:
-
int srcW
和int srcH
:源圖像的寬度和高度。 -
int dstW
和int dstH
:目標(biāo)圖像的寬度和高度。 -
enum AVPixelFormat srcFormat
和enum AVPixelFormat dstFormat
:源圖像和目標(biāo)圖像的像素格式。 -
int flags
:圖像轉(zhuǎn)換時的一些特殊選項,如是否進(jìn)行區(qū)間縮放等。 -
double param
:一些額外的參數(shù),如亮度、對比度等。
在使用FFmpeg解碼時,默認(rèn)解碼后圖像的顏色格式為YUV420p,關(guān)于YUV420p介紹見YUV圖像處理入門1。
該結(jié)構(gòu)體涉及以下函數(shù):
sws_getContext
sws_getContext的作用是創(chuàng)建一個用于圖像轉(zhuǎn)換的SwsContext結(jié)構(gòu)體。如果創(chuàng)建成功,返回一個指向SwsContext結(jié)構(gòu)體的指針,否則返回NULL。函數(shù)原型如下:
struct SwsContext *sws_getContext(
int srcW,
int srcH,
enum AVPixelFormat srcFormat,
int dstW,
int dstH,
enum AVPixelFormat dstFormat,
int flags,
SwsFilter *srcFilter,
SwsFilter *dstFilter,
const double *param
);
-
srcW
:輸入圖像寬度。 -
srcH
:輸入圖像高度。 -
srcFormat
:輸入圖像像素格式。 -
dstW
:輸出圖像寬度。 -
dstH
:輸出圖像高度。 -
dstFormat
:輸出圖像像素格式。 -
flags
:轉(zhuǎn)換標(biāo)志,用于指定轉(zhuǎn)換算法和參數(shù)。常用設(shè)置如下:- SWS_FAST_BILINEAR:較快的雙線性轉(zhuǎn)換,適用于實時應(yīng)用,但可能會有些失真。
- SWS_BILINEAR:雙線性轉(zhuǎn)換,速度較快,但輸出質(zhì)量較低。
- SWS_BICUBIC:雙三次轉(zhuǎn)換,速度較慢,但輸出質(zhì)量較高。
- SWS_X:可自定義的轉(zhuǎn)換算法,速度和質(zhì)量取決于具體實現(xiàn)。
- SWS_POINT:轉(zhuǎn)換的速度非??斓淖罱彶逯邓惴?,但是轉(zhuǎn)換后的圖像質(zhì)量相對其他方法低。因為SWS_POINT將目標(biāo)像素點映射到圖像時,直接使用最近的像素點來進(jìn)行映射,會導(dǎo)致轉(zhuǎn)換后的圖像出現(xiàn)鋸齒狀的邊緣,而且圖像的細(xì)節(jié)信息也會丟失。
-
srcFilter
:輸入圖像過濾器,用于圖像縮放和裁剪。 -
dstFilter
:輸出圖像過濾器,用于圖像縮放和裁剪。 -
param
:轉(zhuǎn)換參數(shù),用于指定轉(zhuǎn)換算法的參數(shù)。
sws_scale
sws_scale用于執(zhí)行多種不同的像素格式轉(zhuǎn)換。sws_scale函數(shù)的返回值為輸出圖像的高度,返回值小于等于0表示轉(zhuǎn)換失敗。
int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[],
const int srcStride[], int srcSliceY, int srcSliceH,
uint8_t *const dst[], const int dstStride[]);
-
c
:可以通過sws_getContext函數(shù)獲取。 -
srcSlice[]
:輸入圖像數(shù)據(jù)指針數(shù)組。 -
srcStride[]
:輸入圖像每行的字節(jié)數(shù)組。 -
srcSliceY
:輸入圖像的起始行。 -
srcSliceH
:輸入圖像的高度。 -
dst[]
:輸出圖像數(shù)據(jù)指針數(shù)組。 -
dstStride[]
:輸出圖像每行的字節(jié)數(shù)組。
sws_freeContext
sws_freeContext的作用是釋放SwsContext結(jié)構(gòu)體占用的內(nèi)存空間,避免內(nèi)存泄露。
void sws_freeContext(struct SwsContext *context);
-
context
:要釋放的SwsContext結(jié)構(gòu)體指針。
AVDictionary
AVDictionary是FFmpeg中的一個字典結(jié)構(gòu)體,用于存儲鍵值對數(shù)據(jù)。AVDictionary使用后一般不需要手動釋放內(nèi)存,但是建議手動釋放內(nèi)存。以下是AVDictionary屬性的說明:
-
int count
:AVDictionary中鍵值對的數(shù)量。 -
AVDictionaryEntry * elems
:指向AVDictionaryEntry結(jié)構(gòu)體數(shù)組的指針,每個元素包含一個鍵值對。
該結(jié)構(gòu)體涉及以下函數(shù):
av_dict_set
av_dict_set用于向字典中添加或修改鍵值對。該函數(shù)的返回值為0表示成功,否則表示失敗。av_dict_set可以設(shè)置的有效鍵值對需要參閱。
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
-
pm
:指向字典指針的指針。 -
key
:要添加或修改的鍵名。 -
value
:要添加或修改的鍵值。 -
flags
:標(biāo)志位,控制鍵名是否可以覆蓋已存在的鍵名。
av_dict_free
av_dict_free用于釋放字典(dictionary)結(jié)構(gòu)體占用的內(nèi)存空間。
void av_dict_free(AVDictionary **m)
-
m
:指向AVDictionary指針的指針。
其他函數(shù)
avdevice_register_all
avdevice_register_all用于注冊所有可用的音視頻輸入/輸出設(shè)備,以方便進(jìn)行數(shù)據(jù)采集。
void avdevice_register_all(void);
av_find_input_format文章來源:http://www.zghlxwxcb.cn/news/detail-465581.html
av_find_input_format用于查找輸入視頻流格式。該函數(shù)返回值是一個指向AVInputFormat結(jié)構(gòu)體的指針。文章來源地址http://www.zghlxwxcb.cn/news/detail-465581.html
AVInputFormat *av_find_input_format(const char *short_name);
-
short_name
是待查找的輸入流格式的短名稱。短名稱是該格式的簡稱,例如:- mp4:表示MP4格式。
- vfwcap:是一個視頻捕獲設(shè)備的輸入格式,用于Windows平臺。它使用VFW(Video for Windows)API來捕獲視頻數(shù)據(jù)。
- dshow:是一個視頻捕獲設(shè)備的輸入格式,用于Windows平臺。它使用DirectShow API來捕獲視頻數(shù)據(jù)。
- video4linux2:是一個視頻捕獲設(shè)備的輸入格式,用于Linux平臺。它使用Video4Linux2 API來捕獲視頻數(shù)據(jù)。
- gdigrab:用于在Windows上捕獲屏幕的輸入格式。
- x11grab:用于在Linux上捕獲屏幕的輸入格式。
3 參考
3.1 參考文章
- FFmpeg + Visual studio 開發(fā)環(huán)境搭建
- ffmpeg4.4編譯
- ffmpeg-libav-tutorial/0_hello_world.c
- ffmpeg-libav-tutorial
- ffmpeg-learning-indexes
- 視音頻編解碼技術(shù)零基礎(chǔ)學(xué)習(xí)方法
- ffmpeg-libav-tutorial/decoding.png
- YUV圖像處理入門1
3.2 ffmpeg結(jié)構(gòu)體
- AVFormatContext
- AVInputFormat
- AVStream
- AVCodecContext
- AVCodec
- AVCodecParameters
- AVPacket
- AVFrame
- AVRational
- SwsContext
- AVDictionary
3.3 ffmpeg函數(shù)
- avformat_alloc_context
- avformat_open_input
- avformat_find_stream_info
- avformat_close_input
- avformat_free_context
- avcodec_find_decoder
- avcodec_parameters_to_context
- avcodec_open2
- avcodec_send_packet
- avcodec_receive_frame
- avcodec_free_context
- av_packet_alloc
- av_packet_unref
- av_packet_free
- av_frame_alloc
- av_read_frame
- av_frame_free
- av_q2d
- sws_getContext
- sws_scale
- sws_freeContext
- av_dict_set
- av_dict_free
- avdevice_register_all
- av_find_input_format
到了這里,關(guān)于[音視頻處理] FFmpeg使用指北1-視頻解碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!