ترجمة FFmpeg إلى WebAssembly (= ffmpeg.js): الجزء 2 - ترجمة مع Emscripten



قائمة الأجزاء المترجمة من السلسلة:


  1. الطبخ
  2. ترجمة باستخدام Emscripten (أنت هنا)
  3. تحويل افي إلى mp4


بدءًا من هذا الجزء ، ستكون المادة أكثر تعقيدًا ، لذا لا تتردد في google أثناء القراءة ، إذا كنت لا تفهم ما يحدث.


بالإضافة إلى ذلك ، سأحاول توثيق حل المشكلات المحتملة حتى تتمكن من تجميع المكتبة بالإعدادات الخاصة بك.


في هذا الجزء سوف نحلل:


  1. كيفية إعداد بيئة لـ Emscripten في Docker
  2. باستخدام emconfigure و emmake
  3. كيفية حل المشاكل عند تجميع FFmpeg مع Emscripten



كيفية إعداد بيئة لـ Emscripten في Docker


في الجزء الأول ، قمنا بتجميع FFmpeg مع gcc ويمكننا الانتقال إلى استخدام صورة Docker مع emscripten.


سأستخدم إصدار trzeci / emscripten 1.38.45:


$ docker pull trzeci/emscripten:1.38.45 

نظرًا لأن الصورة تستغرق حوالي 1 غيغابايت ، فقد تستغرق العملية بعض الوقت.


الآن سنجد التكوين الصحيح لتجميع FFmpeg إلى رموز emscripten بالتجربة والخطأ ، مما سيتطلب المثابرة وقراءة كميات كبيرة من الوثائق. تشغيل الحاوية مع emscripten وقم بتحميل مصادر FFmpeg في الدليل / src .


 # ,      FFmpeg $ docker run -it \ -v $PWD:/src \ trzeci/emscripten:1.38.45 \ /bin/bash 

داخل الحاوية ، قم بتنفيذ ls - اللون لرؤية شيء مثل هذا:



باستخدام emconfigure و emmake . كيفية حل مشاكل التجميع


لنبدأ مع التكوين. في الجزء الأول ، أجرينا ./configure - disable-x86asm ، في emscripten يتم تحقيق ذلك باستخدام الأمر emconfigure ./configure --disable-x86asm . (للحصول على تفاصيل حول استخدام emconfigure ، انظر هنا )


 $ emconfigure ./configure --disable-x86asm 

وبما أننا لم نر أي أخطاء ، يبقى فقط تنفيذ emmake make -j4 والحصول على FFmpeg.js المطلوب؟ لسوء الحظ ، لا. واحدة من أهم مهام emconfigure هي استبدال برنامج التحويل البرمجي لـ gcc بـ emcc (أو g ++ بـ em ++) ، لكن الإخراج من ./configure لا يزال ينتج gcc.


 root@57ab95def750:/src# emconfigure ./configure --disable-x86asm emscripten sdl2-config called with /emsdk_portable/emscripten/tag-1.38.45/system/bin/sdl2-config --cflags emscripten sdl2-config called with /emsdk_portable/emscripten/tag-1.38.45/system/bin/sdl2-config --libs install prefix /usr/local source path . C compiler gcc #    emcc C library glibc ARCH x86 (generic) big-endian no runtime cpu detection yes standalone assembly no x86 assembler nasm 

أي أتمتة لها حدودها ، وفي هذه الحالة ، للأسف ، علينا أن نفعل كل شيء يدويًا. دعونا نرى ما إذا كانت هناك أي حجج لمساعدتنا:


 $ ./configure --help 

ضمن قسم خيارات Toolchain ، نرى وسيطات للإشارة إلى نوع برنامج التحويل البرمجي.


 root@57ab95def750:/src# ./configure --help Usage: configure [options] Options: [defaults in brackets after descriptions]Help options: ... Toolchain options: ... --nm=NM use nm tool NM [nm -g] --ar=AR use archive tool AR [ar] --as=AS use assembler AS [] --ln_s=LN_S use symbolic link tool LN_S [ln -s -f] --strip=STRIP use strip tool STRIP [strip] --windres=WINDRES use windows resource compiler WINDRES [windres] --x86asmexe=EXE use nasm-compatible assembler EXE [nasm] --cc=CC use C compiler CC [gcc] --cxx=CXX use C compiler CXX [g++] --objcc=OCC use ObjC compiler OCC [gcc] --dep-cc=DEPCC use dependency generator DEPCC [gcc] --nvcc=NVCC use Nvidia CUDA compiler NVCC [nvcc] --ld=LD use linker LD [] ... 

