Как вызывать функцию FFmpeg main() из Qt
Как можно вызывать функцию из \fftols\ffmpeg.c c параметрами
> ffmpeg {1} {2} -i {3} {4} {5}, где:
{1} — глобальные параметры
{2} — параметры входного файла
{3} — входящий URL
{4} — параметры выходного файла
{5} — исходящий URL
В QtCreator?
Я скачал .zip архив FFmpeg: https://github.com/FFmpeg/FFmpeg
И поместил данный архив в корень своего тестового проекта на QT где лежит .pro файл, который хочу запустить на android
Переименовал в файле \fftols\ffmpeg.c функцию int main(int argc, char **argv) на int ffmpeg_main(int argc, char **argv) дабы не возникали ошибки с вызовом этой функции
По началу ругалось на отсутствие файла avconfig.h
Добавил её собственноручно взяв образец из интернета
/* Generated by ffmpeg configure */
#ifndef AVUTIL_AVCONFIG_H
#define AVUTIL_AVCONFIG_H
#define AV_HAVE_BIGENDIAN 0
#define AV_HAVE_FAST_UNALIGNED 0
#endif /* AVUTIL_AVCONFIG_H */
В самом .pro файле добавил:
INCLUDEPATH += $$PWD/FFmpeg
После этого данный код собрался в Qt для android arm64-v8a c компилятором Android Clang
#include "mainwindow.h"
#include <QApplication>
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavutil/opt.h"
#include "libswscale/swscale.h"
#include "libavfilter/avfilter.h"
#include "libavutil/log.h"
#include "libavutil/imgutils.h"
}
// Extermal Functions Declaration
extern "C"
{
// помните, мы переименовали main() функцию в ffmpeg.c в ffmpeg_main() вот здесь она и декларируется
int ffmpeg_main(int argc, char **argv);
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
//ffmpeg();
w.show();
return a.exec();
}
Но когда я хочу взывать функцию ffmpeg_main()
void ffmpeg()
{
int argc = 5;
char* argv[5] = { "ffmpeg", "-i", "//storage//extSdCard//DCIM//Camera//video.mp4", "-an", "//storage//extSdCard//DCIM//Camera//video_no_audio.mp4"};
// вызов этой функции с такими аргументами это то же самое, как если бы вы запустили в консоли программу ffmpeg.exe с такими параметрами:
// > ffmpeg.exe -i "storage/extSdCard/DCIM/Camera/video.mp4" -an "storage/extSdCard/DCIM/Camera/video_no_audio.mp4"
// параметр -an говорит ffmpeg удалить аудио подток из файла, короче убрать звук и сохранить новый файл в video_no_audio.mp4
ffmpeg_main(argc, argv);
}
Возникает ошибка undefined reference to "ffmpeg_main"
Я много раз натыкался, что нужно перед использованием собирать FFmpeg. В моём случае я так понимаю в файлы .so для android. Но не понимаю зачем, если все исходники .c/.h файлов есть и можно их подключить в проект? Можно ли как-то без предварительной конфигурации FFmpeg обойтись и просто вызвать функцию ffmpeg_main() в Qt?
Ответы (2 шт):
Вы изменили имя функции, и теперь нужно перекомпилировать код. Изменение имени и сигнатуры функций требует перекомпиляции самого файла (translation unit) и всех зависимых файлов, потому что меняются таблицы импорта и экспорта в объектных модулях. А вот изменение самого алгоритма внутри функции требует только перекомпиляции одного файла. Короче, вам нужно сбилдить FFmpeg самому. И не факт, что у вас это получится после модификации исходного кода. А поставленной задачи можно добиться, используя саму библиотеку FFmpeg, вместо FFTools.
В итоге пришлось все таки использовать .so файлы.
На windows, как указано в разных источниках у меня не удалось из скаченных исходников собрать свои .so библиотеки, поэтому я скачал mobile-ffmpeg-full-gpl-4.3.2.aar
по ссылке https://github.com/tanersener/mobile-ffmpeg/releases/tag/v4.3.2. Открыл данный файл WinRar и вытащил все .so файлы из архитектур armeabi-v7a и arm64-v8a в папке Jni подключил эти библиотеки в .pro файл с помощью LIBS +=\.
По ссылке https://github.com/tanersener/mobile-ffmpeg/tree/master/src/ffmpeg скачал по новой FFMPEG libav и закинул его в проект. Указал с помошью INCLUDEPATH +=\ путь куда я его закинул.
Данные файлы h.\c. закинул туда же где лежат остальные файлы https://github.com/tanersener/mobile-ffmpeg/tree/master/android/app/src/main/cpp
В самом проекте библиотеки подключается так:
#ifdef __cplusplus
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include "libavutil/opt.h"
#include "libavfilter/avfilter.h"
#include "libavutil/log.h"
#include "libavutil/imgutils.h"
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "libavcodec/jni.h"
#include "libavutil/bprint.h"
}
// Extermal Functions Declaration
extern "C"
{
int ffmpeg_execute(int argc, char** argv);
}
#endif
А вызов команды для FFmpeg так:
int argc = 5;
string SPath = "storage/emulated/0/Video.mp4
string NewStr = "storage/emulated/0/NewVideoNoSound.mp4
// здесь путь к фидеофайлу может отличаться, запишите на видеокамеру что-ниубдь и пропишите здесь путь к этомй файлу
// FFmpeg поддерживает целую тучу кодеков и форматов, так что это не обязательно должен быть mp4
const char* argv[5] = { "ffmpeg", "-i", SPath.c_str(), "-an", NewStr.c_str() };
// вызов этой функции с такими аргументами это то же самое, как если бы вы запустили в консоли программу ffmpeg.exe с такими параметрами:
// > ffmpeg.exe -i "storage/extSdCard/DCIM/Camera/video.mp4" -an "storage/extSdCard/DCIM/Camera/video_no_audio.mp4"
// параметр -an говорит ffmpeg удалить аудио подток из файла, короче убрать звук и сохранить новый файл в video_no_audio.mp4
ffmpeg_execute(argc, const_cast<char**>(argv));
Хочу заметить, что функция main() в ffmpeg.c уже переименована на ffmpeg_execute() в этом коде на GitHub. Поэтому вы лишь пишете её прототип через extern "c" и вызываете её с нужной вам командой.