commit 7d80da496b9fcd0892c93a1dcc16308a2c9a6941 Author: Sandro Santilli Date: Sun Jul 31 18:45:35 2011 +0200 Add a way to wait for a given amount of bytes to be loaded Use this to ensure 65535 bytes are loaded before constructing an root movie. This fixes unstable results from the swfdec test registerclass-previous.swf diff --git a/libcore/SWFMovie.cpp b/libcore/SWFMovie.cpp index e97a540..39ba448 100644 --- a/libcore/SWFMovie.cpp +++ b/libcore/SWFMovie.cpp @@ -56,6 +56,8 @@ SWFMovie::construct(as_object* /*init*/) ); } + _def->ensure_bytes_loaded(std::min(65535, _def->get_bytes_total())); + // Invoke parent placement event handler MovieClip::construct(); } diff --git a/libcore/parser/SWFMovieDefinition.cpp b/libcore/parser/SWFMovieDefinition.cpp index beebe69..170068c 100644 --- a/libcore/parser/SWFMovieDefinition.cpp +++ b/libcore/parser/SWFMovieDefinition.cpp @@ -155,6 +155,7 @@ SWFMovieDefinition::SWFMovieDefinition(const RunResources& runResources) _frames_loaded(0u), _waiting_for_frame(0), _bytes_loaded(0), + _waiting_for_bytes(0), m_loading_sound_stream(-1), m_file_length(0), m_jpeg_in(0), @@ -394,6 +395,28 @@ SWFMovieDefinition::ensure_frame_loaded(size_t framenum) const return ( framenum <= _frames_loaded ); } +bool +SWFMovieDefinition::ensure_bytes_loaded(size_t numbytes) const +{ + boost::mutex::scoped_lock lock(_bytes_loaded_mutex); + +#ifndef LOAD_MOVIES_IN_A_SEPARATE_THREAD + return ( numbytes <= _bytes_loaded ); +#endif + + if ( numbytes <= _bytes_loaded ) return true; + + // TODO: verify the parser is still alive before waiting + // on a condition that will otherwise never arrive. + + _waiting_for_bytes = numbytes; + + // TODO: return false on timeout + _bytes_reached_condition.wait(lock); + + return ( numbytes <= _bytes_loaded ); +} + Movie* SWFMovieDefinition::createMovie(Global_as& gl, DisplayObject* parent) { @@ -516,6 +539,12 @@ SWFMovieDefinition::read_all_swf() // Notify any thread waiting on frame reached condition _frame_reached_condition.notify_all(); } + + // Notify any thread waiting on bytes loaded condition + { + boost::mutex::scoped_lock lock(_bytes_loaded_mutex); + _bytes_reached_condition.notify_all(); + } } size_t @@ -559,6 +588,22 @@ SWFMovieDefinition::incrementLoadedFrames() } void +SWFMovieDefinition:: setBytesLoaded(unsigned long bytes) +{ + boost::mutex::scoped_lock lock(_bytes_loaded_mutex); + _bytes_loaded=bytes; + + // signal load of bytes if anyone requested it + if (_waiting_for_bytes && _bytes_loaded >= _waiting_for_bytes ) + { + // or should we notify_one ? + // See: http://boost.org/doc/html/condition.html + _bytes_reached_condition.notify_all(); + } + +} + +void SWFMovieDefinition::registerExport(const std::string& symbol, boost::uint16_t id) { diff --git a/libcore/parser/SWFMovieDefinition.h b/libcore/parser/SWFMovieDefinition.h index 94f85e8..d61854e 100644 --- a/libcore/parser/SWFMovieDefinition.h +++ b/libcore/parser/SWFMovieDefinition.h @@ -338,6 +338,11 @@ public: /// has been loaded (load on demand). bool ensure_frame_loaded(size_t framenum) const; + /// \brief + /// Ensure that the given number of bytes + /// has been loaded (load on demand). + bool ensure_bytes_loaded(size_t numbytes) const; + /// Read and parse all the SWF stream (blocking until load is finished) // /// This function uses a private TagLoadersTable @@ -481,6 +486,15 @@ private: /// thread will read it. mutable boost::mutex _bytes_loaded_mutex; + /// A semaphore to signal load of a minimum number of bytes + mutable boost::condition _bytes_reached_condition; + + /// Set this to trigger signaling of reached amount of bytes loaded + // + /// Make sure you locked _bytes_loaded_mutex + /// when accessing this member ! + mutable size_t _waiting_for_bytes; + int m_loading_sound_stream; boost::uint32_t m_file_length; @@ -512,11 +526,7 @@ private: /// Set number of bytes loaded from input stream // /// NOTE: this method locks _bytes_loaded_mutex - void setBytesLoaded(unsigned long bytes) - { - boost::mutex::scoped_lock lock(_bytes_loaded_mutex); - _bytes_loaded=bytes; - } + void setBytesLoaded(unsigned long bytes); /// A flag set to true when load cancellation is requested bool _loadingCanceled;