دعونا نستخدمها في المخطوطات


 $ emconfigure ./configure \ --disable-x86asm \ --nm="llvm-nm -g" \ --ar=emar \ --cc=emcc \ --cxx=em++ \ --objcc=emcc \ --dep-cc=emcc 

سوف يستغرق التنفيذ الآن ./configure مزيدًا من الوقت ، لكن نتيجة لذلك نحصل على emcc.


 root@57ab95def750:/src# emconfigure ... emscripten sdl2-config called with /emsdk_portable/emscripten/tag-1.38.45/system/bin/sdl2-config --cflags emscripten sdl2-config called with /emsdk_portable/emscripten/tag-1.38.45/system/bin/sdl2-config --libs install prefix /usr/local source path . C compiler emcc # emcc    C library ARCH x86 (generic) big-endian no runtime cpu detection yes standalone assembly no 

دعونا نرى كيف يذهب التجميع.


 $ emmake make -j4 

وعلى الفور خطأ ...


 root@57ab95def750:/src# emmake make -j4 ... ./libavutil/x86/timer.h:39:24: error: invalid output constraint '=a' in asm : "=a" (a), "=d" (d)); ^ 

تظهر الرسالة أن الخطأ مرتبط بطريقة ما بـ ASM. افتح ./libavutil/x86/timer.h لمعرفة أن المشكلة في x86 مضمّنة المجمّع ، وهو غير متوافق مع WebAssembly ، لذلك أوقف تشغيله.


 $ emconfigure ./configure \ --disable-x86asm \ --disable-inline-asm \ #   asm --nm="llvm-nm -g" \ --ar=emar \ --cc=emcc \ --cxx=em++ \ --objcc=emcc \ --dep-cc=emcc 

دعنا نحاول تجميع مرة أخرى.


 $ emmake make -j4 

يستمر التجميع حتى الخطأ التالي.


 root@57ab95def750:/src# emmake make -j4 ... AR libavdevice/libavdevice.a AR libavfilter/libavfilter.a AR libavformat/libavformat.a AR libavcodec/libavcodec.a AR libswresample/libswresample.a AR libswscale/libswscale.a AR libavutil/libavutil.a HOSTLD doc/print_options GENTEXI doc/avoptions_format.texi /bin/sh: 1: doc/print_options: Exec format error doc/Makefile:59: recipe for target 'doc/avoptions_format.texi' failed make: *** [doc/avoptions_format.texi] Error 2 make: *** Waiting for unfinished jobs.... 

هناك شيء متعلق بتوليد الوثائق ، والتي لا نحتاج إليها مطلقًا ، لذا قم بإيقاف تشغيلها.


 $ emconfigure ./configure \ --disable-x86asm \ --disable-inline-asm \ --disable-doc \ #    --nm="llvm-nm -g" \ --ar=emar \ --cc=emcc \ --cxx=em++ \ --objcc=emcc \ --dep-cc=emcc 

نحن نفعل ذلك مرة أخرى.


 $ emmake make -j4 

الآن حدث الخطأ في مرحلة الشريط.


 root@57ab95def750:/src# emmake make -j4 ... STRIP ffmpeg STRIP ffprobe strip:ffmpeg_g: File format not recognized strip:ffprobe_g: File format not recognized Makefile:101: recipe for target 'ffmpeg' failed make: *** [ffmpeg] Error 1 make: *** Waiting for unfinished jobs.... Makefile:101: recipe for target 'ffprobe' failed make: *** [ffprobe] Error 1 

نظرًا لأن زراعة المحاصيل الأصلية لا تتوافق مع إصدار WebAssembly الخاص بنا ، فسنقوم أيضًا بتعطيله.


 $ emconfigure ./configure \ --disable-x86asm \ --disable-inline-asm \ --disable-doc \ --disable-stripping \ #  strip --nm="llvm-nm -g" \ --ar=emar \ --cc=emcc \ --cxx=em++ \ --objcc=emcc \ --dep-cc=emcc 

المحاولة الرابعة.


 $ emmake make -j4 

