2012-05-18 16 views
9

में बनावट, ओवरले या समान करने के लिए हार्डवेयर त्वरित एच .264 डिकोडिंग, क्या यह संभव है, और समर्थित है, आईओएस हार्डवेयर त्वरित एच.264 डीकोडिंग एपीआई का उपयोग स्थानीय (स्ट्रीम नहीं) वीडियो फ़ाइल को डीकोड करने के लिए, और फिर अन्य लिखें इसके ऊपर वस्तुओं?आईओएस

मैं एक ऐसा एप्लिकेशन बनाना चाहता हूं जिसमें वीडियो के सामने ग्राफिकल ऑब्जेक्ट्स ड्राइंग करना शामिल है, और वीडियो पर जो भी चल रहा है, उस पर सिंक्रनाइज़ करने के लिए प्लेबैक टाइमर का उपयोग करें। फिर, उपयोगकर्ता के कार्यों के आधार पर, जो मैं शीर्ष पर चित्रित कर रहा हूं उसे बदलें (लेकिन वीडियो नहीं)

एंड्रॉइड के लिए डायरेक्टएक्स, ओपनजीएल और ओपनजीएल ईएस से आ रहा है, मैं एक बनावट में वीडियो को प्रस्तुत करने और उपयोग करने जैसा कुछ चित्रित कर रहा हूं एक पूर्ण स्क्रीन क्वाड खींचने के लिए बनावट, फिर शेष वस्तुओं को आकर्षित करने के लिए अन्य sprites का उपयोग करें; या शायद रेंडरर से पहले एक इंटरमीडिएट फ़िल्टर लिखना, इसलिए मैं व्यक्तिगत आउटपुट फ्रेम में हेरफेर कर सकता हूं और अपनी सामग्री खींच सकता हूं; या शायद वीडियो के शीर्ष पर एक 2 डी परत के लिए ड्राइंग।

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

कृपया "यह आपके लिए बहुत उन्नत है, पहले दुनिया को आजमाएं" उत्तर से बचें। मैं अपनी सामग्री जानता हूं, और सिर्फ यह जानना चाहता हूं कि मैं क्या करना चाहता हूं (और सबसे महत्वपूर्ण रूप से, समर्थित है, इसलिए ऐप को अंततः अस्वीकार नहीं किया जाएगा), इससे पहले कि मैं अपने विवरणों का अध्ययन करूं।

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

मैं आईओएस विकास में जानकार नहीं हूँ, लेकिन पेशेवर Android के लिए डायरेक्ट, ओपन और OpenGL ES है। मैं वर्तमान में एक एंड्रॉइड एप्लिकेशन का आईओएस संस्करण बनाने पर विचार कर रहा हूं, और मैं सिर्फ यह जानना चाहता हूं कि यह संभव है या नहीं। यदि ऐसा है, तो मेरे पास स्क्रैच से आईओएस विकास शुरू करने के लिए पर्याप्त समय है, जो मैं करना चाहता हूं। यदि यह संभव नहीं है, तो मैं इस समय पूरे मंच का अध्ययन करने में समय नहीं लगाऊंगा।

इसलिए, यह एक तकनीकी व्यवहार्यता प्रश्न है। मैं कोड का अनुरोध नहीं कर रहा हूं। मैं इस प्रकार के उत्तरों की तलाश में हूं "हां, आप यह कर सकते हैं। बस ए और बी का उपयोग करें, डी में प्रस्तुत करने के लिए सी का उपयोग करें और ई के साथ अपनी सामग्री खींचें", या "नहीं, आप नहीं कर सकते। हार्डवेयर त्वरित डिकोडिंग है तीसरे पक्ष के अनुप्रयोगों के लिए उपलब्ध नहीं है "(जो एक दोस्त ने मुझे बताया)। बस यह, और मैं अपने रास्ते पर रहूंगा।

मैंने ios technology overview के पृष्ठ 32 में वीडियो तकनीकों के लिए अवलोकन पढ़ा है। यह काफी कहता है कि मैं सबसे आसान प्लेबैक कार्यक्षमता (जो मैं खोज रहा हूं) के लिए मीडिया प्लेयर का उपयोग नहीं कर सकता, यूआईकिट एम्बेडिंग पर थोड़ा अधिक नियंत्रण के साथ वीडियो एम्बेड करने के लिए, लेकिन वास्तविक प्लेबैक पर नहीं (मैं क्या नहीं ' मैं देख रहा हूं), प्लेबैक पर अधिक नियंत्रण के लिए AVFoundation (शायद मुझे जो चाहिए, लेकिन अधिकांश संसाधन मुझे कैमरे का उपयोग करने के बारे में ऑनलाइन बात करते हैं), या कोर मीडिया वीडियो पर पूर्ण निम्न स्तर का नियंत्रण रखने के लिए (शायद मैं क्या जरूरत है, लेकिन extremely poorly documented, और यहां तक ​​कि AVFoundation की तुलना में प्लेबैक पर संसाधनों में भी कमी है)।

मुझे चिंता है कि मैं अगले छह महीनों में आईओएस प्रोग्रामिंग पूर्णकालिक सीखने के लिए समर्पित कर सकता हूं, केवल अंत में यह पता लगाने के लिए कि प्रासंगिक एपीआई तीसरे पक्ष के डेवलपर्स के लिए उपलब्ध नहीं है, और मैं जो करना चाहता हूं वह आईट्यून्स के लिए अस्वीकार्य है स्टोर परिनियोजन। यही मेरे दोस्त ने मुझे बताया, लेकिन मुझे ऐप विकास दिशानिर्देशों में कुछ भी प्रासंगिक नहीं लग रहा है। इसलिए, मैं यहां उन लोगों से पूछने आया हूं जिनके पास इस क्षेत्र में अधिक अनुभव है, चाहे मैं क्या करना चाहता हूं या नहीं। अब और नहीं।

मैं इसे एक वैध उच्च स्तरीय प्रश्न मानता हूं, जिसे एक I-didn't-do-my-Homeework-plz-give-me-teh-codez प्रश्न के रूप में गलत समझा जा सकता है।अगर यहां मेरा निर्णय गलत था, तो इस प्रश्न को अपने दिल की अवमानना ​​को हटाने या हटाने के लिए स्वतंत्र महसूस करें।

+1

एसओ की सामग्री के आधार उत्तर प्रदान के बारे में है सवाल। अगर हम "नमस्ते दुनिया से शुरू" कहने लगे, तो हम यह कहेंगे। आपके प्रश्न के लिए, क्या आपने [AVComposition] (https://developer.apple.com/library/mac/documentation/AVFoundation/Reference/AVComposition_Class/Reference/Reference.html) पर एक नज़र डाली है? – CodaFi

उत्तर

24

हां, आप यह कर सकते हैं, और मुझे लगता है कि आपका प्रश्न यहां मौजूद होने के लिए पर्याप्त विशिष्ट था। आप अकेले नहीं हैं जो ऐसा करना चाहते हैं, और यह पता लगाने के लिए कि आप क्या कर सकते हैं और नहीं कर सकते हैं, यह थोड़ा खुदाई करता है।

एवी फाउंडेशन आपको AVAssetReader का उपयोग करके H.264 वीडियो के हार्डवेयर-त्वरित डिकोडिंग करने देता है, जिस बिंदु पर आपको बीजीआरए प्रारूप में वीडियो के कच्चे डीकोडेड फ्रेम दिए जाते हैं। इन्हें glTexImage2D() या आईओएस 5.0 में अधिक कुशल बनावट कैश का उपयोग करके बनावट पर अपलोड किया जा सकता है। वहां से, आप ओपनजीएल ES से फ्रेम को प्रदर्शित करने या पुनर्प्राप्त करने के लिए प्रक्रिया कर सकते हैं और परिणामों के हार्डवेयर-त्वरित एच .264 एन्कोडिंग करने के लिए AVAssetWriter का उपयोग कर सकते हैं। यह सब सार्वजनिक एपीआई का उपयोग करता है, इसलिए किसी भी समय आप किसी चीज़ के पास कहीं भी नहीं पहुंचते हैं जो ऐप स्टोर से अस्वीकार कर देगा।

हालांकि, आपको इसके अपने कार्यान्वयन को रोल करने की आवश्यकता नहीं है। मेरा बीएसडी-लाइसेंस प्राप्त ओपन सोर्स फ्रेमवर्क GPUImage इन परिचालनों को समाहित करता है और यह सब आपके लिए संभालता है। आप अपने इनपुट H.264 मूवी के लिए एक GPUImageMovie इंस्टेंस बनाते हैं, उस पर फ़िल्टर संलग्न करते हैं (जैसे ओवरले ब्लेंड या क्रोमो कीिंग ऑपरेशंस), और फिर इन फिल्टर को GPUImageView में डिस्प्ले और/या GPUImageMovieWriter को एच को फिर से एन्कोड करने के लिए संलग्न करें। संसाधित वीडियो से 264 फिल्म।

वर्तमान में एक मुद्दा यह है कि मैं प्लेबैक के लिए वीडियो में टाइमस्टैम्प का पालन नहीं करता हूं, इसलिए फिल्मों को फिल्म से डीकोड किए जाने पर फ्रेम को संसाधित किया जाता है। किसी वीडियो के फ़िल्टरिंग और पुनः-एन्कोडिंग के लिए, यह कोई समस्या नहीं है, क्योंकि टाइमस्टैम्प रिकॉर्डर के माध्यम से पारित होते हैं, लेकिन स्क्रीन पर सीधे डिस्प्ले के लिए इसका मतलब है कि वीडियो को 2-4X तक बढ़ाया जा सकता है । मैं किसी भी योगदान का स्वागत करता हूं जो आपको प्लेबैक दर को वास्तविक वीडियो टाइमस्टैम्प में सिंक्रनाइज़ करने देता है।

मैं वर्तमान में आईफोन 4 और 720 पी वीडियो पर ~ 20-25 एफपीएस पर 30 एफपीएस पर 640x480 वीडियो को वापस चला सकता हूं, फिल्टर कर सकता हूं और फिर से एन्कोड कर सकता हूं, आईफोन 4 एस 1080p फ़िल्टरिंग और एन्कोडिंग में महत्वपूर्ण रूप से सक्षम है 30 एफपीएस से अधिक। कुछ अधिक महंगी फिल्टर GPU कर सकते हैं और इसे धीमा कर सकते हैं, लेकिन अधिकांश फ़िल्टर इन फ़्रेमेट श्रेणियों में काम करते हैं।

आप चाहते हैं, तो आप यह कैसे OpenGL ES को यह अपलोडिंग करता है देखने के लिए GPUImageMovie वर्ग जांच कर सकते हैं, लेकिन प्रासंगिक कोड इस प्रकार है:

- (void)startProcessing; 
{ 
    NSDictionary *inputOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:AVURLAssetPreferPreciseDurationAndTimingKey]; 
    AVURLAsset *inputAsset = [[AVURLAsset alloc] initWithURL:self.url options:inputOptions]; 

    [inputAsset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:@"tracks"] completionHandler: ^{ 
     NSError *error = nil; 
     AVKeyValueStatus tracksStatus = [inputAsset statusOfValueForKey:@"tracks" error:&error]; 
     if (!tracksStatus == AVKeyValueStatusLoaded) 
     { 
      return; 
     } 
     reader = [AVAssetReader assetReaderWithAsset:inputAsset error:&error]; 

     NSMutableDictionary *outputSettings = [NSMutableDictionary dictionary]; 
     [outputSettings setObject: [NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey: (NSString*)kCVPixelBufferPixelFormatTypeKey]; 
     // Maybe set alwaysCopiesSampleData to NO on iOS 5.0 for faster video decoding 
     AVAssetReaderTrackOutput *readerVideoTrackOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:[[inputAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] outputSettings:outputSettings]; 
     [reader addOutput:readerVideoTrackOutput]; 

     NSArray *audioTracks = [inputAsset tracksWithMediaType:AVMediaTypeAudio]; 
     BOOL shouldRecordAudioTrack = (([audioTracks count] > 0) && (self.audioEncodingTarget != nil)); 
     AVAssetReaderTrackOutput *readerAudioTrackOutput = nil; 

     if (shouldRecordAudioTrack) 
     {    
      audioEncodingIsFinished = NO; 

      // This might need to be extended to handle movies with more than one audio track 
      AVAssetTrack* audioTrack = [audioTracks objectAtIndex:0]; 
      readerAudioTrackOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:audioTrack outputSettings:nil]; 
      [reader addOutput:readerAudioTrackOutput]; 
     } 

     if ([reader startReading] == NO) 
     { 
      NSLog(@"Error reading from file at URL: %@", self.url); 
      return; 
     } 

     if (synchronizedMovieWriter != nil) 
     { 
      __unsafe_unretained GPUImageMovie *weakSelf = self; 

      [synchronizedMovieWriter setVideoInputReadyCallback:^{ 
       [weakSelf readNextVideoFrameFromOutput:readerVideoTrackOutput]; 
      }]; 

      [synchronizedMovieWriter setAudioInputReadyCallback:^{ 
       [weakSelf readNextAudioSampleFromOutput:readerAudioTrackOutput]; 
      }]; 

      [synchronizedMovieWriter enableSynchronizationCallbacks]; 
     } 
     else 
     { 
      while (reader.status == AVAssetReaderStatusReading) 
      { 
       [self readNextVideoFrameFromOutput:readerVideoTrackOutput]; 

       if ((shouldRecordAudioTrack) && (!audioEncodingIsFinished)) 
       { 
        [self readNextAudioSampleFromOutput:readerAudioTrackOutput]; 
       } 

      }    

      if (reader.status == AVAssetWriterStatusCompleted) { 
       [self endProcessing]; 
      } 
     } 
    }]; 
} 

- (void)readNextVideoFrameFromOutput:(AVAssetReaderTrackOutput *)readerVideoTrackOutput; 
{ 
    if (reader.status == AVAssetReaderStatusReading) 
    { 
     CMSampleBufferRef sampleBufferRef = [readerVideoTrackOutput copyNextSampleBuffer]; 
     if (sampleBufferRef) 
     { 
      runOnMainQueueWithoutDeadlocking(^{ 
       [self processMovieFrame:sampleBufferRef]; 
      }); 

      CMSampleBufferInvalidate(sampleBufferRef); 
      CFRelease(sampleBufferRef); 
     } 
     else 
     { 
      videoEncodingIsFinished = YES; 
      [self endProcessing]; 
     } 
    } 
    else if (synchronizedMovieWriter != nil) 
    { 
     if (reader.status == AVAssetWriterStatusCompleted) 
     { 
      [self endProcessing]; 
     } 
    } 
} 

- (void)processMovieFrame:(CMSampleBufferRef)movieSampleBuffer; 
{ 
    CMTime currentSampleTime = CMSampleBufferGetOutputPresentationTimeStamp(movieSampleBuffer); 
    CVImageBufferRef movieFrame = CMSampleBufferGetImageBuffer(movieSampleBuffer); 

    int bufferHeight = CVPixelBufferGetHeight(movieFrame); 
    int bufferWidth = CVPixelBufferGetWidth(movieFrame); 

    CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); 

    if ([GPUImageOpenGLESContext supportsFastTextureUpload]) 
    { 
     CVPixelBufferLockBaseAddress(movieFrame, 0); 

     [GPUImageOpenGLESContext useImageProcessingContext]; 
     CVOpenGLESTextureRef texture = NULL; 
     CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, coreVideoTextureCache, movieFrame, NULL, GL_TEXTURE_2D, GL_RGBA, bufferWidth, bufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0, &texture); 

     if (!texture || err) { 
      NSLog(@"Movie CVOpenGLESTextureCacheCreateTextureFromImage failed (error: %d)", err); 
      return; 
     } 

     outputTexture = CVOpenGLESTextureGetName(texture); 
     //  glBindTexture(CVOpenGLESTextureGetTarget(texture), outputTexture); 
     glBindTexture(GL_TEXTURE_2D, outputTexture); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 

     for (id<GPUImageInput> currentTarget in targets) 
     {    
      NSInteger indexOfObject = [targets indexOfObject:currentTarget]; 
      NSInteger targetTextureIndex = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; 

      [currentTarget setInputSize:CGSizeMake(bufferWidth, bufferHeight) atIndex:targetTextureIndex]; 
      [currentTarget setInputTexture:outputTexture atIndex:targetTextureIndex]; 

      [currentTarget newFrameReadyAtTime:currentSampleTime]; 
     } 

     CVPixelBufferUnlockBaseAddress(movieFrame, 0); 

     // Flush the CVOpenGLESTexture cache and release the texture 
     CVOpenGLESTextureCacheFlush(coreVideoTextureCache, 0); 
     CFRelease(texture); 
     outputTexture = 0;   
    } 
    else 
    { 
     // Upload to texture 
     CVPixelBufferLockBaseAddress(movieFrame, 0); 

     glBindTexture(GL_TEXTURE_2D, outputTexture); 
     // Using BGRA extension to pull in video frame data directly 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bufferWidth, bufferHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, CVPixelBufferGetBaseAddress(movieFrame)); 

     CGSize currentSize = CGSizeMake(bufferWidth, bufferHeight); 
     for (id<GPUImageInput> currentTarget in targets) 
     { 
      NSInteger indexOfObject = [targets indexOfObject:currentTarget]; 
      NSInteger targetTextureIndex = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; 

      [currentTarget setInputSize:currentSize atIndex:targetTextureIndex]; 
      [currentTarget newFrameReadyAtTime:currentSampleTime]; 
     } 
     CVPixelBufferUnlockBaseAddress(movieFrame, 0); 
    } 

    if (_runBenchmark) 
    { 
     CFAbsoluteTime currentFrameTime = (CFAbsoluteTimeGetCurrent() - startTime); 
     NSLog(@"Current frame time : %f ms", 1000.0 * currentFrameTime); 
    } 
} 
+0

