2011-10-12 15 views
28

मैं एंड्रॉयड पर हार्डवेयर H264 encoder का उपयोग कैमरे से वीडियो बनाने के लिए, और FFmpeg उपयोग करने के लिए (एंड्रॉयड फोन पर ही सब) ऑडियो में mux करने के लिए कोशिश कर रहा हूँडिकोड एंड्रॉयड के हार्डवेयर इनकोडिंग H264 कैमरा वास्तविक समय

में ffmpeg का उपयोग कर फ़ीड

जो मैंने अभी तक पूरा किया है, वह H264 वीडियो को rtsp पैकेट में पैकेटेट कर रहा है, और वीएलसी (UDP से अधिक) का उपयोग करके इसे डीकोड कर रहा है, इसलिए मुझे पता है कि वीडियो कम से कम सही रूप से स्वरूपित है। हालांकि, मुझे वीडियो डेटा को ffmpeg पर एक प्रारूप में प्राप्त करने में समस्या हो रही है जो इसे समझ सकता है।

मैं एक ही rtsp पैकेट, (यूडीपी से अधिक) स्थानीय होस्ट पर एक बंदरगाह 5006 के लिए भेजने से तो sdp फ़ाइल है कि यह बताता है जो स्थानीय बंदरगाह वीडियो स्ट्रीम पर में आ रहा है और कैसे वीडियो को डिकोड करने के साथ ffmpeg प्रदान करने की कोशिश की है , अगर मैं सही ढंग से स्ट्रीमिंग rtsp समझता हूं। हालांकि यह काम नहीं करता है और मुझे निदान करने में परेशानी हो रही है, क्यों ffmpeg इनपुट के लिए प्रतीक्षा कर रहा है।

विलंबता और स्केलेबिलिटी के कारणों के लिए मैं सिर्फ सर्वर और वीडियो को सर्वर पर नहीं भेज सकता हूं और इसे वहां मक्स कर सकता हूं, इसे फोन पर, जितना संभव हो उतना हल्का वजन में किया जाना चाहिए।

मुझे लगता है कि मैं क्या देख रहा हूं यह सुझाव है कि यह कैसे पूरा किया जा सकता है। इष्टतम समाधान पैकेट पर H264 वीडियो को ffmpeg पर भेज देगा, लेकिन फिर मैं ffmpegsdp फ़ाइल पैरामीटर को वीडियो को डीकोड करने की आवश्यकता नहीं भेज सकता।

मैं अनुरोध पर अधिक जानकारी प्रदान कर सकता हूं, जैसे ffmpeg एंड्रॉइड के लिए संकलित किया गया है लेकिन मुझे संदेह है कि यह आवश्यक है।

ओह, और जिस तरह से मैं ffmpeg शुरू करता हूं, कमांड लाइन के माध्यम से होता है, तो मैं वास्तव में जेनी के साथ मिलकर बचाना चाहता हूं यदि यह संभव हो।

और सहायता की बहुत सराहना की जाएगी, धन्यवाद।

+3

आप ffmpeg का उपयोग करके डीकोडिंग क्यों कर रहे हैं? निर्मित मीडियाप्लेयर ऑब्जेक्ट –

+0

का उपयोग करें क्या आपने RTSP के माध्यम से ffmpeg के आउटपुट को स्ट्रीम करने के लिए live555 का उपयोग करने का प्रयास किया है? साथ ही, स्ट्रीम की जांच ffmpeg नहीं करना चाहिए और स्ट्रीम-जानकारी स्वयं ही पता लगाना चाहिए? – Shark

+0

मुझे लगता है कि अवियाद की सच्चाई है। आप कैसे जानते हैं कि कैमरा किस वीडियो प्रारूप का उत्पादन करता है? –

उत्तर

1

क्या आपने java.lang.Runtime का उपयोग करने का प्रयास किया है?

String[] parameters = {"ffmpeg", "other", "args"}; 
Program program Runtime.getRuntime().exec(parameters); 

InputStream in = program.getInputStream(); 
OutputStream out = program.getOutputStream(); 
InputStream err = program.getErrorStream(); 

फिर आप stdout लिखते हैं और stdin और stderr से पढ़ते हैं। यह एक पाइप नहीं है लेकिन यह नेटवर्क इंटरफ़ेस का उपयोग करने से बेहतर होना चाहिए।

+0

ओपी यहां, मैं अब इस समस्या पर काम नहीं कर रहा हूं (मैंने छोड़ दिया), लेकिन मुझे यह जोड़ना चाहिए कि मैंने वास्तव में यह प्रयास किया था। मुझे सभी विवरण याद नहीं हैं, लेकिन मैंने इनपुट इनपुट, और ओएस (वीडियो के लिए एक पाइप, ऑडियो के लिए एक) का उपयोग करके कई फीफो पाइप का उपयोग करने का प्रयास किया। हालांकि, इस विधि के साथ समस्या यह थी कि मैं कैमरे फ़ीड द्वारा उत्पन्न वीडियो पैकेट को समझने और डीकोड करने के लिए पर्याप्त जानकारी ffmpeg प्रदान करने में असमर्थ था। वास्तविक कारण मैं आरटीएसपी का उपयोग करना चाहता था यह था कि - सैद्धांतिक रूप से - लाइव स्ट्रीम को डीकोड करने के लिए एफएफएमपीजी पर्याप्त जानकारी प्रदान करेगा। – joebobfrank

1

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

यदि आप किसी एंड्रॉइड डिवाइस से कैमरा और माइक स्ट्रीम करना चाहते हैं तो आपके पास दो मुख्य विकल्प हैं: जावा या एनडीके कार्यान्वयन।

  1. जावा कार्यान्वयन।

    मैं केवल विचार का जिक्र करने जा रहा हूं लेकिन मूल रूप से यह इन मानकों Real-Time Streaming Protocol Version 2.0 और RTP Payload Format for H.264 Video पर आधारित जावा में एक आरटीएसपी सर्वर और आरटीपी प्रोटोकॉल लागू कर रहा है। यह कार्य बहुत लंबा और कठिन होगा। लेकिन अगर आप अपना पीएचपी कर रहे हैं तो एंड्रॉइड के लिए एक अच्छा आरटीएसपी जावा लिब होना अच्छा लगेगा।

  2. एनडीके कार्यान्वयन।

    इस विकल्प में विभिन्न समाधान शामिल हैं। मुख्य विचार हमारे एंड्रॉइड एप्लिकेशन में पावर सी या सी ++ लाइब्रेरी का उपयोग करना है। इस उदाहरण के लिए, एफएफएमपीईजी।इस पुस्तकालय को एंड्रॉइड के लिए संकलित किया जा सकता है और विभिन्न आर्किटेक्चर का समर्थन कर सकता है। इस दृष्टिकोण की समस्या यह है कि इसे पूरा करने के लिए आपको Android NDK, C और C++ के बारे में जानने की आवश्यकता हो सकती है।

    लेकिन एक विकल्प है। आप सी पुस्तकालय लपेट सकते हैं और एफएफएमपीईजी का उपयोग कर सकते हैं। पर कैसे?

    उदाहरण के लिए, FFmpeg Android का उपयोग करके, जिसे x264, libass, fontconfig, freetype और fribidi के साथ संकलित किया गया है और विभिन्न आर्किटेक्चर का समर्थन करता है। लेकिन अगर आप रीयल-टाइम में स्ट्रीम करना चाहते हैं तो प्रोग्राम प्रोग्राम करना मुश्किल है, आपको फ़ाइल डिस्क्रिप्टरों और इन/आउट स्ट्रीम से निपटने की आवश्यकता है।

    जावा प्रोग्रामिंग बिंदु दृश्य से सबसे अच्छा विकल्प, JavaCV का उपयोग करना है। JavaCV कंप्यूटर दृष्टि भी शामिल की आमतौर पर इस्तेमाल किया पुस्तकालयों से रैपर का उपयोग करता है: (OpenCV, FFmpeg, आदि, और उपयोगिता वर्गों प्रदान करता है उनकी कार्यक्षमता, जावा मंच पर उपयोग करने के लिए (बेशक) Android सहित आसान बनाने के लिए

    JavaCV भी आता है। हार्डवेयर त्वरित पूर्ण स्क्रीन छवि प्रदर्शन (CanvasFrame और GLCanvasFrame), कई कोर (Parallel), कैमरा और प्रोजेक्टर के उपयोगकर्ता के अनुकूल ज्यामितीय और रंग अंशांकन पर समानांतर में कोड निष्पादित करने के लिए आसानी से उपयोग के तरीकों के साथ (GeometricCalibrator, ProCamGeometricCalibrator, ProCamColorCalibrator) , फीचर पॉइंट्स का पता लगाने और मिलान (ObjectFinder), प्रोजेक्टर-कैमरा सिस्टम के मुख्य छवि संरेखण को लागू करने वाले वर्गों का एक सेट (मुख्य रूप से GNImageAligner, ProjectiveTransformer, ProjectiveColorTransformer, ProCamTransformer, और ReflectanceInitializer), एक ब्लॉब विश्लेषण पैकेज (Blobs), साथ ही साथ JavaCV कक्षा में विविध कार्यक्षमता। इन कक्षाओं में से कुछ भी एक OpenCL और ओपन समकक्ष है, उनके नाम CL के साथ समाप्त होने या GL के साथ शुरू, यानी .: JavaCVCL, GLCanvasFrame, आदि

लेकिन हम इस समाधान का उपयोग कर सकते हैं?

यहां हमारे पास यूडीपी का उपयोग करके स्ट्रीम करने के लिए बुनियादी कार्यान्वयन है।

String streamURL = "udp://ip_destination:port"; 
recorder = new FFmpegFrameRecorder(streamURL, frameWidth, frameHeight, 1); 
recorder.setInterleaved(false); 
// video options // 
recorder.setFormat("mpegts"); 
recorder.setVideoOption("tune", "zerolatency"); 
recorder.setVideoOption("preset", "ultrafast"); 
recorder.setVideoBitrate(5 * 1024 * 1024); 
recorder.setFrameRate(30); 
recorder.setSampleRate(AUDIO_SAMPLE_RATE); 
recorder.setVideoCodec(AV_CODEC_ID_H264); 
recorder.setAudioCodec(AV_CODEC_ID_AAC); 

कोड के इस भाग से पता चलता रिकॉर्डर बुलाया FFmpegFrameRecorder वस्तु को प्रारंभ करने के लिए कैसे। यह ऑब्जेक्ट कैमरे से प्राप्त फ्रेम और माइक्रोफ़ोन से प्राप्त नमूने को कैप्चर और एन्कोड करेगा।

आप एक ही Android एप्लिकेशन में एक पूर्वावलोकन पर कब्जा करना चाहते हैं तो हम एक CameraPreview कक्षा इस वर्ग के कच्चे डेटा में परिवर्तित कर देंगे कैमरा से प्रदान किए जाते लागू करने की आवश्यकता है और यह पूर्वावलोकन और FFmpegFrameRecorder के लिए फ्रेम का निर्माण करेगा।

आईपी_डिस्टिनेशन को पीसी या डिवाइस के आईपी के साथ बदलने के लिए याद रखें जहां आप स्ट्रीम भेजना चाहते हैं। उदाहरण के रूप में बंदरगाह 8080 हो सकता है।

@Override 
public Mat onCameraFrame(Mat mat) 
{ 
    if (audioRecordRunnable == null) { 
     startTime = System.currentTimeMillis(); 
     return mat; 
    } 
    if (recording && mat != null) { 
     synchronized (semaphore) { 
      try { 
       Frame frame = converterToMat.convert(mat); 
       long t = 1000 * (System.currentTimeMillis() - startTime); 
       if (t > recorder.getTimestamp()) { 
        recorder.setTimestamp(t); 
       } 
       recorder.record(frame); 
      } catch (FFmpegFrameRecorder.Exception e) { 
       LogHelper.i(TAG, e.getMessage()); 
       e.printStackTrace(); 
      } 
     } 
    } 
    return mat; 
} 

इस विधि onCameraFrame विधि है कि कैमरे से चटाई (चित्र) मिलता है के कार्यान्वयन से पता चलता है और यह एक फ्रेम के रूप में परिवर्तित और FFmpegFrameRecorder वस्तु द्वारा दर्ज की गई है।

@Override 
public void onSampleReady(ShortBuffer audioData) 
{ 
    if (recorder == null) return; 
    if (recording && audioData == null) return; 

    try { 
     long t = 1000 * (System.currentTimeMillis() - startTime); 
     if (t > recorder.getTimestamp()) { 
      recorder.setTimestamp(t); 
     } 
     LogHelper.e(TAG, "audioData: " + audioData); 
     recorder.recordSamples(audioData); 
    } catch (FFmpegFrameRecorder.Exception e) { 
     LogHelper.v(TAG, e.getMessage()); 
     e.printStackTrace(); 
    } 
} 

ऑडियो audioData के साथ भी यही एक ShortBuffer उद्देश्य यह है कि FFmpegFrameRecorder द्वारा रिकॉर्डर हो जाएगा।

पीसी या डिवाइस गंतव्य में आप स्ट्रीम प्राप्त करने के लिए निम्न आदेश चला सकते हैं।

ffplay udp://ip_source:port 

ip_source स्मार्टफोन है कि कैमरा और माइक धारा स्ट्रीमिंग है के आईपी है। पोर्ट एक ही 8080 होना चाहिए।

मैंने यहां अपने जीथब भंडार में एक समाधान बनाया: UDPAVStreamer

शुभकामनाएं

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