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 32 of file KisDlgImportVideoAnimation.cpp.

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

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

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

◆ documentInfo()

QStringList KisDlgImportVideoAnimation::documentInfo ( )

Definition at line 296 of file KisDlgImportVideoAnimation.cpp.

296 {
297 QStringList documentInfoList;
298
299 // We're looking for a possible profile here, otherwise it gets generated. Then we get the name.
300 QString profileColorSpace = RGBAColorModelID.id();
301 QString profileName = KoColorSpaceRegistry::instance()->p709SRGBProfile()->name();
304 profileName = profile->name();
305 profileColorSpace = profile->colorModelID();
306 }
307
308 documentInfoList << QString::number(m_ui.frameSkipSpinbox->value())
309 << QString::number(m_ui.fpsSpinbox->value())
310 << QString::number(qCeil(m_ui.fpsSpinbox->value() * m_ui.exportDurationSpinbox->value()))
311 << m_videoInfo.file;
312
313 if ( m_ui.cmbDocumentHandler->currentIndex() == 0 ) {
314 documentInfoList << "0"
315 << QString::number(m_ui.documentWidthSpinbox->value())
316 << QString::number(m_ui.documentHeightSpinbox->value())
317 << QString::number(72)
318 << profileColorSpace
320 << profileName;
321 } else {
322 documentInfoList << "1";
323 }
324
325 return documentInfoList;
326}
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 150 of file KisDlgImportVideoAnimation.cpp.

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

References KisConfig::exportConfiguration().

◆ loadVideoFile

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

Definition at line 367 of file KisDlgImportVideoAnimation.cpp.

368{
369 const QFileInfo resultFileInfo(filename);
370 const QDir videoDir(resultFileInfo.absolutePath());
371
372 m_videoInfo = loadVideoInfo(filename);
373
374 if ( m_videoInfo.file.isEmpty() ) return;
375
376 QStringList textInfo;
377
378 textInfo.append(i18nc("video importer: video file statistics", "Width: %1 px", QString::number(m_videoInfo.width)));
379 textInfo.append(i18nc("video importer: video file statistics", "Height: %1 px", QString::number(m_videoInfo.height)));
380
382 textInfo.append(i18nc("video importer: video file statistics"
383 , "Color Primaries: %1"
385 textInfo.append(i18nc("video importer: video file statistics"
386 , "Color Transfer: %1"
388 }
389 textInfo.append(i18nc("video importer: video file statistics", "Duration: %1 s", QString::number(m_videoInfo.duration, 'f', 2)));
390 textInfo.append(i18nc("video importer: video file statistics", "Frames: %1", QString::number(m_videoInfo.frames)));
391 textInfo.append(i18nc("video importer: video file statistics", "FPS: %1", QString::number(m_videoInfo.fps)));
392
393
395 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>"));
396 }
397
398 m_ui.fpsSpinbox->setValue( qCeil(m_videoInfo.fps) );
399 m_ui.fileLoadedDetails->setText(textInfo.join("\n"));
400
401
402 m_ui.videoPreviewSlider->setRange(0, m_videoInfo.frames);
403 m_ui.currentFrameNumberInput->setRange(0, m_videoInfo.frames);
404 m_ui.exportDurationSpinbox->setRange(0, 9999.0);
405
406 if (m_ui.cmbDocumentHandler->currentIndex() == 0) {
407 m_ui.documentWidthSpinbox->setValue(m_videoInfo.width);
408 m_ui.documentHeightSpinbox->setValue(m_videoInfo.height);
409 }
410
411 m_ui.videoWidthSpinbox->setValue(m_videoInfo.width);
412 m_ui.videoHeightSpinbox->setValue(m_videoInfo.height);
413
414 m_ui.exportDurationSpinbox->setValue(m_videoInfo.duration);
415
417
418 if ( m_videoInfo.file.isEmpty() ) {
419 toggleInputControls(false);
420 } else {
423 }
424
425
426}
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 652 of file KisDlgImportVideoAnimation.cpp.

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

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

◆ renderFrames()

RenderedFrames KisDlgImportVideoAnimation::renderFrames ( const QDir & directory)

Definition at line 165 of file KisDlgImportVideoAnimation.cpp.

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

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

References KisConfig::setExportConfiguration().

◆ showOpenFileDialog()

QStringList KisDlgImportVideoAnimation::showOpenFileDialog ( )

Definition at line 347 of file KisDlgImportVideoAnimation.cpp.

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

References KoFileDialog::ImportFiles, and makeVideoMimeTypesList().

◆ slotDocumentHandlerChanged

void KisDlgImportVideoAnimation::slotDocumentHandlerChanged ( int selectedIndex)
protectedslot

Definition at line 600 of file KisDlgImportVideoAnimation.cpp.

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

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

◆ slotFFMpegFile

void KisDlgImportVideoAnimation::slotFFMpegFile ( )
protectedslot

Definition at line 572 of file KisDlgImportVideoAnimation.cpp.

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

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

◆ slotFFProbeFile

void KisDlgImportVideoAnimation::slotFFProbeFile ( )
protectedslot

Definition at line 551 of file KisDlgImportVideoAnimation.cpp.

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

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

◆ slotFrameNumberChanged

void KisDlgImportVideoAnimation::slotFrameNumberChanged ( int frame)
protectedslot

Definition at line 545 of file KisDlgImportVideoAnimation.cpp.

546{
547 CurrentFrameChanged(frame);
548}

References CurrentFrameChanged().

◆ slotImportDurationChanged

void KisDlgImportVideoAnimation::slotImportDurationChanged ( qreal time)
protectedslot

Definition at line 468 of file KisDlgImportVideoAnimation.cpp.

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

References CurrentFrameChanged(), and m_currentFrame.

◆ slotPrevFrame

void KisDlgImportVideoAnimation::slotPrevFrame ( )
protectedslot

Definition at line 540 of file KisDlgImportVideoAnimation.cpp.

References CurrentFrameChanged(), and m_currentFrame.

◆ slotVideoSliderChanged

void KisDlgImportVideoAnimation::slotVideoSliderChanged ( )
protectedslot

Definition at line 623 of file KisDlgImportVideoAnimation.cpp.

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

References CurrentFrameChanged(), m_ui, and m_videoSliderTimer.

◆ slotVideoTimerTimeout

void KisDlgImportVideoAnimation::slotVideoTimerTimeout ( )
protectedslot

Definition at line 463 of file KisDlgImportVideoAnimation.cpp.

464{
466}

References updateVideoPreview().

◆ toggleInputControls()

void KisDlgImportVideoAnimation::toggleInputControls ( bool toggleBool)
private

Definition at line 358 of file KisDlgImportVideoAnimation.cpp.

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

References KoDialog::enableButtonOk(), and m_ui.

◆ updateVideoPreview()

void KisDlgImportVideoAnimation::updateVideoPreview ( )
private

Definition at line 429 of file KisDlgImportVideoAnimation.cpp.

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