]> git.vomp.tv Git - vompclient-marten.git/blob - imagereader.cc
libCEC support
[vompclient-marten.git] / imagereader.cc
1 /*
2     Copyright 2004-2006 Chris Tallon, Andreas Vogel
3
4     This file is part of VOMP.
5
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.
10
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.
15
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.
19 */
20
21 #include "imagereader.h"
22 #include "mediaprovider.h"
23 #include "media.h"
24 #include "i18n.h"
25 #include "log.h"
26
27
28 ImageReader::ImageReader(int c, MediaProvider *p) 
29 {
30   logger = Log::getInstance();
31   logger->log("ImageReader", Log::DEBUG, "ctorI");
32   provider=p;
33   channel=c;
34   running=false;
35   readerRunning=false;
36   this->run();
37 }
38
39 ImageReader::~ImageReader()
40 {
41   if (readerRunning) shutdown();
42   for (int i=0;i<MAXCHUNKS;i++) {
43     if (data[i].buffer != NULL) free(data[i].buffer);
44     data[i].buffer=NULL;
45   }
46 }
47
48
49 void ImageReader::run() {
50   if (running) return;
51   running=true;
52   readerRunning=true;
53   threadStart();
54 }
55
56
57 void ImageReader::shutdown()
58 {
59   running=false;
60   if (readerRunning) {
61     logger->log("ImageReader",Log::DEBUG,"shutdown - warting for reader thread to stop");
62     threadSignalNoLock();
63     logger->log("ImageReader",Log::DEBUG,"shutdown notified");
64     //wait for the reader thread to stop
65     //at most wait 10s
66     for (int loopcount=200;readerRunning && loopcount > 0;loopcount--) {
67       MILLISLEEP(50);
68     }
69     if (readerRunning) {
70       logger->log("ImageReader",Log::ERR,"shutdown - unable to stop reader within 10s");
71     }
72   }
73 }
74
75 void ImageReader::stop() {
76   if (readerRunning) {
77     threadLock();
78     int numopen=0;
79     for (int i=0; i< MAXCHUNKS;i++) {
80       if (data[i].state == S_FETCHING) {
81         data[i].state = S_BREAK;
82         numopen++;
83       }
84     }
85     threadUnlock();
86     int loopcount=200;
87     while (numopen > 0 && loopcount > 0) {
88       numopen=0;
89       logger->log("ImageReader",Log::DEBUG,"stop - warting for reader thread to stop");
90       threadSignalNoLock();
91       logger->log("ImageReader",Log::DEBUG,"stop notified");
92       MILLISLEEP(50);
93       threadLock();
94       for (int i=0; i< MAXCHUNKS;i++) {
95         if (data[i].state == S_FETCHING) {
96           data[i].state = S_BREAK;
97           numopen++;
98         }
99       }
100       threadUnlock();
101       loopcount--;
102     }
103     if (numopen > 0) 
104       logger->log("ImageReader",Log::ERR,"stop - unable to stop reader thread");
105   }
106 }
107
108
109
110 bool ImageReader::isReaderRunning() {
111   return readerRunning;
112 }
113
114
115
116 // ----------------------------------- Feed thread
117
118 void ImageReader::waitTimed(int ms) {
119   threadLock();
120   struct timespec nt;
121   int sec=ms/1000;
122   int us=1000*(ms - 1000*sec);
123 #ifndef WIN32
124   struct timeval ct;
125   gettimeofday(&ct,NULL);
126   nt.tv_sec=ct.tv_sec+sec;
127   nt.tv_nsec=1000*us+1000*ct.tv_usec;
128 #else 
129     DWORD ct=timeGetTime();
130     nt.tv_sec=ct/1000+sec;
131     nt.tv_nsec=1000*us+1000*ct*1000;
132 #endif
133   threadWaitForSignalTimed(&nt);
134   threadUnlock();
135 }
136
137 void ImageReader::threadMethod()
138 {
139   logger->log("ImageReader", Log::DEBUG, "player thread started");
140   int currentChunk=-1;
141   while(1)
142   {
143     if (! running) {
144       break;
145     }
146     if (currentChunk < 0) {
147       threadLock();
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);
153           currentChunk=i;
154           data[i].state=S_FETCHING;
155           break;
156           }
157         }
158       threadUnlock();
159     }
160     threadCheckExit();
161     if (currentChunk < 0) {
162       waitTimed(500);
163       continue;
164     }
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;
177         }
178       }
179     threadLock();
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;
188     }
189     data[currentChunk].state=S_READY;
190     if (data[currentChunk].len > 0) {
191       int i=0;
192       for (; i< MAXCHUNKS;i++) {
193         if (data[i].state == S_FREE ) {
194           data[i].state=S_REQUEST;
195           data[i].buffer=NULL;
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);
199           break;
200           }
201         }
202         //if we have a free chunk - read the data
203         if (i < MAXCHUNKS) currentChunk=i;
204         else currentChunk=-1;
205       } 
206     else {
207       //OEF or error - don't read next chunk
208       currentChunk=-1;
209       }
210     threadUnlock();
211     threadSignalNoLock();
212     }
213   logger->log("ImageReaderThread", Log::DEBUG, "finished");
214   readerRunning=false;
215   return;
216 }
217
218 void ImageReader::threadPostStopCleanup()
219 {
220 }
221
222 void ImageReader::call(void *) {
223   threadSignalNoLock();
224 }
225  
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);
229   threadLock();
230   *buffer=NULL;
231   *rsize=0;
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) {
236         found=0;
237         while ( data[i].state != S_READY && data[i].state != S_FREE && readerRunning) {
238             threadUnlock();
239             waitTimed(500);
240             threadLock();
241             }
242         if (data[i].state == S_READY) {
243           //data is available
244           *buffer=data[i].buffer;
245           *rsize=data[i].len;
246           //now free the entry
247           data[i].buffer=NULL;
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;
253             bool nfound=false;
254             for (int x=0;x<MAXCHUNKS;x++) {
255               if (data[x].state != S_FREE && data[x].state != S_BREAK && data[x].offset==nexto) {
256                 nfound=true;
257                 break;
258               }
259             }
260             if (! nfound) {
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);
265             }
266           }
267           break;
268           }
269         else {
270           //thread seems to be stopped
271           logger->log("ImageReader", Log::DEBUG, "no ready chunk found although in list");
272           ;
273           }
274         break;
275         }
276       }
277     if (found == 0) {
278       threadUnlock();
279       logger->log("ImageReader", Log::DEBUG, "returning buffer 0x%p, len %u",*buffer,*rsize);
280       threadSignalNoLock();
281       return 0;
282       }
283     //we found no chunk for us - so set up a new one
284     //remove all chunks 
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;
289         }
290       else {
291         data[i].state=S_FREE;
292         if (data[i].buffer) free(data[i].buffer);
293         data[i].buffer=NULL;
294       }
295     }
296     //now we should find one free anyway
297     bool ffree=false;
298     for (int i=0;i<MAXCHUNKS;i++) {
299       if (data[i].state==S_FREE) {
300         ffree=true;
301         data[i].offset=offset;
302         data[i].reqlen=len;
303         data[i].state=S_REQUEST;
304         threadSignalNoLock();
305         break;
306         }
307       }
308     if (! ffree) {
309       logger->log("ImageReader", Log::ERR, "no free chunk to load data");
310       threadUnlock();
311       return -1;
312       }
313     }
314   threadUnlock();
315   logger->log("ImageReader", Log::ERR, "unable to get data");
316   return -1;
317   }
318         
319     
320   
321
322