2015-10-10 2 views
0

У меня есть следующий код, чтобы попытаться получить скриншот видеофайла из NSData. Я могу подтвердить, что NSData действительна и не равна нулю, но как dataString, так и movieURL возвращают нуль.Objective-C: Получение PNG Thumbnail из фильма с NSData

- (UIImage *)imageFromMovie:(NSData *)movieData { 

    // set up the movie player 
    NSString *dataString = [[NSString alloc] initWithData:movieData encoding:NSUTF8StringEncoding]; 
    NSURL *movieURL = [NSURL URLWithString:dataString]; 

    // get the thumbnail 
    AVURLAsset *asset1 = [[AVURLAsset alloc] initWithURL:movieURL options:nil]; 
    AVAssetImageGenerator *generate1 = [[AVAssetImageGenerator alloc] initWithAsset:asset1]; 
    generate1.appliesPreferredTrackTransform = YES; 
    NSError *err = NULL; 
    CMTime time = CMTimeMake(1, 2); 
    CGImageRef oneRef = [generate1 copyCGImageAtTime:time actualTime:NULL error:&err]; 
    UIImage *one = [[UIImage alloc] initWithCGImage:oneRef]; 

    return(one); 

} 

EDIT: Вот посмотрите, где/как я получаю NSData от UIImagePicker

if ([mediaType isEqualToString:@"ALAssetTypeVideo"]) { 

    ALAssetsLibrary *assetLibrary=[[ALAssetsLibrary alloc] init]; 
    [assetLibrary assetForURL:[[info objectAtIndex:x] valueForKey:UIImagePickerControllerReferenceURL] resultBlock:^(ALAsset *asset) { 

    ALAssetRepresentation *rep = [asset defaultRepresentation]; 

     unsigned long DataSize = (unsigned long)[rep size]; 
    Byte *buffer = (Byte*)malloc(DataSize); 
     NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:DataSize error:nil]; 

    //here’s the NSData 
    NSData *data = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES]; 



    } failureBlock:^(NSError *err) { 
      NSLog(@"Error: %@",[err localizedDescription]); 
     }]; 
} 
+0

Что такое MovieData? – user523234

+0

Как получить moviedata. –

+0

Можете ли вы добавить пример того, как выглядит содержимое фильма? Я думаю, что если вы NSLog, вы можете получить шестнадцатеричный дамп. NSURL ожидает полный URL-адрес, поэтому, если ваши исходные данные не включают схему или это просто путь, это не сработает. Аналогичным образом, если вы не избежали определенных символов в URL-адресе с% xx, он не сможет его принять.Поэтому убедитесь, что у вас есть правильный, канонический URL-адрес, а не только недопустимый, который Safari и NSURLComponents принимают из пользовательского ввода, потому что они хороши. – uliwitness

ответ

0

Возможно, у вас есть проблемы с кодировкой.

NSString метод экземпляра -(id)initWithData:data:encoding возвращает NIL, если данные не представляют действительные данные для кодирования. (https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/#//apple_ref/occ/instm/NSString/initWithData:encoding:)

Попробуйте использовать правильную кодировку в -(id)initWithData:data:encoding метода.

0

Вы пытаетесь преобразовать данные фильма в NSURL, поэтому вы получаете URL-адрес nil.

В своей реализации, вы можете получить эскиз следующим образом:

AVURLAsset *asset1 = [[AVURLAsset alloc] initWithURL:[[info objectAtIndex:x] valueForKey:UIImagePickerControllerReferenceURL] options:nil]; 
AVAssetImageGenerator *generate1   = [[AVAssetImageGenerator alloc] initWithAsset:asset1]; 
generate1.appliesPreferredTrackTransform = YES; 
NSError *err        = NULL; 
CMTime time        = CMTimeMake(1, 2); 
CGImageRef oneRef      = [generate1 copyCGImageAtTime:time actualTime:NULL error:&err]; 
UIImage *one        = [[UIImage alloc] initWithCGImage:oneRef]; 
+0

отправка ALAsset в AVAssetImageGenerator генерирует несовместимую ошибку указателя –

+0

@AdamG: Пожалуйста, проверьте мой обновленный ответ, мой mac не со мной прямо сейчас, проверит это и обновит мой ответ. Пожалуйста, дайте мне знать, работает ли это или нет. –

0

Скачать мой пример проекта, прежде чем читать этот ответ от:

https://drive.google.com/open?id=0B_exgT43OZJOWl9HMDJCR0cyTW8

Я знаю, что это было на самом деле долгое время с тех пор, как вы разместили этот вопрос; но, я нашел его, могу ответить на него и достаточно уверен, что, если вы не использовали образец кода, предоставленный веб-сайтом Apple Developer Connection, который делает то, что вы просите, вам все равно нужен ответ. Я основываю это исключительно на этом факте: трудно понять.

Тем не менее, у меня есть базовый рабочий проект, который касается вашего вопроса; однако, прежде чем смотреть на него, проверить видео, которое я сделал из него работает на моем iPhone 6с Plus:

<iframe width="640" height="360" src="https://www.youtube.com/embed/GiF-FFKvy5M?rel=0&amp;controls=0&amp;showinfo=0" frameborder="0" allowfullscreen></iframe>

Как вы можете видеть, плакат кадр для каждого актива в видео моего iPhone в коллекция отображается в UICollectionViewCell; в UICollectionViewController (или UICollectionView/источника данных делегата:

void (^renderThumbnail)(NSIndexPath *, CustomCell *) = ^(NSIndexPath *indexPath, CustomCell *cell) { 
[[PHImageManager defaultManager] requestAVAssetForVideo:AppDelegate.assetsFetchResults[indexPath.section] options:nil resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) { 
    cell.asset = [asset copy]; 
    cell.frameTime = [NSValue valueWithCMTime:kCMTimeZero]; 
}]; 
}; 

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 
    PHAsset *phAsset = AppDelegate.assetsFetchResults[indexPath.section]; 
    CustomCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellReuseIdentifier forIndexPath:indexPath]; 
    cell.representedAssetIdentifier = phAsset.localIdentifier; 
    CGFloat hue = (CGFloat)indexPath.section/5; 
    cell.backgroundColor = [UIColor colorWithHue:hue saturation:1.0f brightness:0.5f alpha:1.0f]; 

    if ([cell.representedAssetIdentifier isEqualToString:phAsset.localIdentifier]) { 
     NSPurgeableData *data = [self.thumbnailCache objectForKey:phAsset.localIdentifier]; 
     [data beginContentAccess]; 
     UIImage *image = [UIImage imageWithData:data]; 
     if (image != nil) { 
      cell.contentView.layer.contents = (__bridge id)image.CGImage; 
      NSLog(@"Cached image found"); 
     } else { 
      renderThumbnail(indexPath, cell); 
     } 
     [data endContentAccess]; 
     [data discardContentIfPossible]; 



    } 

    // Request an image for the asset from the PHCachingImageManager. 
    /*[AppDelegate.imageManager requestImageForAsset:phAsset 
    targetSize:cell.contentView.bounds.size 
    contentMode:PHImageContentModeAspectFill 
    options:nil 
    resultHandler:^(UIImage *result, NSDictionary *info) { 
    // Set the cell's thumbnail image if it's still showing the same asset. 
    if ([cell.representedAssetIdentifier isEqualToString:phAsset.localIdentifier]) { 
    cell.thumbnailImage = result; 
    } 
    }];*/ 

    return cell; 
} 

