2012-05-30 11 views
7

मैं एक आईओएस ऐप लिख रहा हूं जो नेटवर्क पर वीडियो और ऑडियो स्ट्रीम करता है।क्या मैं एएसी स्ट्रीम को स्मृति में एन्कोड करने के लिए AVCaptureSession का उपयोग कर सकता हूं?

मैं AVCaptureSession उपयोग कर रहा हूँ AVCaptureVideoDataOutput का उपयोग कर कच्चे वीडियो फ्रेम आकर्षित करने और उन्हें सॉफ्टवेयर using x264 में एन्कोड करने के लिए। यह बहुत अच्छा काम करता है।

मैं ऑडियो के लिए ऐसा करना चाहता था, केवल मुझे ऑडियो पक्ष पर इतना अधिक नियंत्रण की आवश्यकता नहीं है, इसलिए मैं एएसी स्ट्रीम बनाने के लिए निर्मित हार्डवेयर एन्कोडर का उपयोग करना चाहता था। इसका मतलब ऑडियो टूलबॉक्स परत से Audio Converter का उपयोग करना था।

- (void)captureOutput:(AVCaptureOutput *)captureOutput 
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
     fromConnection:(AVCaptureConnection *)connection 
{ 
    // get the audio samples into a common buffer _pcmBuffer 
    CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer); 
    CMBlockBufferGetDataPointer(blockBuffer, 0, NULL, &_pcmBufferSize, &_pcmBuffer); 

    // use AudioConverter to 
    UInt32 ouputPacketsCount = 1; 
    AudioBufferList bufferList; 
    bufferList.mNumberBuffers = 1; 
    bufferList.mBuffers[0].mNumberChannels = 1; 
    bufferList.mBuffers[0].mDataByteSize = sizeof(_aacBuffer); 
    bufferList.mBuffers[0].mData = _aacBuffer; 
    OSStatus st = AudioConverterFillComplexBuffer(_converter, converter_callback, (__bridge void *) self, &ouputPacketsCount, &bufferList, NULL); 
    if (0 == st) { 
     // ... send bufferList.mBuffers[0].mDataByteSize bytes from _aacBuffer... 
    } 
} 

इस मामले ऑडियो कनवर्टर के लिए कॉलबैक फ़ंक्शन बहुत सरल है (पैकेट आकार संभालने और मायने रखता है ठीक से सेट कर रहे हैं): ऐसा करने के लिए मैं AVCaptudeAudioDataOutput की ऑडियो फ्रेम के लिए कोई हैंडलर में डाल:

- (void) putPcmSamplesInBufferList:(AudioBufferList *)bufferList withCount:(UInt32 *)count 
{ 
    bufferList->mBuffers[0].mData = _pcmBuffer;   
    bufferList->mBuffers[0].mDataByteSize = _pcmBufferSize; 
} 

और ऑडियो कनवर्टर के लिए सेटअप इस तरह दिखता है:

{ 
    // ... 
    AudioStreamBasicDescription pcmASBD = {0}; 
    pcmASBD.mSampleRate = ((AVAudioSession *) [AVAudioSession sharedInstance]).currentHardwareSampleRate; 
    pcmASBD.mFormatID = kAudioFormatLinearPCM; 
    pcmASBD.mFormatFlags = kAudioFormatFlagsCanonical; 
    pcmASBD.mChannelsPerFrame = 1; 
    pcmASBD.mBytesPerFrame = sizeof(AudioSampleType); 
    pcmASBD.mFramesPerPacket = 1; 
    pcmASBD.mBytesPerPacket = pcmASBD.mBytesPerFrame * pcmASBD.mFramesPerPacket; 
    pcmASBD.mBitsPerChannel = 8 * pcmASBD.mBytesPerFrame; 

    AudioStreamBasicDescription aacASBD = {0}; 
    aacASBD.mFormatID = kAudioFormatMPEG4AAC; 
    aacASBD.mSampleRate = pcmASBD.mSampleRate; 
    aacASBD.mChannelsPerFrame = pcmASBD.mChannelsPerFrame; 
    size = sizeof(aacASBD); 
    AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &aacASBD); 

    AudioConverterNew(&pcmASBD, &aacASBD, &_converter); 
    // ... 
} 

यह बहुत सीधा लगता है केवल को आगे बढ़ाएं यह काम नहीं करता है। एक बार AVCaptureSession चल रहा है, ऑडियो कनवर्टर (विशेष रूप से AudioConverterFillComplexBuffer) एक 'hwiu' (उपयोग में हार्डवेयर) त्रुटि देता है। सत्र बंद होने पर रूपांतरण ठीक काम करता है लेकिन फिर मैं कुछ भी कैप्चर नहीं कर सकता ...

