[vlc-commits] commit: VLCKit: Protect against file that takes forever to thumbnail. ( Pierre d'Herbemont )
git at videolan.org
git at videolan.org
Sat Sep 25 23:08:47 CEST 2010
vlc | branch: master | Pierre d'Herbemont <pdherbemont at free.fr> | Sat Sep 25 20:56:33 2010 +0200| [0381d38320edc33cd7bff46fa4adcb6236f5f7fa] | committer: Pierre d'Herbemont
VLCKit: Protect against file that takes forever to thumbnail.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=0381d38320edc33cd7bff46fa4adcb6236f5f7fa
---
.../framework/Headers/Public/VLCMediaThumbnailer.h | 4 +
.../macosx/framework/Sources/VLCMediaThumbnailer.m | 62 +++++++++++++++++---
2 files changed, 58 insertions(+), 8 deletions(-)
diff --git a/projects/macosx/framework/Headers/Public/VLCMediaThumbnailer.h b/projects/macosx/framework/Headers/Public/VLCMediaThumbnailer.h
index e27c344..a18b4fc 100644
--- a/projects/macosx/framework/Headers/Public/VLCMediaThumbnailer.h
+++ b/projects/macosx/framework/Headers/Public/VLCMediaThumbnailer.h
@@ -21,9 +21,12 @@
CGImageRef _thumbnail;
void *_data;
NSTimer *_parsingTimeoutTimer;
+ NSTimer *_thumbnailingTimeoutTimer;
CGFloat _thumbnailHeight,_thumbnailWidth;
CGFloat _effectiveThumbnailHeight,_effectiveThumbnailWidth;
+ int _numberOfReceivedFrames;
+ BOOL _shouldRejectFrames;
}
+ (VLCMediaThumbnailer *)thumbnailerWithMedia:(VLCMedia *)media andDelegate:(id<VLCMediaThumbnailerDelegate>)delegate;
@@ -52,5 +55,6 @@
@protocol VLCMediaThumbnailerDelegate
@required
+- (void)mediaThumbnailerDidTimeOut:(VLCMediaThumbnailer *)mediaThumbnailer;
- (void)mediaThumbnailer:(VLCMediaThumbnailer *)mediaThumbnailer didFinishThumbnail:(CGImageRef)thumbnail;
@end
diff --git a/projects/macosx/framework/Sources/VLCMediaThumbnailer.m b/projects/macosx/framework/Sources/VLCMediaThumbnailer.m
index 71ad3d1..133dfc9 100644
--- a/projects/macosx/framework/Sources/VLCMediaThumbnailer.m
+++ b/projects/macosx/framework/Sources/VLCMediaThumbnailer.m
@@ -18,6 +18,7 @@
- (void)fetchThumbnail;
- (void)startFetchingThumbnail;
@property (readonly, assign) void *dataPointer;
+ at property (readonly, assign) BOOL shouldRejectFrames;
@end
static void *lock(void *opaque, void **pixels)
@@ -42,7 +43,7 @@ void unlock(void *opaque, void *picture, void *const *p_pixels)
// We may already have a thumbnail if we are receiving picture after the first one.
// Just ignore.
- if ([thumbnailer thumbnail])
+ if ([thumbnailer thumbnail] || [thumbnailer shouldRejectFrames])
return;
[thumbnailer performSelectorOnMainThread:@selector(didFetchThumbnail) withObject:nil waitUntilDone:YES];
@@ -59,6 +60,7 @@ void display(void *opaque, void *picture)
@synthesize dataPointer=_data;
@synthesize thumbnailWidth=_thumbnailWidth;
@synthesize thumbnailHeight=_thumbnailHeight;
+ at synthesize shouldRejectFrames=_shouldRejectFrames;
+ (VLCMediaThumbnailer *)thumbnailerWithMedia:(VLCMedia *)media andDelegate:(id<VLCMediaThumbnailerDelegate>)delegate
{
@@ -70,6 +72,8 @@ void display(void *opaque, void *picture)
- (void)dealloc
{
+ NSAssert(!_thumbnailingTimeoutTimer, @"Timer not released");
+ NSAssert(!_parsingTimeoutTimer, @"Timer not released");
NSAssert(!_data, @"Data not released");
NSAssert(!_mp, @"Not properly retained");
if (_thumbnail)
@@ -101,6 +105,7 @@ void display(void *opaque, void *picture)
{
NSArray *tracks = [_media tracksInformation];
+
// Find the video track
NSDictionary *videoTrack = nil;
for (NSDictionary *track in tracks) {
@@ -129,11 +134,14 @@ void display(void *opaque, void *picture)
int newWidth = round(videoWidth * ratio);
int newHeight = round(videoHeight * ratio);
- NSLog(@"video %dx%d from %dx%d or %dx%d", newWidth, newHeight, videoWidth, videoHeight, imageWidth, imageHeight);
+
imageWidth = newWidth > 0 ? newWidth : imageWidth;
imageHeight = newHeight > 0 ? newHeight : imageHeight;
}
+ _numberOfReceivedFrames = 0;
+ NSAssert(!_shouldRejectFrames, @"Are we still running?");
+
_effectiveThumbnailHeight = imageHeight;
_effectiveThumbnailWidth = imageWidth;
@@ -150,6 +158,9 @@ void display(void *opaque, void *picture)
libvlc_video_set_callbacks(_mp, lock, unlock, display, self);
libvlc_media_player_play(_mp);
libvlc_media_player_set_position(_mp, kSnapshotPosition);
+
+ NSAssert(!_thumbnailingTimeoutTimer, @"We already have a timer around");
+ _thumbnailingTimeoutTimer = [[NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(mediaThumbnailingTimedOut) userInfo:nil repeats:NO] retain];
}
- (void)mediaParsingTimedOut
@@ -177,13 +188,21 @@ void display(void *opaque, void *picture)
- (void)didFetchThumbnail
{
+ if (_shouldRejectFrames)
+ return;
+
// The video thread is blocking on us. Beware not to do too much work.
+ _numberOfReceivedFrames++;
+
// Make sure we are getting the right frame
- if (libvlc_media_player_get_position(_mp) < kSnapshotPosition &&
+ if (libvlc_media_player_get_position(_mp) < kSnapshotPosition / 2 &&
// Arbitrary choice to work around broken files.
- libvlc_media_player_get_length(_mp) > 1000)
+ libvlc_media_player_get_length(_mp) > 1000 &&
+ _numberOfReceivedFrames < 10)
+ {
return;
+ }
NSAssert(_data, @"We have no data");
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
@@ -214,10 +233,8 @@ void display(void *opaque, void *picture)
[self performSelector:@selector(notifyDelegate) withObject:nil afterDelay:0];
}
-- (void)notifyDelegate
+- (void)stopAsync
{
- // Stop the media player
- NSAssert(_mp, @"We have already destroyed mp");
libvlc_media_player_stop(_mp);
libvlc_media_player_release(_mp);
_mp = NULL;
@@ -226,10 +243,39 @@ void display(void *opaque, void *picture)
free(_data);
_data = NULL;
+ _shouldRejectFrames = NO;
+}
+
+- (void)endThumbnailing
+{
+ _shouldRejectFrames = YES;
+
+ [_thumbnailingTimeoutTimer invalidate];
+ [_thumbnailingTimeoutTimer release];
+ _thumbnailingTimeoutTimer = nil;
+
+ // Stop the media player
+ NSAssert(_mp, @"We have already destroyed mp");
+
+ [self performSelectorInBackground:@selector(stopAsync) withObject:nil];
+
+ [self autorelease]; // Balancing -fetchThumbnail
+}
+
+- (void)notifyDelegate
+{
+ [self endThumbnailing];
+
// Call delegate
[_delegate mediaThumbnailer:self didFinishThumbnail:_thumbnail];
- [self release]; // Balancing -fetchThumbnail
}
+- (void)mediaThumbnailingTimedOut
+{
+ [self endThumbnailing];
+
+ // Call delegate
+ [_delegate mediaThumbnailerDidTimeOut:self];
+}
@end
More information about the vlc-commits
mailing list