Fix 1 crash on low memory.
authorCarl Hetherington <cth@carlh.net>
Sun, 9 Feb 2014 22:21:31 +0000 (22:21 +0000)
committerCarl Hetherington <cth@carlh.net>
Sun, 9 Feb 2014 22:21:31 +0000 (22:21 +0000)
ChangeLog
src/lib/ffmpeg.cc
src/lib/image.cc
src/lib/util.cc
src/lib/util.h
src/wx/film_viewer.cc

index 1febaac514450f3988f0cee99029e1c542611139..4f0bce552e6ae8ce9c160d94a286c0bb4a5967bb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,7 @@
 2014-02-09  Carl Hetherington  <cth@carlh.net>
 
+       * Some small bits of increased low-memory stability.
+
        * Version 1.64.7 released.
 
 2014-02-08  Carl Hetherington  <cth@carlh.net>
index b7ae04b069017d8404325939fdbbad8ba4108f26..fae9baa2b9da70cef4086e424fd34261472de473 100644 (file)
@@ -26,6 +26,7 @@ extern "C" {
 #include "ffmpeg.h"
 #include "ffmpeg_content.h"
 #include "exceptions.h"
+#include "util.h"
 
 #include "i18n.h"
 
@@ -85,7 +86,7 @@ FFmpeg::setup_general ()
        av_register_all ();
 
        _file_group.set_paths (_ffmpeg_content->paths ());
-       _avio_buffer = static_cast<uint8_t*> (av_malloc (_avio_buffer_size));
+       _avio_buffer = static_cast<uint8_t*> (wrapped_av_malloc (_avio_buffer_size));
        _avio_context = avio_alloc_context (_avio_buffer, _avio_buffer_size, 0, this, avio_read_wrapper, 0, avio_seek_wrapper);
        _format_context = avformat_alloc_context ();
        _format_context->pb = _avio_context;
index 95bf2b04d171085615e786418600d23d858f2909..4722563c45d532f397bb5231adf3ffdc548c4835 100644 (file)
@@ -498,13 +498,13 @@ Image::Image (AVPixelFormat p, libdcp::Size s, bool aligned)
 void
 Image::allocate ()
 {
-       _data = (uint8_t **) av_malloc (4 * sizeof (uint8_t *));
+       _data = (uint8_t **) wrapped_av_malloc (4 * sizeof (uint8_t *));
        _data[0] = _data[1] = _data[2] = _data[3] = 0;
        
-       _line_size = (int *) av_malloc (4 * sizeof (int));
+       _line_size = (int *) wrapped_av_malloc (4 * sizeof (int));
        _line_size[0] = _line_size[1] = _line_size[2] = _line_size[3] = 0;
        
-       _stride = (int *) av_malloc (4 * sizeof (int));
+       _stride = (int *) wrapped_av_malloc (4 * sizeof (int));
        _stride[0] = _stride[1] = _stride[2] = _stride[3] = 0;
 
        for (int i = 0; i < components(); ++i) {
@@ -520,7 +520,7 @@ Image::allocate ()
                   seem to mind.  The nasty + 1 in this malloc makes sure there is always a byte
                   for that instruction to read safely.
                */
-               _data[i] = (uint8_t *) av_malloc (_stride[i] * lines (i) + 1);
+               _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * lines (i) + 1);
        }
 }
 
index edb202df260ea0f6dd333a8a455e627deeb07d22..190bb42b19ab01ec7fe5dc4ca291a1e4d16b6c37 100644 (file)
@@ -27,6 +27,7 @@
 #include <iostream>
 #include <fstream>
 #include <climits>
+#include <stdexcept>
 #ifdef DCPOMATIC_POSIX
 #include <execinfo.h>
 #include <cxxabi.h>
@@ -92,6 +93,7 @@ using std::istream;
 using std::numeric_limits;
 using std::pair;
 using std::cout;
+using std::bad_alloc;
 using std::streampos;
 using boost::shared_ptr;
 using boost::thread;
@@ -916,3 +918,14 @@ fit_ratio_within (float ratio, libdcp::Size full_frame)
        
        return libdcp::Size (full_frame.width, rint (full_frame.width / ratio));
 }
+
+void *
+wrapped_av_malloc (size_t s)
+{
+       void* p = av_malloc (s);
+       if (!p) {
+               throw bad_alloc ();
+       }
+       return p;
+}
+               
index 7dcd920b7cac3d72974332eda264466faf0cc42a..a229bbfc9df05ff0aab8a74ef00df6ac55183311 100644 (file)
@@ -120,6 +120,7 @@ extern float get_required_float (std::multimap<std::string, std::string> const &
 extern std::string get_required_string (std::multimap<std::string, std::string> const & kv, std::string k);
 extern int get_optional_int (std::multimap<std::string, std::string> const & kv, std::string k);
 extern std::string get_optional_string (std::multimap<std::string, std::string> const & kv, std::string k);
+extern void* wrapped_av_malloc (size_t);
 
 /** @class Socket
  *  @brief A class to wrap a boost::asio::ip::tcp::socket with some things
index fbca835c2bc2126513b9eb1b0eb49efce3fa1e29..e24583d6cfa478ea62a6aefa7740d2fa1c022db2 100644 (file)
@@ -45,6 +45,7 @@ using std::min;
 using std::max;
 using std::cout;
 using std::list;
+using std::bad_alloc;
 using std::make_pair;
 using boost::shared_ptr;
 using boost::dynamic_pointer_cast;
@@ -126,7 +127,14 @@ FilmViewer::set_film (shared_ptr<Film> f)
                return;
        }
 
-       _player = f->make_player ();
+       try {
+               _player = f->make_player ();
+       } catch (bad_alloc) {
+               error_dialog (this, _("There is not enough free memory to do that."));
+               _film.reset ();
+               return;
+       }
+       
        _player->disable_audio ();
        _player->Video.connect (boost::bind (&FilmViewer::process_video, this, _1, _2, _5));
        _player->Changed.connect (boost::bind (&FilmViewer::player_changed, this, _1));