2012-11-22 15 views
12

मैं एक आईओएस एप्लिकेशन (मेरा पहला) बना रहा हूं जो वीडियो को अभी भी फ्लाई पर फ्रेम करता है। इसमें कूदने के लिए, मैंने ऐप्पल से example from the AV* documentation का पालन किया।AVCaptureDeviceOutput प्रतिनिधि विधि कैप्चर नहीं कर रहा है आउटपुट

प्रक्रिया में एक इनपुट (कैमरा) और आउटपुट स्थापित करना शामिल है। आउटपुट एक प्रतिनिधि के साथ काम करता है, जो इस मामले में नियंत्रक स्वयं होता है (यह आवश्यक विधि को अनुरूप और लागू करता है)।

मेरी समस्या यह है कि प्रतिनिधि विधि को कभी भी बुलाया नहीं जाता है। नीचे दिया गया कोड नियंत्रक का कार्यान्वयन है और इसमें कुछ एनएसएलॉग हैं। मैं "प्रारंभ" संदेश देख सकता हूं, लेकिन "प्रतिनिधि विधि" जिसे कभी नहीं दिखाया जाता है।

यह कोड सभी एक नियंत्रक के भीतर है जो "AVCaptureVideoDataOutputSampleBufferDelegate" प्रोटोकॉल लागू करता है।

- (void)viewDidLoad { 

    [super viewDidLoad]; 

    // Initialize AV session  
     AVCaptureSession *session = [AVCaptureSession new]; 

     if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) 
      [session setSessionPreset:AVCaptureSessionPreset640x480]; 
     else 
      [session setSessionPreset:AVCaptureSessionPresetPhoto]; 

    // Initialize back camera input 
     AVCaptureDevice *camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 

     NSError *error = nil; 

     AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:camera error:&error]; 

     if([session canAddInput:input]){ 
      [session addInput:input]; 
     } 


    // Initialize image output 
     AVCaptureVideoDataOutput *output = [AVCaptureVideoDataOutput new]; 

     NSDictionary *rgbOutputSettings = [NSDictionary dictionaryWithObject: 
              [NSNumber numberWithInt:kCMPixelFormat_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]; 
     [output setVideoSettings:rgbOutputSettings]; 
     [output setAlwaysDiscardsLateVideoFrames:YES]; // discard if the data output queue is blocked (as we process the still image) 


     //[output addObserver:self forKeyPath:@"capturingStillImage" options:NSKeyValueObservingOptionNew context:@"AVCaptureStillImageIsCapturingStillImageContext"]; 

     videoDataOutputQueue = dispatch_queue_create("VideoDataOutputQueue", DISPATCH_QUEUE_SERIAL); 
     [output setSampleBufferDelegate:self queue:videoDataOutputQueue]; 


     if([session canAddOutput:output]){ 
      [session addOutput:output]; 
     } 

     [[output connectionWithMediaType:AVMediaTypeVideo] setEnabled:YES]; 


    [session startRunning]; 

    NSLog(@"started"); 


} 


- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { 

     NSLog(@"delegate method called"); 

     CGImageRef cgImage = [self imageFromSampleBuffer:sampleBuffer]; 

     self.theImage.image = [UIImage imageWithCGImage: cgImage ]; 

     CGImageRelease(cgImage); 

} 

नोट: मैं एक लक्ष्य के रूप आईओएस 5.0 के साथ निर्माण कर रहा हूँ।

संपादित करें:

मैं एक question पाया है कि, हालांकि एक अलग समस्या का समाधान के लिए पूछ, क्या कर रही है वास्तव में क्या मेरे कोड करने के लिए माना जाता है। मैंने उस प्रश्न से कोड को रिक्त एक्सकोड ऐप में कॉपी किया है, कैप्चरऑटपुट फ़ंक्शन में NSLogs जोड़ा गया है और इसे कॉल नहीं किया जाता है। क्या यह एक विन्यास मुद्दा है? क्या मुझे कुछ याद आ रही है?

+2

यदि आपका सत्र चलने में कोई त्रुटि हो रही है (संभवतः जब से आपको कोई फ्रेम नहीं मिल रहा है) तो यह 'AVCaptureSessionRuntimeErrorNotification' अधिसूचना पोस्ट करेगा। '[[NSNotificationCenter defaultCenter] addObserver का उपयोग करके इसके लिए सुनो: चयनकर्ता: नाम: ऑब्जेक्ट:]; 'और जब आपका चयनकर्ता कहलाता है, तो त्रुटि देखने के लिए उपयोगकर्ता शब्दकोश से' AVCaptureSessionErrorKey 'प्राप्त करें। – lnafziger

+1

आपके इनपुट @Inafziger के लिए धन्यवाद। मैंने AVCaptureSessionRuntimeErrorNotification को संदेह किया लेकिन यह ट्रिगर नहीं लग रहा है: | – SuitedSloth

+0

व्यू कंट्रोलर किस तरह से बनाया गया है? आउटपुट प्राप्त 'शुरू' किया है? – Tommy

उत्तर

28

आपका session एक स्थानीय चर है। इसका दायरा viewDidLoad तक सीमित है। चूंकि यह एक नई परियोजना है, मुझे लगता है कि यह कहना सुरक्षित है कि आप एआरसी का उपयोग कर रहे हैं। उस स्थिति में वह वस्तु रिसाव नहीं होगी और इसलिए जीने के लिए जारी रहेगा क्योंकि यह लिंक किए गए प्रश्न में किया होगा, बल्कि संकलक यह सुनिश्चित करेगा कि ऑब्जेक्ट viewDidLoad निकास से पहले हटा दिया गया हो।

