Not compiling with newest ffmpeg

Bug #1075053 reported by Plaristote
8
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Panda3D
Fix Released
Undecided
rdb

Bug Description

Panda3D ffmpeg module doesn't compile with the most recent versions of ffmpeg, as the ArchLinux users will have noticed (since the package version of ffmpeg there is 1:1.0-1).

Some deprecated functions used by Panda3D have been removed.
Someone talked about it in the ArchLinux forum:
https://bbs.archlinux.org/viewtopic.php?id=145045
He presented downgrading as a solution, but it's more of a workaround :( !

I'll use his post to show you the errors and warning during compilation:
In file included from panda/src/movies/p3movies_composite2.cxx:3:0:
panda/src/movies/ffmpegVirtualFile.cxx: In member function ‘bool FfmpegVirtualFile::open_vfs(const Filename&)’:
panda/src/movies/ffmpegVirtualFile.cxx:123:68: error: ‘av_open_input_file’ was not declared in this scope
panda/src/movies/ffmpegVirtualFile.cxx: In member function ‘bool FfmpegVirtualFile::open_subfile(const SubfileInfo&)’:
panda/src/movies/ffmpegVirtualFile.cxx:179:68: error: ‘av_open_input_file’ was not declared in this scope
panda/src/movies/ffmpegVirtualFile.cxx: In member function ‘void FfmpegVirtualFile::close()’:
panda/src/movies/ffmpegVirtualFile.cxx:197:5: warning: ‘void av_close_input_file(AVFormatContext*)’ is deprecated (declared at /usr/include/libavformat/avformat.h:1533) [-Wdeprecated-declarations]
panda/src/movies/ffmpegVirtualFile.cxx:197:40: warning: ‘void av_close_input_file(AVFormatContext*)’ is deprecated (declared at /usr/include/libavformat/avformat.h:1533) [-Wdeprecated-declarations]
panda/src/movies/ffmpegVirtualFile.cxx: In static member function ‘static void FfmpegVirtualFile::register_protocol()’:
panda/src/movies/ffmpegVirtualFile.cxx:231:10: error: ‘URLProtocol’ does not name a type
panda/src/movies/ffmpegVirtualFile.cxx:232:3: error: ‘protocol’ was not declared in this scope
panda/src/movies/ffmpegVirtualFile.cxx:249:52: error: ‘av_register_protocol2’ was not declared in this scope
panda/src/movies/ffmpegVirtualFile.cxx: In static member function ‘static int FfmpegVirtualFile::pandavfs_open(URLContext*, const char*, int)’:
panda/src/movies/ffmpegVirtualFile.cxx:271:4: error: invalid use of incomplete type ‘struct URLContext’
In file included from panda/src/movies/ffmpegAudioCursor.h:26:0,
                 from panda/src/movies/ffmpegAudio.cxx:19,
                 from panda/src/movies/p3movies_composite2.cxx:1:
panda/src/movies/ffmpegVirtualFile.h:31:8: error: forward declaration of ‘struct URLContext’
In file included from panda/src/movies/p3movies_composite2.cxx:3:0:
panda/src/movies/ffmpegVirtualFile.cxx: In static member function ‘static int FfmpegVirtualFile::pandavfs_read(URLContext*, unsigned char*, int)’:
panda/src/movies/ffmpegVirtualFile.cxx:282:52: error: invalid use of incomplete type ‘struct URLContext’
In file included from panda/src/movies/ffmpegAudioCursor.h:26:0,
                 from panda/src/movies/ffmpegAudio.cxx:19,
                 from panda/src/movies/p3movies_composite2.cxx:1:
panda/src/movies/ffmpegVirtualFile.h:31:8: error: forward declaration of ‘struct URLContext’
In file included from panda/src/movies/p3movies_composite2.cxx:3:0:
panda/src/movies/ffmpegVirtualFile.cxx: In static member function ‘static int64_t FfmpegVirtualFile::pandavfs_seek(URLContext*, int64_t, int)’:
panda/src/movies/ffmpegVirtualFile.cxx:324:52: error: invalid use of incomplete type ‘struct URLContext’
In file included from panda/src/movies/ffmpegAudioCursor.h:26:0,
                 from panda/src/movies/ffmpegAudio.cxx:19,
                 from panda/src/movies/p3movies_composite2.cxx:1:
panda/src/movies/ffmpegVirtualFile.h:31:8: error: forward declaration of ‘struct URLContext’
In file included from panda/src/movies/p3movies_composite2.cxx:3:0:
panda/src/movies/ffmpegVirtualFile.cxx: In static member function ‘static int FfmpegVirtualFile::pandavfs_close(URLContext*)’:
panda/src/movies/ffmpegVirtualFile.cxx:365:4: error: invalid use of incomplete type ‘struct URLContext’
In file included from panda/src/movies/ffmpegAudioCursor.h:26:0,
                 from panda/src/movies/ffmpegAudio.cxx:19,
                 from panda/src/movies/p3movies_composite2.cxx:1:
