Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Movie import #1258

Merged
merged 20 commits into from
May 7, 2020
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
2109f8f
Add movie importing features
scribblemaniac Aug 31, 2019
ce079a8
Add ffprobe to CI builds
scribblemaniac Aug 31, 2019
4218c7a
Detect failed movie video import
scribblemaniac Aug 31, 2019
1bb7f1b
Add cancel to movie import and audio mixing step of movie export
scribblemaniac Aug 31, 2019
036bcd3
Add cancel to movie audio import
scribblemaniac Aug 31, 2019
e8593f1
Add progress updates and cancel to numbered image sequence import
scribblemaniac Aug 31, 2019
5aa5fdc
Added support for many new audio formats
scribblemaniac Sep 7, 2019
45aaada
Create a Movies import format that matches all supported extensions
scribblemaniac Sep 14, 2019
52c2fb9
Make ffprobe optional by default and don't include by default
scribblemaniac Sep 14, 2019
3650d8a
Merge branch 'master' into movie-import
scribblemaniac Mar 4, 2020
0dc229c
Write to disk during movie import
scribblemaniac Mar 4, 2020
d458c10
Change ffmpeg-based duration detection
scribblemaniac Mar 4, 2020
3b4aa3a
Add some checks and TODOs to the movie importer
scribblemaniac Mar 4, 2020
055e626
Delete temporary folders on closing without saving
scribblemaniac Mar 4, 2020
9804aec
Merge branch 'master' into pr-1258-changes
MrStevns May 4, 2020
5a7257b
Move MovieImport Logic into MovieImporter class and decouple UI from …
MrStevns May 6, 2020
df12488
Rename verifyFFMPEG -> verifyFFmpegExists
MrStevns May 6, 2020
ea33310
Refactor movie importer...again
scribblemaniac May 7, 2020
1dc3ade
Fix blank dialog when cancelling movie import
scribblemaniac May 7, 2020
514f130
Remove unnecessary QProgressDialog reference in Editor
scribblemaniac May 7, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion app/src/actioncommands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,17 @@ Status ActionCommands::importSound()
return Status::SAFE;
}

Status st = mEditor->sound()->loadSound(key, strSoundFile);
Status st = Status::FAIL;

if (strSoundFile.endsWith(".wav"))
{
st = mEditor->sound()->loadSound(key, strSoundFile);
}
else
{
QProgressDialog dummyDialog;
st = mEditor->importMovieAudio(strSoundFile, dummyDialog) ? Status::OK : Status::FAIL;
}

if (!st.ok())
{
Expand Down
2 changes: 1 addition & 1 deletion app/src/filedialogex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ QString FileDialog::openFileFilters( FileType fileType )
case FileType::IMAGE: return PFF_IMAGE_FILTER;
case FileType::IMAGE_SEQUENCE: return PFF_IMAGE_SEQ_FILTER;
case FileType::GIF: return PFF_GIF_EXT_FILTER;
case FileType::MOVIE: { Q_ASSERT(false); return PFF_MOVIE_EXT; } // currently not supported
case FileType::MOVIE: return PFF_MOVIE_EXT;
case FileType::SOUND: return PFF_SOUND_EXT_FILTER;
case FileType::PALETTE: return PFF_PALETTE_EXT_FILTER;
}
Expand Down
80 changes: 72 additions & 8 deletions app/src/mainwindow2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,12 @@ void MainWindow2::createMenus()
connect(ui->actionImport_ImageSeq, &QAction::triggered, this, &MainWindow2::importImageSequence);
connect(ui->actionImport_ImageSeqNum, &QAction::triggered, this, &MainWindow2::importPredefinedImageSet);
connect(ui->actionImportLayers_from_pclx, &QAction::triggered, this, &MainWindow2::importLayers);
connect(ui->actionImport_MovieVideo, &QAction::triggered, this, &MainWindow2::importMovieVideo);
connect(ui->actionImport_Gif, &QAction::triggered, this, &MainWindow2::importGIF);
connect(ui->actionImport_Movie, &QAction::triggered, this, &MainWindow2::importMovie);

connect(ui->actionImport_Sound, &QAction::triggered, mCommands, &ActionCommands::importSound);
connect(ui->actionImport_MovieAudio, &QAction::triggered, this, &MainWindow2::importMovieAudio);