बहुत बहुत धन्यवाद। मैं इसके बारे में अपने दोस्त से पूछूंगा। मैंने http://stackoverflow.com/questions/4237538/is-it-possible-using-video-as-texture-for-gl-in-ios भी पाया, जो आप जो कर रहे हैं उसके समान ही लगता है। – user1003819

+0

@ user1003819 - उस मामले में, टॉमी वर्णन कर रहा है कि आने वाले वीडियो के जीपीयू को फ्रेम कैसे भेजना है, जिसे मैं उपरोक्त लिंकवर्क में भी संभालता हूं (वास्तव में, यह इसका प्राथमिक फोकस है)। आईओएस 5.0 में लाइव कैमरे के फ्रेम को अपलोड करने के लिए एक तेज़ तरीका है जो उसने वर्णन किया है, जो उसे पोस्ट करने के बाद बाहर आया था। फिर, इसके लिए कोड मेरे ओपन सोर्स फ्रेमवर्क में है। –

+0

ओह, आप सही हैं। मैं वास्तव में गलत सवाल से जुड़ा हुआ हूं। मेरा मतलब यह था: http://stackoverflow.com/questions/5621627/ios4-how-do-i-use-video-file-as-an-opengl-texture – user1003819

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

  • कोई संबंधित समस्या नहीं^_^