इसलिए आपका सत्र नहीं चल रहा है क्योंकि यह अब मौजूद नहीं है।

:

तो (एक तरफ के बाद से यह मुख्य कतार के एक UIKit कार्रवाई करता है self.theImage.image = ... असुरक्षित है तो आप शायद dispatch_async कि अधिक करने के लिए dispatch_get_main_queue() करना चाहते हैं), नमूना सुधार:

@implementation YourViewController 
{ 
    AVCaptureSession *session; 
} 

- (void)viewDidLoad { 

    [super viewDidLoad]; 

    // Initialize AV session  
     session = [AVCaptureSession new]; 

     if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) 
      [session setSessionPreset:AVCaptureSessionPreset640x480]; 
     else 
     /* ... etc ... */ 
} 


- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { 

     NSLog(@"delegate method called"); 

     CGImageRef cgImage = [self imageFromSampleBuffer:sampleBuffer]; 

     dispatch_sync(dispatch_get_main_queue(), 
     ^{ 
      self.theImage.image = [UIImage imageWithCGImage: cgImage ]; 
      CGImageRelease(cgImage); 
     }); 
} 

ज्यादातर लोग उदाहरण के वैरिएबल नामों की शुरुआत में अंडरस्कोर का उपयोग करके वकील आजकल मैंने इसे सादगी के लिए छोड़ा। आप यह सत्यापित करने के बाद कि निदान सही है, ठीक करने के लिए आप इसे ठीक करने के लिए एक्सकोड के निर्मित रेफैक्टर टूल का उपयोग कर सकते हैं।

मैंने मुख्य कतार में भेजे गए ब्लॉक के अंदर CGImageRelease स्थानांतरित किया ताकि यह सुनिश्चित किया जा सके कि इसका जीवनकाल UIImage में कैप्चर करने से परे हो। मैं किसी भी दस्तावेज़ को तुरंत पुष्टि करने में सक्षम नहीं हूं कि कोरफॉउंडेशन ऑब्जेक्ट्स को ब्लॉक में कैप्चर करते समय स्वचालित रूप से विस्तारित किया जाता है।

+0

आपको बहुत धन्यवाद सर, यह पूरी तरह से किया :) - यह नहीं किया एक सत्र परिवर्तनीय सत्र बनाने के परीक्षण के लिए मेरे पास नहीं होता है। बेशक, अब मैं स्क्वायरकैम को देखने के लिए वापस जाता हूं और यह निश्चित रूप से भी वहां है। मैंने इस मुद्दे से कई अन्य चीजें सीखी हैं, इसलिए यह सब बर्बाद नहीं था। एक बार फिर धन्यवाद! – SuitedSloth

+2

मैंने उस समाधान की कोशिश की और यह मेरे लिए काम नहीं किया। क्या आप मुझे कोई और अंतर्दृष्टि दे सकते हैं? – tuler

+1

@ टुलर मुझे एक और कारण मिला है कि 'didOutputSampleBuffer' प्रतिनिधि विधि क्यों नहीं कहा जा सकता है, नीचे मेरा जवाब देखें। http://stackoverflow.com/a/27704982/2979418 –

2

मेरे मामले में समस्या नहीं है, क्योंकि मैं

if ([_session canAddOutput:_videoDataOutput]) 
     [_session addOutput:_videoDataOutput]; 

फोन करने से पहले मैं

[_session startRunning]; 

फोन मैं सिर्फ फोन addOutput: के बाद startRunning

आशा है कि यह किसी को मदद देने लगेंगे रहा हूँ।

+0

@nbanic कृपया 'cuz' शब्द 'क्योंकि' शब्द को बदलने के लिए अपडेट _just_ को रोकना बंद करें, पोस्ट पर अन्य सुधार किए बिना। आपने अभी तक कई उत्तरों को संपादित किया है जो अन्य महत्वपूर्ण सुधारों के साथ कर सकते हैं। – doppelgreener

+1

@ जोनाथन हॉब्स संदेश प्राप्त हुआ, मैं इसके साथ रुक जाऊंगा। – nbanic

+9

सत्र शुरू करने के बाद addOutput क्यों कॉल करना होगा? – jgvb

16

मैंने पाया एक और कारण है कि didOutputSampleBuffer प्रतिनिधि विधि नहीं कहा जा सकता है - और प्राप्त नमूना बफर उत्पादन कनेक्शन दायर करने के लिए बचाने के लिए परस्पर अनन्य हैं। दूसरे शब्दों में, यदि आपके सत्र में पहले से ही AVCaptureMovieFileOutput है और फिर आप AVCaptureVideoDataOutput जोड़ते हैं, तो केवल AVCaptureFileOutputRecordingDelegate प्रतिनिधि विधियां कॉल की जाती हैं।

बस संदर्भ के लिए, मुझे AV Foundation फ्रेमवर्क दस्तावेज़ीकरण में इस सीमा के स्पष्ट विवरण में कहीं भी नहीं मिला, लेकिन ऐप्पल समर्थन ने कुछ साल पहले इसकी पुष्टि की, जैसा कि SO answer में उल्लेख किया गया है। समस्या को हल करने

एक तरह से didOutputSampleBuffer प्रतिनिधि विधि में फाइल करने के लिए पूरी तरह से AVCaptureMovieFileOutput दूर करने के लिए और मैन्युअल रूप से लिखना दर्ज की फ्रेम, अपने कस्टम बफर डाटा प्रोसेसिंग के साथ है। आपको thesetwo SO उपयोगी मिल सकता है।

संबंधित मुद्दे