--- Tomas Groth <[EMAIL PROTECTED]> 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
_______________________________________________
Gnash-commit mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/gnash-commit

Reply via email to