В подклассе UICollectionViewCell:

@implementation CustomCell 

- (void)prepareForReuse { 
    [super prepareForReuse]; 
    _asset = nil; 
    _frameTime = nil; 
    _thumbnailImage = nil; 
    [self.contentView.layer setContents:nil]; 
    [[self contentView] setContentMode:UIViewContentModeScaleAspectFit]; 
    [[self contentView] setClipsToBounds:YES]; 
} 

- (void)dealloc { 

} 

- (void)setAsset:(AVAsset *)asset { 
    _asset = asset; 
} 

- (void)setFrameTime:(NSValue *)frameTime { 
    _frameTime = frameTime; 
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0); 
    dispatch_async(concurrentQueue, ^{ 
     AVAssetImageGenerator *imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:_asset]; 
     imageGenerator.appliesPreferredTrackTransform = YES; 
     imageGenerator.requestedTimeToleranceAfter = kCMTimeZero; 
     imageGenerator.requestedTimeToleranceBefore = kCMTimeZero; 
      [imageGenerator generateCGImagesAsynchronouslyForTimes:@[frameTime] completionHandler:^(CMTime requestedTime, CGImageRef _Nullable image, CMTime actualTime, AVAssetImageGeneratorResult result, NSError * _Nullable error) { 
       dispatch_sync(dispatch_get_main_queue(), ^{ 
        self.thumbnailImage = [UIImage imageWithCGImage:image scale:25.0 orientation:UIImageOrientationUp]; 
       }); 
      }]; 
    }); 
} 

- (void)setThumbnailImage:(UIImage *)thumbnailImage { 
    _thumbnailImage = thumbnailImage; 
    self.contentView.layer.contents = (__bridge id)_thumbnailImage.CGImage; 
} 

@end 

В NSCache устанавливается следующим образом:

self.thumbnailCache = [[NSCache alloc] init]; 
    self.thumbnailCache.name = @"Thumbnail Cache"; 
    self.thumbnailCache.delegate = self; 
    self.thumbnailCache.evictsObjectsWithDiscardedContent = true; 
    self.thumbnailCache.countLimit = AppDelegate.assetsFetchResults.count; 

В PHAssets были приобретены это путь:

- (PHFetchResult *)assetsFetchResults { 
    __block PHFetchResult *i = self->_assetsFetchResults; 
    if (!i) { 
     static dispatch_once_t onceToken; 
     dispatch_once(&onceToken, ^{ 
      PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumVideos options:nil]; 
      self->_assetCollection = smartAlbums.firstObject; 
      if (![self->_assetCollection isKindOfClass:[PHAssetCollection class]]) self->_assetCollection = nil; 
      PHFetchOptions *allPhotosOptions = [[PHFetchOptions alloc] init]; 
      allPhotosOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]]; 
      i = [PHAsset fetchAssetsInAssetCollection:self->_assetCollection options:allPhotosOptions]; 
      self->_assetsFetchResults = i; 
     }); 
    } 

    return i; 
} 
Смежные вопросы