/* try to get video frame data in ARGB format, restore GXA state */
bool CScreenShot::GetData()
{
	static OpenThreads::Mutex mutex;
	bool res = false;

	mutex.lock();
#ifdef USE_NEVIS_GXA
	CFrameBuffer::getInstance()->setActive(false);
#endif
	if (videoDecoder->getBlank()) 
		get_video = false;
#if !HAVE_GENERIC_HARDWARE
	res = videoDecoder->GetScreenImage(pixel_data, xres, yres, get_video, get_osd, scale_to_video);
#endif

#ifdef USE_NEVIS_GXA
	/* sort of hack. GXA used to transfer/convert live image to RGB,
	 * so setup GXA back */
	CFrameBuffer::getInstance()->setupGXA();
	//CFrameBuffer::getInstance()->add_gxa_sync_marker();
	CFrameBuffer::getInstance()->setActive(true);
#endif
	mutex.unlock();
	if (!res) {
		printf("CScreenShot::Start: GetScreenImage failed\n");
		return false;
	}

	printf("CScreenShot::GetData: data: %p %d x %d\n", pixel_data, xres, yres);
	return true;
}
Beispiel #2
0
void SendThread::run()
{
#ifdef __linux__
    prctl(PR_SET_NAME, "RRServer send", 0, 0, 0);
#endif
    for (;;)
    {
        m_mutexData.lock();
        m_condData.wait(&m_mutexData);
        if (m_rrdpy && m_b)
        {
            try
            {
                m_rrdpy->sendframe(m_b);
                m_rrdpy = NULL;
                m_b = NULL;
            }
            catch (...)
            {
                fprintf(stderr, "send failed, client disconnectd?\n");
            }
        }
        else
        {
            // finish thread
            m_mutexData.unlock();
            return;
        }
        m_mutexData.unlock();
    }
}
double ossimDtedElevationDatabase::getHeightAboveMSL(const ossimGpt& gpt)
{
   if(!isSourceEnabled())
      return ossim::nan();

   double result = ossim::nan();
   m_mutex.lock();
   if(m_lastHandler.valid() && m_lastHandler->pointHasCoverage(gpt))
   {
      result = m_lastHandler->getHeightAboveMSL(gpt);
   }
   else
   {
      m_lastHandler = getOrCreateCellHandler(gpt);
      if(m_lastHandler.valid())
         result = m_lastHandler->getHeightAboveMSL(gpt);
   }

#if 0
   d_mutex.lock();
   cout << "THREAD ID: "<<OpenThreads::Thread::CurrentThread()->getThreadId()<<"  "
         <<"ossimDtedElevationDatabase @ "<<(unsigned long)this<<"  m_lastHandler @ "
         <<(unsigned long)m_lastHandler.get()<<endl; //### TODO: for debug, remove
   d_mutex.unlock();
#endif

   m_mutex.unlock();
   return result;
}
Beispiel #4
0
void SendThread::stop()
{
    m_mutexData.lock();
    m_rrdpy = NULL;
    m_b = NULL;
    m_condData.signal();
    m_mutexData.unlock();
}
Beispiel #5
0
void SendThread::send(rrdisplayclient *rrdpy, rrframe *b)
{
    m_mutexData.lock();
    m_rrdpy = rrdpy;
    m_b = b;
    m_condData.signal();
    m_mutexData.unlock();
}
Beispiel #6
0
	virtual void run() {
		helper::PerformanceMeasurer PM;

		PM.tic();
		while(!is->done()) {
			_mutex.lock();

			is->get(frame);
			if(frame.empty()) {
				loglni("[TrackThread] no valid frame, exit!!!");
				OpenCVneedQuit = true;
				_mutex.unlock();
				break;
			}

			cvtColor(frame, gray, CV_BGR2GRAY);
			double rms, ncc;
			if( needToInit ) {
				loglni("[TrackThread] INITing...");
				Mat tmpH;
				if( findAprilTag(frame, 0, tmpH, true) ) {
#if !USE_INTERNAL_DETECTOR
					Mat initH = tmpH * iHI;
					needToInit = !tracker.init(gray, initH, rms, ncc);
#else
					needToInit=!tracker.init(gray,rms,ncc);
#endif
					if(!needToInit) loglni("[TrackThread] ...INITed");
					if(!needToInit) tracker.draw3D(frame);
				}
			} else {
				needToInit=!tracker(gray, rms, ncc, opencvDraw?&frame:0);
				if(!needToInit) tracker.GetCameraPose(camR,camT,false,true);
			}
			++BkgModifyCnt;
			loglni("[TrackThread] fps="<<1.0/PM.toctic());

			_mutex.unlock();
			if(OpenCVneedQuit) {
				break;
			}

			++framecnt;
		}

		OpenThreads::Thread::YieldCurrentThread();
		loglni("[TrackThread] OpenCV quited...");
		if(!videoFromWebcam) {
			loglni("[TrackThread] OpenCV notify OSG to quit...");
			viewer.setDone(true);
		}
	}
