1、背景
FFmpeg 是音視訊開發中最常用到的開源軟體,許多商業軟體都以 FFmpeg 為基礎進行開發定制。 由于近期工作中的項目涉及到了音視訊相關開發,本系列文章用來整理和記錄在使用 FFmpeg 開發過程中的一些學習經驗,以備之後的查閱。
2、視訊播放基本原理
上圖來源于網上,描述了視訊播放的基本原理。即:要實作一個視訊播放器,需要完整實作上圖中的每一個過程。 本文先從打開視訊檔案開始,記錄怎麼使用 FFmpeg 打開一個視訊檔案。
3、打開視訊檔案
3.1 概述
在進行音視訊解碼之前,需要先打開媒體檔案,以擷取其中包含的音/視訊流的相關資訊。打開音視訊檔案包含以下步驟:
3.2 建立 FFmpegPlayer 類
C++音視訊學習資料免費擷取方法:關注音視訊開發T哥,點選「連結」即可免費擷取2023年最新C++音視訊開發進階獨家免費學習大禮包!
建立一個 FFmpegPlayer 類用于對相關資源進行管理:
class FFmpegPlayer {
public:
explicit FFmpegPlayer(const char* m_url);
~FFmpegPlayer();
public:
bool openFile();//打開檔案
private:
std::string url;//檔案路徑
AVFormatContext* formatContext = nullptr;//封裝格式上下文
};
實作 openFile 接口:
bool FFmpegPlayer::openFile() {
// 建立 formatContext
formatContext = avformat_alloc_context();
if( !formatContext )
{
avformat_close_input(&formatContext);
return false;
}
// 打開檔案
if (avformat_open_input(&formatContext, url.c_str(), nullptr, nullptr) != 0)
{
if( !formatContext ) {
avformat_close_input(&formatContext);
}
return false;
}
// 查找輸入流資訊
if (avformat_find_stream_info(formatContext, nullptr) < 0)
{
if( !formatContext ) {
avformat_close_input(&formatContext);
}
return false;
}
// 查找音視訊流索引
int video_index = av_find_best_stream(formatContext, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
int audio_index = av_find_best_stream(formatContext, AVMEDIA_TYPE_AUDIO, -1, video_index, nullptr, 0);
//列印視訊資訊
std::cout <<"視訊流索引:" << video_index <<std::endl;
std::cout <<"音頻流索引:" << audio_index<<std::endl;
std::cout <<"時長:"<< formatContext->duration / AV_TIME_BASE <<std::endl;
std::cout <<"視訊寬度:" << formatContext->streams[video_index]->codecpar->width << std::endl;
std::cout <<"視訊高度:" << formatContext->streams[video_index]->codecpar->height << std::endl;
auto frame_rate = av_guess_frame_rate(formatContext, formatContext->streams[video_index], nullptr);
std::cout <<"幀率:" << (double )frame_rate.num / frame_rate.den << std::endl;
return true;
}
3.3 運作示例
傳入視訊檔案路徑,打開檔案:
#include "FFmpegPlayer.h"
int main() {
const char * url = "C:\\Users\\111111\\Desktop\\ts\\0.ts";
FFmpegPlayer * player = new FFmpegPlayer(url);
if( player->openFile())
{
std::cout << "檔案打開成功!"<<std::endl;
}
return 0;
}
代碼運作結果如下:
原文連結:FFmpeg 入門學習 01--打開視訊檔案