gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Gnash-commit] gnash ChangeLog libbase/LoadThread.cpp


From: Tomas Groth
Subject: Re: [Gnash-commit] gnash ChangeLog libbase/LoadThread.cpp
Date: Wed, 30 May 2007 02:01:09 +0200 (CEST)

--- Tomas Groth <address@hidden> skrev:

> CVSROOT:      /sources/gnash
> Module name:  gnash
> Changes by:   Tomas Groth <tgc>       07/05/29 23:41:26
> 
> Modified files:
>       .              : ChangeLog 
>       libbase        : LoadThread.cpp 
> 
> Log message:
>               * libbase/LoadThread.cpp: Don't lock the mutex and try to join 
> the 
>                 download thread when calling complete(), instead do that in 
> the
>                 destrutor. Fixes some blocking (with the 
> no-decode-thread-patch
>                 for NetStreamFfmpeg).
> 

I've attached the latest version of the no-decode-thread-patch to this mail if
anyone wants to test. I think it is now better than the currently used model,
though it still needs a bit cleaning... Feel free to test (yes, i mean you
Sandro)!!

cheers,

Tomas




      
Index: server/asobj/NetStreamFfmpeg.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamFfmpeg.cpp,v
retrieving revision 1.67
diff -u -r1.67 NetStreamFfmpeg.cpp
--- server/asobj/NetStreamFfmpeg.cpp    29 May 2007 22:48:25 -0000      1.67
+++ server/asobj/NetStreamFfmpeg.cpp    29 May 2007 23:54:05 -0000
@@ -67,7 +67,9 @@
        m_last_audio_timestamp(0),
        m_current_timestamp(0),
        m_unqueued_data(NULL),
-       m_time_of_pause(0)
+       m_time_of_pause(0),
+       m_current_audioframe(NULL),
+       m_current_videoframe(NULL)      
 {
 
        ByteIOCxt.buffer = NULL;
@@ -94,7 +96,7 @@
        if (!m_pause && !m_go) { 
                setStatus(playStart);
                m_go = true;
-               _decodeThread = new 
boost::thread(boost::bind(NetStreamFfmpeg::av_streamer, this)); 
+               av_streamer(this);
        }
 
 }
@@ -106,11 +108,11 @@
        {
                // terminate thread
                m_go = false;
-               decode_wait.notify_one();
+/*             decode_wait.notify_one();
 
                // wait till thread is complete before main continues
                _decodeThread->join();
-               delete _decodeThread;
+               delete _decodeThread;*/
 
        }
 
@@ -233,7 +235,7 @@
        pauseDecoding();
 
        // This starts the decoding thread
-       _decodeThread = new 
boost::thread(boost::bind(NetStreamFfmpeg::av_streamer, this)); 
+       av_streamer(this); 
 
        return;
 }
