2013-05-31 37 views
5

Tôi đã xây dựng một số mã để xử lý các tệp video trên OSX, khung theo khung. Sau đây là một trích đoạn từ mã xây dựng OK, mở tệp, định vị bản nhạc video (chỉ theo dõi) và bắt đầu đọc CMSampleBuffers mà không gặp vấn đề gì. Tuy nhiên, mỗi CMSampleBufferRef tôi thu được trả về NULL khi tôi cố gắng trích xuất khung bộ đệm pixel. Không có dấu hiệu trong tài liệu iOS là lý do tại sao tôi có thể mong đợi một giá trị trả về NULL hoặc làm thế nào tôi có thể mong đợi để sửa chữa vấn đề. Nó xảy ra với tất cả các video mà tôi đã thử nghiệm nó, bất kể nguồn chụp hoặc CODEC.Tại sao CMSampleBufferGetImageBuffer trả về NULL

Bất kỳ trợ giúp nào được đánh giá cao.

NSString *assetInPath = @"/Users/Dave/Movies/movie.mp4"; 
NSURL *assetInUrl = [NSURL fileURLWithPath:assetInPath]; 
AVAsset *assetIn = [AVAsset assetWithURL:assetInUrl]; 

NSError *error; 
AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:assetIn error:&error]; 
AVAssetTrack *track = [assetIn.tracks objectAtIndex:0]; 
AVAssetReaderOutput *assetReaderOutput = [[AVAssetReaderTrackOutput alloc] 
               initWithTrack:track 
               outputSettings:nil]; 
[assetReader addOutput:assetReaderOutput]; 

// Start reading 
[assetReader startReading]; 

CMSampleBufferRef sampleBuffer; 
do { 
     sampleBuffer = [assetReaderOutput copyNextSampleBuffer]; 

     /** 
     ** At this point, sampleBuffer is non-null, has all appropriate attributes to indicate that 
     ** it's a video frame, 320x240 or whatever and looks perfectly fine. But the next 
     ** line always returns NULL without logging any obvious error message 
     **/ 

     CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 

     if(pixelBuffer != NULL) { 
      size_t width = CVPixelBufferGetWidth(pixelBuffer); 
      size_t height = CVPixelBufferGetHeight(pixelBuffer); 
      CVPixelBufferLockBaseAddress(pixelBuffer, 0); 
      ... 
      other processing removed here for clarity 
     } 
} while(...); 

Để rõ ràng, tôi đã xóa hết mã kiểm tra lỗi nhưng không có sự cố nào được chỉ ra trong mã đó. tức là Các AVAssetReader đang đọc, CMSampleBufferRef có vẻ tốt đẹp, vv

Trả lời

2

FWIW: Đây là những gì tài liệu chính thức nói cho giá trị trở lại của CMSampleBufferGetImageBuffer:.

"Kết quả là một CVImageBuffer dữ liệu phương tiện truyền thông Kết quả sẽ là NULL nếu CMSampleBuffer không chứa CVImageBuffer, hoặc nếu CMSampleBuffer chứa CMBlockBuffer, hoặc nếu có một số lỗi khác. "

Cũng lưu ý rằng người gọi không sở hữu bộ đệm dữ liệu trả về từ CMSampleBufferGetImageBuffer và phải giữ lại nó một cách rõ ràng nếu người gọi cần duy trì tham chiếu đến nó.

Hy vọng thông tin này sẽ hữu ích.

+0

Cảm ơn! Không quan tâm, bạn đã tìm thấy báo giá đó ở đâu? Bởi vì ở đây: https://developer.apple.com/library/mac/#documentation/CoreMedia/Reference/CMSampleBuffer/Reference/Reference.html và trong tài liệu được giải mã trong phiên bản XCode của tôi hoàn toàn không có bình luận nào cả! –

+0

Trong các tệp tiêu đề. Apple có một tài liệu rất chi tiết cho từng phương pháp.Trong xcode nhấp chuột phải vào tên phương thức trong mã của bạn và bấm vào 'đi đến định nghĩa' (Từ ngữ có thể không chính xác), và nó sẽ đưa bạn đến đúng định dạng .h và định nghĩa phương thức với tài liệu – Aki

+0

Doh! Tôi đoán tôi giả định rằng vì các tài liệu không có trong tài liệu được tạo ra mà chúng đã không tìm thấy; Cảm ơn một lần nữa Aki. –

9

Bạn chưa chỉ định bất kỳ outputSettings nào khi tạo AVAssetReaderTrackOutput. Tôi đã gặp sự cố khi chỉ định "nil" để nhận định dạng pixel gốc của bản nhạc video khi gọi số copyNextSampleBuffer. Trong ứng dụng của tôi, tôi muốn đảm bảo không có chuyển đổi nào xảy ra khi gọi copyNextSampleBuffer vì lợi ích của hiệu suất, nếu đây không phải là mối quan tâm lớn đối với bạn, hãy chỉ định định dạng pixel trong cài đặt đầu ra.

Sau đây là các định dạng điểm ảnh giới thiệu của Apple dựa trên khả năng phần cứng:

kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange kCVPixelFormatType_420YpCbCr8BiPlanarFullRange

+1

Câu trả lời này phải được chấp nhận vì bài đăng hiện được chấp nhận không giải quyết được gì. –

+1

@nenchev bạn đã giải quyết vấn đề như thế nào để đảm bảo không có chuyển đổi nào xảy ra? –

+0

@nenchev bạn đã giải quyết vấn đề như thế nào để đảm bảo không có chuyển đổi nào xảy ra? –

2

Bởi vì bạn đã không được cung cấp bất kỳ outputSettings bạn buộc phải sử dụng dữ liệu thô chứa trong khung.

Bạn có để có được bộ đệm khối từ bộ đệm mẫu sử dụng CMSampleBufferGetDataBuffer(sampleBuffer), sau khi bạn có mà bạn cần để có được vị trí thực tế của bộ đệm khối sử dụng

size_t blockBufferLength; char *blockBufferPointer; CMBlockBufferGetDataPointer(blockBuffer, 0, NULL, &blockBufferLength, &blockBufferPointer);

Nhìn vào *blockBufferPointer và giải mã byte sử dụng thông tin tiêu đề khung cho codec yêu cầu của bạn.

Các vấn đề liên quan