Krita Source Code Documentation
Loading...
Searching...
No Matches
KisDlgImportVideoAnimation Class Reference

#include <KisDlgImportVideoAnimation.h>

+ Inheritance diagram for KisDlgImportVideoAnimation:

Public Member Functions

QStringList documentInfo ()
 
 KisDlgImportVideoAnimation (KisMainWindow *m_mainWindow, KisView *m_activeView)
 
RenderedFrames renderFrames (const QDir &directory)
 
QStringList showOpenFileDialog ()
 
- Public Member Functions inherited from KoDialog
QPushButton * button (ButtonCode id) const
 
QIcon buttonIcon (ButtonCode id) const
 
QString buttonText (ButtonCode id) const
 
QString buttonToolTip (ButtonCode id) const
 
QString buttonWhatsThis (ButtonCode id) const
 
ButtonCode defaultButton () const
 
QString helpLinkText () const
 
void incrementInitialSize (const QSize &size)
 
bool isButtonEnabled (ButtonCode id) const
 
 KoDialog (QWidget *parent=0, Qt::WindowFlags f=Qt::WindowFlags())
 
QWidget * mainWidget ()
 
QSize minimumSizeHint () const override
 
void setButtonFocus (ButtonCode id)
 
void setButtonGuiItem (ButtonCode id, const KGuiItem &item)
 
void setButtonIcon (ButtonCode id, const QIcon &icon)
 
void setButtons (ButtonCodes buttonMask)
 
void setButtonsOrientation (Qt::Orientation orientation)
 
void setButtonText (ButtonCode id, const QString &text)
 
void setButtonToolTip (ButtonCode id, const QString &text)
 
void setButtonWhatsThis (ButtonCode id, const QString &text)
 
void setDefaultButton (ButtonCode id)
 
void setEscapeButton (ButtonCode id)
 
void setInitialSize (const QSize &size)
 
void setMainWidget (QWidget *widget)
 
void showButton (ButtonCode id, bool state)
 
void showButtonSeparator (bool state)
 
QSize sizeHint () const override
 
 ~KoDialog () override
 

Protected Slots

void loadVideoFile (const QString &filename)
 
void slotDocumentHandlerChanged (int selectedIndex)
 
void slotFFMpegFile ()
 
void slotFFProbeFile ()
 
void slotFrameNumberChanged (int frame)
 
void slotImportDurationChanged (qreal time)
 
void slotNextFrame ()
 
void slotPrevFrame ()
 
void slotVideoSliderChanged ()
 
void slotVideoTimerTimeout ()
 
- Protected Slots inherited from KoDialog
virtual void slotButtonClicked (int button)
 

Private Member Functions

void CurrentFrameChanged (int frame)
 
KisPropertiesConfigurationSP loadLastUsedConfiguration (QString configurationID)
 
KisBasicVideoInfo loadVideoInfo (const QString &inputFile)
 
QStringList makeVideoMimeTypesList ()
 
void saveLastUsedConfiguration (QString configurationID, KisPropertiesConfigurationSP config)
 
void toggleInputControls (bool toggleBool)
 
void updateVideoPreview ()
 

Private Attributes

KisViewm_activeView
 
int m_currentFrame
 
int m_ffmpegFindInput
 
KisMainWindowm_mainWindow
 
Ui_VideoImportDialog m_ui
 
KisBasicVideoInfo m_videoInfo
 
QTimer * m_videoSliderTimer
 

Additional Inherited Members

- Public Types inherited from KoDialog
enum  ButtonCode {
  None = 0x00000000 , Help = 0x00000001 , Default = 0x00000002 , Ok = 0x00000004 ,
  Apply = 0x00000008 , Try = 0x00000010 , Cancel = 0x00000020 , Close = 0x00000040 ,
  No = 0x00000080 , Yes = 0x00000100 , Reset = 0x00000200 , Details = 0x00000400 ,
  User1 = 0x00001000 , User2 = 0x00002000 , User3 = 0x00004000 , NoDefault = 0x00008000
}
 
enum  ButtonPopupMode { InstantPopup = 0 , DelayedPopup = 1 }
 
enum  CaptionFlag { NoCaptionFlags = 0 , AppNameCaption = 1 , ModifiedCaption = 2 , HIGCompliantCaption = AppNameCaption }
 
- Public Slots inherited from KoDialog
void delayedDestruct ()
 
void enableButton (ButtonCode id, bool state)
 
void enableButtonApply (bool state)
 
void enableButtonCancel (bool state)
 
void enableButtonOk (bool state)
 
void enableLinkedHelp (bool state)
 
bool isDetailsWidgetVisible () const
 
virtual void setCaption (const QString &caption)
 
virtual void setCaption (const QString &caption, bool modified)
 
void setDetailsWidget (QWidget *detailsWidget)
 
void setDetailsWidgetVisible (bool visible)
 
void setHelp (const QString &anchor, const QString &appname=QString())
 
void setHelpLinkText (const QString &text)
 
virtual void setPlainCaption (const QString &caption)
 
- Signals inherited from KoDialog
void aboutToShowDetails ()
 
void applyClicked ()
 
void buttonClicked (KoDialog::ButtonCode button)
 
void cancelClicked ()
 
void closeClicked ()
 
void defaultClicked ()
 
void finished ()
 
void helpClicked ()
 
void hidden ()
 
void layoutHintChanged ()
 
void noClicked ()
 
void okClicked ()
 
void resetClicked ()
 
void tryClicked ()
 
void user1Clicked ()
 
void user2Clicked ()
 
void user3Clicked ()
 
void yesClicked ()
 
- Static Public Member Functions inherited from KoDialog
static int groupSpacingHint ()
 
static QString makeStandardCaption (const QString &userCaption, QWidget *window=0, CaptionFlags flags=HIGCompliantCaption)
 
static int marginHint ()
 
static void resizeLayout (QLayout *lay, int margin, int spacing)
 
static void resizeLayout (QWidget *widget, int margin, int spacing)
 
static int spacingHint ()
 
- Protected Member Functions inherited from KoDialog
void closeEvent (QCloseEvent *e) override
 
void hideEvent (QHideEvent *) override
 
void keyPressEvent (QKeyEvent *) override
 
void showEvent (QShowEvent *e) override
 

Detailed Description

Definition at line 52 of file KisDlgImportVideoAnimation.h.

Constructor & Destructor Documentation

◆ KisDlgImportVideoAnimation()

KisDlgImportVideoAnimation::KisDlgImportVideoAnimation ( KisMainWindow * m_mainWindow,
KisView * m_activeView )

Definition at line 33 of file KisDlgImportVideoAnimation.cpp.

