ffmpeg

2011-08-15 18 views
5

का उपयोग कर .mov से फ्रेम-दर-फ्रेम पार्सिंग मैं एक .mov फ़ाइल से H.264 फ्रेम को पार्स करने का प्रयास कर रहा हूं। मुझे लगता है कि मैं इस निष्कर्ष पर आया हूं कि एफएफएमपीईजी के एवीफॉर्मैट-भाग से mov.c जाने का रास्ता है। लेकिन mov.c असम्बद्ध कोड के बगल में ~ 2600 लाइनें है। मैं एफएफएमपीईजी के उपयोग के उदाहरणों की तलाश में हूं, विशेष रूप से किसी भी फ़ाइल प्रकार की संरचना को पार्स करना। कोई फर्क नहीं पड़ता कि यह एमपीईजी 4 या क्विकटाइम मूवी है क्योंकि वे संरचना में काफी समान हैं।ffmpeg

यदि कोई मौजूदा उदाहरण नहीं है (मुझे कोई नहीं मिल रहा है) शायद किसी ने इसका उपयोग किया है और मुझे कोड की कुछ पंक्तियां दे सकते हैं, या समझाया जा सकता है कि कैसे शुरू किया जाए?

मुझे क्या करना कोशिश कर रहा हूँ: मैं AVCaptureSession का उपयोग वीडियो कैमरा से नमूने पर कब्जा करने, इन नमूनों तो H264 में इनकोडिंग और AVAssetsWriter, AVAssetsWriterInput और AVAssetsWriterInputPixelBufferAdaptor की मदद से फाइल करने के लिए लिखा जाता है। इसका कारण यह है कि मैं सीधे हार्डवेयर H264 एन्कोडिंग तक नहीं पहुंच सकता क्योंकि सेब इसे अनुमति नहीं देगा। क्या मैं अब क्या करने की जरूरत (मुझे यकीन है कि नहीं लगता) को पार्स आउट है:

"mdat" -atom .mov फ़ाइल से (मूवी डेटा, वहाँ हो सकता है एक से अधिक मुझे लगता है कि)। फिर के साथ "-टॉम और फिर वीडियो-परमाणु के भीतर (वीडियो डेटा नमूना, एक से अधिक हो सकता है)। मुझे लगता है कि कई परमाणु होंगे जो मैं मानता हूं कि फ्रेम है। ये "avc1" प्रकार का होगा (यह H264 के लिए प्रकार है)। कृपया मुझे इस में सही करें क्योंकि मुझे पूरा यकीन है कि मुझे यह सब ठीक से नहीं मिला है

मेरा प्रश्न यह है कि, मैं एकल फ्रेम को पार्स करने के बारे में कैसे जाउंगा। मैं the documentation पढ़ रहा हूं और iFrameExtractor पर देखा (जो फ्रेम को डीकोड करने के बाद से बहुत उपयोगी नहीं है)। मुझे लगता है कि जब मैं mov.c FFMPEG-AVFormat से उपयोग करना चाहता हूं तो मुझे यह सही ढंग से समझ गया है लेकिन मुझे यकीन नहीं है।

संपादित करें: मैं अब इस तरह कोशिश कर रहा हूँ:

  1. मैं जो .mov फ़ाइल में वीडियोस्ट्रीम पाता है थोड़ा कम init समारोह मैं iFrameExtractor चलाते हैं।

  2. मैं इस तरह के फ्रेम के लिए डेटा प्राप्त:

    AVPacket packet; 
    av_read_frame(pFormatCtx, &packet); 
    NSData *frame; 
    if(packet.stream_index == videoStream){ 
        frame = [NSData dataWithBytes:packet.data length:packet.size]; 
    } 
    videoStream++; 
    av_free_packet(&packet); 
    return frame; 
    

