From 341e779fc4f943fb78cba56f2da5e60bed4d8f2f Mon Sep 17 00:00:00 2001 From: selim mustafaev Date: Sun, 6 Nov 2016 21:02:59 +0300 Subject: [PATCH] fixes for building on macOS with ffmpeg 3.1 --- CMakeLists.txt | 4 +- cmake/modules/FindFFMPEG.cmake | 354 ++++++++++++++++++++++----------- ffcpp/MediaFile.cpp | 5 +- ffcpp/MediaFile.h | 2 +- ffcpp/Resampler.cpp | 1 - main.cpp | 11 +- 6 files changed, 242 insertions(+), 135 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b4ea29..fea8ae0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,10 +6,10 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -ggdb -O2") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -std=c++14 -ggdb -O0") find_package(FFMPEG REQUIRED) -include_directories(${FFMPEG_INCLUDE_DIRS}) +include_directories(${FFMPEG_INCLUDE_DIR}) link_directories(${FFMPEG_LIBRARY_DIRS}) -#message(FATAL_ERROR ${FFMPEG_LIBRARIES}) +#message(FATAL_ERROR ${FFMPEG_INCLUDE_DIR}) set(SOURCE_FILES main.cpp ffcpp/MediaFile.cpp ffcpp/MediaFile.h ffcpp/ffcpp.cpp ffcpp/ffcpp.h ffcpp/Stream.cpp ffcpp/Stream.h ffcpp/Codec.cpp ffcpp/Codec.h ffcpp/Packet.cpp ffcpp/Packet.h ffcpp/Frame.cpp ffcpp/Frame.h ffcpp/FifoQueue.cpp ffcpp/FifoQueue.h ffcpp/Scaler.cpp ffcpp/Scaler.h ffcpp/Resampler.cpp ffcpp/Resampler.h) add_executable(ffConv ${SOURCE_FILES}) diff --git a/cmake/modules/FindFFMPEG.cmake b/cmake/modules/FindFFMPEG.cmake index 68b57f1..6214539 100644 --- a/cmake/modules/FindFFMPEG.cmake +++ b/cmake/modules/FindFFMPEG.cmake @@ -1,148 +1,260 @@ -# - Try to find FFMPEG -# Once done this will define -# FFMPEG_FOUND - System has FFMPEG -# FFMPEG_INCLUDE_DIRS - The FFMPEG include directories -# FFMPEG_LIBRARIES - The libraries needed to use FFMPEG -# FFMPEG_LIBRARY_DIRS - The directory to find FFMPEG libraries +#.rst: +# FindFFMPEG +# ---------- # -# written by Roy Shilkrot 2013 http://www.morethantechnical.com/ +# Find the native FFMPEG includes and library # +# This module defines:: +# +# FFMPEG_INCLUDE_DIR, where to find avcodec.h, avformat.h ... +# FFMPEG_LIBRARIES, the libraries to link against to use FFMPEG. +# FFMPEG_FOUND, If false, do not try to use FFMPEG. +# +# also defined, but not for general use are:: +# +# FFMPEG_avformat_LIBRARY, where to find the FFMPEG avformat library. +# FFMPEG_avcodec_LIBRARY, where to find the FFMPEG avcodec library. +# +# This is useful to do it this way so that we can always add more libraries +# if needed to ``FFMPEG_LIBRARIES`` if ffmpeg ever changes... -find_package(PkgConfig) +#============================================================================= +# Copyright: 1993-2008 Ken Martin, Will Schroeder, Bill Lorensen +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of YCM, substitute the full +# License text for the above reference.) + +# Originally from VTK project -MACRO(FFMPEG_FIND varname shortname headername) +find_path(FFMPEG_INCLUDE_DIR1 avformat.h + $ENV{FFMPEG_DIR} + $ENV{FFMPEG_DIR}/ffmpeg + $ENV{FFMPEG_DIR}/libavformat + $ENV{FFMPEG_DIR}/include/libavformat + $ENV{FFMPEG_DIR}/include/ffmpeg + /usr/local/include/ffmpeg + /usr/include/ffmpeg + /usr/include/libavformat + /usr/include/ffmpeg/libavformat + /usr/include/${CMAKE_LIBRARY_ARCHITECTURE}/libavformat + /usr/local/include/libavformat + ) - IF(NOT WIN32) - PKG_CHECK_MODULES(PC_${varname} ${shortname}) +find_path(FFMPEG_INCLUDE_DIR2 avutil.h + $ENV{FFMPEG_DIR} + $ENV{FFMPEG_DIR}/ffmpeg + $ENV{FFMPEG_DIR}/libavutil + $ENV{FFMPEG_DIR}/include/libavutil + $ENV{FFMPEG_DIR}/include/ffmpeg + /usr/local/include/ffmpeg + /usr/include/ffmpeg + /usr/include/libavutil + /usr/include/ffmpeg/libavutil + /usr/include/${CMAKE_LIBRARY_ARCHITECTURE}/libavutil + /usr/local/include/libavutil + ) - FIND_PATH(${varname}_INCLUDE_DIR "${shortname}/${headername}" - HINTS ${PC_${varname}_INCLUDEDIR} ${PC_${varname}_INCLUDE_DIRS} - NO_DEFAULT_PATH - ) - ELSE() - FIND_PATH(${varname}_INCLUDE_DIR "${shortname}/${headername}") - ENDIF() +find_path(FFMPEG_INCLUDE_DIR3 avcodec.h + $ENV{FFMPEG_DIR} + $ENV{FFMPEG_DIR}/ffmpeg + $ENV{FFMPEG_DIR}/libavcodec + $ENV{FFMPEG_DIR}/include/libavcodec + $ENV{FFMPEG_DIR}/include/ffmpeg + /usr/local/include/ffmpeg + /usr/include/ffmpeg + /usr/include/libavcodec + /usr/include/ffmpeg/libavcodec + /usr/include/${CMAKE_LIBRARY_ARCHITECTURE}/libavcodec + /usr/local/include/libavcodec + ) - IF(${varname}_INCLUDE_DIR STREQUAL "${varname}_INCLUDE_DIR-NOTFOUND") - message(STATUS "look for newer strcture") - IF(NOT WIN32) - PKG_CHECK_MODULES(PC_${varname} "lib${shortname}") +find_path(FFMPEG_INCLUDE_DIR4 swscale.h + $ENV{FFMPEG_DIR} + $ENV{FFMPEG_DIR}/ffmpeg + $ENV{FFMPEG_DIR}/libswscale + $ENV{FFMPEG_DIR}/include/libswscale + $ENV{FFMPEG_DIR}/include/ffmpeg + /usr/local/include/ffmpeg + /usr/include/ffmpeg + /usr/include/libswscale + /usr/include/ffmpeg/libswscale + /usr/include/${CMAKE_LIBRARY_ARCHITECTURE}/libswscale + /usr/local/include/libswscale + ) - FIND_PATH(${varname}_INCLUDE_DIR "lib${shortname}/${headername}" - HINTS ${PC_${varname}_INCLUDEDIR} ${PC_${varname}_INCLUDE_DIRS} - NO_DEFAULT_PATH - ) - ELSE() - FIND_PATH(${varname}_INCLUDE_DIR "lib${shortname}/${headername}") - IF(${${varname}_INCLUDE_DIR} STREQUAL "${varname}_INCLUDE_DIR-NOTFOUND") - #Desperate times call for desperate measures - MESSAGE(STATUS "globbing...") - FILE(GLOB_RECURSE ${varname}_INCLUDE_DIR "/ffmpeg*/${headername}") - MESSAGE(STATUS "found: ${${varname}_INCLUDE_DIR}") - IF(${varname}_INCLUDE_DIR) - GET_FILENAME_COMPONENT(${varname}_INCLUDE_DIR "${${varname}_INCLUDE_DIR}" PATH) - GET_FILENAME_COMPONENT(${varname}_INCLUDE_DIR "${${varname}_INCLUDE_DIR}" PATH) - ELSE() - SET(${varname}_INCLUDE_DIR "${varname}_INCLUDE_DIR-NOTFOUND") - ENDIF() - ENDIF() - ENDIF() - ENDIF() +find_path(FFMPEG_INCLUDE_DIR5 avdevice.h + $ENV{FFMPEG_DIR} + $ENV{FFMPEG_DIR}/ffmpeg + $ENV{FFMPEG_DIR}/libavdevice + $ENV{FFMPEG_DIR}/include/libavdevice + $ENV{FFMPEG_DIR}/include/ffmpeg + /usr/local/include/ffmpeg + /usr/include/ffmpeg + /usr/include/libavdevice + /usr/include/ffmpeg/libavdevice + /usr/include/${CMAKE_LIBRARY_ARCHITECTURE}/libavdevice + /usr/local/include/libavdevice + ) - IF(${${varname}_INCLUDE_DIR} STREQUAL "${varname}_INCLUDE_DIR-NOTFOUND") - MESSAGE(STATUS "Can't find includes for ${shortname}...") - ELSE() - MESSAGE(STATUS "Found ${shortname} include dirs: ${${varname}_INCLUDE_DIR}") +find_path(FFMPEG_INCLUDE_DIR6 swresample.h + $ENV{FFMPEG_DIR} + $ENV{FFMPEG_DIR}/ffmpeg + $ENV{FFMPEG_DIR}/libswresample + $ENV{FFMPEG_DIR}/include/libswresample + $ENV{FFMPEG_DIR}/include/ffmpeg + /usr/local/include/ffmpeg + /usr/include/ffmpeg + /usr/include/libswresample + /usr/include/ffmpeg/libswresample + /usr/include/${CMAKE_LIBRARY_ARCHITECTURE}/libswresample + /usr/local/include/libswresample + ) - # GET_DIRECTORY_PROPERTY(FFMPEG_PARENT DIRECTORY ${${varname}_INCLUDE_DIR} PARENT_DIRECTORY) - GET_FILENAME_COMPONENT(FFMPEG_PARENT ${${varname}_INCLUDE_DIR} PATH) - MESSAGE(STATUS "Using FFMpeg dir parent as hint: ${FFMPEG_PARENT}") +if(FFMPEG_INCLUDE_DIR1) + if(FFMPEG_INCLUDE_DIR2) + if(FFMPEG_INCLUDE_DIR3) + set(FFMPEG_INCLUDE_DIR ${FFMPEG_INCLUDE_DIR1} + ${FFMPEG_INCLUDE_DIR2} + ${FFMPEG_INCLUDE_DIR3}) + endif() + endif() +endif() - IF(NOT WIN32) - FIND_LIBRARY(${varname}_LIBRARIES NAMES ${shortname} - HINTS ${PC_${varname}_LIBDIR} ${PC_${varname}_LIBRARY_DIR} ${FFMPEG_PARENT}) - ELSE() - # FIND_PATH(${varname}_LIBRARIES "${shortname}.dll.a" HINTS ${FFMPEG_PARENT}) - FILE(GLOB_RECURSE ${varname}_LIBRARIES "${FFMPEG_PARENT}/*${shortname}.lib") - # GLOBing is very bad... but windows sux, this is the only thing that works - ENDIF() +if(FFMPEG_INCLUDE_DIR4) + set(FFMPEG_INCLUDE_DIR ${FFMPEG_INCLUDE_DIR} + ${FFMPEG_INCLUDE_DIR4}) +endif() - IF(${varname}_LIBRARIES STREQUAL "${varname}_LIBRARIES-NOTFOUND") - MESSAGE(STATUS "look for newer structure for library") - FIND_LIBRARY(${varname}_LIBRARIES NAMES lib${shortname} - HINTS ${PC_${varname}_LIBDIR} ${PC_${varname}_LIBRARY_DIR} ${FFMPEG_PARENT}) - ENDIF() +if(FFMPEG_INCLUDE_DIR5) + set(FFMPEG_INCLUDE_DIR ${FFMPEG_INCLUDE_DIR} + ${FFMPEG_INCLUDE_DIR5} + ${FFMPEG_INCLUDE_DIR5}/..) +endif() +if(FFMPEG_INCLUDE_DIR6) + set(FFMPEG_INCLUDE_DIR ${FFMPEG_INCLUDE_DIR} + ${FFMPEG_INCLUDE_DIR6}) +endif() - IF(${varname}_LIBRARIES STREQUAL "${varname}_LIBRARIES-NOTFOUND") - MESSAGE(STATUS "Can't find lib for ${shortname}...") - ELSE() - MESSAGE(STATUS "Found ${shortname} libs: ${${varname}_LIBRARIES}") - ENDIF() +find_library(FFMPEG_avformat_LIBRARY avformat + $ENV{FFMPEG_DIR} + $ENV{FFMPEG_DIR}/lib + $ENV{FFMPEG_DIR}/libavformat + /usr/local/lib + /usr/lib + ) +find_library(FFMPEG_avcodec_LIBRARY avcodec + $ENV{FFMPEG_DIR} + $ENV{FFMPEG_DIR}/lib + $ENV{FFMPEG_DIR}/libavcodec + /usr/local/lib + /usr/lib + ) - IF(NOT ${varname}_INCLUDE_DIR STREQUAL "${varname}_INCLUDE_DIR-NOTFOUND" - AND NOT ${varname}_LIBRARIES STREQUAL ${varname}_LIBRARIES-NOTFOUND) +find_library(FFMPEG_avutil_LIBRARY avutil + $ENV{FFMPEG_DIR} + $ENV{FFMPEG_DIR}/lib + $ENV{FFMPEG_DIR}/libavutil + /usr/local/lib + /usr/lib + ) - MESSAGE(STATUS "found ${shortname}: include ${${varname}_INCLUDE_DIR} lib ${${varname}_LIBRARIES}") - SET(FFMPEG_${varname}_FOUND 1) - SET(FFMPEG_${varname}_INCLUDE_DIRS ${${varname}_INCLUDE_DIR}) - SET(FFMPEG_${varname}_LIBS ${${varname}_LIBRARIES}) - SET(FFMPEG_${varname}_LIBDIR ${PC_${varname}_LIBDIR}) +if(NOT DISABLE_SWSCALE) + find_library(FFMPEG_swscale_LIBRARY swscale + $ENV{FFMPEG_DIR} + $ENV{FFMPEG_DIR}/lib + $ENV{FFMPEG_DIR}/libswscale + /usr/local/lib + /usr/lib + ) +endif(NOT DISABLE_SWSCALE) - ELSE() - MESSAGE(STATUS "Can't find ${shortname}") - ENDIF() +find_library(FFMPEG_avdevice_LIBRARY avdevice + $ENV{FFMPEG_DIR} + $ENV{FFMPEG_DIR}/lib + $ENV{FFMPEG_DIR}/libavdevice + /usr/local/lib + /usr/lib + ) - ENDIF() +find_library(_FFMPEG_z_LIBRARY_ z + $ENV{FFMPEG_DIR} + $ENV{FFMPEG_DIR}/lib + /usr/local/lib + /usr/lib + ) -ENDMACRO(FFMPEG_FIND) - -FFMPEG_FIND(LIBAVFORMAT avformat avformat.h) -FFMPEG_FIND(LIBAVDEVICE avdevice avdevice.h) -FFMPEG_FIND(LIBAVCODEC avcodec avcodec.h) -FFMPEG_FIND(LIBAVUTIL avutil avutil.h) -FFMPEG_FIND(LIBSWSCALE swscale swscale.h) -FFMPEG_FIND(LIBSWRESAMPLE swresample swresample.h) - -SET(FFMPEG_FOUND "NO") -IF (FFMPEG_LIBAVFORMAT_FOUND AND - FFMPEG_LIBAVDEVICE_FOUND AND - FFMPEG_LIBAVCODEC_FOUND AND - FFMPEG_LIBAVUTIL_FOUND AND - FFMPEG_LIBSWSCALE_FOUND AND - FFMPEG_LIBSWRESAMPLE_FOUND +find_library(FFMPEG_swresample_LIBRARY swresample + $ENV{FFMPEG_DIR} + $ENV{FFMPEG_DIR}/lib + $ENV{FFMPEG_DIR}/libswresample + /usr/local/lib + /usr/lib ) - SET(FFMPEG_FOUND "YES") - SET(FFMPEG_INCLUDE_DIRS ${FFMPEG_LIBAVFORMAT_INCLUDE_DIRS}) +if(FFMPEG_INCLUDE_DIR) + if(FFMPEG_avformat_LIBRARY) + if(FFMPEG_avcodec_LIBRARY) + if(FFMPEG_avutil_LIBRARY) + set(FFMPEG_FOUND "YES") + set(FFMPEG_LIBRARIES ${FFMPEG_avformat_LIBRARY} + ${FFMPEG_avcodec_LIBRARY} + ${FFMPEG_avutil_LIBRARY} + ) + if(FFMPEG_swscale_LIBRARY) + set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} + ${FFMPEG_swscale_LIBRARY} + ) + endif() + if(FFMPEG_swresample_LIBRARY) + set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} + ${FFMPEG_swresample_LIBRARY} + ) + endif() + if(FFMPEG_avdevice_LIBRARY) + set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} + ${FFMPEG_avdevice_LIBRARY} + ) + endif() + if(_FFMPEG_z_LIBRARY_) + set( FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} + ${_FFMPEG_z_LIBRARY_} + ) + endif() + endif() + endif() + endif() +endif() - SET(FFMPEG_LIBRARY_DIRS ${FFMPEG_LIBAVFORMAT_LIBDIR}) +mark_as_advanced( + FFMPEG_INCLUDE_DIR + FFMPEG_INCLUDE_DIR1 + FFMPEG_INCLUDE_DIR2 + FFMPEG_INCLUDE_DIR3 + FFMPEG_INCLUDE_DIR4 + FFMPEG_INCLUDE_DIR5 + FFMPEG_avformat_LIBRARY + FFMPEG_avcodec_LIBRARY + FFMPEG_avutil_LIBRARY + FFMPEG_swscale_LIBRARY + FFMPEG_avdevice_LIBRARY + FFMPEG_swresample_LIBRARY + _FFMPEG_z_LIBRARY_ +) - SET(FFMPEG_LIBRARIES - ${FFMPEG_LIBAVFORMAT_LIBS} - ${FFMPEG_LIBAVDEVICE_LIBS} - ${FFMPEG_LIBAVCODEC_LIBS} - ${FFMPEG_LIBAVUTIL_LIBS} - ${FFMPEG_LIBSWSCALE_LIBS} - ${FFMPEG_LIBSWRESAMPLE_LIBS} - ) - -ELSE () - - MESSAGE(STATUS "Could not find FFMPEG") - -ENDIF() - -message(STATUS ${FFMPEG_LIBRARIES} ${FFMPEG_LIBAVFORMAT_LIBRARIES}) - -include(FindPackageHandleStandardArgs) -# handle the QUIETLY and REQUIRED arguments and set FFMPEG_FOUND to TRUE -# if all listed variables are TRUE -find_package_handle_standard_args(FFMPEG DEFAULT_MSG - FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIRS) - -mark_as_advanced(FFMPEG_INCLUDE_DIRS FFMPEG_LIBRARY_DIRS FFMPEG_LIBRARIES) +# Set package properties if FeatureSummary was included +if(COMMAND set_package_properties) + set_package_properties(FFMPEG PROPERTIES DESCRIPTION "A complete, cross-platform solution to record, convert and stream audio and video") + set_package_properties(FFMPEG PROPERTIES URL "http://ffmpeg.org/") +endif() \ No newline at end of file diff --git a/ffcpp/MediaFile.cpp b/ffcpp/MediaFile.cpp index 49b19bd..2991101 100644 --- a/ffcpp/MediaFile.cpp +++ b/ffcpp/MediaFile.cpp @@ -92,7 +92,7 @@ namespace ffcpp { } } - Stream& MediaFile::addVideoStream(AVCodecID codecID, int width, int height, AVPixelFormat pixelFormat) { + Stream& MediaFile::addVideoStream(AVCodecID codecID, int width, int height, AVRational timeBase, AVPixelFormat pixelFormat) { AVCodec* codec = avcodec_find_encoder(codecID); if(!codec) throw std::runtime_error("cannot find codec"); @@ -102,6 +102,7 @@ namespace ffcpp { AVCodecContext* ctx = stream->codec; ctx->width = width; ctx->height = height; + ctx->time_base = timeBase; if(pixelFormat == AV_PIX_FMT_NONE) { ctx->pix_fmt = codec->pix_fmts[0]; @@ -131,6 +132,8 @@ namespace ffcpp { ctx->channels = channels; ctx->channel_layout = (uint64_t)av_get_default_channel_layout(channels); ctx->sample_rate = sampleRate; + ctx->time_base = AVRational {1, sampleRate}; + ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; _streams.emplace_back(stream, codec); return _streams.back(); diff --git a/ffcpp/MediaFile.h b/ffcpp/MediaFile.h index 8069d99..e71b3e9 100644 --- a/ffcpp/MediaFile.h +++ b/ffcpp/MediaFile.h @@ -33,7 +33,7 @@ namespace ffcpp { bool hasAudio() const; Stream& videoStream(size_t index = 0); Stream& audioStream(size_t index = 0); - Stream& addVideoStream(AVCodecID codecID, int width, int height, AVPixelFormat pixelFormat = AV_PIX_FMT_NONE); + Stream& addVideoStream(AVCodecID codecID, int width, int height, AVRational timeBase, AVPixelFormat pixelFormat = AV_PIX_FMT_NONE); Stream& addAudioStream(AVCodecID codecID, int channels, int sampleRate, AVSampleFormat sampleFormat = AV_SAMPLE_FMT_NONE); Packet readPacket(); AVMediaType packetType(const Packet& packet); diff --git a/ffcpp/Resampler.cpp b/ffcpp/Resampler.cpp index 6676c0f..53c7025 100644 --- a/ffcpp/Resampler.cpp +++ b/ffcpp/Resampler.cpp @@ -2,7 +2,6 @@ #include "ffcpp.h" #include #include -#include extern "C" { #include diff --git a/main.cpp b/main.cpp index e85ce97..4724487 100644 --- a/main.cpp +++ b/main.cpp @@ -1,9 +1,9 @@ -#include #include "ffcpp/ffcpp.h" #include "ffcpp/MediaFile.h" #include "ffcpp/FifoQueue.h" #include "ffcpp/Scaler.h" #include "ffcpp/Resampler.h" +//#include constexpr int VIDEO_STREAM_INDEX = 0; constexpr int AUDIO_STREAM_INDEX = 1; @@ -40,19 +40,12 @@ int main(int argc, char** argv) { double aspect = 1.0*vDecoder.width()/vDecoder.height(); int outHeight = (int)(VIDEO_WIDTH/aspect) & ~1; - ff::Stream& outVStream = output.addVideoStream(AV_CODEC_ID_H264, VIDEO_WIDTH, outHeight, AV_PIX_FMT_YUV420P); + ff::Stream& outVStream = output.addVideoStream(AV_CODEC_ID_H264, VIDEO_WIDTH, outHeight, vDecoder.timeBase(), AV_PIX_FMT_YUV420P); ff::Codec& vEncoder = outVStream.codec(); ff::Stream& outAStream = output.addAudioStream(AV_CODEC_ID_VORBIS, 2, 44100, AV_SAMPLE_FMT_FLTP); ff::Codec& aEncoder = outAStream.codec(); - auto aEncTimeBase = aEncoder.timeBase(); - if(aEncTimeBase.den/aEncTimeBase.num != aEncoder.sampleRate()) { - std::cout << "audio encoder time base is not based on sample rate" << std::endl; - std::cout << "exiting" << std::endl; - return 0; - } - output.writeHeader(); int64_t aPts = 0;