Ignorer les images lors du traitement de la video sur iOS

J'essaie de traiter un file video local et je fais simplement une parsing sur datatables de pixels. Rien n'est sorti. Mon code actuel parcourt chaque image de la video, mais je voudrais sauter environ 15 images à la fois pour accélérer les choses. Existe-t-il un moyen d'ignorer les images sans les décoder?

En Ffmpeg, je pourrais simplement appeler av_read_frame sans appeler avcodec_decode_video2.

Merci d'avance! Voici mon code actuel:

- (void) readMovie:(NSURL *)url { [self performSelectorOnMainThread:@selector(updateInfo:) withObject:@"scanning" waitUntilDone:YES]; startTime = [NSDate date]; AVURLAsset * asset = [AVURLAsset URLAssetWithURL:url options:nil]; [asset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:@"tracks"] completionHandler: ^{ dispatch_async(dispatch_get_main_queue(), ^{ AVAssetTrack * videoTrack = nil; NSArray * tracks = [asset tracksWithMediaType:AVMediaTypeVideo]; if ([tracks count] == 1) { videoTrack = [tracks objectAtIndex:0]; videoDuration = CMTimeGetSeconds([videoTrack timeRange].duration); NSError * error = nil; // _movieReader is a member variable _movieReader = [[AVAssetReader alloc] initWithAsset:asset error:&error]; if (error) NSLog(@"%@", error.localizedDescription); NSSsortingng* key = (NSSsortingng*)kCVPixelBufferPixelFormatTypeKey; NSNumber* value = [NSNumber numberWithUnsignedInt: kCVPixelFormatType_420YpCbCr8Planar]; NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key]; AVAssetReaderTrackOutput* output = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:videoTrack outputSettings:videoSettings]; output.alwaysCopiesSampleData = NO; [_movieReader addOutput:output]; if ([_movieReader startReading]) { NSLog(@"reading started"); [self readNextMovieFrame]; } else { NSLog(@"reading can't be started"); } } }); }]; } - (void) readNextMovieFrame { //NSLog(@"readNextMovieFrame called"); if (_movieReader.status == AVAssetReaderStatusReading) { //NSLog(@"status is reading"); AVAssetReaderTrackOutput * output = [_movieReader.outputs objectAtIndex:0]; CMSampleBufferRef sampleBuffer = [output copyNextSampleBuffer]; if (sampleBuffer) { // I'm guessing this is the expensive part that we can skip if we want to skip frames CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); // Lock the image buffer CVPixelBufferLockBaseAddress(imageBuffer,0); // Get information of the image uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer); size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); size_t width = CVPixelBufferGetWidth(imageBuffer); size_t height = CVPixelBufferGetHeight(imageBuffer); // do my pixel analysis // Unlock the image buffer CVPixelBufferUnlockBaseAddress(imageBuffer,0); CFRelease(sampleBuffer); [self readNextMovieFrame]; } else { NSLog(@"could not copy next sample buffer. status is %d", _movieReader.status); NSTimeInterval scanDuration = -[startTime timeIntervalSinceNow]; float scanMultiplier = videoDuration / scanDuration; NSSsortingng* info = [NSSsortingng ssortingngWithFormat:@"Done\n\nvideo duration: %f seconds\nscan duration: %f seconds\nmultiplier: %f", videoDuration, scanDuration, scanMultiplier]; [self performSelectorOnMainThread:@selector(updateInfo:) withObject:info waitUntilDone:YES]; } } else { NSLog(@"status is now %d", _movieReader.status); } } - (void) updateInfo: (id*)message { NSSsortingng* info = [NSSsortingng ssortingngWithFormat:@"%@", message]; [infoTextView setText:info]; } 

Si vous voulez un traitement de trame less précis (pas image par image), vous devez utiliser AVAssetImageGenerator .

Cette class renvoie un cadre pour une durée spécifiée que vous avez demandée.

Spécifiquement, construisez un tableau rempli de time entre la durée du clip avec une différence de 0.5s entre chaque fois (films iPhone à environ 29.3 fps si vous voulez que toutes les 15 images soient à peu près toutes les 30 secondes) et laissez le générateur d'images returnner vos images.

Pour chaque image, vous pouvez voir l'heure que vous avez demandée et l'heure réelle du cadre. Sa valeur par défaut est environ 0.5s de tolérance à partir du moment où vous avez demandé, mais vous pouvez également changer cela en changeant les propriétés:

requestedTimeToleranceBefore et requestedTimeToleranceAfter

J'espère avoir répondu à votre question, bonne chance.