[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