panda/src/movies/ffmpegVirtualFile.h:31:8: error: forward declaration of ‘struct URLContext’
In file included from panda/src/movies/p3movies_composite2.cxx:4:0:
panda/src/movies/ffmpegAudioCursor.cxx: In constructor ‘FfmpegAudioCursor::FfmpegAudioCursor(FfmpegAudio*)’:
panda/src/movies/ffmpegAudioCursor.cxx:55:7: warning: ‘int av_find_stream_info(AVFormatContext*)’ is deprecated (declared at /usr/include/libavformat/avformat.h:1357) [-Wdeprecated-declarations]
panda/src/movies/ffmpegAudioCursor.cxx:55:38: warning: ‘int av_find_stream_info(AVFormatContext*)’ is deprecated (declared at /usr/include/libavformat/avformat.h:1357) [-Wdeprecated-declarations]
panda/src/movies/ffmpegAudioCursor.cxx:81:6: warning: ‘int avcodec_open(AVCodecContext*, AVCodec*)’ is deprecated (declared at /usr/include/libavcodec/avcodec.h:3380) [-Wdeprecated-declarations]
panda/src/movies/ffmpegAudioCursor.cxx:81:42: warning: ‘int avcodec_open(AVCodecContext*, AVCodec*)’ is deprecated (declared at /usr/include/libavcodec/avcodec.h:3380) [-Wdeprecated-declarations]
panda/src/movies/ffmpegAudioCursor.cxx: In member function ‘bool FfmpegAudioCursor::reload_buffer()’:
panda/src/movies/ffmpegAudioCursor.cxx:218:17: warning: ‘int avcodec_decode_audio3(AVCodecContext*, int16_t*, int*, AVPacket*)’ is deprecated (declared at /usr/include/libavcodec/avcodec.h:3658) [-Wdeprecated-declarations]
panda/src/movies/ffmpegAudioCursor.cxx:218:74: warning: ‘int avcodec_decode_audio3(AVCodecContext*, int16_t*, int*, AVPacket*)’ is deprecated (declared at /usr/include/libavcodec/avcodec.h:3658) [-Wdeprecated-declarations]
panda/src/movies/ffmpegAudioCursor.cxx: In member function ‘virtual void FfmpegAudioCursor::seek(double)’:
panda/src/movies/ffmpegAudioCursor.cxx:266:6: warning: ‘int avcodec_open(AVCodecContext*, AVCodec*)’ is deprecated (declared at /usr/include/libavcodec/avcodec.h:3380) [-Wdeprecated-declarations]
panda/src/movies/ffmpegAudioCursor.cxx:266:42: warning: ‘int avcodec_open(AVCodecContext*, AVCodec*)’ is deprecated (declared at /usr/include/libavcodec/avcodec.h:3380) [-Wdeprecated-declarations]
In file included from panda/src/movies/p3movies_composite2.cxx:5:0:
panda/src/movies/ffmpegVideoCursor.cxx: In member function ‘bool FfmpegVideoCursor::open_stream()’:
panda/src/movies/ffmpegVideoCursor.cxx:512:7: warning: ‘int av_find_stream_info(AVFormatContext*)’ is deprecated (declared at /usr/include/libavformat/avformat.h:1357) [-Wdeprecated-declarations]
panda/src/movies/ffmpegVideoCursor.cxx:512:38: warning: ‘int av_find_stream_info(AVFormatContext*)’ is deprecated (declared at /usr/include/libavformat/avformat.h:1357) [-Wdeprecated-declarations]
panda/src/movies/ffmpegVideoCursor.cxx:544:7: warning: ‘int avcodec_open(AVCodecContext*, AVCodec*)’ is deprecated (declared at /usr/include/libavcodec/avcodec.h:3380) [-Wdeprecated-declarations]
panda/src/movies/ffmpegVideoCursor.cxx:544:43: warning: ‘int avcodec_open(AVCodecContext*, AVCodec*)’ is deprecated (declared at /usr/include/libavcodec/avcodec.h:3380) [-Wdeprecated-declarations]
Storing dependency cache.
Elapsed Time: 8 min 5 sec
The following command returned a non-zero value: g++ -ftemplate-depth-30 -fPIC -c -o built/tmp/p3movies_composite2.o -Ibuilt/tmp -Ibuilt/include -I/usr/include/python2.7 -DMAKEPANDA= -Ipanda/src/movies -pthread -msse2 -O2 -march=x86-64 -mtune=generic -O2 -pipe -fstack-protector --param=ssp-buffer-size=4 -D_FORTIFY_SOURCE=2 -DBUILDING_PANDA panda/src/movies/p3movies_composite2.cxx

Revision history for this message
Tureba (tureba) wrote :

Attached is as partial solution. It fixes some of the problems I encountered regarding ffmpegAudioCursor.cxx and ffmpegVideoCursor.cxx. But the ffmpegVirtualFile.cxx is a different subject. The whole API was trashed and redone, so the whole class needs to be overhauled now.

Old ffmpeg support is old. As the packager of a rolling release distro, I recommend removing the support for the older APIs (say, 5+ years) and add some minimum ffmpeg version as dependency. It would simplify greatly those #if checks of my patch and a lot more of previous code. Even other distros don't use any ffmpeg older than 0.8 anymore, so I don't think anyone loses. Food for thought.