33 :
34 KoDialog(mainWindow),
35 m_mainWindow(mainWindow),
36 m_activeView(activeView)
37{
40 setWindowTitle(i18nc("@title:window", "Import Video Animation"));
41
42 QWidget *page = new QWidget(this);
43 m_ui.setupUi(page);
44 setMainWidget(page);
45
47
49 QFileInfo ffmpegFileInfo(config->getPropertyLazy("ffmpeg_path",""));
50 QFileInfo ffprobeFileInfo(config->getPropertyLazy("ffprobe_path",""));
51
52 dbgFile << "Config data =" << "ffmpeg:" << ffmpegFileInfo.absoluteFilePath() << "ffprobe:" << ffprobeFileInfo.absoluteFilePath();
53
54 QJsonObject ffmpegInfo = KisFFMpegWrapper::findFFMpeg(ffmpegFileInfo.absoluteFilePath());
55
56 if (ffmpegInfo["enabled"].toBool()) {
57 m_ui.cmbFFMpegLocation->addItem(ffmpegInfo["path"].toString(),ffmpegInfo);
58
59 if (ffprobeFileInfo.filePath().isEmpty())
60 ffprobeFileInfo.setFile(ffmpegFileInfo.absoluteDir().filePath("ffprobe"));
61
62 } else {
63 enableButtonOk(false);
64 m_ui.tabGeneral->setEnabled(false);
65 QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("FFMpeg not found! Please add a path to FFMpeg in the \"Advanced\" tab"));
66 }
67
68 QJsonObject ffprobeInfo = KisFFMpegWrapper::findFFProbe(ffprobeFileInfo.absoluteFilePath());
69
70 if (ffprobeInfo["enabled"].toBool())
71 m_ui.cmbFFProbeLocation->addItem(ffprobeInfo["path"].toString(),ffprobeInfo);
72
73 m_ui.cmbFFProbeLocation->addItem("[Disabled]",QJsonObject({{"path",""},{"enabled",false}}));
74
75 m_ui.fileLocation->setMode(KoFileDialog::OpenFile);
76 m_ui.fileLocation->setMimeTypeFilters(makeVideoMimeTypesList());
77 m_ui.nextFrameButton->setIcon(KisIconUtils::loadIcon("arrow-right"));
78 m_ui.prevFrameButton->setIcon(KisIconUtils::loadIcon("arrow-left"));
79
80 m_ui.fpsSpinbox->setValue(24.0);
81 m_ui.fpsSpinbox->setSuffix(i18nc("FPS as a unit following a value, like 60 FPS", " FPS"));
82
83 m_ui.frameSkipSpinbox->setValue(1);
84 m_ui.frameSkipSpinbox->setRange(1,20);
85
86 m_ui.startExportingAtSpinbox->setValue(0.0);
87 m_ui.startExportingAtSpinbox->setRange(0.0, 9999.0);
88 m_ui.startExportingAtSpinbox->setSuffix(i18nc("Second as a unit following a value, like 60 s", " s"));
89
90 m_ui.videoPreviewSlider->setTickInterval(1);
91 m_ui.videoPreviewSlider->setValue(0);
92
93 m_ui.exportDurationSpinbox->setValue(3.0);
94 m_ui.exportDurationSpinbox->setSuffix(i18nc("Second as a unit following a value, like 60 s", " s"));
95
96 m_ui.lblWarning->hide();
97
98 connect(m_ui.cmbDocumentHandler, SIGNAL(currentIndexChanged(int)), SLOT(slotDocumentHandlerChanged(int)));
99
100 m_ui.cmbDocumentHandler->addItem(i18nc("Import video to New Document", "New Document"), "0");
101
103 m_ui.cmbDocumentHandler->addItem(i18nc("Import video to Current Document", "Current Document"), "1");
104 m_ui.cmbDocumentHandler->setCurrentIndex(1);
105 m_ui.fpsDocumentLabel->setText(i18nc("Video importer: fps of the document you're importing into"
106 , "<small>Document:\n %1 FPS</small>"
107 , QString::number(m_activeView->document()->image()->animationInterface()->framerate()))
108 );
109 }
110
111 m_ui.documentWidthSpinbox->setValue(0);
112 m_ui.documentHeightSpinbox->setValue(0);
113 m_ui.documentWidthSpinbox->setRange(1,100000);
114 m_ui.documentHeightSpinbox->setRange(1,100000);
115
116 m_ui.videoWidthSpinbox->setValue(0);
117 m_ui.videoHeightSpinbox->setValue(0);
118 m_ui.videoWidthSpinbox->setRange(1,100000);
119 m_ui.videoHeightSpinbox->setRange(1,100000);
120
121 m_ui.sensitivitySpinbox->setValue(50.0f);
122
123 m_ui.cmbVideoScaleFilter->addItem(i18n("Bicubic"), "bicubic");
124 m_ui.cmbVideoScaleFilter->addItem(i18n("Bilinear"), "bilinear");
125 m_ui.cmbVideoScaleFilter->addItem(i18n("Lanczos3"), "lanczos");
126 m_ui.cmbVideoScaleFilter->addItem(i18n("Nearest Neighbor"), "neighbor");
127 m_ui.cmbVideoScaleFilter->addItem(i18nc("An interpolation method", "Spline"), "spline");
128
129 m_ui.tabWidget->setCurrentIndex(0);
130
131 m_videoSliderTimer = new QTimer(this);
132 m_videoSliderTimer->setSingleShot(true);
133
134 connect(m_videoSliderTimer, SIGNAL(timeout()), SLOT(slotVideoTimerTimeout()));
135
136 m_currentFrame = 0;
138
140 connect(m_ui.nextFrameButton, SIGNAL(clicked()), SLOT(slotNextFrame()));
141 connect(m_ui.prevFrameButton, SIGNAL(clicked()), SLOT(slotPrevFrame()));
142 connect(m_ui.currentFrameNumberInput, SIGNAL(valueChanged(int)), SLOT(slotFrameNumberChanged(int)));
143 connect(m_ui.videoPreviewSlider, SIGNAL(valueChanged(int)), SLOT(slotVideoSliderChanged()));
144
145 connect(m_ui.ffprobePickerButton, SIGNAL(clicked()), SLOT(slotFFProbeFile()));
146 connect(m_ui.ffmpegPickerButton, SIGNAL(clicked()), SLOT(slotFFMpegFile()));
147
148 connect(m_ui.exportDurationSpinbox, SIGNAL(valueChanged(qreal)), SLOT(slotImportDurationChanged(qreal)));
149}
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
KisPropertiesConfigurationSP loadLastUsedConfiguration(QString configurationID)
void loadVideoFile(const QString &filename)
void slotDocumentHandlerChanged(int selectedIndex)
static QJsonObject findFFProbe(const QString &customLocation)
static QJsonObject findFFMpeg(const QString &customLocation)
void fileSelected(const QString &fileName)
QPointer< KisDocument > document
Definition KisView.cpp:121
void enableButtonOk(bool state)
Definition KoDialog.cpp:615
void setMainWidget(QWidget *widget)
Definition KoDialog.cpp:354
void setButtons(ButtonCodes buttonMask)
Definition KoDialog.cpp:195
void setDefaultButton(ButtonCode id)
Definition KoDialog.cpp:302
@ Ok
Show Ok button. (this button accept()s the dialog; result set to QDialog::Accepted)
Definition KoDialog.h:127
@ Cancel
Show Cancel-button. (this button reject()s the dialog; result set to QDialog::Rejected)
Definition KoDialog.h:130
KoDialog(QWidget *parent=0, Qt::WindowFlags f=Qt::WindowFlags())
Definition KoDialog.cpp:176
#define dbgFile
Definition kis_debug.h:53
QString toString(const QString &value)
QIcon loadIcon(const QString &name)

