From 93827c87377c58c24e4d3aa5a2504bd194932f98 Mon Sep 17 00:00:00 2001 From: adam Date: Mon, 22 Nov 2021 02:15:14 +0100 Subject: [PATCH] [GUI] search scene change + shortcuts for black frame search --- avidemux/common/ADM_commonUI/myOwnMenu.h | 6 +- avidemux/common/gtkgui.h | 2 + avidemux/common/gui_action.names | 2 + avidemux/common/gui_navigate.cpp | 6 + avidemux/common/gui_scenechange.cpp | 251 ++++++++++++++++++ .../qt4/ADM_userInterfaces/ADM_gui/Q_gui2.cpp | 28 +- .../ADM_userInterfaces/ADM_gui/avidemux.qrc | 2 + .../ADM_gui/avidemux_osx.qrc | 2 + .../ADM_gui/avidemux_win32.qrc | 2 + .../ADM_gui/avidemux_win32_custom_font.qrc | 2 + .../ADM_gui/pics/next_scd.png | Bin 0 -> 1280 bytes .../ADM_gui/pics/prev_scd.png | Bin 0 -> 1279 bytes cmake/commonCmakeApplication.cmake | 1 + 13 files changed, 298 insertions(+), 6 deletions(-) create mode 100644 avidemux/common/gui_scenechange.cpp create mode 100644 avidemux/qt4/ADM_userInterfaces/ADM_gui/pics/next_scd.png create mode 100644 avidemux/qt4/ADM_userInterfaces/ADM_gui/pics/prev_scd.png diff --git a/avidemux/common/ADM_commonUI/myOwnMenu.h b/avidemux/common/ADM_commonUI/myOwnMenu.h index 2c3d2d43e7..f83b5d9d5e 100644 --- a/avidemux/common/ADM_commonUI/myOwnMenu.h +++ b/avidemux/common/ADM_commonUI/myOwnMenu.h @@ -137,8 +137,10 @@ static const MenuEntry _myMenuGo[] = { {MENU_ACTION,QT_TRANSLATE_NOOP("adm","Next Intra Frame"), NULL,ACT_NextKFrame, MKICON(player_fwd), "Up",0}, {MENU_ACTION,QT_TRANSLATE_NOOP("adm","Previous Cut Point"), NULL,ACT_PrevCutPoint, MKICON(prev_cut), NULL,0}, {MENU_ACTION,QT_TRANSLATE_NOOP("adm","Next Cut Point"), NULL,ACT_NextCutPoint, MKICON(next_cut), NULL,0}, - {MENU_ACTION,QT_TRANSLATE_NOOP("adm","Previous Black Frame"),NULL,ACT_PrevBlackFrame, MKICON(prev_black), NULL,0}, - {MENU_ACTION,QT_TRANSLATE_NOOP("adm","Next Black Frame"), NULL,ACT_NextBlackFrame, MKICON(next_black), NULL,0}, + {MENU_ACTION,QT_TRANSLATE_NOOP("adm","Previous Scene Change"),NULL,ACT_PrevSceneChange, MKICON(prev_scd), "Alt+Left",0}, + {MENU_ACTION,QT_TRANSLATE_NOOP("adm","Next Scene Change"), NULL,ACT_NextSceneChange, MKICON(next_scd), "Alt+Right",0}, + {MENU_ACTION,QT_TRANSLATE_NOOP("adm","Previous Black Frame"),NULL,ACT_PrevBlackFrame, MKICON(prev_black), "Alt+Shift+Left",0}, + {MENU_ACTION,QT_TRANSLATE_NOOP("adm","Next Black Frame"), NULL,ACT_NextBlackFrame, MKICON(next_black), "Alt+Shift+Right",0}, {MENU_ACTION,QT_TRANSLATE_NOOP("adm","First Frame"), NULL,ACT_Begin, MKICON(player_start), "Home",0}, {MENU_ACTION,QT_TRANSLATE_NOOP("adm","Last Frame"), NULL,ACT_End, MKICON(player_end), "End",0}, {MENU_SEPARATOR,"-",NULL,ACT_DUMMY,NULL,NULL,1}, diff --git a/avidemux/common/gtkgui.h b/avidemux/common/gtkgui.h index 33dc0ece07..f0b7d74aae 100644 --- a/avidemux/common/gtkgui.h +++ b/avidemux/common/gtkgui.h @@ -28,6 +28,8 @@ bool GUI_PreviousKeyFrame(void); bool GUI_GoToTime(uint64_t time); uint8_t GUI_close(void); +void GUI_PrevSceneChange(); +void GUI_NextSceneChange(); void GUI_PrevBlackFrame(void); void GUI_NextBlackFrame( ) ; void GUI_NextPrevBlackFrame( int ) ; diff --git a/avidemux/common/gui_action.names b/avidemux/common/gui_action.names index 495feeffa8..696022a67e 100644 --- a/avidemux/common/gui_action.names +++ b/avidemux/common/gui_action.names @@ -42,6 +42,8 @@ ACT(PreviousKFrame) ACT(PreviousFrame) ACT(PrevCutPoint) ACT(NextCutPoint) +ACT(PrevSceneChange) +ACT(NextSceneChange) ACT(PrevBlackFrame) ACT(NextBlackFrame) ACT(Goto) diff --git a/avidemux/common/gui_navigate.cpp b/avidemux/common/gui_navigate.cpp index 12e32a36f2..d8a19c1c93 100644 --- a/avidemux/common/gui_navigate.cpp +++ b/avidemux/common/gui_navigate.cpp @@ -267,6 +267,12 @@ static int ignore_change=0; case ACT_NextCutPoint: GUI_NextCutPoint(); break; + case ACT_PrevSceneChange: + GUI_PrevSceneChange(); + break; + case ACT_NextSceneChange: + GUI_NextSceneChange(); + break; case ACT_NextBlackFrame: GUI_NextBlackFrame(); break; diff --git a/avidemux/common/gui_scenechange.cpp b/avidemux/common/gui_scenechange.cpp new file mode 100644 index 0000000000..cbaccea4b5 --- /dev/null +++ b/avidemux/common/gui_scenechange.cpp @@ -0,0 +1,251 @@ +/*************************************************************************** + gui_scenechange.cpp - description + ------------------- + + Detect scene change + + + copyright : (C) 2002/2008 by mean + 2021 szlldm + email : fixounet@free.fr + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "ADM_cpp.h" +#include "avi_vars.h" + +#include + +#include "DIA_fileSel.h" +#include "ADM_assert.h" +#include "prototype.h" +#include "audio_out.h" +#include "ADM_coreAudio.h" +#include "gui_action.hxx" +#include "gtkgui.h" +#include "DIA_coreToolkit.h" +#include "ADM_render/GUI_render.h" +#include "DIA_working.h" +#include "DIA_processing.h" +#include "ADM_commonUI/DIA_busy.h" +#include "ADM_commonUI/GUI_ui.h" + +#include "ADM_vidMisc.h" +#include "ADM_preview.h" + +static float histogramGUISceneChange[64]; + +/** + \fn scChUtilCalcHisto + \brief Calculate histogram +*/ +void scChUtilCalcHisto(ADMImage *img, float * hist) +{ + uint32_t w,h; + int strides[3]; + uint8_t * planes[3], *ptr1, *ptr2; + img->getWidthHeight(&w,&h); + img->GetPitches(strides); + img->GetReadPlanes(planes); + + uint32_t tmpHist[64]; + for (int i=0;i<64;i++) + tmpHist[i] = 0; + + w /= 2; + h /= 2; + int u,v; + for (int y=0; y 0.5) + return true; + + // adapt histogram + for (int i=0; i<64; i++) + { + hist[i] = nextHist[i]; + } + + return false; +} + +/** + \fn GUI_PrevSceneChange +*/ +void GUI_PrevSceneChange(void) +{ + if (playing) + return; + if (! avifileinfo) + return; + + admPreview::deferDisplay(true); + ADMImage *rdr; + + admPreview::samePicture(); + rdr=admPreview::getBuffer(); + if(rdr->refType!=ADM_HW_NONE) // need to convert it to plain YV12 + { + if(false==rdr->hwDownloadFromRef()) + { + ADM_warning("Cannot convert hw image to yv12\n"); + admPreview::deferDisplay(false); + return; + } + } + initSCeneChangeDetector(rdr); + + uint64_t startTime=admPreview::getCurrentPts(); + DIA_processingBase *work=createProcessing(QT_TRANSLATE_NOOP("scenechange", "Searching scene change.."),startTime); + + bool scFound=false; + while(1) + { + UI_purge(); + + if(false==admPreview::previousPicture()) + break; + rdr=admPreview::getBuffer(); + if(rdr->refType!=ADM_HW_NONE) // need to convert it to plain YV12 + { + if(false==rdr->hwDownloadFromRef()) + { + ADM_warning("Cannot convert hw image to yv12\n"); + break; + } + } + if(isSCeneChange(rdr)) + { + scFound = true; + break; + } + if(work->update(1,startTime-admPreview::getCurrentPts())) + break; + } + delete work; + if (!scFound) + admPreview::seekToTime(startTime); + admPreview::deferDisplay(false); + admPreview::samePicture(); + GUI_setCurrentFrameAndTime(); + return; +} + +/** + \fn GUI_NextSceneChange +*/ +void GUI_NextSceneChange(void) +{ + if (playing) + return; + if (! avifileinfo) + return; + + admPreview::deferDisplay(true); + ADMImage *rdr; + + admPreview::samePicture(); + rdr=admPreview::getBuffer(); + if(rdr->refType!=ADM_HW_NONE) // need to convert it to plain YV12 + { + if(false==rdr->hwDownloadFromRef()) + { + ADM_warning("Cannot convert hw image to yv12\n"); + admPreview::deferDisplay(false); + return; + } + } + initSCeneChangeDetector(rdr); + + uint64_t duration=video_body->getVideoDuration(); + uint64_t startTime=admPreview::getCurrentPts(); + DIA_processingBase *work=createProcessing(QT_TRANSLATE_NOOP("scenechange", "Searching scene change.."),duration-startTime); + + bool scFound=false; + while(1) + { + UI_purge(); + + if(false==admPreview::nextPicture()) + break; + rdr=admPreview::getBuffer(); + if(rdr->refType!=ADM_HW_NONE) // need to convert it to plain YV12 + { + if(false==rdr->hwDownloadFromRef()) + { + ADM_warning("Cannot convert hw image to yv12\n"); + break; + } + } + if(isSCeneChange(rdr)) + { + scFound = true; + break; + } + if(work->update(1,admPreview::getCurrentPts()-startTime)) + break; + } + delete work; + if (!scFound) + admPreview::seekToTime(startTime); + admPreview::deferDisplay(false); + admPreview::samePicture(); + GUI_setCurrentFrameAndTime(); + return; +} + +//EOF diff --git a/avidemux/qt4/ADM_userInterfaces/ADM_gui/Q_gui2.cpp b/avidemux/qt4/ADM_userInterfaces/ADM_gui/Q_gui2.cpp index 66c7c4ccb8..888bc05fb7 100644 --- a/avidemux/qt4/ADM_userInterfaces/ADM_gui/Q_gui2.cpp +++ b/avidemux/qt4/ADM_userInterfaces/ADM_gui/Q_gui2.cpp @@ -1426,7 +1426,7 @@ void MainWindow::updateActionShortcuts(void) q = findAction(&myMenuGo, ACT_NextCutPoint); if(q) q->setShortcut(Qt::SHIFT | (swpud ? Qt::Key_Down : Qt::Key_Up)); - + q = findAction(&myMenuGo, ACT_Back1Mn); if(q) q->setShortcut(Qt::CTRL | (swpud ? Qt::Key_Up : Qt::Key_Down)); @@ -1604,7 +1604,13 @@ void MainWindow::widgetsUpdateTooltips(void) tt += SHORTCUT(ACT_NextCutPoint,Go) ui.toolButtonNextCutPoint->setToolTip(tt); - // go to black frame tooltips are static, the actions don't have shortcuts + tt = QString(QT_TRANSLATE_NOOP("qgui2","Search previous black frame")); + tt += SHORTCUT(ACT_PrevBlackFrame,Go) + ui.toolButtonPreviousBlackFrame->setToolTip(tt); + + tt = QString(QT_TRANSLATE_NOOP("qgui2","Search next black frame")); + tt += SHORTCUT(ACT_NextBlackFrame,Go) + ui.toolButtonNextBlackFrame->setToolTip(tt); tt = QString(QT_TRANSLATE_NOOP("qgui2","Go to first frame")); tt += SHORTCUT(ACT_Begin,Go) @@ -1759,7 +1765,14 @@ bool MainWindow::eventFilter(QObject* watched, QEvent* event) switch (keyEvent->key()) { case Qt::Key_Left: - if ((keyEvent->modifiers() & Qt::ShiftModifier) && (keyEvent->modifiers() & Qt::ControlModifier)) + if (keyEvent->modifiers() & Qt::AltModifier) + { + if (keyEvent->modifiers() & Qt::ShiftModifier) + sendAction(ACT_PrevBlackFrame); + else + sendAction(ACT_PrevSceneChange); + } + else if ((keyEvent->modifiers() & Qt::ShiftModifier) && (keyEvent->modifiers() & Qt::ControlModifier)) sendAction(ACT_Back4Seconds); else if (keyEvent->modifiers() & Qt::ShiftModifier) sendAction(ACT_Back1Second); @@ -1770,7 +1783,14 @@ bool MainWindow::eventFilter(QObject* watched, QEvent* event) return true; case Qt::Key_Right: - if ((keyEvent->modifiers() & Qt::ShiftModifier) && (keyEvent->modifiers() & Qt::ControlModifier)) + if (keyEvent->modifiers() & Qt::AltModifier) + { + if (keyEvent->modifiers() & Qt::ShiftModifier) + sendAction(ACT_NextBlackFrame); + else + sendAction(ACT_NextSceneChange); + } + else if ((keyEvent->modifiers() & Qt::ShiftModifier) && (keyEvent->modifiers() & Qt::ControlModifier)) sendAction(ACT_Forward4Seconds); else if (keyEvent->modifiers() & Qt::ShiftModifier) sendAction(ACT_Forward1Second); diff --git a/avidemux/qt4/ADM_userInterfaces/ADM_gui/avidemux.qrc b/avidemux/qt4/ADM_userInterfaces/ADM_gui/avidemux.qrc index 4e3b214e91..09604556b5 100644 --- a/avidemux/qt4/ADM_userInterfaces/ADM_gui/avidemux.qrc +++ b/avidemux/qt4/ADM_userInterfaces/ADM_gui/avidemux.qrc @@ -17,6 +17,7 @@ pics/next.png pics/next_black.png pics/next_cut.png + pics/next_scd.png pics/player_end.png pics/player_fwd.png pics/player_play.png @@ -28,6 +29,7 @@ pics/play_filtered.png pics/prev_black.png pics/prev_cut.png + pics/prev_scd.png pics/preview_input.png pics/preview_output.png pics/preview_separate.png diff --git a/avidemux/qt4/ADM_userInterfaces/ADM_gui/avidemux_osx.qrc b/avidemux/qt4/ADM_userInterfaces/ADM_gui/avidemux_osx.qrc index 14af026910..3c91295b71 100644 --- a/avidemux/qt4/ADM_userInterfaces/ADM_gui/avidemux_osx.qrc +++ b/avidemux/qt4/ADM_userInterfaces/ADM_gui/avidemux_osx.qrc @@ -17,6 +17,7 @@ pics/next.png pics/next_black.png pics/next_cut.png + pics/next_scd.png pics/player_end.png pics/player_fwd.png pics/player_play.png @@ -28,6 +29,7 @@ pics/play_filtered.png pics/prev_black.png pics/prev_cut.png + pics/prev_scd.png pics/preview_input.png pics/preview_output.png pics/preview_separate.png diff --git a/avidemux/qt4/ADM_userInterfaces/ADM_gui/avidemux_win32.qrc b/avidemux/qt4/ADM_userInterfaces/ADM_gui/avidemux_win32.qrc index fd6b585a24..74a5fbd53b 100644 --- a/avidemux/qt4/ADM_userInterfaces/ADM_gui/avidemux_win32.qrc +++ b/avidemux/qt4/ADM_userInterfaces/ADM_gui/avidemux_win32.qrc @@ -17,6 +17,7 @@ pics/next.png pics/next_black.png pics/next_cut.png + pics/next_scd.png pics/player_end.png pics/player_fwd.png pics/player_play.png @@ -28,6 +29,7 @@ pics/play_filtered.png pics/prev_black.png pics/prev_cut.png + pics/prev_scd.png pics/preview_input.png pics/preview_output.png pics/preview_separate.png diff --git a/avidemux/qt4/ADM_userInterfaces/ADM_gui/avidemux_win32_custom_font.qrc b/avidemux/qt4/ADM_userInterfaces/ADM_gui/avidemux_win32_custom_font.qrc index 38502f826f..a0006348a8 100644 --- a/avidemux/qt4/ADM_userInterfaces/ADM_gui/avidemux_win32_custom_font.qrc +++ b/avidemux/qt4/ADM_userInterfaces/ADM_gui/avidemux_win32_custom_font.qrc @@ -17,6 +17,7 @@ pics/next.png pics/next_black.png pics/next_cut.png + pics/next_scd.png pics/player_end.png pics/player_fwd.png pics/player_play.png @@ -28,6 +29,7 @@ pics/play_filtered.png pics/prev_black.png pics/prev_cut.png + pics/prev_scd.png pics/preview_input.png pics/preview_output.png pics/preview_separate.png diff --git a/avidemux/qt4/ADM_userInterfaces/ADM_gui/pics/next_scd.png b/avidemux/qt4/ADM_userInterfaces/ADM_gui/pics/next_scd.png new file mode 100644 index 0000000000000000000000000000000000000000..c6170dfca4e681737d1b3ee591ce0ef0cb795081 GIT binary patch literal 1280 zcmV+b1^@bqP)U2IfE7(FxhXZP;*ZnxWQ=|b5S3RXg@m4XC96nGIZ`aldZ z#`q>dAB-jv-wg&IG=>oElga}xVqXyx5&{}Zpisa>8rt1ZqcjmkI+?nspe8ceH&=}(_Owm(}s}TSo8Q3Je86uel;63j{_PhYsqB~;k+YdFY z?&~#Ly3=a7B?|UT^kTy`7!|Uzru{GUGa5$KV7}^^Y@zDy5eoE z3BIa1jP7I!h9+=7-++m%L^d-m=du|)d*{sM%&k+$glAm=5Ij?uait@*^+yLTg-u!mF23_Ou0)p$WpeNz_5^g{sBCJkmFe5tqrWgRp|Ch6B=GfyZ}7@@ zCbpl9VOM`6x>EuzZEMVU$F75nu{dXpw=|^sdSmfs9uEg7S^@UECZGZ*MbCwlBYi<3;-Yhy!<>cv>WeiyI2(lK{z>wWZ-fV-i)2Q_oz^j zD7ax1yef-c2y*%S)Ufv}z^*GjOX<)!;CU{bg^6t7Rc1Jm%$6VDxD7iiHHDzpF{Fs6 zMEw=zW+@%ID!`nKv@^HHMBq%T0KDSVwE;Uf_I_*9Y-%#~6_qIl0Qj)Kgm!Z=&j!Qf zij`<$9?rtJRh%3=Pg3Sp01#gJ^3;_Rzb00Fd$_Z?2_cnL%M(?FkN%WFJOp4d<P+E3}WUf3te7)l9o29v_(~M|Hm@0IQLs!{T z)D&Q@;A3RGfV+cdu1{Y*dEB#$Lqs$OK-Ak#L^5BV9=@5+OhrmcXJ^@0bwiUZYN${- z2WJ40KyKc`U*knNGCENnz4XKHb0eqw7e%uGeBjwv69*90B8k26j$H?%slLsT#QIcY zW1|58g;LS6^AEFj=GItoa`3!co*9%J-0xuTnlF-|gY q1Fte80%w|}%o9-wfDJ&_3;YXK@o417r%=lP0000)t)+UBlbiY9Ilnn`=46K9zfEI|$C;uh7*`DdAnDm8oLM571K_L|$kzM8wcy@x zNB{ArjeWg=cz06u$AbVM?0nUpyZ@;2`1T!h=H_MLRIURM{|jbZO+_{z{9xn0lW(=Q zry}ibQNE$okM39*0Zm}M*o3K^L@t|=g3QTwfBI|s*Uvt3?fEOqaAjqt ziQOl@diKQ+Up~68g}r+qfUOAyK23ou0LP<-E1V$~R@kP&B>^T=k|B|~NVZjn8SppSXpnqEk08m=e z%C) zYy_rlz~W6jnCRPH{QH+AXNsN(#J445AqLx#Sg0&^%;j4L8h~o?J?%vwj07wGfJJh~rC)Xw;$XAUg z?aCNbe=NWiJ)|y+W=%u3L{OG0F^ZN(z#A{D&a|zzc-H(#vZ%ke;$AZQ1&iVDB zssd;naGW}73sX7Ism^jDnX5d$eFt_KwqH#DuKf|YQx8c;+S%84L zM@Wy)V|3v2AM)w%J`qApE#DPXD?Oa>1n=?3x;r~!8Z&$hfCQ0*t`K}0!KW^MIVb#f zw*sF^U~n-yRg_~lz8@;2FJADR+C2c}#w7%jbCt~SP}SA9%TP~O$j}fCsn9hJU1e)r zQ-DIrMS7xydxMvTGB?hhacuJz5fuQ4Ct!exWU-PN{-c1vbMqGdoG@j2bgD9X_59C;^u-HH&>R34c>2@C0R%N8dN9(t|5z~5x7~