国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

[音視頻處理] FFmpeg使用指北1-視頻解碼

這篇具有很好參考價值的文章主要介紹了[音視頻處理] FFmpeg使用指北1-視頻解碼。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

本文將詳細(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ù)
  • 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格式的音頻流。一般解封裝的流程如下:

  1. 在使用FFmpeg解碼音視頻文件時,需要通過AVFormatContext來獲取文件信息和流信息。AVFormatContext中包含AVInputFormat結(jié)構(gòu)體指針,指向當(dāng)前媒體文件的輸入格式。
  2. AVInputFormat結(jié)構(gòu)體描述了媒體文件的封裝格式,如MP4、AVI、MKV等。
  3. avformat_alloc_context用于創(chuàng)建并初始化AVFormatContext結(jié)構(gòu)體,為后續(xù)的音視頻文件解碼或編碼做好準(zhǔn)備。
  4. avformat_open_input用于打開音視頻文件并讀取文件信息到AVFormatContext結(jié)構(gòu)體中。
  5. avformat_find_stream_info用于獲取音視頻流信息并存儲到AVFormatContext結(jié)構(gòu)體中。
  6. 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ù)。一般解碼的流程如下:

  1. 每個AVStream結(jié)構(gòu)都存儲一個視頻/音頻流的相關(guān)數(shù)據(jù),例如流的編號、流的類型、流的碼率等等。AVStream結(jié)構(gòu)中還包含一個指向?qū)?yīng)AVCodecContext結(jié)構(gòu)的指針,該結(jié)構(gòu)用于存儲該視頻/音頻流解碼方式的所有信息,如編碼器的名稱、編碼器的屬性、編碼器的狀態(tài)等等。
  2. 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)字段。
  3. 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 widthint height:視頻的寬高。
  • int sample_rateint 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 widthint 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 widthint 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_ptsint64_t pkt_dts:分別表示這一幀所屬的AVPacket中的時間戳和解碼時間戳(Decode Time Stamp)。它們與pts的含義類似,但是它們是從AVPacket中直接獲取的,可能會存在一些偏差或不準(zhǔn)確的情況。
  • int sample_rateint 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 srcWint srcH:源圖像的寬度和高度。
  • int dstWint dstH:目標(biāo)圖像的寬度和高度。
  • enum AVPixelFormat srcFormatenum 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

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)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 音視頻處理工具FFmpeg與Java結(jié)合的簡單使用

    音視頻處理工具FFmpeg與Java結(jié)合的簡單使用

    一、什么是FFmpeg FFmpeg是一套可以用來記錄、轉(zhuǎn)換數(shù)字音頻、視頻,并能將其轉(zhuǎn)化為流的開源計算機程序。采用LGPL或GPL許可證。它提供了錄制、轉(zhuǎn)換以及流化音視頻的完整解決方案。它包含了非常先進(jìn)的音頻/視頻編解碼庫libavcodec,為了保證高可移植性和編解碼質(zhì)量,libavcod

    2024年02月11日
    瀏覽(91)
  • 音視頻 FFmpeg音視頻處理流程

    音視頻 FFmpeg音視頻處理流程

    推薦一個零聲學(xué)院項目課,個人覺得老師講得不錯,分享給大家: 零聲白金學(xué)習(xí)卡(含基礎(chǔ)架構(gòu)/高性能存儲/golang云原生/音視頻/Linux內(nèi)核) https://xxetb.xet.tech/s/VsFMs

    2024年02月12日
    瀏覽(97)
  • 【配置環(huán)境】安裝Ffmpeg音視頻編解碼工具和搭建EasyDarwin開源流媒體服務(wù)器

    【配置環(huán)境】安裝Ffmpeg音視頻編解碼工具和搭建EasyDarwin開源流媒體服務(wù)器

    目錄 一,安裝Ffmpeg音視頻編解碼工具 1,簡介 2,開發(fā)文檔 3,安裝部署 二,搭建EasyDarwin開源流媒體服務(wù)器 1,簡介 2,主要功能特點 3,安裝部署 4,效果圖 三,簡單測試 Ffmpeg是一套可以用來記錄、轉(zhuǎn)換數(shù)字音頻、視頻,并能將其轉(zhuǎn)化為流的開源計算機程序。采用LGPL或GPL許

    2024年02月07日
    瀏覽(122)
  • 【音視頻原理】音視頻 “ 采樣 - 編碼 - 封裝 過程 “ 和 “ 解封裝 - 解碼 - 播放 過程 “ 分析 ( 視頻采集處理流程 | 音頻采集處理流程 | 音視頻文件解封裝播放流程 )

    【音視頻原理】音視頻 “ 采樣 - 編碼 - 封裝 過程 “ 和 “ 解封裝 - 解碼 - 播放 過程 “ 分析 ( 視頻采集處理流程 | 音頻采集處理流程 | 音視頻文件解封裝播放流程 )

    本篇文件主要分析 音視頻文件 是怎么產(chǎn)生的 , 以及 音視頻文件是如何播放的 ; 視頻文件從錄像到生成文件的全過程 : 采集圖像幀 : 攝像頭 硬件 負(fù)責(zé) 采集畫面 , 采集的 初始畫面 稱為 \\\" 圖像幀 \\\" , 一秒鐘 采集 的 圖像幀 數(shù)量 稱為 \\\" 幀率 \\\" , 如 : 60 幀 就是 一秒鐘采集 60 個畫

    2024年02月11日
    瀏覽(103)
  • ffmpeg系列學(xué)習(xí)——FFmpeg的音視頻處理

    1.音視頻的采樣率、采樣位深度和聲道數(shù) 音頻和視頻的采樣率、采樣位深度和聲道數(shù)是媒體文件中的重要參數(shù),它們會直接影響到音視頻的質(zhì)量和文件大小。下面對它們進(jìn)行詳細(xì)解釋: 采樣率 采樣率指音頻每秒鐘采樣的次數(shù),用赫茲(Hz)表示。采樣率越高,音頻的還原度越

    2024年02月04日
    瀏覽(84)
  • FFmpeg源碼分析:avcodec_send_packet()與avcodec_receive_frame()音視頻解碼

    FFmpeg源碼分析:avcodec_send_packet()與avcodec_receive_frame()音視頻解碼

    FFmpeg在libavcodec模塊,舊版本提供avcodec_decode_video2()作為視頻解碼函數(shù),avcodec_decode_audio4()作為音頻解碼函數(shù)。在FFmpeg 3.1版本新增avcodec_send_packet()與avcodec_receive_frame()作為音視頻解碼函數(shù)。后來,在3.4版本把avcodec_decode_video2()和avcodec_decode_audio4()標(biāo)記為過時API。版本變更描述如下

    2024年02月03日
    瀏覽(94)
  • 「Python|音視頻處理|場景案例」如何使用ffmpeg下載m3u8視頻到本地并保存成mp4

    本文主要介紹如何使用ffmpeg批量下載視頻到本地并保存成指定格式。 當(dāng)我們希望將網(wǎng)頁上的視頻下載到本地的時候,我們可能獲取到的視頻地址是指向 .m3u8 格式的,當(dāng)視頻多的時候,手動下載并使用工具轉(zhuǎn)換格式就顯得工作量過大。 ffmpeg 是一個強大的音視頻處理工具,具體

    2024年02月16日
    瀏覽(34)
  • FFmpeg音視頻處理工具介紹及應(yīng)用

    FFmpeg音視頻處理工具介紹及應(yīng)用

    FFmpeg項目由 Fabrice Bellard在2000年創(chuàng)立。到目前為止,F(xiàn)Fmpeg項目的開發(fā)者仍然與VLC、MPV、dav1d、x264等多媒體開源項目有著廣泛的重疊。Ffmpeg(FastForward Mpeg)是一款遵循GPL的開源軟件,在音視頻處理方面表現(xiàn)十分優(yōu)秀,幾乎囊括了現(xiàn)存所有的視音頻格式的編碼,解碼、轉(zhuǎn)碼、混合

    2024年02月08日
    瀏覽(94)
  • JavaCV與FFmpeg:音視頻流處理技巧

    1. JavaCV簡介 JavaCV是一個開源的Java接口,為OpenCV、FFmpeg和其他類似工具提供了封裝。它允許Java開發(fā)者直接在他們的應(yīng)用程序中使用這些強大的本地庫,而無需深入了解復(fù)雜的本地代碼。JavaCV特別適用于處理圖像和視頻數(shù)據(jù),提供了一系列的功能,如圖像捕獲、處理和視頻編解

    2024年02月04日
    瀏覽(109)
  • 音視頻處理 ffmpeg中級開發(fā) H264編碼

    音視頻處理 ffmpeg中級開發(fā) H264編碼

    libavcodec/avcodec.h 常用的數(shù)據(jù)結(jié)構(gòu) AVCodec 編碼器結(jié)構(gòu)體 AVCodecContext 編碼器上下文 AVFrame 解碼后的幀 結(jié)構(gòu)體內(nèi)存的分配和釋放 av_frame_alloc 申請 av_frame_free() 釋放 avcodec_alloc_context3() 創(chuàng)建編碼器上下文 avcodec_free_context() 釋放編碼器上下文 解碼步驟 avcodec_find_decoder 查找解碼器 avcod

    2024年02月01日
    瀏覽(109)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包