References KoDialog::Cancel, connect(), CurrentFrameChanged(), dbgFile, KisView::document, KoDialog::enableButtonOk(), KisFileNameRequester::fileSelected(), KisFFMpegWrapper::findFFMpeg(), KisFFMpegWrapper::findFFProbe(), KisIconUtils::loadIcon(), loadLastUsedConfiguration(), loadVideoFile(), m_activeView, m_currentFrame, m_ui, m_videoSliderTimer, makeVideoMimeTypesList(), KoDialog::Ok, KoFileDialog::OpenFile, KoDialog::setButtons(), KoDialog::setDefaultButton(), KoDialog::setMainWidget(), slotDocumentHandlerChanged(), slotFFMpegFile(), slotFFProbeFile(), slotFrameNumberChanged(), slotImportDurationChanged(), slotNextFrame(), slotPrevFrame(), slotVideoSliderChanged(), slotVideoTimerTimeout(), and toggleInputControls().

Member Function Documentation

◆ CurrentFrameChanged()

void KisDlgImportVideoAnimation::CurrentFrameChanged ( int frame)
private

Definition at line 632 of file KisDlgImportVideoAnimation.cpp.

633{
634 float currentSeconds = 0;
635
636 // update frame and seconds model data if they have changed
637 if (m_currentFrame != frame ) {
638 dbgFile << "Frame change to:" << frame;
639 m_currentFrame = frame;
640 currentSeconds = m_currentFrame / m_videoInfo.fps;
641 }
642
643 // update UI components if they are out of sync
644 if (m_currentFrame != m_ui.currentFrameNumberInput->value())
645 m_ui.currentFrameNumberInput->setValue(m_currentFrame);
646
647 if (m_currentFrame != m_ui.videoPreviewSlider->value())
648 m_ui.videoPreviewSlider->setValue(m_currentFrame);
649
650 m_ui.videoPreviewSliderValueLabel->setText( QString::number(currentSeconds, 'f', 2).append(i18nc("Second as a unit following a value, like 60 s", " s")) );
651}

References dbgFile, KisBasicVideoInfo::fps, m_currentFrame, m_ui, and m_videoInfo.

◆ documentInfo()

QStringList KisDlgImportVideoAnimation::documentInfo ( )

Definition at line 297 of file KisDlgImportVideoAnimation.cpp.

297 {
298 QStringList documentInfoList;
299
300 // We're looking for a possible profile here, otherwise it gets generated. Then we get the name.
301 QString profileColorSpace = RGBAColorModelID.id();
302 QString profileName = KoColorSpaceRegistry::instance()->p709SRGBProfile()->name();
305 profileName = profile->name();
306 profileColorSpace = profile->colorModelID();
307 }
308
309 documentInfoList << QString::number(m_ui.frameSkipSpinbox->value())
310 << QString::number(m_ui.fpsSpinbox->value())
311 << QString::number(qCeil(m_ui.fpsSpinbox->value() * m_ui.exportDurationSpinbox->value()))
312 << m_videoInfo.file;
313
314 if ( m_ui.cmbDocumentHandler->currentIndex() == 0 ) {
315 documentInfoList << "0"
316 << QString::number(m_ui.documentWidthSpinbox->value())
317 << QString::number(m_ui.documentHeightSpinbox->value())
318 << QString::number(72)
319 << profileColorSpace
321 << profileName;
322 } else {
323 documentInfoList << "1";
324 }
325
326 return documentInfoList;
327}
const KoID RGBAColorModelID("RGBA", ki18n("RGB/Alpha"))
@ PRIMARIES_UNSPECIFIED
QString id() const
Definition KoID.cpp:63
TransferCharacteristics colorTransfer
virtual QString colorModelID() const
const KoColorProfile * profileFor(const QVector< double > &colorants, ColorPrimaries colorPrimaries, TransferCharacteristics transferFunction) const
profileFor tries to find the profile that matches these characteristics, if no such profile is found,...
static KoColorSpaceRegistry * instance()
const KoColorProfile * p709SRGBProfile() const

References KisBasicVideoInfo::colorDepth, KoColorProfile::colorModelID(), KisBasicVideoInfo::colorPrimaries, KisBasicVideoInfo::colorTransfer, KisBasicVideoInfo::file, KoID::id(), KoColorSpaceRegistry::instance(), m_ui, m_videoInfo, KoColorProfile::name, KoColorSpaceRegistry::p709SRGBProfile(), PRIMARIES_UNSPECIFIED, KoColorSpaceRegistry::profileFor(), RGBAColorModelID, and TRC_UNSPECIFIED.

◆ loadLastUsedConfiguration()

KisPropertiesConfigurationSP KisDlgImportVideoAnimation::loadLastUsedConfiguration ( QString configurationID)
private

Definition at line 151 of file KisDlgImportVideoAnimation.cpp.

151 {
152 KisConfig globalConfig(true);
153 return globalConfig.exportConfiguration(configurationID);
154}

References KisConfig::exportConfiguration().

◆ loadVideoFile

void KisDlgImportVideoAnimation::loadVideoFile ( const QString & filename)
protectedslot

Definition at line 368 of file KisDlgImportVideoAnimation.cpp.

