From f10ecf3c4538b19705753e118c3bc8c4702d4747 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Mardelle Date: Sat, 21 Jun 2008 00:35:14 +0000 Subject: [PATCH] more work on keyframe effects and thumbnail fixes svn path=/branches/KDE4/; revision=2256 --- effects/volume.xml | 2 +- src/abstractclipitem.cpp | 42 ++++++++++++++++------------------ src/abstractclipitem.h | 10 ++++---- src/clipitem.cpp | 23 ++++++++----------- src/customtrackview.cpp | 6 +++-- src/kthumb.cpp | 39 ++++++++++++++++---------------- src/kthumb.h | 2 +- src/projectlist.cpp | 4 ++-- src/renderer.cpp | 49 +++++++++++++++++++--------------------- src/renderer.h | 2 +- 10 files changed, 86 insertions(+), 93 deletions(-) diff --git a/effects/volume.xml b/effects/volume.xml index 207866dc..0a8ca002 100644 --- a/effects/volume.xml +++ b/effects/volume.xml @@ -4,7 +4,7 @@ Adjust audio volume with keyframes Dan Dennedy - + Gain diff --git a/src/abstractclipitem.cpp b/src/abstractclipitem.cpp index c071c0a8..cdd197de 100644 --- a/src/abstractclipitem.cpp +++ b/src/abstractclipitem.cpp @@ -212,23 +212,23 @@ QPainterPath AbstractClipItem::lowerRectPart(QRectF br) { void AbstractClipItem::drawKeyFrames(QPainter *painter, QRectF exposedRect) { QRectF br = rect(); - double maxw = br.width() / 100.0; + double maxw = br.width() / m_cropDuration.frames(m_fps); double maxh = br.height() / 100.0; if (m_keyframes.count() > 1) { - QMap::const_iterator i = m_keyframes.constBegin(); + QMap::const_iterator i = m_keyframes.constBegin(); double x1; double y1; double x2; double y2; QColor color(Qt::blue); - x1 = br.x() + maxw * i.key(); + x1 = br.x() + maxw * (i.key() - m_cropStart.frames(m_fps)); y1 = br.bottom() - i.value() * maxh; while (i != m_keyframes.constEnd()) { if (i.key() == m_selectedKeyframe) color = QColor(Qt::red); else color = QColor(Qt::blue); ++i; if (i == m_keyframes.constEnd()) break; - x2 = br.x() + maxw * i.key(); + x2 = br.x() + maxw * (i.key() - m_cropStart.frames(m_fps)); y2 = br.bottom() - i.value() * maxh; QLineF l(x1, y1, x2, y2); painter->drawLine(l); @@ -244,14 +244,14 @@ void AbstractClipItem::drawKeyFrames(QPainter *painter, QRectF exposedRect) { int AbstractClipItem::mouseOverKeyFrames(QPointF pos) { QRectF br = rect(); - double maxw = br.width() / 100.0; + double maxw = br.width() / m_cropDuration.frames(m_fps); double maxh = br.height() / 100.0; if (m_keyframes.count() > 1) { - QMap::const_iterator i = m_keyframes.constBegin(); + QMap::const_iterator i = m_keyframes.constBegin(); double x1; double y1; while (i != m_keyframes.constEnd()) { - x1 = br.x() + maxw * i.key(); + x1 = br.x() + maxw * (i.key() - m_cropStart.frames(m_fps)); y1 = br.bottom() - i.value() * maxh; if (qAbs(pos.x() - x1) < 6 && qAbs(pos.y() - y1) < 6) { setToolTip("[" + QString::number(i.key()) + "x" + QString::number(i.value()) + "]"); @@ -267,28 +267,27 @@ int AbstractClipItem::mouseOverKeyFrames(QPointF pos) { void AbstractClipItem::updateSelectedKeyFrame() { if (m_editedKeyframe == -1) return; QRectF br = rect(); - double maxw = br.width() / 100.0; + double maxw = br.width() / m_cropDuration.frames(m_fps); double maxh = br.height() / 100.0; - update(br.x() + maxw * m_selectedKeyframe - 3, br.bottom() - m_keyframes[m_selectedKeyframe] * maxh - 3, 12, 12); + update(br.x() + maxw * (m_selectedKeyframe - m_cropStart.frames(m_fps)) - 3, br.bottom() - m_keyframes[m_selectedKeyframe] * maxh - 3, 12, 12); m_selectedKeyframe = m_editedKeyframe; - update(br.x() + maxw * m_selectedKeyframe - 3, br.bottom() - m_keyframes[m_selectedKeyframe] * maxh - 3, 12, 12); + update(br.x() + maxw * (m_selectedKeyframe - m_cropStart.frames(m_fps)) - 3, br.bottom() - m_keyframes[m_selectedKeyframe] * maxh - 3, 12, 12); } -void AbstractClipItem::updateKeyFramePos(const QPoint pos) { +void AbstractClipItem::updateKeyFramePos(const GenTime pos, const int value) { if (m_selectedKeyframe == -1) return; QRectF br = rect(); - double maxw = br.width() / 100.0; double maxh = br.height() / 100.0; - int newval = (int)((br.bottom() - pos.y()) / maxh); - int newpos = (int)((pos.x() - br.x()) / maxw); - if (newval < -50 && m_selectedKeyframe != 0 && m_selectedKeyframe != 100) { + double newval = (br.bottom() - value) / maxh; + int newpos = (int) pos.frames(m_fps); + if (newval < -50 && m_selectedKeyframe != m_cropStart.frames(m_fps) && m_selectedKeyframe != (m_cropStart + m_cropDuration).frames(m_fps)) { // remove kexframe if it is dragged outside m_keyframes.remove(m_selectedKeyframe); m_selectedKeyframe = -1; update(); return; } - if (newval > 150 && m_selectedKeyframe != 0 && m_selectedKeyframe != 100) { + if (newval > 150 && m_selectedKeyframe != m_cropStart.frames(m_fps) && m_selectedKeyframe != (m_cropStart + m_cropDuration).frames(m_fps)) { // remove kexframe if it is dragged outside m_keyframes.remove(m_selectedKeyframe); m_selectedKeyframe = -1; @@ -297,7 +296,7 @@ void AbstractClipItem::updateKeyFramePos(const QPoint pos) { } if (newval < 0) newval = 0; else if (newval > 100) newval = 100; - if (m_selectedKeyframe == 0 || m_selectedKeyframe == 100) { + if (m_selectedKeyframe == m_cropStart.frames(m_fps) || m_selectedKeyframe == (m_cropStart + m_cropDuration).frames(m_fps)) { // start and end keyframes should stay in place m_keyframes[m_selectedKeyframe] = newval; } else { @@ -308,18 +307,17 @@ void AbstractClipItem::updateKeyFramePos(const QPoint pos) { update(); } -void AbstractClipItem::addKeyFrame(const QPoint pos) { +void AbstractClipItem::addKeyFrame(const GenTime pos, const int value) { QRectF br = rect(); - double maxw = br.width() / 100.0; double maxh = br.height() / 100.0; - int newval = (int)((br.bottom() - pos.y()) / maxh); - int newpos = (int)((pos.x() - br.x()) / maxw); + double newval = (br.bottom() - value) / maxh; + int newpos = (int) pos.frames(m_fps) ; m_keyframes[newpos] = newval; m_selectedKeyframe = newpos; update(); } -bool AbstractClipItem::hasKeyFrames() { +bool AbstractClipItem::hasKeyFrames() const { return !m_keyframes.isEmpty(); } diff --git a/src/abstractclipitem.h b/src/abstractclipitem.h index cb055483..6c35b726 100644 --- a/src/abstractclipitem.h +++ b/src/abstractclipitem.h @@ -30,9 +30,9 @@ class AbstractClipItem : public QObject , public QGraphicsRectItem { public: AbstractClipItem(const ItemInfo info, const QRectF& rect, double fps); void updateSelectedKeyFrame(); - void updateKeyFramePos(const QPoint pos); - void addKeyFrame(const QPoint pos); - bool hasKeyFrames(); + void updateKeyFramePos(const GenTime pos, const int value); + void addKeyFrame(const GenTime pos, const int value); + bool hasKeyFrames() const; virtual OPERATIONTYPE operationMode(QPointF pos, double scale) = 0; virtual GenTime startPos() const ; @@ -41,7 +41,7 @@ public: virtual int track() const ; virtual void moveTo(int x, double scale, int offset, int newTrack); virtual GenTime cropStart() const ; - virtual void resizeStart(int posx, double scale); + virtual void resizeStart(int posx, double scale); virtual void resizeEnd(int posx, double scale); virtual GenTime duration() const; virtual double fps() const; @@ -56,7 +56,7 @@ protected: GenTime m_cropDuration; GenTime m_startPos; GenTime m_maxDuration; - QMap m_keyframes; + QMap m_keyframes; double m_fps; QPainterPath upperRectPart(QRectF); QPainterPath lowerRectPart(QRectF); diff --git a/src/clipitem.cpp b/src/clipitem.cpp index 96e489cd..958af22d 100644 --- a/src/clipitem.cpp +++ b/src/clipitem.cpp @@ -104,6 +104,7 @@ int ClipItem::selectedEffectIndex() const { return m_selectedEffect; } + void ClipItem::setSelectedEffect(int ix) { //if (ix == m_selectedEffect) return; m_selectedEffect = ix; @@ -122,19 +123,15 @@ void ClipItem::setSelectedEffect(int ix) { // Effect has a keyframe type parameter, we need to set the values if (e.attribute("keyframes").isEmpty()) { // no keyframes defined, set up 2 keyframes (start and end) with default value. - m_keyframes[0] = 100 * def / (max - min); - m_keyframes[100] = 100 * def / (max - min); + m_keyframes[m_cropStart.frames(m_fps)] = 100 * def / (max - min); + m_keyframes[(m_cropStart + m_cropDuration).frames(m_fps)] = 100 * def / (max - min); } else { // parse keyframes - QStringList keyframes = e.attribute("keyframes").split(";"); + QStringList keyframes = e.attribute("keyframes").split(";", QString::SkipEmptyParts); foreach(QString str, keyframes) { - if (!str.isEmpty()) { - int pos = str.section(":", 0, 0).toInt(); - int val = str.section(":", 1, 1).toInt(); - /*int frame = (int) (pos * 100 / m_cropDuration.frames(m_fps)); - int value = (int) (((val * factor) - min) * 100 * factor / (max - min));*/ - m_keyframes[pos] = val; - } + int pos = str.section(":", 0, 0).toInt(); + double val = str.section(":", 1, 1).toDouble(); + m_keyframes[pos] = val; } } update(); @@ -162,7 +159,7 @@ void ClipItem::updateKeyframeEffect() { QString keyframes; if (m_keyframes.count() > 1) { - QMap::const_iterator i = m_keyframes.constBegin(); + QMap::const_iterator i = m_keyframes.constBegin(); double x1; double y1; while (i != m_keyframes.constEnd()) { @@ -801,8 +798,8 @@ QMap ClipItem::getEffectArgs(QDomElement effect) { effectParams["max"] = e.attribute("max"); effectParams["min"] = e.attribute("min"); effectParams["factor"] = e.attribute("factor"); - effectParams["starttag"] = e.attribute("starttag"); - effectParams["endtag"] = e.attribute("endtag"); + effectParams["starttag"] = e.attribute("starttag", "start"); + effectParams["endtag"] = e.attribute("endtag", "end"); } else if (e.attribute("namedesc").contains(";")) { QString format = e.attribute("format"); QStringList separators = format.split("%d", QString::SkipEmptyParts); diff --git a/src/customtrackview.cpp b/src/customtrackview.cpp index 0de318f2..19e94e7f 100644 --- a/src/customtrackview.cpp +++ b/src/customtrackview.cpp @@ -199,7 +199,8 @@ void CustomTrackView::mouseMoveEvent(QMouseEvent * event) { int pos = (int)(mapToScene(event->pos()).x() / m_scale); ((ClipItem*) m_dragItem)->setFadeOut((int)(m_dragItem->endPos().frames(m_document->fps()) - pos), m_scale); } else if (m_operationMode == KEYFRAME) { - m_dragItem->updateKeyFramePos(event->pos()); + GenTime keyFramePos = GenTime((int)(mapToScene(event->pos()).x() / m_scale), m_document->fps()) - m_dragItem->startPos() + m_dragItem->cropStart(); + m_dragItem->updateKeyFramePos(keyFramePos, mapToScene(event->pos()).toPoint().y()); } if (m_animation) delete m_animation; @@ -536,7 +537,8 @@ void CustomTrackView::mousePressEvent(QMouseEvent * event) { void CustomTrackView::mouseDoubleClickEvent(QMouseEvent *event) { if (m_dragItem && m_dragItem->hasKeyFrames()) { - m_dragItem->addKeyFrame(event->pos()); + GenTime keyFramePos = GenTime((int)(mapToScene(event->pos()).x() / m_scale), m_document->fps()) - m_dragItem->startPos() + m_dragItem->cropStart(); + m_dragItem->addKeyFrame(keyFramePos, mapToScene(event->pos()).toPoint().y()); ClipItem * item = (ClipItem *) m_dragItem; item->updateKeyframeEffect(); updateEffect(m_tracksList.count() - item->track(), item->startPos(), item->selectedEffect()); diff --git a/src/kthumb.cpp b/src/kthumb.cpp index d1da8630..88ab7b43 100644 --- a/src/kthumb.cpp +++ b/src/kthumb.cpp @@ -162,7 +162,7 @@ void KThumb::extractImage(int frame, int frame2) { Mlt::Producer producer(*m_profile, "westley-xml", tmp); delete[] tmp; - int twidth = (int)(KdenliveSettings::trackheight() * KdenliveSettings::project_display_ratio()); + int twidth = (int)(KdenliveSettings::trackheight() * m_profile->dar()); if (producer.is_blank()) { QPixmap pix(twidth, KdenliveSettings::trackheight()); pix.fill(Qt::black); @@ -170,14 +170,13 @@ void KThumb::extractImage(int frame, int frame2) { return; } if (frame != -1) { - QPixmap pix = getFrame(&producer, frame, twidth, KdenliveSettings::trackheight()); + QPixmap pix = getFrame(producer, frame, twidth, KdenliveSettings::trackheight()); emit thumbReady(frame, pix); } if (frame2 != -1) { - QPixmap pix = getFrame(&producer, frame2, twidth , KdenliveSettings::trackheight()); + QPixmap pix = getFrame(producer, frame2, twidth , KdenliveSettings::trackheight()); emit thumbReady(frame2, pix); } - } //static @@ -196,7 +195,7 @@ QPixmap KThumb::getImage(KUrl url, int frame, int width, int height) { pix.fill(Qt::black); return pix; } - return getFrame(&producer, frame, width, height); + return getFrame(producer, frame, width, height); } //static @@ -217,35 +216,35 @@ QPixmap KThumb::getImage(QDomElement xml, int frame, int width, int height) { pix.fill(Qt::black); return pix; } - return getFrame(&producer, frame, width, height); + return getFrame(producer, frame, width, height); } //static -QPixmap KThumb::getFrame(Mlt::Producer* producer, int framepos, int width, int height) { +QPixmap KThumb::getFrame(Mlt::Producer producer, int framepos, int width, int height) { if (framepos > 0) - producer->seek(framepos); - Mlt::Frame *frame = producer->get_frame(); + producer.seek(framepos); + Mlt::Frame *frame = producer.get_frame(); mlt_image_format format = mlt_image_yuv422; - uint8_t* data; int frame_width = 0; int frame_height = 0; - //frame->set("rescale.interp", "nearest"); - frame->set("normalised_height", height); - frame->set("normalised_width", width); - mlt_frame_get_image(frame->get_frame(), &data, &format, &frame_width, &frame_height, 0); + frame->set("normalised_height", height); + frame->set("normalised_width", width); QPixmap pix(width, height); + + uint8_t *data = frame->get_image(format, frame_width, frame_height, 0); uint8_t *new_image = (uint8_t *)mlt_pool_alloc(frame_width * (frame_height + 1) * 4); mlt_convert_yuv422_to_rgb24a((uint8_t *)data, new_image, frame_width * frame_height); QImage image((uchar *)new_image, frame_width, frame_height, QImage::Format_ARGB32); if (!image.isNull()) { - //QImage scale = image.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation).rgbSwapped(); - image = image.rgbSwapped(); - pix = pix.fromImage(image); - } else pix.fill(Qt::black); - mlt_pool_release(new_image); - if (frame) delete frame; + pix = pix.fromImage(image.rgbSwapped()); + } else + pix.fill(Qt::black); + + mlt_pool_release(new_image); + delete frame; + return pix; } /* diff --git a/src/kthumb.h b/src/kthumb.h index 1c4628c2..ffbd745d 100644 --- a/src/kthumb.h +++ b/src/kthumb.h @@ -86,7 +86,7 @@ public slots: void removeAudioThumb(); void getAudioThumbs(int channel, double frame, double frameLength, int arrayWidth); static QPixmap getImage(KUrl url, int frame, int width, int height); - static QPixmap getFrame(Mlt::Producer* producer, int framepos, int width, int height); + static QPixmap getFrame(Mlt::Producer producer, int framepos, int width, int height); protected: virtual void customEvent(QEvent * event); diff --git a/src/projectlist.cpp b/src/projectlist.cpp index ea95c5ae..60eae55f 100644 --- a/src/projectlist.cpp +++ b/src/projectlist.cpp @@ -444,8 +444,8 @@ void ProjectList::slotRefreshClipThumbnail(int clipId) { void ProjectList::slotRefreshClipThumbnail(ProjectItem *item) { if (item) { - int height = 50; - int width = (int)(height * m_render->dar()); + int height = 50; + int width = (int)(height * m_render->dar()); QPixmap pix = KThumb::getImage(item->toXml(), item->referencedClip()->getProjectThumbFrame(), width, height); //QPixmap pix = KThumb::getFrame(item->toXml()), 0, width, height); item->setIcon(0, pix); diff --git a/src/renderer.cpp b/src/renderer.cpp index 343092fd..b9346a67 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -379,7 +379,7 @@ bool Render::isValid(KUrl url) { } const double Render::dar() const { - return m_mltProfile->dar(); + return m_mltProfile->dar(); } void Render::getFileProperties(const QDomElement &xml, int clipId) { @@ -398,10 +398,6 @@ void Render::getFileProperties(const QDomElement &xml, int clipId) { Mlt::Producer producer(*m_mltProfile, "westley-xml", tmp); delete[] tmp; -/* Mlt::Filter filter(*m_mltProfile, "rescale"); - producer.attach(filter);*/ - //mlt_properties_set_int( MLT_FILTER_PROPERTIES( filter ), "_fezzik", 1 ); - if (producer.is_blank()) { return; } @@ -434,24 +430,24 @@ void Render::getFileProperties(const QDomElement &xml, int clipId) { filePropertyMap["type"] = "video"; mlt_image_format format = mlt_image_yuv422; - uint8_t* data; int frame_width = 0; int frame_height = 0; - //frame->set("rescale.interp", "hyper"); - frame->set("normalised_height", height); - frame->set("normalised_width", width); - mlt_frame_get_image(frame->get_frame(), &data, &format, &frame_width, &frame_height, 0); - //kDebug()<<"/// GOT TUMB, SIZE: "<set("rescale.interp", "hyper"); + frame->set("normalised_height", height); + frame->set("normalised_width", width); QPixmap pix(width, height); + + uint8_t *data = frame->get_image(format, frame_width, frame_height, 0); uint8_t *new_image = (uint8_t *)mlt_pool_alloc(frame_width * (frame_height + 1) * 4); mlt_convert_yuv422_to_rgb24a((uint8_t *)data, new_image, frame_width * frame_height); QImage image((uchar *)new_image, frame_width, frame_height, QImage::Format_ARGB32); if (!image.isNull()) { - image = image.rgbSwapped();// = image.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation).rgbSwapped(); - pix = pix.fromImage(image); - } else pix.fill(Qt::black); - mlt_pool_release(new_image); + pix = pix.fromImage(image.rgbSwapped()); + } else + pix.fill(Qt::black); + + mlt_pool_release(new_image); emit replyGetImage(clipId, 0, pix, width, height); } else if (frame->get_int("test_audio") == 0) { @@ -1150,16 +1146,17 @@ void Render::mltAddEffect(int track, GenTime position, QMap a char *filterId = decodedString(args.value("id")); QMap::Iterator it; QString kfr = args.value("keyframes"); - + if (!kfr.isEmpty()) { - QStringList keyFrames = kfr.split(";"); + QStringList keyFrames = kfr.split(";", QString::SkipEmptyParts); kDebug() << "// ADDING KEYFRAME EFFECT: " << args.value("keyframes"); char *starttag = decodedString(args.value("starttag")); char *endtag = decodedString(args.value("endtag", "end")); + kDebug() << "// ADDING KEYFRAME TAGS: " << starttag << ", " << endtag; int duration = clip->get_playtime(); int max = args.value("max").toInt(); int min = args.value("min").toInt(); - int factor = args.value("factor").toInt(); + int factor = args.value("factor", "1").toInt(); args.remove("starttag"); args.remove("endtag"); args.remove("keyframes"); @@ -1167,10 +1164,10 @@ void Render::mltAddEffect(int track, GenTime position, QMap a Mlt::Filter *filter = new Mlt::Filter(*m_mltProfile, filterTag); filter->set("kdenlive_id", filterId); int x1 = keyFrames.at(i).section(":", 0, 0).toInt(); - int y1 = keyFrames.at(i).section(":", 1, 1).toInt(); + double y1 = keyFrames.at(i).section(":", 1, 1).toDouble(); int x2 = keyFrames.at(i + 1).section(":", 0, 0).toInt(); - int y2 = keyFrames.at(i + 1).section(":", 1, 1).toInt(); - + double y2 = keyFrames.at(i + 1).section(":", 1, 1).toDouble(); + if (x2 == -1) x2 = duration; for (it = args.begin(); it != args.end(); ++it) { char *name = decodedString(it.key()); char *value = decodedString(it.value()); @@ -1179,11 +1176,11 @@ void Render::mltAddEffect(int track, GenTime position, QMap a delete[] value; } - filter->set("in", duration / 100 * x1); - filter->set("out", duration / 100 * x2); - filter->set(starttag, (min + y1 * 100 / (max - min)) / factor); - filter->set(endtag, (min + y2 * 100 / (max - min)) / factor); - kDebug() << "// SETTING FILT VALS: " << duration / 100 * x1 << " to " << duration / 100 * x2 << ", STAT:" << (min + y1 * 100 / (max - min)) / factor << "end: " << (min + y2 * 100 / (max - min)) / factor; + filter->set("in", x1); + filter->set("out", x2); + //kDebug() << "// ADDING KEYFRAME vals: " << min<<" / "<set(starttag, QString::number((min + y1 * (max - min) / 100.0) / factor).toUtf8().data()); + filter->set(endtag, QString::number((min + y2 * (max - min) / 100.0) / factor).toUtf8().data()); clipService.attach(*filter); } diff --git a/src/renderer.h b/src/renderer.h index e04c66a8..77fbdfaf 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -145,7 +145,7 @@ Q_OBJECT public: const double fps() const; const int renderWidth() const; const int renderHeight() const; - /** get display aspect ratio */ + /** get display aspect ratio */ const double dar() const; /** Playlist manipulation */ -- 2.39.2