Mercurial > mplayer.hg
annotate libmpdemux/cache2.c @ 16946:47c5e9846cd3
ultra simple&slow pp filter, yes yet another spp like filter :)
this one does actually compress&decompress the video at various shifts with lavc while the other spp filters are doing optimized intra only filtering
limitations:
mpeg4 is hardcoded, all options too, pretty trivial to change though, even filtering with non dct codecs like snow could be tried ...
the qscale/qp is only taken fron the first MB of each image and then used for the whole image (would needs some small changes to lavc to let the user set the qscales for the mbs themselfs but iam to lazy ...)
this needs ALOT of cpu time and memory especially at uspp=8 ...
author | michael |
---|---|
date | Tue, 08 Nov 2005 13:15:19 +0000 |
parents | 09ad0b5e6643 |
children | 6ff3379a0862 |
rev | line source |
---|---|
2324 | 1 #include "config.h" |
2 | |
2322 | 3 #ifdef USE_STREAM_CACHE |
4 | |
5 // Initial draft of my new cache system... | |
2352 | 6 // Note it runs in 2 processes (using fork()), but doesn't requires locking!! |
2322 | 7 // TODO: seeking, data consistency checking |
8 | |
2352 | 9 #define READ_USLEEP_TIME 10000 |
10 #define FILL_USLEEP_TIME 50000 | |
4825
41d2da3bd082
Make blocking call in libmpdemux interuptable (only with new input,
albeu
parents:
3726
diff
changeset
|
11 #define PREFILL_SLEEP_TIME 200 |
2322 | 12 |
13 #include <stdio.h> | |
14 #include <stdlib.h> | |
15 #include <string.h> | |
16 #include <signal.h> | |
3726 | 17 #include <sys/types.h> |
18 #include <unistd.h> | |
2322 | 19 |
10197 | 20 #include "../osdep/timer.h" |
21 #ifndef WIN32 | |
10242 | 22 #include <sys/wait.h> |
9380 | 23 #include "../osdep/shmem.h" |
10197 | 24 #else |
25 #include <windows.h> | |
26 static DWORD WINAPI ThreadProc(void* s); | |
27 #endif | |
2322 | 28 |
2371 | 29 #include "mp_msg.h" |
16793
8d4fb5469efb
Make a few more messages translatable by moving them into help_mp-en.h.
diego
parents:
16750
diff
changeset
|
30 #include "help_mp.h" |
2371 | 31 |
2322 | 32 #include "stream.h" |
33 | |
34 int stream_fill_buffer(stream_t *s); | |
35 int stream_seek_long(stream_t *s,off_t pos); | |
36 | |
7862
013c255225d8
mpdemux.c|h moved to libinput, mpdemux_check_interrupt() -> mp_input_check_interrupt()
arpi
parents:
7472
diff
changeset
|
37 extern int mp_input_check_interrupt(int time); |
2322 | 38 |
39 typedef struct { | |
40 // constats: | |
41 unsigned char *buffer; // base pointer of the alllocated buffer memory | |
2352 | 42 int buffer_size; // size of the alllocated buffer memory |
43 int sector_size; // size of a single sector (2048/2324) | |
44 int back_size; // we should keep back_size amount of old bytes for backward seek | |
45 int fill_limit; // we should fill buffer only if space>=fill_limit | |
16152
10a69a812eff
remove unused cache-prefill and create cache-seek-min that controls when seek_long is prefered over waiting for cache to fill
iive
parents:
12899
diff
changeset
|
46 int seek_limit; // keep filling cache if distanse is less that seek limit |
2374 | 47 // filler's pointers: |
48 int eof; | |
49 off_t min_filepos; // buffer contain only a part of the file, from min-max pos | |
50 off_t max_filepos; | |
51 off_t offset; // filepos <-> bufferpos offset value (filepos of the buffer's first byte) | |
2322 | 52 // reader's pointers: |
2374 | 53 off_t read_filepos; |
2322 | 54 // commands/locking: |
2352 | 55 // int seek_lock; // 1 if we will seek/reset buffer, 2 if we are ready for cmd |
56 // int fifo_flag; // 1 if we should use FIFO to notice cache about buffer reads. | |
2322 | 57 // callback |
58 stream_t* stream; | |
59 } cache_vars_t; | |
60 | |
2352 | 61 static int min_fill=0; |
62 | |
63 int cache_fill_status=0; | |
2322 | 64 |
65 void cache_stats(cache_vars_t* s){ | |
66 int newb=s->max_filepos-s->read_filepos; // new bytes in the buffer | |
7472
c4434bdf6e51
tons of warning fixes, also some 10l bugfixes, including Dominik's PVA bug
arpi
parents:
7204
diff
changeset
|
67 printf("0x%06X [0x%06X] 0x%06X ",(int)s->min_filepos,(int)s->read_filepos,(int)s->max_filepos); |
2322 | 68 printf("%3d %% (%3d%%)\n",100*newb/s->buffer_size,100*min_fill/s->buffer_size); |
69 } | |
70 | |
71 int cache_read(cache_vars_t* s,unsigned char* buf,int size){ | |
72 int total=0; | |
73 while(size>0){ | |
74 int pos,newb,len; | |
2352 | 75 |
76 //printf("CACHE2_READ: 0x%X <= 0x%X <= 0x%X \n",s->min_filepos,s->read_filepos,s->max_filepos); | |
2322 | 77 |
2374 | 78 if(s->read_filepos>=s->max_filepos || s->read_filepos<s->min_filepos){ |
2352 | 79 // eof? |
80 if(s->eof) break; | |
81 // waiting for buffer fill... | |
10197 | 82 usec_sleep(READ_USLEEP_TIME); // 10ms |
2352 | 83 continue; // try again... |
84 } | |
85 | |
2374 | 86 newb=s->max_filepos-s->read_filepos; // new bytes in the buffer |
2322 | 87 if(newb<min_fill) min_fill=newb; // statistics... |
88 | |
89 // printf("*** newb: %d bytes ***\n",newb); | |
2352 | 90 |
91 pos=s->read_filepos - s->offset; | |
92 if(pos<0) pos+=s->buffer_size; else | |
93 if(pos>=s->buffer_size) pos-=s->buffer_size; | |
94 | |
2322 | 95 if(newb>s->buffer_size-pos) newb=s->buffer_size-pos; // handle wrap... |
96 if(newb>size) newb=size; | |
97 | |
2352 | 98 // check: |
2371 | 99 if(s->read_filepos<s->min_filepos) mp_msg(MSGT_CACHE,MSGL_ERR,"Ehh. s->read_filepos<s->min_filepos !!! Report bug...\n"); |
2352 | 100 |
2322 | 101 // len=write(mem,newb) |
102 //printf("Buffer read: %d bytes\n",newb); | |
103 memcpy(buf,&s->buffer[pos],newb); | |
104 buf+=newb; | |
2352 | 105 len=newb; |
2322 | 106 // ... |
107 | |
108 s->read_filepos+=len; | |
109 size-=len; | |
110 total+=len; | |
111 | |
112 } | |
2352 | 113 cache_fill_status=100*(s->max_filepos-s->read_filepos)/s->buffer_size; |
2322 | 114 return total; |
115 } | |
116 | |
117 int cache_fill(cache_vars_t* s){ | |
7472
c4434bdf6e51
tons of warning fixes, also some 10l bugfixes, including Dominik's PVA bug
arpi
parents:
7204
diff
changeset
|
118 int back,back2,newb,space,len,pos; |
2374 | 119 off_t read=s->read_filepos; |
2322 | 120 |
2352 | 121 if(read<s->min_filepos || read>s->max_filepos){ |
122 // seek... | |
2371 | 123 mp_msg(MSGT_CACHE,MSGL_DBG2,"Out of boundaries... seeking to 0x%X \n",read); |
8938
fc21a94f98c6
do not discard cache content at seeking type=STREAMTYPE_STREAM
arpi
parents:
7862
diff
changeset
|
124 // streaming: drop cache contents only if seeking backward or too much fwd: |
fc21a94f98c6
do not discard cache content at seeking type=STREAMTYPE_STREAM
arpi
parents:
7862
diff
changeset
|
125 if(s->stream->type!=STREAMTYPE_STREAM || |
16152
10a69a812eff
remove unused cache-prefill and create cache-seek-min that controls when seek_long is prefered over waiting for cache to fill
iive
parents:
12899
diff
changeset
|
126 read<s->min_filepos || read>=s->max_filepos+s->seek_limit) |
8938
fc21a94f98c6
do not discard cache content at seeking type=STREAMTYPE_STREAM
arpi
parents:
7862
diff
changeset
|
127 { |
fc21a94f98c6
do not discard cache content at seeking type=STREAMTYPE_STREAM
arpi
parents:
7862
diff
changeset
|
128 s->offset= // FIXME!? |
fc21a94f98c6
do not discard cache content at seeking type=STREAMTYPE_STREAM
arpi
parents:
7862
diff
changeset
|
129 s->min_filepos=s->max_filepos=read; // drop cache content :( |
fc21a94f98c6
do not discard cache content at seeking type=STREAMTYPE_STREAM
arpi
parents:
7862
diff
changeset
|
130 if(s->stream->eof) stream_reset(s->stream); |
fc21a94f98c6
do not discard cache content at seeking type=STREAMTYPE_STREAM
arpi
parents:
7862
diff
changeset
|
131 stream_seek(s->stream,read); |
fc21a94f98c6
do not discard cache content at seeking type=STREAMTYPE_STREAM
arpi
parents:
7862
diff
changeset
|
132 mp_msg(MSGT_CACHE,MSGL_DBG2,"Seek done. new pos: 0x%X \n",(int)stream_tell(s->stream)); |
fc21a94f98c6
do not discard cache content at seeking type=STREAMTYPE_STREAM
arpi
parents:
7862
diff
changeset
|
133 } |
2352 | 134 } |
135 | |
2322 | 136 // calc number of back-bytes: |
137 back=read - s->min_filepos; | |
138 if(back<0) back=0; // strange... | |
139 if(back>s->back_size) back=s->back_size; | |
140 | |
141 // calc number of new bytes: | |
142 newb=s->max_filepos - read; | |
143 if(newb<0) newb=0; // strange... | |
144 | |
145 // calc free buffer space: | |
146 space=s->buffer_size - (newb+back); | |
147 | |
148 // calc bufferpos: | |
149 pos=s->max_filepos - s->offset; | |
150 if(pos>=s->buffer_size) pos-=s->buffer_size; // wrap-around | |
151 | |
152 if(space<s->fill_limit){ | |
153 // printf("Buffer is full (%d bytes free, limit: %d)\n",space,s->fill_limit); | |
154 return 0; // no fill... | |
155 } | |
156 | |
157 // printf("### read=0x%X back=%d newb=%d space=%d pos=%d\n",read,back,newb,space,pos); | |
158 | |
159 // reduce space if needed: | |
160 if(space>s->buffer_size-pos) space=s->buffer_size-pos; | |
161 | |
162 // if(space>32768) space=32768; // limit one-time block size | |
163 if(space>4*s->sector_size) space=4*s->sector_size; | |
164 | |
2352 | 165 // if(s->seek_lock) return 0; // FIXME |
166 | |
167 #if 1 | |
168 // back+newb+space <= buffer_size | |
169 back2=s->buffer_size-(space+newb); // max back size | |
170 if(s->min_filepos<(read-back2)) s->min_filepos=read-back2; | |
171 #else | |
2322 | 172 s->min_filepos=read-back; // avoid seeking-back to temp area... |
2352 | 173 #endif |
2322 | 174 |
175 // .... | |
176 //printf("Buffer fill: %d bytes of %d\n",space,s->buffer_size); | |
177 //len=stream_fill_buffer(s->stream); | |
178 //memcpy(&s->buffer[pos],s->stream->buffer,len); // avoid this extra copy! | |
179 // .... | |
2348 | 180 len=stream_read(s->stream,&s->buffer[pos],space); |
181 if(!len) s->eof=1; | |
2322 | 182 |
183 s->max_filepos+=len; | |
184 if(pos+len>=s->buffer_size){ | |
185 // wrap... | |
186 s->offset+=s->buffer_size; | |
187 } | |
188 | |
189 return len; | |
190 | |
191 } | |
192 | |
193 cache_vars_t* cache_init(int size,int sector){ | |
194 int num; | |
10197 | 195 #ifndef WIN32 |
2322 | 196 cache_vars_t* s=shmem_alloc(sizeof(cache_vars_t)); |
10197 | 197 #else |
198 cache_vars_t* s=malloc(sizeof(cache_vars_t)); | |
199 #endif | |
12899 | 200 if(s==NULL) return NULL; |
201 | |
2322 | 202 memset(s,0,sizeof(cache_vars_t)); |
203 num=size/sector; | |
12835
4235ae5a2d60
cache min fill adjustment, based on patch by Jeremy Huddleston
iive
parents:
10272
diff
changeset
|
204 if(num < 16){ |
4235ae5a2d60
cache min fill adjustment, based on patch by Jeremy Huddleston
iive
parents:
10272
diff
changeset
|
205 num = 16; |
4235ae5a2d60
cache min fill adjustment, based on patch by Jeremy Huddleston
iive
parents:
10272
diff
changeset
|
206 }//32kb min_size |
2322 | 207 s->buffer_size=num*sector; |
208 s->sector_size=sector; | |
10197 | 209 #ifndef WIN32 |
2322 | 210 s->buffer=shmem_alloc(s->buffer_size); |
10197 | 211 #else |
212 s->buffer=malloc(s->buffer_size); | |
213 #endif | |
12899 | 214 |
215 if(s->buffer == NULL){ | |
216 #ifndef WIN32 | |
217 shmem_free(s,sizeof(cache_vars_t)); | |
218 #else | |
219 free(s); | |
220 #endif | |
221 return NULL; | |
222 } | |
223 | |
2322 | 224 s->fill_limit=8*sector; |
12835
4235ae5a2d60
cache min fill adjustment, based on patch by Jeremy Huddleston
iive
parents:
10272
diff
changeset
|
225 s->back_size=s->buffer_size/2; |
2322 | 226 return s; |
227 } | |
228 | |
9915 | 229 void cache_uninit(stream_t *s) { |
230 cache_vars_t* c = s->cache_data; | |
231 if(!s->cache_pid) return; | |
10197 | 232 #ifndef WIN32 |
9915 | 233 kill(s->cache_pid,SIGKILL); |
234 waitpid(s->cache_pid,NULL,0); | |
10197 | 235 #else |
236 TerminateThread((HANDLE)s->cache_pid,0); | |
237 free(c->stream); | |
238 #endif | |
9915 | 239 if(!c) return; |
10197 | 240 #ifndef WIN32 |
9915 | 241 shmem_free(c->buffer,c->buffer_size); |
242 shmem_free(s->cache_data,sizeof(cache_vars_t)); | |
10197 | 243 #else |
244 free(c->buffer); | |
245 free(s->cache_data); | |
246 #endif | |
9915 | 247 } |
248 | |
2322 | 249 static void exit_sighandler(int x){ |
250 // close stream | |
251 exit(0); | |
252 } | |
253 | |
16152
10a69a812eff
remove unused cache-prefill and create cache-seek-min that controls when seek_long is prefered over waiting for cache to fill
iive
parents:
12899
diff
changeset
|
254 int stream_enable_cache(stream_t *stream,int size,int min,int seek_limit){ |
3562 | 255 int ss=(stream->type==STREAMTYPE_VCD)?VCD_SECTOR_DATA:STREAM_BUFFER_SIZE; |
5991 | 256 cache_vars_t* s; |
7006
c0b490505298
disable cache if stream->fd<0 (no regular file/pipe but some special thing)
arpi
parents:
5991
diff
changeset
|
257 |
7204 | 258 if (stream->type==STREAMTYPE_STREAM && stream->fd < 0) { |
259 // The stream has no 'fd' behind it, so is non-cacheable | |
260 mp_msg(MSGT_CACHE,MSGL_STATUS,"\rThis stream is non-cacheable\n"); | |
261 return 1; | |
262 } | |
7006
c0b490505298
disable cache if stream->fd<0 (no regular file/pipe but some special thing)
arpi
parents:
5991
diff
changeset
|
263 |
5991 | 264 s=cache_init(size,ss); |
12899 | 265 if(s == NULL) return 0; |
3562 | 266 stream->cache_data=s; |
267 s->stream=stream; // callback | |
16152
10a69a812eff
remove unused cache-prefill and create cache-seek-min that controls when seek_long is prefered over waiting for cache to fill
iive
parents:
12899
diff
changeset
|
268 s->seek_limit=seek_limit; |
12835
4235ae5a2d60
cache min fill adjustment, based on patch by Jeremy Huddleston
iive
parents:
10272
diff
changeset
|
269 |
4235ae5a2d60
cache min fill adjustment, based on patch by Jeremy Huddleston
iive
parents:
10272
diff
changeset
|
270 |
4235ae5a2d60
cache min fill adjustment, based on patch by Jeremy Huddleston
iive
parents:
10272
diff
changeset
|
271 //make sure that we won't wait from cache_fill |
4235ae5a2d60
cache min fill adjustment, based on patch by Jeremy Huddleston
iive
parents:
10272
diff
changeset
|
272 //more data than it is alowed to fill |
16152
10a69a812eff
remove unused cache-prefill and create cache-seek-min that controls when seek_long is prefered over waiting for cache to fill
iive
parents:
12899
diff
changeset
|
273 if (s->seek_limit > s->buffer_size - s->fill_limit ){ |
10a69a812eff
remove unused cache-prefill and create cache-seek-min that controls when seek_long is prefered over waiting for cache to fill
iive
parents:
12899
diff
changeset
|
274 s->seek_limit = s->buffer_size - s->fill_limit; |
12835
4235ae5a2d60
cache min fill adjustment, based on patch by Jeremy Huddleston
iive
parents:
10272
diff
changeset
|
275 } |
4235ae5a2d60
cache min fill adjustment, based on patch by Jeremy Huddleston
iive
parents:
10272
diff
changeset
|
276 if (min > s->buffer_size - s->fill_limit) { |
4235ae5a2d60
cache min fill adjustment, based on patch by Jeremy Huddleston
iive
parents:
10272
diff
changeset
|
277 min = s->buffer_size - s->fill_limit; |
4235ae5a2d60
cache min fill adjustment, based on patch by Jeremy Huddleston
iive
parents:
10272
diff
changeset
|
278 } |
3562 | 279 |
10197 | 280 #ifndef WIN32 |
3562 | 281 if((stream->cache_pid=fork())){ |
10197 | 282 #else |
283 { | |
284 DWORD threadId; | |
285 stream_t* stream2=malloc(sizeof(stream_t)); | |
286 memcpy(stream2,s->stream,sizeof(stream_t)); | |
287 s->stream=stream2; | |
288 stream->cache_pid = CreateThread(NULL,0,ThreadProc,s,0,&threadId); | |
289 #endif | |
3562 | 290 // wait until cache is filled at least prefill_init % |
5931 | 291 mp_msg(MSGT_CACHE,MSGL_V,"CACHE_PRE_INIT: %d [%d] %d pre:%d eof:%d \n", |
3600 | 292 s->min_filepos,s->read_filepos,s->max_filepos,min,s->eof); |
3562 | 293 while(s->read_filepos<s->min_filepos || s->max_filepos-s->read_filepos<min){ |
16793
8d4fb5469efb
Make a few more messages translatable by moving them into help_mp-en.h.
diego
parents:
16750
diff
changeset
|
294 mp_msg(MSGT_CACHE,MSGL_STATUS,MSGTR_CacheFill, |
3600 | 295 100.0*(float)(s->max_filepos-s->read_filepos)/(float)(s->buffer_size), |
3562 | 296 s->max_filepos-s->read_filepos |
297 ); | |
298 if(s->eof) break; // file is smaller than prefill size | |
7862
013c255225d8
mpdemux.c|h moved to libinput, mpdemux_check_interrupt() -> mp_input_check_interrupt()
arpi
parents:
7472
diff
changeset
|
299 if(mp_input_check_interrupt(PREFILL_SLEEP_TIME)) |
4825
41d2da3bd082
Make blocking call in libmpdemux interuptable (only with new input,
albeu
parents:
3726
diff
changeset
|
300 return 0; |
3562 | 301 } |
16870 | 302 mp_msg(MSGT_CACHE,MSGL_STATUS,"\n"); |
4825
41d2da3bd082
Make blocking call in libmpdemux interuptable (only with new input,
albeu
parents:
3726
diff
changeset
|
303 return 1; // parent exits |
3562 | 304 } |
305 | |
10197 | 306 #ifdef WIN32 |
307 } | |
308 static DWORD WINAPI ThreadProc(void*s){ | |
309 #endif | |
310 | |
2322 | 311 // cache thread mainloop: |
312 signal(SIGTERM,exit_sighandler); // kill | |
313 while(1){ | |
10197 | 314 if(!cache_fill((cache_vars_t*)s)){ |
315 usec_sleep(FILL_USLEEP_TIME); // idle | |
2322 | 316 } |
2327 | 317 // cache_stats(s->cache_data); |
2322 | 318 } |
319 } | |
320 | |
321 int cache_stream_fill_buffer(stream_t *s){ | |
322 int len; | |
323 if(s->eof){ s->buf_pos=s->buf_len=0; return 0; } | |
324 if(!s->cache_pid) return stream_fill_buffer(s); | |
325 | |
2352 | 326 // cache_stats(s->cache_data); |
327 | |
2371 | 328 if(s->pos!=((cache_vars_t*)s->cache_data)->read_filepos) mp_msg(MSGT_CACHE,MSGL_ERR,"!!! read_filepos differs!!! report this bug...\n"); |
2327 | 329 |
2322 | 330 len=cache_read(s->cache_data,s->buffer, ((cache_vars_t*)s->cache_data)->sector_size); |
2352 | 331 //printf("cache_stream_fill_buffer->read -> %d\n",len); |
2327 | 332 |
2322 | 333 if(len<=0){ s->eof=1; s->buf_pos=s->buf_len=0; return 0; } |
334 s->buf_pos=0; | |
335 s->buf_len=len; | |
336 s->pos+=len; | |
337 // printf("[%d]",len);fflush(stdout); | |
338 return len; | |
339 | |
340 } | |
341 | |
2352 | 342 int cache_stream_seek_long(stream_t *stream,off_t pos){ |
343 cache_vars_t* s; | |
344 off_t newpos; | |
345 if(!stream->cache_pid) return stream_seek_long(stream,pos); | |
346 | |
347 s=stream->cache_data; | |
348 // s->seek_lock=1; | |
349 | |
2371 | 350 mp_msg(MSGT_CACHE,MSGL_DBG2,"CACHE2_SEEK: 0x%X <= 0x%X (0x%X) <= 0x%X \n",s->min_filepos,(int)pos,s->read_filepos,s->max_filepos); |
2322 | 351 |
2352 | 352 newpos=pos/s->sector_size; newpos*=s->sector_size; // align |
353 stream->pos=s->read_filepos=newpos; | |
354 s->eof=0; // !!!!!!! | |
355 | |
356 cache_stream_fill_buffer(stream); | |
2322 | 357 |
2352 | 358 pos-=newpos; |
359 if(pos>=0 && pos<=stream->buf_len){ | |
360 stream->buf_pos=pos; // byte position in sector | |
361 return 1; | |
362 } | |
363 | |
364 // stream->buf_pos=stream->buf_len=0; | |
365 // return 1; | |
366 | |
16750
0a31740dd5e6
Use PRI?64 defines as format strings for 64 bit variables.
reimar
parents:
16152
diff
changeset
|
367 mp_msg(MSGT_CACHE,MSGL_V,"cache_stream_seek: WARNING! Can't seek to 0x%"PRIX64" !\n",(int64_t)(pos+newpos)); |
2322 | 368 return 0; |
369 } | |
370 | |
371 #endif |