Software decoding — فرآیند decompress دادههای رسانهای توسط واحد پردازش مرکزی (CPU) با استفاده از کتابخانههای نرمافزاری، بدون استفاده از بلوکهای سختافزاری SoC است. دیکدرهای نرمافزاری به صورت کتابخانههای چندسکویی پیادهسازی شدهاند: FFmpeg با libavcodec و dav1d برای AV1. طبق مستندات FFmpeg (2026)، libavcodec از بیش از 200 کدک پشتیبانی میکند که software decoding را به تنها راه پخش فرمتهای نادر تبدیل میکند.
نکات اصلی
Software decoding — روشی برای decompress دادههای رسانهای است که در آن تمام عملیات محاسباتی روی هستههای عمومی CPU انجام میشود. برخلاف دیکدینگ سختافزاری که هر کدک یک بلوک فیزیکی اختصاصی دارد، دیکدر نرمافزاری کدی معمولی است که همان الگوریتمها را با دستورالعملهای پردازنده اجرا میکند.
دیکدرهای نرمافزاری به زبان C/C++ با استفاده از بهینهسازیهای متناسب با معماریهای خاص CPU نوشته میشوند: دستورالعملهای SIMD ARM NEON برای دستگاههای موبایل، Intel SSE/AVX برای دسکتاپ. کتابخانه libavcodec از FFmpeg شامل دهها هزار خط کد اسمبلی بهینهسازی شده برای پلتفرمهای مختلف است که به دیکدینگ نرمافزاری امکان میدهد حتی برای فرمتهای سنگین مانند AV1 روی CPUهای قدرتمند به عملکرد مناسبی دست یابد.
مزیت اصلی دیکدینگ نرمافزاری — جهانی بودن است. اگر دیکدر سختافزاری تنها 4–5 فرمت اصلی (H.264، H.265، VP9، AV1) را پشتیبانی میکند، FFmpeg میتواند بیش از 200 کدک را دیکد کند: از AV1 و H.265 مدرن گرفته تا Sorenson Spark، RealVideo و Motion JPEG قدیمی. این امر دیکدینگ نرمافزاری را به ابزاری ضروری برای برنامههایی تبدیل میکند که با دادههای رسانهای غیراستاندارد کار میکنند — مانند ویرایشگرهای حرفهای ویدئو، سیستمهای نظارت تصویری و پخشکنندههای تخصصی.
دیکدینگ نرمافزاری همان مراحل دیکدینگ سختافزاری را تکرار میکند، اما روی CPU عمومی. هر مرحله به صورت توابعی پیادهسازی میشود که به ترتیب برای هر ماکروبلاک یا فریم فراخوانی میشوند. تفاوت کلیدی — انعطافپذیری است: توسعهدهنده میتواند pipeline را تغییر دهد، بین مراحل دیکدینگ فیلترها و پردازش بعدی اضافه کند.
یک دیکدر نرمافزاری معمولی از ماژولهایی تشکیل شده است که مراحل جداگانه الگوریتم را پیادهسازی میکنند. ماژول دیکدینگ آنتروپی جریان بیت را میخواند و ضرایب DCT کوانتیزه شده را بازسازی میکند. برای H.264 این ماژول CABAC (Context-Adaptive Binary Arithmetic Coding) — الگوریتم پیچیدهای با انشعابات شرطی را پیادهسازی میکند که به سختی شتاب سختافزاری میگیرد، اما روی 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 از طریق wrapperها استفاده میشود: ffmpeg-kit برای iOS و Android، mobile-ffmpeg برای React Native.
Dav1d — دیکدر نرمافزاری AV1 از VideoLAN (توسعهدهندگان VLC)، نوشته شده به زبان C با بهینهسازیهای SIMD. وظیفه اصلی آن — سریعترین دیکدینگ نرمافزاری AV1 روی CPU بدون پشتیبانی سختافزاری است. Dav1d 30–50% سریعتر از دیکدر مرجع libaom از Alliance for Open Media است به لطف بهینهسازیهای تهاجمی: مدیریت دستی کش، استفاده از JIT-کامپایل برای فیلترهای پردازش بعدی و بردارسازی توابع بحرانی.
در دستگاههای موبایل dav1d میتواند 1080p AV1 را در زمان واقعی روی SoCهای پرچمدار (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 وات |
| سفارشیسازی | کنترل کامل روی pipeline | فقط از طریق API |
| تأخیر | 30–80 میلیثانیه | 5–15 میلیثانیه |
| تولید گرما | زیاد (45–50 درجه) | کم (35–40 درجه) |
| بهروزرسانی کدک | با بهروزرسانی کتابخانه | فقط با SoC جدید |
دیکدینگ نرمافزاری حداکثر انعطافپذیری را فراهم میکند: توسعهدهنده میتواند الگوریتمها را تغییر دهد، فیلترهای سفارشی اضافه کند، خطوط لوله پردازش خود را پیادهسازی کند. مثلاً در برنامههای ویرایش ویدئو، هر مرحله دیکدینگ میتواند برای تصحیح رنگ یا اعمال افکت به GPU هدایت شود — این فقط با کنترل نرمافزاری روی دیکدینگ ممکن است.
اما بهای انعطافپذیری — مصرف انرژی است. برای دستگاههای موبایل با باتری 3000–5000 میلیآمپر ساعت، دیکدینگ نرمافزاری مداوم زمان تماشا را از 10–15 ساعت (سختافزاری) به 2–4 ساعت کاهش میدهد. گرمایش CPU تا 45–50 درجه همچنین میتواند باعث throthling — کاهش فرکانس پردازنده برای محافظت از گرمای بیش از حد شود که منجر به افت فریم و بدتر شدن تجربه کاربری میشود.
پیادهسازی عملی دیکدینگ نرمافزاری را در هر دو پلتفرم موبایل بررسی میکنیم. در iOS دیکدینگ نرمافزاری از طریق FFmpeg استفاده میشود، در Android — از همان کتابخانه با wrapper 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;
}
};
کد یک pipeline حداقلی 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("دیکدر", "پایان یافته با 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 منهای یک است تا منبعی برای رشته UI باقی بماند. Dav1d همچنین از Dav1dPicAllocator برای مدیریت حافظه و جلوگیری از کپیهای اضافی هنگام ارسال فریم به GPU پشتیبانی میکند.
علیرغم مصرف انرژی بالاتر، دیکدینگ نرمافزاری در سناریوهایی که دیکدینگ سختافزاری نمیتواند عملکرد لازم را ارائه دهد، غیرقابل جایگزین است. درک این سناریوها به توسعهدهنده در تصمیمگیری معماری کمک میکند.
دیکدرهای سختافزاری فقط فرمتهای مدرن را پشتیبانی میکنند. اگر برنامه با ضبطهای آرشیوی، نظارت تصویری (MJPEG، H.263)، کدکهای حرفهای (ProRes، DNxHD، CineForm) یا محتوای منابع شخص ثالث کار میکند — دیکدینگ نرمافزاری از طریق FFmpeg تنها گزینه خواهد بود. ProRes روی همه دستگاهها به جز تراشههای Apple A13+ با پشتیبانی سختافزاری به صورت نرمافزاری دیکد میشود. برای H.263 هیچ پشتیبانی سختافزاری روی هیچ SoC مدرنی وجود ندارد — فقط دیکدینگ نرمافزاری.
دیکدینگ نرمافزاری دسترسی کامل به هر مرحله پردازش فریم میدهد. این برای برنامههایی که نیاز به اعمال فیلترها (محو کردن، کاهش نویز، افزایش وضوح) مستقیماً روی دادههای دیکد شده قبل از خروجی دارند، حیاتی است. فیلترهای FFmpeg امکان ساخت زنجیرههای پیچیده را فراهم میکنند: دیکدینگ -> تصحیح رنگ -> مقیاسبندی -> اضافه کردن زیرنویس -> کدگذاری — همه در یک کتابخانه بدون انتقال داده بین APIهای مختلف.
معماری توصیه شده برای پخشکننده رسانه — ترکیبی است: دیکدینگ سختافزاری به عنوان اصلی، نرمافزاری به عنوان fallback. قبل از پخش، برنامه در دسترس بودن دیکدر سختافزاری برای کدک مشخص را بررسی میکند. اگر دیکدر پیدا نشد — دیکدینگ نرمافزاری از طریق FFmpeg راهاندازی میشود. این استراتژی حداکثر سازگاری را بدون افت عملکرد برای فرمتهای اصلی تضمین میکند. بررسی در دسترس بودن باید در هر راهاندازی انجام شود، زیرا پشتیبانی سختافزاری حتی در دستگاههای یک مدل به دلیل revisیههای مختلف SoC ممکن است متفاوت باشد.
سوالات متداول
CPU یک پردازنده جهانی است که وظایف مختلف زیادی را انجام میدهد. برای دیکدینگ از بلوکهای محاسباتی مشترک و حافظه کش استفاده میکند که حتی هنگام انجام یک کار انرژی مصرف میکنند. دیکدر سختافزاری — یک مدار تخصصی با خط لوله ثابت است که هر ترانزیستور فقط در دیکدینگ شرکت دارد که مصرف انرژی را به شدت کاهش میدهد.
برای H.264/H.265 — libavcodec از FFmpeg با بهینهسازیهای SIMD فعال. برای AV1 — dav1d که 30–50% سریعتر از libaom مرجع است. در دستگاههای موبایل عملکرد dav1d امکان دیکدینگ 1080p AV1 در زمان واقعی روی SoCهای پرچمدار (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 فقط در SoCهای پرچمدار با 70–90% بار همه هستهها ممکن است.
از دیکدینگ چندنخی (frame-level parallelism) از طریق FFmpeg با پرچم thread_count استفاده کنید، skip_frame را روی فریمهای B تنظیم کنید (اگر سناریو اجازه میدهد)، رزولوشن را از طریق فیلتر scale قبل از دیکدینگ کاهش دهید. برای AV1 با dav1d از n_threads = تعداد هستههای CPU منهای یک استفاده کنید.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید