From 8dc72bd60956225e8e41dad8be00e55b7c913531 Mon Sep 17 00:00:00 2001 From: "Stephen E. Baker" Date: Fri, 23 Jan 2015 22:35:19 -0500 Subject: [PATCH 1/3] Support playing movies with libav Makes libav an optional alternative to ffmpeg, selected in cmake. The intro movie plays perfectly with this libav code. --- CMake/FindLibAV.cmake | 145 ++++++++++++++++++++++++++++++++++++++ CMakeLists.txt | 15 +++- CorsixTH/CMakeLists.txt | 16 ++++- CorsixTH/Src/config.h.in | 10 +-- CorsixTH/Src/th_movie.cpp | 57 +++++++++++---- CorsixTH/Src/th_movie.h | 20 ++++-- 6 files changed, 237 insertions(+), 26 deletions(-) create mode 100644 CMake/FindLibAV.cmake diff --git a/CMake/FindLibAV.cmake b/CMake/FindLibAV.cmake new file mode 100644 index 000000000..9bfdf1c63 --- /dev/null +++ b/CMake/FindLibAV.cmake @@ -0,0 +1,145 @@ +# vim: ts=2 sw=2 +# - Try to find the required libav components(default: AVFORMAT, AVUTIL, AVCODEC) +# +# Once done this will define +# LIBAV_FOUND - System has the all required components. +# LIBAV_INCLUDE_DIRS - Include directory necessary for using the required components headers. +# LIBAV_LIBRARIES - Link these to use the required libav components. +# LIBAV_DEFINITIONS - Compiler switches required for using the required libav components. +# +# For each of the components it will additionally set. +# - AVCODEC +# - AVDEVICE +# - AVFILTER +# - AVFORMAT +# - AVRESAMPLE +# - AVUTIL +# - SWSCALE +# the following variables will be defined +# _FOUND - System has +# _INCLUDE_DIRS - Include directory necessary for using the headers +# _LIBRARIES - Link these to use +# _DEFINITIONS - Compiler switches required for using +# _VERSION - The components version +# +# Copyright (c) 2006, Matthias Kretz, +# Copyright (c) 2008, Alexander Neundorf, +# Copyright (c) 2011, Michael Jansen, +# Copyright (c) 2013,2015 Stephen Baker +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +include(FindPackageHandleStandardArgs) + +# The default components were taken from a survey over other FindLIBAV.cmake files +if (NOT LibAV_FIND_COMPONENTS) + set(LibAV_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL) +endif () + +# +### Macro: set_component_found +# +# Marks the given component as found if both *_LIBRARIES AND *_INCLUDE_DIRS is present. +# +macro(set_component_found _component ) + if (${_component}_LIBRARIES AND ${_component}_INCLUDE_DIRS) + # message(STATUS " - ${_component} found.") + set(${_component}_FOUND TRUE) + else () + # message(STATUS " - ${_component} not found.") + endif () +endmacro() + +# +### Macro: find_component +# +# Checks for the given component by invoking pkgconfig and then looking up the libraries and +# include directories. +# +macro(find_component _component _pkgconfig _library _header) + + if (NOT WIN32) + # use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(PC_${_component} ${_pkgconfig}) + endif () + endif (NOT WIN32) + + find_path(${_component}_INCLUDE_DIRS ${_header} + HINTS + ${PC_LIB${_component}_INCLUDEDIR} + ${PC_LIB${_component}_INCLUDE_DIRS} + PATH_SUFFIXES + libav + ) + + find_library(${_component}_LIBRARIES NAMES ${_library} + HINTS + ${PC_LIB${_component}_LIBDIR} + ${PC_LIB${_component}_LIBRARY_DIRS} + ) + + set(${_component}_DEFINITIONS ${PC_${_component}_CFLAGS_OTHER} CACHE STRING "The ${_component} CFLAGS.") + set(${_component}_VERSION ${PC_${_component}_VERSION} CACHE STRING "The ${_component} version number.") + + set_component_found(${_component}) + +endmacro() + + +# Check for cached results. If there are skip the costly part. +if (NOT LIBAV_LIBRARIES) + + # Check for all possible component. + find_component(AVCODEC libavcodec avcodec libavcodec/avcodec.h) + find_component(AVFORMAT libavformat avformat libavformat/avformat.h) + find_component(AVDEVICE libavdevice avdevice libavdevice/avdevice.h) + find_component(AVFILTER libavfilter avfilter libavfilter/avfilter.h) + find_component(AVRESAMPLE libavresample avresample libavresample/avresample.h) + find_component(AVUTIL libavutil avutil libavutil/avutil.h) + find_component(SWSCALE libswscale swscale libswscale/swscale.h) + + # Check if the required components were found and add their stuff to the LIBAV_* vars. + foreach (_component ${LibAV_FIND_COMPONENTS}) + if (${_component}_FOUND) + # message(STATUS "Required component ${_component} present.") + set(LIBAV_LIBRARIES ${LIBAV_LIBRARIES} ${${_component}_LIBRARIES}) + set(LIBAV_DEFINITIONS ${LIBAV_DEFINITIONS} ${${_component}_DEFINITIONS}) + list(APPEND LIBAV_INCLUDE_DIRS ${${_component}_INCLUDE_DIRS}) + else () + # message(STATUS "Required component ${_component} missing.") + endif () + endforeach () + + # Build the include path with duplicates removed. + if (LIBAV_INCLUDE_DIRS) + list(REMOVE_DUPLICATES LIBAV_INCLUDE_DIRS) + endif () + + # cache the vars. + set(LIBAV_INCLUDE_DIRS ${LIBAV_INCLUDE_DIRS} CACHE STRING "The LibAV include directories." FORCE) + set(LIBAV_LIBRARIES ${LIBAV_LIBRARIES} CACHE STRING "The LibAV libraries." FORCE) + set(LIBAV_DEFINITIONS ${LIBAV_DEFINITIONS} CACHE STRING "The LibAV cflags." FORCE) + + mark_as_advanced(LIBAV_INCLUDE_DIRS + LIBAV_LIBRARIES + LIBAV_DEFINITIONS) + +endif () + +# Now set the noncached _FOUND vars for the components. +foreach (_component AVCODEC AVDEVICE AVFILTER AVFORMAT AVRESAMPLE AVUTIL SWSCALE) + set_component_found(${_component}) +endforeach () + +# Compile the list of required vars +set(_LibAV_REQUIRED_VARS LIBAV_LIBRARIES LIBAV_INCLUDE_DIRS) +foreach (_component ${LibAV_FIND_COMPONENTS}) + list(APPEND _LibAV_REQUIRED_VARS ${_component}_LIBRARIES ${_component}_INCLUDE_DIRS) +endforeach () + +# Give a nice error message if some of the required vars are missing. +find_package_handle_standard_args(LibAV DEFAULT_MSG ${_LibAV_REQUIRED_VARS}) diff --git a/CMakeLists.txt b/CMakeLists.txt index e2a617d87..d59cacc33 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,7 @@ # - BUILD_ANIMVIEWER # - BUILD_MAPEDITOR # - WITH_LUAJIT : Whether to use LuaJIT 2 instead of Lua51 (default is LuaJIT 2) +# - WITH_LIBAV : Whether to use LibAV (as opposed to FFMEPG) when building movies PROJECT(CorsixTH_Top_Level) CMAKE_MINIMUM_REQUIRED(VERSION 2.6) @@ -36,6 +37,7 @@ OPTION(WITH_AUDIO "Activate Sound" ON) # enabled by default OPTION(WITH_MOVIES "Activate in game movies" ON) OPTION(WITH_FREETYPE2 "Enhanced Font Support" ON) OPTION(WITH_LUAJIT "Use LuaJIT instead of Lua" ON) +OPTION(WITH_LIBAV "Use LibAV instead of FFmpeg" OFF) OPTION(BUILD_ANIMVIEWER "Build the animation viewer as part of the build process" OFF) OPTION(BUILD_MAPEDITOR "Build the map editor as part of the build process" OFF) @@ -49,14 +51,23 @@ ENDIF(WITH_AUDIO) IF(WITH_MOVIES) IF(WITH_AUDIO) - SET(CORSIX_TH_USE_FFMPEG ON) - MESSAGE("Note: FFMPEG video is enabled (default)") + IF(WITH_LIBAV) + SET(CORSIX_TH_USE_FFMPEG OFF) + SET(CORSIX_TH_USE_LIBAV ON) + MESSAGE("Note: LibAV video is enabled") + ELSE() + SET(CORSIX_TH_USE_FFMPEG ON) + SET(CORSIX_TH_USE_LIBAV OFF) + MESSAGE("Note: FFMPEG video is enabled (default)") + ENDIF(WITH_LIBAV) ELSE() SET(CORSIX_TH_USE_FFMPEG OFF) + SET(CORSIX_TH_USE_LIBAV OFF) MESSAGE("Note: FFMPEG video disabled since it requires SDL audio.") ENDIF(WITH_AUDIO) ELSE() SET(CORSIX_TH_USE_FFMPEG OFF) + SET(CORSIX_TH_USE_LIBAV OFF) MESSAGE("Note: FFMPEG video is disabled") ENDIF(WITH_MOVIES) diff --git a/CorsixTH/CMakeLists.txt b/CorsixTH/CMakeLists.txt index 0af753061..19c017a74 100644 --- a/CorsixTH/CMakeLists.txt +++ b/CorsixTH/CMakeLists.txt @@ -137,7 +137,7 @@ message( STATUS "CMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}" ) # Find FFMPEG IF(CORSIX_TH_USE_FFMPEG) - FIND_PACKAGE(FFmpeg COMPONENTS AVFORMAT AVCODEC AVUTIL SWSCALE SWRESAMPLE REQUIRED) + FIND_PACKAGE(FFmpeg COMPONENTS AVFORMAT AVCODEC AVUTIL SWSCALE SWRESAMPLE REQUIRED) IF(FFMPEG_FOUND) TARGET_LINK_LIBRARIES(CorsixTH ${FFMPEG_LIBRARIES}) INCLUDE_DIRECTORIES(${FFMPEG_INCLUDE_DIRS}) @@ -150,6 +150,20 @@ IF(CORSIX_TH_USE_FFMPEG) ENDIF(FFMPEG_FOUND) ENDIF(CORSIX_TH_USE_FFMPEG) +IF(CORSIX_TH_USE_LIBAV) + FIND_PACKAGE(LibAV COMPONENTS AVFORMAT AVCODEC AVRESAMPLE AVUTIL SWSCALE REQUIRED) + IF(LIBAV_FOUND) + TARGET_LINK_LIBRARIES(CorsixTH ${LIBAV_LIBRARIES}) + INCLUDE_DIRECTORIES(${LIBAV_INCLUDE_DIRS}) + IF(APPLE) + TARGET_LINK_LIBRARIES(CorsixTH libz.dylib) + ENDIF() + message(" LibAV found") + ELSE(LIBAV_FOUND) + message("Error: LibAV library not found, even though it was selected to be included") + ENDIF(LIBAV_FOUND) +ENDIF(CORSIX_TH_USE_LIBAV) + # Find Freetype2 IF(CORSIX_TH_USE_FREETYPE2) FIND_PACKAGE(Freetype REQUIRED) diff --git a/CorsixTH/Src/config.h.in b/CorsixTH/Src/config.h.in index 3c9d7c8b3..a09313040 100644 --- a/CorsixTH/Src/config.h.in +++ b/CorsixTH/Src/config.h.in @@ -46,11 +46,13 @@ SOFTWARE. #cmakedefine CORSIX_TH_USE_SDL_MIXER /** Movie options **/ -// FFMPEG is used for in game movies. If this library is not present on your -// system, then you can comment out the next line and the game will not have -// movies. +// FFMPEG or LibAV are used for in game movies. +// If this library is not present on your system, then you can comment out the +// next line and the game will not have movies. #cmakedefine CORSIX_TH_USE_FFMPEG - +#ifndef CORSIX_TH_USE_FFMPEG +#cmakedefine CORSIX_TH_USE_LIBAV +#endif /** Font options **/ // FreeType2 can be used for font support beyond the CP437 bitmap fonts which // come with Theme Hospital. It must be used if translations like Russian or diff --git a/CorsixTH/Src/th_movie.cpp b/CorsixTH/Src/th_movie.cpp index 81e9f568c..44bf874f4 100644 --- a/CorsixTH/Src/th_movie.cpp +++ b/CorsixTH/Src/th_movie.cpp @@ -23,7 +23,7 @@ SOFTWARE. #include "th_movie.h" #include "config.h" #include "lua_sdl.h" -#ifdef CORSIX_TH_USE_FFMPEG +#if defined(CORSIX_TH_USE_FFMPEG) || defined(CORSIX_TH_USE_LIBAV) #include "th_gfx.h" extern "C" @@ -31,6 +31,7 @@ extern "C" #include #include #include + #include #include } #include @@ -399,7 +400,7 @@ THMovie::THMovie(): m_pVideoQueue(NULL), m_pAudioQueue(NULL), m_pMoviePictureBuffer(new THMoviePictureBuffer()), - m_pSwrContext(NULL), + m_pAudioResampleContext(NULL), m_iAudioBufferSize(0), m_iAudioBufferMaxSize(0), m_pAudioPacket(NULL), @@ -573,7 +574,16 @@ void THMovie::unload() m_frame = NULL; } - swr_free(&m_pSwrContext); +#ifdef CORSIX_TH_USE_FFMPEG + swr_free(&m_pAudioResampleContext); +#elif defined(CORSIX_TH_USE_LIBAV) + // avresample_free doesn't skip NULL on it's own. + if (m_pAudioResampleContext != NULL) + { + avresample_free(&m_pAudioResampleContext); + m_pAudioResampleContext = NULL; + } +#endif if(m_pAudioPacket) { @@ -620,8 +630,9 @@ void THMovie::play(int iX, int iY, int iWidth, int iHeight, int iChannel) if(m_iAudioStream >= 0) { Mix_QuerySpec(&m_iMixerFrequency, NULL, &m_iMixerChannels); - m_pSwrContext = swr_alloc_set_opts( - m_pSwrContext, +#ifdef CORSIX_TH_USE_FFMPEG + m_pAudioResampleContext = swr_alloc_set_opts( + m_pAudioResampleContext, m_iMixerChannels==1?AV_CH_LAYOUT_MONO:AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, m_iMixerFrequency, @@ -630,8 +641,17 @@ void THMovie::play(int iX, int iY, int iWidth, int iHeight, int iChannel) m_pAudioCodecContext->sample_rate, 0, NULL); - swr_init(m_pSwrContext); - + swr_init(m_pAudioResampleContext); +#elif defined(CORSIX_TH_USE_LIBAV) + m_pAudioResampleContext = avresample_alloc_context(); + av_opt_set_int(m_pAudioResampleContext, "in_channel_layout", m_pAudioCodecContext->channel_layout, 0); + av_opt_set_int(m_pAudioResampleContext, "out_channel_layout", m_iMixerChannels == 1 ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO, 0); + av_opt_set_int(m_pAudioResampleContext, "in_sample_rate", m_pAudioCodecContext->sample_rate, 0); + av_opt_set_int(m_pAudioResampleContext, "out_sample_rate", m_iMixerFrequency, 0); + av_opt_set_int(m_pAudioResampleContext, "in_sample_fmt", m_pAudioCodecContext->sample_fmt, 0); + av_opt_set_int(m_pAudioResampleContext, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); + avresample_open(m_pAudioResampleContext); +#endif m_pChunk = Mix_QuickLoad_RAW(m_pbChunkBuffer, AUDIO_BUFFER_SIZE); m_iChannel = Mix_PlayChannel(iChannel, m_pChunk, -1); @@ -788,7 +808,7 @@ void THMovie::runVideo() continue; } - dClockPts = iStreamPts * av_q2d(m_pVideoCodecContext->time_base); + dClockPts = iStreamPts * av_q2d(m_pFormatContext->streams[m_iVideoStream]->time_base); iError = m_pMoviePictureBuffer->write(pFrame, dClockPts); if(iError < 0) @@ -832,11 +852,19 @@ int THMovie::getVideoFrame(AVFrame *pFrame, int64_t *piPts) { iError = 1; +#ifdef CORSIX_TH_USE_LIBAV + *piPts = pFrame->pts; + if (*piPts == AV_NOPTS_VALUE) + { + *piPts = pFrame->pkt_dts; + } +#else #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 18, 100) *piPts = *(int64_t*)av_opt_ptr(avcodec_get_frame_class(), pFrame, "best_effort_timestamp"); #else *piPts = av_frame_get_best_effort_timestamp(pFrame); -#endif +#endif //LIBAVCODEC_VERSION_INT +#endif //CORSIX_T_USE_LIBAV if(*piPts == AV_NOPTS_VALUE) { @@ -995,7 +1023,7 @@ int THMovie::decodeAudioFrame(bool fFirst) //output samples = (input samples + delay) * output rate / input rate iOutSamples = (int)av_rescale_rnd( swr_get_delay( - m_pSwrContext, + m_pAudioResampleContext, m_pAudioCodecContext->sample_rate) + m_frame->nb_samples, m_iMixerFrequency, m_pAudioCodecContext->sample_rate, @@ -1013,11 +1041,14 @@ int THMovie::decodeAudioFrame(bool fFirst) } #endif - swr_convert(m_pSwrContext, &m_pbAudioBuffer, iOutSamples, (const uint8_t**)&m_frame->data[0], m_frame->nb_samples); - +#ifdef CORSIX_TH_USE_FFMPEG + swr_convert(m_pAudioResampleContext, &m_pbAudioBuffer, iOutSamples, (const uint8_t**)&m_frame->data[0], m_frame->nb_samples); +#elif defined(CORSIX_TH_USE_LIBAV) + avresample_convert(m_pAudioResampleContext, &m_pbAudioBuffer, 0, iOutSamples, (uint8_t**)&m_frame->data[0], 0, m_frame->nb_samples); +#endif return iSampleSize; } -#else //CORSIX_TH_USE_FFMPEG +#else //CORSIX_TH_USE_FFMPEG || CORSIX_TH_USE_LIBAV THMovie::THMovie() {} THMovie::~THMovie() {} void THMovie::setRenderer(SDL_Renderer *pRenderer) {} diff --git a/CorsixTH/Src/th_movie.h b/CorsixTH/Src/th_movie.h index bb1afde41..286826f4c 100644 --- a/CorsixTH/Src/th_movie.h +++ b/CorsixTH/Src/th_movie.h @@ -29,7 +29,7 @@ SOFTWARE. #include #include "config.h" -#ifdef CORSIX_TH_USE_FFMPEG +#if defined(CORSIX_TH_USE_FFMPEG) || defined(CORSIX_TH_USE_LIBAV) #include "SDL_mixer.h" extern "C" @@ -40,8 +40,12 @@ extern "C" #endif #include #include -#include #include +#ifdef CORSIX_TH_USE_FFMPEG +#include +#elif defined(CORSIX_TH_USE_LIBAV) +#include +#endif } struct SDL_Renderer; @@ -115,7 +119,7 @@ class THAVPacketQueue SDL_mutex *m_pMutex; SDL_cond *m_pCond; }; -#endif //CORSIX_TH_USE_FFMPEG +#endif //CORSIX_TH_USE_FFMPEG || CORSIX_TH_USE_LIBAV class THMovie { @@ -148,7 +152,7 @@ class THMovie void runVideo(); void copyAudioToStream(uint8_t *pbStream, int iStreamSize); protected: -#ifdef CORSIX_TH_USE_FFMPEG +#if defined(CORSIX_TH_USE_FFMPEG) || defined(CORSIX_TH_USE_LIBAV) int decodeAudioFrame(bool fFirst); int getVideoFrame(AVFrame *pFrame, int64_t *piPts); @@ -184,7 +188,11 @@ class THMovie double m_iCurSyncPts; //audio resample context - SwrContext* m_pSwrContext; +#ifdef CORSIX_TH_USE_FFMPEG + SwrContext* m_pAudioResampleContext; +#elif defined(CORSIX_TH_USE_LIBAV) + AVAudioResampleContext* m_pAudioResampleContext; +#endif //decoded audio buffer int m_iAudioBufferSize; @@ -215,7 +223,7 @@ class THMovie //threads SDL_Thread* m_pStreamThread; SDL_Thread* m_pVideoThread; -#endif //CORSIX_TH_USE_FFMPEG +#endif //CORSIX_TH_USE_FFMPEG || CORSIX_TH_USE_LIBAV }; #endif // TH_VIDEO_H From 4967521cdbb690448c16a9ed9b317d07a1c1358b Mon Sep 17 00:00:00 2001 From: "Stephen E. Baker" Date: Mon, 26 Jan 2015 21:40:35 -0500 Subject: [PATCH 2/3] Fix stutter in ffmpeg movie audio Attempting to calculate the resampling delay for determining the number of out samples was actually causing underruns. There is no harm in not accounting for any resample delay because any samples not taken are buffered for the next conversion. --- CorsixTH/Src/th_movie.cpp | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/CorsixTH/Src/th_movie.cpp b/CorsixTH/Src/th_movie.cpp index 44bf874f4..424ece97c 100644 --- a/CorsixTH/Src/th_movie.cpp +++ b/CorsixTH/Src/th_movie.cpp @@ -1005,7 +1005,6 @@ int THMovie::decodeAudioFrame(bool fFirst) } } -#if LIBSWRESAMPLE_VERSION_INT < AV_VERSION_INT(0, 12, 100) //over-estimate output samples iOutSamples = (int)av_rescale_rnd(m_frame->nb_samples, m_iMixerFrequency, m_pAudioCodecContext->sample_rate, AV_ROUND_UP); iSampleSize = av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * iOutSamples * m_iMixerChannels; @@ -1019,27 +1018,6 @@ int THMovie::decodeAudioFrame(bool fFirst) m_pbAudioBuffer = (uint8_t*)av_malloc(iSampleSize); m_iAudioBufferMaxSize = iSampleSize; } -#else - //output samples = (input samples + delay) * output rate / input rate - iOutSamples = (int)av_rescale_rnd( - swr_get_delay( - m_pAudioResampleContext, - m_pAudioCodecContext->sample_rate) + m_frame->nb_samples, - m_iMixerFrequency, - m_pAudioCodecContext->sample_rate, - AV_ROUND_UP); - iSampleSize = av_samples_get_buffer_size(NULL, m_iMixerChannels, iOutSamples, AV_SAMPLE_FMT_S16, 0); - - if(iSampleSize > m_iAudioBufferMaxSize) - { - if(m_iAudioBufferMaxSize > 0) - { - av_free(m_pbAudioBuffer); - } - av_samples_alloc(&m_pbAudioBuffer, NULL, m_iMixerChannels, iOutSamples, AV_SAMPLE_FMT_S16, 0); - m_iAudioBufferMaxSize = iSampleSize; - } -#endif #ifdef CORSIX_TH_USE_FFMPEG swr_convert(m_pAudioResampleContext, &m_pbAudioBuffer, iOutSamples, (const uint8_t**)&m_frame->data[0], m_frame->nb_samples); From 5710f1c38467e6c0664fc62220ee390ed37bdebc Mon Sep 17 00:00:00 2001 From: "Stephen E. Baker" Date: Thu, 29 Jan 2015 16:26:07 -0500 Subject: [PATCH 3/3] Fix deprecation warnings in th_movies.cpp and free frames properly Use av_frame_alloc, av_frame_unref, and av_frame_free instead of their earlier equivalents. In the case of av_frame_free we were not using the earlier equivalent but av_free. With these changes avcodec_frame_free will be used on versions that don't yet support av_frame_free. FFMPEG versions that do not support avcodec_frame_free are not supported with this commit. --- CorsixTH/Src/th_movie.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/CorsixTH/Src/th_movie.cpp b/CorsixTH/Src/th_movie.cpp index 424ece97c..39833480b 100644 --- a/CorsixTH/Src/th_movie.cpp +++ b/CorsixTH/Src/th_movie.cpp @@ -40,6 +40,13 @@ extern "C" #define INBUF_SIZE 4096 #define AUDIO_BUFFER_SIZE 1024 +#if (defined(CORSIX_TH_USE_LIBAV) && LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 45, 101)) || \ + (defined(CORSIX_TH_USE_FFMPEG) && LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 28, 1)) +#define av_frame_alloc avcodec_alloc_frame +#define av_frame_unref avcodec_get_frame_defaults +#define av_frame_free avcodec_free_frame +#endif + int th_movie_stream_reader_thread(void* pState) { THMovie *pMovie = (THMovie *)pState; @@ -272,7 +279,7 @@ int THMoviePictureBuffer::write(AVFrame* pFrame, double dPts) } /* Allocate a new frame and buffer for the destination RGB24 data. */ - AVFrame *pFrameRGB = avcodec_alloc_frame(); + AVFrame *pFrameRGB = av_frame_alloc(); int numBytes = avpicture_get_size(pMoviePicture->m_pixelFormat, pMoviePicture->m_iWidth, pMoviePicture->m_iHeight); uint8_t *buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t)); avpicture_fill((AVPicture *)pFrameRGB, buffer, pMoviePicture->m_pixelFormat, pMoviePicture->m_iWidth, pMoviePicture->m_iHeight); @@ -284,7 +291,7 @@ int THMoviePictureBuffer::write(AVFrame* pFrame, double dPts) SDL_UpdateTexture(pMoviePicture->m_pTexture, NULL, buffer, pMoviePicture->m_iWidth * 3); av_free(buffer); - av_free(pFrameRGB); + av_frame_free(&pFrameRGB); pMoviePicture->m_dPts = dPts; @@ -568,11 +575,7 @@ void THMovie::unload() avformat_close_input(&m_pFormatContext); } - if(m_frame) - { - av_free(m_frame); - m_frame = NULL; - } + av_frame_free(&m_frame); #ifdef CORSIX_TH_USE_FFMPEG swr_free(&m_pAudioResampleContext); @@ -787,7 +790,7 @@ void THMovie::readStreams() void THMovie::runVideo() { - AVFrame *pFrame = avcodec_alloc_frame(); + AVFrame *pFrame = av_frame_alloc(); int64_t iStreamPts = AV_NOPTS_VALUE; double dClockPts; int iError; @@ -796,7 +799,7 @@ void THMovie::runVideo() while(!m_fAborting) { - avcodec_get_frame_defaults(pFrame); + av_frame_unref(pFrame); iError = getVideoFrame(pFrame, &iStreamPts); if(iError < 0) @@ -818,7 +821,7 @@ void THMovie::runVideo() } avcodec_flush_buffers(m_pVideoCodecContext); - av_free(pFrame); + av_frame_free(&pFrame); } int THMovie::getVideoFrame(AVFrame *pFrame, int64_t *piPts) @@ -971,11 +974,11 @@ int THMovie::decodeAudioFrame(bool fFirst) { if(!m_frame) { - m_frame = avcodec_alloc_frame(); + m_frame = av_frame_alloc(); } else { - avcodec_get_frame_defaults(m_frame); + av_frame_unref(m_frame); } if(fFlushComplete)