[Top][All Lists]
[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