मैं तो NSOperation की एक उपवर्ग जहां यह अपलोड करने के लिए प्रतीक्षा में बनाए रखा है के लिए इसे पारित। लेकिन मुझे EXC_BAD_ACC प्राप्त होता है, क्या मैं फ्रेम से डेटा कॉपी करते समय कुछ गलत कर रहा हूं? कोई विचार। मुझे EXC _.. मिलता है। जब मैं क्लास वेरिएबल NSData* frame को अपने (nonatomic, retain) -property का उपयोग करके सेट करने का प्रयास करता हूं। (यह संश्लेषण पंक्ति पर EXC_BAD_ACC कहता है)

+0

mov.c अंत लक्ष्य के साथ मदद करने के लिए नहीं जा रहा है। यदि आपको एमओवी/एमपी 4 पार्सिंग सहायता की ज़रूरत है तो यह आसान हो सकता है। जब चीजें किसी न किसी हो जाती हैं [mp4v2] (http://code.google.com/p/mp4v2/) के लिए एक और आसान लाइब्रेरी। असल में आपको इसे खुद लिखना होगा। विभिन्न कारणों से नौकरी पाने के लिए कोई पुस्तकालय नहीं जा रहा है। –

+0

@Steve McFarlin, धन्यवाद, आप क्यूटी-प्रलेखन छोड़कर पढ़ने क्योंकि मैं सच में मुसीबत यह सभी उत्साहित हो रही है mov फ़ाइल की पूरी संरचना समझ पर कोई सुझाव है, यह है कि परमाणु भी नहीं है सही है एक विशिष्ट क्रम में होना चाहिए? आपको लगता है कि mov या mp4 के साथ काम करने के लिए सबसे आसान कौन सा था? –

+0

@Steve McFarlin, मैं लगता है कि आप iFrameExtractor परियोजना को देखा है। मार्टिन बोहेम (उदाहरण के लिए dranger.com पर) के ट्यूटोरियल में यह भी वही कोड है। अगले फ्रेम फ़ंक्शन में वे केवल av_read_frame का उपयोग करते हैं और फिर इसे डीकोड करते हैं। AV_read_frame द्वारा संशोधित AVPacket एन्कोडेड H264-फ्रेम नहीं होगा? –

उत्तर

1

मैं mov फ़ाइल से प्रत्येक फ्रेम पार्स करने के लिए निम्नलिखित का उपयोग करें:

यहाँ एक ओपन सोर्स प्रोजेक्ट है।

-(NSData *)nextFrame { 
    AVPacket packet; 
    NSData *frame = nil; 

    while(!frame && av_read_frame(pFormatCtx, &packet)>=0) { 

     if(packet.stream_index == streamNo) { 
      frame = [[[NSData alloc] initWithBytes:packet.data length:packet.size] autorelease]; 
     } 
     av_free_packet(&packet); 
    } 
    return frame; 
} 

हालांकि देखें कि av_read_frame फ़्रेम को सत्यापित नहीं करता है, जो डीकोडिंग चरण में किया जाता है। इसका मतलब है कि लौटे "फ्रेम" में अतिरिक्त जानकारी हो सकती है जो वास्तविक फ्रेम का हिस्सा नहीं है।

init को AVFormatContext * pFormatCtx और AVCodecContext * pCodecCtx मैं इस कोड (जो मेरा मानना ​​है कि मार्टिन Böhme के उदाहरण कोड से ली गई है) का उपयोग करें:

AVCodec *pCodec; 

    // Register all formats and codecs 
    av_register_all(); 

    // Open video file 
    if(avformat_open_input(&pFormatCtx, [moviePath cStringUsingEncoding:NSASCIIStringEncoding], NULL, NULL)!=0) 
     goto initError; // Couldn't open file 

    // Retrieve stream information 
    if(avformat_find_stream_info(pFormatCtx,NULL)<0) 
     goto initError; // Couldn't find stream information 

    // Find the video stream 
    streamNo = -1; 
    for(int i=0; i<pFormatCtx->nb_streams; i++){ 
     if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) 
     { 
      streamNo = i; 
      break; 
     } 
    } 
    if(streamNo == -1) 
     goto initError; // Didn't find a video stream 

    // Get a pointer to the codec context for the video stream 
    pCodecCtx=pFormatCtx->streams[streamNo]->codec; 

    // Find the decoder for the video stream 
    pCodec=avcodec_find_decoder(pCodecCtx->codec_id); 
    if(pCodec==NULL) 
     goto initError; // Codec not found 

    // Open codec 
    if(avcodec_open2(pCodecCtx, pCodec, NULL)<0) 
     goto initError; // Could not open codec 

    return self; 

