Mercurial > libdvdnav.hg
annotate read_cache.c @ 370:d80a041928be src
gettimeofday() doesn't exist on windows, but recent mingw32 runtime
include a replacement. The dvdnav replacement clashes with mingw32's
one.
This patch will check for it in configure.ac and define the private
function only if gettimeofday() is not defined.
Patch by Rafael Carr? (funman videolan org)
| author | nicodvb |
|---|---|
| date | Thu, 05 Jun 2008 08:45:35 +0000 |
| parents | 68736572c62c |
| children | 2e9382be8e25 |
| rev | line source |
|---|---|
| 105 | 1 /* |
| 0 | 2 * Copyright (C) 2000 Rich Wareham <richwareham@users.sourceforge.net> |
|
242
f794e1c17947
porting AMD64 patches from xine (provided by Goetz Waschk and Gwenole Beauchesne
mroi
parents:
230
diff
changeset
|
3 * 2001-2004 the dvdnav project |
| 105 | 4 * |
| 0 | 5 * This file is part of libdvdnav, a DVD navigation library. |
| 105 | 6 * |
| 0 | 7 * libdvdnav is free software; you can redistribute it and/or modify |
| 8 * it under the terms of the GNU General Public License as published by | |
| 9 * the Free Software Foundation; either version 2 of the License, or | |
| 10 * (at your option) any later version. | |
| 105 | 11 * |
| 0 | 12 * libdvdnav is distributed in the hope that it will be useful, |
| 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 * GNU General Public License for more details. | |
| 105 | 16 * |
| 0 | 17 * You should have received a copy of the GNU General Public License |
| 18 * along with this program; if not, write to the Free Software | |
| 19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | |
| 20 * | |
| 21 * $Id$ | |
| 22 * | |
| 23 */ | |
| 225 | 24 /* |
| 25 * There was a multithreaded read ahead cache in here for some time, but | |
| 26 * it had only been used for a short time. If you want to have a look at it, | |
| 27 * search the CVS attic. | |
| 28 */ | |
| 0 | 29 |
| 30 #ifdef HAVE_CONFIG_H | |
| 31 #include "config.h" | |
| 32 #endif | |
| 33 | |
| 278 | 34 #include <inttypes.h> |
|
288
ce4230602517
moved away from dvdnav_internal.h inclusion of various system headers
nicodvb
parents:
285
diff
changeset
|
35 #include <stdlib.h> |
|
294
2146ff691bcd
include limits.h; it was included in the previous dvdnav_internal.h and without it players segfault
nicodvb
parents:
290
diff
changeset
|
36 #include <limits.h> |
| 290 | 37 #include <sys/time.h> |
| 38 #include <time.h> | |
|
285
52877d182e96
moved all header inclusions from .h to .c files; my word, I've never seen such a horrible entanglement as in this mess
nicodvb
parents:
278
diff
changeset
|
39 #include "dvd_types.h" |
|
52877d182e96
moved all header inclusions from .h to .c files; my word, I've never seen such a horrible entanglement as in this mess
nicodvb
parents:
278
diff
changeset
|
40 #include "nav_types.h" |
|
52877d182e96
moved all header inclusions from .h to .c files; my word, I've never seen such a horrible entanglement as in this mess
nicodvb
parents:
278
diff
changeset
|
41 #include "ifo_types.h" |
|
52877d182e96
moved all header inclusions from .h to .c files; my word, I've never seen such a horrible entanglement as in this mess
nicodvb
parents:
278
diff
changeset
|
42 #include "remap.h" |
|
52877d182e96
moved all header inclusions from .h to .c files; my word, I've never seen such a horrible entanglement as in this mess
nicodvb
parents:
278
diff
changeset
|
43 #include "vm/decoder.h" |
|
52877d182e96
moved all header inclusions from .h to .c files; my word, I've never seen such a horrible entanglement as in this mess
nicodvb
parents:
278
diff
changeset
|
44 #include "vm/vm.h" |
|
34
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
45 #include "dvdnav.h" |
| 230 | 46 #include "dvdnav_internal.h" |
| 0 | 47 #include "read_cache.h" |
| 46 | 48 |
| 60 | 49 #define READ_CACHE_CHUNKS 10 |
| 50 | |
|
74
bf89c194f781
align read cache chunks in memory to allow use of raw devices
mroi
parents:
65
diff
changeset
|
51 /* all cache chunks must be memory aligned to allow use of raw devices */ |
|
bf89c194f781
align read cache chunks in memory to allow use of raw devices
mroi
parents:
65
diff
changeset
|
52 #define ALIGNMENT 2048 |
|
bf89c194f781
align read cache chunks in memory to allow use of raw devices
mroi
parents:
65
diff
changeset
|
53 |
| 105 | 54 #define READ_AHEAD_SIZE_MIN 4 |
| 55 #define READ_AHEAD_SIZE_MAX 512 | |
| 56 | |
| 60 | 57 typedef struct read_cache_chunk_s { |
| 58 uint8_t *cache_buffer; | |
|
74
bf89c194f781
align read cache chunks in memory to allow use of raw devices
mroi
parents:
65
diff
changeset
|
59 uint8_t *cache_buffer_base; /* used in malloc and free for alignment */ |
|
34
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
60 int32_t cache_start_sector; /* -1 means cache invalid */ |
|
103
8905d8de7e91
changes to read cache behaviour inspired by Thibaut Mattern:
mroi
parents:
76
diff
changeset
|
61 int32_t cache_read_count; /* this many sectors are already read */ |
|
8905d8de7e91
changes to read cache behaviour inspired by Thibaut Mattern:
mroi
parents:
76
diff
changeset
|
62 size_t cache_block_count; /* this many sectors will go in this chunk */ |
|
34
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
63 size_t cache_malloc_size; |
|
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
64 int cache_valid; |
| 60 | 65 int usage_count; /* counts how many buffers where issued from this chunk */ |
| 66 } read_cache_chunk_t; | |
| 67 | |
| 68 struct read_cache_s { | |
| 69 read_cache_chunk_t chunk[READ_CACHE_CHUNKS]; | |
| 70 int current; | |
| 71 int freeing; /* is set to one when we are about to dispose the cache */ | |
| 166 | 72 uint32_t read_ahead_size; |
| 105 | 73 int read_ahead_incr; |
| 74 int last_sector; | |
|
65
dcde6d9cea7a
ensure serialized access to the cache to avoid concurrent access on the
mroi
parents:
62
diff
changeset
|
75 pthread_mutex_t lock; |
|
34
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
76 |
|
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
77 /* Bit of strange cross-linking going on here :) -- Gotta love C :) */ |
| 60 | 78 dvdnav_t *dvd_self; |
|
34
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
79 }; |
|
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
80 |
| 105 | 81 /* |
| 76 | 82 #define READ_CACHE_TRACE 0 |
| 105 | 83 */ |
|
107
b2801805c433
include some fixes done in xine's copy to avoid merging conflicts
mroi
parents:
105
diff
changeset
|
84 |
|
b2801805c433
include some fixes done in xine's copy to avoid merging conflicts
mroi
parents:
105
diff
changeset
|
85 #ifdef __GNUC__ |
|
b2801805c433
include some fixes done in xine's copy to avoid merging conflicts
mroi
parents:
105
diff
changeset
|
86 # if READ_CACHE_TRACE |
| 114 | 87 # define dprintf(fmt, args...) fprintf(MSG_OUT, "libdvdnav: %s: "fmt, __func__ , ## args) |
|
107
b2801805c433
include some fixes done in xine's copy to avoid merging conflicts
mroi
parents:
105
diff
changeset
|
88 # else |
|
b2801805c433
include some fixes done in xine's copy to avoid merging conflicts
mroi
parents:
105
diff
changeset
|
89 # define dprintf(fmt, args...) /* Nowt */ |
|
b2801805c433
include some fixes done in xine's copy to avoid merging conflicts
mroi
parents:
105
diff
changeset
|
90 # endif |
|
41
50e0855a2017
Experimental multi-threaded cache now enabled by default so that it can get tested during change from 0.1.1 to 0.1.2
richwareham
parents:
40
diff
changeset
|
91 #else |
|
107
b2801805c433
include some fixes done in xine's copy to avoid merging conflicts
mroi
parents:
105
diff
changeset
|
92 # if READ_CACHE_TRACE |
| 114 | 93 # define dprintf(fmt, ...) fprintf(MSG_OUT, "libdvdnav: %s: "fmt, __func__ , __VA_ARGS__) |
|
107
b2801805c433
include some fixes done in xine's copy to avoid merging conflicts
mroi
parents:
105
diff
changeset
|
94 # else |
| 176 | 95 #ifdef _MSC_VER |
| 96 # define dprintf(fmt, str) /* Nowt */ | |
| 97 #else | |
|
107
b2801805c433
include some fixes done in xine's copy to avoid merging conflicts
mroi
parents:
105
diff
changeset
|
98 # define dprintf(fmt, ...) /* Nowt */ |
| 176 | 99 #endif /* _MSC_VER */ |
|
107
b2801805c433
include some fixes done in xine's copy to avoid merging conflicts
mroi
parents:
105
diff
changeset
|
100 # endif |
|
41
50e0855a2017
Experimental multi-threaded cache now enabled by default so that it can get tested during change from 0.1.1 to 0.1.2
richwareham
parents:
40
diff
changeset
|
101 #endif |
|
50e0855a2017
Experimental multi-threaded cache now enabled by default so that it can get tested during change from 0.1.1 to 0.1.2
richwareham
parents:
40
diff
changeset
|
102 |
|
40
a049c3753f32
Added some packaging patches from Philipp Matthias Hahn <pmhahn@titan.lahn.de> and an initial (non-working) multi-threaded read-ahead cache.
richwareham
parents:
37
diff
changeset
|
103 |
|
34
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
104 read_cache_t *dvdnav_read_cache_new(dvdnav_t* dvd_self) { |
| 60 | 105 read_cache_t *self; |
| 106 int i; | |
|
34
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
107 |
| 60 | 108 self = (read_cache_t *)malloc(sizeof(read_cache_t)); |
|
34
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
109 |
| 60 | 110 if(self) { |
| 111 self->current = 0; | |
| 112 self->freeing = 0; | |
| 113 self->dvd_self = dvd_self; | |
| 105 | 114 self->last_sector = 0; |
| 115 self->read_ahead_size = READ_AHEAD_SIZE_MIN; | |
| 116 self->read_ahead_incr = 0; | |
|
65
dcde6d9cea7a
ensure serialized access to the cache to avoid concurrent access on the
mroi
parents:
62
diff
changeset
|
117 pthread_mutex_init(&self->lock, NULL); |
| 60 | 118 dvdnav_read_cache_clear(self); |
| 119 for (i = 0; i < READ_CACHE_CHUNKS; i++) { | |
| 120 self->chunk[i].cache_buffer = NULL; | |
| 121 self->chunk[i].usage_count = 0; | |
| 122 } | |
|
34
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
123 } |
| 105 | 124 |
| 60 | 125 return self; |
|
34
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
126 } |
|
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
127 |
|
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
128 void dvdnav_read_cache_free(read_cache_t* self) { |
| 60 | 129 dvdnav_t *tmp; |
| 130 int i; | |
| 105 | 131 |
|
65
dcde6d9cea7a
ensure serialized access to the cache to avoid concurrent access on the
mroi
parents:
62
diff
changeset
|
132 pthread_mutex_lock(&self->lock); |
| 60 | 133 self->freeing = 1; |
| 134 for (i = 0; i < READ_CACHE_CHUNKS; i++) | |
| 135 if (self->chunk[i].cache_buffer && self->chunk[i].usage_count == 0) { | |
|
74
bf89c194f781
align read cache chunks in memory to allow use of raw devices
mroi
parents:
65
diff
changeset
|
136 free(self->chunk[i].cache_buffer_base); |
| 60 | 137 self->chunk[i].cache_buffer = NULL; |
| 138 } | |
|
65
dcde6d9cea7a
ensure serialized access to the cache to avoid concurrent access on the
mroi
parents:
62
diff
changeset
|
139 pthread_mutex_unlock(&self->lock); |
| 105 | 140 |
| 60 | 141 for (i = 0; i < READ_CACHE_CHUNKS; i++) |
| 142 if (self->chunk[i].cache_buffer) return; | |
|
34
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
143 |
| 60 | 144 /* all buffers returned, free everything */ |
| 145 tmp = self->dvd_self; | |
|
65
dcde6d9cea7a
ensure serialized access to the cache to avoid concurrent access on the
mroi
parents:
62
diff
changeset
|
146 pthread_mutex_destroy(&self->lock); |
|
34
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
147 free(self); |
| 60 | 148 free(tmp); |
|
34
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
149 } |
|
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
150 |
| 0 | 151 /* This function MUST be called whenever self->file changes. */ |
|
34
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
152 void dvdnav_read_cache_clear(read_cache_t *self) { |
| 60 | 153 int i; |
| 154 | |
| 0 | 155 if(!self) |
| 156 return; | |
| 105 | 157 |
|
65
dcde6d9cea7a
ensure serialized access to the cache to avoid concurrent access on the
mroi
parents:
62
diff
changeset
|
158 pthread_mutex_lock(&self->lock); |
|
dcde6d9cea7a
ensure serialized access to the cache to avoid concurrent access on the
mroi
parents:
62
diff
changeset
|
159 for (i = 0; i < READ_CACHE_CHUNKS; i++) |
| 60 | 160 self->chunk[i].cache_valid = 0; |
|
65
dcde6d9cea7a
ensure serialized access to the cache to avoid concurrent access on the
mroi
parents:
62
diff
changeset
|
161 pthread_mutex_unlock(&self->lock); |
| 0 | 162 } |
|
34
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
163 |
| 0 | 164 /* This function is called just after reading the NAV packet. */ |
|
34
1f29402ef2ef
'Objectified' the read-ahead cache in preparation to implement a 'proper' threaded cache a-la that recommended in the DVD Demystified book.
richwareham
parents:
3
diff
changeset
|
165 void dvdnav_pre_cache_blocks(read_cache_t *self, int sector, size_t block_count) { |
|
103
8905d8de7e91
changes to read cache behaviour inspired by Thibaut Mattern:
mroi
parents:
76
diff
changeset
|
166 int i, use; |
| 105 | 167 |
| 0 | 168 if(!self) |
| 60 | 169 return; |
| 105 | 170 |
| 60 | 171 if(!self->dvd_self->use_read_ahead) |
| 0 | 172 return; |
| 173 | |
|
65
dcde6d9cea7a
ensure serialized access to the cache to avoid concurrent access on the
mroi
parents:
62
diff
changeset
|
174 pthread_mutex_lock(&self->lock); |
| 105 | 175 |
| 60 | 176 /* find a free cache chunk that best fits the required size */ |
| 177 use = -1; | |
| 178 for (i = 0; i < READ_CACHE_CHUNKS; i++) | |
|
61
6b7520caf9a1
fix stupid bug: test if the buffer is there before using it
mroi
parents:
60
diff
changeset
|
179 if (self->chunk[i].usage_count == 0 && self->chunk[i].cache_buffer && |
|
6b7520caf9a1
fix stupid bug: test if the buffer is there before using it
mroi
parents:
60
diff
changeset
|
180 self->chunk[i].cache_malloc_size >= block_count && |
| 60 | 181 (use == -1 || self->chunk[use].cache_malloc_size > self->chunk[i].cache_malloc_size)) |
| 182 use = i; | |
| 105 | 183 |
| 60 | 184 if (use == -1) { |
| 185 /* we haven't found a cache chunk, so we try to reallocate an existing one */ | |
| 186 for (i = 0; i < READ_CACHE_CHUNKS; i++) | |
| 187 if (self->chunk[i].usage_count == 0 && self->chunk[i].cache_buffer && | |
| 188 (use == -1 || self->chunk[use].cache_malloc_size < self->chunk[i].cache_malloc_size)) | |
| 189 use = i; | |
| 190 if (use >= 0) { | |
|
74
bf89c194f781
align read cache chunks in memory to allow use of raw devices
mroi
parents:
65
diff
changeset
|
191 self->chunk[use].cache_buffer_base = realloc(self->chunk[use].cache_buffer_base, |
|
bf89c194f781
align read cache chunks in memory to allow use of raw devices
mroi
parents:
65
diff
changeset
|
192 block_count * DVD_VIDEO_LB_LEN + ALIGNMENT); |
|
bf89c194f781
align read cache chunks in memory to allow use of raw devices
mroi
parents:
65
diff
changeset
|
193 self->chunk[use].cache_buffer = |
|
242
f794e1c17947
porting AMD64 patches from xine (provided by Goetz Waschk and Gwenole Beauchesne
mroi
parents:
230
diff
changeset
|
194 (uint8_t *)(((uintptr_t)self->chunk[use].cache_buffer_base & ~((uintptr_t)(ALIGNMENT - 1))) + ALIGNMENT); |
| 60 | 195 dprintf("pre_cache DVD read realloc happened\n"); |
| 196 self->chunk[use].cache_malloc_size = block_count; | |
| 197 } else { | |
| 198 /* we still haven't found a cache chunk, let's allocate a new one */ | |
| 199 for (i = 0; i < READ_CACHE_CHUNKS; i++) | |
| 200 if (!self->chunk[i].cache_buffer) { | |
| 201 use = i; | |
| 202 break; | |
| 203 } | |
| 204 if (use >= 0) { | |
| 205 /* We start with a sensible figure for the first malloc of 500 blocks. | |
| 206 * Some DVDs I have seen venture to 450 blocks. | |
| 207 * This is so that fewer realloc's happen if at all. | |
| 105 | 208 */ |
|
74
bf89c194f781
align read cache chunks in memory to allow use of raw devices
mroi
parents:
65
diff
changeset
|
209 self->chunk[i].cache_buffer_base = |
|
bf89c194f781
align read cache chunks in memory to allow use of raw devices
mroi
parents:
65
diff
changeset
|
210 malloc((block_count > 500 ? block_count : 500) * DVD_VIDEO_LB_LEN + ALIGNMENT); |
|
bf89c194f781
align read cache chunks in memory to allow use of raw devices
mroi
parents:
65
diff
changeset
|
211 self->chunk[i].cache_buffer = |
|
242
f794e1c17947
porting AMD64 patches from xine (provided by Goetz Waschk and Gwenole Beauchesne
mroi
parents:
230
diff
changeset
|
212 (uint8_t *)(((uintptr_t)self->chunk[i].cache_buffer_base & ~((uintptr_t)(ALIGNMENT - 1))) + ALIGNMENT); |
| 60 | 213 self->chunk[i].cache_malloc_size = block_count > 500 ? block_count : 500; |
| 214 dprintf("pre_cache DVD read malloc %d blocks\n", | |
| 105 | 215 (block_count > 500 ? block_count : 500 )); |
| 0 | 216 } |
| 217 } | |
| 48 | 218 } |
| 105 | 219 |
| 60 | 220 if (use >= 0) { |
| 221 self->chunk[use].cache_start_sector = sector; | |
| 222 self->chunk[use].cache_block_count = block_count; | |
|
103
8905d8de7e91
changes to read cache behaviour inspired by Thibaut Mattern:
mroi
parents:
76
diff
changeset
|
223 self->chunk[use].cache_read_count = 0; |
|
8905d8de7e91
changes to read cache behaviour inspired by Thibaut Mattern:
mroi
parents:
76
diff
changeset
|
224 self->chunk[use].cache_valid = 1; |
| 60 | 225 self->current = use; |
| 105 | 226 } else { |
| 60 | 227 dprintf("pre_caching was impossible, no cache chunk available\n"); |
| 105 | 228 } |
|
65
dcde6d9cea7a
ensure serialized access to the cache to avoid concurrent access on the
mroi
parents:
62
diff
changeset
|
229 pthread_mutex_unlock(&self->lock); |
| 60 | 230 } |
| 231 | |
| 232 int dvdnav_read_cache_block(read_cache_t *self, int sector, size_t block_count, uint8_t **buf) { | |
| 233 int i, use; | |
| 105 | 234 int start; |
| 235 int size; | |
| 236 int incr; | |
| 237 uint8_t *read_ahead_buf; | |
| 238 int32_t res; | |
| 239 | |
| 60 | 240 if(!self) |
| 241 return 0; | |
| 105 | 242 |
| 60 | 243 use = -1; |
| 105 | 244 |
| 60 | 245 if(self->dvd_self->use_read_ahead) { |
| 246 /* first check, if sector is in current chunk */ | |
| 247 read_cache_chunk_t cur = self->chunk[self->current]; | |
| 248 if (cur.cache_valid && sector >= cur.cache_start_sector && | |
| 105 | 249 sector <= (cur.cache_start_sector + cur.cache_read_count) && |
| 60 | 250 sector + block_count <= cur.cache_start_sector + cur.cache_block_count) |
| 251 use = self->current; | |
| 252 else | |
| 253 for (i = 0; i < READ_CACHE_CHUNKS; i++) | |
| 105 | 254 if (self->chunk[i].cache_valid && |
| 255 sector >= self->chunk[i].cache_start_sector && | |
| 256 sector <= (self->chunk[i].cache_start_sector + self->chunk[i].cache_read_count) && | |
| 257 sector + block_count <= self->chunk[i].cache_start_sector + self->chunk[i].cache_block_count) | |
| 258 use = i; | |
| 60 | 259 } |
| 105 | 260 |
| 60 | 261 if (use >= 0) { |
| 108 | 262 read_cache_chunk_t *chunk; |
| 263 | |
| 105 | 264 /* Increment read-ahead size if sector follows the last sector */ |
| 265 if (sector == (self->last_sector + 1)) { | |
| 225 | 266 if (self->read_ahead_incr < READ_AHEAD_SIZE_MAX) |
| 267 self->read_ahead_incr++; | |
| 105 | 268 } else { |
| 269 self->read_ahead_size = READ_AHEAD_SIZE_MIN; | |
| 270 self->read_ahead_incr = 0; | |
| 271 } | |
| 272 self->last_sector = sector; | |
| 273 | |
| 274 /* The following resources need to be protected by a mutex : | |
| 275 * self->chunk[*].cache_buffer | |
| 276 * self->chunk[*].cache_malloc_size | |
| 277 * self->chunk[*].usage_count | |
| 278 */ | |
| 279 pthread_mutex_lock(&self->lock); | |
| 108 | 280 chunk = &self->chunk[use]; |
| 105 | 281 read_ahead_buf = chunk->cache_buffer + chunk->cache_read_count * DVD_VIDEO_LB_LEN; |
| 282 *buf = chunk->cache_buffer + (sector - chunk->cache_start_sector) * DVD_VIDEO_LB_LEN; | |
| 283 chunk->usage_count++; | |
| 284 pthread_mutex_unlock(&self->lock); | |
| 285 | |
| 225 | 286 dprintf("libdvdnav: sector=%d, start_sector=%d, last_sector=%d\n", sector, chunk->cache_start_sector, chunk->cache_start_sector + chunk->cache_block_count); |
| 105 | 287 |
| 225 | 288 /* read_ahead_size */ |
| 289 incr = self->read_ahead_incr >> 1; | |
| 290 if ((self->read_ahead_size + incr) > READ_AHEAD_SIZE_MAX) { | |
| 291 self->read_ahead_size = READ_AHEAD_SIZE_MAX; | |
| 292 } else { | |
| 293 self->read_ahead_size += incr; | |
| 294 } | |
| 105 | 295 |
| 225 | 296 /* real read size */ |
| 297 start = chunk->cache_start_sector + chunk->cache_read_count; | |
| 298 if (chunk->cache_read_count + self->read_ahead_size > chunk->cache_block_count) { | |
| 299 size = chunk->cache_block_count - chunk->cache_read_count; | |
| 300 } else { | |
| 301 size = self->read_ahead_size; | |
| 302 /* ensure that the sector we want will be read */ | |
| 303 if (sector >= chunk->cache_start_sector + chunk->cache_read_count + size) | |
| 304 size = sector - chunk->cache_start_sector - chunk->cache_read_count; | |
| 305 } | |
| 306 dprintf("libdvdnav: read_ahead_size=%d, size=%d\n", self->read_ahead_size, size); | |
| 105 | 307 |
| 225 | 308 if (size) |
| 105 | 309 chunk->cache_read_count += DVDReadBlocks(self->dvd_self->file, |
| 310 start, | |
| 311 size, | |
| 312 read_ahead_buf); | |
| 313 | |
| 314 res = DVD_VIDEO_LB_LEN * block_count; | |
| 315 | |
| 60 | 316 } else { |
| 105 | 317 |
| 60 | 318 if (self->dvd_self->use_read_ahead) |
| 319 dprintf("cache miss on sector %d\n", sector); | |
| 105 | 320 |
| 321 res = DVDReadBlocks(self->dvd_self->file, | |
| 322 sector, | |
| 323 block_count, | |
| 324 *buf) * DVD_VIDEO_LB_LEN; | |
| 60 | 325 } |
| 105 | 326 |
| 327 return res; | |
| 328 | |
| 60 | 329 } |
| 330 | |
| 331 dvdnav_status_t dvdnav_free_cache_block(dvdnav_t *self, unsigned char *buf) { | |
| 332 read_cache_t *cache; | |
| 333 int i; | |
| 105 | 334 |
| 60 | 335 if (!self) |
| 336 return DVDNAV_STATUS_ERR; | |
| 105 | 337 |
| 60 | 338 cache = self->cache; |
| 339 if (!cache) | |
| 340 return DVDNAV_STATUS_ERR; | |
| 105 | 341 |
|
65
dcde6d9cea7a
ensure serialized access to the cache to avoid concurrent access on the
mroi
parents:
62
diff
changeset
|
342 pthread_mutex_lock(&cache->lock); |
| 105 | 343 for (i = 0; i < READ_CACHE_CHUNKS; i++) { |
| 60 | 344 if (cache->chunk[i].cache_buffer && buf >= cache->chunk[i].cache_buffer && |
| 105 | 345 buf < cache->chunk[i].cache_buffer + cache->chunk[i].cache_malloc_size * DVD_VIDEO_LB_LEN) { |
| 60 | 346 cache->chunk[i].usage_count--; |
| 105 | 347 } |
| 348 } | |
|
65
dcde6d9cea7a
ensure serialized access to the cache to avoid concurrent access on the
mroi
parents:
62
diff
changeset
|
349 pthread_mutex_unlock(&cache->lock); |
|
dcde6d9cea7a
ensure serialized access to the cache to avoid concurrent access on the
mroi
parents:
62
diff
changeset
|
350 |
| 60 | 351 if (cache->freeing) |
| 352 /* when we want to dispose the cache, try freeing it now */ | |
| 353 dvdnav_read_cache_free(cache); | |
| 105 | 354 |
| 60 | 355 return DVDNAV_STATUS_OK; |
| 0 | 356 } |
