البرمجة

حل مشكلة ترميز YUV420p باستخدام MediaCodec

عند استخدام MediaCodec لترميز الفيديو باستخدام تنسيق الألوان COLOR_FormatYUV420Flexible، يجب أن تتأكد من أن الأجهزة التي تستخدمها تدعم هذا التنسيق. على الرغم من أن هذا التنسيق مدعوم منذ API 21، إلا أن بعض الأجهزة قد تواجه مشكلة في استرجاع الصورة الخام (Image) باستخدام getInputImage، كما تظهر في حالتك مع هواوي P7 وموتورولا Moto X Pro.

حتى تتمكن من التعامل مع هذه المشكلة، يمكنك استخدام الطريقة الأولى التي وصفتها بتعبئة البيانات مباشرة في الـ ByteBuffer الذي تحصل عليه من dequeueInputBuffer، وذلك بدلاً من الاعتماد على getInputImage. يمكنك محاولة تعيين القيم المباشرة في الـ ByteBuffer واختبارها على الأجهزة التي تواجه مشكلة.

على الرغم من أن هذا الحل قد يعمل، إلا أنه ليس الأمثل، لذا يجب عليك البحث عن حلول أخرى قد تكون أفضل. يمكنك مراجعة منتديات المطورين أو الوثائق الرسمية لـ Android لمعرفة ما إذا كان هناك حلاً أفضل لمشكلتك.

المزيد من المعلومات

عند استخدام COLOR_FormatYUV420Flexible في MediaCodec، يجب أن تتأكد من مطابقة تنسيق الألوان مع بيانات الفيديو الخام التي تقدمها. يعتمد تنسيق YUV420 على ترتيب محدد للمكونات (Y، U، V) وحجم معين لكل مكون.

إذا كنت تعالج بيانات YUV420p، يجب أن تتأكد من ترتيب البيانات وحجم الإطارات (frames) الخاصة بك. الشكل القياسي للإطار YUV420p هو كالتالي:

  • المكون Y (السطوع) يأخذ مكانًا في البداية مع حجم نفس حجم الإطار.
  • المكون U (اللون الأزرق) يأتي بعد Y بنسبة 1:4 من حجم الإطار.
  • المكون V (اللون الأحمر) يأتي بعد U بنسبة 1:4 من حجم الإطار.

عند تعيين البيانات في الـ ByteBuffer، يجب أن تكون متأكدًا من مطابقة ترتيب البيانات وحجم الإطارات لتنسيق YUV420p. إذا كان هذا الترتيب غير صحيح، فقد يؤدي ذلك إلى ظهور ألوان غير صحيحة عند تشفير الفيديو.

يمكنك استخدام الشفرة التالية كمرجع لتعيين البيانات في الـ ByteBuffer بترتيب YUV420p الصحيح:

java
int width = ...; // عرض الإطار int height = ...; // ارتفاع الإطار int strideY = width; int strideUV = (width + 1) / 2; ByteBuffer inputBuffer = inputBuffers[inputBufferIndex]; inputBuffer.clear(); // Fill Y plane for (int y = 0; y < height; y++) { inputBuffer.put(yuv420pData, y * width, width); } // Fill U and V planes for (int y = 0; y < height / 2; y++) { inputBuffer.put(yuv420pData, width * height + y * strideUV, strideUV); } for (int y = 0; y < height / 2; y++) { inputBuffer.put(yuv420pData, width * height + strideUV * (height / 2 + y), strideUV); }

حيث yuv420pData هو مصفوفة تحتوي على البيانات الخام YUV420p.

زر الذهاب إلى الأعلى