connect(ui->actionImport_Append_Palette, &QAction::triggered, this, &MainWindow2::importPalette);
connect(ui->actionImport_Replace_Palette, &QAction::triggered, this, &MainWindow2::openPalette);

Expand Down Expand Up @@ -364,7 +366,7 @@ void MainWindow2::createMenus()
mColorBox->toggleViewAction(),
mColorPalette->toggleViewAction(),
mTimeLine->toggleViewAction(),
mDisplayOptionWidget->toggleViewAction(),
mDisplayOptionWidget->toggleViewAction(),
mColorInspector->toggleViewAction(),
mOnionSkinWidget->toggleViewAction()
};
Expand Down Expand Up @@ -727,6 +729,8 @@ bool MainWindow2::saveObject(QString strSavedFileName)
mEditor->object()->setFilePath(strSavedFileName);
mEditor->object()->setModified(false);

mEditor->clearTemporary();

QSettings settings(PENCIL2D, PENCIL2D);
settings.setValue(LAST_PCLX_PATH, strSavedFileName);

Expand Down Expand Up @@ -970,15 +974,74 @@ void MainWindow2::importGIF()
mIsImportingImageSequence = false;
}

void MainWindow2::importMovie()
void MainWindow2::importMovieVideo()
{
FileDialog fileDialog(this);
QString filePath = fileDialog.openFile(FileType::MOVIE);
if (filePath.isEmpty())
{
return;
}
mEditor->importMovie(filePath, mEditor->playback()->fps());

// Flag this so we don't prompt the user about auto-save in the middle of the import.
mIsImportingImageSequence = true;

// Show a progress dialog, as this can take a while if you have lots of images.
QProgressDialog progress(tr("Importing movie video..."), tr("Abort"), 0, 100, this);
hideQuestionMark(progress);
progress.setWindowModality(Qt::WindowModal);
progress.show();

bool ok = mEditor->importMovieVideo(filePath, mEditor->playback()->fps(), progress);

if (!ok)
{
QMessageBox::warning(this,
tr("Warning"),
tr("was unable to import") + filePath,
QMessageBox::Ok,
QMessageBox::Ok);
}

mEditor->layers()->notifyAnimationLengthChanged();

progress.setValue(100);
progress.close();

mIsImportingImageSequence = false;
}

void MainWindow2::importMovieAudio()
{
FileDialog fileDialog(this);
QString filePath = fileDialog.openFile(FileType::MOVIE);
if (filePath.isEmpty())
{
return;
}

// Show a progress dialog. The progress isn't actually tracked, but this will allow the operation to be cancelled
QProgressDialog progress(tr("Importing movie video..."), tr("Abort"), 0, 100, this);
hideQuestionMark(progress);
progress.setWindowModality(Qt::WindowModal);
progress.setValue(0);
progress.show();

bool ok = mEditor->importMovieAudio(filePath, progress);

if (!ok)
{
QMessageBox::warning(this,
tr("Warning"),
tr("was unable to import") + filePath,
QMessageBox::Ok,
QMessageBox::Ok);
}

mEditor->layers()->notifyAnimationLengthChanged();

progress.setValue(100);
progress.close();
}

void MainWindow2::lockWidgets(bool shouldLock)
Expand All @@ -992,7 +1055,7 @@ void MainWindow2::lockWidgets(bool shouldLock)
mOnionSkinWidget->setFeatures(feat);
mToolOptions->setFeatures(feat);
mToolBox->setFeatures(feat);
mTimeLine->setFeatures(feat);
mTimeLine->setFeatures(feat);
}

void MainWindow2::preferences()
Expand Down Expand Up @@ -1041,7 +1104,7 @@ bool MainWindow2::newObject()