369{
370 const QFileInfo resultFileInfo(filename);
371 const QDir videoDir(resultFileInfo.absolutePath());
372
373 m_videoInfo = loadVideoInfo(filename);
374
375 if ( m_videoInfo.file.isEmpty() ) return;
376
377 QStringList textInfo;
378
379 textInfo.append(i18nc("video importer: video file statistics", "Width: %1 px", QString::number(m_videoInfo.width)));
380 textInfo.append(i18nc("video importer: video file statistics", "Height: %1 px", QString::number(m_videoInfo.height)));
381
383 textInfo.append(i18nc("video importer: video file statistics"
384 , "Color Primaries: %1"
386 textInfo.append(i18nc("video importer: video file statistics"
387 , "Color Transfer: %1"
389 }
390 textInfo.append(i18nc("video importer: video file statistics", "Duration: %1 s", QString::number(m_videoInfo.duration, 'f', 2)));
391 textInfo.append(i18nc("video importer: video file statistics", "Frames: %1", QString::number(m_videoInfo.frames)));
392 textInfo.append(i18nc("video importer: video file statistics", "FPS: %1", QString::number(m_videoInfo.fps)));
393
394
396 textInfo.append(i18nc("video importer: video file statistics", "*<font size='0.5em'><em>*FPS not right in file. Modified to see full duration</em></font>"));
397 }
398
399 m_ui.fpsSpinbox->setValue( qCeil(m_videoInfo.fps) );
400 m_ui.fileLoadedDetails->setText(textInfo.join("\n"));
401
402
403 m_ui.videoPreviewSlider->setRange(0, m_videoInfo.frames);
404 m_ui.currentFrameNumberInput->setRange(0, m_videoInfo.frames);
405 m_ui.exportDurationSpinbox->setRange(0, 9999.0);
406
407 if (m_ui.cmbDocumentHandler->currentIndex() == 0) {
408 m_ui.documentWidthSpinbox->setValue(m_videoInfo.width);
409 m_ui.documentHeightSpinbox->setValue(m_videoInfo.height);
410 }
411
412 m_ui.videoWidthSpinbox->setValue(m_videoInfo.width);
413 m_ui.videoHeightSpinbox->setValue(m_videoInfo.height);
414
415 m_ui.exportDurationSpinbox->setValue(m_videoInfo.duration);
416
418
419 if ( m_videoInfo.file.isEmpty() ) {
420 toggleInputControls(false);
421 } else {
424 }
425
426
427}
KisBasicVideoInfo loadVideoInfo(const QString &inputFile)
static QString getTransferCharacteristicName(TransferCharacteristics curve)
getTransferCharacteristicName
static QString getColorPrimariesName(ColorPrimaries primaries)
getColorPrimariesName

References KisBasicVideoInfo::colorPrimaries, KisBasicVideoInfo::colorTransfer, CurrentFrameChanged(), KisBasicVideoInfo::duration, KisBasicVideoInfo::file, KisBasicVideoInfo::fps, KisBasicVideoInfo::frames, KoColorProfile::getColorPrimariesName(), KoColorProfile::getTransferCharacteristicName(), KisBasicVideoInfo::hasOverriddenFPS, KisBasicVideoInfo::height, loadVideoInfo(), m_ui, m_videoInfo, PRIMARIES_UNSPECIFIED, toggleInputControls(), TRC_UNSPECIFIED, updateVideoPreview(), and KisBasicVideoInfo::width.

◆ loadVideoInfo()

KisBasicVideoInfo KisDlgImportVideoAnimation::loadVideoInfo ( const QString & inputFile)
private

Definition at line 653 of file KisDlgImportVideoAnimation.cpp.

654{
655 QJsonObject ffmpegInfo = m_ui.cmbFFMpegLocation->currentData().toJsonObject();
656 QJsonObject ffprobeInfo = m_ui.cmbFFProbeLocation->currentData().toJsonObject();
657 struct KisBasicVideoInfo videoInfoData;
658
659 KisFFMpegWrapper *ffprobe = new KisFFMpegWrapper(this);
660 QJsonObject ffprobeJsonObj;
661
662 std::function<void(void)> warnFFmpegFormatSupport = [this](){
663 QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("Your FFMpeg version does not support this format"));
664 };
665
666 if (ffprobeInfo["enabled"].toBool()) {
667 ffprobeJsonObj = ffprobe->ffprobe(inputFile, ffprobeInfo["path"].toString());
668 }
669
670 // Attempt manual probing with ffmpeg itself if ffprobe is disable or if something went wrong with ffprobe.
671 if ( !ffprobeInfo["enabled"].toBool() || ffprobeJsonObj["error"].toInt() == FFProbeErrorCodes::INVALID_JSON ) {
672 KisFFMpegWrapper *ffmpeg = new KisFFMpegWrapper(this);
673
674 ffprobeJsonObj = ffmpeg->ffmpegProbe(inputFile, ffmpegInfo["path"].toString(), false);
675
676 dbgFile << "ffmpeg probe1" << ffprobeJsonObj;
677
678 QJsonObject ffprobeProgress = ffprobeJsonObj["progress"].toObject();
679
680 videoInfoData.frames = ffprobeProgress["frame"].toString().toInt();
681 }
682
683 if ( ffprobeJsonObj["error"].toInt() == FFProbeErrorCodes::UNSUPPORTED_CODEC) {
684 // If, after all of that, we still don't determine a supported codec then we'll back out.
685 warnFFmpegFormatSupport();
686 return {};
687 } else if ( ffprobeJsonObj["error"].toInt() == FFProbeErrorCodes::NONE ) {
688
689 QJsonObject ffprobeFormat = ffprobeJsonObj["format"].toObject();
690 QJsonArray ffprobeStreams = ffprobeJsonObj["streams"].toArray();
691
692 videoInfoData.file = inputFile;
693 for (const QJsonValueRef &streamItemRef : ffprobeStreams) {
694 QJsonObject streamItemObj = streamItemRef.toObject();
695
696 if ( streamItemObj["codec_type"].toString() == "video" ) {
697 videoInfoData.stream = streamItemObj["index"].toInt();
698 break;
699 }
700 }
701
702 if ( videoInfoData.stream == -1 ) {
703 QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("No video stream could be found!"));
704 return {};
705 }
706
707 const QJsonObject ffprobeSelectedStream = ffprobeStreams[videoInfoData.stream].toObject();
708
709 const QJsonObject decoders = ffmpegInfo.value("codecs").toObject();
710
711 const QString codecName = ffprobeSelectedStream["codec_name"].toString();
712
713 const auto decoder = decoders.constFind(codecName);
714
715 if (decoder == decoders.constEnd() ) {
716 dbgFile << "Codec missing or unsupported:" << codecName;
717 warnFFmpegFormatSupport();
718 return {};
719 } else if (!decoder->toObject().value("decoding").toBool()) {
720 dbgFile << "Codec not supported for decoding:" << codecName;
721 warnFFmpegFormatSupport();
722 return {};
723 }
724
725 videoInfoData.width = ffprobeSelectedStream["width"].toInt();
726 videoInfoData.height = ffprobeSelectedStream["height"].toInt();
727 videoInfoData.encoding = ffprobeSelectedStream["codec_name"].toString();
728 videoInfoData.colorPrimaries = KisFFMpegWrapper::colorPrimariesFromName(ffprobeSelectedStream["color_primaries"].toString());
729 videoInfoData.colorTransfer = KisFFMpegWrapper::transferCharacteristicsFromName(ffprobeSelectedStream["color_transfer"].toString());
730
731 // bits_per_raw_sample was introduced in 2014.
732 if (ffprobeSelectedStream.value("bits_per_raw_sample").toInt() > 8) {
733 videoInfoData.colorDepth = Integer16BitsColorDepthID.id();
734 } else {
735 videoInfoData.colorDepth = Integer8BitsColorDepthID.id();
736 }
737
738 // frame rate comes back in odd format...so we need to do a bit of work so it is more usable.
739 // data will come back like "50/3"
740 QStringList rawFrameRate = ffprobeSelectedStream["r_frame_rate"].toString().split('/');
741
742 if (!rawFrameRate.isEmpty())
743 videoInfoData.fps = qCeil(rawFrameRate[0].toFloat() / rawFrameRate[1].toFloat());
744
745 if ( !ffprobeSelectedStream["nb_frames"].isNull() ) {
746 videoInfoData.frames = ffprobeSelectedStream["nb_frames"].toString().toInt();
747 }
748
749 // Get duration from stream, if it doesn't exist such as on VP8 and VP9, try to get it out of format
750 if ( !ffprobeSelectedStream["duration"].isNull() ) {
751 videoInfoData.duration = ffprobeSelectedStream["duration"].toString().toFloat();
752 } else if ( !ffprobeFormat["duration"].isNull() ) {
753 videoInfoData.duration = ffprobeFormat["duration"].toString().toFloat();
754 } else if ( videoInfoData.frames ) {
755 videoInfoData.duration = videoInfoData.frames / videoInfoData.fps;
756 }
757
758 dbgFile << "Initial video info from probe: "
759 << "stream:" << videoInfoData.stream
760 << "frames:" << videoInfoData.frames
761 << "duration:" << videoInfoData.duration
762 << "fps:" << videoInfoData.fps
763 << "encoding:" << videoInfoData.encoding;
764
765 if ( !videoInfoData.frames && !videoInfoData.duration ) {
766 KisFFMpegWrapper *ffmpeg = new KisFFMpegWrapper(this);
767
768 QJsonObject ffmpegJsonObj = ffmpeg->ffmpegProbe(inputFile, ffmpegInfo["path"].toString(), false);
769
770 dbgFile << "ffmpeg probe2" << ffmpegJsonObj;
771
772 if ( ffprobeJsonObj["error"].toInt() != FFProbeErrorCodes::NONE ) {
773 QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("Failed to load video information"));
774 return {};
775 }
776
777 QJsonObject ffmpegProgressJsonObj = ffmpegJsonObj["progress"].toObject();
778 float ffmpegFPS = ffmpegProgressJsonObj["ffmpeg_fps"].toString().toFloat();
779
780 videoInfoData.frames = ffmpegProgressJsonObj["frame"].toString().toInt();
781
782 if (ffmpegFPS > 0 && videoInfoData.frames) {
783 videoInfoData.duration = videoInfoData.frames / ffmpegFPS;
784 videoInfoData.fps = ffmpegFPS;
785 } else {
786 videoInfoData.duration = ffmpegProgressJsonObj["out_time_ms"].toString().toFloat() / 1000000;
787 if (videoInfoData.frames) videoInfoData.fps = videoInfoData.frames / videoInfoData.duration;
788 }
789
790 }
791 }
792
793 // if there is no data on frames but duration and fps exists like OGV, try to estimate it
794 if ( videoInfoData.fps && videoInfoData.duration && !videoInfoData.frames ) {
795 videoInfoData.frames = qCeil( videoInfoData.fps * videoInfoData.duration );
796 }
797
798 dbgFile << "Final video info from probe: "
799 << "stream:" << videoInfoData.stream
800 << "frames:" << videoInfoData.frames
801 << "duration:" << videoInfoData.duration
802 << "fps:" << videoInfoData.fps
803 << "encoding:" << videoInfoData.encoding;
804
805 const float calculatedFrameRateByDuration = videoInfoData.frames / videoInfoData.duration;
806 const int frameRateDifference = qAbs(videoInfoData.fps - calculatedFrameRateByDuration);
807
808 if (frameRateDifference > 1) {
809 // something is not right with the frame rate with this file, so let's use our calculated value
810 // to make sure we get the whole duration
811 videoInfoData.hasOverriddenFPS = true;
812 videoInfoData.fps = calculatedFrameRateByDuration;
813 } else {
814 videoInfoData.hasOverriddenFPS = false;
815 }
816
817 return videoInfoData;
818}
@ INVALID_JSON
@ UNSUPPORTED_CODEC
@ NONE
const KoID Integer8BitsColorDepthID("U8", ki18n("8-bit integer/channel"))
const KoID Integer16BitsColorDepthID("U16", ki18n("16-bit integer/channel"))
static TransferCharacteristics transferCharacteristicsFromName(QString name)
QJsonObject ffmpegProbe(const QString &inputFile, const QString &ffmpegPath, bool batchMode)
static ColorPrimaries colorPrimariesFromName(QString name)
typedef void(QOPENGLF_APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC)(GLuint buffer)
int toInt(const QString &str, bool *ok=nullptr)

