2 Copyright 2004-2006 Chris Tallon, Andreas Vogel
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "imagereader.h"
22 #include "mediaprovider.h"
28 ImageReader::ImageReader(int c, MediaProvider *p)
30 logger = Log::getInstance();
31 logger->log("ImageReader", Log::DEBUG, "ctorI");
39 ImageReader::~ImageReader()
41 if (readerRunning) shutdown();
42 for (int i=0;i<MAXCHUNKS;i++) {
43 if (data[i].buffer != NULL) free(data[i].buffer);
49 void ImageReader::run() {
57 void ImageReader::shutdown()
61 logger->log("ImageReader",Log::DEBUG,"shutdown - warting for reader thread to stop");
63 logger->log("ImageReader",Log::DEBUG,"shutdown notified");
64 //wait for the reader thread to stop
66 for (int loopcount=200;readerRunning && loopcount > 0;loopcount--) {
70 logger->log("ImageReader",Log::ERR,"shutdown - unable to stop reader within 10s");
75 void ImageReader::stop() {
79 for (int i=0; i< MAXCHUNKS;i++) {
80 if (data[i].state == S_FETCHING) {
81 data[i].state = S_BREAK;
87 while (numopen > 0 && loopcount > 0) {
89 logger->log("ImageReader",Log::DEBUG,"stop - warting for reader thread to stop");
91 logger->log("ImageReader",Log::DEBUG,"stop notified");
94 for (int i=0; i< MAXCHUNKS;i++) {
95 if (data[i].state == S_FETCHING) {
96 data[i].state = S_BREAK;
104 logger->log("ImageReader",Log::ERR,"stop - unable to stop reader thread");
110 bool ImageReader::isReaderRunning() {
111 return readerRunning;
116 // ----------------------------------- Feed thread
118 void ImageReader::waitTimed(int ms) {
122 int us=1000*(ms - 1000*sec);
125 gettimeofday(&ct,NULL);
126 nt.tv_sec=ct.tv_sec+sec;
127 nt.tv_nsec=1000*us+1000*ct.tv_usec;
129 DWORD ct=timeGetTime();
130 nt.tv_sec=ct/1000+sec;
131 nt.tv_nsec=1000*us+1000*ct*1000;
133 threadWaitForSignalTimed(&nt);
137 void ImageReader::threadMethod()
139 logger->log("ImageReader", Log::DEBUG, "player thread started");
146 if (currentChunk < 0) {
148 //check if new request is there (used=true && ongoing=true)
149 for (int i=0; i< MAXCHUNKS; i++) {
150 if (data[i].state == S_REQUEST) {
151 //found new chunk request
152 logger->log("ImageReaderThread", Log::DEBUG, "new chunk request found %i, offset=%llu, len=%u",i,data[i].offset,data[i].reqlen);
154 data[i].state=S_FETCHING;
161 if (currentChunk < 0) {
165 data[currentChunk].len=0;
166 logger->log("ImageReaderThread", Log::DEBUG, "start receive, offset %llu, len %u",data[currentChunk].offset,data[currentChunk].reqlen);
167 data[currentChunk].buffer=NULL;
168 int rt= provider->getMediaBlock(channel,data[currentChunk].offset, data[currentChunk].reqlen , &(data[currentChunk].len),&(data[currentChunk].buffer));
169 //set the chunk to ready
170 logger->log("ImageReaderThread", Log::DEBUG, "chunk received, offset %llu, len %u",data[currentChunk].offset,data[currentChunk].len);
171 if (rt != 0 || !(data[currentChunk].buffer) || data[currentChunk].len == 0 ) {
172 //OK we count this as end of stream
173 logger->log("ImageReaderThread", Log::DEBUG, "stream end");
174 if (data[currentChunk].buffer != NULL) {
175 free(data[currentChunk].buffer);
176 data[currentChunk].buffer=NULL;
180 //OK - now the chunk is received, try to see if we can read the next
181 //if somebody told us that this chunk is not needed any more we clean up
182 if ( data[currentChunk].state == S_BREAK) {
183 logger->log("ImageReaderThread", Log::DEBUG, "throw away chunk offset %llu, len %u", data[currentChunk].offset,data[currentChunk].reqlen);
184 data[currentChunk].len=0;
185 if (data[currentChunk].buffer) free(data[currentChunk].buffer);
186 data[currentChunk].buffer=NULL;
187 data[currentChunk].state=S_FREE;
189 data[currentChunk].state=S_READY;
190 if (data[currentChunk].len > 0) {
192 for (; i< MAXCHUNKS;i++) {
193 if (data[i].state == S_FREE ) {
194 data[i].state=S_REQUEST;
196 data[i].offset=data[currentChunk].offset+data[currentChunk].len;
197 data[i].reqlen=data[currentChunk].reqlen;
198 logger->log("ImageReaderThread", Log::DEBUG, "follow on for offset %llu, len %u", data[i].offset,data[i].reqlen);
202 //if we have a free chunk - read the data
203 if (i < MAXCHUNKS) currentChunk=i;
204 else currentChunk=-1;
207 //OEF or error - don't read next chunk
211 threadSignalNoLock();
213 logger->log("ImageReaderThread", Log::DEBUG, "finished");
218 void ImageReader::threadPostStopCleanup()
222 void ImageReader::call(void *) {
223 threadSignalNoLock();
226 // the real entry for receiving data
227 int ImageReader::getImageChunk(ULLONG offset,UINT len, UINT * rsize, UCHAR **buffer){
228 logger->log("ImageReader", Log::DEBUG, "request chunk offset=%llu, len=%u",offset,len);
232 for (int found=2;found> 0; found--) {
233 //currently simple - we only check if we really have a chunk with exactly matching start
234 for (int i=0; i< MAXCHUNKS; i++ ) {
235 if (data[i].state != S_FREE && data[i].offset == offset) {
237 while ( data[i].state != S_READY && data[i].state != S_FREE && readerRunning) {
242 if (data[i].state == S_READY) {
244 *buffer=data[i].buffer;
248 data[i].state=S_FREE;
249 logger->log("ImageReader", Log::DEBUG, "ready chunk found at index %u,offset=%llu, len=%u",i,data[i].offset,data[i].len);
250 if ( data[i].len >0) {
251 //check if the next chunk is already on the way
252 ULLONG nexto=data[i].offset+data[i].len;
254 for (int x=0;x<MAXCHUNKS;x++) {
255 if (data[x].state != S_FREE && data[x].state != S_BREAK && data[x].offset==nexto) {
261 //set up request for next chunk
262 data[i].offset=nexto;
263 data[i].state=S_REQUEST;
264 logger->log("ImageReader", Log::DEBUG, "next chunk requested at index %u,offset=%llu, len=%u",i,data[i].offset,data[i].reqlen);
270 //thread seems to be stopped
271 logger->log("ImageReader", Log::DEBUG, "no ready chunk found although in list");
279 logger->log("ImageReader", Log::DEBUG, "returning buffer 0x%p, len %u",*buffer,*rsize);
280 threadSignalNoLock();
283 //we found no chunk for us - so set up a new one
285 for (int i=0;i<MAXCHUNKS;i++) {
286 if (data[i].state == S_FETCHING) {
287 //the reader is just fetching - let him finish
288 data[i].state = S_BREAK;
291 data[i].state=S_FREE;
292 if (data[i].buffer) free(data[i].buffer);
296 //now we should find one free anyway
298 for (int i=0;i<MAXCHUNKS;i++) {
299 if (data[i].state==S_FREE) {
301 data[i].offset=offset;
303 data[i].state=S_REQUEST;
304 threadSignalNoLock();
309 logger->log("ImageReader", Log::ERR, "no free chunk to load data");
315 logger->log("ImageReader", Log::ERR, "unable to get data");