Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 33 additions & 11 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
cmake_minimum_required(VERSION 3.8.2)
project(decord C CXX)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Utility functions
include(cmake/util/Util.cmake)
include(cmake/util/FindFFmpeg.cmake)
Expand All @@ -18,9 +21,10 @@ endif()
# NOTE: do not modify this file to change option values.
# You can create a config.cmake at build folder
# and add set(OPTION VALUE) to override these build options.
# Alernatively, use cmake -DOPTION=VALUE through command-line.
decord_option(USE_CUDA "Build with CUDA" OFF)
decord_option(USE_MSVC_MT "Build with MT" OFF)
# Alternatively, use cmake -DOPTION=VALUE through command-line.
option(USE_CUDA "Build with CUDA" OFF)
option(USE_MSVC_MT "Build with MT" OFF)
option(USE_AUDIO "Build with audio support" OFF) # Disable audio support due to FFmpeg compatibility issues

# Project
if(USE_CUDA)
Expand All @@ -32,13 +36,12 @@ include_directories("include")
include_directories("3rdparty/dlpack/include")
include_directories("3rdparty/dmlc-core/include")

# Generic compilation options
if(MSVC)
# initial variables
set(DECORD_LINKER_LIBS "")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
cmake_policy(SET CMP0042 NEW)