References KisBasicVideoInfo::colorDepth, KisBasicVideoInfo::colorPrimaries, KisFFMpegWrapper::colorPrimariesFromName(), KisBasicVideoInfo::colorTransfer, dbgFile, KisBasicVideoInfo::duration, KisBasicVideoInfo::encoding, KisFFMpegWrapper::ffmpegProbe(), KisBasicVideoInfo::file, KisBasicVideoInfo::fps, KisBasicVideoInfo::frames, KisBasicVideoInfo::hasOverriddenFPS, KisBasicVideoInfo::height, KoID::id(), Integer16BitsColorDepthID, Integer8BitsColorDepthID, INVALID_JSON, m_ui, NONE, KisBasicVideoInfo::stream, KisFFMpegWrapper::transferCharacteristicsFromName(), UNSUPPORTED_CODEC, void(), and KisBasicVideoInfo::width.

◆ makeVideoMimeTypesList()

QStringList KisDlgImportVideoAnimation::makeVideoMimeTypesList ( )
private

Definition at line 329 of file KisDlgImportVideoAnimation.cpp.

330{
331 QStringList supportedMimeTypes = QStringList();
332 supportedMimeTypes << "video/x-matroska";
333 supportedMimeTypes << "image/gif";
334 supportedMimeTypes << "image/apng";
335 supportedMimeTypes << "image/png";
336 supportedMimeTypes << "video/quicktime"; // MOV
337 supportedMimeTypes << "video/ogg";
338 supportedMimeTypes << "video/mp4";
339 supportedMimeTypes << "video/mpeg";
340 supportedMimeTypes << "video/webm";
341
342 // All files
343 supportedMimeTypes << "application/octet-stream";
344
345 return supportedMimeTypes;
346}
QList< QString > QStringList

◆ renderFrames()

RenderedFrames KisDlgImportVideoAnimation::renderFrames ( const QDir & directory)

Definition at line 166 of file KisDlgImportVideoAnimation.cpp.

