2011-02-09 28 views
29

मैं वीडियो रिकॉर्ड करना चाहता हूं और एक ही समय में अपने कोड के साथ फ्रेम पकड़ना चाहता हूं।एक ही समय में AVCaptureVideoDataOutput और AVCaptureMovieFileOutput का उपयोग कर सकते हैं?

मैं वीडियो रिकॉर्डिंग के लिए AVCaptureVideoDataOutput हथियार फ्रेम और AVCaptureMovieFileOutput का उपयोग कर रहा हूं। लेकिन काम नहीं कर सकते हैं और एक ही समय पर काम करते समय त्रुटि कोड -12780 प्राप्त कर सकते हैं।

मैंने इस समस्या की खोज की लेकिन कोई जवाब नहीं मिला। क्या किसी के पास एक ही अनुभव है या समझाया गया है? यह मुझे थोड़ी देर के लिए वास्तव में परेशान करता है।

धन्यवाद।

+0

_ "वीडियो को सीधे AVCaptureMovieFileOutput के साथ फ़ाइल पर कब्जा कर लिया जा सकता है। हालांकि, इस वर्ग में कोई डिस्प्ले-सक्षम डेटा नहीं है और ** ** को AVCaptureVideoDataOutput के साथ ** एक साथ उपयोग नहीं किया जा सकता है।" _ यहां मिला: [link] (https: // developer.xamarin.com/api/type/MonoTouch.AVFoundation.AVCaptureSession/) .. समस्या के वास्तविक कारण को स्पष्ट करने के लिए – Csharpest

उत्तर

48

मैं विशिष्ट प्रश्न डाल उत्तर नहीं दे सकता है, लेकिन मैं सफलतापूर्वक वीडियो रिकॉर्डिंग कर रहे हैं और एक ही समय में फ्रेम हथियाने का उपयोग कर:

  • AVCaptureSession और AVCaptureVideoDataOutput मार्ग फ्रेम करने के लिए अपने खुद के कोड में
  • AVAssetWriter, AVAssetWriterInput और AVAssetWriterInputPixelBufferAdaptor एक 264 इनकोडिंग मूवी फाइल

कि ऑडियो की जांच के बिना है के लिए बाहर फ्रेम लिखने के लिए। मैं कैप्चर सत्र से CMSampleBuffers प्राप्त कर रहा हूं और फिर उन्हें पिक्सेल बफर एडाप्टर में दबा रहा हूं।

संपादित करें: तो मेरे कोड कम या ज्यादा की तरह दिखता है, बिट्स आप कोई समस्या नहीं के साथ खत्म हो गया स्किम्ड आ रही हैं, और गुंजाइश के मुद्दों की अनदेखी कर के साथ:

/* to ensure I'm given incoming CMSampleBuffers */ 
AVCaptureSession *captureSession = alloc and init, set your preferred preset/etc; 
AVCaptureDevice *captureDevice = default for video, probably; 

AVCaptureDeviceInput *deviceInput = input with device as above, 
            and attach it to the session; 

AVCaptureVideoDataOutput *output = output for 32BGRA pixel format, with me as the 
            delegate and a suitable dispatch queue affixed. 

/* to prepare for output; I'll output 640x480 in H.264, via an asset writer */ 
NSDictionary *outputSettings = 
    [NSDictionary dictionaryWithObjectsAndKeys: 

      [NSNumber numberWithInt:640], AVVideoWidthKey, 
      [NSNumber numberWithInt:480], AVVideoHeightKey, 
      AVVideoCodecH264, AVVideoCodecKey, 

      nil]; 

AVAssetWriterInput *assetWriterInput = [AVAssetWriterInput 
            assetWriterInputWithMediaType:AVMediaTypeVideo 
                outputSettings:outputSettings]; 

/* I'm going to push pixel buffers to it, so will need a 
    AVAssetWriterPixelBufferAdaptor, to expect the same 32BGRA input as I've 
    asked the AVCaptureVideDataOutput to supply */ 
AVAssetWriterInputPixelBufferAdaptor *pixelBufferAdaptor = 
      [[AVAssetWriterInputPixelBufferAdaptor alloc] 
       initWithAssetWriterInput:assetWriterInput 
       sourcePixelBufferAttributes: 
        [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithInt:kCVPixelFormatType_32BGRA], 
          kCVPixelBufferPixelFormatTypeKey, 
        nil]]; 