@@ -596,10 +598,6 @@
 {
        GNASH_REPORT_FUNCTION;
 
-       log_debug("Thread %d locking on ::av_streamer", pthread_self());
-       boost::mutex::scoped_lock lock(ns->decoding_mutex);
-       log_debug(" obtained (av_streamer)");
-
        // This should only happen if close() is called before this thread is 
ready
        if (!ns->m_go)
        {
@@ -632,146 +630,74 @@
 
        ns->m_start_clock = tu_timer::ticks_to_seconds(tu_timer::get_ticks());
 
-       ns->m_unqueued_data = NULL;
-
-       // Loop while we're playing
-       while (ns->m_go)
-       {
-               log_debug("Decoding iteration");
-
-               if (ns->m_isFLV) {
-                       // If queues are full then don't bother filling it
-                       if (ns->m_qvideo.size() < 20 || ns->m_qvideo.size() < 
20) {
-
-                               // If we have problems with decoding - break
-                               if (!ns->decodeFLVFrame() && 
ns->m_start_onbuffer == false && ns->m_qvideo.size() == 0 && 
ns->m_qaudio.size() == 0)
-                               {
-                                       break;
-                               }
-                       }
 
-                       if (ns->m_pause || (ns->m_qvideo.size() > 10 && 
ns->m_qaudio.size() > 10))
-                       { 
-                               assert(ns->m_go);
-                               log_debug("Waiting on lock..");
-                               ns->decode_wait.wait(lock);
-                               log_debug("Finished waiting.");
-                       }
-               } else {
-
-                       // If we have problems with decoding - break
-                       if (ns->decodeMediaFrame() == false && 
ns->m_start_onbuffer == false && ns->m_qvideo.size() == 0 && 
ns->m_qaudio.size() == 0)
-                       {
-                               break;
-                       }
-
-                       // If paused, wait for being unpaused, or
-                       // if the queue is full we wait until someone notifies 
us that data is needed.
-                       if (ns->m_pause || ((ns->m_qvideo.size() > 0 && 
ns->m_qaudio.size() > 0) && ns->m_unqueued_data))
-                       { 
-                               log_debug("Waiting on lock..");
-                               ns->decode_wait.wait(lock);
-                               log_debug("Finished waiting.");
-                       }
-               }
-
-       }
-
-       log_debug("Out of decoding loop");
-       ns->m_go = false;
-
-       log_debug("Setting playStop status");
-       ns->setStatus(playStop);
 }
 
 // audio callback is running in sound handler thread
 bool NetStreamFfmpeg::audio_streamer(void *owner, uint8_t *stream, int len)
 {
-       GNASH_REPORT_FUNCTION;
+       //GNASH_REPORT_FUNCTION;
 
        NetStreamFfmpeg* ns = static_cast<NetStreamFfmpeg*>(owner);
 
-       log_debug("Thread %d locking on ::audio_streamer", pthread_self());
+       //log_debug("Thread %d locking on ::audio_streamer", pthread_self());
        boost::mutex::scoped_lock  lock(ns->decoding_mutex);
-       log_debug(" obtained (audio_streamer)");
+       //log_debug(" obtained (audio_streamer)");
 
        if (!ns->m_go || ns->m_pause) return false;
 
-       while (len > 0 && ns->m_qaudio.size() > 0)
+       while (len > 0)
        {
-               raw_mediadata_t* samples = ns->m_qaudio.front();
+               if (!ns->m_current_audioframe) {
+                       FLVFrame* frame = ns->m_parser->nextAudioFrame();
+                       if (frame == NULL) {
+                               if (ns->_netCon->loadCompleted()) {
+                                       // Stop!
+                                       //m_go = false;
+                               } else {
+                                       // We pause and load and buffer a 
second before continuing.
+                                       ns->pauseDecoding();
+                                       ns->m_bufferTime = 
static_cast<uint32_t>(ns->m_current_timestamp) * 1000 + 1000;
+                                       ns->setStatus(bufferEmpty);
+                                       ns->m_start_onbuffer = true;
+                               }
+                               return false;
+                       }
+                       AVPacket packet;
+                       packet.destruct = avpacket_destruct;
+                       packet.size = frame->dataSize;
+                       packet.data = frame->data;
+                       // FIXME: is this the right value for packet.dts?
+                       packet.pts = packet.dts = 
static_cast<int64_t>(frame->timestamp);
 
-               // If less than 3 frames in the queue notify the decoding thread
-               // so that we don't suddenly run out.
-               if (ns->m_qaudio.size() < 3) {
-                       ns->decode_wait.notify_one();
+                       ns->m_current_audioframe = ns->decodeAudio(&packet);
                }
 
-               int n = imin(samples->m_size, len);
-               memcpy(stream, samples->m_ptr, n);
+               if (!ns->m_current_audioframe) return false;
+
+               int n = imin(ns->m_current_audioframe->m_size, len);
+               memcpy(stream, ns->m_current_audioframe->m_ptr, n);
                stream += n;
-               samples->m_ptr += n;
-               samples->m_size -= n;
+               ns->m_current_audioframe->m_ptr += n;
+               ns->m_current_audioframe->m_size -= n;
                len -= n;
 
-               ns->m_current_timestamp = samples->m_pts;
+               ns->m_current_timestamp = ns->m_current_audioframe->m_pts;
 
-               if (samples->m_size == 0)
+               if (ns->m_current_audioframe->m_size == 0)
                {
-                       ns->m_qaudio.pop();
-                       delete samples;
+                       delete ns->m_current_audioframe;
+                       ns->m_current_audioframe = NULL;
                }
 
        }
        return true;
 }
 
-bool NetStreamFfmpeg::decodeFLVFrame()
-{
-       AVPacket packet;
-
-       FLVFrame* frame;
-       if (m_qvideo.size() < m_qaudio.size()) {
-               frame = m_parser->nextVideoFrame();
-       } else {
-               frame = m_parser->nextAudioFrame();
-       }
-
-       if (frame == NULL) {
-               if (_netCon->loadCompleted())
-               {
-                       log_debug("decodeFLVFrame: load completed, stopping");
-                       // Stop!
-                       m_go = false;
-               } else {
-                       // We pause and load and buffer a second before 
continuing.
-                       pauseDecoding();
-                       m_bufferTime = 
static_cast<uint32_t>(m_current_timestamp) * 1000 + 1000;
-                       setStatus(bufferEmpty);
-                       m_start_onbuffer = true;
-               }
-               return false;
-       }
-
-       packet.destruct = avpacket_destruct;
-       packet.size = frame->dataSize;
-       packet.data = frame->data;
-       // FIXME: is this the right value for packet.dts?
-       packet.pts = packet.dts = static_cast<int64_t>(frame->timestamp);
-
-       if (frame->tag == 9) {
-               packet.stream_index = 0;
-               return decodeVideo(&packet);
-       } else {
-               packet.stream_index = 1;
-               return decodeAudio(&packet);
-       }
-
-}
 
-bool NetStreamFfmpeg::decodeAudio(AVPacket* packet)
+raw_mediadata_t* NetStreamFfmpeg::decodeAudio(AVPacket* packet)
 {
-       if (!m_ACodecCtx) return false;
+       if (!m_ACodecCtx) return NULL;
 
        int frame_size;
        unsigned int bufsize = (AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2;
@@ -831,15 +757,14 @@
 
                m_last_audio_timestamp += frame_delay;
 
-               if (m_isFLV) m_qaudio.push(raw);
-               else m_unqueued_data = m_qaudio.push(raw) ? NULL : raw;
+               return raw;
        }
-       return true;
+       return NULL;
 }
 
-bool NetStreamFfmpeg::decodeVideo(AVPacket* packet)
+raw_mediadata_t* NetStreamFfmpeg::decodeVideo(AVPacket* packet)
 {
-       if (!m_VCodecCtx) return false;
+       if (!m_VCodecCtx) return NULL;
 
        int got = 0;
        avcodec_decode_video(m_VCodecCtx, m_Frame, &got, packet->data, 
packet->size);
@@ -855,7 +780,7 @@
                }
 
                if (m_videoFrameFormat == render::NONE) { // NullGui?
-                       return false;
+                       return NULL;
 
                } else if (m_videoFrameFormat == render::YUV && 
m_VCodecCtx->pix_fmt != PIX_FMT_YUV420P) {
                        assert(0);      // TODO
@@ -948,18 +873,15 @@
 
                }
 
-               if (m_isFLV) m_qvideo.push(video);
-               else m_unqueued_data = m_qvideo.push(video) ? NULL : video;
-
-               return true;
+               return video;
        }
 
-       return false;
+       return NULL;
 }
 
 bool NetStreamFfmpeg::decodeMediaFrame()
 {
-       log_debug("Thread %d locking on ::decodeMediaFrame", pthread_self());
+/*     log_debug("Locking on ::decodeMediaFrame");
        boost::mutex::scoped_lock  lock(decoding_mutex);
        log_debug(" obtained (decodeMediaFrame)");
 
@@ -1012,13 +934,14 @@
                log_error(_("Problems decoding frame"));
                return false;
        }
-
+*/
        return true;
 }
 
 void
 NetStreamFfmpeg::seek(double pos)
 {
+
        long newpos = 0;
        double timebase = 0;
 
@@ -1052,11 +975,13 @@
 
        } else if (m_isFLV) {
                double newtime = static_cast<double>(newpos) / 1000.0;
-               m_start_clock += (m_last_audio_timestamp - newtime) / 1000.0;
+               if (m_VCodecCtx) m_start_clock += (m_last_video_timestamp - 
newtime) / 1000.0;
+               else m_start_clock += (m_last_audio_timestamp - newtime) / 
1000.0;
 
-               m_last_audio_timestamp = newtime;
-               m_last_video_timestamp = newtime;
+               if (m_ACodecCtx) m_last_audio_timestamp = newtime;
+               if (m_VCodecCtx) m_last_video_timestamp = newtime;
                m_current_timestamp = newtime;
+
        } else {
                AVPacket Packet;
                av_init_packet(&Packet);
@@ -1081,18 +1006,11 @@
                m_current_timestamp = newtime;
        }
        