167{
168 RenderedFrames frames;
169 QStringList &frameFileList = frames.renderedFrameFiles;
170 QList<int> &frameTimeList = frames.renderedFrameTargetTimes;
171
172 if ( !directory.mkpath(".") ) {
173 QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("Failed to create a work directory, make sure you have write permission"));
174 return frames;
175 }
176
177 QStringList args;
178 const float exportDuration = m_ui.exportDurationSpinbox->value();
179 const float fps = m_ui.fpsSpinbox->value();
180 const float nDuplicateSensitivity = m_ui.sensitivitySpinbox->value() / m_ui.sensitivitySpinbox->maximum();
181
182 if (exportDuration / fps > 100.0) {
183 if (QMessageBox::warning(this, i18nc("Title for a messagebox", "Krita"),
184 i18n("Warning: you are trying to import more than 100 frames into Krita.\n\n"
185 "This means you might be overloading your system.\n"
186 "If you want to edit a clip larger than 100 frames, consider using a real video editor, like Kdenlive (https://kdenlive.org)."),
187 QMessageBox::Ok | QMessageBox::Cancel,
188 QMessageBox::Cancel) == QMessageBox::Cancel) {
189 return frames;
190 }
191 }
192
193 // Setup FFMpeg Command Args...
194 args << "-ss" << QString::number(m_ui.startExportingAtSpinbox->value())
195 << "-i" << m_videoInfo.file;
196
197 const float sceneFiltrationFilterThreshold = rerange( 1 - nDuplicateSensitivity, 0.0f, 1.0f, 0.0005f, 0.2f);
198
199 if (m_ui.optionFilterDuplicates->isChecked()) {
200 args << "-filter:v" << QString("select=gt(scene\\,%1)+eq(n\\,0)").arg(sceneFiltrationFilterThreshold)
201 << "-vsync" << "0";
202 }
203
204 args << "-t" << QString::number(exportDuration)
205 << "-r" << QString::number(fps);
206
207 if ( m_videoInfo.width != m_ui.videoWidthSpinbox->value() || m_videoInfo.height != m_ui.videoHeightSpinbox->value() ) {
208 args << "-vf" << QString("scale=w=")
209 .append(QString::number(m_ui.videoWidthSpinbox->value()))
210 .append(":h=")
211 .append(QString::number(m_ui.videoHeightSpinbox->value()))
212 .append(":flags=")
213 .append(m_ui.cmbVideoScaleFilter->currentData().toString());
214 }
215
216 QJsonObject ffmpegInfo = m_ui.cmbFFMpegLocation->currentData().toJsonObject();
217 QJsonObject ffprobeInfo = m_ui.cmbFFProbeLocation->currentData().toJsonObject();
218
219 KisPropertiesConfigurationSP config = loadLastUsedConfiguration("ANIMATION_EXPORT");
220
221 config->setProperty("ffmpeg_path", ffmpegInfo["path"].toString());
222 config->setProperty("ffprobe_path", ffprobeInfo["path"].toString());
223
224 saveLastUsedConfiguration("ANIMATION_EXPORT", config);
225
226 {
227 KisFFMpegWrapperSettings ffmpegSettings;
228
229 ffmpegSettings.processPath = ffmpegInfo["path"].toString();
230 ffmpegSettings.args = args;
231 ffmpegSettings.outputFile = directory.filePath("output_%04d.png");
232 ffmpegSettings.logPath = QDir::tempPath() + QDir::separator() + "krita" + QDir::separator() + "ffmpeg.log";
233 ffmpegSettings.totalFrames = qCeil(exportDuration * fps);
234 ffmpegSettings.progressMessage = i18nc("FFMPEG animated video import message. arg1: frame progress number. arg2: file suffix."
235 , "Extracted %1 frames from %2 video.", "[progress]", "[suffix]");
236
237 QScopedPointer<KisFFMpegWrapper> ffmpeg(new KisFFMpegWrapper(this));
238
239 ffmpeg->startNonBlocking(ffmpegSettings);
240
241 bool ffmpegSuccess = ffmpeg->waitForFinished();
242 if (!ffmpegSuccess) {
243 return RenderedFrames();
244 }
245
246 frameFileList = directory.entryList(QStringList() << "output_*.png",QDir::Files);
247 frameFileList.replaceInStrings("output_", directory.absolutePath() + QDir::separator() + "output_");
248
249 dbgFile << "Import frames list:" << frameFileList;
250 }
251
252 if (m_ui.optionFilterDuplicates->isChecked()){
253 KisFFMpegWrapperSettings ffmpegSettings;
254 ffmpegSettings.defaultPrependArgs.clear();
255 ffmpegSettings.processPath = ffprobeInfo["path"].toString();
256
257 QString filter = "movie=" + m_videoInfo.file + QString(",setpts=N+1,select=gt(scene\\,%1)").arg(sceneFiltrationFilterThreshold);
258 ffmpegSettings.args = QStringList() << "-select_streams" << "v"
259 << "-show_entries" << "frame=pkt_pts"
260 << "-of" << "compact=p=0:nk=1"
261 << "-f" << "lavfi" << filter;
262
263
264 QScopedPointer<KisFFMpegWrapper> ffmpeg(new KisFFMpegWrapper(this));
265 frameTimeList = {0}; // We always have a frame 0 here...
266 connect(ffmpeg.data(), &KisFFMpegWrapper::sigReadSTDOUT, [&](QByteArray arr) {
267 QString out = QString(arr);
268
269 QStringList integerOuts = out.split("\n", Qt::SkipEmptyParts);
270 Q_FOREACH(const QString& str, integerOuts){
271 bool ok = false;
272 const int value = str.toUInt(&ok);
273 if (ok) {
274 frameTimeList.push_back(value);
275 }
276 }
277 });
278
279 ffmpeg->startNonBlocking(ffmpegSettings);
280
281 bool ffmpegSuccess = ffmpeg->waitForFinished();
282 if (!ffmpegSuccess) {
283 return RenderedFrames();
284 }
285
286 dbgFile << "Assign to frames:" << ppVar(frameTimeList);
287 }
288
289 if ( frameFileList.isEmpty() ) {
290 QMessageBox::critical(this, i18nc("@title:window", "Krita"), i18n("Failed to export frames from video"));
291 }
292
293 return frames;
294}
float rerange(float value, float oldMin, float oldMax, float newMin, float newMax)
void saveLastUsedConfiguration(QString configurationID, KisPropertiesConfigurationSP config)
void sigReadSTDOUT(QByteArray stdoutBuffer)
#define ppVar(var)
Definition kis_debug.h:155
QList< int > renderedFrameTargetTimes

References KisFFMpegWrapperSettings::args, connect(), dbgFile, KisFFMpegWrapperSettings::defaultPrependArgs, KisBasicVideoInfo::file, KisBasicVideoInfo::height, loadLastUsedConfiguration(), KisFFMpegWrapperSettings::logPath, m_ui, m_videoInfo, KisFFMpegWrapperSettings::outputFile, ppVar, KisFFMpegWrapperSettings::processPath, KisFFMpegWrapperSettings::progressMessage, RenderedFrames::renderedFrameFiles, RenderedFrames::renderedFrameTargetTimes, rerange(), saveLastUsedConfiguration(), KisFFMpegWrapper::sigReadSTDOUT(), KisFFMpegWrapperSettings::totalFrames, and KisBasicVideoInfo::width.

◆ saveLastUsedConfiguration()

void KisDlgImportVideoAnimation::saveLastUsedConfiguration ( QString configurationID,
KisPropertiesConfigurationSP config )
private

Definition at line 156 of file KisDlgImportVideoAnimation.cpp.

157{
158 KisConfig globalConfig(false);
159 globalConfig.setExportConfiguration(configurationID, config);
160}

References KisConfig::setExportConfiguration().

◆ showOpenFileDialog()