أخيرًا ، انتهت العملية دون أخطاء. ولكن فقط في الإخراج حصلنا على ملف ffmpeg ، الذي لا يبدأ ، وهو ليس ملف js (أو ملف wasm). للحصول على ملف js ، نحتاج إلى إضافة -o ffmpeg.js إلى أمر emcc ، والذي يمكن القيام به بطريقتين:


  1. تغيير Makefile من FFmpeg نفسها
  2. إضافة تجميع / ربط إضافية

سنختار الطريقة الثانية ، حيث أنني لا أريد أن أتطرق إلى مصادر FFmpeg بسبب الآثار الجانبية المحتملة. لذلك نجد كيف يتم إنشاء ffmpeg باستخدام make. هذا هو المكان الذي يأتي فيه خيار جعله مفيدًا لتشغيل الجفاف.


 $ emmake make -n 

نحن نرى فريق الجيل.


 root@57ab95def750:/src# emmake make -n ... printf "LD\t%s\n" ffmpeg_g; emcc -Llibavcodec -Llibavdevice -Llibavfilter -Llibavformat -Llibavresample -Llibavutil -Llibpostproc -Llibswscale -Llibswresample -Wl,--as-needed -Wl,-z,noexecstack -Wl,--warn-common -Wl,-rpath-link=libpostproc:libswresample:libswscale:libavfilter:libavdevice:libavformat:libavcodec:libavutil:libavresample -Qunused-arguments -o ffmpeg_g fftools/ffmpeg_opt.o fftools/ffmpeg_filter.o fftools/ffmpeg_hw.o fftools/cmdutils.o fftools/ffmpeg.o -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil -lm -pthread -lm -lm -pthread -lm -lm -lm -pthread -lm printf "CP\t%s\n" ffmpeg; cp -p ffmpeg_g ffmpeg ... 

هناك الكثير من الأشياء غير الضرورية ، لذلك دعونا نزيل الوسائط غير المستخدمة (التي ستراها في نهاية المجموعة) ، وقم بتنظيفها قليلاً وإعادة تسمية ffmpeg_g إلى ffmpeg.js .


 $ emcc \ -Llibavcodec -Llibavdevice -Llibavfilter -Llibavformat -Llibavresample -Llibavutil -Llibpostproc -Llibswscale -Llibswresample \ -Qunused-arguments \ -o ffmpeg.js fftools/ffmpeg_opt.o fftools/ffmpeg_filter.o fftools/ffmpeg_hw.o fftools/cmdutils.o fftools/ffmpeg.o \ -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil -lm -pthread 

كان يجب أن يكون ناجحًا ، لكننا سنواجه مشكلة نقص الذاكرة.


 root@57ab95def750:/src# emcc ... shared:ERROR: Memory is not large enough for static data (11794000) plus the stack (5242880), please increase TOTAL_MEMORY (16777216) to at least 17037904 

أضف الوسيطة TOTAL_MEMORY لزيادة حجم الذاكرة (33554432 بايت: = 32 ميغابايت).


 $ emcc \ -Llibavcodec -Llibavdevice -Llibavfilter -Llibavformat -Llibavresample -Llibavutil -Llibpostproc -Llibswscale -Llibswresample \ -Qunused-arguments \ -o ffmpeg.js fftools/ffmpeg_opt.o fftools/ffmpeg_filter.o fftools/ffmpeg_hw.o fftools/cmdutils.o fftools/ffmpeg.o \ -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil -lm -pthread \ -s TOTAL_MEMORY=33554432 

أخيرًا ، حصلنا على ملفات js و wasm


 root@57ab95def750:/src# ls ffmpeg* ffmpeg ffmpeg.js ffmpeg.js.mem ffmpeg.wasm ffmpeg.worker.js ffmpeg_g 

قم بإنشاء test.html لاختبار FFmpeg.js


 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script src="./ffmpeg.js"></script> </head> <body> </body> </html> 

لنبدأ تشغيل الخادم السهل (عن طريق تنفيذ python2 -m SimpleHTTPServer ) وفتح الصفحة الناتجة ( http: // localhost: 8000 / test.html ) ، ثم افتح Chrome DevTools.



كما ترون ، تعمل FFmpeg إلى النصف بخطيئة ، لذا يمكنك الآن بدء تلميع ffmpeg.js.


يمكن العثور على البرنامج النصي للبناء الكامل في هذا المخزون (build-with-docker.sh و build-js.sh)

.

Source: https://habr.com/ru/post/ar473134/


All Articles