Woohooo, gotta love open source, I was just about to discuss on osg-users the need for updating FindFFmpeg.cmake to make it portable... So I check my email before sending and hey presto the solution is my inbox ;-)
On the pkgconfig, it was just a quick solution, get things up and running quickly at my end. If FindFFmpeg.cmake without pkgconfig works across platforms then there is no need for this path and we can rely on the usual search paths. I'll now get to reviewing your changes. On the crash on exit front, I get it occasionally at this end as well and have investigated it already. It looks to be an issue of managing the various threads and object destruction. Leave me to resolving this, if I get it working cleanly at my end I'll ping the list to ask for me testing. On the warning front, I get the warnings too. Many from ffmpeg itself, and number from the ffmpeg plugin. I will be doing a review of the warnings and see what ones I can fix without any ambiguity, others I'll pass onto Tanguy to review as he may have different intentions for the code. We also need to contact the ffmpeg team to get some of the warnings fixed. Robert. On Wed, Mar 4, 2009 at 3:36 PM, Jean-Sébastien Guay <[email protected]> wrote: > Hi Robert, > > Sorry in advance for the long message... > > I wanted to test the ffmpeg module on Windows, so I had to modify the > FindFFMPEG.cmake file to find the headers and libs on my machine. > > I added steps that will be executed only if ffmpeg is not found using > pkgconfig (if applicable). In my case, I have pkgconfig, but it doesn't know > about the ffmpeg libraries I have, so I get the pkgconfig messages saying > that libavformat and others are not found, but that doesn't matter much. > Most other Windows machines won't have pkgconfig at all, so they'll just run > the other find code. > > I made a macro to find the include and lib directories of a given library > (libavformat, libavdevice, ...) in one shot. It's a simple macro, but looks > a lot better than copy-pasting that code 5 times. :-) > > For the swscale case, I'm not sure about which header(s) to look for to find > its include path. I put swscale.h, but for all I know that could not even > exist (the windows binaries Tanguy sent do not use swscale). Could you > please check and correct that? > > For the paths, I used the FindCOLLADA.cmake file as an example, keeping most > of the paths that are there in case they're used on other architectures. > Feel free to tweak the list of paths as you want. In my case, the first one > is used (FFMPEG_ROOT) since I set FFMPEG_DIR in my environment variables. > > Note that using this code path (not using pkgconfig), even if ffmpeg is not > found the paths can be entered manually (or with -D command line options I > think) by the user. I prefer setting an env var so that it will always be > found, but others might prefer doing it manually. > > I also added a message that will be displayed when FFMPEG is not found, you > can keep that or remove it at your discretion, but I think we should be > clearer about which optional libraries are found and which are not so that > we know what we're getting in our build... And if it's clear at CMake > configure time, we can check it right then instead of waiting till the > project is generated or building to find out. > > Using this CMake module, I can build the ffmpeg plugin. For some unknown > reason, FFmpegDecoderVideo.hpp included <boost/shared_ptr.h> but didn't use > it, so I removed the include (attached the modified file too). > > I'm getting warnings building the ffmpeg plugin, I thought you'd like to > know right now so they can be fixed or suppressed. > ____________________________________________________________________ > > 2>FFmpegDecoderVideo.cpp > 2>c:\dev\libs\ffmpeg-r15261\include\libavutil\common.h(213) : warning C4244: > 'return' : conversion from 'int' to 'uint8_t', possible loss of data > 2>c:\dev\libs\ffmpeg-r15261\include\libavutil\common.h(214) : warning C4244: > 'return' : conversion from 'int' to 'uint8_t', possible loss of data > 2>c:\dev\libs\ffmpeg-r15261\include\libavutil\common.h(224) : warning C4244: > 'return' : conversion from 'int' to 'int16_t', possible loss of data > 2>c:\dev\libs\ffmpeg-r15261\include\libavutil\common.h(225) : warning C4244: > 'return' : conversion from 'int' to 'int16_t', possible loss of data > 2>c:\dev\libs\ffmpeg-r15261\include\libavutil\rational.h(51) : warning > C4244: 'return' : conversion from 'const int64_t' to 'int', possible loss of > data > 2>FFmpegDecoder.cpp > 2>..\..\..\..\src\osgPlugins\ffmpeg\FFmpegDecoder.cpp(225) : warning C4389: > '==' : signed/unsigned mismatch > 2>..\..\..\..\src\osgPlugins\ffmpeg\FFmpegDecoder.cpp(232) : warning C4389: > '==' : signed/unsigned mismatch > 2>FFmpegDecoderAudio.cpp > 2>..\..\..\..\src\osgPlugins\ffmpeg\FFmpegDecoderAudio.cpp(120) : warning > C4189: 'filled' : local variable is initialized but not referenced > ____________________________________________________________________ > > But once the plugin is built, I can do: > > osgmovie -e ffmpeg <path>\aliensong.mpg --screen 1 > > and see the video. It seems to work with pretty much any video I throw at it > (.mov, .wmv, .avi, .flv, ...). > > I'm getting a crash on exit if I quit after letting it play for a while > though (but if I quit after just a few seconds it doesn't crash). I'll > investigate that and get back to you. > > Great work! Thanks, > > J-S > -- > ______________________________________________________ > Jean-Sebastien Guay [email protected] > http://www.cm-labs.com/ > http://whitestar02.webhop.org/ > > # Locate ffmpeg > # This module defines > # FFMPEG_LIBRARIES > # FFMPEG_FOUND, if false, do not try to link to ffmpeg > # FFMPEG_INCLUDE_DIR, where to find the headers > # > # $FFMPEG_DIR is an environment variable that would > # correspond to the ./configure --prefix=$FFMPEG_DIR > # > # Created by Robert Osfield. > > #use pkg-config to find various modes > INCLUDE(FindPkgConfig OPTIONAL) > > IF(PKG_CONFIG_FOUND) > > INCLUDE(FindPkgConfig) > > pkg_check_modules(FFMPEG_LIBAVFORMAT libavformat) > pkg_check_modules(FFMPEG_LIBAVDEVICE libavdevice) > pkg_check_modules(FFMPEG_LIBAVCODEC libavcodec) > pkg_check_modules(FFMPEG_LIBAVUTIL libavutil) > pkg_check_modules(FFMPEG_LIBSWSCALE libswscale) > > ENDIF(PKG_CONFIG_FOUND) > > # If FFMPEG was not found with pkgconfig, try to find it through other > means. > IF(NOT FFMPEG_LIBAVFORMAT_FOUND) > > # Macro to find header and lib directories > # example: FFMPEG_FIND(AVFORMAT avformat avformat.h) > MACRO(FFMPEG_FIND varname shortname headername) > # First try to find header directly in include directory > FIND_PATH(FFMPEG_${varname}_INCLUDE_DIRS ${headername} > ${FFMPEG_ROOT}/include > $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 > ) > > # If not found, try to find it in a subdirectory. Tanguy's build has > # avformat.h in include/libavformat, so this catches that case. If > that's > # standard, perhaps we can keep just this case. > IF(NOT FFMPEG_${varname}_INCLUDE_DIRS) > FIND_PATH(FFMPEG_${varname}_INCLUDE_DIRS > lib${shortname}/${headername} > ${FFMPEG_ROOT}/include > $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 > ) > ENDIF(NOT FFMPEG_${varname}_INCLUDE_DIRS) > > FIND_LIBRARY(FFMPEG_${varname}_LIBRARIES > NAMES ${shortname} > PATHS > ${FFMPEG_ROOT}/lib > $ENV{FFMPEG_DIR}/lib > $ENV{OSGDIR}/lib > $ENV{OSG_ROOT}/lib > ~/Library/Frameworks > /Library/Frameworks > /usr/local/lib > /usr/local/lib64 > /usr/lib > /usr/lib64 > /sw/lib > /opt/local/lib > /opt/csw/lib > /opt/lib > /usr/freeware/lib64 > ) > > IF (FFMPEG_${varname}_LIBRARIES) > SET(FFMPEG_${varname}_FOUND 1) > ENDIF(FFMPEG_${varname}_LIBRARIES) > > ENDMACRO(FFMPEG_FIND) > > SET(FFMPEG_ROOT "$ENV{FFMPEG_DIR}" CACHE PATH "Location of FFMPEG") > > 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) # not sure about the header > to look for here. > > ENDIF(NOT FFMPEG_LIBAVFORMAT_FOUND) > > SET(FFMPEG_FOUND "NO") > # Note we don't check FFMPEG_LIBSWSCALE_FOUND here, it's optional. > IF (FFMPEG_LIBAVFORMAT_FOUND AND FFMPEG_LIBAVDEVICE_FOUND AND > FFMPEG_LIBAVCODEC_FOUND AND FFMPEG_LIBAVUTIL_FOUND) > > SET(FFMPEG_FOUND "YES") > > SET(FFMPEG_INCLUDE_DIRS ${FFMPEG_LIBAVFORMAT_INCLUDE_DIRS}) > > SET(FFMPEG_LIBRARY_DIRS ${FFMPEG_LIBAVFORMAT_LIBRARY_DIRS}) > > # Note we don't add FFMPEG_LIBSWSCALE_LIBRARIES here, it will be added if > found later. > SET(FFMPEG_LIBRARIES > ${FFMPEG_LIBAVFORMAT_LIBRARIES} > ${FFMPEG_LIBAVDEVICE_LIBRARIES} > ${FFMPEG_LIBAVCODEC_LIBRARIES} > ${FFMPEG_LIBAVUTIL_LIBRARIES}) > > ELSE (FFMPEG_LIBAVFORMAT_FOUND AND FFMPEG_LIBAVDEVICE_FOUND AND > FFMPEG_LIBAVCODEC_FOUND AND FFMPEG_LIBAVUTIL_FOUND) > > MESSAGE(STATUS "Could not find FFMPEG") > > ENDIF(FFMPEG_LIBAVFORMAT_FOUND AND FFMPEG_LIBAVDEVICE_FOUND AND > FFMPEG_LIBAVCODEC_FOUND AND FFMPEG_LIBAVUTIL_FOUND) > > > #ifndef HEADER_GUARD_OSGFFMPEG_FFMPEG_DECODER_VIDEO_H > #define HEADER_GUARD_OSGFFMPEG_FFMPEG_DECODER_VIDEO_H > > > #include "FFmpegHeaders.hpp" > #include "BoundedMessageQueue.hpp" > #include "FFmpegClocks.hpp" > #include "FFmpegPacket.hpp" > > #include <OpenThreads/Thread> > #include <vector> > > namespace osgFFmpeg { > > class FramePtr > { > public: > > typedef AVFrame T; > > explicit FramePtr() : _ptr(0) {} > explicit FramePtr(T* ptr) : _ptr(ptr) {} > > ~FramePtr() > { > cleanup(); > } > > T* get() { return _ptr; } > > T * operator-> () const // never throws > { > return _ptr; > } > > void reset(T* ptr) > { > if (ptr==_ptr) return; > cleanup(); > _ptr = ptr; > } > > void cleanup() > { > if (_ptr) av_free(_ptr); > _ptr = 0; > } > > > > protected: > > T* _ptr; > }; > > class FFmpegDecoderVideo : public OpenThreads::Thread > { > public: > > typedef BoundedMessageQueue<FFmpegPacket> PacketQueue; > typedef void (* PublishFunc) (const FFmpegDecoderVideo & decoder, void * > user_data); > > FFmpegDecoderVideo(PacketQueue & packets, FFmpegClocks & clocks); > ~FFmpegDecoderVideo(); > > void open(AVStream * stream); > virtual void run(); > > void setUserData(void * user_data); > void setPublishCallback(PublishFunc function); > > int width() const; > int height() const; > double aspectRatio() const; > bool alphaChannel() const; > double frameRate() const; > const uint8_t * image() const; > > private: > > typedef std::vector<uint8_t> Buffer; > > void decodeLoop(); > void findAspectRatio(); > void publishFrame(double delay); > void swapBuffers(); > double synchronizeVideo(double pts); > void yuva420pToRgba(AVPicture *dst, const AVPicture *src, int width, int > height); > > int convert(AVPicture *dst, int dst_pix_fmt, const AVPicture *src, > int src_pix_fmt, int src_width, int src_height); > > > static int getBuffer(AVCodecContext * context, AVFrame * picture); > static void releaseBuffer(AVCodecContext * context, AVFrame * picture); > > PacketQueue & m_packets; > FFmpegClocks & m_clocks; > AVStream * m_stream; > AVCodecContext * m_context; > AVCodec * m_codec; > const uint8_t * m_packet_data; > int m_bytes_remaining; > int64_t m_packet_pts; > > FramePtr m_frame; > FramePtr m_frame_rgba; > Buffer m_buffer_rgba; > Buffer m_buffer_rgba_public; > > void * m_user_data; > PublishFunc m_publish_func; > > double m_frame_rate; > double m_aspect_ratio; > int m_width; > int m_height; > size_t m_next_frame_index; > bool m_alpha_channel; > > volatile bool m_exit; > > #ifdef USE_SWSCALE > struct SwsContext * m_swscale_ctx; > #endif > }; > > > > > > inline void FFmpegDecoderVideo::setUserData(void * const user_data) > { > m_user_data = user_data; > } > > > inline void FFmpegDecoderVideo::setPublishCallback(const PublishFunc > function) > { > m_publish_func = function; > } > > > inline int FFmpegDecoderVideo::width() const > { > return m_width; > } > > > inline int FFmpegDecoderVideo::height() const > { > return m_height; > } > > > inline double FFmpegDecoderVideo::aspectRatio() const > { > return m_aspect_ratio; > } > > > inline bool FFmpegDecoderVideo::alphaChannel() const > { > return m_alpha_channel; > } > > > inline double FFmpegDecoderVideo::frameRate() const > { > return m_frame_rate; > } > > > inline const uint8_t * FFmpegDecoderVideo::image() const > { > return &m_buffer_rgba_public[0]; > } > > > > } // namespace osgFFmpeg > > > > #endif // HEADER_GUARD_OSGFFMPEG_FFMPEG_DECODER_VIDEO_H > > _______________________________________________ > osg-submissions mailing list > [email protected] > http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org > > _______________________________________________ osg-submissions mailing list [email protected] http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org
