From 4a4ba8509f62a325d1074ec488b97b00922c6fc5 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 8 Jul 2014 10:03:58 +0100 Subject: Conversion of frame index to FFmpeg time must always use the original or detected FFmpeg video frame rate. --- src/lib/ffmpeg_decoder.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/lib/ffmpeg_decoder.cc') diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 07f988e2b..f2d434e3b 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -334,7 +334,7 @@ FFmpegDecoder::seek (VideoContent::Frame frame, bool accurate) } /* Initial seek time in the stream's timebase */ - int64_t const initial_vt = ((initial / _ffmpeg_content->video_frame_rate()) - _pts_offset) / time_base; + int64_t const initial_vt = ((initial / _ffmpeg_content->original_video_frame_rate()) - _pts_offset) / time_base; av_seek_frame (_format_context, _video_stream, initial_vt, AVSEEK_FLAG_BACKWARD); @@ -375,7 +375,7 @@ FFmpegDecoder::seek (VideoContent::Frame frame, bool accurate) r = avcodec_decode_video2 (video_codec_context(), _frame, &finished, &_packet); if (r >= 0 && finished) { _video_position = rint ( - (av_frame_get_best_effort_timestamp (_frame) * time_base + _pts_offset) * _ffmpeg_content->video_frame_rate() + (av_frame_get_best_effort_timestamp (_frame) * time_base + _pts_offset) * _ffmpeg_content->original_video_frame_rate() ); if (_video_position >= (frame - 1)) { @@ -495,12 +495,12 @@ FFmpegDecoder::decode_video_packet () /* We just did a seek, so disable any attempts to correct for where we are / should be. */ - _video_position = rint (pts * _ffmpeg_content->video_frame_rate ()); + _video_position = rint (pts * _ffmpeg_content->original_video_frame_rate ()); _just_sought = false; } - double const next = _video_position / _ffmpeg_content->video_frame_rate(); - double const one_frame = 1 / _ffmpeg_content->video_frame_rate (); + double const next = _video_position / _ffmpeg_content->original_video_frame_rate(); + double const one_frame = 1 / _ffmpeg_content->original_video_frame_rate (); double delta = pts - next; while (delta > one_frame) { -- cgit v1.2.3 From 4388fff5376a6e5a6dc8d33e244a1245a728335c Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sat, 9 Aug 2014 13:43:09 +0100 Subject: Properly remove JSON server; remove some unused usings; remove some unnecessary uses of stringstream. --- src/lib/audio_decoder.cc | 1 - src/lib/colour_conversion.cc | 1 - src/lib/encoder.cc | 1 - src/lib/ffmpeg.cc | 1 - src/lib/ffmpeg_decoder.cc | 1 - src/lib/image.cc | 1 - src/lib/image_proxy.cc | 1 - src/lib/playlist.cc | 1 - src/lib/ratio.cc | 1 - src/lib/scp_dcp_job.cc | 8 +++----- src/lib/writer.cc | 1 - src/tools/dcpomatic.cc | 7 +++---- src/tools/dcpomatic_cli.cc | 16 +--------------- src/wx/dolby_certificate_dialog.cc | 1 - test/film_metadata_test.cc | 1 - 15 files changed, 7 insertions(+), 36 deletions(-) (limited to 'src/lib/ffmpeg_decoder.cc') diff --git a/src/lib/audio_decoder.cc b/src/lib/audio_decoder.cc index c0ef02f65..18f4b890d 100644 --- a/src/lib/audio_decoder.cc +++ b/src/lib/audio_decoder.cc @@ -25,7 +25,6 @@ #include "i18n.h" -using std::stringstream; using std::list; using std::pair; using std::cout; diff --git a/src/lib/colour_conversion.cc b/src/lib/colour_conversion.cc index f8675900e..e5b1104ff 100644 --- a/src/lib/colour_conversion.cc +++ b/src/lib/colour_conversion.cc @@ -30,7 +30,6 @@ using std::list; using std::string; -using std::stringstream; using std::cout; using std::vector; using boost::shared_ptr; diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc index 02a271029..693fd587e 100644 --- a/src/lib/encoder.cc +++ b/src/lib/encoder.cc @@ -45,7 +45,6 @@ using std::pair; using std::string; -using std::stringstream; using std::vector; using std::list; using std::cout; diff --git a/src/lib/ffmpeg.cc b/src/lib/ffmpeg.cc index 7ecc811be..ebe62b51f 100644 --- a/src/lib/ffmpeg.cc +++ b/src/lib/ffmpeg.cc @@ -32,7 +32,6 @@ extern "C" { using std::string; using std::cout; -using std::stringstream; using boost::shared_ptr; using libdcp::raw_convert; diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index f2d434e3b..9ecc503dc 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -53,7 +53,6 @@ extern "C" { using std::cout; using std::string; using std::vector; -using std::stringstream; using std::list; using std::min; using std::pair; diff --git a/src/lib/image.cc b/src/lib/image.cc index f340637dc..066f12c07 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -38,7 +38,6 @@ using std::string; using std::min; using std::cout; using std::cerr; -using std::stringstream; using boost::shared_ptr; using libdcp::Size; diff --git a/src/lib/image_proxy.cc b/src/lib/image_proxy.cc index ba572c727..7c212be04 100644 --- a/src/lib/image_proxy.cc +++ b/src/lib/image_proxy.cc @@ -32,7 +32,6 @@ using std::cout; using std::string; -using std::stringstream; using boost::shared_ptr; ImageProxy::ImageProxy (shared_ptr log) diff --git a/src/lib/playlist.cc b/src/lib/playlist.cc index 8b874aae6..c3e430082 100644 --- a/src/lib/playlist.cc +++ b/src/lib/playlist.cc @@ -40,7 +40,6 @@ using std::vector; using std::min; using std::max; using std::string; -using std::stringstream; using std::pair; using boost::optional; using boost::shared_ptr; diff --git a/src/lib/ratio.cc b/src/lib/ratio.cc index 52577d3bb..4a5b39a22 100644 --- a/src/lib/ratio.cc +++ b/src/lib/ratio.cc @@ -24,7 +24,6 @@ #include "i18n.h" using std::string; -using std::stringstream; using std::vector; vector Ratio::_ratios; diff --git a/src/lib/scp_dcp_job.cc b/src/lib/scp_dcp_job.cc index 637840813..5aade6382 100644 --- a/src/lib/scp_dcp_job.cc +++ b/src/lib/scp_dcp_job.cc @@ -40,7 +40,6 @@ #define LOG_GENERAL_NC(...) _film->log()->log (__VA_ARGS__, Log::TYPE_GENERAL); using std::string; -using std::stringstream; using std::min; using boost::shared_ptr; @@ -217,12 +216,11 @@ string SCPDCPJob::status () const { boost::mutex::scoped_lock lm (_status_mutex); - stringstream s; - s << Job::status (); + string s = Job::status (); if (!_status.empty ()) { - s << N_("; ") << _status; + s += N_("; ") + _status; } - return s.str (); + return s; } void diff --git a/src/lib/writer.cc b/src/lib/writer.cc index 66ddb58f7..e8d4f90a6 100644 --- a/src/lib/writer.cc +++ b/src/lib/writer.cc @@ -53,7 +53,6 @@ using std::pair; using std::string; using std::list; using std::cout; -using std::stringstream; using boost::shared_ptr; using boost::weak_ptr; diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc index aeb62a44e..cd2978052 100644 --- a/src/tools/dcpomatic.cc +++ b/src/tools/dcpomatic.cc @@ -337,13 +337,12 @@ private: void file_changed (boost::filesystem::path f) { - stringstream s; - s << wx_to_std (_("DCP-o-matic")); + string s = wx_to_std (_("DCP-o-matic")); if (!f.empty ()) { - s << " - " << f.string (); + s += " - " + f.string (); } - SetTitle (std_to_wx (s.str())); + SetTitle (std_to_wx (s)); } void file_new () diff --git a/src/tools/dcpomatic_cli.cc b/src/tools/dcpomatic_cli.cc index ff948e9fb..5cb05e11d 100644 --- a/src/tools/dcpomatic_cli.cc +++ b/src/tools/dcpomatic_cli.cc @@ -33,7 +33,6 @@ #include "lib/log.h" #include "lib/ui_signaller.h" #include "lib/server_finder.h" -#include "lib/json_server.h" using std::string; using std::cerr; @@ -53,7 +52,6 @@ help (string n) << " -f, --flags show flags passed to C++ compiler on build\n" << " -n, --no-progress do not print progress to stdout\n" << " -r, --no-remote do not use any remote servers\n" - << " -j, --json run a JSON server on the specified port\n" << " -k, --keep-going keep running even when the job is complete\n" << "\n" << " is the film directory.\n"; @@ -65,7 +63,6 @@ main (int argc, char* argv[]) string film_dir; bool progress = true; bool no_remote = false; - int json_port = 0; bool keep_going = false; int option_index = 0; @@ -77,12 +74,11 @@ main (int argc, char* argv[]) { "flags", no_argument, 0, 'f'}, { "no-progress", no_argument, 0, 'n'}, { "no-remote", no_argument, 0, 'r'}, - { "json", required_argument, 0, 'j' }, { "keep-going", no_argument, 0, 'k' }, { 0, 0, 0, 0 } }; - int c = getopt_long (argc, argv, "vhdfnrj:k", long_options, &option_index); + int c = getopt_long (argc, argv, "vhdfnrk", long_options, &option_index); if (c == -1) { break; @@ -107,9 +103,6 @@ main (int argc, char* argv[]) case 'r': no_remote = true; break; - case 'j': - json_port = atoi (optarg); - break; case 'k': keep_going = true; break; @@ -130,10 +123,6 @@ main (int argc, char* argv[]) ServerFinder::instance()->disable (); } - if (json_port) { - new JSONServer (json_port); - } - cout << "DCP-o-matic " << dcpomatic_version << " git " << dcpomatic_git_commit; char buf[256]; if (gethostname (buf, 256) == 0) { @@ -151,9 +140,6 @@ main (int argc, char* argv[]) } cout << "\nMaking DCP for " << film->name() << "\n"; -// cout << "Content: " << film->content() << "\n"; -// pair const f = Filter::ffmpeg_strings (film->filters ()); -// cout << "Filters: " << f.first << " " << f.second << "\n"; film->make_dcp (); diff --git a/src/wx/dolby_certificate_dialog.cc b/src/wx/dolby_certificate_dialog.cc index e5bb18962..a05a3bbc7 100644 --- a/src/wx/dolby_certificate_dialog.cc +++ b/src/wx/dolby_certificate_dialog.cc @@ -27,7 +27,6 @@ using std::list; using std::string; using std::vector; -using std::stringstream; using std::cout; using boost::optional; using boost::algorithm::split; diff --git a/test/film_metadata_test.cc b/test/film_metadata_test.cc index 7440e4338..c41e86189 100644 --- a/test/film_metadata_test.cc +++ b/test/film_metadata_test.cc @@ -27,7 +27,6 @@ #include "test.h" using std::string; -using std::stringstream; using std::list; using boost::shared_ptr; -- cgit v1.2.3 From 9a2b45caa81d8fb056802dfe3c25f214e808ffdf Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 19 Aug 2014 21:01:28 +0100 Subject: Use SafeStringStream instead of std::stringstream to try to fix random crashes on OS X. --- ChangeLog | 6 ++ src/lib/analyse_audio_job.cc | 2 +- src/lib/compose.hpp | 4 +- src/lib/config.cc | 1 - src/lib/content.cc | 4 +- src/lib/dcp_video_frame.cc | 9 +-- src/lib/ffmpeg_content.cc | 6 +- src/lib/ffmpeg_decoder.cc | 1 - src/lib/ffmpeg_examiner.cc | 8 +-- src/lib/film.cc | 11 ++-- src/lib/filter_graph.cc | 4 +- src/lib/image_content.cc | 4 +- src/lib/internet.cc | 7 +-- src/lib/job.cc | 4 +- src/lib/kdm.cc | 8 +-- src/lib/log.cc | 5 +- src/lib/md5_digester.cc | 5 +- src/lib/safe_stringstream.cc | 23 ++++++++ src/lib/safe_stringstream.h | 115 +++++++++++++++++++++++++++++++++++++ src/lib/server.cc | 16 +++--- src/lib/server_finder.cc | 5 +- src/lib/sndfile_content.cc | 4 +- src/lib/stack.cpp | 1 - src/lib/transcode_job.cc | 4 +- src/lib/update.cc | 8 +-- src/lib/util.cc | 11 ++-- src/lib/video_content.cc | 8 +-- src/lib/wscript | 1 + src/tools/dcpomatic.cc | 1 - src/tools/dcpomatic_kdm.cc | 4 +- src/tools/dcpomatic_server_cli.cc | 1 - src/wx/colour_conversion_editor.cc | 4 +- src/wx/film_editor.cc | 4 +- src/wx/job_wrapper.cc | 1 - src/wx/properties_dialog.cc | 6 +- test/film_metadata_test.cc | 1 - 36 files changed, 217 insertions(+), 90 deletions(-) create mode 100644 src/lib/safe_stringstream.cc create mode 100644 src/lib/safe_stringstream.h (limited to 'src/lib/ffmpeg_decoder.cc') diff --git a/ChangeLog b/ChangeLog index 04778b35f..1f93e2f98 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2014-08-19 Carl Hetherington + + * Attempt to fix random crashes on OS X (especially during encodes) + thought to be caused by multiple threads using (different) stringstreams + at the same time; see src/lib/safe_stringstream.h + 2014-08-09 Carl Hetherington * Version 1.72.10 released. diff --git a/src/lib/analyse_audio_job.cc b/src/lib/analyse_audio_job.cc index 8186f9de4..ab985bdf7 100644 --- a/src/lib/analyse_audio_job.cc +++ b/src/lib/analyse_audio_job.cc @@ -87,7 +87,7 @@ AnalyseAudioJob::audio (shared_ptr b, Time) for (int j = 0; j < b->channels(); ++j) { float s = b->data(j)[i]; if (fabsf (s) < 10e-7) { - /* stringstream can't serialise and recover inf or -inf, so prevent such + /* SafeStringStream can't serialise and recover inf or -inf, so prevent such values by replacing with this (140dB down) */ s = 10e-7; } diff --git a/src/lib/compose.hpp b/src/lib/compose.hpp index b3f410c8e..aa67b5a1f 100644 --- a/src/lib/compose.hpp +++ b/src/lib/compose.hpp @@ -33,10 +33,10 @@ #ifndef STRING_COMPOSE_H #define STRING_COMPOSE_H -#include #include #include #include // for multimap +#include "safe_stringstream.h" namespace StringPrivate { @@ -56,7 +56,7 @@ namespace StringPrivate std::string str() const; private: - std::ostringstream os; + SafeStringStream os; int arg_no; // we store the output as a list - when the output string is requested, the diff --git a/src/lib/config.cc b/src/lib/config.cc index ee1b01386..d11bcf983 100644 --- a/src/lib/config.cc +++ b/src/lib/config.cc @@ -17,7 +17,6 @@ */ -#include #include #include #include diff --git a/src/lib/content.cc b/src/lib/content.cc index 7966219ff..11a4b21cc 100644 --- a/src/lib/content.cc +++ b/src/lib/content.cc @@ -27,11 +27,11 @@ #include "ui_signaller.h" #include "exceptions.h" #include "film.h" +#include "safe_stringstream.h" #include "i18n.h" using std::string; -using std::stringstream; using std::set; using std::list; using std::cout; @@ -230,7 +230,7 @@ Content::trimmed (Time t) const string Content::identifier () const { - stringstream s; + SafeStringStream s; s << Content::digest() << "_" << position() diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc index 09b909696..bb7eaa064 100644 --- a/src/lib/dcp_video_frame.cc +++ b/src/lib/dcp_video_frame.cc @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -67,7 +66,6 @@ #include "i18n.h" using std::string; -using std::stringstream; using std::cout; using boost::shared_ptr; using libdcp::Size; @@ -282,10 +280,9 @@ DCPVideoFrame::encode_remotely (ServerDescription serv) LOG_GENERAL (N_("Sending frame %1 to remote"), _index); /* Send XML metadata */ - stringstream xml; - doc.write_to_stream (xml, "UTF-8"); - socket->write (xml.str().length() + 1); - socket->write ((uint8_t *) xml.str().c_str(), xml.str().length() + 1); + string xml = doc.write_to_string ("UTF-8"); + socket->write (xml.length() + 1); + socket->write ((uint8_t *) xml.c_str(), xml.length() + 1); /* Send binary data */ _frame->send_binary (socket); diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc index 4d886a6dd..a4209f5b6 100644 --- a/src/lib/ffmpeg_content.cc +++ b/src/lib/ffmpeg_content.cc @@ -32,13 +32,13 @@ extern "C" { #include "log.h" #include "exceptions.h" #include "frame_rate_change.h" +#include "safe_stringstream.h" #include "i18n.h" #define LOG_GENERAL(...) film->log()->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL); using std::string; -using std::stringstream; using std::vector; using std::list; using std::cout; @@ -241,7 +241,7 @@ FFmpegContent::information () const return ""; } - stringstream s; + SafeStringStream s; s << String::compose (_("%1 frames; %2 frames per second"), video_length_after_3d_combine(), video_frame_rate()) << "\n"; s << VideoContent::information (); @@ -445,7 +445,7 @@ FFmpegContent::set_audio_mapping (AudioMapping m) string FFmpegContent::identifier () const { - stringstream s; + SafeStringStream s; s << VideoContent::identifier(); diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 9ecc503dc..d40b798ba 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -23,7 +23,6 @@ #include #include -#include #include #include #include diff --git a/src/lib/ffmpeg_examiner.cc b/src/lib/ffmpeg_examiner.cc index bc82a9700..5fb20ef2c 100644 --- a/src/lib/ffmpeg_examiner.cc +++ b/src/lib/ffmpeg_examiner.cc @@ -23,13 +23,13 @@ extern "C" { } #include "ffmpeg_examiner.h" #include "ffmpeg_content.h" +#include "safe_stringstream.h" #include "i18n.h" using std::string; using std::cout; using std::max; -using std::stringstream; using boost::shared_ptr; using boost::optional; @@ -144,7 +144,7 @@ FFmpegExaminer::video_length () const string FFmpegExaminer::audio_stream_name (AVStream* s) const { - stringstream n; + SafeStringStream n; n << stream_name (s); @@ -160,7 +160,7 @@ FFmpegExaminer::audio_stream_name (AVStream* s) const string FFmpegExaminer::subtitle_stream_name (AVStream* s) const { - stringstream n; + SafeStringStream n; n << stream_name (s); @@ -174,7 +174,7 @@ FFmpegExaminer::subtitle_stream_name (AVStream* s) const string FFmpegExaminer::stream_name (AVStream* s) const { - stringstream n; + SafeStringStream n; if (s->metadata) { AVDictionaryEntry const * lang = av_dict_get (s->metadata, "language", 0, 0); diff --git a/src/lib/film.cc b/src/lib/film.cc index 0a77caf50..2701d81b8 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -55,11 +54,11 @@ #include "ratio.h" #include "cross.h" #include "cinema.h" +#include "safe_stringstream.h" #include "i18n.h" using std::string; -using std::stringstream; using std::multimap; using std::pair; using std::map; @@ -159,7 +158,7 @@ Film::video_identifier () const { assert (container ()); - stringstream s; + SafeStringStream s; s.imbue (std::locale::classic ()); s << container()->id() @@ -493,7 +492,7 @@ Film::file (boost::filesystem::path f) const string Film::isdcf_name (bool if_created_now) const { - stringstream d; + SafeStringStream d; string raw_name = name (); @@ -817,7 +816,7 @@ Film::info_path (int f, Eyes e) const boost::filesystem::path p; p /= info_dir (); - stringstream s; + SafeStringStream s; s.width (8); s << setfill('0') << f; @@ -844,7 +843,7 @@ Film::j2c_path (int f, Eyes e, bool t) const p /= "j2c"; p /= video_identifier (); - stringstream s; + SafeStringStream s; s.width (8); s << setfill('0') << f; diff --git a/src/lib/filter_graph.cc b/src/lib/filter_graph.cc index c11ee6331..0d72eacdf 100644 --- a/src/lib/filter_graph.cc +++ b/src/lib/filter_graph.cc @@ -34,10 +34,10 @@ extern "C" { #include "exceptions.h" #include "image.h" #include "ffmpeg_content.h" +#include "safe_stringstream.h" #include "i18n.h" -using std::stringstream; using std::string; using std::list; using std::pair; @@ -80,7 +80,7 @@ FilterGraph::FilterGraph (shared_ptr content, libdcp::Size throw DecodeError (N_("Could not create buffer sink filter")); } - stringstream a; + SafeStringStream a; a << "video_size=" << _size.width << "x" << _size.height << ":" << "pix_fmt=" << _pixel_format << ":" << "time_base=1/1:" diff --git a/src/lib/image_content.cc b/src/lib/image_content.cc index 6acf0bab9..915da7beb 100644 --- a/src/lib/image_content.cc +++ b/src/lib/image_content.cc @@ -25,12 +25,12 @@ #include "film.h" #include "job.h" #include "frame_rate_change.h" +#include "safe_stringstream.h" #include "i18n.h" using std::string; using std::cout; -using std::stringstream; using boost::shared_ptr; ImageContent::ImageContent (shared_ptr f, boost::filesystem::path p) @@ -138,7 +138,7 @@ ImageContent::full_length () const string ImageContent::identifier () const { - stringstream s; + SafeStringStream s; s << VideoContent::identifier (); s << "_" << video_length(); return s.str (); diff --git a/src/lib/internet.cc b/src/lib/internet.cc index 99ae5c214..c28e650fd 100644 --- a/src/lib/internet.cc +++ b/src/lib/internet.cc @@ -24,11 +24,11 @@ #include #include #include "util.h" +#include "safe_stringstream.h" #include "i18n.h" using std::string; -using std::stringstream; using std::list; using boost::optional; using boost::function; @@ -130,11 +130,10 @@ ftp_ls (string url) return list (); } - stringstream s (ls_raw); - string line; + SafeStringStream s (ls_raw); list ls; while (s.good ()) { - getline (s, line); + string const line = s.getline (); if (line.length() > 55) { string const file = line.substr (55); if (file != "." && file != "..") { diff --git a/src/lib/job.cc b/src/lib/job.cc index 530ad9798..52ec1426c 100644 --- a/src/lib/job.cc +++ b/src/lib/job.cc @@ -29,13 +29,13 @@ #include "cross.h" #include "ui_signaller.h" #include "exceptions.h" +#include "safe_stringstream.h" #include "i18n.h" using std::string; using std::list; using std::cout; -using std::stringstream; using boost::shared_ptr; Job::Job (shared_ptr f) @@ -306,7 +306,7 @@ Job::status () const pc = 99; } - stringstream s; + SafeStringStream s; if (!finished ()) { s << pc << N_("%"); if (p >= 0 && t > 10 && r > 0) { diff --git a/src/lib/kdm.cc b/src/lib/kdm.cc index 177dec078..f5054b8ed 100644 --- a/src/lib/kdm.cc +++ b/src/lib/kdm.cc @@ -28,10 +28,10 @@ #include "util.h" #include "film.h" #include "config.h" +#include "safe_stringstream.h" using std::list; using std::string; -using std::stringstream; using std::cout; using boost::shared_ptr; @@ -233,9 +233,9 @@ email_kdms ( quickmail_initialize (); - stringstream start; + SafeStringStream start; start << from.date() << " " << from.time_of_day(); - stringstream end; + SafeStringStream end; end << to.date() << " " << to.time_of_day(); string subject = Config::instance()->kdm_subject(); @@ -259,7 +259,7 @@ email_kdms ( boost::algorithm::replace_all (body, "$END_TIME", end.str ()); boost::algorithm::replace_all (body, "$CINEMA_NAME", i->cinema->name); - stringstream screens; + SafeStringStream screens; for (list::const_iterator j = i->screen_kdms.begin(); j != i->screen_kdms.end(); ++j) { screens << j->screen->name << ", "; } diff --git a/src/lib/log.cc b/src/lib/log.cc index 4de6bd874..5e8277a23 100644 --- a/src/lib/log.cc +++ b/src/lib/log.cc @@ -26,6 +26,7 @@ #include "log.h" #include "cross.h" #include "config.h" +#include "safe_stringstream.h" #include "i18n.h" @@ -63,7 +64,7 @@ Log::log (string message, int type) time (&t); string a = ctime (&t); - stringstream s; + SafeStringStream s; s << a.substr (0, a.length() - 1) << N_(": "); if (type & TYPE_ERROR) { @@ -90,7 +91,7 @@ Log::microsecond_log (string m, int t) struct timeval tv; gettimeofday (&tv, 0); - stringstream s; + SafeStringStream s; s << tv.tv_sec << N_(":") << tv.tv_usec << N_(" ") << m; do_log (s.str ()); } diff --git a/src/lib/md5_digester.cc b/src/lib/md5_digester.cc index 1244209bd..1d4d1974a 100644 --- a/src/lib/md5_digester.cc +++ b/src/lib/md5_digester.cc @@ -18,12 +18,11 @@ */ #include -#include #include #include "md5_digester.h" +#include "safe_stringstream.h" using std::string; -using std::stringstream; using std::hex; using std::setfill; using std::setw; @@ -51,7 +50,7 @@ MD5Digester::get () const unsigned char digest[MD5_DIGEST_LENGTH]; MD5_Final (digest, &_context); - stringstream s; + SafeStringStream s; for (int i = 0; i < MD5_DIGEST_LENGTH; ++i) { s << hex << setfill('0') << setw(2) << ((int) digest[i]); } diff --git a/src/lib/safe_stringstream.cc b/src/lib/safe_stringstream.cc new file mode 100644 index 000000000..01d545045 --- /dev/null +++ b/src/lib/safe_stringstream.cc @@ -0,0 +1,23 @@ +/* + Copyright (C) 2014 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include "safe_stringstream.h" + +boost::mutex SafeStringStream::_mutex; diff --git a/src/lib/safe_stringstream.h b/src/lib/safe_stringstream.h new file mode 100644 index 000000000..e455de964 --- /dev/null +++ b/src/lib/safe_stringstream.h @@ -0,0 +1,115 @@ +/* + Copyright (C) 2014 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef DCPOMATIC_SAFE_STRINGSTREAM_H +#define DCPOMATIC_SAFE_STRINGSTREAM_H + +#include + +/* I've not been able to reproduce it, but there have been reports that DCP-o-matic crashes + * on OS X with two simultaneous backtraces that look like this: + * + * 0 libSystem.B.dylib 0x00007fff84ebe264 __numeric_load_locale + 125 + * 1 libSystem.B.dylib 0x00007fff84e2aac4 loadlocale + 323 + * 2 libstdc++.6.dylib 0x00007fff8976ba69 std::__convert_from_v(int* const&, char*, int, char const*, ...) + 199 + * 3 libstdc++.6.dylib 0x00007fff8974e99b std::ostreambuf_iterator > std::num_put > >::_M_insert_float(std::ostreambuf_iterator >, std::ios_base&, char, char, double) const + 199 + * 4 libstdc++.6.dylib 0x00007fff8974ebc0 std::num_put > +>::do_put(std::ostreambuf_iterator >, std::ios_base&, char, double) const + 28 + * 5 libstdc++.6.dylib 0x00007fff897566a2 std::ostream& std::ostream::_M_insert(double) + 178 + * 6 libdcpomatic.dylib 0x0000000100331e21 StringPrivate::Composition& StringPrivate::Composition::arg(float const&) + 33 + * + * in two different threads. I'm assuming that for some bizarre reason it is unsafe to use two separate stringstream + * objects in different threads on OS X. This is a hack to work around it. + */ + +class SafeStringStream +{ +public: + SafeStringStream () + {} + + SafeStringStream (std::string s) + : _stream (s) + {} + + template + std::ostream& operator<< (T val) + { + boost::mutex::scoped_lock lm (_mutex); + _stream << val; + return _stream; + } + + template + std::istream& operator>> (T& val) + { + boost::mutex::scoped_lock lm (_mutex); + _stream >> val; + return _stream; + } + + std::string str () const { + return _stream.str (); + } + + void str (std::string const & s) { + _stream.str (s); + } + + void imbue (std::locale const & loc) + { + boost::mutex::scoped_lock lm (_mutex); + _stream.imbue (loc); + } + + void width (int w) + { + _stream.width (w); + } + + void precision (int p) + { + _stream.precision (p); + } + + bool good () const + { + return _stream.good (); + } + + std::string getline () + { + boost::mutex::scoped_lock lm (_mutex); + std::string s; + std::getline (_stream, s); + return s; + } + + void setf (std::ios_base::fmtflags flags, std::ios_base::fmtflags mask) + { + _stream.setf (flags, mask); + } + +private: + static boost::mutex _mutex; + std::stringstream _stream; +}; + +#endif diff --git a/src/lib/server.cc b/src/lib/server.cc index f1c6d6c44..9591be188 100644 --- a/src/lib/server.cc +++ b/src/lib/server.cc @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -38,6 +37,7 @@ #include "config.h" #include "cross.h" #include "player_video_frame.h" +#include "safe_stringstream.h" #include "i18n.h" @@ -47,7 +47,6 @@ #define LOG_ERROR_NC(...) _log->log (__VA_ARGS__, Log::TYPE_ERROR); using std::string; -using std::stringstream; using std::multimap; using std::vector; using std::list; @@ -82,9 +81,9 @@ Server::process (shared_ptr socket, struct timeval& after_read, struct t scoped_array buffer (new char[length]); socket->read (reinterpret_cast (buffer.get()), length); - stringstream s (buffer.get()); + string s (buffer.get()); shared_ptr xml (new cxml::Document ("EncodingRequest")); - xml->read_stream (s); + xml->read_string (s); if (xml->number_child ("Version") != SERVER_LINK_VERSION) { cerr << "Mismatched server/client versions\n"; LOG_ERROR_NC ("Mismatched server/client versions"); @@ -154,7 +153,7 @@ Server::worker_thread () struct timeval end; gettimeofday (&end, 0); - stringstream message; + SafeStringStream message; message.precision (2); message << fixed << "Encoded frame " << frame << " from " << ip << ": " @@ -246,14 +245,13 @@ Server::broadcast_received () xmlpp::Document doc; xmlpp::Element* root = doc.create_root_node ("ServerAvailable"); root->add_child("Threads")->add_child_text (raw_convert (_worker_threads.size ())); - stringstream xml; - doc.write_to_stream (xml, "UTF-8"); + string xml = doc.write_to_string ("UTF-8"); shared_ptr socket (new Socket); try { socket->connect (boost::asio::ip::tcp::endpoint (_broadcast.send_endpoint.address(), Config::instance()->server_port_base() + 1)); - socket->write (xml.str().length() + 1); - socket->write ((uint8_t *) xml.str().c_str(), xml.str().length() + 1); + socket->write (xml.length() + 1); + socket->write ((uint8_t *) xml.c_str(), xml.length() + 1); } catch (...) { } diff --git a/src/lib/server_finder.cc b/src/lib/server_finder.cc index 65e0940a0..744a65f59 100644 --- a/src/lib/server_finder.cc +++ b/src/lib/server_finder.cc @@ -27,7 +27,6 @@ #include "ui_signaller.h" using std::string; -using std::stringstream; using std::list; using std::vector; using std::cout; @@ -116,9 +115,9 @@ try scoped_array buffer (new char[length]); sock->read (reinterpret_cast (buffer.get()), length); - stringstream s (buffer.get()); + string s (buffer.get()); shared_ptr xml (new cxml::Document ("ServerAvailable")); - xml->read_stream (s); + xml->read_string (s); string const ip = sock->socket().remote_endpoint().address().to_string (); if (!server_found (ip)) { diff --git a/src/lib/sndfile_content.cc b/src/lib/sndfile_content.cc index 3efba6fd5..ba3bd0a77 100644 --- a/src/lib/sndfile_content.cc +++ b/src/lib/sndfile_content.cc @@ -25,11 +25,11 @@ #include "compose.hpp" #include "job.h" #include "util.h" +#include "safe_stringstream.h" #include "i18n.h" using std::string; -using std::stringstream; using std::cout; using boost::shared_ptr; using libdcp::raw_convert; @@ -76,7 +76,7 @@ SndfileContent::information () const return ""; } - stringstream s; + SafeStringStream s; s << String::compose ( _("%1 channels, %2kHz, %3 samples"), diff --git a/src/lib/stack.cpp b/src/lib/stack.cpp index a8183d344..167524017 100644 --- a/src/lib/stack.cpp +++ b/src/lib/stack.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include "stack.hpp" diff --git a/src/lib/transcode_job.cc b/src/lib/transcode_job.cc index 675a95116..831c74b3b 100644 --- a/src/lib/transcode_job.cc +++ b/src/lib/transcode_job.cc @@ -27,6 +27,7 @@ #include "film.h" #include "transcoder.h" #include "log.h" +#include "safe_stringstream.h" #include "i18n.h" @@ -34,7 +35,6 @@ #define LOG_ERROR_NC(...) _film->log()->log (__VA_ARGS__, Log::TYPE_ERROR); using std::string; -using std::stringstream; using std::fixed; using std::setprecision; using boost::shared_ptr; @@ -89,7 +89,7 @@ TranscodeJob::status () const return Job::status (); } - stringstream s; + SafeStringStream s; s << Job::status (); diff --git a/src/lib/update.cc b/src/lib/update.cc index af3e46f0e..7bec061e9 100644 --- a/src/lib/update.cc +++ b/src/lib/update.cc @@ -18,7 +18,6 @@ */ #include -#include #include #include #include @@ -26,13 +25,13 @@ #include "update.h" #include "version.h" #include "ui_signaller.h" +#include "safe_stringstream.h" #define BUFFER_SIZE 1024 using std::cout; using std::min; using std::string; -using std::stringstream; using libdcp::raw_convert; UpdateChecker* UpdateChecker::_instance = 0; @@ -103,10 +102,9 @@ UpdateChecker::thread () } _buffer[_offset] = '\0'; - stringstream s; - s << _buffer; + string s (_buffer); cxml::Document doc ("Update"); - doc.read_stream (s); + doc.read_string (s); { boost::mutex::scoped_lock lm (_data_mutex); diff --git a/src/lib/util.cc b/src/lib/util.cc index 6f3907391..d96001d13 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -22,7 +22,6 @@ * @brief Some utility functions and classes. */ -#include #include #include #include @@ -70,6 +69,7 @@ extern "C" { #include "cross.h" #include "video_content.h" #include "md5_digester.h" +#include "safe_stringstream.h" #ifdef DCPOMATIC_WINDOWS #include "stack.hpp" #endif @@ -77,7 +77,6 @@ extern "C" { #include "i18n.h" using std::string; -using std::stringstream; using std::setfill; using std::ostream; using std::endl; @@ -121,7 +120,7 @@ seconds_to_hms (int s) int h = m / 60; m -= (h * 60); - stringstream hms; + SafeStringStream hms; hms << h << N_(":"); hms.width (2); hms << std::setfill ('0') << m << N_(":"); @@ -142,7 +141,7 @@ seconds_to_approximate_hms (int s) int h = m / 60; m -= (h * 60); - stringstream ap; + SafeStringStream ap; bool const hours = h > 0; bool const minutes = h < 10 && m > 0; @@ -261,7 +260,7 @@ stacktrace (ostream& out, int levels) static string ffmpeg_version_to_string (int v) { - stringstream s; + SafeStringStream s; s << ((v & 0xff0000) >> 16) << N_(".") << ((v & 0xff00) >> 8) << N_(".") << (v & 0xff); return s.str (); } @@ -270,7 +269,7 @@ ffmpeg_version_to_string (int v) string dependency_version_summary () { - stringstream s; + SafeStringStream s; s << N_("libopenjpeg ") << opj_version () << N_(", ") << N_("libavcodec ") << ffmpeg_version_to_string (avcodec_version()) << N_(", ") << N_("libavfilter ") << ffmpeg_version_to_string (avfilter_version()) << N_(", ") diff --git a/src/lib/video_content.cc b/src/lib/video_content.cc index 15e1ca791..b0d4c2de5 100644 --- a/src/lib/video_content.cc +++ b/src/lib/video_content.cc @@ -31,6 +31,7 @@ #include "film.h" #include "exceptions.h" #include "frame_rate_change.h" +#include "safe_stringstream.h" #include "i18n.h" @@ -42,7 +43,6 @@ int const VideoContentProperty::VIDEO_SCALE = 4; int const VideoContentProperty::COLOUR_CONVERSION = 5; using std::string; -using std::stringstream; using std::setprecision; using std::cout; using std::vector; @@ -207,7 +207,7 @@ VideoContent::information () const return ""; } - stringstream s; + SafeStringStream s; s << String::compose ( _("%1x%2 pixels (%3:1)"), @@ -299,7 +299,7 @@ VideoContent::set_scale (VideoContentScale s) string VideoContent::identifier () const { - stringstream s; + SafeStringStream s; s << Content::identifier() << "_" << crop().left << "_" << crop().right @@ -473,7 +473,7 @@ VideoContentScale::as_xml (xmlpp::Node* node) const string VideoContentScale::id () const { - stringstream s; + SafeStringStream s; if (_ratio) { s << _ratio->id () << "_"; diff --git a/src/lib/wscript b/src/lib/wscript index f53ae7b74..1e4efddc4 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -48,6 +48,7 @@ sources = """ playlist.cc ratio.cc resampler.cc + safe_stringstream.cc scp_dcp_job.cc scaler.cc send_kdm_email_job.cc diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc index cd2978052..c92f5b6cf 100644 --- a/src/tools/dcpomatic.cc +++ b/src/tools/dcpomatic.cc @@ -64,7 +64,6 @@ using std::cout; using std::string; using std::wstring; -using std::stringstream; using std::map; using std::make_pair; using std::list; diff --git a/src/tools/dcpomatic_kdm.cc b/src/tools/dcpomatic_kdm.cc index 092a1ca1b..758060a08 100644 --- a/src/tools/dcpomatic_kdm.cc +++ b/src/tools/dcpomatic_kdm.cc @@ -24,9 +24,9 @@ #include "lib/kdm.h" #include "lib/config.h" #include "lib/exceptions.h" +#include "lib/safe_stringstream.h" using std::string; -using std::stringstream; using std::cout; using std::cerr; using std::list; @@ -76,7 +76,7 @@ time_from_string (string t) static boost::posix_time::time_duration duration_from_string (string d) { - stringstream s (d); + SafeStringStream s (d); int N; string unit; s >> N >> unit; diff --git a/src/tools/dcpomatic_server_cli.cc b/src/tools/dcpomatic_server_cli.cc index e4ac85f4c..f35797954 100644 --- a/src/tools/dcpomatic_server_cli.cc +++ b/src/tools/dcpomatic_server_cli.cc @@ -20,7 +20,6 @@ #include "lib/server.h" #include #include -#include #include #include #include diff --git a/src/wx/colour_conversion_editor.cc b/src/wx/colour_conversion_editor.cc index 6617b66d6..4a1e5074f 100644 --- a/src/wx/colour_conversion_editor.cc +++ b/src/wx/colour_conversion_editor.cc @@ -21,12 +21,12 @@ #include #include #include "lib/colour_conversion.h" +#include "lib/safe_stringstream.h" #include "wx_util.h" #include "colour_conversion_editor.h" using std::string; using std::cout; -using std::stringstream; using boost::shared_ptr; using boost::lexical_cast; @@ -110,7 +110,7 @@ ColourConversionEditor::set (ColourConversion conversion) _input_gamma_linearised->SetValue (conversion.input_gamma_linearised); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { - stringstream s; + SafeStringStream s; s.setf (std::ios::fixed, std::ios::floatfield); s.precision (7); s << conversion.matrix (i, j); diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index b341cb0fe..87310d21a 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -45,6 +45,7 @@ #include "lib/playlist.h" #include "lib/content.h" #include "lib/content_factory.h" +#include "lib/safe_stringstream.h" #include "timecode.h" #include "wx_util.h" #include "film_editor.h" @@ -57,7 +58,6 @@ using std::string; using std::cout; -using std::stringstream; using std::pair; using std::fixed; using std::setprecision; @@ -420,7 +420,7 @@ FilmEditor::film_changed (Film::Property p) return; } - stringstream s; + SafeStringStream s; for (list::iterator i = _panels.begin(); i != _panels.end(); ++i) { (*i)->film_changed (p); diff --git a/src/wx/job_wrapper.cc b/src/wx/job_wrapper.cc index df4aa7d2e..4c4ef049b 100644 --- a/src/wx/job_wrapper.cc +++ b/src/wx/job_wrapper.cc @@ -17,7 +17,6 @@ */ -#include #include "lib/film.h" #include "lib/exceptions.h" #include "job_wrapper.h" diff --git a/src/wx/properties_dialog.cc b/src/wx/properties_dialog.cc index 28247bc33..53ca23755 100644 --- a/src/wx/properties_dialog.cc +++ b/src/wx/properties_dialog.cc @@ -22,11 +22,11 @@ #include #include "lib/film.h" #include "lib/config.h" +#include "lib/safe_stringstream.h" #include "properties_dialog.h" #include "wx_util.h" using std::string; -using std::stringstream; using std::fixed; using std::setprecision; using boost::shared_ptr; @@ -48,7 +48,7 @@ PropertiesDialog::PropertiesDialog (wxWindow* parent, shared_ptr film) _frames->SetLabel (std_to_wx (lexical_cast (_film->time_to_video_frames (_film->length())))); double const disk = double (_film->required_disk_space()) / 1073741824.0f; - stringstream s; + SafeStringStream s; s << fixed << setprecision (1) << disk << wx_to_std (_("Gb")); _disk->SetLabel (std_to_wx (s.str ())); @@ -58,7 +58,7 @@ PropertiesDialog::PropertiesDialog (wxWindow* parent, shared_ptr film) string PropertiesDialog::frames_already_encoded () const { - stringstream u; + SafeStringStream u; try { u << _film->encoded_frames (); } catch (boost::thread_interrupted &) { diff --git a/test/film_metadata_test.cc b/test/film_metadata_test.cc index c41e86189..c9f4a2c38 100644 --- a/test/film_metadata_test.cc +++ b/test/film_metadata_test.cc @@ -17,7 +17,6 @@ */ -#include #include #include #include -- cgit v1.2.3