Revision history for this message
rdb (rdb) wrote :

Thank you for the patch, I will review it soon. I just also remembered some separate changes I had made to ffmpegVirtualFile, which I just checked in, but you're right - it requires overhauling so that we can support the newer versions. If only the ffmpeg developers would stop changing the API so often...

Would you like to volunteer to rewrite the FfmpegVirtualFile interface?

Revision history for this message
Tureba (tureba) wrote :

I will see what I can do to ffmpegVirtualFile, but I never used it myself, so the testing will be limited.

I also noticed a couple of other problems that need attention, but I haven't found good solutions to them yet. For instance, img_convert has been completely removed in favour of sws_scale, so sws is mandatory for recent versions ffmpeg. Which is not really a problem, since sws is a part of ffmpeg - only distros that insist on dismembering ffmpeg into a dozen packages or two will see a problem - not my case. Still, it would be nice to find a way to not break other people's build systems, so I will have to get back to you on that one later.

Revision history for this message
Tureba (tureba) wrote :

Upon further inspection, the URLProtocol API and friends were completely internalized and are not exported anymore. That means that FfmpegVirtualFile cannot be used with most versions of ffmpeg nowadays, that is, libavformat API version 52.107.0 onwards.

Does anyone actually use this? It seems that not even Ubuntu has the headers necessary for compilation anymore (or perhaps Lucid LTS). I am very inclined to remove FfmpegVirtualFile from Sources.pp until upstream changes their minds or something else happens.

I understand it is a useful functionality, but even if upstream exports back the protocol registering API, it would take quite a while until everyone got the update, and there would still be a huge hiatus of unworking ffmpeg/libavformat versions to consider.

Comments?

Revision history for this message
rdb (rdb) wrote :

Thanks, your help is greatly appreciated!

Using URLProtocol directly is deprecated. Nowadays, one is supposed to use the higher-level AVIOContext interface. This structure also defines function pointers where we can supply hooks to load files via our own virtual file system.

(Removing it is not an option at the moment as it would remove the ability to play videos and decode sounds when loading from a .p3d file.)

We don't use img_convert anymore for quite a while, we do have support for libswscale. The img_convert code is still there, but it only gets invoked when HAVE_SWSCALE is not defined.

Revision history for this message
Tureba (tureba) wrote :

I may be mistaken, but from what I see, AVIOContext is a replacement for URLContext, not for URLProtocol, which is necessary for av_register_protocol2 (also gone).

I mentioned img_convert because I bumped into it and it botched my compilation. I will consider removing it if it is really not needed on any configuration.

Revision history for this message
rdb (rdb) wrote :

It seems that all that may be needed is to create an AVIOContext using avio_alloc_context and passing the function pointers of the Panda hooks to that function, and then making sure that ffmpeg uses that particular AVIOContext when using the avformat_open_xxx functions, or something like that.

Revision history for this message
rdb (rdb) wrote :

From the ffmpeg docs: ( http://ffmpeg.org/doxygen/trunk/group__lavf__decoding.html )
"In some cases you might want to preallocate an AVFormatContext yourself with avformat_alloc_context() and do some tweaking on it before passing it to avformat_open_input(). One such case is when you want to use custom functions for reading input data instead of lavf internal I/O layer. To do that, create your own AVIOContext with avio_alloc_context(), passing your reading callbacks to it. Then set the pb field of your AVFormatContext to newly created AVIOContext."

Revision history for this message
rdb (rdb) wrote :

Replying to your comment that I just noticed (sorry for the flood of e-mails): Well, if we can use AVIOContext directly instead of using the protocol interface, perhaps we can avoid the hacky pandavfs:// protocol method entirely and just use it the way it was intended, by directly hooking in at the context level.

Revision history for this message
rdb (rdb) wrote :

I've just committed most of the changes from the original patch. I'm not 100% sure about the avcodec_decode_audio4 part yet, so I haven't checked in that part yet.

Revision history for this message
rdb (rdb) wrote :

OK, I finally took care of the rest. I removed the old URLProtocol interface, replaced it with a shiny new AVIOContext interface and ported the audio cursor code to use avcodec_decode_audio4.

They also changed some codecs to return float data instead of 16-bit signed ints, so I added support for libswresample (part of ffmpeg nowadays) in order to resample the data to 16-bit signed int. This means that you'll need to compile with support for libswresample in order to use a recent build of ffmpeg.

There might be a range of not-too-old ffmpeg versions that doesn't have avcodec_decode_audio4 but still supplies float data. If you have one of those, tough luck. I can't really be bothered to special-case every single permutation of ffmpeg features. If you have trouble, just upgrade.

Now watch all this effort become obsolete when they release a new version of ffmpeg tomorrow that deprecates all of this again in favour of a new interface. Gee, I hope not.

Changed in panda3d:
assignee: nobody → rdb (rdb)
status: New → Fix Committed
milestone: none → 1.9.0
rdb (rdb)
Changed in panda3d:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.