QStringList KisDlgImportVideoAnimation::showOpenFileDialog ( )

Definition at line 348 of file KisDlgImportVideoAnimation.cpp.

349{
350 KoFileDialog dialog(this, KoFileDialog::ImportFiles, "OpenDocument");
351 dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation));
352 dialog.setMimeTypeFilters( makeVideoMimeTypesList() );
353 dialog.setCaption(i18n("Select your Video File"));
354
355 return dialog.filenames();
356}

References KoFileDialog::ImportFiles, and makeVideoMimeTypesList().

◆ slotDocumentHandlerChanged

void KisDlgImportVideoAnimation::slotDocumentHandlerChanged ( int selectedIndex)
protectedslot

Definition at line 601 of file KisDlgImportVideoAnimation.cpp.

602{
603 bool toggleDocumentOptions = selectedIndex == 0;
604
605 if (toggleDocumentOptions) {
606 m_ui.fpsDocumentLabel->setText(" ");
607
608 if (m_videoInfo.stream != -1) {
609 m_ui.documentWidthSpinbox->setValue(m_videoInfo.width);
610 m_ui.documentHeightSpinbox->setValue(m_videoInfo.height);
611 }
612
613 } else if (m_activeView) {
614 m_ui.fpsDocumentLabel->setText(i18nc("Video importer: fps of the document you're importing into"
615 , "<small>Document:\n %1 FPS</small>"
616 , QString::number(m_activeView->document()->image()->animationInterface()->framerate()))
617 );
618 }
619
620 m_ui.optionsDocumentGroup->setEnabled(toggleDocumentOptions);
621
622}

References KisView::document, KisBasicVideoInfo::height, m_activeView, m_ui, m_videoInfo, KisBasicVideoInfo::stream, and KisBasicVideoInfo::width.

◆ slotFFMpegFile

void KisDlgImportVideoAnimation::slotFFMpegFile ( )
protectedslot

Definition at line 573 of file KisDlgImportVideoAnimation.cpp.

574{
575 KoFileDialog dialog(this, KoFileDialog::OpenFile, i18n("Open FFMpeg"));
576 dialog.setDefaultDir(QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation).last());
577 dialog.setCaption(i18n("Open FFMpeg"));
578
579 QStringList filenames = dialog.filenames();
580
581 if (!filenames.isEmpty()) {
582 QJsonObject ffmpegInfo = KisFFMpegWrapper::findFFMpeg(filenames[0]);
583
584 if (ffmpegInfo["enabled"].toBool()) {
585 if (ffmpegInfo["custom"].toBool()) {
586 m_ui.cmbFFMpegLocation->addItem(filenames[0],ffmpegInfo);
587 m_ui.cmbFFMpegLocation->setCurrentText(filenames[0]);
588 } else {
589 QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("FFMpeg is invalid!"));
590 }
591 m_ui.tabGeneral->setEnabled(true);
592 return;
593 }
594
595 m_ui.tabGeneral->setEnabled(false);
596 QMessageBox::critical(this, i18nc("@title:window", "Krita"), i18n("No FFMpeg found!"));
597 }
598
599}

References KisFFMpegWrapper::findFFMpeg(), m_ui, and KoFileDialog::OpenFile.

◆ slotFFProbeFile

void KisDlgImportVideoAnimation::slotFFProbeFile ( )
protectedslot

Definition at line 552 of file KisDlgImportVideoAnimation.cpp.

553{
554 KoFileDialog dialog(this, KoFileDialog::OpenFile, i18n("Open FFProbe"));
555 dialog.setDefaultDir(QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation).last());
556 dialog.setCaption(i18n("Open FFProbe"));
557
558 QStringList filenames = dialog.filenames();
559
560 if (!filenames.isEmpty()) {
561 QJsonObject ffprobeInfo = KisFFMpegWrapper::findFFProbe(filenames[0]);
562
563 if (ffprobeInfo["enabled"].toBool() && ffprobeInfo["custom"].toBool()) {
564 m_ui.cmbFFProbeLocation->addItem(filenames[0],ffprobeInfo);
565 m_ui.cmbFFProbeLocation->setCurrentText(filenames[0]);
566 return;
567 }
568 QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("FFProbe is invalid!"));
569 }
570
571}

References KisFFMpegWrapper::findFFProbe(), m_ui, and KoFileDialog::OpenFile.

◆ slotFrameNumberChanged

void KisDlgImportVideoAnimation::slotFrameNumberChanged ( int frame)
protectedslot

Definition at line 546 of file KisDlgImportVideoAnimation.cpp.

547{
548 CurrentFrameChanged(frame);
549}

References CurrentFrameChanged().

◆ slotImportDurationChanged

void KisDlgImportVideoAnimation::slotImportDurationChanged ( qreal time)
protectedslot

Definition at line 469 of file KisDlgImportVideoAnimation.cpp.

