Commit a5cd0534 authored by Arnaud Gelas's avatar Arnaud Gelas
Browse files

ENH: When using FFMPEG encoder, it first check if you are using a recent...

ENH: When using FFMPEG encoder, it first check if you are using a recent version of FFMPEG (or an old one as it was required previously for vtk). Then vtkFFMPEGWriter uses either the older API or the new one. See http://www.vtk.org/pipermail/vtk-developers/2009-December/006522.html. Original solution provided by Berk Geveci and improved by Nicolas Rannou.
parent ec68d4b0
......@@ -11,11 +11,45 @@
# This is usefull to do it this way so that we can always add more libraries
# if needed to FFMPEG_LIBRARIES if ffmpeg ever changes...
FIND_PATH(FFMPEG_INCLUDE_DIR ffmpeg/avformat.h
/usr/local/include
/usr/include
FIND_PATH(FFMPEG_INCLUDE_DIR avformat.h
PATHS
$ENV{FFMPEG_DIR}/include
$ENV{OSGDIR}/include
$ENV{OSG_ROOT}/include
~/Library/Frameworks
/Library/Frameworks
/usr/local/include
/usr/include
/sw/include # Fink
/opt/local/include # DarwinPorts
/opt/csw/include # Blastwave
/opt/include
/usr/freeware/include
PATH_SUFFIXES ffmpeg
DOC "Location of FFMPEG Headers"
)
IF( NOT FFMPEG_INCLUDE_DIR )
FIND_PATH(FFMPEG_INCLUDE_DIR libavformat/avformat.h
PATHS
$ENV{FFMPEG_DIR}/include
$ENV{OSGDIR}/include
$ENV{OSG_ROOT}/include
~/Library/Frameworks
/Library/Frameworks
/usr/local/include
/usr/include
/sw/include # Fink
/opt/local/include # DarwinPorts
/opt/csw/include # Blastwave
/opt/include
/usr/freeware/include
PATH_SUFFIXES ffmpeg
DOC "Location of FFMPEG Headers"
)
ENDIF( NOT FFMPEG_INCLUDE_DIR )
FIND_LIBRARY(FFMPEG_avformat_LIBRARY avformat
/usr/local/lib
/usr/lib
......@@ -61,6 +95,11 @@ FIND_LIBRARY(FFMPEG_gsm_LIBRARY gsm
/usr/lib
)
FIND_LIBRARY(FFMPEG_swscale_LIBRARY swscale
/usr/local/lib
/usr/lib
)
FIND_LIBRARY(FFMPEG_z_LIBRARY z
/usr/local/lib
/usr/lib
......@@ -85,6 +124,7 @@ IF(FFMPEG_INCLUDE_DIR)
${FFMPEG_theora_LIBRARY}
${FFMPEG_dts_LIBRARY}
${FFMPEG_gsm_LIBRARY}
${FFMPEG_swscale_LIBRARY}
${FFMPEG_z_LIBRARY})
ENDIF(FFMPEG_avutil_LIBRARY)
ENDIF(FFMPEG_avcodec_LIBRARY)
......@@ -102,5 +142,6 @@ MARK_AS_ADVANCED(
FFMPEG_theora_LIBRARY
FFMPEG_dts_LIBRARY
FFMPEG_gsm_LIBRARY
FFMPEG_swscale_LIBRARY
FFMPEG_z_LIBRARY
)
extern "C" {
#ifdef HAS_OLD_HEADER
# include <ffmpeg/avformat.h>
#else
# include <libavformat/avformat.h>
#endif
}
int main()
{
avformat_alloc_context();
return 0;
}
extern "C" {
#ifdef HAS_OLD_HEADER
# include <ffmpeg/avcodec.h>
#else
# include <libavcodec/avcodec.h>
#endif
}
int main()
{
img_convert(0, PIX_FMT_RGB24,
0, PIX_FMT_RGB24,
0, 0);
return 0;
}
extern "C" {
#ifdef HAS_OLD_HEADER
# include <ffmpeg/avformat.h>
#else
# include <libavformat/avformat.h>
#endif
}
int main()
{
AVFormatContext *ctx;
url_fclose(&ctx->pb);
return 0;
}
IF (FFMPEG_INCLUDE_DIR)
IF("VTK_FFMPEG_HAS_OLD_HEADER" MATCHES "^VTK_FFMPEG_HAS_OLD_HEADER$" OR NOT "VTK_FFMPEG_CACHED_INCLUDE" MATCHES "^${FFMPEG_INCLUDE_DIR}$")
IF (EXISTS ${FFMPEG_INCLUDE_DIR}/ffmpeg)
SET(VTK_FFMPEG_HAS_OLD_HEADER "TRUE" CACHE INTERNAL "Is the FFMPEG include in the old location" FORCE)
ELSE (EXISTS ${FFMPEG_INCLUDE_DIR}/ffmpeg)
SET(VTK_FFMPEG_HAS_OLD_HEADER "FALSE" CACHE INTERNAL "Is the FFMPEG include in the old location" FORCE)
ENDIF (EXISTS ${FFMPEG_INCLUDE_DIR}/ffmpeg)
IF (VTK_FFMPEG_HAS_OLD_HEADER)
MESSAGE(STATUS "Checking if FFMPEG uses old style header files - yes")
ELSE (VTK_FFMPEG_HAS_OLD_HEADER)
MESSAGE(STATUS "Checking if FFMPEG uses old style header files - no")
ENDIF (VTK_FFMPEG_HAS_OLD_HEADER)
SET(VTK_FFMPEG_CACHED_INCLUDE ${FFMPEG_INCLUDE_DIR} CACHE INTERNAL "Previous value of FFMPEG_INCLUDE_DIR" FORCE)
ENDIF("VTK_FFMPEG_HAS_OLD_HEADER" MATCHES "^VTK_FFMPEG_HAS_OLD_HEADER$" OR NOT "VTK_FFMPEG_CACHED_INCLUDE" MATCHES "^${FFMPEG_INCLUDE_DIR}$")
IF("VTK_FFMPEG_HAS_IMG_CONVERT" MATCHES "^VTK_FFMPEG_HAS_IMG_CONVERT$" OR NOT "VTK_FFMPEG_CACHED_AVCODEC" MATCHES "^${FFMPEG_avcodec_LIBRARY}$")
IF(VTK_FFMPEG_HAS_OLD_HEADER)
SET(VTK_FFMPEG_CDEFS "HAS_OLD_HEADER")
ELSE(VTK_FFMPEG_HAS_OLD_HEADER)
SET(VTK_FFMPEG_CDEFS "HAS_NEW_HEADER")
ENDIF(VTK_FFMPEG_HAS_OLD_HEADER)
IF(FFMPEG_avcodec_LIBRARY)
TRY_COMPILE(VTK_FFMPEG_HAS_IMG_CONVERT
${VTK_BINARY_DIR}/CMakeTmp
${VTK_CMAKE_DIR}/vtkFFMPEGTestImgConvert.cxx
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${FFMPEG_INCLUDE_DIR}"
"-DLINK_LIBRARIES:STRING=${FFMPEG_avcodec_LIBRARY}"
-DCOMPILE_DEFINITIONS:STRING=-D${VTK_FFMPEG_CDEFS}
OUTPUT_VARIABLE OUTPUT)
IF(VTK_FFMPEG_HAS_IMG_CONVERT)
MESSAGE(STATUS "Checking if FFMPEG has img_convert - found")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Checking if FFMPEG has img_convert (passed):\n"
"${OUTPUT}\n\n")
ELSE(VTK_FFMPEG_HAS_IMG_CONVERT)
MESSAGE(STATUS "Checking if FFMPEG has img_convert - not found")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Checking if FFMPEG has img_convert (failed):\n"
"${OUTPUT}\n\n")
ENDIF(VTK_FFMPEG_HAS_IMG_CONVERT)
ENDIF(FFMPEG_avcodec_LIBRARY)
SET(VTK_FFMPEG_CACHED_AVCODEC ${FFMPEG_avcodec_LIBRARY} CACHE INTERNAL "Previous value of FFMPEG_avcodec_LIBRARY" FORCE)
ENDIF("VTK_FFMPEG_HAS_IMG_CONVERT" MATCHES "^VTK_FFMPEG_HAS_IMG_CONVERT$" OR NOT "VTK_FFMPEG_CACHED_AVCODEC" MATCHES "^${FFMPEG_avcodec_LIBRARY}$")
IF("VTK_FFMPEG_OLD_URL_FCLOSE" MATCHES "^VTK_FFMPEG_OLD_URL_FCLOSE$" OR NOT "VTK_FFMPEG_CACHED_AVFORMAT" MATCHES "^${FFMPEG_avformat_LIBRARY}$")
IF(VTK_FFMPEG_HAS_OLD_HEADER)
SET(VTK_FFMPEG_CDEFS "HAS_OLD_HEADER")
ELSE(VTK_FFMPEG_HAS_OLD_HEADER)
SET(VTK_FFMPEG_CDEFS "HAS_NEW_HEADER")
ENDIF(VTK_FFMPEG_HAS_OLD_HEADER)
IF(FFMPEG_avformat_LIBRARY)
TRY_COMPILE(VTK_FFMPEG_OLD_URL_FCLOSE
${VTK_BINARY_DIR}/CMakeTmp
${VTK_CMAKE_DIR}/vtkFFMPEGTestURLFClose.cxx
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${FFMPEG_INCLUDE_DIR}"
-DCOMPILE_DEFINITIONS:STRING=-D${VTK_FFMPEG_CDEFS}
"-DLINK_LIBRARIES:STRING=${FFMPEG_avformat_LIBRARY}"
OUTPUT_VARIABLE OUTPUT)
IF(VTK_FFMPEG_OLD_URL_FCLOSE)
MESSAGE(STATUS "Checking if FFMPEG uses old API for url_fclose - found")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Checking if FFMPEG uses old API for url_fclose (passed):\n"
"${OUTPUT}\n\n")
ELSE(VTK_FFMPEG_OLD_URL_FCLOSE)
MESSAGE(STATUS "Checking if FFMPEG uses old API for url_fclose - not found")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Checking if FFMPEG uses old API for url_fclose (failed):\n"
"${OUTPUT}\n\n")
ENDIF(VTK_FFMPEG_OLD_URL_FCLOSE)
ENDIF(FFMPEG_avformat_LIBRARY)
ENDIF("VTK_FFMPEG_OLD_URL_FCLOSE" MATCHES "^VTK_FFMPEG_OLD_URL_FCLOSE$" OR NOT "VTK_FFMPEG_CACHED_AVFORMAT" MATCHES "^${FFMPEG_avformat_LIBRARY}$")
IF("VTK_FFMPEG_NEW_ALLOC" MATCHES "^VTK_FFMPEG_NEW_ALLOC$" OR NOT "VTK_FFMPEG_CACHED_AVFORMAT" MATCHES "^${FFMPEG_avformat_LIBRARY}$")
IF(VTK_FFMPEG_HAS_OLD_HEADER)
SET(VTK_FFMPEG_CDEFS "HAS_OLD_HEADER")
ELSE(VTK_FFMPEG_HAS_OLD_HEADER)
SET(VTK_FFMPEG_CDEFS "HAS_NEW_HEADER")
ENDIF(VTK_FFMPEG_HAS_OLD_HEADER)
IF(FFMPEG_avformat_LIBRARY)
TRY_COMPILE(VTK_FFMPEG_NEW_ALLOC
${VTK_BINARY_DIR}/CMakeTmp
${VTK_CMAKE_DIR}/vtkFFMPEGTestAvAlloc.cxx
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${FFMPEG_INCLUDE_DIR}"
-DCOMPILE_DEFINITIONS:STRING=-D${VTK_FFMPEG_CDEFS}
"-DLINK_LIBRARIES:STRING=${FFMPEG_avformat_LIBRARY}"
OUTPUT_VARIABLE OUTPUT)
IF(VTK_FFMPEG_NEW_ALLOC)
MESSAGE(STATUS "Checking if FFMPEG has avformat_alloc_context - found")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Checking if FFMPEG has avformat_alloc_context (passed):\n"
"${OUTPUT}\n\n")
ELSE(VTK_FFMPEG_NEW_ALLOC)
MESSAGE(STATUS "Checking if FFMPEG has avformat_alloc_context - not found")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Checking if FFMPEG has avformat_alloc_context (failed):\n"
"${OUTPUT}\n\n")
ENDIF(VTK_FFMPEG_NEW_ALLOC)
ENDIF(FFMPEG_avformat_LIBRARY)
SET(VTK_FFMPEG_CACHED_AVFORMAT ${FFMPEG_avformat_LIBRARY} CACHE INTERNAL "Previous value of FFMPEG_avformat_LIBRARY" FORCE)
ENDIF("VTK_FFMPEG_NEW_ALLOC" MATCHES "^VTK_FFMPEG_NEW_ALLOC$" OR NOT "VTK_FFMPEG_CACHED_AVFORMAT" MATCHES "^${FFMPEG_avformat_LIBRARY}$")
ENDIF (FFMPEG_INCLUDE_DIR)
......@@ -887,6 +887,12 @@ OPTION (VTK_USE_FFMPEG_ENCODER "If the FFMPEG library is available, should VTK u
MARK_AS_ADVANCED(VTK_USE_FFMPEG_ENCODER)
IF (VTK_USE_FFMPEG_ENCODER)
INCLUDE(${VTK_CMAKE_DIR}/FindFFMPEG.cmake OPTIONAL)
MARK_AS_ADVANCED(CLEAR
FFMPEG_INCLUDE_DIR
FFMPEG_avformat_LIBRARY
FFMPEG_avcodec_LIBRARY
FFMPEG_avutil_LIBRARY
)
ENDIF (VTK_USE_FFMPEG_ENCODER)
#-----------------------------------------------------------------------------
......
......@@ -256,12 +256,25 @@ ENDIF(WIN32)
# FFMPEG
# If the ffmpeg library is available, compile vtkFFMPEGWriter.
IF (VTK_USE_FFMPEG_ENCODER)
INCLUDE(${VTK_CMAKE_DIR}/vtkTestFFMPEG.cmake)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/vtkFFMPEGConfig.h.in
${CMAKE_CURRENT_BINARY_DIR}/vtkFFMPEGConfig.h @ONLY)
INCLUDE_DIRECTORIES(${VTK_BINARY_DIR}/IO)
INSTALL(FILES vtkFFMPEGConfig.h
DESTINATION ${VTK_INSTALL_INCLUDE_DIR_CM24}
COMPONENT Development)
INCLUDE_DIRECTORIES(${FFMPEG_INCLUDE_DIR})
SET(Kit_SRCS ${Kit_SRCS} vtkFFMPEGWriter.cxx)
SET(KIT_LIBS ${KIT_LIBS}
${FFMPEG_avformat_LIBRARY}
${FFMPEG_avcodec_LIBRARY}
${FFMPEG_avutil_LIBRARY})
IF (NOT VTK_FFMPEG_HAS_IMG_CONVERT)
SET(KIT_LIBS ${KIT_LIBS}
${FFMPEG_swscale_LIBRARY})
ENDIF (NOT VTK_FFMPEG_HAS_IMG_CONVERT)
ENDIF (VTK_USE_FFMPEG_ENCODER)
#-----------------------------------------------------------------------------
......
/*=========================================================================
Program: Visualization Toolkit
Module: vtkFFMPEGConfig.h.in
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#ifndef __vtkFFMPEGConfig_h
#define __vtkFFMPEGConfig_h
/* This header is configured by VTK's build process. */
#cmakedefine VTK_FFMPEG_HAS_OLD_HEADER
#cmakedefine VTK_FFMPEG_OLD_URL_FCLOSE
#cmakedefine VTK_FFMPEG_HAS_IMG_CONVERT
#cmakedefine VTK_FFMPEG_NEW_ALLOC
#endif
......@@ -18,9 +18,18 @@
#include "vtkImageData.h"
#include "vtkObjectFactory.h"
#include "vtkErrorCode.h"
#include "vtkFFMPEGConfig.h"
extern "C" {
#include <ffmpeg/avformat.h>
#ifdef VTK_FFMPEG_HAS_OLD_HEADER
# include <ffmpeg/avformat.h>
#else
# include <libavformat/avformat.h>
#endif
#ifndef VTK_FFMPEG_HAS_IMG_CONVERT
# include <libswscale/swscale.h>
#endif
}
//---------------------------------------------------------------------------
......@@ -98,7 +107,11 @@ int vtkFFMPEGWriterInternal::Start()
av_register_all();
//create the format context that wraps all of the media output structures
#ifdef VTK_FFMPEG_NEW_ALLOC
this->avFormatContext = avformat_alloc_context();
#else
this->avFormatContext = av_alloc_format_context();
#endif
if (!this->avFormatContext)
{
vtkGenericWarningMacro (<< "Coult not open the format context.");
......@@ -256,10 +269,39 @@ int vtkFFMPEGWriterInternal::Write(vtkImageData *id)
}
//convert that to YUV for input to the codec
#ifdef VTK_FFMPEG_HAS_IMG_CONVERT
img_convert((AVPicture *)this->yuvOutput, cc->pix_fmt,
(AVPicture *)this->rgbInput, PIX_FMT_RGB24,
cc->width, cc->height);
#else
//convert that to YUV for input to the codec
SwsContext* convert_ctx = sws_getContext(
cc->width, cc->height, PIX_FMT_RGB24,
cc->width, cc->height, cc->pix_fmt,
SWS_BICUBIC, NULL, NULL, NULL);
if(convert_ctx == NULL)
{
vtkGenericWarningMacro(<< "swscale context initialization failed");
return 0;
}
int result = sws_scale(convert_ctx,
this->rgbInput->data, this->rgbInput->linesize,
0, cc->height,
this->yuvOutput->data, this->yuvOutput->linesize
);
sws_freeContext(convert_ctx);
if(!result)
{
vtkGenericWarningMacro(<< "sws_scale() failed");
return 0;
}
#endif
//run the encoder
int toAdd = avcodec_encode_video(cc,
this->codecBuf,
......@@ -332,7 +374,11 @@ void vtkFFMPEGWriterInternal::End()
if (this->openedFile)
{
av_write_trailer(this->avFormatContext);
#ifdef VTK_FFMPEG_OLD_URL_FCLOSE
url_fclose(&this->avFormatContext->pb);
#else
url_fclose(this->avFormatContext->pb);
#endif
this->openedFile = 0;
}
......@@ -354,7 +400,7 @@ void vtkFFMPEGWriterInternal::End()
//---------------------------------------------------------------------------
vtkStandardNewMacro(vtkFFMPEGWriter);
vtkCxxRevisionMacro(vtkFFMPEGWriter, "1.6");
vtkCxxRevisionMacro(vtkFFMPEGWriter, "1.7");
//---------------------------------------------------------------------------
vtkFFMPEGWriter::vtkFFMPEGWriter()
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment