Commit e52ea59c authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Restore timeline thumbs

parent 2aaee52c
......@@ -25,6 +25,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "projectsubclip.h"
#include "bin.h"
#include "timecode.h"
#include "doc/kthumb.h"
#include "kdenlivesettings.h"
#include "project/projectcommands.h"
#include "mltcontroller/clipcontroller.h"
#include "mltcontroller/clippropertiescontroller.h"
......@@ -43,6 +45,7 @@ ProjectClip::ProjectClip(const QString &id, QIcon thumb, ClipController *control
, m_controller(controller)
, audioFrameCache()
, m_audioThumbCreated(false)
, m_gpuProducer(NULL)
{
m_clipStatus = StatusReady;
m_thumbnail = thumb;
......@@ -58,6 +61,7 @@ ProjectClip::ProjectClip(const QDomElement& description, QIcon thumb, ProjectFol
, m_controller(NULL)
, audioFrameCache()
, m_audioThumbCreated(false)
, m_gpuProducer(NULL)
{
Q_ASSERT(description.hasAttribute("id"));
m_clipStatus = StatusWaiting;
......@@ -609,3 +613,36 @@ QVariant ProjectClip::data(DataType type) const
}
return AbstractProjectItem::data(type);
}
void ProjectClip::slotExtractImage(QList <int> frames)
{
Mlt::Producer *prod = producer();
if (prod == NULL) return;
// Check if we are using GPU accel, then we need to use alternate producer
if (KdenliveSettings::gpu_accel()) {
if (m_gpuProducer == NULL) {
QString service = prod->get("mlt_service");
m_gpuProducer = new Mlt::Producer(*prod->profile(), service.toUtf8().constData(), prod->get("resource"));
Mlt::Filter scaler(*prod->profile(), "swscale");
Mlt::Filter converter(*prod->profile(), "avcolor_space");
m_gpuProducer->attach(scaler);
m_gpuProducer->attach(converter);
}
prod = m_gpuProducer;
}
int imageWidth = (int)((double) 150 * prod->profile()->width() / prod->profile()->height() + 0.5);
int fullWidth = (int)((double) 150 * prod->profile()->dar() + 0.5);
for (int i = 0; i < frames.count(); i++) {
int pos = frames.at(i);
int max = prod->get_out();
if (pos >= max) pos = max - 1;
prod->seek(pos);
Mlt::Frame *frame = prod->get_frame();
if (frame && frame->is_valid()) {
QImage img = KThumb::getFrame(frame, imageWidth, fullWidth, 150);
emit thumbReady(frames.at(i), img);
}
delete frame;
}
}
......@@ -195,6 +195,7 @@ public:
public slots:
//TODO
void updateAudioThumbnail(const audioByteArray& data);
void slotExtractImage(QList <int> frames);
protected:
bool m_hasLimitedDuration;
......@@ -204,6 +205,7 @@ private:
QList <int> m_markers;
/** @brief The Clip controller for this clip. */
ClipController *m_controller;
Mlt::Producer *m_gpuProducer;
/** @brief Generate and store file hash if not available. */
const QString getFileHash() const;
bool m_audioThumbCreated;
......@@ -214,6 +216,7 @@ signals:
void gotAudioData();
void refreshPropertiesPanel();
void refreshClipDisplay();
void thumbReady(int, QImage);
};
#endif
......@@ -184,9 +184,14 @@ Monitor::Monitor(Kdenlive::MonitorId id, MonitorManager *manager, QWidget *paren
QIcon icon;
if (KdenliveSettings::volume() == 0) icon = QIcon::fromTheme("audio-volume-muted");
else icon = QIcon::fromTheme("audio-volume-medium");
m_volumeWidget = m_toolbar->widgetForAction(m_toolbar->addAction(icon, i18n("Audio volume"), this, SLOT(slotShowVolume())));
if (id == Kdenlive::ClipMonitor) {
m_toolbar->addSeparator();
m_effectCompare = m_toolbar->addAction(QIcon::fromTheme("view-split-left-right"), i18n("Compare effect"));
m_effectCompare->setCheckable(true);
connect(m_effectCompare, SIGNAL(toggled(bool)), this, SLOT(slotSwitchCompare(bool)));
}
// we need to show / hide the popup once so that it's geometry can be calculated in slotShowVolume
m_volumePopup->show();
m_volumePopup->hide();
......@@ -285,10 +290,6 @@ void Monitor::setupMenu(QMenu *goMenu, QAction *playZone, QAction *loopZone, QMe
} else {
QAction *setThumbFrame = m_contextMenu->addAction(QIcon::fromTheme("document-new"), i18n("Set current image as thumbnail"), this, SLOT(slotSetThumbFrame()));
m_configMenu->addAction(setThumbFrame);
m_contextMenu->addSeparator();
m_effectCompare = m_contextMenu->addAction(QIcon::fromTheme("view-split-left-right"), i18n("Compare effect"));
m_effectCompare->setCheckable(true);
connect(m_effectCompare, SIGNAL(toggled(bool)), this, SLOT(slotSwitchCompare(bool)));
}
QAction *overlayAudio = m_contextMenu->addAction(QIcon(), i18n("Overlay audio waveform"));
......@@ -1351,6 +1352,9 @@ void Monitor::slotSwitchCompare(bool enable)
warningMessage(i18n("Select a clip in project bin to compare effect"));
return;
}
if (!m_controller->hasEffects()) {
warningMessage(i18n("Clip has no effects"));
}
int pos = position().frames(m_monitorManager->timecode().fps());
if (enable) {
m_splitEffect = new Mlt::Filter(*profile(), "frei0r.scale0tilt");
......
......@@ -2126,7 +2126,6 @@ int Render::mltInsertClip(ItemInfo info, const QString &clipId, bool overwrite,
return 0;
}
Mlt::Producer *Render::getTrackProducer(const QString &id, int track, bool audioOnly, bool videoOnly)
{
Mlt::Service service(m_mltProducer->parent().get_service());
......
......@@ -418,6 +418,7 @@ private slots:
/** @brief Update all track producers to master's effect */
void slotUpdateTrackProducers(const QString &clipId);
signals:
/** @brief The renderer received a reply to a getFileProperties request. */
......@@ -425,7 +426,7 @@ signals:
/** @brief The renderer received a reply to a getImage request. */
void replyGetImage(const QString &, const QImage &);
/** @brief The renderer stopped, either playing or rendering. */
void stopped();
......
......@@ -32,7 +32,7 @@
#include <QDebug>
#include <QIcon>
#include <QtConcurrent>
#include <QPainter>
#include <QTimer>
#include <QStyleOptionGraphicsItem>
......@@ -97,17 +97,17 @@ ClipItem::ClipItem(ProjectClip *clip, const ItemInfo& info, double fps, double s
connect(m_binClip, SIGNAL(refreshClipDisplay()), this, SLOT(slotRefreshClip()));
if (m_clipType == AV || m_clipType == Video || m_clipType == SlideShow || m_clipType == Playlist ) {
m_baseColor = QColor(141, 166, 215);
//TODO:
if (false /*&& !m_clip->isPlaceHolder()*/) {
if (m_binClip->isReady()) {
m_hasThumbs = true;
m_startThumbTimer.setSingleShot(true);
/*connect(&m_startThumbTimer, SIGNAL(timeout()), this, SLOT(slotGetStartThumb()));
connect(&m_startThumbTimer, SIGNAL(timeout()), this, SLOT(slotGetStartThumb()));
m_endThumbTimer.setSingleShot(true);
connect(&m_endThumbTimer, SIGNAL(timeout()), this, SLOT(slotGetEndThumb()));
connect(m_clip->thumbProducer(), SIGNAL(thumbReady(int,QImage)), this, SLOT(slotThumbReady(int,QImage)));
connect(m_clip->thumbProducer(), SIGNAL(thumbsCached()), this, SLOT(slotRefreshClip()));
connect(m_clip, SIGNAL(gotAudioData()), this, SLOT(slotGotAudioData()));
if (generateThumbs) QTimer::singleShot(200, this, SLOT(slotFetchThumbs()));*/
//connect(m_clip->thumbProducer(), SIGNAL(thumbReady(int,QImage)), this, SLOT(slotThumbReady(int,QImage)));
connect(m_binClip, SIGNAL(thumbReady(int,QImage)), this, SLOT(slotThumbReady(int,QImage)));
//connect(m_clip->thumbProducer(), SIGNAL(thumbsCached()), this, SLOT(slotRefreshClip()));
//connect(m_clip, SIGNAL(gotAudioData()), this, SLOT(slotGotAudioData()));
if (generateThumbs) QTimer::singleShot(200, this, SLOT(slotFetchThumbs()));
}
} else if (m_clipType == Color) {
......@@ -504,7 +504,9 @@ void ClipItem::slotFetchThumbs()
}
//TODO
//if (!frames.isEmpty()) m_binClip->slotExtractImage(frames);
if (!frames.isEmpty()) {
QtConcurrent::run(m_binClip, &ProjectClip::slotExtractImage, frames);
}
}
void ClipItem::stopThumbs()
......@@ -517,6 +519,7 @@ void ClipItem::stopThumbs()
void ClipItem::slotGetStartThumb()
{
m_startThumbRequested = true;
QtConcurrent::run(m_binClip, &ProjectClip::slotExtractImage, QList<int>() << (int)m_speedIndependantInfo.cropStart.frames(m_fps));
//TODO
//m_clip->slotExtractImage(QList<int>() << (int)m_speedIndependantInfo.cropStart.frames(m_fps));
}
......@@ -524,6 +527,7 @@ void ClipItem::slotGetStartThumb()
void ClipItem::slotGetEndThumb()
{
m_endThumbRequested = true;
QtConcurrent::run(m_binClip, &ProjectClip::slotExtractImage, QList<int>() << (int)(m_speedIndependantInfo.cropStart + m_speedIndependantInfo.cropDuration).frames(m_fps) - 1);
//TODO
//m_clip->slotExtractImage(QList<int>() << (int)(m_speedIndependantInfo.cropStart + m_speedIndependantInfo.cropDuration).frames(m_fps) - 1);
}
......@@ -554,10 +558,10 @@ void ClipItem::slotSetEndThumb(const QImage &img)
void ClipItem::slotThumbReady(int frame, const QImage &img)
{
if (scene() == NULL) return;
QRectF r = boundingRect();
QPixmap pix = QPixmap::fromImage(img);
double width = pix.width() / projectScene()->scale().x();
if (m_startThumbRequested && frame == m_speedIndependantInfo.cropStart.frames(m_fps)) {
QRectF r = boundingRect();
QPixmap pix = QPixmap::fromImage(img);
double width = pix.width() / projectScene()->scale().x();
m_startPix = pix;
m_startThumbRequested = false;
update(r.left(), r.top(), width, pix.height());
......@@ -565,6 +569,9 @@ void ClipItem::slotThumbReady(int frame, const QImage &img)
update(r.right() - width, r.top(), width, pix.height());
}
} else if (m_endThumbRequested && frame == (m_speedIndependantInfo.cropStart + m_speedIndependantInfo.cropDuration).frames(m_fps) - 1) {
QRectF r = boundingRect();
QPixmap pix = QPixmap::fromImage(img);
double width = pix.width() / projectScene()->scale().x();
m_endPix = pix;
m_endThumbRequested = false;
update(r.right() - width, r.top(), width, pix.height());
......@@ -709,6 +716,7 @@ void ClipItem::paint(QPainter *painter,
thumbRect.moveTopLeft(mapped.topLeft());
painter->drawPixmap(thumbRect, m_startPix, m_startPix.rect());
}
} else {
// if we are in full zoom, paint thumbnail for every frame
//TODO
......
......@@ -1701,7 +1701,6 @@ bool CustomTrackView::insertDropClips(const QMimeData *data, const QPoint &pos)
m_selectionGroup->setSelected(true);
} else if (data->hasFormat("kdenlive/producerslist")) {
QStringList ids = QString(data->data("kdenlive/producerslist")).split(';');
QList <GenTime> offsetList;
QList <ItemInfo> infoList;
GenTime start = GenTime((int)(framePos.x() + 0.5), m_document->fps());
......@@ -1773,7 +1772,7 @@ bool CustomTrackView::insertDropClips(const QMimeData *data, const QPoint &pos)
info.track = 0;
start += info.cropDuration;
offsetList.append(start);
ClipItem *item = new ClipItem(clip, info, m_document->fps(), 1.0, 1, getFrameWidth(), false);
ClipItem *item = new ClipItem(clip, info, m_document->fps(), 1.0, 1, getFrameWidth(), true);
if (ids.size() > 1) m_selectionGroup->addItem(item);
else m_dragItem = item;
item->setSelected(true);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment