Software decoding — عملية فك ضغط بيانات الوسائط باستخدام المعالج المركزي (CPU) عبر مكتبات برمجية، دون استخدام كتل أجهزة SoC. يتم تنفيذ مفككات التشفير البرمجية كمكتبات عبر المنصات: FFmpeg مع libavcodec وdav1d لـ AV1. وفقًا لـ توثيق FFmpeg (2026)، يدعم libavcodec أكثر من 200 ترميز، مما يجعل software decoding الطريقة الوحيدة لتشغيل التنسيقات النادرة.
الملامح الرئيسية
Software decoding هو طريقة لفك ضغط بيانات الوسائط حيث يتم تنفيذ جميع العمليات الحسابية على أنوية CPU ذات الأغراض العامة. على عكس فك التشفير بالأجهزة، حيث يكون لكل ترميز كتلة مادية مخصصة، فإن مفكك التشفير البرمجي هو كود عادي ينفذ نفس الخوارزميات باستخدام تعليمات المعالج.
تكتب مفككات التشفير البرمجية بلغة C/C++ باستخدام تحسينات لبنى CPU محددة: تعليمات SIMD ARM NEON للأجهزة المحمولة، Intel SSE/AVX لأجهزة سطح المكتب. تحتوي مكتبة libavcodec من FFmpeg على عشرات الآلاف من أسطر كود التجميع المحسّن لمنصات مختلفة، مما يسمح لفك التشفير البرمجي بتحقيق أداء لائق حتى للتنسيقات الثقيلة مثل AV1 على CPUs القوية.
الميزة الرئيسية لفك التشفير البرمجي هي التنوع. إذا كان مفكك التشفير بالأجهزة يدعم فقط 4–5 تنسيقات رئيسية (H.264, H.265, VP9, AV1)، فيمكن لـ FFmpeg فك تشفير أكثر من 200 ترميز: من AV1 وH.265 الحديثين إلى Sorenson Spark وRealVideo وMotion JPEG. هذا يجعل فك التشفير البرمجي أداة لا غنى عنها للتطبيقات التي تعمل مع بيانات وسائط غير قياسية — مثل محرري الفيديو المحترفين وأنظمة المراقبة بالفيديو والمشغلات المتخصصة.
يتبع فك التشفير البرمجي نفس المراحل التي يتبعها فك التشفير بالأجهزة، ولكن على CPU للأغراض العامة. يتم تنفيذ كل مرحلة كدوال تُستدعى بالتسلسل لكل macroblock أو إطار. الفرق الرئيسي هو المرونة: يمكن للمطور تعديل خط الأنابيب وإضافة المرشحات والمعالجة اللاحقة بين مراحل فك التشفير.
يتكون مفكك التشفير البرمجي النموذجي من وحدات تنفذ مراحل خوارزمية فردية. تقرأ وحدة فك التشفير الإحصائي تدفق البتات وتستعيد معاملات DCT المكممة. بالنسبة لـ H.264، تنفذ هذه الوحدة CABAC (الترميز الحسابي الثنائي المتكيف مع السياق) — خوارزمية معقدة ذات فروع شرطية يصعب تسريعها بالأجهزة ولكنها تعمل بكفاءة على CPU مع متنبئ فروع جيد.
تضرب وحدة التكميم العكسي المعاملات في خطوة التكميم، وتطبق وحدة DCT العكسية تحويل جيب التمام المتقطع. يستخدم التنفيذ البرمجي لـ DCT العكسية خوارزمية Chen السريعة أو خوارزمية Loeffler، اللتين تقلصان عدد عمليات الضرب-التراكم من 4096 إلى 256 لكتلة 8x8. تسمح تعليمات SIMD NEON (ARM) أو SSE (x86) بمعالجة 4–8 معاملات لكل تعليمة، مما يوفر تسريعًا بمقدار 4–8 مرات مقارنة بالكود العددي.
وحدة تعويض الحركة هي الأكثر استهلاكًا للذاكرة. تستخرج المناطق من الإطارات المرجعية وفقًا لمتجهات الحركة وتطبق الاستيفاء دون البكسل. بالنسبة لـ H.265، تصل دقة الاستيفاء إلى 1/8 بكسل، مما يتطلب مرشح FIR بـ 8 نقاط للإضاءة و4 نقاط للون. يضطر التنفيذ البرمجي إلى تحميل كميات كبيرة من بيانات الإطارات المرجعية من ذاكرة التخزين المؤقت، مما يجعل تعويض الحركة عنق زجاجة عند فك تشفير الدقة العالية على CPU.
تحتوي المعالجات المحمولة الحديثة، مثل Apple A17 أو Qualcomm Snapdragon 8 Gen 2، على 6–8 أنوية بأداء كافٍ لفك التشفير البرمجي لـ 1080p H.264 دون فقدان الإطارات. ومع ذلك، بالنسبة لمحتوى 4K، خاصة بتنسيقات H.265 وAV1، قد يواجه فك التشفير البرمجي على CPU صعوبات: يصل الحمل النموذجي لجميع الأنوية إلى 70–90%، وهو أمر بالغ الأهمية لتعدد المهام. توفر الأنوية الكبيرة (Apple Performance, Qualcomm Kryo Prime) أداءً ~4–5 مرات مقارنة بالأنوية الصغيرة الموفرة للطاقة، ولكنها تستهلك طاقة أكثر نسبيًا.
يضم سوق مفككات التشفير البرمجية عدة مكتبات رئيسية، كل منها محسّنة لمجالها. يعتمد اختيار مفكك التشفير على التنسيقات المطلوبة والمنصة وقيود الترخيص.
FFmpeg هو المعيار الفعلي لفك التشفير البرمجي في الصناعة. تتضمن مكتبة libavcodec مفككات تشفير لجميع الترميزات الرئيسية ومعظم الترميزات النادرة، وتدعم جميع الحاويات (MP4, MKV, AVI, MOV, WebM) وتعمل على جميع المنصات. FFmpeg مرخص بموجب LGPL/GPL، مما يتطلب الامتثال لشروط الترخيص للاستخدام التجاري. على الأجهزة المحمولة، يُستخدم FFmpeg عبر أغلفة: ffmpeg-kit لنظامي iOS وAndroid، mobile-ffmpeg لـ React Native.
Dav1d هو مفكك تشفير برمجي لـ AV1 من VideoLAN (مطوري VLC)، مكتوب بلغة C مع تحسينات SIMD. هدفه الرئيسي هو أسرع فك تشفير برمجي ممكن لـ AV1 على CPUs بدون دعم أجهزة. Dav1d أسرع بنسبة 30–50% من مفكك التشفير المرجعي libaom من Alliance for Open Media بفضل التحسينات القوية: إدارة يدوية للذاكرة المؤقتة، وتجميع JIT لمرشحات المعالجة اللاحقة، وتحويل الوظائف الحرجة إلى متجهات.
على الأجهزة المحمولة، يمكن لـ dav1d فك تشفير 1080p AV1 في الوقت الفعلي على SoCs الرائدة (Apple A16+, Snapdragon 8 Gen 2+)، لكن 4K يتطلب CPU قويًا. على سبيل المثال، على Apple M1، يحقق dav1d البرمجي ~60 FPS لـ 4K AV1، بينما على Snapdragon 8 Gen 2 يصل إلى ~35 FPS. للتشغيل المستقر لـ 4K AV1 على الأجهزة المحمولة، لا يزال دعم الأجهزة موصى به.
| مفكك التشفير | التنسيقات | المنصات | الترخيص |
|---|---|---|---|
| libavcodec | 200+ ترميز | الكل | LGPL/GPL |
| dav1d | AV1 | الكل | BSD 2-Clause |
| libaom | AV1 | الكل | BSD 2-Clause |
| MediaFoundation | H.264, H.265 | Windows | امتلاكي |
الاختيار بين فك التشفير البرمجي والأجهزة هو مفاضلة بين التوافق والكفاءة. يقدم الجدول أدناه مقارنة مفصلة للخصائص الرئيسية.
| المعامل | Software Decoding | Hardware Decoding |
|---|---|---|
| التنسيقات المدعومة | 200+ ترميز | 4–6 ترميزات |
| استهلاك الطاقة | 1,5–5 واط | 0,2–0,8 واط |
| التخصيص | تحكم كامل في خط الأنابيب | فقط عبر API |
| زمن الاستجابة | 30–80 مللي ثانية | 5–15 مللي ثانية |
| تبديد الحرارة | مرتفع (45–50 درجة) | منخفض (35–40 درجة) |
| تحديث الترميزات | عبر تحديث المكتبة | فقط مع SoC جديد |
فك التشفير البرمجي يوفر أقصى مرونة: يمكن للمطور تعديل الخوارزميات وإضافة مرشحات مخصصة وتنفيذ خطوط أنابيب معالجة خاصة. على سبيل المثال، في تطبيقات تحرير الفيديو، يمكن توجيه كل مرحلة من مراحل فك التشفير إلى GPU لتصحيح الألوان أو تراكب التأثيرات — وهذا ممكن فقط مع التحكم البرمجي في فك التشفير.
ومع ذلك، ثمن المرونة هو استهلاك الطاقة. بالنسبة للأجهزة المحمولة ببطارية 3000–5000 مللي أمبير في الساعة، يقلل فك التشفير البرمجي المستمر من وقت المشاهدة من 10–15 ساعة (الأجهزة) إلى 2–4 ساعات. يمكن أن يسبب تسخين CPU إلى 45–50 درجة أيضًا اختناقًا حراريًا — انخفاضًا في تردد المعالج لمنع ارتفاع الحرارة، مما يؤدي إلى فقدان الإطارات وتدهور تجربة المستخدم.
دعونا ننظر في تنفيذ عملي لفك التشفير البرمجي على كلتا المنصتين المحمولتين. على iOS، يُستخدم فك التشفير البرمجي عبر FFmpeg، وعلى Android — عبر نفس المكتبة بغلاف Java/Kotlin.
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}
class SoftwareDecoder {
AVCodecContext* codecCtx;
public:
bool init(const char* filename) {
AVFormatContext* fmtCtx = nullptr;
avformat_open_input(&fmtCtx, filename, nullptr, nullptr);
avformat_find_stream_info(fmtCtx, nullptr);
int videoStream = av_find_best_stream(
fmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0
);
AVCodec* decoder = avcodec_find_decoder(
fmtCtx->streams[videoStream]->codecpar->codec_id
);
codecCtx = avcodec_alloc_context3(decoder);
avcodec_parameters_to_context(codecCtx,
fmtCtx->streams[videoStream]->codecpar);
avcodec_open2(codecCtx, decoder, nullptr);
return true;
}
AVFrame* decodePacket(AVPacket* packet) {
avcodec_send_packet(codecCtx, packet);
AVFrame* frame = av_frame_alloc();
int ret = avcodec_receive_frame(codecCtx, frame);
return (ret >= 0) ? frame : nullptr;
}
};
يوضح الكود خط أنابيب FFmpeg أدنى لفك التشفير البرمجي. avformat_open_input يفتح الملف ويحدد تنسيق الحاوية، ويجد avcodec_find_decoder تلقائيًا مفكك تشفير مناسب لأي ترميز. تستخدم طريقة decodePacket واجهة API الجديدة (avcodec_send_packet / avcodec_receive_frame)، التي تدعم فك التشفير متعدد الخيوط مع تمكين علم AV_CODEC_FLAG_LOW_DELAY للتطبيقات في الوقت الفعلي.
class SoftwareDecoder(private val context: Context) {
fun decodeVideo(inputPath: String, outputFolder: String) {
val cmd = "-i $inputPath -vf fps=1 $outputFolder/frame_%04d.jpg"
FFmpegExecutor(context).executeCommand(cmd) { rc ->
Log.d("Decoder", "Finished with rc: $rc")
}
}
fun getFrameCount(filePath: String): Int {
val probe = MediaMetadataRetriever()
probe.setDataSource(filePath)
val duration = probe.extractMetadata(
MediaMetadataRetriever.METADATA_KEY_DURATION
)?.toIntOrNull() ?: 0
val fps = probe.extractMetadata(
MediaMetadataRetriever.METADATA_KEY_VIDEO_FRAME_COUNT
)?.toIntOrNull() ?: 0
probe.release()
return fps
}
}
يستخدم مثال Kotlin FFmpegExecutor لاستخراج إطار واحد في الثانية من الفيديو. تنشئ المعلمة -vf fps=1 مرشحًا يتخطى 59 إطارًا من كل 60، مما يقلل من حمل CPU. هذا النهج مفيد لإنشاء معاينات ونماذجplaceholder في التطبيقات المحمولة. لفك التشفير البرمجي في الوقت الفعلي، يُوصى باستخدام واجهة API منخفضة المستوى لـ libavcodec مباشرة عبر JNI.
#include <dav1d/dav1d.h>
int decode_av1_frame(const uint8_t* data, size_t size) {
Dav1dContext* ctx = nullptr;
Dav1dSettings settings = { 0 };
dav1d_default_settings(&settings);
settings.n_threads = 4;
dav1d_open(&ctx, &settings);
Dav1dData dav1d_data = { 0 };
dav1d_data_wrap(&dav1d_data, data, size, nullptr, nullptr);
Dav1dPicture pic = { 0 };
if (dav1d_send_data(ctx, &dav1d_data) == 0) {
dav1d_get_picture(ctx, &pic);
}
dav1d_close(&ctx);
return pic.p.w;
}
يوفر Dav1d واجهة API بسيطة: dav1d_open ينشئ سياق مفكك تشفير بعدد محدد من الخيوط، ويقبل dav1d_send_data تدفق البتات المضغوط، ويعيد dav1d_get_picture الإطار المفكوك بتنسيق YUV420. بالنسبة للأجهزة المحمولة، العدد الأمثل للخيوط (n_threads) هو عدد أنوية CPU الأدائية ناقص واحد، لترك موارد لخيط واجهة المستخدم. يدعم Dav1d أيضًا Dav1dPicAllocator لإدارة الذاكرة وتجنب النسخ غير الضروري عند نقل الإطارات إلى GPU.
على الرغم من استهلاك الطاقة الأعلى، فإن فك التشفير البرمجي لا غنى عنه في عدة سيناريوهات حيث لا يمكن لفك التشفير بالأجهزة توفير الوظائف المطلوبة. يساعد فهم هذه السيناريوهات المطورين على اتخاذ قرارات معمارية.
تدعم مفككات التشفير بالأجهزة التنسيقات الحديثة فقط. إذا كان التطبيق يعمل مع تسجيلات أرشيفية، أو مراقبة فيديو (MJPEG, H.263)، أو ترميزات احترافية (ProRes, DNxHD, CineForm)، أو محتوى من مصادر خارجية — سيكون فك التشفير البرمجي عبر FFmpeg هو الخيار الوحيد. يتم فك تشفير ProRes برمجيًا فقط على جميع الأجهزة باستثناء شرائح Apple A13+ مع دعم الأجهزة. بالنسبة لـ H.263، لا يوجد دعم أجهزة على أي SoC حديثة — فقط فك التشفير البرمجي.
يوفر فك التشفير البرمجي وصولاً كاملاً إلى كل مرحلة من مراحل معالجة الإطار. هذا أمر بالغ الأهمية للتطبيقات التي تحتاج إلى تطبيق مرشحات (التمويه، تقليل الضوضاء، زيادة الحدة) مباشرة على البيانات المفكوكة قبل الإخراج. تسمح مرشحات FFmpeg ببناء سلاسل معقدة: فك التشفير -> تصحيح الألوان -> تغيير الحجم -> تراكب الترجمة -> الترميز — كل ذلك ضمن مكتبة واحدة دون نقل البيانات بين واجهات API مختلفة.
البنية الموصى بها لمشغل الوسائط هي هجينة: فك التشفير بالأجهزة كأساسي، وفك التشفير البرمجي كـ fallback. قبل التشغيل، يتحقق التطبيق من توفر مفكك تشفير بالأجهزة للترميز المحدد. إذا لم يتم العثور على مفكك تشفير، يبدأ فك التشفير البرمجي عبر FFmpeg. هذه الاستراتيجية تضمن أقصى توافق دون التضحية بالأداء للتنسيقات الرئيسية. يجب إجراء فحوصات التوفر عند كل تشغيل، حيث قد يختلف دعم الأجهزة حتى على أجهزة من نفس الطراز بسبب مراجعات SoC المختلفة.
الأسئلة الشائعة
CPU هو معالج للأغراض العامة يقوم بالعديد من المهام المختلفة. لفك التشفير، يستخدم وحدات حوسبة مشتركة وذاكرة تخزين مؤقت تستهلك الطاقة حتى عند أداء مهمة واحدة. مفكك التشفير بالأجهزة هو دائرة متخصصة للغاية بخط أنابيب ثابت، حيث كل ترانزستور مخصص فقط لفك التشفير، مما يقلل استهلاك الطاقة بشكل جذري.
لـ H.264/H.265 — libavcodec من FFmpeg مع تحسينات SIMD المفعلة. لـ AV1 — dav1d، الأسرع بنسبة 30–50% من libaom المرجعي. على الأجهزة المحمولة، يسمح أداء dav1d بفك تشفير 1080p AV1 في الوقت الفعلي على SoCs الرائدة (A16+, Dimensity 9200+).
نعم، FFmpeg منقول لكلتا المنصتين. لنظام iOS، استخدم ffmpeg-kit — بناء جاهز مع دعم جميع الترميزات والتنسيقات. لنظام Android — mobile-ffmpeg أو قم ببناء FFmpeg عبر NDK. ضع في اعتبارك قيود الترخيص GPL/LGPL للتوزيع التجاري.
فك التشفير في الوقت الفعلي يعني أن CPU يمكنه فك تشفير الإطارات أسرع من عرضها على الشاشة (عادة 30 أو 60 FPS). لـ 1080p H.264، يتعامل معه CPU محمول حديث بسهولة، مستخدمًا حوالي 30–50% من نواة أداء واحدة. لـ 4K H.265، الوقت الفعلي على CPU ممكن فقط على SoCs الرائدة مع تحميل 70–90% لجميع الأنوية.
استخدم فك التشفير متعدد الخيوط (التوازي على مستوى الإطار) عبر FFmpeg مع علم thread_count، واضبط skip_frame على B-frames (إذا كان مقبولاً للسيناريو)، وقلل الدقة عبر مرشح scale قبل فك التشفير. لـ AV1 مع dav1d، استخدم n_threads = عدد أنوية CPU ناقص واحد.
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا