From 830bfcb05610369890cf7d8b8d39065ab08fad01 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 16 Jun 2011 20:23:30 +0000 Subject: [PATCH] integrate with latest ffmpeg --- panda/src/framework/windowFramework.cxx | 13 +++++-- panda/src/grutil/ffmpegTexture.cxx | 52 ++++++++++++++++--------- panda/src/movies/config_movies.cxx | 1 + panda/src/movies/config_movies.h | 1 + panda/src/movies/ffmpegAudioCursor.cxx | 8 +++- panda/src/movies/ffmpegVideoCursor.cxx | 9 ++++- panda/src/movies/ffmpegVirtualFile.cxx | 50 ++++++++++++++++++++++-- panda/src/movies/ffmpegVirtualFile.h | 10 +++-- 8 files changed, 110 insertions(+), 34 deletions(-) diff --git a/panda/src/framework/windowFramework.cxx b/panda/src/framework/windowFramework.cxx index 305a20af76..85135d2687 100644 --- a/panda/src/framework/windowFramework.cxx +++ b/panda/src/framework/windowFramework.cxx @@ -1229,18 +1229,25 @@ load_image_as_model(const Filename &filename) { // Choose the dimensions of the polygon appropriately. float left,right,top,bottom; + static const float scale = 10.0; if (x_size > y_size) { - float scale = 10.0; left = -scale; right = scale; top = (scale * y_size) / x_size; bottom = -(scale * y_size) / x_size; - } else { - float scale = 10.0; + } else if (y_size != 0) { left = -(scale * x_size) / y_size; right = (scale * x_size) / y_size; top = scale; bottom = -scale; + } else { + framework_cat.warning() + << "Texture size is 0 0: " << *tex << "\n"; + + left = -scale; + right = scale; + top = scale; + bottom = -scale; } PT(GeomNode) card_node = new GeomNode("card"); diff --git a/panda/src/grutil/ffmpegTexture.cxx b/panda/src/grutil/ffmpegTexture.cxx index 5a4df8d265..589de7f5cf 100644 --- a/panda/src/grutil/ffmpegTexture.cxx +++ b/panda/src/grutil/ffmpegTexture.cxx @@ -24,6 +24,10 @@ TypeHandle FFMpegTexture::_type_handle; +#if LIBAVFORMAT_VERSION_MAJOR < 53 + #define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO +#endif + //////////////////////////////////////////////////////////////////// // Function: FFMpegTexture::Constructor // Access: Published @@ -271,9 +275,8 @@ update_frame(int frame) { source -= source_row_width; } } - - } + ++_image_modified; } if (page._alpha.is_valid()) { @@ -301,8 +304,8 @@ update_frame(int frame) { dest += dest_row_width; source -= source_row_width; } - } + ++_image_modified; } } } @@ -513,12 +516,12 @@ get_frame_data(int frame_number) { if (frame_number > coming_from) { // Ok, we do have to skip a few frames. - _codec_context->hurry_up = true; + _codec_context->skip_frame = AVDISCARD_BIDIR; + while (frame_number > coming_from) { int err = read_video_frame(&packet); if (err < 0) { return false; - } #if LIBAVCODEC_VERSION_INT < 3414272 avcodec_decode_video(_codec_context, _frame, &got_frame, packet.data, packet.size); @@ -528,7 +531,7 @@ get_frame_data(int frame_number) { av_free_packet(&packet); ++coming_from; } - _codec_context->hurry_up = false; + _codec_context->skip_frame = AVDISCARD_DEFAULT; } // Now we're ready to read a frame. @@ -550,7 +553,7 @@ get_frame_data(int frame_number) { // Okay, now we're at the nearest keyframe behind our timestamp. // Hurry up and move through frames until we find a frame just after it. - _codec_context->hurry_up = true; + _codec_context->skip_frame = AVDISCARD_BIDIR; do { int err = read_video_frame(&packet); if (err < 0) { @@ -564,15 +567,15 @@ get_frame_data(int frame_number) { } #if LIBAVCODEC_VERSION_INT < 3414272 - avcodec_decode_video(_codec_context, _frame, &got_frame, packet.data, packet.size); + avcodec_decode_video(_codec_context, _frame, &got_frame, packet.data, packet.size); #else - avcodec_decode_video2(_codec_context, _frame, &got_frame, &packet); + avcodec_decode_video2(_codec_context, _frame, &got_frame, &packet); #endif av_free_packet(&packet); } while (true); - _codec_context->hurry_up = false; + _codec_context->skip_frame = AVDISCARD_DEFAULT; // Now near frame with Packet ready for decode (and free) } @@ -584,9 +587,9 @@ get_frame_data(int frame_number) { if (packet.stream_index == _stream_number) { // Decode video frame #if LIBAVCODEC_VERSION_INT < 3414272 - avcodec_decode_video(_codec_context, _frame, &frame_finished, packet.data, packet.size); + avcodec_decode_video(_codec_context, _frame, &frame_finished, packet.data, packet.size); #else - avcodec_decode_video2(_codec_context, _frame, &frame_finished, &packet); + avcodec_decode_video2(_codec_context, _frame, &frame_finished, &packet); #endif // Did we get a video frame? @@ -603,9 +606,10 @@ get_frame_data(int frame_number) { } else { dst_format = PIX_FMT_RGB32; } - struct SwsContext *convert_ctx = sws_getContext(_codec_context->width, _codec_context->height, - _codec_context->pix_fmt, _codec_context->width, _codec_context->height, - dst_format, 2, NULL, NULL, NULL); + struct SwsContext *convert_ctx = + sws_getContext(_codec_context->width, _codec_context->height, + _codec_context->pix_fmt, _codec_context->width, _codec_context->height, + dst_format, SWS_FAST_BILINEAR, NULL, NULL, NULL); nassertr(convert_ctx != NULL, false); sws_scale(convert_ctx, _frame->data, _frame->linesize, 0, _codec_context->height, _frame_out->data, _frame_out->linesize); @@ -663,7 +667,7 @@ read(const Filename &filename) { _stream_number = -1; for(int i = 0; i < _format_context->nb_streams; i++) { - if ((*_format_context->streams[i]->codec).codec_type == CODEC_TYPE_VIDEO) { + if ((*_format_context->streams[i]->codec).codec_type == AVMEDIA_TYPE_VIDEO) { _stream_number = i; break; } @@ -671,7 +675,7 @@ read(const Filename &filename) { if (_stream_number == -1) { grutil_cat.error() - << "ffmpeg: no stream found with codec of type CODEC_TYPE_VIDEO" << endl; + << "ffmpeg: no stream found with codec of type AVMEDIA_TYPE_VIDEO" << endl; clear(); return false; } @@ -796,6 +800,10 @@ clear() { int FFMpegTexture::VideoStream:: read_video_frame(AVPacket *packet) { int err = av_read_frame(_format_context, packet); + if (grutil_cat.is_spam()) { + grutil_cat.spam() + << "av_read_frame() = " << err << "\n"; + } if (err < 0) { return err; } @@ -805,9 +813,15 @@ read_video_frame(AVPacket *packet) { av_free_packet(packet); err = av_read_frame(_format_context, packet); + if (grutil_cat.is_spam()) { + grutil_cat.spam() + << "av_read_frame() = " << err << "\n"; + } if (err < 0) { - grutil_cat.debug() - << "Got error " << err << " reading frame.\n"; + if (grutil_cat.is_debug()) { + grutil_cat.debug() + << "Got error " << err << " reading frame.\n"; + } return err; } } diff --git a/panda/src/movies/config_movies.cxx b/panda/src/movies/config_movies.cxx index 424cb8c665..4bbed30c6a 100644 --- a/panda/src/movies/config_movies.cxx +++ b/panda/src/movies/config_movies.cxx @@ -23,6 +23,7 @@ extern "C" { ConfigureDef(config_movies); NotifyCategoryDef(movies, ""); +NotifyCategoryDef(ffmpeg, "movies"); ConfigureFn(config_movies) { init_libmovies(); diff --git a/panda/src/movies/config_movies.h b/panda/src/movies/config_movies.h index 9402b11264..c91c138c4f 100644 --- a/panda/src/movies/config_movies.h +++ b/panda/src/movies/config_movies.h @@ -38,6 +38,7 @@ ConfigureDecl(config_movies, EXPCL_PANDA_MOVIES, EXPTP_PANDA_MOVIES); NotifyCategoryDecl(movies, EXPCL_PANDA_MOVIES, EXPTP_PANDA_MOVIES); +NotifyCategoryDecl(ffmpeg, EXPCL_PANDA_MOVIES, EXPTP_PANDA_MOVIES); extern EXPCL_PANDA_MOVIES void init_libmovies(); diff --git a/panda/src/movies/ffmpegAudioCursor.cxx b/panda/src/movies/ffmpegAudioCursor.cxx index d689de0fdc..c8eca204ca 100644 --- a/panda/src/movies/ffmpegAudioCursor.cxx +++ b/panda/src/movies/ffmpegAudioCursor.cxx @@ -22,6 +22,10 @@ extern "C" { TypeHandle FfmpegAudioCursor::_type_handle; +#if LIBAVFORMAT_VERSION_MAJOR < 53 + #define AVMEDIA_TYPE_AUDIO CODEC_TYPE_AUDIO +#endif + //////////////////////////////////////////////////////////////////// // Function: FfmpegAudioCursor::Constructor // Access: Protected @@ -51,8 +55,8 @@ FfmpegAudioCursor(FfmpegAudio *src) : } // Find the audio stream - for(int i=0; i<_format_ctx->nb_streams; i++) { - if(_format_ctx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO) { + for(int i = 0; i < (int)_format_ctx->nb_streams; i++) { + if(_format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { _audio_index = i; _audio_ctx = _format_ctx->streams[i]->codec; _audio_timebase = av_q2d(_format_ctx->streams[i]->time_base); diff --git a/panda/src/movies/ffmpegVideoCursor.cxx b/panda/src/movies/ffmpegVideoCursor.cxx index ead9eab71d..789e8052ac 100644 --- a/panda/src/movies/ffmpegVideoCursor.cxx +++ b/panda/src/movies/ffmpegVideoCursor.cxx @@ -28,6 +28,11 @@ extern "C" { TypeHandle FfmpegVideoCursor::_type_handle; +#if LIBAVFORMAT_VERSION_MAJOR < 53 + #define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO +#endif + + //////////////////////////////////////////////////////////////////// // Function: FfmpegVideoCursor::Constructor // Access: Public @@ -58,8 +63,8 @@ FfmpegVideoCursor(FfmpegVideo *src) : } // Find the video stream - for(int i=0; i<_format_ctx->nb_streams; i++) { - if(_format_ctx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) { + for(int i = 0; i < (int)_format_ctx->nb_streams; i++) { + if(_format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { _video_index = i; _video_ctx = _format_ctx->streams[i]->codec; _video_timebase = av_q2d(_format_ctx->streams[i]->time_base); diff --git a/panda/src/movies/ffmpegVirtualFile.cxx b/panda/src/movies/ffmpegVirtualFile.cxx index 54adedbb41..27e66c8105 100644 --- a/panda/src/movies/ffmpegVirtualFile.cxx +++ b/panda/src/movies/ffmpegVirtualFile.cxx @@ -50,9 +50,13 @@ extern "C" { static int pandavfs_open(URLContext *h, const char *filename, int flags) { if (flags != 0) { - movies_cat.error() << "ffmpeg is trying to write to the VFS.\n"; - return -1; + if (movies_cat.is_debug()) { + movies_cat.debug() + << "ffmpeg is trying to write to the VFS.\n"; + } + // We'll allow this, but just fail any actual writes. } + filename += 9; // Skip over "pandavfs:" VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); istream *s = vfs->open_read_file(filename, true); @@ -98,7 +102,8 @@ pandavfs_write(URLContext *h, unsigned char *buf, int size) { #else pandavfs_write(URLContext *h, const unsigned char *buf, int size) { #endif - movies_cat.error() << "ffmpeg is trying to write to the VFS.\n"; + movies_cat.warning() + << "ffmpeg is trying to write to the VFS.\n"; return -1; } @@ -177,9 +182,46 @@ register_protocol() { protocol.url_close = pandavfs_close; #if LIBAVFORMAT_VERSION_INT < 3415296 ::register_protocol(&protocol); -#else +#elif LIBAVFORMAT_VERSION_MAJOR < 53 av_register_protocol(&protocol); +#else + av_register_protocol2(&protocol, sizeof(protocol)); #endif + + // Let's also register the logging to Panda's notify callback. + av_log_set_callback(&log_callback); +} + +//////////////////////////////////////////////////////////////////// +// Function: FfmpegVirtualFile::log_callback +// Access: Private, Static +// Description: These callbacks are made when ffmpeg wants to write a +// log entry; it redirects into Panda's notify. +//////////////////////////////////////////////////////////////////// +void FfmpegVirtualFile:: +log_callback(void *ptr, int level, const char *fmt, va_list v1) { + NotifySeverity severity; + if (level <= AV_LOG_PANIC) { + severity = NS_fatal; + } else if (level <= AV_LOG_ERROR) { + severity = NS_error; + } else if (level <= AV_LOG_WARNING) { + severity = NS_warning; + } else if (level <= AV_LOG_INFO) { + severity = NS_info; + } else if (level <= AV_LOG_VERBOSE) { + severity = NS_debug; + } else /* level <= AV_LOG_DEBUG */ { + severity = NS_spam; + } + + if (ffmpeg_cat.is_on(severity)) { + static const size_t buffer_size = 4096; + static char buffer[buffer_size]; + vsnprintf(buffer, buffer_size, fmt, v1); + ffmpeg_cat.out(severity, true) + << buffer; + } } #endif // HAVE_FFMPEG diff --git a/panda/src/movies/ffmpegVirtualFile.h b/panda/src/movies/ffmpegVirtualFile.h index 7ddfa52335..48cc490939 100644 --- a/panda/src/movies/ffmpegVirtualFile.h +++ b/panda/src/movies/ffmpegVirtualFile.h @@ -17,15 +17,14 @@ #ifdef HAVE_FFMPEG #include "config_movies.h" +#include //////////////////////////////////////////////////////////////////// // Class : FfmpegVirtualFile // Description : Enables ffmpeg to access panda's VFS. // -// This class only has one public method, -// register_hooks. Once the hooks are registered, -// ffmpeg will be able to open "URLs" that look -// like this: +// Once register_protocol() is called, ffmpeg will be +// able to open "URLs" that look like this: // // pandavfs:/c/mygame/foo.avi // @@ -33,6 +32,9 @@ class EXPCL_PANDA_MOVIES FfmpegVirtualFile { public: static void register_protocol(); + + private: + static void log_callback(void *ptr, int level, const char *fmt, va_list v1); }; #include "ffmpegVirtualFile.I"