2011-06-05 17 views
29

से पढ़ने (स्ट्रीम) पढ़ने के लिए AVAssetReader का उपयोग करना मेरा मुख्य लक्ष्य सर्वर से वीडियो स्ट्रीम करना है, और स्ट्रीमिंग के दौरान फ्रेम द्वारा फ्रेम को काटना है (ताकि इसे ओपनजीएल द्वारा उपयोग किया जा सके)। कि के लिए, मैं इस कोड है कि मैं इंटरनेट पर हर जगह पाए का उपयोग किया है (यह एप्पल के GLVideoFrame नमूना कोड से था, जैसा कि मुझे याद है):रिमोट एसेट

NSArray * tracks = [asset tracks]; 
NSLog(@"%d", tracks.count); 

for(AVAssetTrack* track in tracks) { 

    NSLog(@"type: %@", [track mediaType]); 

    initialFPS = track.nominalFrameRate; 
    width = (GLuint)track.naturalSize.width; 
    height = (GLuint)track.naturalSize.height; 


    NSError * error = nil; 

    // _movieReader is a member variable 
    @try { 
     self._movieReader = [[[AVAssetReader alloc] initWithAsset:asset error:&error] autorelease]; 
    } 
    @catch (NSException *exception) { 
     NSLog(@"%@ -- %@", [exception name], [exception reason]); 
     NSLog(@"skipping track"); 

     continue; 
    } 


    if (error) 
    { 
     NSLog(@"CODE:%d\nDOMAIN:%@\nDESCRIPTION:%@\nFAILURE_REASON:%@", [error code], [error domain], error.localizedDescription, [error localizedFailureReason]);           
     continue; 
    } 

    NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey; 
    NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA]; 
    NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key]; 
    [_movieReader addOutput:[AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track 
                     outputSettings:videoSettings]]; 
    [_movieReader startReading]; 
    [self performSelectorOnMainThread:@selector(frameStarter) withObject:nil waitUntilDone:NO]; 
} 

लेकिन मैं हमेशा [[AVAssetReader alloc] initWithAsset:error:] में इस अपवाद मिलता है।

NSInvalidArgumentException -- *** -[AVAssetReader initWithAsset:error:] Cannot initialize an instance of AVAssetReader with an asset at non-local URL 'http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8' 

तो मेरे दो प्रश्न हैं:

  1. अपवाद वास्तव में मुझे बता कि AVAssetReader एक स्थानीय URL होना आवश्यक है? क्या इसका उपयोग स्ट्रीमिंग के लिए किया जा सकता है (बस बाकी AVFoundation कक्षाओं की तरह)?
  2. यदि AVFoundation दृष्टिकोण काम नहीं करेगा, तो वीडियो स्ट्रीम करने और एक ही समय में अपने फ्रेम को विभाजित करने के लिए अन्य सुझाव क्या हैं?

आपकी मदद के लिए बहुत बहुत धन्यवाद।

+1

यहाँ एक ऐसी ही समस्या मिल गया है उस के साथ बहुत अच्छी तरह से काम नहीं करता है सकते हैं।हालांकि, मेरे मामले में, अपवाद प्राप्त करने के बजाय, AVAssetReader बस प्रारंभ करने से इंकार कर देता है, और 'अज्ञात त्रुटि' (AVFoundationErrorDomain -11800) फेंकता है। मैंने वीडियो ट्रैक को लेने की कोशिश की है, इसे एक नए AVMutableComposition और संबंधित AVMutableCompositionTrack को खिलाया है, और उसके बाद से AVAssetReader बनाने का प्रयास किया है। यह या तो काम नहीं करता है। संपादित करें: बीटीडब्ल्यू, वह दृष्टिकोण स्थानीय एमपी 4/mov फ़ाइलों के लिए काम करता है। –

+0

आईओएस में कुछ नया एपीआई है जो आपको अपने अंतिम लक्ष्य तक पहुंचने में मदद करेगी। Http://stackoverflow.com/questions/12500408/can-i-use-avfoundation-to-stream-downloaded-video-frames-into-an-opengl-es-textu/12500409#12500409 –

उत्तर

35

@ कोकोनेटिक्स, मैं कम प्रतिनिधि के कारण टिप्पणी करने में असमर्थ हूं। लेकिन आपने जो कहा है वह पूरी तरह से सही नहीं लगता है। AVFoundation स्थानीय और गैर-स्थानीय फ़ाइलों के बीच उतना अंतर नहीं लग रहा है, क्योंकि यह फ़ाइलों या प्रोटोकॉल के उपयोग के बीच करता है। MP3/mov के बनाम m3u8 के माध्यम से HTTP लाइव स्ट्रीमिंग प्रोटोकॉल का उपयोग कर एक बहुत स्पष्ट अंतर है, लेकिन स्थानीय या दूरस्थ एमपी 4 का उपयोग करने वाले मतभेद थोड़ा अस्पष्ट हैं।

ऊपर पर विस्तार करने के लिए:

क) यदि आपका 'दूरस्थ' परिसंपत्ति एक M3U8 (जो है, आप HTTP स्ट्रीमिंग का उपयोग कर रहे 'जी') है, तो कोई मौका नहीं जो भी। इससे कोई फर्क नहीं पड़ता कि एम 3 यू 8 आपके स्थानीय फाइल सिस्टम या रिमोट सर्वर पर है, कई कारणों से AVAssetReader और सभी AVAsset- संबद्ध कार्यक्षमता बस काम नहीं करती है। However, AVPlayer, AVPlayerItem etc would work just fine.

बी) यदि यह एमपी 4/एमओवी है, तो थोड़ी और जांच की वजह है। Local MP4/MOV's work flawlessly. रिमोट एमपी 4/एमओवी के मामले में, मैं एक AVPlayerItem या AVPlayer या AVAssetTracks से एक पुनर्प्राप्ति (या पुनर्प्राप्त करने में सक्षम हूं) एक AVURLASSet जिसके साथ मैं कभी-कभी AVAssetReader को सफलतापूर्वक प्रारंभ करने में सक्षम हूं (मैं कभी-कभी ' 'साथ ही, जल्द ही)। हालांकि, copyNextSampleBuffer always returns nil in case of remote MP4's

i) copyNextSampleBuffer दूरस्थ mp4 के लिए काम नहीं कर, अन्य सभी चरणों का सफल होने के बाद, है इरादा/उम्मीद: copyNextSampleBuffer काम लागू की बात तक कई चीजें के बाद से, मैं 100% यकीन है कि अगर नहीं कर रहा हूँ कार्यक्षमता।

ii) रिमोट एमपी 4 के लिए 'अन्य कदम' काम करने लगते हैं, यह ऐप्पल के कार्यान्वयन का दुर्घटना है, और जब हम कॉपी NextSampleBuffer को दबाते हैं तो यह असंगतता सामने आ रही है .......... .... ये 'अन्य कदम' क्या हैं, मैं जल्द ही विस्तार से बताऊंगा।

iii) दूरस्थ MP4 के लिए copyNextSampleBuffer को आमंत्रित करने का प्रयास करते समय मैं कुछ गलत कर रहा हूं।

तो @Paula आप जांच करने के लिए दूरदराज के MOV/MP4 के साथ थोड़ा और आगे की कोशिश कर सकते।

संदर्भ के लिए, दृष्टिकोण मैं वीडियो से एक फ्रेम पर कब्जा करने के लिए करने की कोशिश की हैं:

एक)

वीडियो URL से सीधे एक AVURLAsset बनाएँ।

का उपयोग कर वीडियो ट्रैक पुनर्प्राप्त [संपत्ति tracksWithMediaType: AVMediaTypeVideo]

स्रोत के रूप में वीडियो ट्रैक का उपयोग कर एक AVAssetReaderTrackOutput तैयार करें।

AVURLASSet का उपयोग करके एक AVAssetReader बनाएं।

AVAssetReader और startReading को AVAssetReaderTrackOutput जोड़ें।

copyNextSampleBuffer का उपयोग कर छवियों को पुनर्प्राप्त करें।

ख)

वीडियो URL से एक AVPlayerItem बनाएं, और फिर इसे से एक AVPlayer (या URL से सीधे AVPlayer बनाएँ)।

AVPlayer की 'संपत्ति' संपत्ति को पुनः प्राप्त और उसके 'पटरियों' का उपयोग करके लोड "loadValuesAsynchronouslyForKeys:"।

एवीएमडिया टाइप टाइप (या बस ट्रैक ट्रैक करेंथिडियाडिया टाइप: ट्रैक पर लोड होने के बाद संपत्ति पर) ट्रैक को अलग करें, और वीडियो ट्रैक का उपयोग करके अपना AVAssetReaderTrackOutput बनाएं।

AVPlayer की 'संपत्ति', 'startReading' का उपयोग कर AVAssetReader बनाएं और फिर copyNextSampleBuffer का उपयोग कर छवियों को पुनः प्राप्त।

ग)

एक AVPlayerItem + AVPlayer या AVPlayer वीडियो URL से सीधे बनाएँ।

एवीप्लेयर इटिम की 'ट्रैक' संपत्ति केवीओ, और एक बार पटरियों को लोड करने के बाद, AVAssetTracks प्रकार AVMediaTypeVideo को अलग करें।

AVPlayerItem/AVPlayer/AVAssetTrack की 'संपत्ति' संपत्ति से AVAsset प्राप्त करें।

शेष चरण दृष्टिकोण (बी) के समान हैं।

घ)

एक AVPlayerItem + AVPlayer या AVPlayer वीडियो URL से सीधे बनाएँ।

KVO AVPlayerItem की 'पटरियों' संपत्ति, और एक बार पटरियों लोड किए गए हैं, प्रकार AVMediaTypeVideo के लोगों को अलग करते हैं।

एक AVMutableComposition बनाएँ, और प्रकार AVMediaTypeVideo का एक संबद्ध AVMutableCompositionTrack आरंभ कर देगा।

इस AVMutableCompositionTrack में पहले से प्राप्त वीडियो ट्रैक से उचित CMTimeRange डालें।

