FFmpegKit Linux API 6.0
Loading...
Searching...
No Matches
FFmpegKitConfig.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022 Taner Sener
3 *
4 * This file is part of FFmpegKit.
5 *
6 * FFmpegKit is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * FFmpegKit is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <pthread.h>
23extern "C" {
24 #include "libavutil/ffversion.h"
25 #include "libavutil/bprint.h"
26 #include "fftools_cmdutils.h"
27}
28#include "ArchDetect.h"
29#include "FFmpegKit.h"
30#include "FFmpegKitConfig.h"
31#include "FFmpegSession.h"
32#include "FFprobeKit.h"
33#include "FFprobeSession.h"
34#include "Level.h"
37#include "Packages.h"
38#include "SessionState.h"
39#include <atomic>
40#include <mutex>
41#include <future>
42#include <condition_variable>
43#include <iostream>
44#include <fstream>
45#include <algorithm>
46
47extern "C" {
48 void set_report_callback(void (*callback)(int, float, float, int64_t, double, double, double));
49 void cancel_operation(long id);
50}
51
55static std::atomic<long> pipeIndexGenerator(1);
56
57/* Session history variables */
59static std::map<long, std::shared_ptr<ffmpegkit::Session>> sessionHistoryMap;
60static std::list<std::shared_ptr<ffmpegkit::Session>> sessionHistoryList;
61static std::recursive_mutex sessionMutex;
62
64#define SESSION_MAP_SIZE 1000
65static std::atomic<short> sessionMap[SESSION_MAP_SIZE];
67
70
73
78
80
83static std::recursive_mutex callbackDataMutex;
84static std::mutex callbackMutex;
85static std::condition_variable callbackMonitor;
86class CallbackData;
87static std::list<CallbackData*> callbackDataList;
88
90volatile int handleSIGQUIT = 1;
91volatile int handleSIGINT = 1;
92volatile int handleSIGTERM = 1;
93volatile int handleSIGXCPU = 1;
94volatile int handleSIGPIPE = 1;
95
97__thread long globalSessionId = 0;
98
101
102#ifdef __cplusplus
103extern "C" {
104#endif
105
107int ffmpeg_execute(int argc, char **argv);
108
110int ffprobe_execute(int argc, char **argv);
111
112void ffmpegkit_log_callback_function(void *ptr, int level, const char* format, va_list vargs);
113
114#ifdef __cplusplus
115}
116#endif
117
118static std::once_flag ffmpegKitInitializerFlag;
119static pthread_t callbackThread;
120
121void* ffmpegKitInitialize();
122
124
129
130static bool fs_exists(const std::string& s, const bool isFile, const bool isDirectory) {
131 struct stat dir_info;
132
133 if (stat(s.c_str(), &dir_info) == 0) {
134 if (isFile && S_ISREG(dir_info.st_mode)) {
135 return true;
136 }
137 if (isDirectory && S_ISDIR(dir_info.st_mode)) {
138 return true;
139 }
140 }
141
142 return false;
143}
144
145static bool fs_create_dir(const std::string& s) {
146 if (!fs_exists(s, false, true)) {
147 if (mkdir(s.c_str(), S_IRWXU | S_IRWXG | S_IROTH) != 0) {
148 std::cout << "Failed to create directory: " << s << ". Operation failed with " << errno << "." << std::endl;
149 return false;
150 }
151 }
152 return true;
153}
154
156 while (sessionHistoryList.size() > sessionHistorySize) {
157 auto first = sessionHistoryList.front();
158 if (first != nullptr) {
159 sessionHistoryList.pop_front();
160 sessionHistoryMap.erase(first->getSessionId());
161 }
162 }
163}
164
165void addSessionToSessionHistory(const std::shared_ptr<ffmpegkit::Session> session) {
166 std::unique_lock<std::recursive_mutex> lock(sessionMutex, std::defer_lock);
167
168 const long sessionId = session->getSessionId();
169
170 lock.lock();
171
172 /*
173 * ASYNC SESSIONS CALL THIS METHOD TWICE
174 * THIS CHECK PREVENTS ADDING THE SAME SESSION AGAIN
175 */
176 if (sessionHistoryMap.count(sessionId) == 0) {
177 sessionHistoryMap.insert({sessionId, session});
178 sessionHistoryList.push_back(session);
180 }
181
182 lock.unlock();
183}
184
189 public:
190 CallbackData(const long sessionId, const int logLevel, const AVBPrint* data) :
191 _type{LogType}, _sessionId{sessionId}, _logLevel{logLevel} {
192 av_bprint_init(&_logData, 0, AV_BPRINT_SIZE_UNLIMITED);
193 av_bprintf(&_logData, "%s", data->str);
194 }
195
196 CallbackData(const long sessionId,
197 const int videoFrameNumber,
198 const float videoFps,
199 const float videoQuality,
200 const int64_t size,
201 const double time,
202 const double bitrate,
203 const double speed) :
205 _sessionId{sessionId},
206 _statisticsFrameNumber{videoFrameNumber},
207 _statisticsFps{videoFps},
208 _statisticsQuality{videoQuality},
209 _statisticsSize{size},
210 _statisticsTime{time},
211 _statisticsBitrate{bitrate},
212 _statisticsSpeed{speed} {
213 }
214
216 return _type;
217 }
218
220 return _sessionId;
221 }
222
224 return _logLevel;
225 }
226
227 AVBPrint* getLogData() {
228 return &_logData;
229 }
230
233 }
234
236 return _statisticsFps;
237 }
238
240 return _statisticsQuality;
241 }
242
244 return _statisticsSize;
245 }
246
248 return _statisticsTime;
249 }
250
252 return _statisticsBitrate;
253 }
254
256 return _statisticsSpeed;
257 }
258
259 private:
261 long _sessionId; // session id
262
263 int _logLevel; // log level
264 AVBPrint _logData; // log data
265
266 int _statisticsFrameNumber; // statistics frame number
267 float _statisticsFps; // statistics fps
268 float _statisticsQuality; // statistics quality
269 int64_t _statisticsSize; // statistics size
270 double _statisticsTime; // statistics time
271 double _statisticsBitrate; // statistics bitrate
272 double _statisticsSpeed; // statistics speed
273};
274
280static void callbackWait(int milliSeconds) {
281 std::unique_lock<std::mutex> callbackLock{callbackMutex};
282 callbackMonitor.wait_for(callbackLock, std::chrono::milliseconds(milliSeconds));
283}
284
288static void callbackNotify() {
289 callbackMonitor.notify_one();
290}
291
292static const char *avutil_log_get_level_str(int level) {
293 switch (level) {
294 case AV_LOG_STDERR:
295 return "stderr";
296 case AV_LOG_QUIET:
297 return "quiet";
298 case AV_LOG_DEBUG:
299 return "debug";
300 case AV_LOG_VERBOSE:
301 return "verbose";
302 case AV_LOG_INFO:
303 return "info";
304 case AV_LOG_WARNING:
305 return "warning";
306 case AV_LOG_ERROR:
307 return "error";
308 case AV_LOG_FATAL:
309 return "fatal";
310 case AV_LOG_PANIC:
311 return "panic";
312 default:
313 return "";
314 }
315}
316
317static void avutil_log_format_line(void *avcl, int level, const char *fmt, va_list vl, AVBPrint part[4], int *print_prefix) {
318 int flags = av_log_get_flags();
319 AVClass* avc = avcl ? *(AVClass **) avcl : NULL;
320 av_bprint_init(part+0, 0, 1);
321 av_bprint_init(part+1, 0, 1);
322 av_bprint_init(part+2, 0, 1);
323 av_bprint_init(part+3, 0, 65536);
324
325 if (*print_prefix && avc) {
326 if (avc->parent_log_context_offset) {
327 AVClass** parent = *(AVClass ***) (((uint8_t *) avcl) +
328 avc->parent_log_context_offset);
329 if (parent && *parent) {
330 av_bprintf(part+0, "[%s @ %p] ",
331 (*parent)->item_name(parent), parent);
332 }
333 }
334 av_bprintf(part+1, "[%s @ %p] ",
335 avc->item_name(avcl), avcl);
336 }
337
338 if (*print_prefix && (level > AV_LOG_QUIET) && (flags & AV_LOG_PRINT_LEVEL))
339 av_bprintf(part+2, "[%s] ", avutil_log_get_level_str(level));
340
341 av_vbprintf(part+3, fmt, vl);
342
343 if(*part[0].str || *part[1].str || *part[2].str || *part[3].str) {
344 char lastc = part[3].len && part[3].len <= part[3].size ? part[3].str[part[3].len - 1] : 0;
345 *print_prefix = lastc == '\n' || lastc == '\r';
346 }
347}
348
349static void avutil_log_sanitize(char *line) {
350 while(*line){
351 if(*line < 0x08 || (*line > 0x0D && *line < 0x20))
352 *line='?';
353 line++;
354 }
355}
356
363static void logCallbackDataAdd(int level, AVBPrint *data) {
364 std::unique_lock<std::recursive_mutex> lock(callbackDataMutex, std::defer_lock);
365 CallbackData* callbackData = new CallbackData(globalSessionId, level, data);
366
367 lock.lock();
368 callbackDataList.push_back(callbackData);
369 lock.unlock();
370
372
374}
375
379static void statisticsCallbackDataAdd(int frameNumber, float fps, float quality, int64_t size, int time, double bitrate, double speed) {
380 std::unique_lock<std::recursive_mutex> lock(callbackDataMutex, std::defer_lock);
381 CallbackData* callbackData = new CallbackData(globalSessionId, frameNumber, fps, quality, size, time, bitrate, speed);
382
383 lock.lock();
384 callbackDataList.push_back(callbackData);
385 lock.unlock();
386
388
390}
391
396 std::unique_lock<std::recursive_mutex> lock(callbackDataMutex, std::defer_lock);
397 CallbackData* newData = nullptr;
398
399 lock.lock();
400 if (callbackDataList.size() > 0) {
401 newData = callbackDataList.front();
402 callbackDataList.pop_front();
403 }
404 lock.unlock();
405
406 return newData;
407}
408
414static void registerSessionId(long sessionId) {
415 std::atomic_store(&sessionMap[sessionId % SESSION_MAP_SIZE], (short)1);
416}
417
423static void removeSession(long sessionId) {
424 std::atomic_store(&sessionMap[sessionId % SESSION_MAP_SIZE], (short)0);
425}
426
427#ifdef __cplusplus
428extern "C" {
429#endif
430
436void cancelSession(long sessionId) {
437 std::atomic_store(&sessionMap[sessionId % SESSION_MAP_SIZE], (short)2);
438}
439
446int cancelRequested(long sessionId) {
447 if (std::atomic_load(&sessionMap[sessionId % SESSION_MAP_SIZE]) == 2) {
448 return 1;
449 } else {
450 return 0;
451 }
452}
453
454#ifdef __cplusplus
455}
456#endif
457
463static void resetMessagesInTransmit(long sessionId) {
464 std::atomic_store(&sessionInTransitMessageCountMap[sessionId % SESSION_MAP_SIZE], 0);
465}
466
475void ffmpegkit_log_callback_function(void *ptr, int level, const char* format, va_list vargs) {
476 AVBPrint fullLine;
477 AVBPrint part[4];
478 int print_prefix = 1;
479
480 // DO NOT PROCESS UNWANTED LOGS
481 if (level >= 0) {
482 level &= 0xff;
483 }
484 int activeLogLevel = av_log_get_level();
485
486 // LevelAVLogStdErr logs are always redirected
487 if ((activeLogLevel == ffmpegkit::LevelAVLogQuiet && level != ffmpegkit::LevelAVLogStdErr) || (level > activeLogLevel)) {
488 return;
489 }
490
491 av_bprint_init(&fullLine, 0, AV_BPRINT_SIZE_UNLIMITED);
492
493 avutil_log_format_line(ptr, level, format, vargs, part, &print_prefix);
494 avutil_log_sanitize(part[0].str);
495 avutil_log_sanitize(part[1].str);
496 avutil_log_sanitize(part[2].str);
497 avutil_log_sanitize(part[3].str);
498
499 // COMBINE ALL 4 LOG PARTS
500 av_bprintf(&fullLine, "%s%s%s%s", part[0].str, part[1].str, part[2].str, part[3].str);
501
502 if (fullLine.len > 0) {
503 logCallbackDataAdd(level, &fullLine);
504 }
505
506 av_bprint_finalize(part, NULL);
507 av_bprint_finalize(part+1, NULL);
508 av_bprint_finalize(part+2, NULL);
509 av_bprint_finalize(part+3, NULL);
510 av_bprint_finalize(&fullLine, NULL);
511}
512
524void ffmpegkit_statistics_callback_function(int frameNumber, float fps, float quality, int64_t size, double time, double bitrate, double speed) {
525 statisticsCallbackDataAdd(frameNumber, fps, quality, size, time, bitrate, speed);
526}
527
528static void process_log(long sessionId, int levelValueInt, AVBPrint* logMessage) {
529 int activeLogLevel = av_log_get_level();
530 ffmpegkit::Level levelValue = static_cast<ffmpegkit::Level>(levelValueInt);
531 std::shared_ptr<ffmpegkit::Log> log = std::make_shared<ffmpegkit::Log>(sessionId, levelValue, logMessage->str);
532 bool globalCallbackDefined = false;
533 bool sessionCallbackDefined = false;
535
536 // LevelAVLogStdErr logs are always redirected
537 if ((activeLogLevel == ffmpegkit::LevelAVLogQuiet && levelValue != ffmpegkit::LevelAVLogStdErr) || (levelValue > activeLogLevel)) {
538 // LOG NEITHER PRINTED NOR FORWARDED
539 return;
540 }
541
542 auto session = ffmpegkit::FFmpegKitConfig::getSession(sessionId);
543 if (session != nullptr) {
544 activeLogRedirectionStrategy = session->getLogRedirectionStrategy();
545 session->addLog(log);
546
547 ffmpegkit::LogCallback sessionLogCallback = session->getLogCallback();
548 if (sessionLogCallback != nullptr) {
549 sessionCallbackDefined = true;
550
551 try {
552 // NOTIFY SESSION CALLBACK DEFINED
553 sessionLogCallback(log);
554 } catch(const std::exception& exception) {
555 std::cout << "Exception thrown inside session log callback. " << exception.what() << std::endl;
556 }
557 }
558 }
559
560 ffmpegkit::LogCallback globalLogCallback = logCallback;
561 if (globalLogCallback != nullptr) {
562 globalCallbackDefined = true;
563
564 try {
565 // NOTIFY GLOBAL CALLBACK DEFINED
566 globalLogCallback(log);
567 } catch(const std::exception& exception) {
568 std::cout << "Exception thrown inside global log callback. " << exception.what() << std::endl;
569 }
570 }
571
572 // EXECUTE THE LOG STRATEGY
573 switch (activeLogRedirectionStrategy) {
575 return;
576 }
578 if (globalCallbackDefined) {
579 return;
580 }
581 }
582 break;
584 if (sessionCallbackDefined) {
585 return;
586 }
587 }
588 break;
590 if (globalCallbackDefined || sessionCallbackDefined) {
591 return;
592 }
593 }
594 break;
596 }
597 break;
598 }
599
600 // PRINT LOGS
601 switch (levelValue) {
603 // PRINT NO OUTPUT
604 break;
605 default:
606 // WRITE TO STDOUT
607 std::cout << ffmpegkit::FFmpegKitConfig::logLevelToString(levelValue) << ": " << logMessage->str;
608 break;
609 }
610}
611
612void process_statistics(long sessionId, int videoFrameNumber, float videoFps, float videoQuality, long size, double time, double bitrate, double speed) {
613 std::shared_ptr<ffmpegkit::Statistics> statistics = std::make_shared<ffmpegkit::Statistics>(sessionId, videoFrameNumber, videoFps, videoQuality, size, time, bitrate, speed);
614
615 auto session = ffmpegkit::FFmpegKitConfig::getSession(sessionId);
616 if (session != nullptr && session->isFFmpeg()) {
617 std::shared_ptr<ffmpegkit::FFmpegSession> ffmpegSession = std::static_pointer_cast<ffmpegkit::FFmpegSession>(session);
618 ffmpegSession->addStatistics(statistics);
619
620 ffmpegkit::StatisticsCallback sessionStatisticsCallback = ffmpegSession->getStatisticsCallback();
621 if (sessionStatisticsCallback != nullptr) {
622 try {
623 sessionStatisticsCallback(statistics);
624 } catch(const std::exception& exception) {
625 std::cout << "Exception thrown inside session statistics callback. " << exception.what() << std::endl;
626 }
627 }
628 }
629
630 ffmpegkit::StatisticsCallback globalStatisticsCallback = statisticsCallback;
631 if (globalStatisticsCallback != nullptr) {
632 try {
633 globalStatisticsCallback(statistics);
634 } catch(const std::exception& exception) {
635 std::cout << "Exception thrown inside global statistics callback. " << exception.what() << std::endl;
636 }
637 }
638}
639
643void *callbackThreadFunction(void *pointer) {
644 int activeLogLevel = av_log_get_level();
645 if ((activeLogLevel != ffmpegkit::LevelAVLogQuiet) && (ffmpegkit::LevelAVLogDebug <= activeLogLevel)) {
646 std::cout << "Async callback block started." << std::endl;
647 }
648
649 while(redirectionEnabled) {
650 try {
651 CallbackData* callbackData = callbackDataRemove();
652
653 if (callbackData != nullptr) {
654
655 if (callbackData->getType() == LogType) {
656 process_log(callbackData->getSessionId(), callbackData->getLogLevel(), callbackData->getLogData());
657 av_bprint_finalize(callbackData->getLogData(), NULL);
658 } else {
659 process_statistics(callbackData->getSessionId(),
660 callbackData->getStatisticsFrameNumber(),
661 callbackData->getStatisticsFps(),
662 callbackData->getStatisticsQuality(),
663 callbackData->getStatisticsSize(),
664 callbackData->getStatisticsTime(),
665 callbackData->getStatisticsBitrate(),
666 callbackData->getStatisticsSpeed());
667 }
668
669 std::atomic_fetch_sub(&sessionInTransitMessageCountMap[callbackData->getSessionId() % SESSION_MAP_SIZE], 1);
670
671 } else {
672 callbackWait(100);
673 }
674
675 } catch(const std::exception& exception) {
676 activeLogLevel = av_log_get_level();
677 if ((activeLogLevel != ffmpegkit::LevelAVLogQuiet) && (ffmpegkit::LevelAVLogWarning <= activeLogLevel)) {
678 std::cout << "Async callback block received error: " << exception.what() << std::endl;
679 }
680 }
681 }
682
683 activeLogLevel = av_log_get_level();
684 if ((activeLogLevel != ffmpegkit::LevelAVLogQuiet) && (ffmpegkit::LevelAVLogDebug <= activeLogLevel)) {
685 std::cout << "Async callback block stopped." << std::endl;
686 }
687
688 return NULL;
689}
690
691static int executeFFmpeg(const long sessionId, const std::shared_ptr<std::list<std::string>> arguments) {
692 const char* LIB_NAME = "ffmpeg";
693
694 // SETS DEFAULT LOG LEVEL BEFORE STARTING A NEW RUN
695 av_log_set_level(configuredLogLevel);
696
697 char **commandCharPArray = (char **)av_malloc(sizeof(char*) * (arguments->size() + 1));
698
699 /* PRESERVE USAGE FORMAT
700 *
701 * ffmpeg <arguments>
702 */
703 commandCharPArray[0] = (char *)av_malloc(sizeof(char) * (strlen(LIB_NAME) + 1));
704 strcpy(commandCharPArray[0], LIB_NAME);
705
706 // PREPARE ARRAY ELEMENTS
707 int i = 0;
708 for (auto it=arguments->begin(); it != arguments->end(); it++, i++) {
709 commandCharPArray[i + 1] = (char*)it->c_str();
710 }
711
712 // REGISTER THE ID BEFORE STARTING THE SESSION
713 globalSessionId = sessionId;
714 registerSessionId(sessionId);
715
716 resetMessagesInTransmit(sessionId);
717
718 // RUN
719 int returnCode = ffmpeg_execute((arguments->size() + 1), commandCharPArray);
720
721 // ALWAYS REMOVE THE ID FROM THE MAP
722 removeSession(sessionId);
723
724 // CLEANUP
725 av_free(commandCharPArray[0]);
726 av_free(commandCharPArray);
727
728 return returnCode;
729}
730
731int executeFFprobe(const long sessionId, const std::shared_ptr<std::list<std::string>> arguments) {
732 const char* LIB_NAME = "ffprobe";
733
734 // SETS DEFAULT LOG LEVEL BEFORE STARTING A NEW RUN
735 av_log_set_level(configuredLogLevel);
736
737 char **commandCharPArray = (char **)av_malloc(sizeof(char*) * (arguments->size() + 1));
738
739 /* PRESERVE USAGE FORMAT
740 *
741 * ffprobe <arguments>
742 */
743 commandCharPArray[0] = (char *)av_malloc(sizeof(char) * (strlen(LIB_NAME) + 1));
744 strcpy(commandCharPArray[0], LIB_NAME);
745
746 // PREPARE ARRAY ELEMENTS
747 int i = 0;
748 for (auto it=arguments->begin(); it != arguments->end(); it++, i++) {
749 commandCharPArray[i + 1] = (char*)it->c_str();
750 }
751
752 // REGISTER THE ID BEFORE STARTING THE SESSION
753 globalSessionId = sessionId;
754 registerSessionId(sessionId);
755
756 resetMessagesInTransmit(sessionId);
757
758 // RUN
759 int returnCode = ffprobe_execute((arguments->size() + 1), commandCharPArray);
760
761 // ALWAYS REMOVE THE ID FROM THE MAP
762 removeSession(sessionId);
763
764 // CLEANUP
765 av_free(commandCharPArray[0]);
766 av_free(commandCharPArray);
767
768 return returnCode;
769}
770
772 std::call_once(ffmpegKitInitializerFlag, [](){
773 std::cout << "Loading ffmpeg-kit." << std::endl;
774
776
777 for(int i = 0; i<SESSION_MAP_SIZE; i++) {
778 std::atomic_init(&sessionMap[i], (short)0);
779 std::atomic_init(&sessionInTransitMessageCountMap[i], 0);
780 }
781
782 logCallback = nullptr;
783 statisticsCallback = nullptr;
787
789
791
793
794 std::cout << "Loaded ffmpeg-kit-" << ffmpegkit::Packages::getPackageName() << "-" << ffmpegkit::ArchDetect::getArch() << "-" << ffmpegkit::FFmpegKitConfig::getVersion() << "-" << ffmpegkit::FFmpegKitConfig::getBuildDate() << "." << std::endl;
795 });
796
797 return NULL;
798}
799
801 std::unique_lock<std::recursive_mutex> lock(callbackDataMutex, std::defer_lock);
802 lock.lock();
803
804 if (redirectionEnabled != 0) {
805 lock.unlock();
806 return;
807 }
809
810 lock.unlock();
811
812 int rc = pthread_create(&callbackThread, NULL, callbackThreadFunction, NULL);
813 if (rc != 0) {
814 std::cout << "Failed to create async callback block: %d" << rc << std::endl;
815 lock.unlock();
816 return;
817 }
818
819 av_log_set_callback(ffmpegkit_log_callback_function);
821}
822
824 std::unique_lock<std::recursive_mutex> lock(callbackDataMutex, std::defer_lock);
825
826 lock.lock();
827
828 if (redirectionEnabled != 1) {
829 lock.unlock();
830 return;
831 }
833
834 lock.unlock();
835
837
838 pthread_detach(callbackThread);
839
840 av_log_set_callback(av_log_default_callback);
842}
843
845 return ffmpegkit::FFmpegKitConfig::setEnvironmentVariable("FONTCONFIG_PATH", path);
846}
847
848void ffmpegkit::FFmpegKitConfig::setFontDirectory(const std::string& fontDirectoryPath, const std::map<std::string,std::string>& fontNameMapping) {
849 ffmpegkit::FFmpegKitConfig::setFontDirectoryList(std::list<std::string>{fontDirectoryPath}, fontNameMapping);
850}
851
852void ffmpegkit::FFmpegKitConfig::setFontDirectoryList(const std::list<std::string>& fontDirectoryList, const std::map<std::string,std::string>& fontNameMapping) {
853 int validFontNameMappingCount = 0;
854
855 const char *parentDirectory = std::getenv("HOME");
856 if (parentDirectory == NULL) {
857 parentDirectory = std::getenv("TMPDIR");
858 if (parentDirectory == NULL) {
859 parentDirectory = ".";
860 }
861 }
862
863 std::string cacheDir = std::string(parentDirectory) + "/.cache";
864 std::string ffmpegKitDir = cacheDir + "/ffmpegkit";
865 auto tempConfigurationDirectory = ffmpegKitDir + "/fontconfig";
866 auto fontConfigurationFile = std::string(tempConfigurationDirectory) + "/fonts.conf";
867
868 if (!fs_create_dir(cacheDir) || !fs_create_dir(ffmpegKitDir) || !fs_create_dir(tempConfigurationDirectory)) {
869 return;
870 }
871 std::cout << "Created temporary font conf directory: TRUE." << std::endl;
872
873 if (fs_exists(fontConfigurationFile, true, false)) {
874 bool fontConfigurationDeleted = std::remove(fontConfigurationFile.c_str());
875 std::cout << "Deleted old temporary font configuration: " << (fontConfigurationDeleted == 0?"TRUE":"FALSE") << "." << std::endl;
876 }
877
878 /* PROCESS MAPPINGS FIRST */
879 std::string fontNameMappingBlock = "";
880 for (auto const& pair : fontNameMapping) {
881 if ((pair.first.size() > 0) && (pair.second.size() > 0)) {
882
883 fontNameMappingBlock += " <match target=\"pattern\">\n";
884 fontNameMappingBlock += " <test qual=\"any\" name=\"family\">\n";
885 fontNameMappingBlock += " <string>";
886 fontNameMappingBlock += pair.first;
887 fontNameMappingBlock += "</string>\n";
888 fontNameMappingBlock += " </test>\n";
889 fontNameMappingBlock += " <edit name=\"family\" mode=\"assign\" binding=\"same\">\n";
890 fontNameMappingBlock += " <string>";
891 fontNameMappingBlock += pair.second;
892 fontNameMappingBlock += "</string>\n";
893 fontNameMappingBlock += " </edit>\n";
894 fontNameMappingBlock += " </match>\n";
895
896 validFontNameMappingCount++;
897 }
898 }
899
900 std::string fontConfiguration;
901 fontConfiguration += "<?xml version=\"1.0\"?>\n";
902 fontConfiguration += "<!DOCTYPE fontconfig SYSTEM \"fonts.dtd\">\n";
903 fontConfiguration += "<fontconfig>\n";
904 fontConfiguration += " <dir prefix=\"cwd\">.</dir>\n";
905
906 for (const auto& fontDirectoryPath : fontDirectoryList) {
907 fontConfiguration += " <dir>";
908 fontConfiguration += fontDirectoryPath;
909 fontConfiguration += "</dir>\n";
910 }
911 fontConfiguration += fontNameMappingBlock;
912 fontConfiguration += "</fontconfig>\n";
913
914 std::ofstream fontConfigurationStream(fontConfigurationFile, std::ios::out | std::ios::trunc);
915 if (fontConfigurationStream) {
916 fontConfigurationStream << fontConfiguration;
917 }
918 if (fontConfigurationStream.bad()) {
919 std::cout << "Failed to set font directory. Error received while saving font configuration: " << fontConfigurationStream.rdbuf() << "." << std::endl;
920 }
921 fontConfigurationStream.close();
922
923 std::cout << "Saved new temporary font configuration with " << validFontNameMappingCount << " font name mappings." << std::endl;
924
925 ffmpegkit::FFmpegKitConfig::setFontconfigConfigurationPath(tempConfigurationDirectory.c_str());
926
927 for (const auto& fontDirectoryPath : fontDirectoryList) {
928 std::cout << "Font directory " << fontDirectoryPath << " registered successfully." << std::endl;
929 }
930}
931
933 const char *parentDirectory = std::getenv("HOME");
934 if (parentDirectory == NULL) {
935 parentDirectory = std::getenv("TMPDIR");
936 if (parentDirectory == NULL) {
937 parentDirectory = ".";
938 }
939 }
940
941 // PIPES ARE CREATED UNDER THE PIPES DIRECTORY
942 std::string cacheDir = std::string(parentDirectory) + "/.cache";
943 std::string ffmpegKitDir = cacheDir + "/ffmpegkit";
944 std::string pipesDir = ffmpegKitDir + "/pipes";
945
946 if (!fs_create_dir(cacheDir) || !fs_create_dir(ffmpegKitDir) || !fs_create_dir(pipesDir)) {
947 return nullptr;
948 }
949
950 std::shared_ptr<std::string> newFFmpegPipePath = std::make_shared<std::string>(pipesDir + "/" + FFmpegKitNamedPipePrefix + std::to_string(pipeIndexGenerator++));
951
952 // FIRST CLOSE OLD PIPES WITH THE SAME NAME
953 ffmpegkit::FFmpegKitConfig::closeFFmpegPipe(newFFmpegPipePath->c_str());
954
955 int rc = mkfifo(newFFmpegPipePath->c_str(), S_IRWXU | S_IRWXG | S_IROTH);
956 if (rc == 0) {
957 return newFFmpegPipePath;
958 } else {
959 std::cout << "Failed to register new FFmpeg pipe " << newFFmpegPipePath << ". Operation failed with rc=" << rc << "." << std::endl;
960 return nullptr;
961 }
962}
963
964void ffmpegkit::FFmpegKitConfig::closeFFmpegPipe(const std::string& ffmpegPipePath) {
965 std::remove(ffmpegPipePath.c_str());
966}
967
969 return FFMPEG_VERSION;
970}
971
974 return std::string("").append(FFmpegKitVersion).append("-lts");
975 } else {
976 return FFmpegKitVersion;
977 }
978}
979
981 #if defined(FFMPEG_KIT_LTS)
982 return true;
983 #else
984 return false;
985 #endif
986}
987
989 char buildDate[10];
990 sprintf(buildDate, "%d", FFMPEG_KIT_BUILD_DATE);
991 return std::string(buildDate);
992}
993
994int ffmpegkit::FFmpegKitConfig::setEnvironmentVariable(const std::string& variableName, const std::string& variableValue) {
995 return setenv(variableName.c_str(), variableValue.c_str(), true);
996}
997
999 if (signal == ffmpegkit::SignalQuit) {
1000 handleSIGQUIT = 0;
1001 } else if (signal == ffmpegkit::SignalInt) {
1002 handleSIGINT = 0;
1003 } else if (signal == ffmpegkit::SignalTerm) {
1004 handleSIGTERM = 0;
1005 } else if (signal == ffmpegkit::SignalXcpu) {
1006 handleSIGXCPU = 0;
1007 } else if (signal == ffmpegkit::SignalPipe) {
1008 handleSIGPIPE = 0;
1009 }
1010}
1011
1012void ffmpegkit::FFmpegKitConfig::ffmpegExecute(const std::shared_ptr<ffmpegkit::FFmpegSession> ffmpegSession) {
1013 ffmpegSession->startRunning();
1014
1015 try {
1016 int returnCode = executeFFmpeg(ffmpegSession->getSessionId(), ffmpegSession->getArguments());
1017 ffmpegSession->complete(std::make_shared<ffmpegkit::ReturnCode>(returnCode));
1018 } catch(const std::exception& exception) {
1019 ffmpegSession->fail(exception.what());
1020 std::cout << "FFmpeg execute failed: " << ffmpegkit::FFmpegKitConfig::argumentsToString(ffmpegSession->getArguments()) << "." << exception.what() << std::endl;
1021 }
1022}
1023
1024void ffmpegkit::FFmpegKitConfig::ffprobeExecute(const std::shared_ptr<ffmpegkit::FFprobeSession> ffprobeSession) {
1025 ffprobeSession->startRunning();
1026
1027 try {
1028 int returnCode = executeFFprobe(ffprobeSession->getSessionId(), ffprobeSession->getArguments());
1029 ffprobeSession->complete(std::make_shared<ffmpegkit::ReturnCode>(returnCode));
1030 } catch(const std::exception& exception) {
1031 ffprobeSession->fail(exception.what());
1032 std::cout << "FFprobe execute failed: " << ffmpegkit::FFmpegKitConfig::argumentsToString(ffprobeSession->getArguments()) << "." << exception.what() << std::endl;
1033 }
1034}
1035
1036void ffmpegkit::FFmpegKitConfig::getMediaInformationExecute(const std::shared_ptr<ffmpegkit::MediaInformationSession> mediaInformationSession, const int waitTimeout) {
1037 mediaInformationSession->startRunning();
1038
1039 try {
1040 int returnCodeValue = executeFFprobe(mediaInformationSession->getSessionId(), mediaInformationSession->getArguments());
1041 auto returnCode = std::make_shared<ffmpegkit::ReturnCode>(returnCodeValue);
1042 mediaInformationSession->complete(returnCode);
1043 if (returnCode->isValueSuccess()) {
1044 auto allLogs = mediaInformationSession->getAllLogsWithTimeout(waitTimeout);
1045 std::string ffprobeJsonOutput;
1046 std::for_each(allLogs->cbegin(), allLogs->cend(), [&](std::shared_ptr<ffmpegkit::Log> log) {
1047 if (log->getLevel() == LevelAVLogStdErr) {
1048 ffprobeJsonOutput.append(log->getMessage());
1049 }
1050 });
1051 auto mediaInformation = ffmpegkit::MediaInformationJsonParser::fromWithError(ffprobeJsonOutput.c_str());
1052 mediaInformationSession->setMediaInformation(mediaInformation);
1053 }
1054 } catch(const std::exception& exception) {
1055 mediaInformationSession->fail(exception.what());
1056 std::cout << "Get media information execute failed: " << ffmpegkit::FFmpegKitConfig::argumentsToString(mediaInformationSession->getArguments()) << "." << exception.what() << std::endl;
1057 }
1058}
1059
1060void ffmpegkit::FFmpegKitConfig::asyncFFmpegExecute(const std::shared_ptr<ffmpegkit::FFmpegSession> ffmpegSession) {
1061 auto thread = std::thread([ffmpegSession]() {
1063
1064 ffmpegkit::FFmpegSessionCompleteCallback completeCallback = ffmpegSession->getCompleteCallback();
1065 if (completeCallback != nullptr) {
1066 try {
1067 // NOTIFY SESSION CALLBACK DEFINED
1068 completeCallback(ffmpegSession);
1069 } catch(const std::exception& exception) {
1070 std::cout << "Exception thrown inside session complete callback. " << exception.what() << std::endl;
1071 }
1072 }
1073
1075 if (globalFFmpegSessionCompleteCallback != nullptr) {
1076 try {
1077 // NOTIFY SESSION CALLBACK DEFINED
1078 globalFFmpegSessionCompleteCallback(ffmpegSession);
1079 } catch(const std::exception& exception) {
1080 std::cout << "Exception thrown inside global complete callback. " << exception.what() << std::endl;
1081 }
1082 }
1083 });
1084
1085 thread.detach();
1086}
1087
1088void ffmpegkit::FFmpegKitConfig::asyncFFprobeExecute(const std::shared_ptr<ffmpegkit::FFprobeSession> ffprobeSession) {
1089 auto thread = std::thread([ffprobeSession]() {
1091
1092 ffmpegkit::FFprobeSessionCompleteCallback completeCallback = ffprobeSession->getCompleteCallback();
1093 if (completeCallback != nullptr) {
1094 try {
1095 // NOTIFY SESSION CALLBACK DEFINED
1096 completeCallback(ffprobeSession);
1097 } catch(const std::exception& exception) {
1098 std::cout << "Exception thrown inside session complete callback. " << exception.what() << std::endl;
1099 }
1100 }
1101
1103 if (globalFFprobeSessionCompleteCallback != nullptr) {
1104 try {
1105 // NOTIFY SESSION CALLBACK DEFINED
1106 globalFFprobeSessionCompleteCallback(ffprobeSession);
1107 } catch(const std::exception& exception) {
1108 std::cout << "Exception thrown inside global complete callback. " << exception.what() << std::endl;
1109 }
1110 }
1111 });
1112
1113 thread.detach();
1114}
1115
1116void ffmpegkit::FFmpegKitConfig::asyncGetMediaInformationExecute(const std::shared_ptr<ffmpegkit::MediaInformationSession> mediaInformationSession, const int waitTimeout) {
1117 auto thread = std::thread([mediaInformationSession,waitTimeout]() {
1118 ffmpegkit::FFmpegKitConfig::getMediaInformationExecute(mediaInformationSession, waitTimeout);
1119
1120 ffmpegkit::MediaInformationSessionCompleteCallback completeCallback = mediaInformationSession->getCompleteCallback();
1121 if (completeCallback != nullptr) {
1122 try {
1123 // NOTIFY SESSION CALLBACK DEFINED
1124 completeCallback(mediaInformationSession);
1125 } catch(const std::exception& exception) {
1126 std::cout << "Exception thrown inside session complete callback. " << exception.what() << std::endl;
1127 }
1128 }
1129
1131 if (globalMediaInformationSessionCompleteCallback != nullptr) {
1132 try {
1133 // NOTIFY SESSION CALLBACK DEFINED
1134 globalMediaInformationSessionCompleteCallback(mediaInformationSession);
1135 } catch(const std::exception& exception) {
1136 std::cout << "Exception thrown inside global complete callback. " << exception.what() << std::endl;
1137 }
1138 }
1139 });
1140
1141 thread.detach();
1142}
1143
1145 logCallback = callback;
1146}
1147
1149 statisticsCallback = callback;
1150}
1151
1153 ffmpegSessionCompleteCallback = completeCallback;
1154}
1155
1158}
1159
1161 ffprobeSessionCompleteCallback = completeCallback;
1162}
1163
1166}
1167
1169 mediaInformationSessionCompleteCallback = completeCallback;
1170}
1171
1174}
1175
1177 return static_cast<ffmpegkit::Level>(configuredLogLevel);
1178}
1179
1181 configuredLogLevel = level;
1182}
1183
1185 switch (level) {
1186 case ffmpegkit::LevelAVLogStdErr: return "STDERR";
1187 case ffmpegkit::LevelAVLogTrace: return "TRACE";
1188 case ffmpegkit::LevelAVLogDebug: return "DEBUG";
1189 case ffmpegkit::LevelAVLogVerbose: return "VERBOSE";
1190 case ffmpegkit::LevelAVLogInfo: return "INFO";
1191 case ffmpegkit::LevelAVLogWarning: return "WARNING";
1192 case ffmpegkit::LevelAVLogError: return "ERROR";
1193 case ffmpegkit::LevelAVLogFatal: return "FATAL";
1194 case ffmpegkit::LevelAVLogPanic: return "PANIC";
1195 case ffmpegkit::LevelAVLogQuiet: return "QUIET";
1196 default: return "";
1197 }
1198}
1199
1201 return sessionHistorySize;
1202}
1203
1204void ffmpegkit::FFmpegKitConfig::setSessionHistorySize(const int newSessionHistorySize) {
1205 if (newSessionHistorySize >= SESSION_MAP_SIZE) {
1206
1207 /*
1208 * THERE IS A HARD LIMIT ON THE NATIVE SIDE. HISTORY SIZE MUST BE SMALLER THAN SESSION_MAP_SIZE
1209 */
1210 throw std::runtime_error("Session history size must not exceed the hard limit!");
1211 } else if (newSessionHistorySize > 0) {
1212 sessionHistorySize = newSessionHistorySize;
1214 }
1215}
1216
1217std::shared_ptr<ffmpegkit::Session> ffmpegkit::FFmpegKitConfig::getSession(const long sessionId) {
1218 std::unique_lock<std::recursive_mutex> lock(sessionMutex, std::defer_lock);
1219 lock.lock();
1220
1221 auto session = sessionHistoryMap.find(sessionId);
1222 if (session != sessionHistoryMap.end()) {
1223 return session->second;
1224 } else {
1225 return nullptr;
1226 }
1227}
1228
1229std::shared_ptr<ffmpegkit::Session> ffmpegkit::FFmpegKitConfig::getLastSession() {
1230 std::unique_lock<std::recursive_mutex> lock(sessionMutex, std::defer_lock);
1231 lock.lock();
1232
1233 return sessionHistoryList.front();
1234}
1235
1236std::shared_ptr<ffmpegkit::Session> ffmpegkit::FFmpegKitConfig::getLastCompletedSession() {
1237 std::unique_lock<std::recursive_mutex> lock(sessionMutex, std::defer_lock);
1238
1239 lock.lock();
1240
1241 for(auto rit=sessionHistoryList.rbegin(); rit != sessionHistoryList.rend(); ++rit) {
1242 auto session = *rit;
1243 if (session->getState() == SessionStateCompleted) {
1244 return session;
1245 }
1246 }
1247
1248 return nullptr;
1249}
1250
1251std::shared_ptr<std::list<std::shared_ptr<ffmpegkit::Session>>> ffmpegkit::FFmpegKitConfig::getSessions() {
1252 std::unique_lock<std::recursive_mutex> lock(sessionMutex, std::defer_lock);
1253 lock.lock();
1254
1255 auto sessionHistoryListCopy = std::make_shared<std::list<std::shared_ptr<ffmpegkit::Session>>>(sessionHistoryList);
1256
1257 lock.unlock();
1258
1259 return sessionHistoryListCopy;
1260}
1261
1263 std::unique_lock<std::recursive_mutex> lock(sessionMutex, std::defer_lock);
1264 lock.lock();
1265
1266 sessionHistoryList.clear();
1267 sessionHistoryMap.clear();
1268
1269 lock.unlock();
1270}
1271
1272std::shared_ptr<std::list<std::shared_ptr<ffmpegkit::FFmpegSession>>> ffmpegkit::FFmpegKitConfig::getFFmpegSessions() {
1273 std::unique_lock<std::recursive_mutex> lock(sessionMutex, std::defer_lock);
1274 const auto ffmpegSessions = std::make_shared<std::list<std::shared_ptr<ffmpegkit::FFmpegSession>>>();
1275
1276 lock.lock();
1277
1278 for(auto it=sessionHistoryList.begin(); it != sessionHistoryList.end(); ++it) {
1279 auto session = *it;
1280 if (session->isFFmpeg()) {
1281 ffmpegSessions->push_back(std::static_pointer_cast<ffmpegkit::FFmpegSession>(session));
1282 }
1283 }
1284
1285 lock.unlock();
1286
1287 return ffmpegSessions;
1288}
1289
1290std::shared_ptr<std::list<std::shared_ptr<ffmpegkit::FFprobeSession>>> ffmpegkit::FFmpegKitConfig::getFFprobeSessions() {
1291 std::unique_lock<std::recursive_mutex> lock(sessionMutex, std::defer_lock);
1292 const auto ffprobeSessions = std::make_shared<std::list<std::shared_ptr<ffmpegkit::FFprobeSession>>>();
1293
1294 lock.lock();
1295
1296 for(auto it=sessionHistoryList.begin(); it != sessionHistoryList.end(); ++it) {
1297 auto session = *it;
1298 if (session->isFFprobe()) {
1299 ffprobeSessions->push_back(std::static_pointer_cast<ffmpegkit::FFprobeSession>(session));
1300 }
1301 }
1302
1303 lock.unlock();
1304
1305 return ffprobeSessions;
1306}
1307
1308std::shared_ptr<std::list<std::shared_ptr<ffmpegkit::MediaInformationSession>>> ffmpegkit::FFmpegKitConfig::getMediaInformationSessions() {
1309 std::unique_lock<std::recursive_mutex> lock(sessionMutex, std::defer_lock);
1310 const auto mediaInformationSessions = std::make_shared<std::list<std::shared_ptr<ffmpegkit::MediaInformationSession>>>();
1311
1312 lock.lock();
1313
1314 for(auto it=sessionHistoryList.begin(); it != sessionHistoryList.end(); ++it) {
1315 auto session = *it;
1316 if (session->isMediaInformation()) {
1317 mediaInformationSessions->push_back(std::static_pointer_cast<ffmpegkit::MediaInformationSession>(session));
1318 }
1319 }
1320
1321 lock.unlock();
1322
1323 return mediaInformationSessions;
1324}
1325
1326std::shared_ptr<std::list<std::shared_ptr<ffmpegkit::Session>>> ffmpegkit::FFmpegKitConfig::getSessionsByState(const SessionState state) {
1327 std::unique_lock<std::recursive_mutex> lock(sessionMutex, std::defer_lock);
1328 auto sessions = std::make_shared<std::list<std::shared_ptr<ffmpegkit::Session>>>();
1329
1330 lock.lock();
1331
1332 for(auto it=sessionHistoryList.begin(); it != sessionHistoryList.end(); ++it) {
1333 auto session = *it;
1334 if (session->getState() == state) {
1335 sessions->push_back(session);
1336 }
1337 }
1338
1339 lock.unlock();
1340
1341 return sessions;
1342}
1343
1346}
1347
1349 globalLogRedirectionStrategy = logRedirectionStrategy;
1350}
1351
1353 return std::atomic_load(&sessionInTransitMessageCountMap[sessionId % SESSION_MAP_SIZE]);
1354}
1355
1357 switch (state) {
1358 case SessionStateCreated: return "CREATED";
1359 case SessionStateRunning: return "RUNNING";
1360 case SessionStateFailed: return "FAILED";
1361 case SessionStateCompleted: return "COMPLETED";
1362 default: return "";
1363 }
1364}
1365
1366std::list<std::string> ffmpegkit::FFmpegKitConfig::parseArguments(const std::string& command) {
1367 std::list<std::string> argumentList;
1368 std::string currentArgument;
1369
1370 bool singleQuoteStarted = false;
1371 bool doubleQuoteStarted = false;
1372
1373 for (int i = 0; i < command.size(); i++) {
1374 char previousChar;
1375 if (i > 0) {
1376 previousChar = command[i - 1];
1377 } else {
1378 previousChar = 0;
1379 }
1380 char currentChar = command[i];
1381
1382 if (currentChar == ' ') {
1383 if (singleQuoteStarted || doubleQuoteStarted) {
1384 currentArgument += currentChar;
1385 } else if (currentArgument.size() > 0) {
1386 argumentList.push_back(currentArgument);
1387 currentArgument = "";
1388 }
1389 } else if (currentChar == '\'' && (previousChar == 0 || previousChar != '\\')) {
1390 if (singleQuoteStarted) {
1391 singleQuoteStarted = false;
1392 } else if (doubleQuoteStarted) {
1393 currentArgument += currentChar;
1394 } else {
1395 singleQuoteStarted = true;
1396 }
1397 } else if (currentChar == '\"' && (previousChar == 0 || previousChar != '\\')) {
1398 if (doubleQuoteStarted) {
1399 doubleQuoteStarted = false;
1400 } else if (singleQuoteStarted) {
1401 currentArgument += currentChar;
1402 } else {
1403 doubleQuoteStarted = true;
1404 }
1405 } else {
1406 currentArgument += currentChar;
1407 }
1408 }
1409
1410 if (currentArgument.size() > 0) {
1411 argumentList.push_back(currentArgument);
1412 }
1413
1414 return argumentList;
1415}
1416
1417std::string ffmpegkit::FFmpegKitConfig::argumentsToString(std::shared_ptr<std::list<std::string>> arguments) {
1418 if (arguments == nullptr) {
1419 return "null";
1420 }
1421
1422 std::string string;
1423 for(auto it=arguments->begin(); it != arguments->end(); ++it) {
1424 auto argument = *it;
1425 if (it != arguments->begin()) {
1426 string += " ";
1427 }
1428 string += argument;
1429 }
1430
1431 return string;
1432}
static std::mutex callbackMutex
void ffmpegkit_log_callback_function(void *ptr, int level, const char *format, va_list vargs)
static void process_log(long sessionId, int levelValueInt, AVBPrint *logMessage)
void * callbackThreadFunction(void *pointer)
int executeFFprobe(const long sessionId, const std::shared_ptr< std::list< std::string > > arguments)
static std::atomic< long > pipeIndexGenerator(1)
static void statisticsCallbackDataAdd(int frameNumber, float fps, float quality, int64_t size, int time, double bitrate, double speed)
void cancelSession(long sessionId)
#define SESSION_MAP_SIZE
static int sessionHistorySize
static bool fs_exists(const std::string &s, const bool isFile, const bool isDirectory)
static std::list< CallbackData * > callbackDataList
@ StatisticsType
@ LogType
static std::recursive_mutex callbackDataMutex
static void logCallbackDataAdd(int level, AVBPrint *data)
static void avutil_log_sanitize(char *line)
volatile int handleSIGINT
static void registerSessionId(long sessionId)
int ffprobe_execute(int argc, char **argv)
volatile int handleSIGTERM
void set_report_callback(void(*callback)(int, float, float, int64_t, double, double, double))
static ffmpegkit::FFmpegSessionCompleteCallback ffmpegSessionCompleteCallback
void ffmpegkit_statistics_callback_function(int frameNumber, float fps, float quality, int64_t size, double time, double bitrate, double speed)
static std::atomic< int > sessionInTransitMessageCountMap[SESSION_MAP_SIZE]
static const char * avutil_log_get_level_str(int level)
static void avutil_log_format_line(void *avcl, int level, const char *fmt, va_list vl, AVBPrint part[4], int *print_prefix)
static std::recursive_mutex sessionMutex
static std::atomic< short > sessionMap[SESSION_MAP_SIZE]
void addSessionToSessionHistory(const std::shared_ptr< ffmpegkit::Session > session)
static void resetMessagesInTransmit(long sessionId)
static ffmpegkit::LogCallback logCallback
void cancel_operation(long id)
static void callbackNotify()
static pthread_t callbackThread
static std::condition_variable callbackMonitor
static std::list< std::shared_ptr< ffmpegkit::Session > > sessionHistoryList
static std::map< long, std::shared_ptr< ffmpegkit::Session > > sessionHistoryMap
static ffmpegkit::StatisticsCallback statisticsCallback
static ffmpegkit::LogRedirectionStrategy globalLogRedirectionStrategy
static std::once_flag ffmpegKitInitializerFlag
void * ffmpegKitInitialize()
static int executeFFmpeg(const long sessionId, const std::shared_ptr< std::list< std::string > > arguments)
void deleteExpiredSessions()
__thread long globalSessionId
static int redirectionEnabled
static void callbackWait(int milliSeconds)
int cancelRequested(long sessionId)
volatile int handleSIGPIPE
static CallbackData * callbackDataRemove()
void process_statistics(long sessionId, int videoFrameNumber, float videoFps, float videoQuality, long size, double time, double bitrate, double speed)
volatile int handleSIGXCPU
static ffmpegkit::FFprobeSessionCompleteCallback ffprobeSessionCompleteCallback
static void removeSession(long sessionId)
static bool fs_create_dir(const std::string &s)
int configuredLogLevel
static ffmpegkit::MediaInformationSessionCompleteCallback mediaInformationSessionCompleteCallback
int ffmpeg_execute(int argc, char **argv)
const void * _ffmpegKitConfigInitializer
volatile int handleSIGQUIT
float getStatisticsQuality()
AVBPrint * getLogData()
double getStatisticsSpeed()
int getStatisticsFrameNumber()
CallbackData(const long sessionId, const int videoFrameNumber, const float videoFps, const float videoQuality, const int64_t size, const double time, const double bitrate, const double speed)
int64_t getStatisticsSize()
CallbackData(const long sessionId, const int logLevel, const AVBPrint *data)
double getStatisticsBitrate()
CallbackType getType()
CallbackType _type
double getStatisticsTime()
static std::string getArch()
static std::string getVersion()
static std::shared_ptr< std::list< std::shared_ptr< ffmpegkit::MediaInformationSession > > > getMediaInformationSessions()
static void enableFFmpegSessionCompleteCallback(const FFmpegSessionCompleteCallback ffmpegSessionCompleteCallback)
static std::shared_ptr< ffmpegkit::Session > getLastSession()
static void enableLogCallback(const ffmpegkit::LogCallback logCallback)
static std::shared_ptr< std::string > registerNewFFmpegPipe()
static LogRedirectionStrategy getLogRedirectionStrategy()
static std::shared_ptr< std::list< std::shared_ptr< ffmpegkit::FFprobeSession > > > getFFprobeSessions()
static int messagesInTransmit(const long sessionId)
static void closeFFmpegPipe(const std::string &ffmpegPipePath)
static void asyncFFprobeExecute(const std::shared_ptr< ffmpegkit::FFprobeSession > ffprobeSession)
static ffmpegkit::Level getLogLevel()
static std::shared_ptr< ffmpegkit::Session > getSession(const long sessionId)
static void asyncGetMediaInformationExecute(const std::shared_ptr< ffmpegkit::MediaInformationSession > mediaInformationSession, int waitTimeout)
static void setLogRedirectionStrategy(const LogRedirectionStrategy logRedirectionStrategy)
static void getMediaInformationExecute(const std::shared_ptr< ffmpegkit::MediaInformationSession > mediaInformationSession, const int waitTimeout)
static int setEnvironmentVariable(const std::string &variableName, const std::string &variableValue)
static std::shared_ptr< std::list< std::shared_ptr< ffmpegkit::Session > > > getSessionsByState(const SessionState state)
static void enableStatisticsCallback(const ffmpegkit::StatisticsCallback statisticsCallback)
static std::list< std::string > parseArguments(const std::string &command)
static void ffprobeExecute(const std::shared_ptr< ffmpegkit::FFprobeSession > ffprobeSession)
static void setSessionHistorySize(const int sessionHistorySize)
static void setLogLevel(const ffmpegkit::Level level)
static void setFontDirectory(const std::string &fontDirectoryPath, const std::map< std::string, std::string > &fontNameMapping)
static void asyncFFmpegExecute(const std::shared_ptr< ffmpegkit::FFmpegSession > ffmpegSession)
static FFmpegSessionCompleteCallback getFFmpegSessionCompleteCallback()
static void ignoreSignal(const ffmpegkit::Signal signal)
static FFprobeSessionCompleteCallback getFFprobeSessionCompleteCallback()
static std::shared_ptr< ffmpegkit::Session > getLastCompletedSession()
static std::string sessionStateToString(SessionState state)
static std::shared_ptr< std::list< std::shared_ptr< ffmpegkit::FFmpegSession > > > getFFmpegSessions()
static int setFontconfigConfigurationPath(const std::string &path)
static std::string argumentsToString(std::shared_ptr< std::list< std::string > > arguments)
static std::string logLevelToString(const ffmpegkit::Level level)
static void setFontDirectoryList(const std::list< std::string > &fontDirectoryList, const std::map< std::string, std::string > &fontNameMapping)
static void enableMediaInformationSessionCompleteCallback(const MediaInformationSessionCompleteCallback mediaInformationSessionCompleteCallback)
static void enableFFprobeSessionCompleteCallback(const FFprobeSessionCompleteCallback ffprobeSessionCompleteCallback)
static std::string getFFmpegVersion()
static std::shared_ptr< std::list< std::shared_ptr< ffmpegkit::Session > > > getSessions()
static std::string getBuildDate()
static void ffmpegExecute(const std::shared_ptr< ffmpegkit::FFmpegSession > ffmpegSession)
static MediaInformationSessionCompleteCallback getMediaInformationSessionCompleteCallback()
static std::shared_ptr< ffmpegkit::MediaInformation > fromWithError(const std::string &ffprobeJsonOutput)
static std::string getPackageName()
Definition Packages.cpp:25
#define AV_LOG_STDERR
@ LogRedirectionStrategyPrintLogsWhenSessionCallbackNotDefined
@ LogRedirectionStrategyAlwaysPrintLogs
@ LogRedirectionStrategyPrintLogsWhenNoCallbacksDefined
@ LogRedirectionStrategyPrintLogsWhenGlobalCallbackNotDefined
std::function< void(const std::shared_ptr< ffmpegkit::Statistics > statistics)> StatisticsCallback
@ LevelAVLogError
Definition Level.h:57
@ LevelAVLogDebug
Definition Level.h:78
@ LevelAVLogStdErr
Definition Level.h:34
@ LevelAVLogQuiet
Definition Level.h:39
@ LevelAVLogPanic
Definition Level.h:44
@ LevelAVLogWarning
Definition Level.h:63
@ LevelAVLogVerbose
Definition Level.h:73
@ LevelAVLogTrace
Definition Level.h:83
@ LevelAVLogInfo
Definition Level.h:68
@ LevelAVLogFatal
Definition Level.h:51
@ SessionStateRunning
@ SessionStateFailed
@ SessionStateCreated
@ SessionStateCompleted
std::function< void(const std::shared_ptr< ffmpegkit::MediaInformationSession > session)> MediaInformationSessionCompleteCallback
std::function< void(const std::shared_ptr< ffmpegkit::Log > log)> LogCallback
Definition LogCallback.h:35
@ SignalXcpu
Definition Signal.h:30
@ SignalQuit
Definition Signal.h:27
@ SignalInt
Definition Signal.h:26
@ SignalTerm
Definition Signal.h:29
@ SignalPipe
Definition Signal.h:28
std::function< void(const std::shared_ptr< ffmpegkit::FFprobeSession > session)> FFprobeSessionCompleteCallback
std::function< void(const std::shared_ptr< ffmpegkit::FFmpegSession > session)> FFmpegSessionCompleteCallback