SDK下载 github
环境变量配置
cmake_modules/FindFFmpeg.cmake
# This module defines the following variables:
#
# FFmpeg_FOUND - All required components and the core library were found
# FFmpeg_INCLUDE_DIRS - Combined list of all components include dirs
# FFmpeg_LIBRARIES - Combined list of all components libraries
# FFmpeg_VERSION - Version defined in libavutil/ffversion.h
#
# ffmpeg::ffmpeg - FFmpeg target
#
# For each requested component the following variables are defined:
#
# FFmpeg_<component>_FOUND - The component was found
# FFmpeg_<component>_INCLUDE_DIRS - The components include dirs
# FFmpeg_<component>_LIBRARIES - The components libraries
# FFmpeg_<component>_VERSION - The components version
#
# ffmpeg::<component> - The component target
#
# Usage:
# find_package(FFmpeg REQUIRED)
# find_package(FFmpeg 5.1.2 COMPONENTS avutil avcodec avformat avdevice avfilter REQUIRED)
find_package(PkgConfig QUIET)
# find the root dir for specified version
function(find_ffmpeg_root_by_version EXPECTED_VERSION)
set(FFMPEG_FIND_PATHS $ENV{PATH} $ENV{FFMPEG_PATH} $ENV{FFMPEG_ROOT} /opt /usr /sw)
set(FOUND_VERSION)
set(FOUND_ROOT_DIR)
foreach(ROOT_DIR ${FFMPEG_FIND_PATHS})
unset(FFMPEG_VERSION_HEADER CACHE)
find_file(
FFMPEG_VERSION_HEADER
NAMES "ffversion.h"
PATHS ${ROOT_DIR} ${ROOT_DIR}/include ${ROOT_DIR}/include/${CMAKE_LIBRARY_ARCHITECTURE}
PATH_SUFFIXES libavutil
NO_DEFAULT_PATH
)
mark_as_advanced(FFMPEG_VERSION_HEADER)
if(NOT "${FFMPEG_VERSION_HEADER}" STREQUAL "FFMPEG_VERSION_HEADER-NOTFOUND")
file(STRINGS "${FFMPEG_VERSION_HEADER}" FFMPEG_VERSION_STRING REGEX "FFMPEG_VERSION")
# #define FFMPEG_VERSION "6.0-full_build-www.gyan.dev"
# fixme: #define FFMPEG_VERSION "N-111059-gd78bffbf3d"
string(REGEX REPLACE "#define FFMPEG_VERSION[ \t]+\"[n]?([0-9\\.]*).*\"" "\\1" CURRENT_VERSION "${FFMPEG_VERSION_STRING}")
set(CURRENT_VERSION ${FFmpeg_FIND_VERSION})
# not specified, return the first one
if("${EXPECTED_VERSION}" STREQUAL "")
set(FOUND_VERSION ${CURRENT_VERSION})
set(FOUND_ROOT_DIR ${ROOT_DIR})
break()
endif()
# otherwise, the minimum one of suitable versions
if(${CURRENT_VERSION} VERSION_GREATER_EQUAL "${EXPECTED_VERSION}")
if((NOT FOUND_VERSION) OR(${CURRENT_VERSION} VERSION_LESS "${FOUND_VERSION}"))
set(FOUND_VERSION ${CURRENT_VERSION})
set(FOUND_ROOT_DIR ${ROOT_DIR})
endif()
endif()
endif()
endforeach()
set(FFmpeg_VERSION ${FOUND_VERSION} PARENT_SCOPE)
set(FFmpeg_ROOT_DIR ${FOUND_ROOT_DIR} PARENT_SCOPE)
endfunction()
# find a ffmpeg component
function(find_ffmpeg_component ROOT_DIR COMPONENT HEADER)
# header
find_path(
FFmpeg_${COMPONENT}_INCLUDE_DIR
NAMES "lib${COMPONENT}/${HEADER}" "lib${COMPONENT}/version.h"
PATHS ${ROOT_DIR} ${ROOT_DIR}/include/${CMAKE_LIBRARY_ARCHITECTURE}
PATH_SUFFIXES ffmpeg libav include
NO_DEFAULT_PATH
)
# version
if(EXISTS "${FFmpeg_${COMPONENT}_INCLUDE_DIR}/lib${COMPONENT}/version.h")
if(EXISTS "${FFmpeg_${COMPONENT}_INCLUDE_DIR}/lib${COMPONENT}/version_major.h")
file(STRINGS "${FFmpeg_${COMPONENT}_INCLUDE_DIR}/lib${COMPONENT}/version_major.h" MAJOR_VERSION_STRING REGEX "^.*VERSION_MAJOR[ \t]+[0-9]+[ \t]*$")
endif()
# other
file(STRINGS "${FFmpeg_${COMPONENT}_INCLUDE_DIR}/lib${COMPONENT}/version.h" VERSION_STRING REGEX "^.*VERSION_(MAJOR|MINOR|MICRO)[ \t]+[0-9]+[ \t]*$")
list(APPEND VERSION_STRING ${MAJOR_VERSION_STRING})
string(REGEX REPLACE ".*VERSION_MAJOR[ \t]+([0-9]+).*" "\\1" MAJOR "${VERSION_STRING}")
string(REGEX REPLACE ".*VERSION_MINOR[ \t]+([0-9]+).*" "\\1" MINOR "${VERSION_STRING}")
string(REGEX REPLACE ".*VERSION_MICRO[ \t]+([0-9]+).*" "\\1" PATCH "${VERSION_STRING}")
set(FFmpeg_${COMPONENT}_VERSION "${MAJOR}.${MINOR}.${PATCH}" PARENT_SCOPE)
else()
message(STATUS "'${FFmpeg_${COMPONENT}_INCLUDE_DIR}/lib${COMPONENT}/version.h' does not exist.")
endif()
# library
if(WIN32)
find_library(
FFmpeg_${COMPONENT}_IMPLIB
NAMES "${COMPONENT}" "lib${COMPONENT}"
PATHS ${ROOT_DIR} ${ROOT_DIR}/lib/${CMAKE_LIBRARY_ARCHITECTURE}
PATH_SUFFIXES lib lib64 bin bin64
NO_DEFAULT_PATH
)
find_program(
FFmpeg_${COMPONENT}_LIBRARY
NAMES "${COMPONENT}-${MAJOR}.dll" "${COMPONENT}.dll"
PATHS ${ROOT_DIR} ${ROOT_DIR}/bin
NO_DEFAULT_PATH
)
else()
find_library(
FFmpeg_${COMPONENT}_LIBRARY
NAMES "${COMPONENT}" "lib${COMPONENT}"
PATHS ${ROOT_DIR} ${ROOT_DIR}/lib/${CMAKE_LIBRARY_ARCHITECTURE}
PATH_SUFFIXES lib lib64 bin bin64
NO_DEFAULT_PATH
)
endif()
mark_as_advanced(FFmpeg_${COMPONENT}_INCLUDE_DIR FFmpeg_${COMPONENT}_LIBRARY FFmpeg_${COMPONENT}_IMPLIB)
if(FFmpeg_${COMPONENT}_INCLUDE_DIR AND FFmpeg_${COMPONENT}_LIBRARY)
set(FFmpeg_${COMPONENT}_FOUND TRUE PARENT_SCOPE)
set(FFmpeg_${COMPONENT}_IMPLIBS ${FFmpeg_${COMPONENT}_IMPLIB} PARENT_SCOPE)
set(FFmpeg_${COMPONENT}_LIBRARIES ${FFmpeg_${COMPONENT}_LIBRARY} PARENT_SCOPE)
set(FFmpeg_${COMPONENT}_INCLUDE_DIRS ${FFmpeg_${COMPONENT}_INCLUDE_DIR} PARENT_SCOPE)
endif()
endfunction()
# start finding
if(NOT FFmpeg_FIND_COMPONENTS)
list(APPEND FFmpeg_FIND_COMPONENTS avutil avcodec avdevice avfilter avformat swresample swscale postproc)
endif()
find_ffmpeg_root_by_version("${FFmpeg_FIND_VERSION}")
if((NOT FFmpeg_VERSION) OR(NOT FFmpeg_ROOT_DIR))
message(FATAL_ERROR "Can not find the suitable version.")
endif()
list(REMOVE_DUPLICATES FFmpeg_FIND_COMPONENTS)
foreach(COMPONENT ${FFmpeg_FIND_COMPONENTS})
if(COMPONENT STREQUAL "postproc")
find_ffmpeg_component(${FFmpeg_ROOT_DIR} ${COMPONENT} "postprocess.h")
else()
find_ffmpeg_component(${FFmpeg_ROOT_DIR} ${COMPONENT} "${component}.h")
endif()
if(FFmpeg_${COMPONENT}_FOUND)
list(APPEND FFmpeg_LIBRARIES ${FFmpeg_${COMPONENT}_LIBRARIES})
list(APPEND FFmpeg_INCLUDE_DIRS ${FFmpeg_${COMPONENT}_INCLUDE_DIRS})
endif()
endforeach()
list(REMOVE_DUPLICATES FFmpeg_LIBRARIES)
list(REMOVE_DUPLICATES FFmpeg_INCLUDE_DIRS)
#
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
FFmpeg
FOUND_VAR FFmpeg_FOUND
REQUIRED_VARS FFmpeg_ROOT_DIR FFmpeg_INCLUDE_DIRS FFmpeg_LIBRARIES
VERSION_VAR FFmpeg_VERSION
HANDLE_COMPONENTS
)
if(FFmpeg_FOUND)
if(NOT TARGET ffmpeg::ffmpeg)
add_library(ffmpeg::ffmpeg INTERFACE IMPORTED)
endif()
foreach(component IN LISTS FFmpeg_FIND_COMPONENTS)
if(FFmpeg_${component}_FOUND AND NOT TARGET ffmpeg::${component})
if(IS_ABSOLUTE "${FFmpeg_${component}_LIBRARIES}")
if(DEFINED FFmpeg_${component}_IMPLIBS)
if(FFmpeg_${component}_IMPLIBS STREQUAL FFmpeg_${component}_LIBRARIES)
add_library(ffmpeg::${component} STATIC IMPORTED)
else()
add_library(ffmpeg::${component} SHARED IMPORTED)
set_property(TARGET ffmpeg::${component} PROPERTY IMPORTED_IMPLIB "${FFmpeg_${component}_IMPLIBS}")
endif()
else()
add_library(ffmpeg::${component} UNKNOWN IMPORTED)
endif()
set_property(TARGET ffmpeg::${component} PROPERTY IMPORTED_LOCATION "${FFmpeg_${component}_LIBRARIES}")
else()
add_library(ffmpeg::${component} INTERFACE IMPORTED)
set_target_properties(ffmpeg::${component} PROPERTIES IMPORTED_LIBNAME "${FFmpeg_${component}_LIBRARIES}")
endif()
set_target_properties(ffmpeg::${component} PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${FFmpeg_${component}_INCLUDE_DIRS}"
VERSION "${FFmpeg_${component}_VERSION}"
)
get_target_property(FFMPEG_INTERFACE_LIBRARIES ffmpeg::ffmpeg INTERFACE_LINK_LIBRARIES)
if(NOT ffmpeg::${component} IN_LIST FFMPEG_INTERFACE_LIBRARIES)
set_property(TARGET ffmpeg::ffmpeg APPEND PROPERTY INTERFACE_LINK_LIBRARIES ffmpeg::${component})
endif()
endif()
endforeach()
endif()
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
# 设置项目名称
project(MyFFmpegExample VERSION 1.0.0 LANGUAGES CXX)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules" ${CMAKE_MODULE_PATH})
find_package(FFmpeg 6 REQUIRED)
target_link_libraries(test
PRIVATE
ffmpeg::ffmpeg
)
add_executable(${PROJECT_NAME} main.cpp)
main.cpp
cpp
#include <iostream>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
using namespace std;
int main(int argc, char** argv) {
if (argc != 2) {
cerr << "Usage: " << argv[0] << " <input-file>" << endl;
return 1;
}
const char* input_filename = argv[1];
// 初始化 FFmpeg 库
av_register_all();
avformat_network_init();
// 打开输入文件
AVFormatContext* format_ctx = nullptr;
if (avformat_open_input(&format_ctx, input_filename, nullptr, nullptr) != 0) {
cerr << "Could not open input file." << endl;
return 1;
}
// 获取文件信息
if (avformat_find_stream_info(format_ctx, nullptr) < 0) {
cerr << "Failed to retrieve input stream information." << endl;
return 1;
}
// 查找视频流
int video_stream = -1;
for (unsigned int i = 0; i < format_ctx->nb_streams; i++) {
if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
video_stream = i;
break;
}
}
if (video_stream == -1) {
cerr << "No video stream found." << endl;
return 1;
}
// 获取视频编解码器上下文
AVCodecParameters* codecpar = format_ctx->streams[video_stream]->codecpar;
const AVCodec* decoder = avcodec_find_decoder(codecpar->codec_id);
if (!decoder) {
cerr << "Failed to find decoder for the video stream." << endl;
return 1;
}
AVCodecContext* codec_ctx = avcodec_alloc_context3(decoder);
if (avcodec_parameters_to_context(codec_ctx, codecpar) < 0) {
cerr << "Failed to copy codec parameters to codec context." << endl;
return 1;
}
// 打开编解码器
if (avcodec_open2(codec_ctx, decoder, nullptr) < 0) {
cerr << "Failed to open decoder." << endl;
return 1;
}
// 分配帧
AVFrame* frame = av_frame_alloc();
// 分配包
AVPacket packet;
av_init_packet(&packet);
// 逐帧解码
int frame_count = 0;
while (av_read_frame(format_ctx, &packet) >= 0) {
if (packet.stream_index == video_stream) {
// 解码帧
if (avcodec_send_packet(codec_ctx, &packet) == 0) {
while (avcodec_receive_frame(codec_ctx, frame) == 0) {
// 输出帧信息
cout << "Decoded frame " << ++frame_count << endl;
// 重置包
av_packet_unref(&packet);
}
}
}
// 重置包
av_packet_unref(&packet);
}
// 清理
avcodec_free_context(&codec_ctx);
av_frame_free(&frame);
avformat_close_input(&format_ctx);
return 0;
}