Browse Source

ffmpeg: proper fallback when compiling without libswscale

Compiling with libswscale isn't really optional if you want to play most video files, but if you know what you are doing and all your videos already have a supported pixel formats, it is now possible.

Fixes #711
rdb 6 years ago
parent
commit
806496d191
1 changed files with 25 additions and 11 deletions
  1. 25 11
      panda/src/ffmpeg/ffmpegVideoCursor.cxx

+ 25 - 11
panda/src/ffmpeg/ffmpegVideoCursor.cxx

@@ -138,6 +138,15 @@ init_from(FfmpegVideo *source) {
   _convert_ctx = sws_getContext(_size_x, _size_y, _video_ctx->pix_fmt,
                                 _size_x, _size_y, (AVPixelFormat)_pixel_format,
                                 SWS_BILINEAR | SWS_PRINT_INFO, nullptr, nullptr, nullptr);
+#else
+  if (_video_ctx->pix_fmt != _pixel_format) {
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(_video_ctx->pix_fmt);
+    ffmpeg_cat.error()
+      << "Video with pixel format " << (desc ? desc->name : "?")
+      << " needs conversion, but libswscale support is not enabled.\n";
+    cleanup();
+    return;
+  }
 #endif  // HAVE_SWSCALE
 
 #ifdef HAVE_THREADS
@@ -1164,24 +1173,29 @@ export_frame(FfmpegBuffer *buffer) {
   buffer->_begin_frame = _begin_frame;
   buffer->_end_frame = _end_frame;
 
+#ifdef HAVE_SWSCALE
+  nassertv(_convert_ctx != nullptr && _frame != nullptr);
   if (ffmpeg_global_lock) {
     ReMutexHolder av_holder(_av_lock);
-#ifdef HAVE_SWSCALE
-    nassertv(_convert_ctx != nullptr && _frame != nullptr && _frame_out != nullptr);
     sws_scale(_convert_ctx, _frame->data, _frame->linesize, 0, _size_y, _frame_out->data, _frame_out->linesize);
-#else
-    img_convert((AVPicture *)_frame_out, (AVPixelFormat)_pixel_format,
-                (AVPicture *)_frame, _video_ctx->pix_fmt, _size_x, _size_y);
-#endif
   } else {
-#ifdef HAVE_SWSCALE
-    nassertv(_convert_ctx != nullptr && _frame != nullptr && _frame_out != nullptr);
     sws_scale(_convert_ctx, _frame->data, _frame->linesize, 0, _size_y, _frame_out->data, _frame_out->linesize);
+  }
 #else
-    img_convert((AVPicture *)_frame_out, (AVPixelFormat)_pixel_format,
-                (AVPicture *)_frame, _video_ctx->pix_fmt, _size_x, _size_y);
-#endif
+  nassertv(_frame != nullptr);
+  uint8_t const *src = _frame->data[0];
+  uint8_t *dst = _frame_out->data[0];
+  int src_stride = _frame->linesize[0];
+  int dst_stride = _frame_out->linesize[0];
+  size_t copy_size = _size_x * _num_components;
+  nassertv(copy_size <= (size_t)std::abs(src_stride));
+
+  for (int y = 0; y < _size_y; ++y) {
+    memcpy(dst, src, copy_size);
+    src += src_stride;
+    dst += dst_stride;
   }
+#endif
 }
 
 /**