मैंने एंड्रॉइड के मीडियाकोडेक एपीआई का उपयोग करके एक H264 स्ट्रीम एन्कोडर लिखा है। मैंने विभिन्न प्रोसेसर के साथ लगभग दस अलग-अलग उपकरणों पर इसका परीक्षण किया और स्नैपड्रैगन 800 संचालित वाले (Google नेक्सस 5 और सोनी एक्सपीरिया जेड 1) को छोड़कर, उन सभी पर काम किया। उन उपकरणों पर मुझे एसपीएस और पीपीएस और पहला कीफ्रेम मिलता है, लेकिन उसके बाद mEncoder.dequeueOutputBuffer (mBufferInfo, 0) केवल MediaCodec.INFO_TRY_AGAIN_LATER लौटाता है। मैंने पहले से ही अलग-अलग टाइमआउट्स, बिट्रेट्स, रेज़ोल्यूशन और अन्य कॉन्फ़िगरेशन विकल्पों के साथ प्रयोग नहीं किया है, इसका कोई फायदा नहीं हुआ है। परिणाम हमेशा एक ही है।मीडियाकोडेक एच 264 एनकोडर स्नैपड्रैगन 800 डिवाइस पर काम नहीं कर रहा है
मैं निम्नलिखित कोड का उपयोग एनकोडर आरंभ करने के लिए:
mBufferInfo = new MediaCodec.BufferInfo();
encoder = MediaCodec.createEncoderByType("video/avc");
MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", 640, 480);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 768000);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, mEncoderColorFormat);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);
encoder.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
जहां चयनित रंग प्रारूप है:
MediaCodecInfo.CodecCapabilities capabilities = mCodecInfo.getCapabilitiesForType(MIME_TYPE);
for (int i = 0; i < capabilities.colorFormats.length && selectedColorFormat == 0; i++)
{
int format = capabilities.colorFormats[i];
switch (format) {
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar:
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar:
case MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar:
case MediaCodecInfo.CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar:
selectedColorFormat = format;
break;
default:
LogHandler.e(LOG_TAG, "Unsupported color format " + format);
break;
}
}
और मैं कर रहा
ByteBuffer[] inputBuffers = mEncoder.getInputBuffers();
ByteBuffer[] outputBuffers = mEncoder.getOutputBuffers();
int inputBufferIndex = mEncoder.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0)
{
// fill inputBuffers[inputBufferIndex] with valid data
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(rawFrame);
mEncoder.queueInputBuffer(inputBufferIndex, 0, rawFrame.length, 0, 0);
LogHandler.e(LOG_TAG, "Queue Buffer in " + inputBufferIndex);
}
while(true)
{
int outputBufferIndex = mEncoder.dequeueOutputBuffer(mBufferInfo, 0);
if (outputBufferIndex >= 0)
{
Log.d(LOG_TAG, "Queue Buffer out " + outputBufferIndex);
ByteBuffer buffer = outputBuffers[outputBufferIndex];
if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0)
{
// Config Bytes means SPS and PPS
Log.d(LOG_TAG, "Got config bytes");
}
if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) != 0)
{
// Marks a Keyframe
Log.d(LOG_TAG, "Got Sync Frame");
}
if (mBufferInfo.size != 0)
{
// adjust the ByteBuffer values to match BufferInfo (not needed?)
buffer.position(mBufferInfo.offset);
buffer.limit(mBufferInfo.offset + mBufferInfo.size);
int nalUnitLength = 0;
while((nalUnitLength = parseNextNalUnit(buffer)) != 0)
{
switch(mVideoData[0] & 0x0f)
{
// SPS
case 0x07:
{
Log.d(LOG_TAG, "Got SPS");
break;
}
// PPS
case 0x08:
{
Log.d(LOG_TAG, "Got PPS");
break;
}
// Key Frame
case 0x05:
{
Log.d(LOG_TAG, "Got Keyframe");
}
//$FALL-THROUGH$
default:
{
// Process Data
break;
}
}
}
}
mEncoder.releaseOutputBuffer(outputBufferIndex, false);
if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0)
{
// Stream is marked as done,
// break out of while
Log.d(LOG_TAG, "Marked EOS");
break;
}
}
else if(outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED)
{
outputBuffers = mEncoder.getOutputBuffers();
Log.d(LOG_TAG, "Output Buffer changed " + outputBuffers);
}
else if(outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED)
{
MediaFormat newFormat = mEncoder.getOutputFormat();
Log.d(LOG_TAG, "Media Format Changed " + newFormat);
}
else if(outputBufferIndex == MediaCodec.INFO_TRY_AGAIN_LATER)
{
// No Data, break out
break;
}
else
{
// Unexpected State, ignore it
Log.d(LOG_TAG, "Unexpected State " + outputBufferIndex);
}
}
धन्यवाद द्वारा डेटा प्राप्त तुम्हारी मदद के लिए!
आउटपुट स्टाल करते समय बिंदु पर कितने इनपुट फ्रेम कतारबद्ध होते हैं? (मैं यह सुनिश्चित करना चाहता हूं कि यह इनपुट के लिए भूख न हो।) क्या लॉगबैक में कुछ भी संदिग्ध दिख रहा है? (कोडेक्स Log.e स्प्रे करने के लिए प्रवृत्त होते हैं, जो इसे बताना मुश्किल हो सकता है।) किस रंग प्रारूप का चयन किया जा रहा है? (क्या यह क्यूकॉम प्रारूप है?) क्या आपके "कच्चे फ्रेम" का आकार बिल्कुल इनपुट बफर की क्षमता के समान है? (यदि नहीं ... क्यों नहीं?) – fadden
@fadden इससे कोई फर्क नहीं पड़ता कि मैं इसे कितनी देर तक चलाने देता हूं लेकिन इनपुट इनपुट बफर में हमेशा 5 फ्रेम होते हैं। सृजन पर इसका उत्पादन है: 'I/OMXClient (11245): क्लाइंट-साइड ओएमएक्स मक्स का उपयोग करना। I/ACodec (11245): setupVideoEncoder सफल हुआ 'चयनित रंग प्रारूप दोनों मामलों में है' MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar' (यदि मैं सभी प्रारूपों से पूछता हूं कि इसमें केवल दो हैं, उपरोक्त और एक जिसमें 2130708361 है जो चयनित होने पर क्रैश हो ।) कच्चे फ्रेम और इनपुट बफर समान नहीं हैं (कच्चे फ्रेम का आकार हमेशा छोटा होता है और इनपुट बफर क्षमता हमेशा 282624 होती है) – lowtraxx
पांच फ्रेम सामान्य होते हैं - लगता है जैसे यह इनपुट प्रसंस्करण नहीं कर रहा है, इसलिए कोई आउटपुट नहीं है। मुझे लगता है कि आप 'encoder.start()' को कॉल कर रहे हैं? YUV420SemiPlanar अच्छा है; 2130708361 केवल सतह इनपुट के लिए उपयोग किया जाता है। एक YUV420 बफर का आकार 'चौड़ाई * ऊंचाई * 1.5', या 460800 बाइट होना चाहिए, इसलिए मैं आपके बफर आकार के बारे में थोड़ा उलझन में हूं। क्या आप लॉग फ़ाइल में अपना "मीडिया प्रारूप बदल गया" संदेश देखते हैं, और यदि ऐसा है, तो यह क्या कहता है? – fadden