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::call(void *) {
219 threadSignalNoLock();
222 // the real entry for receiving data
223 int ImageReader::getImageChunk(ULLONG offset,UINT len, UINT * rsize, UCHAR **buffer){
224 logger->log("ImageReader", Log::DEBUG, "request chunk offset=%llu, len=%u",offset,len);
228 for (int found=2;found> 0; found--) {
229 //currently simple - we only check if we really have a chunk with exactly matching start
230 for (int i=0; i< MAXCHUNKS; i++ ) {
231 if (data[i].state != S_FREE && data[i].offset == offset) {
233 while ( data[i].state != S_READY && data[i].state != S_FREE && readerRunning) {
238 if (data[i].state == S_READY) {
240 *buffer=data[i].buffer;
244 data[i].state=S_FREE;
245 logger->log("ImageReader", Log::DEBUG, "ready chunk found at index %u,offset=%llu, len=%u",i,data[i].offset,data[i].len);
246 if ( data[i].len >0) {
247 //check if the next chunk is already on the way
248 ULLONG nexto=data[i].offset+data[i].len;
250 for (int x=0;x<MAXCHUNKS;x++) {
251 if (data[x].state != S_FREE && data[x].state != S_BREAK && data[x].offset==nexto) {
257 //set up request for next chunk
258 data[i].offset=nexto;
259 data[i].state=S_REQUEST;
260 logger->log("ImageReader", Log::DEBUG, "next chunk requested at index %u,offset=%llu, len=%u",i,data[i].offset,data[i].reqlen);
266 //thread seems to be stopped
267 logger->log("ImageReader", Log::DEBUG, "no ready chunk found although in list");
275 logger->log("ImageReader", Log::DEBUG, "returning buffer 0x%p, len %u",*buffer,*rsize);
276 threadSignalNoLock();
279 //we found no chunk for us - so set up a new one
281 for (int i=0;i<MAXCHUNKS;i++) {
282 if (data[i].state == S_FETCHING) {
283 //the reader is just fetching - let him finish
284 data[i].state = S_BREAK;
287 data[i].state=S_FREE;
288 if (data[i].buffer) free(data[i].buffer);
292 //now we should find one free anyway
294 for (int i=0;i<MAXCHUNKS;i++) {
295 if (data[i].state==S_FREE) {
297 data[i].offset=offset;
299 data[i].state=S_REQUEST;
300 threadSignalNoLock();
305 logger->log("ImageReader", Log::ERR, "no free chunk to load data");
311 logger->log("ImageReader", Log::ERR, "unable to get data");