bool MainWindow2::newObjectFromPresets(int presetIndex)
{
Object* object = nullptr;
Object* object = nullptr;
QString presetFilePath = (presetIndex > 0) ? PresetDialog::getPresetPath(presetIndex) : "";
if (!presetFilePath.isEmpty())
{
Expand Down Expand Up @@ -1122,7 +1185,8 @@ void MainWindow2::setupKeyboardShortcuts()

ui->actionImport_Image->setShortcut(cmdKeySeq(CMD_IMPORT_IMAGE));
ui->actionImport_ImageSeq->setShortcut(cmdKeySeq(CMD_IMPORT_IMAGE_SEQ));
ui->actionImport_Movie->setShortcut(cmdKeySeq(CMD_IMPORT_MOVIE));
ui->actionImport_MovieVideo->setShortcut(cmdKeySeq(CMD_IMPORT_MOVIE_VIDEO));
ui->actionImport_MovieAudio->setShortcut(cmdKeySeq(CMD_IMPORT_MOVIE_AUDIO));
ui->actionImport_Append_Palette->setShortcut(cmdKeySeq(CMD_IMPORT_PALETTE));
ui->actionImport_Sound->setShortcut(cmdKeySeq(CMD_IMPORT_SOUND));

Expand Down Expand Up @@ -1218,7 +1282,7 @@ void MainWindow2::setupKeyboardShortcuts()
mColorBox->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_COLOR_WHEEL));
mColorPalette->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_COLOR_LIBRARY));
mTimeLine->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_TIMELINE));
mDisplayOptionWidget->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_DISPLAY_OPTIONS));
mDisplayOptionWidget->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_DISPLAY_OPTIONS));
mColorInspector->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_COLOR_INSPECTOR));
mOnionSkinWidget->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_ONION_SKIN));

Expand Down
5 changes: 4 additions & 1 deletion app/src/mainwindow2.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,13 @@ public slots:
// import
void importImage();
void importImageSequence();
void importImageSequenceNumbered();
void addLayerByFilename(QString strFilePath);
void importPredefinedImageSet();
void importLayers();
void importMovie();
void importMovieVideo();
void importGIF();
void importMovieAudio();

void lockWidgets(bool shouldLock);

Expand Down
21 changes: 15 additions & 6 deletions app/ui/mainwindow2.ui
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,13 @@
<addaction name="separator"/>
<addaction name="actionImport_Image"/>
<addaction name="actionImport_ImageSeq"/>
<addaction name="actionImport_Movie"/>
<addaction name="actionImport_ImageSeqNum"/>
<addaction name="actionImport_MovieVideo"/>
<addaction name="actionImport_Gif"/>
<addaction name="actionImportLayers_from_pclx"/>
<addaction name="separator"/>
<addaction name="actionImport_Sound"/>
<addaction name="actionImport_MovieAudio"/>
<addaction name="separator"/>
<addaction name="actionImport_Replace_Palette"/>
<addaction name="actionImport_Append_Palette"/>
Expand Down Expand Up @@ -348,12 +350,9 @@
<string>Image Sequence...</string>
</property>
</action>
<action name="actionImport_Movie">
<action name="actionImport_MovieVideo">
<property name="text">
<string>Movie...</string>
</property>
<property name="visible">
<bool>false</bool>
<string>Movie Video...</string>
</property>
</action>
<action name="actionImport_Sound">
Expand Down Expand Up @@ -1015,6 +1014,16 @@
<string>Peg bar Alignment</string>
</property>
</action>
<action name="actionImport_MovieVideo">
<property name="text">
<string>Movie Video...</string>
</property>
</action>
<action name="actionImport_MovieAudio">
<property name="text">
<string>Movie Audio...</string>
</property>
</action>
<action name="actionImport_Append_Palette">
<property name="text">
<string>Append to Palette...</string>
Expand Down
64 changes: 0 additions & 64 deletions core_lib/src/external/linux/linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,67 +61,3 @@ void initialise()
foreach (QString format, formats)
{qDebug() << "QImageWriter capability: " << format;}
}