-       // Flush the queues
-       while (m_qvideo.size() > 0)
-       {
-               delete m_qvideo.front();
-               m_qvideo.pop();
-       }
+       delete m_current_videoframe;
+       m_current_videoframe = NULL;
 
-       while (m_qaudio.size() > 0)
-       {
-               delete m_qaudio.front();
-               m_qaudio.pop();
-       }
+       delete m_current_audioframe;
+       m_current_audioframe = NULL;
 
 }
 
@@ -1100,20 +1018,38 @@
 NetStreamFfmpeg::refreshVideoFrame()
 {
        // If we're paused or not running, there is no need to do this
-       if (!m_go || m_pause) return;
+       if (m_pause) return;
 
        // Loop until a good frame is found
        while(1) {
-               // Get video frame from queue, will have the lowest timestamp
-               raw_mediadata_t* video = m_qvideo.front();
 
-               // If the queue is empty, we tell the decoding thread to wake 
up,
-               // and decode some more.
-               if (!video) {
-                       decode_wait.notify_one();
-                       return;
+               if (!m_current_videoframe) {
+                       FLVFrame* frame = m_parser->nextVideoFrame();
+                       if (frame == NULL) {
+                               if (_netCon->loadCompleted()) {
+                                       // Stop!
+                                       //m_go = false;
+                               } else {
+                                       // We pause and load and buffer a 
second before continuing.
+                                       pauseDecoding();
+                                       m_bufferTime = 
static_cast<uint32_t>(m_current_timestamp) * 1000 + 1000;
+                                       setStatus(bufferEmpty);
+                                       m_start_onbuffer = true;
+                               }
+                               return;
+                       }
+                       AVPacket packet;
+                       packet.destruct = avpacket_destruct;
+                       packet.size = frame->dataSize;
+                       packet.data = frame->data;
+                       // FIXME: is this the right value for packet.dts?
+                       packet.pts = packet.dts = 
static_cast<int64_t>(frame->timestamp);
+
+                       m_current_videoframe = decodeVideo(&packet);
                }
 
+               if (!m_current_videoframe) return;
+
                // Caclulate the current time
                double current_clock;
                if (m_ACodecCtx && get_sound_handler()) {
@@ -1123,7 +1059,7 @@
                        m_current_timestamp = current_clock;
                }
 
-               double video_clock = video->m_pts;
+               double video_clock = m_current_videoframe->m_pts;
 
                // If the timestamp on the videoframe is smaller than the
                // current time, we put it in the output image.
@@ -1132,16 +1068,16 @@
                        boost::mutex::scoped_lock lock(image_mutex);
                        if (m_videoFrameFormat == render::YUV) {
                                // XXX m_imageframe might be a byte aligned 
buffer, while video is not!
-                               
static_cast<image::yuv*>(m_imageframe)->update(video->m_data);
+                               
static_cast<image::yuv*>(m_imageframe)->update(m_current_videoframe->m_data);
                        } else if (m_videoFrameFormat == render::RGB) {
 
                                image::rgb* imgframe = 
static_cast<image::rgb*>(m_imageframe);
-                               rgbcopy(imgframe, video, m_VCodecCtx->width * 
3);
+                               rgbcopy(imgframe, m_current_videoframe, 
m_VCodecCtx->width * 3);
                        }
 
-                       // Delete the frame from the queue
-                       m_qvideo.pop();
-                       delete video;
+                       // Delete the frame
+                       delete m_current_videoframe;
+                       m_current_videoframe = NULL;
 
                        // A frame is ready for pickup
                        m_newFrameReady = true;
@@ -1152,11 +1088,6 @@
                        return;
                }
 
-               // If less than 3 frames in the queue notify the decoding thread
-               // so that we don't suddenly run out.
-               if (m_qvideo.size() < 3) {
-                       decode_wait.notify_one();
-               }
        }
 }
 