470{
474 const KFormat format;
475
476 const int resolution = m_videoInfo.width * m_videoInfo.height;
477 quint32 pixelSize = 4; //how do we even go about getting the bitdepth???
478 if (m_activeView && m_ui.cmbDocumentHandler->currentIndex() > 0) {
479 pixelSize = m_activeView->image()->colorSpace()->pixelSize() * 4;
480 } else if (m_videoInfo.colorDepth == "U16"){
481 pixelSize = 8;
482 }
483 const qint64 frames = std::lround(qreal(m_videoInfo.fps) * time + 2);
484 // Sometimes, the potential size of the file is so big (a feature length film taking easily 970 gib), that we cannot put it into a number.
485 // It's more efficient therefore to calculate the maximum amount of frames possible.
486
487 const qint64 maxFrames = stats.totalMemoryLimit / resolution / pixelSize;
488
489 QStringList warnings;
490
491 const QString text_frames = i18nc("part of warning in video importer."
492 , "<b>Warning:</b> you are trying to import %1 frames, the maximum amount you can import is %2."
493 , frames
494 , maxFrames);
495
496 QString text_memory;
497
498 const QString text_video_editor = i18nc("part of warning in video importer.",
499 "Use a <a href=\"https://kdenlive.org\">video editor</a> instead!");
500
501 if (maxFrames < frames) {
502 warnings.append(text_frames);
503 text_memory = i18nc("part of warning in video importer."
504 , "You do not have enough memory to load this many frames, the computer will be overloaded.");
505 warnings.insert(0, "<span style=\"color:#ff692e;\">");
506 warnings.append(text_memory);
507 warnings.append(text_video_editor);
508 m_ui.lblWarning->setVisible(true);
509 } else if (maxFrames < frames * 2) {
510 warnings.append(text_frames);
511 text_memory = i18nc("part of warning in video importer."
512 , "This will take over half the available memory, editing will be difficult.");
513 warnings.insert(0, "<span style=\"color:#ffee00;\">");
514 warnings.append(text_memory);
515 warnings.append(text_video_editor);
516 m_ui.lblWarning->setVisible(true);
519 warnings.append(text_frames);
520 QString text_trc = i18nc("part of warning in video importer."
521 , "Krita does not support the video transfer curve (%1), it will be loaded as linear."
523 warnings.append(text_trc);
524 }
525
526 if (warnings.isEmpty()) {
527 m_ui.lblWarning->setVisible(false);
528 } else {
529 m_ui.lblWarning->setText(warnings.join(" "));
530 m_ui.lblWarning->setPixmap(
531 m_ui.lblWarning->style()->standardIcon(QStyle::SP_MessageBoxWarning).pixmap(QSize(32, 32)));
532 m_ui.lblWarning->setVisible(true);
533 }
534}
@ TRC_ITU_R_BT_2100_0_HLG
@ TRC_SMPTE_ST_428_1
const KoColorSpace * colorSpace() const
KisImageWSP image() const
Definition KisView.cpp:432
virtual quint32 pixelSize() const =0
Statistics fetchMemoryStatistics(KisImageSP image) const
static KisMemoryStatisticsServer * instance()

References KisBasicVideoInfo::colorDepth, KisImage::colorSpace(), KisBasicVideoInfo::colorTransfer, KisMemoryStatisticsServer::fetchMemoryStatistics(), KisBasicVideoInfo::fps, KoColorProfile::getTransferCharacteristicName(), KisBasicVideoInfo::height, KisView::image(), KisMemoryStatisticsServer::instance(), m_activeView, m_ui, m_videoInfo, KoColorSpace::pixelSize(), KisMemoryStatisticsServer::Statistics::totalMemoryLimit, TRC_ITU_R_BT_2100_0_HLG, TRC_SMPTE_ST_428_1, and KisBasicVideoInfo::width.

◆ slotNextFrame

void KisDlgImportVideoAnimation::slotNextFrame ( )
protectedslot

Definition at line 536 of file KisDlgImportVideoAnimation.cpp.

References CurrentFrameChanged(), and m_currentFrame.

◆ slotPrevFrame

void KisDlgImportVideoAnimation::slotPrevFrame ( )
protectedslot

Definition at line 541 of file KisDlgImportVideoAnimation.cpp.

References CurrentFrameChanged(), and m_currentFrame.

◆ slotVideoSliderChanged

void KisDlgImportVideoAnimation::slotVideoSliderChanged ( )
protectedslot

Definition at line 624 of file KisDlgImportVideoAnimation.cpp.

625{
626 CurrentFrameChanged(m_ui.videoPreviewSlider->value());
627
628 if (!m_videoSliderTimer->isActive()) m_videoSliderTimer->start(300);
629
630}

References CurrentFrameChanged(), m_ui, and m_videoSliderTimer.

◆ slotVideoTimerTimeout

void KisDlgImportVideoAnimation::slotVideoTimerTimeout ( )
protectedslot

Definition at line 464 of file KisDlgImportVideoAnimation.cpp.

465{
467}

References updateVideoPreview().

◆ toggleInputControls()

void KisDlgImportVideoAnimation::toggleInputControls ( bool toggleBool)
private

Definition at line 359 of file KisDlgImportVideoAnimation.cpp.

360{
361 enableButtonOk(toggleBool);
362 m_ui.videoPreviewSlider->setEnabled(toggleBool);
363 m_ui.currentFrameNumberInput->setEnabled(toggleBool);
364 m_ui.nextFrameButton->setEnabled(toggleBool);
365 m_ui.prevFrameButton->setEnabled(toggleBool);
366}

References KoDialog::enableButtonOk(), and m_ui.

◆ updateVideoPreview()

void KisDlgImportVideoAnimation::updateVideoPreview ( )
private

Definition at line 430 of file KisDlgImportVideoAnimation.cpp.

431{
432 float currentDuration = ( m_videoInfo.stream != -1 ) ? (m_currentFrame / m_videoInfo.fps):0;
433 QStringList args;
434
435 args << "-ss" << QString::number(currentDuration)
436 << "-i" << m_videoInfo.file
437 << "-v" << "quiet"
438 << "-vframes" << "1"
439 << "-vcodec" << "mjpeg"
440 << "-f" << "image2pipe"
441 << "pipe:1";
442
443 struct KisFFMpegWrapperSettings ffmpegSettings;
444
445 QJsonObject ffmpegInfo = m_ui.cmbFFMpegLocation->currentData().toJsonObject();
446 QByteArray byteImage = KisFFMpegWrapper::runProcessAndReturn(ffmpegInfo["path"].toString(), args, FFMPEG_TIMEOUT);
447
448 if ( byteImage.isEmpty() ) {
449 m_ui.thumbnailImageHolder->setText( m_videoInfo.frames == m_currentFrame ? "End of Video":"No Preview" );
450 } else {
451 QPixmap thumbnailPixmap;
452 thumbnailPixmap.loadFromData(byteImage,"JFIF");
453
454 m_ui.thumbnailImageHolder->clear();
455 const QSize previewSize =
456 m_ui.thumbnailImageHolder->contentsRect().size() * m_ui.thumbnailImageHolder->devicePixelRatioF();
457 QPixmap img = thumbnailPixmap.scaled(previewSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
458 img.setDevicePixelRatio(m_ui.thumbnailImageHolder->devicePixelRatioF());
459 m_ui.thumbnailImageHolder->setPixmap(img);
460 }
461}
const int FFMPEG_TIMEOUT
static QByteArray runProcessAndReturn(const QString &processPath, const QStringList &args, int msecs=FFMPEG_TIMEOUT)

References FFMPEG_TIMEOUT, KisBasicVideoInfo::file, KisBasicVideoInfo::fps, KisBasicVideoInfo::frames, m_currentFrame, m_ui, m_videoInfo, KisFFMpegWrapper::runProcessAndReturn(), and KisBasicVideoInfo::stream.

Member Data Documentation

◆ m_activeView

KisView* KisDlgImportVideoAnimation::m_activeView
private

Definition at line 88 of file KisDlgImportVideoAnimation.h.

◆ m_currentFrame

int KisDlgImportVideoAnimation::m_currentFrame
private

Definition at line 92 of file KisDlgImportVideoAnimation.h.

◆ m_ffmpegFindInput

int KisDlgImportVideoAnimation::m_ffmpegFindInput
private

Definition at line 94 of file KisDlgImportVideoAnimation.h.

◆ m_mainWindow

KisMainWindow* KisDlgImportVideoAnimation::m_mainWindow
private

Definition at line 87 of file KisDlgImportVideoAnimation.h.

◆ m_ui

Ui_VideoImportDialog KisDlgImportVideoAnimation::m_ui
private

Definition at line 86 of file KisDlgImportVideoAnimation.h.

◆ m_videoInfo

KisBasicVideoInfo KisDlgImportVideoAnimation::m_videoInfo
private

Definition at line 91 of file KisDlgImportVideoAnimation.h.

◆ m_videoSliderTimer

QTimer* KisDlgImportVideoAnimation::m_videoSliderTimer
private

Definition at line 90 of file KisDlgImportVideoAnimation.h.


The documentation for this class was generated from the following files: