[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash ChangeLog server/asobj/NetStream.cpp serv...
From: |
Sandro Santilli |
Subject: |
[Gnash-commit] gnash ChangeLog server/asobj/NetStream.cpp serv... |
Date: |
Wed, 21 May 2008 16:48:16 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Sandro Santilli <strk> 08/05/21 16:48:16
Modified files:
. : ChangeLog
server/asobj : NetStream.cpp NetStream.h NetStreamFfmpeg.cpp
NetStreamFfmpeg.h
Log message:
* server/asobj/NetStream.{cpp,h}: drop m_pause and m_go.
* server/asobj/NetStreamFfmpeg.{cpp,h}: drop m_pause and m_go,
use separate variables for playback and decoding status.
Add a lot more debugging (not really meant for final user, but
helpful for later progress on this).
NOTE: this is a work in progress, use of ffmpeg backend is discouraged
unless you want to help incrementally getting closer to the design
being discussed on list.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.6668&r2=1.6669
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStream.cpp?cvsroot=gnash&r1=1.90&r2=1.91
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStream.h?cvsroot=gnash&r1=1.62&r2=1.63
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamFfmpeg.cpp?cvsroot=gnash&r1=1.127&r2=1.128
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamFfmpeg.h?cvsroot=gnash&r1=1.65&r2=1.66
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.6668
retrieving revision 1.6669
diff -u -b -r1.6668 -r1.6669
--- ChangeLog 21 May 2008 16:08:22 -0000 1.6668
+++ ChangeLog 21 May 2008 16:48:14 -0000 1.6669
@@ -1,3 +1,11 @@
+2008-05-21 Sandro Santilli <address@hidden>
+
+ * server/asobj/NetStream.{cpp,h}: drop m_pause and m_go.
+ * server/asobj/NetStreamFfmpeg.{cpp,h}: drop m_pause and m_go,
+ use separate variables for playback and decoding status.
+ Add a lot more debugging (not really meant for final user, but
+ helpful for later progress on this).
+
2008-05-21 Benjamin Wolsey <address@hidden>
* server/array.cpp, server/as_function.cpp,
Index: server/asobj/NetStream.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStream.cpp,v
retrieving revision 1.90
retrieving revision 1.91
diff -u -b -r1.90 -r1.91
--- server/asobj/NetStream.cpp 15 May 2008 08:25:20 -0000 1.90
+++ server/asobj/NetStream.cpp 21 May 2008 16:48:15 -0000 1.91
@@ -71,9 +71,7 @@
m_bufferTime(100), // The default size needed to begin playback of
media is 100 miliseconds
m_videoFrameFormat(gnash::render::videoFrameFormat()),
m_newFrameReady(false),
- m_go(false),
m_imageframe(NULL),
- m_pause(false),
m_parser(NULL),
m_isFLV(false),
m_start_onbuffer(false),
Index: server/asobj/NetStream.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStream.h,v
retrieving revision 1.62
retrieving revision 1.63
diff -u -b -r1.62 -r1.63
--- server/asobj/NetStream.h 15 May 2008 08:25:21 -0000 1.62
+++ server/asobj/NetStream.h 21 May 2008 16:48:15 -0000 1.63
@@ -134,15 +134,9 @@
// Mutex to insure we don't corrupt the image
boost::mutex image_mutex;
- // Are the playing loop running or not
- volatile bool m_go;
-
// The image/videoframe which is given to the renderer
image::image_base* m_imageframe;
- // paused or not
- volatile bool m_pause;
-
// The video URL
std::string url;
Index: server/asobj/NetStreamFfmpeg.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamFfmpeg.cpp,v
retrieving revision 1.127
retrieving revision 1.128
diff -u -b -r1.127 -r1.128
--- server/asobj/NetStreamFfmpeg.cpp 21 May 2008 14:43:32 -0000 1.127
+++ server/asobj/NetStreamFfmpeg.cpp 21 May 2008 16:48:15 -0000 1.128
@@ -64,6 +64,10 @@
NetStreamFfmpeg::NetStreamFfmpeg():
+
+ _playback_state(PLAY_NONE),
+ _decoding_state(DEC_NONE),
+
m_video_index(-1),
m_audio_index(-1),
@@ -100,9 +104,10 @@
void NetStreamFfmpeg::pause( PauseMode mode )
{
+ log_debug("::pause(%d) called ", mode);
switch ( mode ) {
case pauseModeToggle:
- if ( m_pause ) {
+ if ( playbackStatus() == PLAY_PAUSED ) {
unpausePlayback();
} else {
pausePlayback();
@@ -118,23 +123,15 @@
break;
}
-#if 0 // we don't want to start _decodeThread so naively...
- if ( !m_pause && !m_go ) {
- setStatus( playStart );
- m_go = true;
-
- _decodeThread = new boost::thread(
boost::bind(NetStreamFfmpeg::av_streamer, this) );
- }
-#endif
}
void NetStreamFfmpeg::close()
{
- if (m_go)
+ if (decodingStatus() != DEC_STOPPED && decodingStatus() != DEC_NONE)
{
// request decoder thread termination
- m_go = false;
+ decodingStatus(DEC_STOPPED);
// resume the decoder, if waiting
_qFillerResume.notify_all();
@@ -242,9 +239,10 @@
{
// Is it already playing ?
- if (m_go)
+ if (playbackStatus() != PLAY_NONE && playbackStatus() != PLAY_STOPPED)
{
- unpausePlayback(); // will check for m_pause itself..
+ log_error("NetStream.play() called already playing ?"); //
TODO: fix this case
+ unpausePlayback(); // will check for playbackStatus itself..
return;
}
@@ -264,8 +262,8 @@
url = url.substr(4);
}
- m_go = true;
- pausePlayback();
+ decodingStatus(DEC_BUFFERING);
+ unpausePlayback();
// This starts the decoding thread
_decodeThread = new
boost::thread(boost::bind(NetStreamFfmpeg::av_streamer, this));
@@ -665,15 +663,11 @@
ns->m_unqueued_data = NULL;
- // Loop while we're playing
- while (ns->m_go)
+ // Loop while we're playing or buffering
+ while (ns->decodingStatus() != DEC_STOPPED)
{
unsigned long int sleepTime = 1000;
-#ifdef GNASH_DEBUG_THREADS
- log_debug("Decoding iteration. bufferTime=%lu, bufferLen=%lu",
ns->bufferTime(), ns->bufferLength());
-#endif
-
{
#ifdef GNASH_DEBUG_THREADS
log_debug("qMutex: waiting for lock in av_streamer");
@@ -682,18 +676,26 @@
#ifdef GNASH_DEBUG_THREADS
log_debug("qMutex: lock obtained in av_streamer");
#endif
+
+#ifdef GNASH_DEBUG_THREADS
+ log_debug("Decoding iteration. bufferTime=%lu, bufferLen=%lu,
videoFrames=%lu, audioFrames=%lu",
+ ns->bufferTime(), ns->bufferLength(),
ns->m_qvideo.size(), ns->m_qaudio.size());
+#endif
+
if (ns->m_isFLV)
{
// If both queues are full then don't bother filling it
if ( ns->m_qvideo.full() && ns->m_qaudio.full() )
{
+ ns->decodingStatus(DEC_DECODING); // that's to
say: not buffering anymore
+
// Instead wait till waked up by short-queues
event
- //log_debug("Queues full, waiting on
qNeedRefill condition");
+ log_debug("Queues full, waiting on qNeedRefill
condition");
ns->_qFillerResume.wait(lock);
}
else
{
- //log_debug("Calling decodeFLVFrame");
+ log_debug("Calling decodeFLVFrame");
bool successDecoding = ns->decodeFLVFrame();
//log_debug("decodeFLVFrame returned %d",
successDecoding);
if ( ! successDecoding )
@@ -701,10 +703,10 @@
// Possible failures:
// 1. could not decode frame... lot's
of possible
// reasons...
+ // 2. EOF reached
if ( ns->m_videoFrameFormat !=
render::NONE )
{
log_error("Could not decode FLV
frame");
- break;
}
// else it's expected, we'll keep going
anyway
}
@@ -733,15 +735,11 @@
}
-#ifdef GNASH_DEBUG_THREADS
- log_debug("Out of decoding loop");
-#endif
- ns->m_go = false;
+//#ifdef GNASH_DEBUG_THREADS
+ log_debug("Out of decoding loop. playbackStatus:%d, decodingStatus:%d",
ns->playbackStatus(), ns->decodingStatus());
+//#endif
+ ns->decodingStatus(DEC_STOPPED);
-#ifdef GNASH_DEBUG_STATUS
- log_debug("Setting playStop status");
-#endif
- ns->setStatus(playStop);
}
// audio callback is running in sound handler thread
@@ -751,12 +749,13 @@
NetStreamFfmpeg* ns = static_cast<NetStreamFfmpeg*>(owner);
- if (!ns->m_go || ns->m_pause)
+ if (ns->playbackStatus() == PLAY_PAUSED)
{
+ log_debug("playback status is paused, won't consume audio
frames");
return false;
}
- while (ns->m_go && len > 0 && ! ns->m_qaudio.empty())
+ while (len > 0 && ! ns->m_qaudio.empty())
{
#ifdef GNASH_DEBUG_THREADS
log_debug("qMutex: waiting for lock in audio_streamer");
@@ -795,31 +794,13 @@
bool NetStreamFfmpeg::decodeFLVFrame()
{
- FLVFrame* frame = NULL;
- if ( m_qvideo.size() < m_qaudio.size() )
- {
- frame = m_parser->nextVideoFrame();
- } else {
- frame = m_parser->nextAudioFrame();
- }
+ FLVFrame* frame = m_parser->nextMediaFrame(); // we don't care which
one, do we ?
if (frame == NULL)
{
- if (_netCon->loadCompleted())
- {
-#ifdef GNASH_DEBUG_THREADS
- log_debug("decodeFLVFrame: load completed, stopping");
-#endif
- // Stop!
- this->m_go = false;
- }
- else
- {
- pausePlayback();
- setStatus(bufferEmpty);
- m_start_onbuffer = true;
- }
- return false;
+ assert ( _netCon->loadCompleted() );
+ decodingStatus(DEC_STOPPED);
+ return true;
}
AVPacket packet;
@@ -955,7 +936,13 @@
m_last_audio_timestamp += frame_delay;
- if (m_isFLV) m_qaudio.push(raw);
+ if (m_isFLV)
+ {
+ if ( ! m_qaudio.push(raw) )
+ {
+ log_error("Audio queue full!");
+ }
+ }
else m_unqueued_data = m_qaudio.push(raw) ? NULL : raw;
}
return true;
@@ -1094,7 +1081,13 @@
}
// NOTE: Caller is assumed to have locked _qMutex already
- if (m_isFLV) m_qvideo.push(video);
+ if (m_isFLV)
+ {
+ if ( ! m_qvideo.push(video) )
+ {
+ log_error("Video queue full !");
+ }
+ }
else m_unqueued_data = m_qvideo.push(video) ? NULL : video;
return true;
@@ -1259,9 +1252,10 @@
log_debug("qMutex: lock obtained in refreshVideoFrame");
#endif
- // If we're paused or not running, there is no need to do this
- if (!m_go || m_pause)
+ // If we're paused (and we got the first imageframe), there is no need
to do this
+ if (playbackStatus() == PLAY_PAUSED && m_imageframe)
{
+ log_debug("refreshVideoFrame doing nothing as playback is
paused and we have an image frame already");
#ifdef GNASH_DEBUG_THREADS
log_debug("qMutex: releasing lock in refreshVideoFrame");
#endif
@@ -1269,15 +1263,36 @@
}
// Loop until a good frame is found
- while(!m_qvideo.empty())
+ do
{
// Get video frame from queue, will have the lowest timestamp
// will return NULL if empty(). See multithread_queue::front
media::raw_mediadata_t* video = m_qvideo.front();
- // If the queue is empty we have nothing to do
+ // If the queue is empty either we're waiting for more data
+ // to be decoded or we're out of data
if (!video)
{
+ log_debug("refreshVideoFrame:: No more video frames in
queue");
+
+ if ( decodingStatus() == DEC_STOPPED )
+ {
+ if ( playbackStatus() != PLAY_STOPPED )
+ {
+ playbackStatus(PLAY_STOPPED);
+//#ifdef GNASH_DEBUG_STATUS
+ log_debug("Setting playStop status");
+//#endif
+ setStatus(playStop);
+ }
+ }
+ else
+ {
+ // There no video but decoder is still running
+ // not much to do here except wait for next call
+ //assert(decodingStatus() == DEC_BUFFERING);
+ }
+
break;
}
@@ -1332,7 +1347,7 @@
break;
}
- }
+ } while(!m_qvideo.empty());
#ifdef GNASH_DEBUG_THREADS
log_debug("qMutex: releasing lock in refreshVideoFrame");
@@ -1345,25 +1360,6 @@
{
//log_debug("advance");
- // Make sure al decoding has stopped
- // This can happen in 2 cases:
- // 1) When playback has just started and we've been waiting for the
buffer
- // to be filled (buffersize set by setBufferTime() and default is 100
- // miliseconds).
- // 2) The buffer has be "starved" (not being filled as quickly as
needed),
- // and we then wait until the buffer contains some data (1 sec)
again.
- if (m_go && m_pause && m_start_onbuffer && m_parser.get() &&
m_parser->isTimeLoaded(m_current_timestamp+m_bufferTime))
- {
-#ifdef GNASH_DEBUG_STATUS
- log_debug("(advance): setting buffer full");
-#endif
- setStatus(bufferFull);
- unpausePlayback();
- m_start_onbuffer = false;
- }
-
- //log_debug("(advance): processing status notification, refreshing
video frame");
-
// Check if there are any new status messages, and if we should
// pass them to a event handler
processStatusNotifications();
@@ -1395,11 +1391,11 @@
void NetStreamFfmpeg::pausePlayback()
{
- //GNASH_REPORT_FUNCTION
+ GNASH_REPORT_FUNCTION;
- if (m_pause) return;
+ if (playbackStatus() == PLAY_PAUSED) return;
- m_pause = true;
+ playbackStatus(PLAY_PAUSED);
// Save the current time so we later can tell how long the pause lasted
m_time_of_pause = clocktime::getTicks();
@@ -1410,12 +1406,15 @@
void NetStreamFfmpeg::unpausePlayback()
{
- if (!m_pause) // already not paused
+ GNASH_REPORT_FUNCTION;
+
+ if (playbackStatus() == PLAY_PLAYING) // already playing
{
+ log_debug("unpausePlayback: already playing");
return;
}
- m_pause = false;
+ playbackStatus(PLAY_PLAYING);
if (m_current_timestamp == 0)
{
@@ -1428,7 +1427,7 @@
m_start_clock += clocktime::getTicks() - m_time_of_pause;
}
- // Re-connect to the soundhandler.
+ // (re)-connect to the soundhandler.
// It was disconnected in ::pausePlayback to avoid to keep playing
sound while paused
if ( _soundHandler ) _soundHandler->attach_aux_streamer(audio_streamer,
(void*) this);
}
@@ -1461,6 +1460,30 @@
return ret_val;
}
+NetStreamFfmpeg::PlaybackState
+NetStreamFfmpeg::playbackStatus(PlaybackState newstate)
+{
+ boost::mutex::scoped_lock lock(_state_mutex);
+
+ if (newstate != PLAY_NONE) {
+ _playback_state = newstate;
+ }
+
+ return _playback_state;
+}
+
+NetStreamFfmpeg::DecodingState
+NetStreamFfmpeg::decodingStatus(DecodingState newstate)
+{
+ boost::mutex::scoped_lock lock(_state_mutex);
+
+ if (newstate != DEC_NONE) {
+ _decoding_state = newstate;
+ }
+
+ return _decoding_state;
+}
+
} // gnash namespcae
Index: server/asobj/NetStreamFfmpeg.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamFfmpeg.h,v
retrieving revision 1.65
retrieving revision 1.66
diff -u -b -r1.65 -r1.66
--- server/asobj/NetStreamFfmpeg.h 21 May 2008 14:43:33 -0000 1.65
+++ server/asobj/NetStreamFfmpeg.h 21 May 2008 16:48:15 -0000 1.66
@@ -103,6 +103,27 @@
private:
+ enum PlaybackState {
+ PLAY_NONE,
+ PLAY_STOPPED,
+ PLAY_PLAYING,
+ PLAY_PAUSED
+ };
+
+ enum DecodingState {
+ DEC_NONE,
+ DEC_STOPPED,
+ DEC_DECODING,
+ DEC_BUFFERING,
+ };
+
+ PlaybackState _playback_state;
+ DecodingState _decoding_state;
+
+ // Mutex protecting _playback_state and _decoding_state
+ // (not sure a single one is appropriate)
+ boost::mutex _state_mutex;
+
// Setups the playback
bool startPlayback();
@@ -145,7 +166,7 @@
///
/// Will call decodeVideo or decodeAudio depending on frame type, and
return
/// what they return.
- /// Will set m_go to false on EOF from input.
+ /// Will set decodingStatus to DEC_BUFFERING when starving on input
///
/// This is a blocking call.
//
@@ -156,9 +177,10 @@
/// - or there is a conversion error
/// - or renderer requested format is NONE
/// ... false will be returned.
- /// If next frame is an audio frame and we have no audio decoding
context, false is returned.
/// In any other case, true is returned.
///
+ /// NOTE: if EOF is reached, true is returned by decodingStatus is set
to DEC_STOPPED
+ ///
/// NOTE: (FIXME) if we succeeded decoding but the relative queue was
full,
/// true will be returned but nothing would be pushed on the
queues.
///
@@ -203,6 +225,9 @@
return time.num / (double) time.den;
}
+ PlaybackState playbackStatus(PlaybackState newstate = PLAY_NONE);
+ DecodingState decodingStatus(DecodingState newstate = DEC_NONE);
+
int m_video_index;
int m_audio_index;