void DiskCache::cleanup()
{
    cleanupLock.lock();
    mapLock.lock();

    for(std::list<std::pair<int,int> >::iterator it = _cleanupList.begin(); it != _cleanupList.end(); )
    {
#ifdef DC_PRINT_DEBUG
        std::cerr << "Cleanup f: " << it->first << " i: " << it->second << std::endl;
#endif
	if(_cacheMap.find(it->first) == _cacheMap.end() || _cacheMap[it->first].find(it->second) == _cacheMap[it->first].end())
	{
#ifdef DC_PRINT_DEBUG
	    std::cerr << "Double Cleanup f: " << it->first << " i: " << it->second << std::endl;
#endif
            it = _cleanupList.erase(it);
	    continue;
	}
	_cacheMap[it->first][it->second]->cji->lock.lock();
	if(_cacheMap[it->first][it->second]->cji->refs <= 1)
	{
	    _cacheMap[it->first][it->second]->cji->lock.unlock();
	    if(_cacheMap[it->first][it->second]->cji->data)
	    {
		delete[] _cacheMap[it->first][it->second]->cji->data;
	    }
	    delete _cacheMap[it->first][it->second]->cji;
	    delete _cacheMap[it->first][it->second];
	    _cacheMap[it->first].erase(it->second);
	    it = _cleanupList.erase(it);
	}
	else
	{
	    _cacheMap[it->first][it->second]->cji->lock.unlock();
	    it++;
	}
    }

    mapLock.unlock();
    cleanupLock.unlock();
}
Beispiel #8
0
void ossim::getFormattedTime(
   const std::string& format, bool gmtFlag, std::string& result )
{
   timeMutex.lock();
   
   time_t rawTime;
   time(&rawTime);
   
   struct tm* timeInfo;
   if ( gmtFlag )
   {
      timeInfo = gmtime(&rawTime);
   }
   else
   {
      timeInfo = localtime(&rawTime);
   }
   
   size_t size = 0;
   if ( timeInfo )
   {
      const size_t STRING_SIZE = 196; // This is a big time string size.
      char outStr[STRING_SIZE];

      size = strftime(outStr, STRING_SIZE, format.c_str(), timeInfo );

      if ( size )
      {
         // Per strftime spec not needed but null terminating anyway.
         outStr[STRING_SIZE-1] = '\0';
         result = outStr;
      }
   }
   if ( !size )
   {
      result.clear();
   }

   timeMutex.unlock();
}
int DiskCache::add_file(const std::string& name)
{
    int id;
    _fileAddLock.lock();

    if(_fileIDMap.find(name) != _fileIDMap.end())
    {
	id = _fileIDMap[name];
    }
    else
    {
	listLock.lock();

	_fileIDMap[name] = _nextID;
	id = _nextID;

	_cacheMap[id] = std::map<int,DiskCacheEntry*>();

	_readList.push_back(std::list<std::pair<sph_task*, CopyJobInfo*> >());

	for(int i = 0; i < _copyList.size(); i++)
	{
	    _copyList[i].push_back(std::list<std::pair<sph_task*, CopyJobInfo*> >());
	}

	listLock.unlock();

	_nextID++;
    }

    _fileAddLock.unlock();

#ifdef DC_PRINT_DEBUG
    std::cerr << "add_file called with name: " << name << " given ID: " << id << std::endl;
#endif

    return id;
}
void DiskCache::add_task(sph_task * task)
{

    
    /*int curPages = 0;
    mapLock.lock();
    for(std::map<int, std::map<int,DiskCacheEntry*> >::iterator it = _cacheMap.begin(); it != _cacheMap.end(); it++)
    {
	curPages += it->second.size();
    }
    mapLock.unlock();
    std::cerr << "Actual Current Pages: " << curPages << std::endl;*/

    cleanup();

    if(!_running || (task->f != _currentFileL && task->f != _currentFileR))
    {
	task->valid = false;
	loadsLock.lock();
	task->cache->loads.insert(*task);
	loadsLock.unlock();
	delete task;
	return;
    }

    if(_cacheIndexMap.find(task->cache) == _cacheIndexMap.end())
    {
	listLock.lock();
	int index = _cacheIndexMap.size();
	_cacheIndexMap[task->cache] = index;

	_copyList.push_back(std::vector<std::list<std::pair<sph_task*, CopyJobInfo*> > >());

	for(int i = 0; i < _fileIDMap.size(); i++)
	{
	    _copyList.back().push_back(std::list<std::pair<sph_task*, CopyJobInfo*> >());
	}

	listLock.unlock();
    }

    mapLock.lock();
    if(!_cacheMap[task->f][task->i])
    {
	_cacheMap[task->f][task->i] = new DiskCacheEntry;
	_cacheMap[task->f][task->i]->timestamp = task->timestamp;
	_cacheMap[task->f][task->i]->f = task->f;
	_cacheMap[task->f][task->i]->i = task->i;

	CopyJobInfo * cji = new CopyJobInfo;
	cji->data = NULL;
	cji->size = 100;
	cji->valid = 0;
	cji->refs = 2;

	_cacheMap[task->f][task->i]->cji = cji;

	mapLock.unlock();


	listLock.lock();

#ifdef DC_PRINT_DEBUG
	std::cerr << "Job started for task f: " << task->f << " i: " << task->i << " t: " << task->timestamp << std::endl;
#endif
	_readList[task->f].push_back(std::pair<sph_task*, CopyJobInfo*>(task,cji));

	listLock.unlock();


	pageCountLock.lock();

	_numPages++;

	/*while(_numPages >= _pages)
	{
	    pageCountLock.unlock();
	    eject();
	    pageCountLock.lock();
	}*/

	pageCountLock.unlock();
    }
    else
    {
	CopyJobInfo * cji = _cacheMap[task->f][task->i]->cji;

	cji->lock.lock();
	if(!cji->size == 0)
	{
	    _cacheMap[task->f][task->i]->timestamp = task->timestamp;
	    cji->refs++;
	    cji->lock.unlock();

	    mapLock.unlock();

#ifdef DC_PRINT_DEBUG
	    std::cerr << "DiskCache Hit f: " << task->f << " i: " << task->i << " t: " << task->timestamp << std::endl;
#endif

	    listLock.lock();

	    _copyList[_cacheIndexMap[task->cache]][task->f].push_back(std::pair<sph_task*, CopyJobInfo*>(task,cji));

	    listLock.unlock();
	}
	else
	{
	    cji->lock.unlock();
	    mapLock.unlock();

#ifdef DC_PRINT_DEBUG
	    std::cerr << "DiskCache Hit on deleting entry f: " << task->f << " i: " << task->i << std::endl;
#endif

	    task->valid = false;
	    loadsLock.lock();
	    task->cache->loads.insert(*task);
	    loadsLock.unlock();
	    delete task;
	}
    }

    int tries = 3;

    pageCountLock.lock();

    while(_numPages >= _pages && tries > 0)
    {
	pageCountLock.unlock();
	ejectLock.lock();
	bool result = eject();
	ejectLock.unlock();

	// if you could not eject a page, stop trying
	if(!result)
	{
	    break;
	}

	tries--;
	pageCountLock.lock();
    }

    pageCountLock.unlock();
}
Beispiel #11
0
void SendThread::complete()
{
    m_mutexData.lock();
    m_mutexData.unlock();
}
Beispiel #12
0
bool CFfmpegDec::SetMetaData(FILE *_in, CAudioMetaData* m, bool save_cover)
{
	if (!meta_data_valid)
	{
		if (!Init(_in, (const CFile::FileType) m->type))
			return false;

		mutex.lock();
		int ret = avformat_find_stream_info(avc, NULL);
		if (ret < 0) {
			mutex.unlock();
			DeInit();
			printf("avformat_find_stream_info error %d\n", ret);
			return false;
		}
		mutex.unlock();
		if (!is_stream) {
			GetMeta(avc->metadata);
			for(unsigned int i = 0; i < avc->nb_streams; i++) {
				if (avc->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
					GetMeta(avc->streams[i]->metadata);
			}
		}

		//fseek((FILE *) in, 0, SEEK_SET);
#ifdef FFDEC_DEBUG
		av_dump_format(avc, 0, "", 0);
#endif

		codec = NULL;
		best_stream = av_find_best_stream(avc, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0);

		if (best_stream < 0) {
			DeInit();
			return false;
		}

		if (!codec)
			codec = avcodec_find_decoder(avc->streams[best_stream]->codec->codec_id);
		samplerate = avc->streams[best_stream]->codec->sample_rate;
		mChannels = av_get_channel_layout_nb_channels(avc->streams[best_stream]->codec->channel_layout);

		std::stringstream ss;

		if (codec && codec->long_name != NULL)
			type_info = codec->long_name;
		else if(codec && codec->name != NULL)
			type_info = codec->name;
		else
			type_info = "unknown";
		ss << " / " << mChannels << " channel" << ( mChannels > 1 ? "s" : "");
		type_info += ss.str();

		bitrate = 0;
		total_time = 0;

		if (avc->duration != int64_t(AV_NOPTS_VALUE))
			total_time = avc->duration / int64_t(AV_TIME_BASE);
		printf("CFfmpegDec: format %s (%s) duration %ld\n", avc->iformat->name, type_info.c_str(), total_time);

		for(unsigned int i = 0; i < avc->nb_streams; i++) {
			if (avc->streams[i]->codec->bit_rate > 0)
				bitrate += avc->streams[i]->codec->bit_rate;
			if (save_cover && (avc->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC)) {
				mkdir(COVERDIR, 0755);
				std::string cover(COVERDIR);
				cover += "/" + to_string(cover_count++) + ".jpg";
				FILE *f = fopen(cover.c_str(), "wb");
				if (f) {
					AVPacket *pkt = &avc->streams[i]->attached_pic;
					fwrite(pkt->data, pkt->size, 1, f);
					fclose(f);
					m->cover = cover;
					m->cover_temporary = true;
				}
			}
		}
		if(!total_time && m->filesize && bitrate)
			total_time = 8 * m->filesize / bitrate;

		meta_data_valid = true;
		m->changed = true;
	}
	if (!is_stream) {
		m->title = title;
		m->artist = artist;
		m->date = date;
		m->album = album;
		m->genre = genre;
		m->total_time = total_time;
	}
	m->type_info = type_info;
	// make sure bitrate is set to prevent refresh metadata from gui, its a flag
	m->bitrate = bitrate ? bitrate : 1; 
	m->samplerate = samplerate;

	return true;
}
Beispiel #13
0
CBaseDec::RetCode CFfmpegDec::Decoder(FILE *_in, int /*OutputFd*/, State* state, CAudioMetaData* _meta_data, time_t* time_played, unsigned int* secondsToSkip)
{
	in = _in;
	RetCode Status=OK;
	is_stream = fseek((FILE *)in, 0, SEEK_SET);

	if (!SetMetaData((FILE *)in, _meta_data, true)) {
		DeInit();
		Status=DATA_ERR;
		return Status;
	}

	AVCodecContext *c = avc->streams[best_stream]->codec;

	mutex.lock();
	int r = avcodec_open2(c, codec, NULL);
	mutex.unlock();
	if (r)
	{
		DeInit();
		Status=DATA_ERR;
		return Status;
	}

	SwrContext *swr = swr_alloc();
	if (!swr) {
		mutex.lock();
		avcodec_close(c);
		mutex.unlock();
		DeInit();
		Status=DATA_ERR;
		return Status;
	}

	mSampleRate = samplerate;
	mChannels = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_STEREO);
#if __BYTE_ORDER == __LITTLE_ENDIAN
	audioDecoder->PrepareClipPlay(mChannels, mSampleRate, 16, 1);
#else
	audioDecoder->PrepareClipPlay(mChannels, mSampleRate, 16, 0);
#endif

	AVFrame *frame = NULL;
	AVPacket rpacket;
	av_init_packet(&rpacket);

	av_opt_set_int(swr, "in_channel_layout",	c->channel_layout,	0);
	//av_opt_set_int(swr, "out_channel_layout",	c->channel_layout,	0);
	av_opt_set_int(swr, "out_channel_layout",	AV_CH_LAYOUT_STEREO,	0);
	av_opt_set_int(swr, "in_sample_rate",		c->sample_rate,		0);
	av_opt_set_int(swr, "out_sample_rate",		c->sample_rate,		0);
	av_opt_set_int(swr, "in_sample_fmt",		c->sample_fmt,		0);
	av_opt_set_int(swr, "out_sample_fmt",		AV_SAMPLE_FMT_S16,	0);

	swr_init(swr);

	uint8_t *outbuf = NULL;
	int outsamples = 0;
	int outsamples_max = 0;

	int64_t pts = 0, start_pts = 0, next_skip_pts = 0;
	uint64_t skip = 0;
	int seek_flags = 0;

	do
	{
		int actSecsToSkip = *secondsToSkip;
		if (!is_stream && (actSecsToSkip || *state==FF || *state==REV) && avc->streams[best_stream]->time_base.num) {
			if (!next_skip_pts || pts >= next_skip_pts) {
				skip = avc->streams[best_stream]->time_base.den / avc->streams[best_stream]->time_base.num;
				if (actSecsToSkip)
					skip *= actSecsToSkip;
				if (*state == REV) {
					next_skip_pts = pts - skip;
					pts = next_skip_pts - skip/4;
					seek_flags = AVSEEK_FLAG_BACKWARD;
					if (pts < start_pts) {
						pts = start_pts;
						*state = PAUSE; 
					}
				} else {
					pts += skip;
					next_skip_pts = pts + skip/4;
					seek_flags = 0;
				}
				av_seek_frame(avc, best_stream, pts, seek_flags);
				skip = 0;
				// if a custom value was set we only jump once
				if (actSecsToSkip != 0) {
					*state=PLAY;
					*secondsToSkip = 0;
				}
			}
		}

		while(*state==PAUSE && !is_stream)
			usleep(10000);

		if (av_read_frame(avc, &rpacket)) {
			Status=DATA_ERR;
			break;
		}

		if (rpacket.stream_index != best_stream) {
			av_free_packet(&rpacket);
			continue;
		}

		AVPacket packet = rpacket;
		while (packet.size > 0) {
			int got_frame = 0;
			if (!frame) {
				if (!(frame = avcodec_alloc_frame())) {
					Status=DATA_ERR;
					break;
				}
			} else
				avcodec_get_frame_defaults(frame);

			int len = avcodec_decode_audio4(c, frame, &got_frame, &packet);
			if (len < 0) {
				// skip frame
				packet.size = 0;
				avcodec_flush_buffers(c);
				mutex.lock();
				avcodec_close(c);
				avcodec_open2(c, codec, NULL);
				mutex.unlock();
				continue;
			}
			if (got_frame && *state!=PAUSE) {
				int out_samples;
				outsamples = av_rescale_rnd(swr_get_delay(swr, c->sample_rate) + frame->nb_samples,
					c->sample_rate, c->sample_rate, AV_ROUND_UP);
				if (outsamples > outsamples_max) {
					av_free(outbuf);
					if (av_samples_alloc(&outbuf, &out_samples, mChannels, //c->channels,
								frame->nb_samples, AV_SAMPLE_FMT_S16, 1) < 0) {
						Status=WRITE_ERR;
						packet.size = 0;
						break;
					}
					outsamples_max = outsamples;
				}
				outsamples = swr_convert(swr, &outbuf, outsamples,
							(const uint8_t **) &frame->data[0], frame->nb_samples);
				int outbuf_size = av_samples_get_buffer_size(&out_samples, mChannels, //c->channels,
									  outsamples, AV_SAMPLE_FMT_S16, 1);

				if(audioDecoder->WriteClip((unsigned char*) outbuf, outbuf_size) != outbuf_size)
				{
					fprintf(stderr,"%s: PCM write error (%s).\n", ProgName, strerror(errno));
					Status=WRITE_ERR;
				}
				pts = av_frame_get_best_effort_timestamp(frame);
				if (!start_pts)
					start_pts = pts;
			}
			packet.size -= len;
			packet.data += len;
		}
		if (time_played && avc->streams[best_stream]->time_base.den)
			*time_played = (pts - start_pts) * avc->streams[best_stream]->time_base.num / avc->streams[best_stream]->time_base.den;
		av_free_packet(&rpacket);
	} while (*state!=STOP_REQ && Status==OK);

	audioDecoder->StopClip();
	meta_data_valid = false;

	swr_free(&swr);
	av_free(outbuf);
	av_free_packet(&rpacket);
	avcodec_free_frame(&frame);
	avcodec_close(c);
	//av_free(avcc);

	DeInit();
	if (_meta_data->cover_temporary && !_meta_data->cover.empty()) {
		_meta_data->cover_temporary = false;
		unlink(_meta_data->cover.c_str());
	}
	return Status;
}
void JobThread::copy()
{
    std::pair<sph_task*, CopyJobInfo*> taskpair;
   
    bool found = false;
    
    listLock.lock();

    if(_copyList->size())
    {
	_copyCacheNum = _copyCacheNum % _copyList->size();
	_copyFileNum = _copyFileNum % _copyList->at(_copyCacheNum).size();
	int lastFile = _copyFileNum;
	for(int i = 0; i < _copyList->size(); i++)
	{
	    for(; _copyFileNum < _copyList->at(_copyCacheNum).size(); _copyFileNum++)
	    {
		if(_copyList->at(_copyCacheNum)[_copyFileNum].size())
		{
		    for(std::list<std::pair<sph_task*, CopyJobInfo*> >::iterator it = _copyList->at(_copyCacheNum)[_copyFileNum].begin(); it != _copyList->at(_copyCacheNum)[_copyFileNum].end(); it++)
		    {
			if(it->second->valid || !it->second->size)
			{
			    taskpair = *it;
			    _copyList->at(_copyCacheNum)[_copyFileNum].erase(it);
			    found = true;
			    break;
			}
		    }
		    if(found)
		    {
			_copyFileNum++;
			break;
		    }
		    //taskpair = _copyList->at(_copyCacheNum)[_copyFileNum].front();
		    //_copyList->at(_copyCacheNum)[_copyFileNum].pop_front();
		    //found = true;
		    //_copyFileNum++;
		    //break;
		}
	    }
	    if(found)
	    {
		if(_copyFileNum == _copyList->at(_copyCacheNum).size())
		{
		    _copyCacheNum++;
		    _copyCacheNum = _copyCacheNum % _copyList->size();
		    _copyFileNum = 0;
		}
		break;
	    }
	    _copyFileNum = 0;
	    _copyCacheNum++;
	    _copyCacheNum = _copyCacheNum % _copyList->size();  
	}

	if(!found)
	{
	    for(_copyFileNum = 0; _copyFileNum < lastFile; _copyFileNum++)
	    {
		if(_copyList->at(_copyCacheNum)[_copyFileNum].size())
		{
		    for(std::list<std::pair<sph_task*, CopyJobInfo*> >::iterator it = _copyList->at(_copyCacheNum)[_copyFileNum].begin(); it != _copyList->at(_copyCacheNum)[_copyFileNum].end(); it++)
		    {
			if(it->second->valid || !it->second->size)
			{
			    taskpair = *it;
			    _copyList->at(_copyCacheNum)[_copyFileNum].erase(it);
			    found = true;
			    break;
			}
		    }
		    if(found)
		    {
			_copyFileNum++;
			break;
		    }
		    //taskpair = _copyList->at(_copyCacheNum)[_copyFileNum].front();
		    //_copyList->at(_copyCacheNum)[_copyFileNum].pop_front();
		    //found = true;
		    //_copyFileNum++;
		    //break;
		}
	    }
	}
    }

#ifdef DC_PRINT_DEBUG
    int cjobsize = 0;
    for(int i = 0; i < _copyList->size(); i++)
    {
	for(int j = 0; j < _copyList->at(i).size(); j++)
	{
	    cjobsize += _copyList->at(i)[j].size();
	}
    }
    if(cjobsize)
    {
	std::cerr << "Copy Jobs left: " << cjobsize << std::endl;
    }
#endif


    /*if(_copyList->size())
    {
	for(int i = 0; i < _copyList->size(); i++)
	{
	    _copyIndex = _copyIndex % _copyList->size();
	    if(_copyList->at(_copyIndex).size())
	    {
		taskpair = _copyList->at(_copyIndex).front();
		_copyList->at(_copyIndex).pop_front();
		_copyIndex++;
		break;
	    }
	    _copyIndex++;
	}
    }*/
    listLock.unlock();

    if(taskpair.first)
    {
#ifdef DC_PRINT_DEBUG
	std::cerr << "Copy thread: " << _id << " got task f: " << taskpair.first->f << " i: " << taskpair.first->i << std::endl;
	if(_jt == READ_THREAD)
	{
	    std::cerr << "Copy done by read thread." << std::endl;
	}
#endif
	unsigned char * currentP = taskpair.second->data;
	unsigned int currentCopied = 0;
	unsigned int size = 0;
	do
	{
	    unsigned int currentValid;
	    taskpair.second->lock.lock();
	    currentValid = taskpair.second->valid;
	    size = taskpair.second->size;
	    taskpair.second->lock.unlock();

	    if(currentCopied < currentValid)
	    {
		unsigned char * dest = ((unsigned char*)taskpair.first->p) + currentCopied;
		unsigned char * src = taskpair.second->data + currentCopied;
		memcpy(dest,src,currentValid - currentCopied);
		currentCopied = currentValid;
	    }

	} while(currentCopied < size);
	taskpair.second->lock.lock();
	taskpair.second->refs--;
	if(!taskpair.second->size)
	{
	    taskpair.first->valid = false;
	}
	loadsLock.lock();
	taskpair.first->cache->loads.insert(*(taskpair.first));
	loadsLock.unlock();
	taskpair.second->lock.unlock();
#ifdef DC_PRINT_DEBUG
	std::cerr << "Copy thread: " << _id << " finished task f: " << taskpair.first->f << " i: " << taskpair.first->i << std::endl;
#endif
	delete taskpair.first;
    }
    else
    {
	struct timespec ts;
	ts.tv_sec = 0;
	ts.tv_nsec = 2000000;

	nanosleep(&ts,NULL);
    }
}
bool DiskCache::eject()
{
#ifdef DC_PRINT_DEBUG
    std::cerr << "DiskCache::eject()" << std::endl;
#endif

    mapLock.lock();
    // find oldest referenced page

    int f = -1;
    int i = -1;
    int mint = INT_MAX;

    for(std::map<int, std::map<int,DiskCacheEntry*> >::iterator it = _cacheMap.begin(); it != _cacheMap.end(); it++)
    {
	for(std::map<int,DiskCacheEntry*>::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++)
	{
	    if(!it2->second)
	    {
		continue;
	    }

	    if(it2->second->timestamp < mint)
	    {
		mint = it2->second->timestamp;
		f = it2->second->f;
		i = it2->second->i;
	    }
	}
    }

    if(f == -1)
    {
	std::cerr << "No Min page found!?!?..." << std::endl;
	mapLock.unlock();
	return false;
    }
    _cacheMap[f][i]->timestamp = INT_MAX;
    mapLock.unlock();

#ifdef DC_PRINT_DEBUG
    std::cerr << "Eject f: " << f << " i: " << i << " t: " << mint << std::endl;
#endif

    _cacheMap[f][i]->cji->lock.lock();

    if(!_cacheMap[f][i]->cji->size)
    {
#ifdef DC_PRINT_DEBUG
	std::cerr << "Already Ejecting f: " << f << " i: " << i << " t: " << mint << std::endl;
#endif
	_cacheMap[f][i]->cji->lock.unlock();

	return false;
    }
    
    _cacheMap[f][i]->cji->size = 0;
    _cacheMap[f][i]->cji->lock.unlock();

    std::queue<sph_task> tempq;

    loadsLock.lock();

    for(std::map<sph_cache*,int>::iterator it = _cacheIndexMap.begin(); it != _cacheIndexMap.end(); it++)
    {
	while(!it->first->loads.empty())
	{
	    tempq.push(it->first->loads.remove());
	    if(tempq.front().f == f && tempq.front().i == i)
	    {
		tempq.front().valid = false;
	    }
	}

	while(tempq.size())
	{
	    it->first->loads.insert(tempq.front());
	    tempq.pop();
	}
    }

    loadsLock.unlock();

    cleanupLock.lock();
    _cleanupList.push_back(std::pair<int,int>(f,i));
    cleanupLock.unlock();

    /*delete[] _cacheMap[f][i]->cji->data;
    delete _cacheMap[f][i]->cji;
    delete _cacheMap[f][i];
    _cacheMap[f].erase(i);*/

    pageCountLock.lock();
    _numPages--;
    pageCountLock.unlock();

    return true;
}
void DiskCache::kill_tasks(int file)
{
    if(file < 0 || file >= _readList.size())
    {
	return;
    }

    listLock.lock();

    std::queue<sph_task> tempq;

    loadsLock.lock();

    for(std::map<sph_cache*,int>::iterator it = _cacheIndexMap.begin(); it != _cacheIndexMap.end(); it++)
    {
	while(!it->first->loads.empty())
	{
	    tempq.push(it->first->loads.remove());
	    if(tempq.front().f == file)
	    {
		tempq.front().valid = false;
	    }
	}

	while(tempq.size())
	{
	    it->first->loads.insert(tempq.front());
	    tempq.pop();
	}
    }

    loadsLock.unlock();

    for(int i = 0; i < _copyList.size(); i++)
    {
        for(std::list<std::pair<sph_task*, CopyJobInfo*> >::iterator it = _copyList[i][file].begin(); it != _copyList[i][file].end(); it++)
        {
            it->first->valid = false;
	    loadsLock.lock();
            it->first->cache->loads.insert(*(it->first));
	    loadsLock.unlock();
	    it->second->lock.lock();
	    it->second->refs--;
	    it->second->lock.unlock();
            delete it->first;
        }
        _copyList[i][file].clear();
    }


    for(std::list<std::pair<sph_task*, CopyJobInfo*> >::iterator it = _readList[file].begin(); it != _readList[file].end(); it++)
    {
	it->first->valid = false;
	loadsLock.lock();
	it->first->cache->loads.insert(*(it->first));
	loadsLock.unlock();

	bool ejecting;
	it->second->lock.lock();
	it->second->refs--;
	if(it->second->size)
	{
	    ejecting = false;
	    it->second->size = 0;
	}
	else
	{
	    ejecting = true;
	}
	it->second->lock.unlock();

	if(!ejecting)
	{
	    cleanupLock.lock();
	    _cleanupList.push_back(std::pair<int,int>(it->first->f,it->first->i));
	    cleanupLock.unlock();
	}

	delete it->first;

	if(!ejecting)
	{
	    pageCountLock.lock();
	    _numPages--;
	    pageCountLock.unlock();
	}
	/*if(!it->second->refs)
	{
	    _cacheMap[it->first->f].erase(it->first->i);
	    it->second->lock.unlock();
	    delete it->second;
	    delete it->first;
	}
	else
	{
	    it->second->size = 0;
	    _cleanupList.push_back(std::pair<int,int>(it->first->f,it->first->i));
	    it->second->lock.unlock();
	}*/
    }

    _readList[file].clear();

    listLock.unlock();
}
void JobThread::read()
{
    CopyJobInfo * cji = NULL;
    sph_task * task = NULL;

    listLock.lock();
    if(_readList->size())
    {
	for(int i = 0; i < _readList->size(); i++)
	{
	    _readIndex = _readIndex % _readList->size();
	    if(_readList->at(_readIndex).size())
	    {
		task = _readList->at(_readIndex).front().first;
		cji = _readList->at(_readIndex).front().second;
		_readList->at(_readIndex).pop_front();
#ifdef DC_PRINT_DEBUG
		std::cerr << "Read Thread grabbed job f: " << task->f << " i: " << task->i << " t: " << task->timestamp << std::endl;
#endif
		_readIndex++;
		break;
	    }
	    _readIndex++;
	}
    }
    listLock.unlock();

    if(task)
    {
	if (!task->cache->files[task->f].name.empty())
        {
            if (TIFF *T = TIFFOpen(task->cache->files[task->f].name.c_str(), "r"))
            {
                if (up(T, task->i))
                {
                    uint32 w = task->cache->files[task->f].w;
                    uint32 h = task->cache->files[task->f].h;
                    uint16 c = task->cache->files[task->f].c;
                    uint16 b = task->cache->files[task->f].b;
                
		    readData(task, cji,T,w,h,c,b);
#ifdef DC_PRINT_DEBUG
		    std::cerr << "Done reading data f: " << task->f << " i: " << task->i << std::endl;
#endif
                    //task.load_texture(T, w, h, c, b);
                    //task->cache->loads.insert(*task);
                }
                TIFFClose(T);
            }
        }
	else
	{
	    delete task;
	}
	cji->lock.lock();
	cji->refs--;
	cji->lock.unlock();
    }
    else
    {
	// no read task, look for a copy one
	//std::cerr << "Read thread doing copy" << std::endl;
	copy();
    }
}
void JobThread::readData(sph_task * task, CopyJobInfo * cji, TIFF * T, uint32 w, uint32 h, uint16 c, uint16 b)
{
    // Confirm the page format.
    
    uint32 W, H;
    uint16 C, B;
    
    TIFFGetField(T, TIFFTAG_IMAGEWIDTH,      &W);
    TIFFGetField(T, TIFFTAG_IMAGELENGTH,     &H);
    TIFFGetField(T, TIFFTAG_BITSPERSAMPLE,   &B);
    TIFFGetField(T, TIFFTAG_SAMPLESPERPIXEL, &C);
    
    if (W == w && H == h && B == b && C == c)
    {
	cji->lock.lock();
	cji->valid = 0;
	cji->refs++;

	if(cji->size == 0)
	{
	    // if job is invalid, forward through to copy op
	    task->valid = false;
	    cji->lock.unlock();
	    listLock.lock();

	    _copyList->at((*_cacheIndexMap)[task->cache])[task->f].push_back(std::pair<sph_task*,CopyJobInfo*>(task,cji));

	    listLock.unlock();
	    return;
	}

	unsigned int linesize = TIFFScanlineSize(T);
	unsigned int totalData = W*H*4;
	unsigned char * data = new unsigned char[totalData];
	unsigned int currentValid = 0;

	cji->data = data;
	cji->size = totalData;
	cji->lock.unlock();

	listLock.lock();

	_copyList->at((*_cacheIndexMap)[task->cache])[task->f].push_back(std::pair<sph_task*,CopyJobInfo*>(task,cji));

	listLock.unlock();

	// Pad a 24-bit image to 32-bit BGRA.

	if (c == 3 && b == 8)
	{
	    if (void *q = malloc(linesize))
	    {
		const uint32 S = w * 4 * b / 8;

		for (uint32 r = 0; r < h; ++r)
		{
		    TIFFReadScanline(T, q, r, 0);

		    for (int j = w - 1; j >= 0; --j)
		    {
			uint8 *s = (uint8 *) q         + j * c * b / 8;
			uint8 *d = (uint8 *) data + r * S + j * 4 * b / 8;

			d[0] = s[2];
			d[1] = s[1];
			d[2] = s[0];
			d[3] = 0xFF;
		    }
		    currentValid += S;
		    cji->lock.lock();
		    cji->valid = currentValid;
		    cji->lock.unlock();
		}
		free(q);
	    }
	}
	else
	{
	    for (uint32 r = 0; r < h; ++r)
	    {
		TIFFReadScanline(T, (uint8 *) data + r * linesize, r, 0);

		currentValid += linesize;
		cji->lock.lock();
		cji->valid = currentValid;
		cji->lock.unlock();
	    }
	}	
    }
    else
    {
	delete task;
    }
}