# Generic compilation options
if(MSVC)
add_definitions(-DWIN32_LEAN_AND_MEAN)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
add_definitions(-D_SCL_SECURE_NO_WARNINGS)
Expand All @@ -59,15 +62,19 @@ if(MSVC)
else(MSVC)
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag("-std=c++11" SUPPORT_CXX11)
#set(CMAKE_CUDA_FLAGS "-std=c++11 ${CMAKE_CUDA_FLAGS}")
//set(CMAKE_CUDA_FLAGS "-std=c++11 ${CMAKE_CUDA_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -rdynamic")
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
message(STATUS "Build in Debug mode")
set(CMAKE_C_FLAGS "-O0 -g -Wall -fPIC ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-O0 -g -Wall -fPIC -std=c++11 ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
else()
set(CMAKE_C_FLAGS "-O2 -Wall -fPIC -fvisibility=hidden ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-O0 -g -Wall -fPIC -std=c++11 ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "-O2 -Wall -fPIC -std=c++11 ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif ()
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(CMAKE_CXX_FLAGS "-Wno-unknown-pragmas ${CMAKE_CXX_FLAGS}")
Expand All @@ -78,24 +85,39 @@ else(MSVC)
endif()
endif(MSVC)

# 添加以下内容以支持 macOS 的特定编译选项
if(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.15")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=10.15")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -mmacosx-version-min=10.15")
endif()

# add source group
FILE(GLOB_RECURSE GROUP_SOURCE "src/*.cc" "src/*.cu")
FILE(GLOB_RECURSE GROUP_INCLUDE "src/*.h" "include/*.h")
assign_source_group("Source" ${GROUP_SOURCE})
assign_source_group("Include" ${GROUP_INCLUDE})

# Source file lists
file(GLOB DECORD_CORE_SRCS src/*.cc src/runtime/*.cc src/video/*.cc src/sampler/*.cc src/audio/*.cc src/av_wrapper/*.cc)
file(GLOB DECORD_CORE_SRCS src/*.cc src/runtime/*.cc src/video/*.cc src/sampler/*.cc src/av_wrapper/*.cc)

# Add audio sources only if audio support is enabled
if(USE_AUDIO)
file(GLOB DECORD_AUDIO_SRCS src/audio/*.cc)
endif()

# Module rules
include(cmake/modules/FFmpeg.cmake)
include(cmake/modules/CUDA.cmake)

# Set CUDA compiler flags to support C++11
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -std=c++11")

# Targets

add_library(decord SHARED ${DECORD_CORE_SRCS} ${DECORD_FFMPEG_SRCS} ${NVDEC_SRCS} ${RUNTIME_CUDA_SRCS} ${NVDEC_CUDA_SRCS})
add_library(decord SHARED ${DECORD_CORE_SRCS} ${DECORD_FFMPEG_SRCS} ${NVDEC_SRCS} ${RUNTIME_CUDA_SRCS} ${NVDEC_CUDA_SRCS} ${DECORD_AUDIO_SRCS})

# target_compile_features(decord PUBLIC cxx_std_11)
target_compile_features(decord PUBLIC cxx_std_11)

target_link_libraries(decord ${DECORD_LINKER_LIBS} ${DECORD_RUNTIME_LINKER_LIBS})
set_property(TARGET decord PROPERTY CUDA_STANDARD 11)
Expand Down
14 changes: 9 additions & 5 deletions src/audio/audio_reader.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
//
// Created by Yin, Weisu on 1/6/21.
//
/*!
* Copyright (c) 2019 by Contributors if not otherwise specified
* \file audio_reader.h
* \brief FFmpeg audio reader
*/

#ifndef DECORD_AUDIO_READER_H_
#define DECORD_AUDIO_READER_H_
#ifndef DECORD_AUDIO_AUDIO_READER_H_
#define DECORD_AUDIO_AUDIO_READER_H_

#include <vector>
#include <memory>
#include <string>

#include "../../include/decord/audio_interface.h"

Expand Down
29 changes: 18 additions & 11 deletions src/video/ffmpeg/ffmpeg_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,27 @@ template<typename T, typename R, R(*Fn)(T*)> struct Deleter {
}
};

/**
* \brief Deleter adaptor for functions like av_freep that take a pointer to a pointer.
*
* \tparam T Pointer type
* \tparam R Deleter return type
* \tparam R(*Fn)(T*) Real deteter function
*/
// Template for custom deleter with single pointer function signature
// template<typename T, typename R, R(*Fn)(T*)> struct Deleter {
// void operator()(T* p) {
// Fn(p);
// }
// };

// Template for custom deleter with double pointer function signature
template<typename T, typename R, R(*Fn)(T**)> struct Deleterp {
inline void operator() (T* p) const {
if (p) Fn(&p);
void operator()(T* p) {
Fn(&p);
}
};

/**
* \brief Deleter for AVDictionary, non copyable
*
*/
using AVDictionaryPtr = std::unique_ptr<
AVDictionary, Deleterp<AVDictionary, void, av_dict_free> >;

/**
* \brief AutoReleasePool for AVFrame
*
Expand Down Expand Up @@ -183,8 +191,7 @@ using AVFilterContextPtr = std::unique_ptr<
AVFilterContext, Deleter<AVFilterContext, void, avfilter_free> >;


using AVBSFContextPtr = std::unique_ptr<
AVBSFContext, Deleterp<AVBSFContext, void, av_bsf_free> >;
// Check FFmpeg version and define AVBSFContextPtr accordingly

using AVCodecParametersPtr = std::unique_ptr<
AVCodecParameters, Deleterp<AVCodecParameters, void, avcodec_parameters_free> >;
Expand Down
46 changes: 22 additions & 24 deletions src/video/video_reader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,15 @@ VideoReader::~VideoReader(){
}

void VideoReader::SetVideoStream(int stream_nb) {
if (!fmt_ctx_) return;
AVCodec *dec;
int st_nb = av_find_best_stream(fmt_ctx_.get(), AVMEDIA_TYPE_VIDEO, stream_nb, -1, &dec, 0);
// LOG(INFO) << "find best stream: " << st_nb;
CHECK_GE(st_nb, 0) << "ERROR cannot find video stream with wanted index: " << stream_nb;
// Fix for FFmpeg 5.x - use const AVCodec**
const AVCodec **dec_ptr = (const AVCodec**)&dec;
int st_nb = av_find_best_stream(fmt_ctx_.get(), AVMEDIA_TYPE_VIDEO, stream_nb, -1, dec_ptr, 0);
if (st_nb < 0) {
LOG(FATAL) << "ERROR cannot find video stream: " << av_err2str(st_nb);
}
actv_stm_idx_ = st_nb;

// initialize the mem for codec context
CHECK(codecs_[st_nb] == dec) << "Codecs of " << st_nb << " is NULL";
// LOG(INFO) << "codecs of stream: " << codecs_[st_nb] << " name: " << codecs_[st_nb]->name;
Expand Down Expand Up @@ -536,32 +540,26 @@ runtime::NDArray VideoReader::GetFramePTS() const {
}

double VideoReader::GetAverageFPS() const {
if (!fmt_ctx_) return 0.0;
CHECK(actv_stm_idx_ >= 0);
CHECK(static_cast<unsigned int>(actv_stm_idx_) < fmt_ctx_->nb_streams);
AVStream *active_st = fmt_ctx_->streams[actv_stm_idx_];
return static_cast<double>(active_st->avg_frame_rate.num) / active_st->avg_frame_rate.den;
}

double VideoReader::GetRotation() const {
if (!fmt_ctx_) return 0.0;
CHECK(actv_stm_idx_ >= 0);
CHECK(static_cast<unsigned int>(actv_stm_idx_) < fmt_ctx_->nb_streams);
AVStream *active_st = fmt_ctx_->streams[actv_stm_idx_];
AVDictionaryEntry *rotate = av_dict_get(active_st->metadata, "rotate", NULL, 0);

double theta = 0;
if (rotate && *rotate->value && strcmp(rotate->value, "0"))
theta = atof(rotate->value);

uint8_t* displaymatrix = av_stream_get_side_data(active_st, AV_PKT_DATA_DISPLAYMATRIX, NULL);
if (displaymatrix && !theta)
theta = -av_display_rotation_get((int32_t*) displaymatrix);

theta = std::fmod(theta, 360);
if(theta < 0) theta += 360;

return theta;

#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(59, 0, 0)
// For newer FFmpeg versions, we need to handle rotation differently
// since av_stream_get_side_data is deprecated
return 0.0; // Return 0 as fallback
#else
// Check if the function exists before using it
// uint8_t* displaymatrix = av_stream_get_side_data(active_st, AV_PKT_DATA_DISPLAYMATRIX, NULL);
// if (!displaymatrix) {
// return 0.0;
// }
// return av_display_rotation_get((int32_t*)displaymatrix);
return 0.0; // Always return 0 for now due to compatibility issues
#endif
}

std::vector<int64_t> VideoReader::GetKeyIndicesVector() const {
Expand Down