2
0
Эх сурвалжийг харах

integrate with latest ffmpeg

David Rose 14 жил өмнө
parent
commit
830bfcb056

+ 10 - 3
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");

+ 33 - 19
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;
     }
   }

+ 1 - 0
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();

+ 1 - 0
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();
 

+ 6 - 2
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);

+ 7 - 2
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);

+ 46 - 4
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

+ 6 - 4
panda/src/movies/ffmpegVirtualFile.h

@@ -17,15 +17,14 @@
 #ifdef HAVE_FFMPEG
 
 #include "config_movies.h"
+#include <stdarg.h>
 
 ////////////////////////////////////////////////////////////////////
 //       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"