void Editor::importMovie (QString filePath, int fps)
{

int i;
QSettings settings( PENCIL2D, PENCIL2D );

qDebug() << "-------IMPORT VIDEO------" << filePath;

// --------- Import all the temporary frames ----------
QDir::temp().mkdir("pencil");
QString tempPath = QDir::temp().absolutePath()+"/pencil/";

QProgressDialog progress("Importing movie...", "Abort", 0, 100, NULL);
progress.setWindowModality(Qt::WindowModal);
progress.show();
progress.setValue(10);
QProcess ffmpeg;
qDebug() << "ffmpeg -i \"" << filePath << "\" -r " << QString::number(fps) << " -f image2 \"" << tempPath << "tmp_import%4d.png\"";
ffmpeg.start("ffmpeg -i \"" + filePath + "\" -r " + QString::number(fps) + " -f image2 \"" + tempPath + "tmp_import%4d.png\"");
progress.setValue(20);
if (ffmpeg.waitForStarted() == true)
{
if (ffmpeg.waitForFinished() == true)
{
QByteArray sErr = ffmpeg.readAllStandardError();
if (sErr == "")
{qDebug() << "ERROR: Could not execute FFmpeg.";}
else
{
qDebug() << "stderr: " + ffmpeg.readAllStandardOutput();
qDebug() << "stdout: " << sErr;
}
}
else
{qDebug() << "ERROR: FFmpeg did not finish executing.";}
}
else
{qDebug() << "Please install FFMPEG: sudo apt-get install ffmpeg";}
progress.setValue(50);
QDir dir1(tempPath);
int nFiles = dir1.entryList().count();
i=1;
QString frameNumberString = QString::number(i);
while( frameNumberString.length() < 4) frameNumberString.prepend("0");
while (QFile::exists(tempPath+"tmp_import"+frameNumberString+".png"))
{
progress.setValue(50+i*50/nFiles);
if(i>1) scrubForward();
importImage(tempPath+"tmp_import"+frameNumberString+".png");
i++;
frameNumberString = QString::number(i);
while( frameNumberString.length() < 4) frameNumberString.prepend("0");
}
progress.setValue(100);
// --------- Clean up temp directory ---------
QDir dir(tempPath);
QStringList filtername("*.*");
QStringList entries = dir.entryList(filtername,QDir::Files,QDir::Type);
for(int i=0; i<entries.size(); i++)
dir.remove(entries[i]);

}

64 changes: 0 additions & 64 deletions core_lib/src/external/macosx/macosx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,68 +83,4 @@ void enableCoalescing()
//MacOSXNative::setMouseCoalescingEnabled(true);
}

void Editor::importMovie(QString filePath, int fps)
{

int i;
QSettings settings( PENCIL2D , PENCIL2D );

qDebug() << "-------IMPORT VIDEO------" << filePath;

// --------- Import all the temporary frames ----------
QDir::temp().mkdir("pencil");
QString tempPath = QDir::temp().absolutePath()+"/pencil/";

QProgressDialog progress("Importing movie...", "Abort", 0, 100, NULL);
progress.setWindowModality(Qt::WindowModal);
progress.show();
progress.setValue(10);
QProcess ffmpeg;
qDebug() << "ffmpeg -i \"" << filePath << "\" -r " << QString::number(fps) << " -f image2 \"" << tempPath << "tmp_import%4d.png\"";
ffmpeg.start("ffmpeg -i \"" + filePath + "\" -r " + QString::number(fps) + " -f image2 \"" + tempPath + "tmp_import%4d.png\"");
progress.setValue(20);
if (ffmpeg.waitForStarted() == true)
{
if (ffmpeg.waitForFinished() == true)
{
QByteArray sErr = ffmpeg.readAllStandardError();
if (sErr == "")
{qDebug() << "ERROR: Could not execute FFmpeg.";}
else
{
qDebug() << "stderr: " + ffmpeg.readAllStandardOutput();
qDebug() << "stdout: " << sErr;
}
}
else
{qDebug() << "ERROR: FFmpeg did not finish executing.";}
}
else
{
qDebug() << "Please install FFMPEG: sudo apt-get install ffmpeg";
}
progress.setValue(50);
QDir dir1(tempPath);
int nFiles = dir1.entryList().count();
i=1;
QString frameNumberString = QString::number(i);
while( frameNumberString.length() < 4) frameNumberString.prepend("0");
while (QFile::exists(tempPath+"tmp_import"+frameNumberString+".png"))
{
progress.setValue(50+i*50/nFiles);
if(i>1) scrubForward();
importImage(tempPath+"tmp_import"+frameNumberString+".png");
i++;
frameNumberString = QString::number(i);
while( frameNumberString.length() < 4) frameNumberString.prepend("0");
}
progress.setValue(100);
// --------- Clean up temp directory ---------
QDir dir(tempPath);
QStringList filtername("*.*");
QStringList entries = dir.entryList(filtername,QDir::Files,QDir::Type);
for(int i=0; i<entries.size(); i++)
dir.remove(entries[i]);
}

} // extern "C"
Loading