initError: 
    NSLog(@"initError in VideoFrameExtractor"); 
    [self release]; 
    return nil; 

आशा है कि यह भविष्य में किसी को मदद मिलती है।

0

libavcodec/libavformat here का उपयोग करने पर एक बहुत अच्छा ट्यूटोरियल है। थोड़ा सा लगता है जैसे आप रुचि रखते हैं DoSomethingWithTheImage() फ़ंक्शन वे अनुपूरक छोड़ चुके हैं।

+0

मैं चाहता हूँ कच्चे H.264 डेटा, तो मैं बाद में सर्वर साइड पर एक mov करने के लिए फ्रेम पुनः कर सकते हैं। मैंने पहले इस उदाहरण को देखा है और अगर मुझे डीकोड चरण छोड़ना था तो मुझे पता नहीं लगा सका? और बस 'rawData = packet.data' रखें? जब मैं डीकोड करता हूं तो क्या होता है? क्या मैं H.264 मानक से तब जाऊं? –

+1

आप दोनों पढ़ और लिखते हैं। एमओवी? फिर तुम क्या कर रहे हो? –

+0

@yi_H मैं .mov फ़ाइल को अलग कर रहा हूं, जबकि यह एक सर्वर पर H264 फ्रेम भेजने के लिए रिकॉर्डिंग कर रहा है जहां मैं उन्हें फिर से इकट्ठा करता हूं। आईओएस के साथ वास्तविक समय में H264 स्ट्रीम करने का यही एकमात्र तरीका है क्योंकि मैं इसे समझता हूं। –

0

यदि आप आईओएस को H264 स्ट्रीम करते हैं तो आपको सेगमेंट स्ट्रीमिंग (उर्फ सेब लाइव स्ट्रीमिंग) की आवश्यकता होती है। http://code.google.com/p/httpsegmenter/

+1

मैं आईओएस से स्ट्रीम करने जा रहा हूं। कैमरे से फ़ाइल में लिखने के लिए AVCaptureSession और AVAssetsWriter का उपयोग करना। तो मैं H264 फ्रेम प्राप्त करने और फ़ाइल में अपलोड करने के लिए फ़ाइल को पार्स करना चाहता हूं। मुझे अपलोड करने के लिए http-packets सहित सब कुछ मिल रहा है। मुझे जो चाहिए वह .mov फ़ाइल में फ्रेम तक पहुंचने का तरीका है, कच्चे फ्रेम डेटा तक पहुंचें। शायद यह दूसरे उत्तर में पोस्ट किए गए उदाहरण के साथ काम करेगा। मैं अब कोशिश कर रहा हूं, अगर आपके पास यह एक और सुझाव है कि मैं इसे कैसे काम कर सकता हूं कृपया इसे साझा करें :) –

+0

क्या आप ऑडियो चैनल छोड़ना चाहते हैं? आप एक अलग कंटेनर का उपयोग करना चाहते हैं? मुझे अभी भी यह नहीं मिला है। –

+0

मुझे एहसास हुआ कि दूसरा जवाब काम नहीं करेगा क्योंकि यह फ्रेम को डीकोड करता है, इसलिए इसे अब H264 में एन्कोड नहीं किया जाएगा। मुझे –