@@ -1164,9 +1095,10 @@
 void
 NetStreamFfmpeg::advance()
 {
-       log_debug("Thread %d locking on ::advance", pthread_self());
+
+       //log_debug("Thread %d locking on ::advance", pthread_self());
        boost::mutex::scoped_lock lock(decoding_mutex);
-       log_debug(" obtained (advance)");
+       //log_debug(" obtained (advance)");
 
        // Make sure al decoding has stopped
        // This can happen in 2 cases: 
@@ -1183,7 +1115,7 @@
                m_start_onbuffer = false;
        }
 
-       log_debug("(advance): processing status notification, refreshing video 
frame");
+       //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
@@ -1238,12 +1170,10 @@
                m_start_clock += 
tu_timer::ticks_to_seconds(tu_timer::get_ticks()) - m_time_of_pause;
        }
 
-       // Notify the decode thread/loop that we are running again
-       decode_wait.notify_one();
-
        // Re-connect to the soundhandler
        sound_handler* s = get_sound_handler();
        if (s) s->attach_aux_streamer(audio_streamer, (void*) this);
+
 }
 
 
Index: server/asobj/NetStreamFfmpeg.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamFfmpeg.h,v
retrieving revision 1.37
diff -u -r1.37 NetStreamFfmpeg.h
--- server/asobj/NetStreamFfmpeg.h      29 May 2007 22:48:25 -0000      1.37
+++ server/asobj/NetStreamFfmpeg.h      29 May 2007 23:54:05 -0000
@@ -49,6 +49,7 @@
 
 namespace gnash {
   
+/// Class containing the decoded media data, either audio or video
 class raw_mediadata_t
 {
 public:
@@ -215,7 +216,7 @@
        static int readPacket(void* opaque, uint8_t* buf, int buf_size);
        static offset_t seekMedia(void *opaque, offset_t offset, int whence);
 
-       /// The decoding thread. Sets up the decoder, and decodes.
+       /// Sets up the decoder, and decodes.
        //
        /// Locks decoding_mutex
        ///
@@ -239,7 +240,8 @@
        // Pauses the decoding - don't directly modify m_pause!!
        //
        // does NOT lock decoding_mutex. Users:
-       //      - ::decodeFLVFrame() not locking  byt called by av_streamer 
which locks
+       //  - ::refreshVideoFrame() not locking  byt called by ::advance which 
locks
+       //  - ::audio_streamer() which locks.
        //      - ::pause() not locking but called by ::advance
        //      - ::play() not locking but called by ::advance which locks
        //
@@ -263,17 +265,11 @@
        // Used to decode and push the next available (non-FLV) frame to the 
audio or video queue
        bool decodeMediaFrame();
 
-       // Used to decode push the next available FLV frame to the audio or 
video queue
-       //
-       // does NOT lock decoding_mutex, uses by ::advance() which locks
-       //
-       bool decodeFLVFrame();
-
        // Used to decode a video frame and push it on the videoqueue
-       bool decodeVideo(AVPacket* packet);
+       raw_mediadata_t* decodeVideo(AVPacket* packet);
 
        // Used to decode a audio frame and push it on the audioqueue
-       bool decodeAudio(AVPacket* packet);
+       raw_mediadata_t* decodeAudio(AVPacket* packet);
 
        // Used to calculate a decimal value from a ffmpeg fraction
        inline double as_double(AVRational time)
@@ -333,6 +329,9 @@
        // there wasen't room for on its queue
        raw_mediadata_t* m_unqueued_data;
 
+       raw_mediadata_t* m_current_audioframe;
+       raw_mediadata_t* m_current_videoframe;
+
        ByteIOContext ByteIOCxt;
 
        // Time of when pause started

reply via email to

[Prev in Thread] Current Thread [Next in Thread]