2012-02-11 13 views
1

ローカルビデオファイルを処理しようとしていますが、単にピクセルデータの分析を行っています。何も出力されていません。現在のコードでは動画の各フレームを繰り返し処理していますが、実際には速度を上げるために一度に15フレームをスキップしたいと思います。フレームをデコードせずにスキップする方法はありますか?iOSでビデオを処理中にフレームをスキップ

Ffmpegでは、avcodec_decode_video2を呼び出さずに単にav_read_frameを呼び出すことができました。

ありがとうございます!ここに私の現在のコードは次のとおりです。

- (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);  

           NSString* key = (NSString*)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; 

      NSString* info = [NSString stringWithFormat:@"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 
{ 
    NSString* info = [NSString stringWithFormat:@"%@", message]; 

    [infoTextView setText:info]; 
} 
+0

解決方法を見つけましたか?私は同じことをしたいと思います。 – GuruMeditation

+0

いいえ - 決して行ったことはありません:-( –

答えて

1

あなたは(フレームごとではない)精度の低いフレーム処理をしたい場合は、AVAssetImageGeneratorを使用する必要があります。

このクラスは、指定した時間のフレームを返します。

具体的には、クリップの持続時間の間に0.5秒の差を入れた配列を作成します(30秒ごとに15フレームごとにiPhoneフィルムを約29.3 fpsで撮影する場合はiPhoneフィルムを返します)あなたのフレーム。

各フレームについて、要求した時間とフレームの実際の時間を見ることができます。これは、デフォルト値はあなたが尋ねた時から0.5秒の公差の周りにあるのですが、あなたはまた、プロパティを変更していることを変更することができます。

requestedTimeToleranceBeforerequestedTimeToleranceAfter

を私はあなたの質問、 幸運に答え願っています。

+0

ありがとうございましたOr.Ron。私は前にこれと遊んでいましたが、まだそれは比較的遅いようでした。 –

関連する問題