FFmpegKit Linux API 5.1
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_ffmpeg.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
50static std::atomic<long> pipeIndexGenerator(1);
51
52/* Session history variables */
54static std::map<long, std::shared_ptr<ffmpegkit::Session>> sessionHistoryMap;
55static std::list<std::shared_ptr<ffmpegkit::Session>> sessionHistoryList;
56static std::recursive_mutex sessionMutex;
57
59#define SESSION_MAP_SIZE 1000
60static std::atomic<short> sessionMap[SESSION_MAP_SIZE];
62
65
68
73
75
78static std::recursive_mutex callbackDataMutex;
79static std::mutex callbackMutex;
80static std::condition_variable callbackMonitor;
81class CallbackData;
82static std::list<CallbackData*> callbackDataList;
83
85volatile int handleSIGQUIT = 1;
86volatile int handleSIGINT = 1;
87volatile int handleSIGTERM = 1;
88volatile int handleSIGXCPU = 1;
89volatile int handleSIGPIPE = 1;
90
92__thread long globalSessionId = 0;
93
96
97#ifdef __cplusplus
98extern "C" {
99#endif
100
102int ffmpeg_execute(int argc, char **argv);
103
105int ffprobe_execute(int argc, char **argv);
106
107void ffmpegkit_log_callback_function(void *ptr, int level, const char* format, va_list vargs);
108
109#ifdef __cplusplus
110}
111#endif
112
113static std::once_flag ffmpegKitInitializerFlag;
114static pthread_t callbackThread;
115
116void* ffmpegKitInitialize();
117
119
124
125static bool fs_exists(const std::string& s, const bool isFile, const bool isDirectory) {
126 struct stat dir_info;
127
128 if (stat(s.c_str(), &dir_info) == 0) {
129 if (isFile && S_ISREG(dir_info.st_mode)) {
130 return true;
131 }
132 if (isDirectory && S_ISDIR(dir_info.st_mode)) {
133 return true;
134 }
135 }
136
137 return false;
138}
139
140static bool fs_create_dir(const std::string& s) {
141 if (!fs_exists(s, false, true)) {
142 if (mkdir(s.c_str(), S_IRWXU | S_IRWXG | S_IROTH) != 0) {
143 std::cout << "Failed to create directory: " << s << ". Operation failed with " << errno << "." << std::endl;
144 return false;
145 }
146 }
147 return true;
148}
149
151 while (sessionHistoryList.size() > sessionHistorySize) {
152 auto first = sessionHistoryList.front();
153 if (first != nullptr) {
154 sessionHistoryList.pop_front();
155 sessionHistoryMap.erase(first->getSessionId());
156 }
157 }
158}
159
160void addSessionToSessionHistory(const std::shared_ptr<ffmpegkit::Session> session) {
161 std::unique_lock<std::recursive_mutex> lock(sessionMutex, std::defer_lock);
162
163 const long sessionId = session->getSessionId();
164
165 lock.lock();
166
167 /*
168 * ASYNC SESSIONS CALL THIS METHOD TWICE
169 * THIS CHECK PREVENTS ADDING THE SAME SESSION AGAIN
170 */
171 if (sessionHistoryMap.count(sessionId) == 0) {
172 sessionHistoryMap.insert({sessionId, session});
173 sessionHistoryList.push_back(session);
175 }
176
177 lock.unlock();
178}
179
184 public:
185 CallbackData(const long sessionId, const int logLevel, const AVBPrint* data) :
186 _type{LogType}, _sessionId{sessionId}, _logLevel{logLevel} {
187 av_bprint_init(&_logData, 0, AV_BPRINT_SIZE_UNLIMITED);
188 av_bprintf(&_logData, "%s", data->str);
189 }
190
191 CallbackData(const long sessionId,
192 const int videoFrameNumber,
193 const float videoFps,
194 const float videoQuality,
195 const int64_t size,
196 const int time,
197 const double bitrate,
198 const double speed) :
200 _sessionId{sessionId},
201 _statisticsFrameNumber{videoFrameNumber},
202 _statisticsFps{videoFps},
203 _statisticsQuality{videoQuality},
204 _statisticsSize{size},
205 _statisticsTime{time},
206 _statisticsBitrate{bitrate},
207 _statisticsSpeed{speed} {
208 }
209
211 return _type;
212 }
213
215 return _sessionId;
216 }
217
219 return _logLevel;
220 }
221
222 AVBPrint* getLogData() {
223 return &_logData;
224 }
225
228 }
229
231 return _statisticsFps;
232 }
233
235 return _statisticsQuality;
236 }
237
239 return _statisticsSize;
240 }
241
243 return _statisticsTime;
244 }
245
247 return _statisticsBitrate;
248 }
249
251 return _statisticsSpeed;
252 }
253
254 private:
256 long _sessionId; // session id
257
258 int _logLevel; // log level
259 AVBPrint _logData; // log data
260
261 int _statisticsFrameNumber; // statistics frame number
262 float _statisticsFps; // statistics fps
263 float _statisticsQuality; // statistics quality
264 int64_t _statisticsSize; // statistics size
265 int _statisticsTime; // statistics time
266 double _statisticsBitrate; // statistics bitrate
267 double _statisticsSpeed; // statistics speed
268};
269
275static void callbackWait(int milliSeconds) {
276 std::unique_lock<std::mutex> callbackLock{callbackMutex};
277 callbackMonitor.wait_for(callbackLock, std::chrono::milliseconds(milliSeconds));
278}
279
283static void callbackNotify() {
284 callbackMonitor.notify_one();
285}
286
287static const char *avutil_log_get_level_str(int level) {
288 switch (level) {
289 case AV_LOG_STDERR:
290 return "stderr";
291 case AV_LOG_QUIET:
292 return "quiet";
293 case AV_LOG_DEBUG:
294 return "debug";
295 case AV_LOG_VERBOSE:
296 return "verbose";
297 case AV_LOG_INFO:
298 return "info";
299 case AV_LOG_WARNING:
300 return "warning";
301 case AV_LOG_ERROR:
302 return "error";
303 case AV_LOG_FATAL:
304 return "fatal";
305 case AV_LOG_PANIC:
306 return "panic";
307 default:
308 return "";
309 }
310}
311
312static void avutil_log_format_line(void *avcl, int level, const char *fmt, va_list vl, AVBPrint part[4], int *print_prefix) {
313 int flags = av_log_get_flags();
314 AVClass* avc = avcl ? *(AVClass **) avcl : NULL;
315 av_bprint_init(part+0, 0, 1);
316 av_bprint_init(part+1, 0, 1);
317 av_bprint_init(part+2, 0, 1);
318 av_bprint_init(part+3, 0, 65536);
319
320 if (*print_prefix && avc) {
321 if (avc->parent_log_context_offset) {
322 AVClass** parent = *(AVClass ***) (((uint8_t *) avcl) +
323 avc->parent_log_context_offset);
324 if (parent && *parent) {
325 av_bprintf(part+0, "[%s @ %p] ",
326 (*parent)->item_name(parent), parent);
327 }
328 }
329 av_bprintf(part+1, "[%s @ %p] ",
330 avc->item_name(avcl), avcl);
331 }
332
333 if (*print_prefix && (level > AV_LOG_QUIET) && (flags & AV_LOG_PRINT_LEVEL))
334 av_bprintf(part+2, "[%s] ", avutil_log_get_level_str(level));
335
336 av_vbprintf(part+3, fmt, vl);
337
338 if(*part[0].str || *part[1].str || *part[2].str || *part[3].str) {
339 char lastc = part[3].len && part[3].len <= part[3].size ? part[3].str[part[3].len - 1] : 0;
340 *print_prefix = lastc == '\n' || lastc == '\r';
341 }
342}
343
344static void avutil_log_sanitize(char *line) {
345 while(*line){
346 if(*line < 0x08 || (*line > 0x0D && *line < 0x20))
347 *line='?';
348 line++;
349 }
350}
351
358static void logCallbackDataAdd(int level, AVBPrint *data) {
359 std::unique_lock<std::recursive_mutex> lock(callbackDataMutex, std::defer_lock);
360 CallbackData* callbackData = new CallbackData(globalSessionId, level, data);
361
362 lock.lock();
363 callbackDataList.push_back(callbackData);
364 lock.unlock();
365
367
369}
370
374static void statisticsCallbackDataAdd(int frameNumber, float fps, float quality, int64_t size, int time, double bitrate, double speed) {
375 std::unique_lock<std::recursive_mutex> lock(callbackDataMutex, std::defer_lock);
376 CallbackData* callbackData = new CallbackData(globalSessionId, frameNumber, fps, quality, size, time, bitrate, speed);
377
378 lock.lock();
379 callbackDataList.push_back(callbackData);
380 lock.unlock();
381
383
385}
386
391 std::unique_lock<std::recursive_mutex> lock(callbackDataMutex, std::defer_lock);
392 CallbackData* newData = nullptr;
393
394 lock.lock();
395 if (callbackDataList.size() > 0) {
396 newData = callbackDataList.front();
397 callbackDataList.pop_front();
398 }
399 lock.unlock();
400
401 return newData;
402}
403
409static void registerSessionId(long sessionId) {
410 std::atomic_store(&sessionMap[sessionId % SESSION_MAP_SIZE], (short)1);
411}
412
418static void removeSession(long sessionId) {
419 std::atomic_store(&sessionMap[sessionId % SESSION_MAP_SIZE], (short)0);
420}
421
422#ifdef __cplusplus
423extern "C" {
424#endif
425
431void cancelSession(long sessionId) {
432 std::atomic_store(&sessionMap[sessionId % SESSION_MAP_SIZE], (short)2);
433}
434
441int cancelRequested(long sessionId) {
442 if (std::atomic_load(&sessionMap[sessionId % SESSION_MAP_SIZE]) == 2) {
443 return 1;
444 } else {
445 return 0;
446 }
447}
448
449#ifdef __cplusplus
450}
451#endif
452
458static void resetMessagesInTransmit(long sessionId) {
459 std::atomic_store(&sessionInTransitMessageCountMap[sessionId % SESSION_MAP_SIZE], 0);
460}
461
470void ffmpegkit_log_callback_function(void *ptr, int level, const char* format, va_list vargs) {
471 AVBPrint fullLine;
472 AVBPrint part[4];
473 int print_prefix = 1;
474
475 // DO NOT PROCESS UNWANTED LOGS
476 if (level >= 0) {
477 level &= 0xff;
478 }
479 int activeLogLevel = av_log_get_level();
480
481 // LevelAVLogStdErr logs are always redirected
482 if ((activeLogLevel == ffmpegkit::LevelAVLogQuiet && level != ffmpegkit::LevelAVLogStdErr) || (level > activeLogLevel)) {
483 return;
484 }
485
486 av_bprint_init(&fullLine, 0, AV_BPRINT_SIZE_UNLIMITED);
487
488 avutil_log_format_line(ptr, level, format, vargs, part, &print_prefix);
489 avutil_log_sanitize(part[0].str);
490 avutil_log_sanitize(part[1].str);
491 avutil_log_sanitize(part[2].str);
492 avutil_log_sanitize(part[3].str);
493
494 // COMBINE ALL 4 LOG PARTS
495 av_bprintf(&fullLine, "%s%s%s%s", part[0].str, part[1].str, part[2].str, part[3].str);
496
497 if (fullLine.len > 0) {
498 logCallbackDataAdd(level, &fullLine);
499 }
500
501 av_bprint_finalize(part, NULL);
502 av_bprint_finalize(part+1, NULL);
503 av_bprint_finalize(part+2, NULL);
504 av_bprint_finalize(part+3, NULL);
505 av_bprint_finalize(&fullLine, NULL);
506}
507
519void ffmpegkit_statistics_callback_function(int frameNumber, float fps, float quality, int64_t size, int time, double bitrate, double speed) {
520 statisticsCallbackDataAdd(frameNumber, fps, quality, size, time, bitrate, speed);
521}
522
523static void process_log(long sessionId, int levelValueInt, AVBPrint* logMessage) {
524 int activeLogLevel = av_log_get_level();
525 ffmpegkit::Level levelValue = static_cast<ffmpegkit::Level>(levelValueInt);
526 std::shared_ptr<ffmpegkit::Log> log = std::make_shared<ffmpegkit::Log>(sessionId, levelValue, logMessage->str);
527 bool globalCallbackDefined = false;
528 bool sessionCallbackDefined = false;
530
531 // LevelAVLogStdErr logs are always redirected
532 if ((activeLogLevel == ffmpegkit::LevelAVLogQuiet && levelValue != ffmpegkit::LevelAVLogStdErr) || (levelValue > activeLogLevel)) {
533 // LOG NEITHER PRINTED NOR FORWARDED
534 return;
535 }
536
537 auto session = ffmpegkit::FFmpegKitConfig::getSession(sessionId);
538 if (session != nullptr) {
539 activeLogRedirectionStrategy = session->getLogRedirectionStrategy();
540 session->addLog(log);
541
542 ffmpegkit::LogCallback sessionLogCallback = session->getLogCallback();
543 if (sessionLogCallback != nullptr) {
544 sessionCallbackDefined = true;
545
546 try {
547 // NOTIFY SESSION CALLBACK DEFINED
548 sessionLogCallback(log);
549 } catch(const std::exception& exception) {
550 std::cout << "Exception thrown inside session log callback. " << exception.what() << std::endl;
551 }
552 }
553 }
554
555 ffmpegkit::LogCallback globalLogCallback = logCallback;
556 if (globalLogCallback != nullptr) {
557 globalCallbackDefined = true;
558
559 try {
560 // NOTIFY GLOBAL CALLBACK DEFINED
561 globalLogCallback(log);
562 } catch(const std::exception& exception) {
563 std::cout << "Exception thrown inside global log callback. " << exception.what() << std::endl;
564 }
565 }
566
567 // EXECUTE THE LOG STRATEGY
568 switch (activeLogRedirectionStrategy) {
570 return;
571 }
573 if (globalCallbackDefined) {
574 return;
575 }
576 }
577 break;
579 if (sessionCallbackDefined) {
580 return;
581 }
582 }
583 break;
585 if (globalCallbackDefined || sessionCallbackDefined) {
586 return;
587 }
588 }
589 break;
591 }
592 break;
593 }
594
595 // PRINT LOGS
596 switch (levelValue) {
598 // PRINT NO OUTPUT
599 break;
600 default:
601 // WRITE TO STDOUT
602 std::cout << ffmpegkit::FFmpegKitConfig::logLevelToString(levelValue) << ": " << logMessage->str;
603 break;
604 }
605}
606
607void process_statistics(long sessionId, int videoFrameNumber, float videoFps, float videoQuality, long size, int time, double bitrate, double speed) {
608 std::shared_ptr<ffmpegkit::Statistics> statistics = std::make_shared<ffmpegkit::Statistics>(sessionId, videoFrameNumber, videoFps, videoQuality, size, time, bitrate, speed);
609
610 auto session = ffmpegkit::FFmpegKitConfig::getSession(sessionId);
611 if (session != nullptr && session->isFFmpeg()) {
612 std::shared_ptr<ffmpegkit::FFmpegSession> ffmpegSession = std::static_pointer_cast<ffmpegkit::FFmpegSession>(session);
613 ffmpegSession->addStatistics(statistics);
614
615 ffmpegkit::StatisticsCallback sessionStatisticsCallback = ffmpegSession->getStatisticsCallback();
616 if (sessionStatisticsCallback != nullptr) {
617 try {
618 sessionStatisticsCallback(statistics);
619 } catch(const std::exception& exception) {
620 std::cout << "Exception thrown inside session statistics callback. " << exception.what() << std::endl;
621 }
622 }
623 }
624
625 ffmpegkit::StatisticsCallback globalStatisticsCallback = statisticsCallback;
626 if (globalStatisticsCallback != nullptr) {
627 try {
628 globalStatisticsCallback(statistics);
629 } catch(const std::exception& exception) {
630 std::cout << "Exception thrown inside global statistics callback. " << exception.what() << std::endl;
631 }
632 }
633}
634
638void *callbackThreadFunction(void *pointer) {
639 int activeLogLevel = av_log_get_level();
640 if ((activeLogLevel != ffmpegkit::LevelAVLogQuiet) && (ffmpegkit::LevelAVLogDebug <= activeLogLevel)) {
641 std::cout << "Async callback block started." << std::endl;
642 }
643
644 while(redirectionEnabled) {
645 try {
646 CallbackData* callbackData = callbackDataRemove();
647
648 if (callbackData != nullptr) {
649
650 if (callbackData->getType() == LogType) {
651 process_log(callbackData->getSessionId(), callbackData->getLogLevel(), callbackData->getLogData());
652 av_bprint_finalize(callbackData->getLogData(), NULL);
653 } else {
654 process_statistics(callbackData->getSessionId(),
655 callbackData->getStatisticsFrameNumber(),
656 callbackData->getStatisticsFps(),
657 callbackData->getStatisticsQuality(),
658 callbackData->getStatisticsSize(),
659 callbackData->getStatisticsTime(),
660 callbackData->getStatisticsBitrate(),
661 callbackData->getStatisticsSpeed());
662 }
663
664 std::atomic_fetch_sub(&sessionInTransitMessageCountMap[callbackData->getSessionId() % SESSION_MAP_SIZE], 1);
665
666 } else {
667 callbackWait(100);
668 }
669
670 } catch(const std::exception& exception) {
671 activeLogLevel = av_log_get_level();
672 if ((activeLogLevel != ffmpegkit::LevelAVLogQuiet) && (ffmpegkit::LevelAVLogWarning <= activeLogLevel)) {
673 std::cout << "Async callback block received error: " << exception.what() << std::endl;
674 }
675 }
676 }
677
678 activeLogLevel = av_log_get_level();
679 if ((activeLogLevel != ffmpegkit::LevelAVLogQuiet) && (ffmpegkit::LevelAVLogDebug <= activeLogLevel)) {
680 std::cout << "Async callback block stopped." << std::endl;
681 }
682
683 return NULL;
684}
685
686static int executeFFmpeg(const long sessionId, const std::shared_ptr<std::list<std::string>> arguments) {
687 const char* LIB_NAME = "ffmpeg";
688
689 // SETS DEFAULT LOG LEVEL BEFORE STARTING A NEW RUN
690 av_log_set_level(configuredLogLevel);
691
692 char **commandCharPArray = (char **)av_malloc(sizeof(char*) * (arguments->size() + 1));
693
694 /* PRESERVE USAGE FORMAT
695 *
696 * ffmpeg <arguments>
697 */
698 commandCharPArray[0] = (char *)av_malloc(sizeof(char) * (strlen(LIB_NAME) + 1));
699 strcpy(commandCharPArray[0], LIB_NAME);
700
701 // PREPARE ARRAY ELEMENTS
702 int i = 0;
703 for (auto it=arguments->begin(); it != arguments->end(); it++, i++) {
704 commandCharPArray[i + 1] = (char*)it->c_str();
705 }
706
707 // REGISTER THE ID BEFORE STARTING THE SESSION
708 globalSessionId = sessionId;
709 registerSessionId(sessionId);
710
711 resetMessagesInTransmit(sessionId);
712
713 // RUN
714 int returnCode = ffmpeg_execute((arguments->size() + 1), commandCharPArray);
715
716 // ALWAYS REMOVE THE ID FROM THE MAP
717 removeSession(sessionId);
718
719 // CLEANUP
720 av_free(commandCharPArray[0]);
721 av_free(commandCharPArray);
722
723 return returnCode;
724}
725
726int executeFFprobe(const long sessionId, const std::shared_ptr<std::list<std::string>> arguments) {
727 const char* LIB_NAME = "ffprobe";
728
729 // SETS DEFAULT LOG LEVEL BEFORE STARTING A NEW RUN
730 av_log_set_level(configuredLogLevel);
731
732 char **commandCharPArray = (char **)av_malloc(sizeof(char*) * (arguments->size() + 1));
733
734 /* PRESERVE USAGE FORMAT
735 *
736 * ffprobe <arguments>
737 */
738 commandCharPArray[0] = (char *)av_malloc(sizeof(char) * (strlen(LIB_NAME) + 1));
739 strcpy(commandCharPArray[0], LIB_NAME);
740
741 // PREPARE ARRAY ELEMENTS
742 int i = 0;
743 for (auto it=arguments->begin(); it != arguments->end(); it++, i++) {
744 commandCharPArray[i + 1] = (char*)it->c_str();
745 }
746
747 // REGISTER THE ID BEFORE STARTING THE SESSION
748 globalSessionId = sessionId;
749 registerSessionId(sessionId);
750
751 resetMessagesInTransmit(sessionId);
752
753 // RUN
754 int returnCode = ffprobe_execute((arguments->size() + 1), commandCharPArray);
755
756 // ALWAYS REMOVE THE ID FROM THE MAP
757 removeSession(sessionId);
758
759 // CLEANUP
760 av_free(commandCharPArray[0]);
761 av_free(commandCharPArray);
762
763 return returnCode;
764}
765
767 std::call_once(ffmpegKitInitializerFlag, [](){
768 std::cout << "Loading ffmpeg-kit." << std::endl;
769
771
772 for(int i = 0; i<SESSION_MAP_SIZE; i++) {
773 std::atomic_init(&sessionMap[i], (short)0);
774 std::atomic_init(&sessionInTransitMessageCountMap[i], 0);
775 }
776
777 logCallback = nullptr;
778 statisticsCallback = nullptr;
782
784
786
788
789 std::cout << "Loaded ffmpeg-kit-" << ffmpegkit::Packages::getPackageName() << "-" << ffmpegkit::ArchDetect::getArch() << "-" << ffmpegkit::FFmpegKitConfig::getVersion() << "-" << ffmpegkit::FFmpegKitConfig::getBuildDate() << "." << std::endl;
790 });
791
792 return NULL;
793}
794
796 std::unique_lock<std::recursive_mutex> lock(callbackDataMutex, std::defer_lock);
797 lock.lock();
798
799 if (redirectionEnabled != 0) {
800 lock.unlock();
801 return;
802 }
804
805 lock.unlock();
806
807 int rc = pthread_create(&callbackThread, NULL, callbackThreadFunction, NULL);
808 if (rc != 0) {
809 std::cout << "Failed to create async callback block: %d" << rc << std::endl;
810 lock.unlock();
811 return;
812 }
813
814 av_log_set_callback(ffmpegkit_log_callback_function);
816}
817
819 std::unique_lock<std::recursive_mutex> lock(callbackDataMutex, std::defer_lock);
820
821 lock.lock();
822
823 if (redirectionEnabled != 1) {
824 lock.unlock();
825 return;
826 }
828
829 lock.unlock();
830
832
833 pthread_detach(callbackThread);
834
835 av_log_set_callback(av_log_default_callback);
837}
838
840 return ffmpegkit::FFmpegKitConfig::setEnvironmentVariable("FONTCONFIG_PATH", path);
841}
842
843void ffmpegkit::FFmpegKitConfig::setFontDirectory(const std::string& fontDirectoryPath, const std::map<std::string,std::string>& fontNameMapping) {
844 ffmpegkit::FFmpegKitConfig::setFontDirectoryList(std::list<std::string>{fontDirectoryPath}, fontNameMapping);
845}
846
847void ffmpegkit::FFmpegKitConfig::setFontDirectoryList(const std::list<std::string>& fontDirectoryList, const std::map<std::string,std::string>& fontNameMapping) {
848 int validFontNameMappingCount = 0;
849
850 const char *parentDirectory = std::getenv("HOME");
851 if (parentDirectory == NULL) {
852 parentDirectory = std::getenv("TMPDIR");
853 if (parentDirectory == NULL) {
854 parentDirectory = ".";
855 }
856 }
857
858 std::string cacheDir = std::string(parentDirectory) + "/.cache";
859 std::string ffmpegKitDir = cacheDir + "/ffmpegkit";
860 auto tempConfigurationDirectory = ffmpegKitDir + "/fontconfig";
861 auto fontConfigurationFile = std::string(tempConfigurationDirectory) + "/fonts.conf";
862
863 if (!fs_create_dir(cacheDir) || !fs_create_dir(ffmpegKitDir) || !fs_create_dir(tempConfigurationDirectory)) {
864 return;
865 }
866 std::cout << "Created temporary font conf directory: TRUE." << std::endl;
867
868 if (fs_exists(fontConfigurationFile, true, false)) {
869 bool fontConfigurationDeleted = std::remove(fontConfigurationFile.c_str());
870 std::cout << "Deleted old temporary font configuration: " << (fontConfigurationDeleted == 0?"TRUE":"FALSE") << "." << std::endl;
871 }
872
873 /* PROCESS MAPPINGS FIRST */
874 std::string fontNameMappingBlock = "";
875 for (auto const& pair : fontNameMapping) {
876 if ((pair.first.size() > 0) && (pair.second.size() > 0)) {
877
878 fontNameMappingBlock += " <match target=\"pattern\">\n";
879 fontNameMappingBlock += " <test qual=\"any\" name=\"family\">\n";
880 fontNameMappingBlock += " <string>";
881 fontNameMappingBlock += pair.first;
882 fontNameMappingBlock += "</string>\n";
883 fontNameMappingBlock += " </test>\n";
884 fontNameMappingBlock += " <edit name=\"family\" mode=\"assign\" binding=\"same\">\n";
885 fontNameMappingBlock += " <string>";
886 fontNameMappingBlock += pair.second;
887 fontNameMappingBlock += "</string>\n";
888 fontNameMappingBlock += " </edit>\n";
889 fontNameMappingBlock += " </match>\n";
890
891 validFontNameMappingCount++;
892 }
893 }
894
895 std::string fontConfiguration;
896 fontConfiguration += "<?xml version=\"1.0\"?>\n";
897 fontConfiguration += "<!DOCTYPE fontconfig SYSTEM \"fonts.dtd\">\n";
898 fontConfiguration += "<fontconfig>\n";
899 fontConfiguration += " <dir prefix=\"cwd\">.</dir>\n";
900
901 for (const auto& fontDirectoryPath : fontDirectoryList) {
902 fontConfiguration += " <dir>";
903 fontConfiguration += fontDirectoryPath;
904 fontConfiguration += "</dir>\n";
905 }
906 fontConfiguration += fontNameMappingBlock;
907 fontConfiguration += "</fontconfig>\n";
908
909 std::ofstream fontConfigurationStream(fontConfigurationFile, std::ios::out | std::ios::trunc);
910 if (fontConfigurationStream) {
911 fontConfigurationStream << fontConfiguration;
912 }
913 if (fontConfigurationStream.bad()) {
914 std::cout << "Failed to set font directory. Error received while saving font configuration: " << fontConfigurationStream.rdbuf() << "." << std::endl;
915 }
916 fontConfigurationStream.close();
917
918 std::cout << "Saved new temporary font configuration with " << validFontNameMappingCount << " font name mappings." << std::endl;
919
920 ffmpegkit::FFmpegKitConfig::setFontconfigConfigurationPath(tempConfigurationDirectory.c_str());
921
922 for (const auto& fontDirectoryPath : fontDirectoryList) {
923 std::cout << "Font directory " << fontDirectoryPath << " registered successfully." << std::endl;
924 }
925}
926
928 const char *parentDirectory = std::getenv("HOME");
929 if (parentDirectory == NULL) {
930 parentDirectory = std::getenv("TMPDIR");
931 if (parentDirectory == NULL) {
932 parentDirectory = ".";
933 }
934 }
935
936 // PIPES ARE CREATED UNDER THE PIPES DIRECTORY
937 std::string cacheDir = std::string(parentDirectory) + "/.cache";
938 std::string ffmpegKitDir = cacheDir + "/ffmpegkit";
939 std::string pipesDir = ffmpegKitDir + "/pipes";
940
941 if (!fs_create_dir(cacheDir) || !fs_create_dir(ffmpegKitDir) || !fs_create_dir(pipesDir)) {
942 return nullptr;
943 }
944
945 std::shared_ptr<std::string> newFFmpegPipePath = std::make_shared<std::string>(pipesDir + "/" + FFmpegKitNamedPipePrefix + std::to_string(pipeIndexGenerator++));
946
947 // FIRST CLOSE OLD PIPES WITH THE SAME NAME
948 ffmpegkit::FFmpegKitConfig::closeFFmpegPipe(newFFmpegPipePath->c_str());
949
950 int rc = mkfifo(newFFmpegPipePath->c_str(), S_IRWXU | S_IRWXG | S_IROTH);
951 if (rc == 0) {
952 return newFFmpegPipePath;
953 } else {
954 std::cout << "Failed to register new FFmpeg pipe " << newFFmpegPipePath << ". Operation failed with rc=" << rc << "." << std::endl;
955 return nullptr;
956 }
957}
958
959void ffmpegkit::FFmpegKitConfig::closeFFmpegPipe(const std::string& ffmpegPipePath) {
960 std::remove(ffmpegPipePath.c_str());
961}
962
964 return FFMPEG_VERSION;
965}
966
969 return std::string("").append(FFmpegKitVersion).append("-lts");
970 } else {
971 return FFmpegKitVersion;
972 }
973}
974
976 #if defined(FFMPEG_KIT_LTS)
977 return true;
978 #else
979 return false;
980 #endif
981}
982
984 char buildDate[10];
985 sprintf(buildDate, "%d", FFMPEG_KIT_BUILD_DATE);
986 return std::string(buildDate);
987}
988
989int ffmpegkit::FFmpegKitConfig::setEnvironmentVariable(const std::string& variableName, const std::string& variableValue) {
990 return setenv(variableName.c_str(), variableValue.c_str(), true);
991}
992
994 if (signal == ffmpegkit::SignalQuit) {
995 handleSIGQUIT = 0;
996 } else if (signal == ffmpegkit::SignalInt) {
997 handleSIGINT = 0;
998 } else if (signal == ffmpegkit::SignalTerm) {
999 handleSIGTERM = 0;
1000 } else if (signal == ffmpegkit::SignalXcpu) {
1001 handleSIGXCPU = 0;
1002 } else if (signal == ffmpegkit::SignalPipe) {
1003 handleSIGPIPE = 0;
1004 }
1005}
1006
1007void ffmpegkit::FFmpegKitConfig::ffmpegExecute(const std::shared_ptr<ffmpegkit::FFmpegSession> ffmpegSession) {
1008 ffmpegSession->startRunning();
1009
1010 try {
1011 int returnCode = executeFFmpeg(ffmpegSession->getSessionId(), ffmpegSession->getArguments());
1012 ffmpegSession->complete(std::make_shared<ffmpegkit::ReturnCode>(returnCode));
1013 } catch(const std::exception& exception) {
1014 ffmpegSession->fail(exception.what());
1015 std::cout << "FFmpeg execute failed: " << ffmpegkit::FFmpegKitConfig::argumentsToString(ffmpegSession->getArguments()) << "." << exception.what() << std::endl;
1016 }
1017}
1018
1019void ffmpegkit::FFmpegKitConfig::ffprobeExecute(const std::shared_ptr<ffmpegkit::FFprobeSession> ffprobeSession) {
1020 ffprobeSession->startRunning();
1021
1022 try {
1023 int returnCode = executeFFprobe(ffprobeSession->getSessionId(), ffprobeSession->getArguments());
1024 ffprobeSession->complete(std::make_shared<ffmpegkit::ReturnCode>(returnCode));
1025 } catch(const std::exception& exception) {
1026 ffprobeSession->fail(exception.what());
1027 std::cout << "FFprobe execute failed: " << ffmpegkit::FFmpegKitConfig::argumentsToString(ffprobeSession->getArguments()) << "." << exception.what() << std::endl;
1028 }
1029}
1030
1031void ffmpegkit::FFmpegKitConfig::getMediaInformationExecute(const std::shared_ptr<ffmpegkit::MediaInformationSession> mediaInformationSession, const int waitTimeout) {
1032 mediaInformationSession->startRunning();
1033
1034 try {
1035 int returnCodeValue = executeFFprobe(mediaInformationSession->getSessionId(), mediaInformationSession->getArguments());
1036 auto returnCode = std::make_shared<ffmpegkit::ReturnCode>(returnCodeValue);
1037 mediaInformationSession->complete(returnCode);
1038 if (returnCode->isValueSuccess()) {
1039 auto allLogs = mediaInformationSession->getAllLogsWithTimeout(waitTimeout);
1040 std::string ffprobeJsonOutput;
1041 std::for_each(allLogs->cbegin(), allLogs->cend(), [&](std::shared_ptr<ffmpegkit::Log> log) {
1042 if (log->getLevel() == LevelAVLogStdErr) {
1043 ffprobeJsonOutput.append(log->getMessage());
1044 }
1045 });
1046 auto mediaInformation = ffmpegkit::MediaInformationJsonParser::fromWithError(ffprobeJsonOutput.c_str());
1047 mediaInformationSession->setMediaInformation(mediaInformation);
1048 }
1049 } catch(const std::exception& exception) {
1050 mediaInformationSession->fail(exception.what());
1051 std::cout << "Get media information execute failed: " << ffmpegkit::FFmpegKitConfig::argumentsToString(mediaInformationSession->getArguments()) << "." << exception.what() << std::endl;
1052 }
1053}
1054
1055void ffmpegkit::FFmpegKitConfig::asyncFFmpegExecute(const std::shared_ptr<ffmpegkit::FFmpegSession> ffmpegSession) {
1056 auto thread = std::thread([ffmpegSession]() {
1058
1059 ffmpegkit::FFmpegSessionCompleteCallback completeCallback = ffmpegSession->getCompleteCallback();
1060 if (completeCallback != nullptr) {
1061 try {
1062 // NOTIFY SESSION CALLBACK DEFINED
1063 completeCallback(ffmpegSession);
1064 } catch(const std::exception& exception) {
1065 std::cout << "Exception thrown inside session complete callback. " << exception.what() << std::endl;
1066 }
1067 }
1068
1070 if (globalFFmpegSessionCompleteCallback != nullptr) {
1071 try {
1072 // NOTIFY SESSION CALLBACK DEFINED
1073 globalFFmpegSessionCompleteCallback(ffmpegSession);
1074 } catch(const std::exception& exception) {
1075 std::cout << "Exception thrown inside global complete callback. " << exception.what() << std::endl;
1076 }
1077 }
1078 });
1079
1080 thread.detach();
1081}
1082
1083void ffmpegkit::FFmpegKitConfig::asyncFFprobeExecute(const std::shared_ptr<ffmpegkit::FFprobeSession> ffprobeSession) {
1084 auto thread = std::thread([ffprobeSession]() {
1086
1087 ffmpegkit::FFprobeSessionCompleteCallback completeCallback = ffprobeSession->getCompleteCallback();
1088 if (completeCallback != nullptr) {
1089 try {
1090 // NOTIFY SESSION CALLBACK DEFINED
1091 completeCallback(ffprobeSession);
1092 } catch(const std::exception& exception) {
1093 std::cout << "Exception thrown inside session complete callback. " << exception.what() << std::endl;
1094 }
1095 }
1096
1098 if (globalFFprobeSessionCompleteCallback != nullptr) {
1099 try {
1100 // NOTIFY SESSION CALLBACK DEFINED
1101 globalFFprobeSessionCompleteCallback(ffprobeSession);
1102 } catch(const std::exception& exception) {
1103 std::cout << "Exception thrown inside global complete callback. " << exception.what() << std::endl;
1104 }
1105 }
1106 });
1107
1108 thread.detach();
1109}
1110
1111void ffmpegkit::FFmpegKitConfig::asyncGetMediaInformationExecute(const std::shared_ptr<ffmpegkit::MediaInformationSession> mediaInformationSession, const int waitTimeout) {
1112 auto thread = std::thread([mediaInformationSession,waitTimeout]() {
1113 ffmpegkit::FFmpegKitConfig::getMediaInformationExecute(mediaInformationSession, waitTimeout);
1114
1115 ffmpegkit::MediaInformationSessionCompleteCallback completeCallback = mediaInformationSession->getCompleteCallback();
1116 if (completeCallback != nullptr) {
1117 try {
1118 // NOTIFY SESSION CALLBACK DEFINED
1119 completeCallback(mediaInformationSession);
1120 } catch(const std::exception& exception) {
1121 std::cout << "Exception thrown inside session complete callback. " << exception.what() << std::endl;
1122 }
1123 }
1124
1126 if (globalMediaInformationSessionCompleteCallback != nullptr) {
1127 try {
1128 // NOTIFY SESSION CALLBACK DEFINED
1129 globalMediaInformationSessionCompleteCallback(mediaInformationSession);
1130 } catch(const std::exception& exception) {
1131 std::cout << "Exception thrown inside global complete callback. " << exception.what() << std::endl;
1132 }
1133 }
1134 });
1135
1136 thread.detach();
1137}
1138
1140 logCallback = callback;
1141}
1142
1144 statisticsCallback = callback;
1145}
1146
1148 ffmpegSessionCompleteCallback = completeCallback;
1149}
1150
1153}
1154
1156 ffprobeSessionCompleteCallback = completeCallback;
1157}
1158
1161}
1162
1164 mediaInformationSessionCompleteCallback = completeCallback;
1165}
1166
1169}
1170
1172 return static_cast<ffmpegkit::Level>(configuredLogLevel);
1173}
1174
1176 configuredLogLevel = level;
1177}
1178
1180 switch (level) {
1181 case ffmpegkit::LevelAVLogStdErr: return "STDERR";
1182 case ffmpegkit::LevelAVLogTrace: return "TRACE";
1183 case ffmpegkit::LevelAVLogDebug: return "DEBUG";
1184 case ffmpegkit::LevelAVLogVerbose: return "VERBOSE";
1185 case ffmpegkit::LevelAVLogInfo: return "INFO";
1186 case ffmpegkit::LevelAVLogWarning: return "WARNING";
1187 case ffmpegkit::LevelAVLogError: return "ERROR";
1188 case ffmpegkit::LevelAVLogFatal: return "FATAL";
1189 case ffmpegkit::LevelAVLogPanic: return "PANIC";
1190 case ffmpegkit::LevelAVLogQuiet: return "QUIET";
1191 default: return "";
1192 }
1193}
1194
1196 return sessionHistorySize;
1197}
1198
1199void ffmpegkit::FFmpegKitConfig::setSessionHistorySize(const int newSessionHistorySize) {
1200 if (newSessionHistorySize >= SESSION_MAP_SIZE) {
1201
1202 /*
1203 * THERE IS A HARD LIMIT ON THE NATIVE SIDE. HISTORY SIZE MUST BE SMALLER THAN SESSION_MAP_SIZE
1204 */
1205 throw std::runtime_error("Session history size must not exceed the hard limit!");
1206 } else if (newSessionHistorySize > 0) {
1207 sessionHistorySize = newSessionHistorySize;
1209 }
1210}
1211
1212std::shared_ptr<ffmpegkit::Session> ffmpegkit::FFmpegKitConfig::getSession(const long sessionId) {
1213 std::unique_lock<std::recursive_mutex> lock(sessionMutex, std::defer_lock);
1214 lock.lock();
1215
1216 auto session = sessionHistoryMap.find(sessionId);
1217 if (session != sessionHistoryMap.end()) {
1218 return session->second;
1219 } else {
1220 return nullptr;
1221 }
1222}
1223
1224std::shared_ptr<ffmpegkit::Session> ffmpegkit::FFmpegKitConfig::getLastSession() {
1225 std::unique_lock<std::recursive_mutex> lock(sessionMutex, std::defer_lock);
1226 lock.lock();
1227
1228 return sessionHistoryList.front();
1229}
1230
1231std::shared_ptr<ffmpegkit::Session> ffmpegkit::FFmpegKitConfig::getLastCompletedSession() {
1232 std::unique_lock<std::recursive_mutex> lock(sessionMutex, std::defer_lock);
1233
1234 lock.lock();
1235
1236 for(auto rit=sessionHistoryList.rbegin(); rit != sessionHistoryList.rend(); ++rit) {
1237 auto session = *rit;
1238 if (session->getState() == SessionStateCompleted) {
1239 return session;
1240 }
1241 }
1242
1243 return nullptr;
1244}
1245
1246std::shared_ptr<std::list<std::shared_ptr<ffmpegkit::Session>>> ffmpegkit::FFmpegKitConfig::getSessions() {
1247 std::unique_lock<std::recursive_mutex> lock(sessionMutex, std::defer_lock);
1248 lock.lock();
1249
1250 auto sessionHistoryListCopy = std::make_shared<std::list<std::shared_ptr<ffmpegkit::Session>>>(sessionHistoryList);
1251
1252 lock.unlock();
1253
1254 return sessionHistoryListCopy;
1255}
1256
1258 std::unique_lock<std::recursive_mutex> lock(sessionMutex, std::defer_lock);
1259 lock.lock();
1260
1261 sessionHistoryList.clear();
1262 sessionHistoryMap.clear();
1263
1264 lock.unlock();
1265}
1266
1267std::shared_ptr<std::list<std::shared_ptr<ffmpegkit::FFmpegSession>>> ffmpegkit::FFmpegKitConfig::getFFmpegSessions() {
1268 std::unique_lock<std::recursive_mutex> lock(sessionMutex, std::defer_lock);
1269 const auto ffmpegSessions = std::make_shared<std::list<std::shared_ptr<ffmpegkit::FFmpegSession>>>();
1270
1271 lock.lock();
1272
1273 for(auto it=sessionHistoryList.begin(); it != sessionHistoryList.end(); ++it) {
1274 auto session = *it;
1275 if (session->isFFmpeg()) {
1276 ffmpegSessions->push_back(std::static_pointer_cast<ffmpegkit::FFmpegSession>(session));
1277 }
1278 }
1279
1280 lock.unlock();
1281
1282 return ffmpegSessions;
1283}
1284
1285std::shared_ptr<std::list<std::shared_ptr<ffmpegkit::FFprobeSession>>> ffmpegkit::FFmpegKitConfig::getFFprobeSessions() {
1286 std::unique_lock<std::recursive_mutex> lock(sessionMutex, std::defer_lock);
1287 const auto ffprobeSessions = std::make_shared<std::list<std::shared_ptr<ffmpegkit::FFprobeSession>>>();
1288
1289 lock.lock();
1290
1291 for(auto it=sessionHistoryList.begin(); it != sessionHistoryList.end(); ++it) {
1292 auto session = *it;
1293 if (session->isFFprobe()) {
1294 ffprobeSessions->push_back(std::static_pointer_cast<ffmpegkit::FFprobeSession>(session));
1295 }
1296 }
1297
1298 lock.unlock();
1299
1300 return ffprobeSessions;
1301}
1302
1303std::shared_ptr<std::list<std::shared_ptr<ffmpegkit::MediaInformationSession>>> ffmpegkit::FFmpegKitConfig::getMediaInformationSessions() {
1304 std::unique_lock<std::recursive_mutex> lock(sessionMutex, std::defer_lock);
1305 const auto mediaInformationSessions = std::make_shared<std::list<std::shared_ptr<ffmpegkit::MediaInformationSession>>>();
1306
1307 lock.lock();
1308
1309 for(auto it=sessionHistoryList.begin(); it != sessionHistoryList.end(); ++it) {
1310 auto session = *it;
1311 if (session->isMediaInformation()) {
1312 mediaInformationSessions->push_back(std::static_pointer_cast<ffmpegkit::MediaInformationSession>(session));
1313 }
1314 }
1315
1316 lock.unlock();
1317
1318 return mediaInformationSessions;
1319}
1320
1321std::shared_ptr<std::list<std::shared_ptr<ffmpegkit::Session>>> ffmpegkit::FFmpegKitConfig::getSessionsByState(const SessionState state) {
1322 std::unique_lock<std::recursive_mutex> lock(sessionMutex, std::defer_lock);
1323 auto sessions = std::make_shared<std::list<std::shared_ptr<ffmpegkit::Session>>>();
1324
1325 lock.lock();
1326
1327 for(auto it=sessionHistoryList.begin(); it != sessionHistoryList.end(); ++it) {
1328 auto session = *it;
1329 if (session->getState() == state) {
1330 sessions->push_back(session);
1331 }
1332 }
1333
1334 lock.unlock();
1335
1336 return sessions;
1337}
1338
1341}
1342
1344 globalLogRedirectionStrategy = logRedirectionStrategy;
1345}
1346
1348 return std::atomic_load(&sessionInTransitMessageCountMap[sessionId % SESSION_MAP_SIZE]);
1349}
1350
1352 switch (state) {
1353 case SessionStateCreated: return "CREATED";
1354 case SessionStateRunning: return "RUNNING";
1355 case SessionStateFailed: return "FAILED";
1356 case SessionStateCompleted: return "COMPLETED";
1357 default: return "";
1358 }
1359}
1360
1361std::list<std::string> ffmpegkit::FFmpegKitConfig::parseArguments(const std::string& command) {
1362 std::list<std::string> argumentList;
1363 std::string currentArgument;
1364
1365 bool singleQuoteStarted = false;
1366 bool doubleQuoteStarted = false;
1367
1368 for (int i = 0; i < command.size(); i++) {
1369 char previousChar;
1370 if (i > 0) {
1371 previousChar = command[i - 1];
1372 } else {
1373 previousChar = 0;
1374 }
1375 char currentChar = command[i];
1376
1377 if (currentChar == ' ') {
1378 if (singleQuoteStarted || doubleQuoteStarted) {
1379 currentArgument += currentChar;
1380 } else if (currentArgument.size() > 0) {
1381 argumentList.push_back(currentArgument);
1382 currentArgument = "";
1383 }
1384 } else if (currentChar == '\'' && (previousChar == 0 || previousChar != '\\')) {
1385 if (singleQuoteStarted) {
1386 singleQuoteStarted = false;
1387 } else if (doubleQuoteStarted) {
1388 currentArgument += currentChar;
1389 } else {
1390 singleQuoteStarted = true;
1391 }
1392 } else if (currentChar == '\"' && (previousChar == 0 || previousChar != '\\')) {
1393 if (doubleQuoteStarted) {
1394 doubleQuoteStarted = false;
1395 } else if (singleQuoteStarted) {
1396 currentArgument += currentChar;
1397 } else {
1398 doubleQuoteStarted = true;
1399 }
1400 } else {
1401 currentArgument += currentChar;
1402 }
1403 }
1404
1405 if (currentArgument.size() > 0) {
1406 argumentList.push_back(currentArgument);
1407 }
1408
1409 return argumentList;
1410}
1411
1412std::string ffmpegkit::FFmpegKitConfig::argumentsToString(std::shared_ptr<std::list<std::string>> arguments) {
1413 if (arguments == nullptr) {
1414 return "null";
1415 }
1416
1417 std::string string;
1418 for(auto it=arguments->begin(); it != arguments->end(); ++it) {
1419 auto argument = *it;
1420 if (it != arguments->begin()) {
1421 string += " ";
1422 }
1423 string += argument;
1424 }
1425
1426 return string;
1427}
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
CallbackType
@ 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
static ffmpegkit::FFmpegSessionCompleteCallback ffmpegSessionCompleteCallback
static std::atomic< int > sessionInTransitMessageCountMap[SESSION_MAP_SIZE]
static const char * avutil_log_get_level_str(int level)
void ffmpegkit_statistics_callback_function(int frameNumber, float fps, float quality, int64_t size, int time, double bitrate, double speed)
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
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)
void process_statistics(long sessionId, int videoFrameNumber, float videoFps, float videoQuality, long size, int time, double bitrate, double speed)
int cancelRequested(long sessionId)
volatile int handleSIGPIPE
static CallbackData * callbackDataRemove()
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
int64_t _statisticsSize
float getStatisticsQuality()
AVBPrint * getLogData()
double _statisticsBitrate
CallbackData(const long sessionId, const int videoFrameNumber, const float videoFps, const float videoQuality, const int64_t size, const int time, const double bitrate, const double speed)
double getStatisticsSpeed()
int getStatisticsFrameNumber()
int64_t getStatisticsSize()
CallbackData(const long sessionId, const int logLevel, const AVBPrint *data)
double getStatisticsBitrate()
CallbackType getType()
CallbackType _type
float getStatisticsFps()
static std::string getArch()
Definition: ArchDetect.cpp:26
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
void set_report_callback(void(*callback)(int, float, float, int64_t, int, double, double))
@ LogRedirectionStrategyPrintLogsWhenSessionCallbackNotDefined
@ LogRedirectionStrategyAlwaysPrintLogs
@ LogRedirectionStrategyNeverPrintLogs
@ 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
Definition: SessionState.h:27
@ SessionStateFailed
Definition: SessionState.h:28
@ SessionStateCreated
Definition: SessionState.h:26
@ SessionStateCompleted
Definition: SessionState.h:29
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