/* that's going to go somewhere, I imagine you've got the URL for that sorted, 
    so create a suitable asset writer; we'll put our H.264 within the normal 
    MPEG4 container */ 
AVAssetWriter *assetWriter = [[AVAssetWriter alloc] 
           initWithURL:URLFromSomwhere 
           fileType:AVFileTypeMPEG4 
           error:you need to check error conditions, 
             this example is too lazy]; 
[assetWriter addInput:assetWriterInput]; 

/* we need to warn the input to expect real time data incoming, so that it tries 
    to avoid being unavailable at inopportune moments */ 
assetWriterInput.expectsMediaDataInRealTime = YES; 

... eventually ... 

[assetWriter startWriting]; 
[assetWriter startSessionAtSourceTime:kCMTimeZero]; 
[captureSession startRunning]; 

... elsewhere ... 

- (void)  captureOutput:(AVCaptureOutput *)captureOutput 
    didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
      fromConnection:(AVCaptureConnection *)connection 
{ 
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 

    // a very dense way to keep track of the time at which this frame 
    // occurs relative to the output stream, but it's just an example! 
    static int64_t frameNumber = 0; 
    if(assetWriterInput.readyForMoreMediaData) 
     [pixelBufferAdaptor appendPixelBuffer:imageBuffer 
         withPresentationTime:CMTimeMake(frameNumber, 25)]; 
    frameNumber++; 
} 

... and, to stop, ensuring the output file is finished properly ... 

[captureSession stopRunning]; 
[assetWriter finishWriting]; 
+3

क्या आप ऐसा करने के लिए नमूना कोड पोस्ट करना चाहते हैं? आपका असली जीवन कर्म 10 गुना बढ़ जाएगा !!! : डी – SpaceDog

+8

ओह, कर्म शामिल है? फिर कुछ बहुत ही बुनियादी नमूना कोड जोड़ा गया है! – Tommy

+2

कोड के लिए धन्यवाद, मुझे छवियों के साथ काम करने के लिए मिला है। वीडियो, ध्वनि के लिए ध्वनि जोड़ने के बारे में क्या? –

1

यह टॉमी के जवाब की एक तेज संस्करण है ।

// Set up the Capture Session 
// Add the Inputs 
// Add the Outputs 


var outputSettings = [ 
    AVVideoWidthKey : Int(640), 
    AVVideoHeightKey : Int(480), 
    AVVideoCodecKey : .h264 
] 

    var assetWriterInput = AVAssetWriterInput(mediaType: AVMediaTypeVideo,outputSettings: outputSettings) 

    var pixelBufferAdaptor = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput, sourcePixelBufferAttributes: 
     [ kCVPixelBufferPixelFormatTypeKey : Int(kCVPixelFormatType_32BGRA)]) 


    var assetWriter = AVAssetWriter(url: URLFromSomwhere, fileType: AVFileTypeMPEG4 , error : Error) 
     assetWriter.addInput(assetWriterInput) 
     assetWriterInput.expectsMediaDataInRealTime = true 
     assetWriter.startWriting() 
     assetWriter.startSession(atSourceTime: kCMTimeZero) 

    captureSession.startRunning() 


    func captureOutput(_ captureOutput: AVCaptureOutput, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { 

    var imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) 
    // a very dense way to keep track of the time at which this frame 
    // occurs relative to the output stream, but it's just an example! 
    var frameNumber: Int64 = 0 

      if assetWriterInput.readyForMoreMediaData { 
    pixelBufferAdaptor.appendPixelBuffer(imageBuffer, withPresentationTime: CMTimeMake(frameNumber, 25)) 
       } 
       frameNumber += 1 } 

     captureSession.stopRunning() 
     assetWriter.finishWriting() 

हालांकि मुझे 100% सटीकता की गारंटी नहीं है, क्योंकि मैं तेज़ी से नया हूं।

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