मेरा मानना है कि आप एनकोडर के onInputBufferAvailable()
कॉलबैक में कुछ करने की ज़रूरत नहीं करना चाहिए - आप encoder.queueInputBuffer()
नहीं बुलाना चाहिए। जैसे ही आप सिंक्रोनस मोड में भूतल इनपुट एन्कोडिंग करते समय encoder.dequeueInputBuffer()
और encoder.queueInputBuffer()
मैन्युअल रूप से कॉल नहीं करते हैं, आपको इसे एसिंक्रोनस मोड में भी नहीं करना चाहिए।
जब आप decoder.releaseOutputBuffer(outputBufferId, true);
फोन (सिंक्रोनस और एसिंक्रोनस दोनों मोड में) इस आंतरिक रूप से (का उपयोग कर Surface
आपके द्वारा दी गई), सतह से एक इनपुट बफर dequeues इसे में उत्पादन प्रस्तुत हुई है, और इसे वापस (करने के लिए enqueues सतह के लिए एनकोडर)। सिंक्रोनस और एसिंक्रोनस मोड के बीच एकमात्र अंतर यह है कि कैसे सार्वजनिक एपीआई में बफर घटनाओं का खुलासा किया जाता है, लेकिन सतह इनपुट का उपयोग करते समय, यह एक अलग (आंतरिक) एपीआई का उपयोग करने के लिए उपयोग करता है, इसलिए सिंक्रोनस बनाम एसिंक्रोनस मोड के लिए कोई फर्क नहीं पड़ता यह बिल्कुल
तो जहां तक मुझे पता है (हालांकि मैंने इसे स्वयं नहीं किया है), आपको एन्कोडर के लिए onInputBufferAvailable()
कॉलबैक खाली छोड़ना चाहिए।
संपादित करें: तो, मैंने इसे स्वयं करने की कोशिश की, और यह ऊपर वर्णित अनुसार (लगभग) सरल है।
यदि एन्कोडर इनपुट सतह को डीकोडर के आउटपुट के रूप में सीधे कॉन्फ़िगर किया गया है (बिना सतह सतह के बीच), चीजें बस एक सिंक्रोनस डीकोड-एनकोड लूप को एक असीमित में परिवर्तित कर देती हैं।
यदि आप भूतलटेक्चर का उपयोग करते हैं, तो भी, आप एक छोटे गोचा में भाग सकते हैं। कॉलिंग थ्रेड के संबंध में सतह के मिश्रण तक पहुंचने के लिए फ्रेम की प्रतीक्षा करने के साथ कोई समस्या है, इसके संदर्भ के लिए https://android.googlesource.com/platform/cts/+/jb-mr2-release/tests/tests/media/src/android/media/cts/DecodeEditEncodeTest.java#106 और https://android.googlesource.com/platform/cts/+/jb-mr2-release/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java#104 और https://android.googlesource.com/platform/cts/+/jb-mr2-release/tests/tests/media/src/android/media/cts/OutputSurface.java#113 देखें।
समस्या, जहां तक मैं इसे देखता हूं, awaitNewImage
में https://android.googlesource.com/platform/cts/+/jb-mr2-release/tests/tests/media/src/android/media/cts/OutputSurface.java#240 में है। यदि onFrameAvailable
कॉलबैक को मुख्य थ्रेड पर कॉल किया जाना है, तो हमारे पास कोई समस्या है यदि awaitNewImage
कॉल मुख्य थ्रेड पर भी चलाया जाता है। यदि onOutputBufferAvailable
कॉलबैक को मुख्य थ्रेड पर भी कॉल किया जाता है और आप वहां से awaitNewImage
पर कॉल करते हैं, तो हमारे पास कोई समस्या है, क्योंकि आप कॉलबैक के लिए प्रतीक्षा कर सकते हैं (wait()
के साथ जो पूरे थ्रेड को अवरुद्ध करता है) जिसे तब तक नहीं चलाया जा सकता है वर्तमान विधि रिटर्न।
इसलिए हमें यह सुनिश्चित करने की आवश्यकता है कि onFrameAvailable
कॉलबैक awaitNewImage
पर कॉल करने वाले किसी भिन्न थ्रेड पर आते हैं। ऐसा करने का एक बहुत ही आसान तरीका एक नया अलग धागा बनाना है, जो onFrameAvailable
कॉलबैक सेवा के अलावा कुछ भी नहीं करता है। ऐसा करने के लिए, आप उदाहरण कर सकते हैं इस:
private HandlerThread mHandlerThread = new HandlerThread("CallbackThread");
private Handler mHandler;
...
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
...
mSurfaceTexture.setOnFrameAvailableListener(this, mHandler);
मुझे आशा है कि यह पर्याप्त आपकी समस्या का हल करने के लिए, अगर तुम मुझे जरूरत सार्वजनिक उदाहरणों में से एक संपादित करने के लिए वहाँ अतुल्यकालिक कॉलबैक लागू करने के लिए मुझे पता है सक्षम होने के लिए के लिए है।
EDIT2: इसके अलावा, जीएल प्रतिपादन onOutputBufferAvailable
कॉलबैक के भीतर से किया जा सकता है के बाद से, यह एक है कि EGL संदर्भ की स्थापना की तुलना में एक अलग धागा हो सकता है। प्रतिपादन से पहले अन्य सूत्र में
mEGL.eglMakeCurrent(mEGLDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
और पुनः अनुलग्न यह:: तो उस स्थिति में, एक, धागा है कि इसे सेट अप में EGL संदर्भ जारी करने के लिए इस तरह की जरूरत है
mEGL.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext);
EDIT3: इसके अतिरिक्त, यदि एन्कोडर और डिकोडर कॉलबैक एक ही थ्रेड पर प्राप्त होते हैं, तो डीकोडर onOutputBufferAvailable
जो प्रतिपादन करता है, एन्कोडर कॉलबैक को वितरित होने से रोक सकता है। अगर उन्हें डिलीवर नहीं किया जाता है, तो प्रतिपादन असीमित रूप से अवरुद्ध किया जा सकता है क्योंकि एन्कोडर को आउटपुट बफर वापस नहीं मिलते हैं। यह सुनिश्चित करके तय किया जा सकता है कि वीडियो डिकोडर कॉलबैक इसके बजाय एक अलग थ्रेड पर प्राप्त किए जाते हैं, और यह इसके बजाय onFrameAvailable
कॉलबैक के साथ समस्या से बचाता है।
मैंने इसे ExtractDecodeEditEncodeMuxTest
के शीर्ष पर कार्यान्वित करने का प्रयास किया, और यह ठीक से काम कर रहा है, https://github.com/mstorsjo/android-decodeencodetest पर एक नज़र डालें। मैंने शुरुआत में अपरिवर्तित परीक्षण आयात किया, और प्रतिबद्ध लॉग में अलग-अलग फ़िक्सेस को देखना आसान बनाने के लिए, अलग-अलग मुश्किल विवरणों के लिए असीमित मोड और फ़िक्स को रूपांतरण किया।
पिंग, क्या आपने https://github.com/mstorsjo/android-decodeencodetest पर पूरा उदाहरण देखा था? क्या यह आपके लिए उपयोगी है, या क्या आपको अभी भी इसकी कमी है? – mstorsjo
मैं @ mstorsjo प्रभावित हूँ! ऐसा प्रतीत होता है कि आपने उदाहरण को रूपांतरित किया है, जिसमें से मैंने एन्कोडर और डिकोडर दोनों के लिए गैर-वंचित एसिंक 'MediaCodec.Callback' विधियों का उपयोग करना शुरू किया था जैसा कि मैंने कामना की थी। ऐसा प्रतीत होता है कि आपके सभी परिवर्तन "ExtractDecodeEditEncodeMuxTest.java" तक ही सीमित हैं। लागू करने के बाद मैं रिपोर्ट करूंगा। धन्यवाद। –
हां, अधिकांश परिवर्तन इस फ़ाइल तक ही सीमित हैं। मुझे InputSurface.java में कुछ मामूली परिवर्तन करना पड़ता था, हालांकि (https://github.com/mstorsjo/android-decodeencodetest/commit/0cad97666a278c88a751400a1fdfcdb054b52662 देखें) और आउटपुट Surface.java में एक परिवर्तन (https://github.com/ mstorsjo/android-decodeencodetest/प्रतिबद्ध/4053871ac53807b95c477403403cd2226b5b6a50) जो डीकोडर कॉलबैक को https://github.com/mstorsjo/android-decodeencodetest/commit/23a0621390404785e02a1ae7c24dfb67f9854129 में किसी भिन्न थ्रेड पर ले जाने के बाद आवश्यक नहीं था। – mstorsjo