2012-02-07 28 views
0

我發現了一個代碼樣本,可以訪問視頻文件的像素數據。我可以使用一些幫助來計算如何獲得每個像素的亮度(Y')值。謝謝!使用AVFoundation讀取視頻像素的亮度值(Y')

這裏是我的代碼:

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

      // 
      // Here's where you can process the buffer! 
      // (your code goes here) 
      // 
      // Finish processing the buffer! 
      // 

      // 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]; 
} 

回答

1

既然你問了kCVPixelFormatType_32BGRA,您的樣品將不會有亮度信息。您將不得不從BGR值計算它,或嘗試以YUV格式獲取樣本,例如kCVPixelFormatType_420YpCbCr8Planar。

更新:

如果你有一個YUV格式的平面,你的「baseAddress」變量將指向頂行的最左側像素的亮度值。 '寬度'和'高度'告訴你每行的像素數量和行數。

+0

好的 - 一旦我這樣做了,我怎樣才能從imageBuffer中獲得實際的亮度值? – 2012-02-07 20:12:50

+0

太好了。我如何穿過框架中的每個像素? – 2012-02-08 02:27:25

+0

這是怎麼回事? (uint y = 0; y 2012-02-08 05:43:52