(ख) और (ग) के समान है, अब अपनी AVAssetReader और AVAssetReaderTrackOutput बनाने के लिए, लेकिन अंतर यह है कि आप अपने AVAssetReader आरंभ के लिए आधार के रूप में AVAsset AVMutableComposition उपयोग करते हैं, और अपने AVAssetReaderTrackOutput के लिए आधार के रूप में AVAssetTrack AVMutableCompositionTrack साथ।

'स्टार्ट रीडिंग' और AVAssetReader से फ्रेम प्राप्त करने के लिए copyNextSampleBuffer का उपयोग करें।

पीएस: मैंने इस तथ्य को प्राप्त करने के लिए यहां दृष्टिकोण (डी) की कोशिश की कि AVAsset सीधे AVPlayerItem या AVPlayer से पुनर्प्राप्त नहीं हो रहा था। इसलिए मैं पहले से ही AVAssetTracks से एक नया AVAsset बनाना चाहता था। स्वीकार्य रूप से हैकी, और शायद व्यर्थ (जहां मूल जानकारी AVAsset नहीं है, तब ट्रैक जानकारी को अंततः पुनर्प्राप्त किया जाएगा!) लेकिन यह वैसे भी एक हताश प्रयास के लायक था।

यहां फ़ाइलें के विभिन्न प्रकार के परिणामों का सारांश है:

1) स्थानीय MOV/MP4 के - सभी 4 दृष्टिकोण दोषरहित काम करते हैं।

2) रिमोट एमओवी/एमपी 4 - संपत्ति और ट्रैक दृष्टिकोण (बी) के माध्यम से सही ढंग से पुनर्प्राप्त किए जाते हैं, और AVAssetReader भी प्रारंभ होता है लेकिन copyNextSampleBuffer हमेशा शून्य देता है। (ए) के मामले में, AVAssetReader का निर्माण स्वयं 'अज्ञात त्रुटि' NSOSStatusErrorDomain -12407 के साथ विफल रहता है।

3) स्थानीय एम 3 यू 8 (इन-ऐप/स्थानीय HTTP सर्वर के माध्यम से पहुंचा) - दृष्टिकोण (ए), (बी) और (सी) फाइलों के लिए किसी भी आकार या रूप में AVURLASSet/AVAsset प्राप्त करने की कोशिश के रूप में बुरी तरह विफल हो जाते हैं एम 3 यू 8 के माध्यम से स्ट्रीम किया गया मूर्ख मूर्ख है।

की (क), संपत्ति सब पर नहीं बनाया गया है, और initWithURL मामले में: AVURLAsset पर कॉल एक 'अज्ञात त्रुटि' AVFoundationErrorDomain -11,800 साथ विफल रहता है।

(बी) और (सी) के मामले में, AVPlayer/AVPlayerItem या AVAssetTracks से AVURLAsset को पुनर्प्राप्त करने से कुछ वस्तु वापस आती है, लेकिन उस पर 'ट्रैक' प्रॉपर्टी तक पहुंचने से हमेशा खाली सरणी होती है।

(घ), मैं निकालते हैं और अलग वीडियो सफलतापूर्वक ट्रैक करता है, करने में सक्षम हूँ के मामले में लेकिन AVMutableCompositionTrack बनाने का प्रयास करते हैं, यह विफल रहता है जब, AVMutableCompositionTrack में स्रोत ट्रैक से CMTimeRange सम्मिलित करने का प्रयास एक साथ 'अज्ञात त्रुटि' NSOSStatusErrorDomain -12780।

4) रिमोट एम 3 यू 8, बिल्कुल स्थानीय एम 3 यू 8 के समान व्यवहार करता है।

मैं पूरी तरह से शिक्षित नहीं हूं कि ये मतभेद क्यों मौजूद हैं, या ऐप्पल द्वारा कम नहीं किया जा सका। लेकिन वहां आप जाते हैं।

-1

वर्तमान में AVFoundation के साथ गैर-स्थानीय URL का उपयोग संभव नहीं है, कम से कम सीधे नहीं।

0

@ कोकनेटिक्स, यह सच नहीं है। आप AVMutableCompositionTrack

पर एक दूरस्थ फ़ाइल प्राप्त
AVURLAsset* soundTrackAsset = [[AVURLAsset alloc]initWithURL:[NSURL URLWithString:@"http://www.yoururl.com/yourfile.mp3"] options:nil]; 

AVMutableCompositionTrack *compositionAudioSoundTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; 
[compositionAudioSoundTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, audioAsset.duration) 
           ofTrack:[[soundTrackAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] 
           atTime:kCMTimeZero error:nil]; 

हालांकि, इस पद्धति फ़ाइलों MP4s की तरह एक उच्च संपीड़न

+1

मुझे ऑडियो तक पहुंचने की आवश्यकता है और लाइव m3u8 url के वीडियो ट्रैक डेटा। क्या आप मेरी मदद कर सकते हैं? क्या हम लाइव m3u8 url के AVAssets प्राप्त कर सकते हैं? – Punita