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;