मैं सोच रहा था कि AVCaptureSession से एएसी स्ट्रीम प्राप्त करने का कोई तरीका है या नहीं। विकल्प पर विचार कर रहा हूँ कर रहे हैं:

  1. किसी तरह AVAssetWriterInput का उपयोग कर एएसी में ऑडियो नमूने एन्कोड करने के लिए और उसके बाद (नहीं AVAssetWriter के माध्यम से है, जो केवल एक फाइल करने के लिए लिखते थे) किसी भी तरह इनकोडिंग पैकेट मिलता है।

  2. मेरे ऐप को पुनर्गठित करना ताकि यह केवल वीडियो पक्ष पर AVCaptureSession का उपयोग करे और ऑडियो पक्ष पर Audio Queues का उपयोग करे। यह प्रवाह नियंत्रण (रिकॉर्डिंग शुरू करना और रोकना, बाधाओं का जवाब देना) अधिक जटिल होगा और मुझे डर है कि यह ऑडियो और वीडियो के बीच सिंकिंग समस्याओं का कारण बन सकता है। इसके अलावा, यह सिर्फ एक अच्छा डिजाइन की तरह प्रतीत नहीं होता है।

क्या किसी को पता है कि AVCaptureSession से एएसी प्राप्त करना संभव है? क्या मुझे यहां ऑडियो कतार का उपयोग करना है? क्या यह मुझे समस्याओं को सिंक करने या नियंत्रित करने में ला सकता है?

+0

क्या आप सुनिश्चित हैं कि आपका ऑडियो कनवर्टर बिल्कुल काम करता है? क्या आपने कुछ शून्यों को कैप्चर करने और एन्कोड करने की कोशिश की है? –

+0

हां, मैंने किया (मुझे लगता है कि मैंने इस सवाल में भी इसका उल्लेख किया है)। AVCaptureSession 'चल रहे' स्थिति में नहीं है तो एन्कोडर ठीक काम करता है। – Avner

+0

ओह, क्षमा करें। ऐसा लगता है कि आप एक बाध्य हैं। आपके कैप्चर सत्र में एक ऑडियो इनपुट जोड़ने से एएसी एन्कोडर को जोड़ना प्रतीत होता है। –

उत्तर

5

मैंने ऐप्पल से सलाह के लिए कहा कि यह पता चला है कि यदि आप एक भुगतान डेवलपर खाता है तो आप यह कर सकते हैं)।

ऐसा लगता है कि AVCaptureSession एएसी हार्डवेयर एन्कोडर की पकड़ पकड़ लेता है लेकिन केवल आपको फ़ाइल पर सीधे लिखने के लिए इसका उपयोग करने देता है।

आप सॉफ्टवेयर एनकोडर उपयोग कर सकते हैं, लेकिन आप AudioConverterNew यह विशेष रूप से के बजाय प्रयोग करने के लिए पूछने के लिए:

- (AudioClassDescription *)getAudioClassDescriptionWithType:(UInt32)type 
              fromManufacturer:(UInt32)manufacturer 
{ 
    static AudioClassDescription desc; 

    UInt32 encoderSpecifier = type; 
    OSStatus st; 

    UInt32 size; 
    st = AudioFormatGetPropertyInfo(kAudioFormatProperty_Encoders, 
            sizeof(encoderSpecifier), 
            &encoderSpecifier, 
            &size); 
    if (st) { 
     NSLog(@"error getting audio format propery info: %s", OSSTATUS(st)); 
     return nil; 
    } 

    unsigned int count = size/sizeof(AudioClassDescription); 
    AudioClassDescription descriptions[count]; 
    st = AudioFormatGetProperty(kAudioFormatProperty_Encoders, 
           sizeof(encoderSpecifier), 
           &encoderSpecifier, 
           &size, 
           descriptions); 
    if (st) { 
     NSLog(@"error getting audio format propery: %s", OSSTATUS(st)); 
     return nil; 
    } 

    for (unsigned int i = 0; i < count; i++) { 
     if ((type == descriptions[i].mSubType) && 
      (manufacturer == descriptions[i].mManufacturer)) { 
      memcpy(&desc, &(descriptions[i]), sizeof(desc)); 
      return &desc; 
     } 
    } 

    return nil; 
} 

सॉफ्टवेयर एनकोडर के साथ

AudioClassDescription *description = [self 
     getAudioClassDescriptionWithType:kAudioFormatMPEG4AAC 
         fromManufacturer:kAppleSoftwareAudioCodecManufacturer]; 
if (!description) { 
    return false; 
} 
// see the question as for setting up pcmASBD and arc ASBD 
OSStatus st = AudioConverterNewSpecific(&pcmASBD, &aacASBD, 1, description, &_converter); 
if (st) { 
    NSLog(@"error creating audio converter: %s", OSSTATUS(st)); 
    return false; 
} 

निश्चित रूप से CPU संसाधनों का समय लग जाएगा, लेकिन काम पूरा हो जाएगा।

+0

क्या आप रूपांतरण के लिए साथ कोड पोस्ट करना चाहते हैं? मुख्य रूप से कॉलबैक फ़ंक्शन कार्यान्वयन और _aacBuffer और _pcmBuffer परिभाषाएं। बहुत बहुत धन्यवाद। –

+0

मैं इसके लिए एक मैक समकक्ष की तलाश में हूं लेकिन मैक के लिए mmanufacturer नहीं मिला है। कोई विचार ? – Dinesh

+0

ऑडियो कनवर्टरफिल कॉम्प्लेक्सबफर में केवल एक त्रुटि आईफ़ोन में हो रही है। आईपैड में नहीं –

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

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