]> git.sesse.net Git - kdenlive/commitdiff
Some update for decklink capture & use mlt_threads for proxies
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Sun, 12 Jun 2011 16:00:42 +0000 (16:00 +0000)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Sun, 12 Jun 2011 16:00:42 +0000 (16:00 +0000)
svn path=/trunk/kdenlive/; revision=5706

src/abstractmonitor.cpp
src/abstractmonitor.h
src/kdenlivesettings.kcfg
src/mainwindow.cpp
src/mltdevicecapture.cpp
src/mltdevicecapture.h
src/projectlist.cpp
src/recmonitor.cpp
src/recmonitor.h
src/widgets/recmonitor_ui.ui

index 4b2d5b7d1cc82a1cc017c454128d78e9c17ede57..270bd4f6151b8ab274885dae5f15e463f8436784 100644 (file)
 
 
 #include "abstractmonitor.h"
+#include "kdenlivesettings.h"
 
 #include <KDebug>
 
+#include <QPaintEvent>
+
 VideoPreviewContainer::VideoPreviewContainer(QWidget *parent) :
-    QFrame(parent)
+    QFrame(parent),
+    m_dar(1.0),
+    m_refresh(false)
 {
     setFrameShape(QFrame::NoFrame);
     setFocusPolicy(Qt::ClickFocus);
@@ -38,50 +43,71 @@ VideoPreviewContainer::~VideoPreviewContainer()
     qDeleteAll(m_imageQueue);
 }
 
+//virtual
+void VideoPreviewContainer::resizeEvent( QResizeEvent * /*event*/ )
+{
+    updateDisplayZone();
+}
+
+void VideoPreviewContainer::setRatio(double ratio)
+{
+    m_dar = ratio;
+    updateDisplayZone();
+}
+
+
+void VideoPreviewContainer::updateDisplayZone()
+{
+    QRect rect = this->frameRect();
+    int paintW = rect.height() * m_dar + 0.5;
+    if (paintW > rect.width()) {
+        int paintH = rect.width() / m_dar + 0.5;
+        int diff = (rect.height() - paintH)  / 2;
+        rect.adjust(0, diff, 0, 0);
+        rect.setHeight(paintH);
+    }
+    else {
+        int diff = (rect.width() - paintW)  / 2;
+        rect.adjust(diff, 0, 0, 0);
+        rect.setWidth(paintW);
+    }
+    m_displayRect = rect;
+    m_refresh = true;
+}
 
 void VideoPreviewContainer::setImage(QImage img)
 {
     if (m_imageQueue.count() > 2) {
-        delete m_imageQueue.takeLast();//replace(10, new QImage(img));
+        delete m_imageQueue.takeLast();
     }
     m_imageQueue.prepend(new QImage(img));
+    update();
 }
 
 void VideoPreviewContainer::stop()
 {
-    m_refreshTimer.stop();
+    //m_refreshTimer.stop();
     qDeleteAll(m_imageQueue);
     m_imageQueue.clear();
 }
 
 void VideoPreviewContainer::start()
 {
-    m_refreshTimer.start();
+    //m_refreshTimer.start();
 }
 
 // virtual
-void VideoPreviewContainer::paintEvent(QPaintEvent */*event*/)
+void VideoPreviewContainer::paintEvent(QPaintEvent *event)
 {
-        if (m_imageQueue.isEmpty()) return;
-        QImage *img = m_imageQueue.takeFirst();
-        QPainter painter(this);
-        double ar = (double) img->width() / img->height();
-        QRect rect = this->frameRect();
-        int paintW = rect.height() * ar + 0.5;
-        if (paintW > rect.width()) {
-            paintW = rect.width() / ar + 0.5;
-            int diff = (rect.height() - paintW)  / 2;
-            rect.adjust(0, diff, 0, 0);
-            rect.setHeight(paintW);
-        }
-        else {
-            int diff = (rect.width() - paintW)  / 2;
-            rect.adjust(diff, 0, 0, 0);
-            rect.setWidth(paintW);
-        }
-
-        painter.drawImage(rect, *img);
-        delete img;
+    if (m_imageQueue.isEmpty()) return;
+    QImage *img = m_imageQueue.takeFirst();
+    QPainter painter(this);
+    if (m_refresh) {
+        painter.fillRect(event->rect(), QColor(KdenliveSettings::window_background()));
+        m_refresh = false;
+    }
+    painter.drawImage(m_displayRect, *img);
+    delete img;
 }
 
 
index 85469a13b5194de681594e96c2b89b57edaa6975..1167e6c446f8bc09b677158f193ee1fc2df7e9d8 100644 (file)
@@ -36,16 +36,32 @@ class VideoPreviewContainer : public QFrame
 public:
     VideoPreviewContainer(QWidget *parent = 0);
     ~VideoPreviewContainer();
+    /** @brief Set the image to be displayed, will be put in the queue. */
     void setImage(QImage img);
+    /** @brief Start the display refresh timer. */
     void start();
+    /** @brief Stop the display refresh timer. */
     void stop();
+    /** @brief Set the display ratio for this display. */
+    void setRatio(double ratio);
 
 protected:
     virtual void paintEvent(QPaintEvent */*event*/);
+    virtual void resizeEvent(QResizeEvent * event);
 
 private:
+    /** @brief The display aspect ratio for profile. */
+    double m_dar;
+    /** @brief When true, the whole widget surface will be repainted, useful when resizing widget. */
+    bool m_refresh;
+    /** @brief The rectangle defining the area for painting our image. */
+    QRect m_displayRect;
+    /** @brief The queue of images to be displayed. */
     QList <QImage *> m_imageQueue;
+    /** @brief We refresh the image with a timer, since this widget is only for preview during capture. */
     QTimer m_refreshTimer;
+    /** @brief Re-calculate the display zone after a resize or aspect ratio change. */
+    void updateDisplayZone();
 };
 
 
index c9116df57af1b929e606f7095dc82e375adeddde..6f046430ea0f79522e61576792a608bd788de33b 100644 (file)
   
   <entry name="decklink_parameters" type="String">
       <label>Default Decklink encoding parameters.</label>
-      <default>vcodec=mpeg2video b=12000k minrate=0 pix_fmt=yuv420p g=15 acodec=mp2 ac=2 ab=128k ar=48000 threads=%threads</default>
+      <default>vcodec=mpeg2video qscale=10 acodec=mp2 ac=2 ab=128k ar=48000 threads=%threads</default>
   </entry>
 
   <entry name="decklink_extension" type="String">
       <label>Display audio levels.</label>
       <default>true</default>
     </entry>
+    
+    <entry name="recording_preview" type="UInt">
+      <label>Should we display video frames while capturing.</label>
+      <default>0</default>
+    </entry>
 
   </group>
 
index 1674d785a2a4868c7f8133e7a2abf120a31b746c..9e369e30aa143aab4a13057e8d54bd9c322164c8 100644 (file)
@@ -4213,7 +4213,7 @@ void MainWindow::slotUpdateColorScopes()
         if (!m_gfxScopesList.at(i)->widget()->visibleRegion().isEmpty() && !(static_cast<AbstractGfxScopeWidget *>(m_gfxScopesList.at(i)->widget())->autoRefreshEnabled())) request = true;
         static_cast<AbstractGfxScopeWidget *>(m_gfxScopesList.at(i)->widget())->slotActiveMonitorChanged();
     }
-    if (request) {
+    if (request && m_monitorManager->activeRenderer()) {
         m_monitorManager->activeRenderer()->sendFrameUpdate();
     }
 }
index f9e647f1042492dee636a86be872aa768b1f5988..914ce5ae52fa60256984bf1521e2911c6ded822f 100644 (file)
@@ -65,20 +65,17 @@ static void rec_consumer_frame_preview(mlt_consumer, MltDeviceCapture * self, ml
     if (self->sendFrameForAnalysis && frame_ptr->convert_image) {
         self->emitFrameUpdated(frame);
     }
-    if (self->doCapture > 0) {
+    if (self->doCapture > 0) {  
         self->doCapture --;
         if (self->doCapture == 0) self->saveFrame(frame);
     }
 
-/*    if (self->analyseAudio) {
+    //TODO: connect record monitor to audio scopes
+    /*
+    if (self->analyseAudio) {
         self->showAudio(frame);
     }
-    if (frame.get_double("_speed") == 0.0) {
-        self->emitConsumerStopped();
-    } else if (frame.get_double("_speed") < 0.0 && mlt_frame_get_position(frame_ptr) <= 0) {
-        self->pause();
-        self->emitConsumerStopped();
-    }*/
+    */
 }
 
 
@@ -90,13 +87,15 @@ MltDeviceCapture::MltDeviceCapture(QString profile, VideoPreviewContainer *surfa
     m_mltProducer(NULL),
     m_mltProfile(NULL),
     m_droppedFrames(0),
-    m_livePreview(true),
+    m_livePreview(KdenliveSettings::recording_preview()),
     m_captureDisplayWidget(surface),
     m_winid((int) surface->winId()),
-    m_analyseAudio(KdenliveSettings::monitor_audio())
+    analyseAudio(KdenliveSettings::monitor_audio()),
+    processingImage(false)
 {
     if (profile.isEmpty()) profile = KdenliveSettings::current_profile();
     buildConsumer(profile);
+    connect(this, SIGNAL(unblockPreview()), this, SLOT(slotPreparePreview()));
 }
 
 MltDeviceCapture::~MltDeviceCapture()
@@ -133,18 +132,17 @@ void MltDeviceCapture::buildConsumer(const QString &profileName)
         // OpenGL monitor
         m_mltConsumer = new Mlt::Consumer(*m_mltProfile, "sdl_audio");
         m_mltConsumer->set("preview_off", 1);
-        m_mltConsumer->set("preview_format", mlt_image_rgb24a);
+        m_mltConsumer->set("preview_format", mlt_image_rgb24);
         m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) consumer_gl_frame_show);
     } else {
         m_mltConsumer = new Mlt::Consumer(*m_mltProfile, "sdl_preview");
         m_mltConsumer->set("window_id", m_winid);
+        m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) rec_consumer_frame_preview);
     }
-    m_mltConsumer->set("resize", 1);
+    //m_mltConsumer->set("resize", 1);
     //m_mltConsumer->set("terminate_on_pause", 1);
     m_mltConsumer->set("window_background", KdenliveSettings::window_background().name().toUtf8().constData());
-    m_mltConsumer->set("rescale", "nearest");
-    
-    m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) rec_consumer_frame_preview);
+    //m_mltConsumer->set("rescale", "nearest");
 
     QString audioDevice = KdenliveSettings::audiodevicename();
     if (!audioDevice.isEmpty())
@@ -158,7 +156,7 @@ void MltDeviceCapture::buildConsumer(const QString &profileName)
     if (!audioDriver.isEmpty())
         m_mltConsumer->set("audio_driver", audioDriver.toUtf8().constData());
 
-    //m_mltConsumer->set("progressive", 1);
+    //m_mltConsumer->set("progressive", 0);
     //m_mltConsumer->set("buffer", 1);
     //m_mltConsumer->set("real_time", 0);
 }
@@ -166,6 +164,7 @@ void MltDeviceCapture::buildConsumer(const QString &profileName)
 void MltDeviceCapture::stop()
 {
     bool isPlaylist = false;
+    disconnect(this, SIGNAL(imageReady(QImage)), this, SIGNAL(frameUpdated(QImage)));
     m_captureDisplayWidget->stop();
     if (m_mltConsumer) {
         m_mltConsumer->set("refresh", 0);
@@ -231,25 +230,37 @@ void MltDeviceCapture::doRefresh()
 
 void MltDeviceCapture::emitFrameUpdated(Mlt::Frame& frame)
 {
-    mlt_image_format format = mlt_image_rgb24a;
+    /*
+    //TEST: is it better to convert the frame in a thread outside of MLT??
+    if (processingImage) return;
+    mlt_image_format format = (mlt_image_format) frame.get_int("format"); //mlt_image_rgb24;
+    int width = frame.get_int("width");
+    int height = frame.get_int("height");
+    unsigned char *buffer = (unsigned char *) frame.get_data("image");
+    if (format == mlt_image_yuv422) {
+        QtConcurrent::run(this, &MltDeviceCapture::uyvy2rgb, (unsigned char *) buffer, width, height);
+    }
+    */
+
+    mlt_image_format format = mlt_image_rgb24;
     int width = 0;
     int height = 0;
     const uchar* image = frame.get_image(format, width, height);
     QImage qimage(width, height, QImage::Format_ARGB32);
-    memcpy(qimage.bits(), image, width * height * 4);
+    memcpy(qimage.bits(), image, width * height * 3);
     emit frameUpdated(qimage.rgbSwapped());
 }
 
 void MltDeviceCapture::showFrame(Mlt::Frame& frame)
 {
-    mlt_image_format format = mlt_image_rgb24a;
+    mlt_image_format format = mlt_image_rgb24;
     int width = 0;
     int height = 0;
     const uchar* image = frame.get_image(format, width, height);
-    QImage qimage(width, height, QImage::Format_ARGB32_Premultiplied);
-    memcpy(qimage.scanLine(0), image, width * height * 4);
+    QImage qimage(width, height, QImage::Format_RGB888);
+    memcpy(qimage.scanLine(0), image, width * height * 3);
     emit showImageSignal(qimage);
-    if (m_analyseAudio) showAudio(frame);
+
     if (sendFrameForAnalysis && frame.get_frame()->convert_image) {
         emit frameUpdated(qimage.rgbSwapped());
     }
@@ -304,6 +315,7 @@ bool MltDeviceCapture::slotStartPreview(const QString &producer, bool xmlFormat)
         m_mltConsumer = NULL;
         return 0;
     }
+    connect(this, SIGNAL(imageReady(QImage)), this, SIGNAL(frameUpdated(QImage)));
     return 1;
 }
 
@@ -311,29 +323,49 @@ void MltDeviceCapture::gotCapturedFrame(Mlt::Frame& frame)
 {
     if (m_mltProducer) {
         int dropped = m_mltProducer->get_int("dropped");
-        if (dropped != m_droppedFrames) {
+        if (dropped > m_droppedFrames) {
             m_droppedFrames = dropped;
             emit droppedFrames(m_droppedFrames);
         }
     }
-    if (!m_livePreview) return;
+    m_frameCount++;
+    if (m_livePreview == 2) return;
+    if (m_livePreview == 0 && (m_frameCount % 10 > 0)) return;
     mlt_image_format format = mlt_image_rgb24a;
     int width = 0;
     int height = 0;
-    const uchar* image = frame.get_image(format, width, height);
-    QImage qimage(width, height, QImage::Format_ARGB32);
-    memcpy(qimage.bits(), image, width * height * 4);
-    m_captureDisplayWidget->setImage(qimage.rgbSwapped());
+    //QImage image(width, height, QImage::Format_ARGB32_Premultiplied);
+    uint8_t *data = frame.get_image(format, width, height, 0);
+    QImage image((uchar *)data, width, height, QImage::Format_ARGB32_Premultiplied);
+    
+    /*uchar *buffer = frame.get_image(format, width, height);
+    memcpy(image.bits(), buffer, width * height * 4);*/
+    m_captureDisplayWidget->setImage(image.rgbSwapped());
+
+    //TEST: is it better to process frame conversion ouside MLT???
+    /*
+    if (!m_livePreview || processingImage) return;
+
+    mlt_image_format format = (mlt_image_format) frame.get_int("format"); //mlt_image_rgb24a;
+    int width = frame.get_int("width");
+    int height = frame.get_int("height");
+    unsigned char *buffer = (unsigned char *) frame.get_data("image");
+    //unsigned char *buffer = frame.get_image(format, width, height);
+    //convert from uyvy422 to rgba
+    if (format == mlt_image_yuv422) {
+        QtConcurrent::run(this, &MltDeviceCapture::uyvy2rgb, (unsigned char *) buffer, width, height);
+        //CaptureHandler::uyvy2rgb((uchar *)frameBytes, (uchar *)image.bits(), videoFrame->GetWidth(), videoFrame->GetHeight());
+    }*/
 }
 
 void MltDeviceCapture::saveFrame(Mlt::Frame& frame)
 {
-    mlt_image_format format = mlt_image_rgb24a;
+    mlt_image_format format = mlt_image_rgb24;
     int width = 0;
     int height = 0;
     const uchar* image = frame.get_image(format, width, height);
-    QImage qimage(width, height, QImage::Format_ARGB32);
-    memcpy(qimage.bits(), image, width * height * 4);
+    QImage qimage(width, height, QImage::Format_RGB888);
+    memcpy(qimage.bits(), image, width * height * 3);
 
     // Re-enable overlay
     Mlt::Service service(m_mltProducer->parent().get_service());
@@ -363,10 +395,11 @@ void MltDeviceCapture::captureFrame(const QString &path)
     doCapture = 5;
 }
 
-bool MltDeviceCapture::slotStartCapture(const QString &params, const QString &path, const QString &playlist, bool livePreview, bool xmlPlaylist)
+bool MltDeviceCapture::slotStartCapture(const QString &params, const QString &path, const QString &playlist, int livePreview, bool xmlPlaylist)
 {
     stop();
     m_livePreview = livePreview;
+    m_frameCount = 0;
     m_droppedFrames = 0;
     if (m_mltProfile) delete m_mltProfile;
     char *tmp = qstrdup(m_activeProfile.toUtf8().constData());
@@ -376,7 +409,7 @@ bool MltDeviceCapture::slotStartCapture(const QString &params, const QString &pa
     kDebug()<<"-- CREATING CAP: "<<params<<", PATH: "<<path;
     tmp = qstrdup(QString("avformat:" + path).toUtf8().constData());
     m_mltConsumer = new Mlt::Consumer(*m_mltProfile, tmp);
-    m_mltConsumer->set("terminate_on_pause", 1);
+    m_mltConsumer->set("real_time", KdenliveSettings::mltthreads());
     delete[] tmp;
 
     QStringList paramList = params.split(" ", QString::SkipEmptyParts);
@@ -400,7 +433,7 @@ bool MltDeviceCapture::slotStartCapture(const QString &params, const QString &pa
     }
     
     // FIXME: the event object returned by the listen gets leaked...
-    m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) rec_consumer_frame_show);
+    m_mltConsumer->listen("consumer-frame-render", this, (mlt_listener) rec_consumer_frame_show);
     tmp = qstrdup(playlist.toUtf8().constData());
     if (xmlPlaylist) {
         // create an xml producer
@@ -416,7 +449,7 @@ bool MltDeviceCapture::slotStartCapture(const QString &params, const QString &pa
         kDebug()<<"//// ERROR CREATRING PROD";
         return false;
     }
-
+    
     m_mltConsumer->connect(*m_mltProducer);
     if (m_mltConsumer->start() == -1) {
         delete m_mltConsumer;
@@ -563,3 +596,84 @@ void MltDeviceCapture::mirror(bool activate)
     mlt_service_unlock(service.get_service());
 }
 
+void MltDeviceCapture::uyvy2rgb(unsigned char *yuv_buffer, int width, int height)
+{
+    processingImage = true;
+    QImage image(width, height, QImage::Format_RGB888);
+    unsigned char *rgb_buffer = image.bits();    
+
+    int len;
+    int r, g, b;
+    int Y, U, V, Y2;
+    int rgb_ptr, y_ptr, t;
+
+    len = width * height / 2;
+
+    rgb_ptr = 0;
+    y_ptr = 0;
+
+    for (t = 0; t < len; t++) { 
+      
+
+        Y = yuv_buffer[y_ptr];
+        U = yuv_buffer[y_ptr+1];
+        Y2 = yuv_buffer[y_ptr+2];
+        V = yuv_buffer[y_ptr+3];
+        y_ptr += 4;
+
+        r = ((298 * (Y - 16)               + 409 * (V - 128) + 128) >> 8);
+
+        g = ((298 * (Y - 16) - 100 * (U - 128) - 208 * (V - 128) + 128) >> 8);
+
+        b = ((298 * (Y - 16) + 516 * (U - 128)               + 128) >> 8);
+
+        if (r > 255) r = 255;
+        if (g > 255) g = 255;
+        if (b > 255) b = 255;
+
+        if (r < 0) r = 0;
+        if (g < 0) g = 0;
+        if (b < 0) b = 0;
+
+        rgb_buffer[rgb_ptr] = r;
+        rgb_buffer[rgb_ptr+1] = g;
+        rgb_buffer[rgb_ptr+2] = b;
+        rgb_ptr += 3;
+
+
+        r = ((298 * (Y2 - 16)               + 409 * (V - 128) + 128) >> 8);
+
+        g = ((298 * (Y2 - 16) - 100 * (U - 128) - 208 * (V - 128) + 128) >> 8);
+
+        b = ((298 * (Y2 - 16) + 516 * (U - 128)               + 128) >> 8);
+
+        if (r > 255) r = 255;
+        if (g > 255) g = 255;
+        if (b > 255) b = 255;
+
+        if (r < 0) r = 0;
+        if (g < 0) g = 0;
+        if (b < 0) b = 0;
+
+        rgb_buffer[rgb_ptr] = r;
+        rgb_buffer[rgb_ptr+1] = g;
+        rgb_buffer[rgb_ptr+2] = b;
+        rgb_ptr += 3;
+    }
+    //emit imageReady(image);
+    m_captureDisplayWidget->setImage(image);
+    emit unblockPreview();
+    //processingImage = false;
+}
+
+void MltDeviceCapture::slotPreparePreview()
+{
+    QTimer::singleShot(1000, this, SLOT(slotAllowPreview()));
+}
+
+void MltDeviceCapture::slotAllowPreview()
+{
+    processingImage = false;
+}
+
+
index 2a332bf96a37a4f2288cd8eabfce0b585c006930..9603326e3394245e970436c19b614381e1f7f7bb 100644 (file)
@@ -28,6 +28,8 @@
 #include "abstractmonitor.h"
 #include "mlt/framework/mlt_types.h"
 
+#include <QtConcurrentRun>
+
 namespace Mlt
 {
 class Consumer;
@@ -76,7 +78,7 @@ Q_OBJECT public:
     /** @brief Starts the MLT Video4Linux process.
      * @param surface The widget onto which the frame should be painted
      */
-    bool slotStartCapture(const QString &params, const QString &path, const QString &playlist, bool livePreview, bool xmlPlaylist = true);
+    bool slotStartCapture(const QString &params, const QString &path, const QString &playlist, int livePreview, bool xmlPlaylist = true);
     bool slotStartPreview(const QString &producer, bool xmlFormat = false);
     /** @brief A frame arrived from the MLT Video4Linux process. */
     void gotCapturedFrame(Mlt::Frame& frame);
@@ -92,13 +94,22 @@ Q_OBJECT public:
     /** @brief This will add a horizontal flip effect, easier to work when filming yourself. */
     void mirror(bool activate);
 
+    /** @brief This property is used to decide if the renderer should send audio data for monitoring. */
+    bool analyseAudio;
+    
+    /** @brief True if we are processing an image (yuv > rgb) when recording. */
+    bool processingImage;
+
 private:
     Mlt::Consumer * m_mltConsumer;
     Mlt::Producer * m_mltProducer;
     Mlt::Profile *m_mltProfile;
     QString m_activeProfile;
     int m_droppedFrames;
-    bool m_livePreview;
+    /** @brief When true, images will be displayed on monitor while capturing. */
+    int m_livePreview;
+    /** @brief Count captured frames, used to display only one in ten images while capturing. */
+    int m_frameCount;
 
     /** @brief The surface onto which the captured frames should be painted. */
     VideoPreviewContainer *m_captureDisplayWidget;
@@ -106,8 +117,7 @@ private:
     /** @brief A human-readable description of this renderer. */
     int m_winid;
 
-    /** @brief This property is used to decide if the renderer should send audio data for monitoring. */
-    bool m_analyseAudio;
+    void uyvy2rgb(unsigned char *yuv_buffer, int width, int height);
 
     QString m_capturePath;
 
@@ -115,8 +125,11 @@ private:
      *  @param profileName The MLT profile to use for the consumer */
     void buildConsumer(const QString &profileName = QString());
 
-private slots:
 
+private slots:
+    void slotPreparePreview();
+    void slotAllowPreview();
+  
 signals:
     /** @brief A frame's image has to be shown.
      *
@@ -129,6 +142,10 @@ signals:
     void frameSaved(const QString);
     
     void droppedFrames(int);
+    
+    void unblockPreview();
+    void imageReady(QImage);
+
 
 public slots:
 
index cddce5e83c53e59a01b21625e5ddf0e241e0bce5..a9087e4e32d4b7ff696843e8c675f75da2bbe403 100644 (file)
@@ -2182,6 +2182,8 @@ void ProjectList::slotGenerateProxy(const QString id)
             else s.replace(' ', '=');
             parameters << s;
         }
+        
+        parameters.append(QString("real_time=-%1").arg(KdenliveSettings::mltthreads()));
 
         // currently, when rendering an xml file through melt, the display ration is lost, so we enforce it manualy
         double display_ratio = KdenliveDoc::getDisplayRatio(url);
index 9083abc239d6b02b421e6dfa8dab881ef8c48ac5..76c5714acb7cd66d75ba4c54e3b9b1c0eff6ee0e 100644 (file)
@@ -158,6 +158,9 @@ RecMonitor::RecMonitor(QString name, MonitorManager *manager, QWidget *parent) :
 
     kDebug() << "/////// BUILDING MONITOR, ID: " << video_frame->winId();
     slotVideoDeviceChanged(device_selector->currentIndex());
+    recording_preview->setToolTip(i18n("Capture preview settings"));
+    recording_preview->setCurrentIndex(KdenliveSettings::recording_preview());
+    connect(recording_preview, SIGNAL(currentIndexChanged(int)), this, SLOT(slotChangeRecordingPreview(int)));
 }
 
 RecMonitor::~RecMonitor()
@@ -210,7 +213,7 @@ void RecMonitor::slotVideoDeviceChanged(int ix)
 {
     QString capturefile;
     QString capturename;
-    enable_preview->setHidden(ix != VIDEO4LINUX && ix != BLACKMAGIC);
+    recording_preview->setHidden(ix != VIDEO4LINUX && ix != BLACKMAGIC);
     m_fwdAction->setVisible(ix == FIREWIRE);
     m_discAction->setVisible(ix == FIREWIRE);
     m_rewAction->setVisible(ix == FIREWIRE);
@@ -386,6 +389,7 @@ void RecMonitor::slotStopCapture()
         if (m_captureDevice) {
             m_captureDevice->stop();
         }
+        recording_preview->setEnabled(true);
         m_isCapturing = false;
         m_isPlaying = false;
         m_playAction->setEnabled(true);
@@ -542,6 +546,7 @@ void RecMonitor::slotRecord()
         return;
     }
     if (m_captureProcess->state() == QProcess::NotRunning) {
+        m_logger.clear();
         m_recAction->setChecked(true);
         QString extension = "mpg";
         if (device_selector->currentIndex() == SCREENGRAB) extension = "ogv"; //KdenliveSettings::screengrabextension();
@@ -568,6 +573,7 @@ void RecMonitor::slotRecord()
         case VIDEO4LINUX:
             path = KStandardDirs::locateLocal("appdata", "profiles/video4linux");
             profile = ProfilesDialog::getVideoProfile(path);
+            m_videoBox->setRatio((double) profile.display_aspect_num / profile.display_aspect_den);
             buildMltDevice(path);
             playlist = QString("<mlt title=\"capture\"><producer id=\"producer0\" in=\"0\" out=\"99999\"><property name=\"mlt_type\">producer</property><property name=\"length\">100000</property><property name=\"eof\">pause</property><property name=\"resource\">video4linux2:%1?width:%2&amp;height:%3&amp;frame_rate:%4</property><property name=\"mlt_service\">avformat-novalidate</property></producer><playlist id=\"playlist0\"><entry producer=\"producer0\" in=\"0\" out=\"99999\"/></playlist>").arg(KdenliveSettings::video4vdevice()).arg(profile.width).arg(profile.height).arg((double) profile.frame_rate_num / profile.frame_rate_den);
 
@@ -589,11 +595,12 @@ void RecMonitor::slotRecord()
 
             playlist.append("</tractor></mlt>");
 
-            if (m_captureDevice->slotStartCapture(KdenliveSettings::v4l_parameters(), m_captureFile.path(), playlist, enable_preview->isChecked())) {
+            if (m_captureDevice->slotStartCapture(KdenliveSettings::v4l_parameters(), m_captureFile.path(), playlist, recording_preview->currentIndex())) {
                 m_videoBox->setHidden(false);
                 m_isCapturing = true;
                 m_recAction->setEnabled(false);
                 m_stopAction->setEnabled(true);
+                recording_preview->setEnabled(false);
             }
             else {
                 video_frame->setText(i18n("Failed to start Video4Linux,\ncheck your parameters..."));                
@@ -605,16 +612,18 @@ void RecMonitor::slotRecord()
         case BLACKMAGIC:
             path = KdenliveSettings::current_profile();
             profile = ProfilesDialog::getVideoProfile(path);
+            m_videoBox->setRatio((double) profile.display_aspect_num / profile.display_aspect_den);
             buildMltDevice(path);
                
             playlist = QString("<producer id=\"producer0\" in=\"0\" out=\"99999\"><property name=\"mlt_type\">producer</property><property name=\"length\">100000</property><property name=\"eof\">pause</property><property name=\"resource\">%1</property><property name=\"mlt_service\">decklink</property></producer>").arg(KdenliveSettings::decklink_capturedevice());
 
-            if (m_captureDevice->slotStartCapture(KdenliveSettings::decklink_parameters(), m_captureFile.path(), QString("decklink:%1").arg(KdenliveSettings::decklink_capturedevice()), enable_preview->isChecked(), false)) {
+            if (m_captureDevice->slotStartCapture(KdenliveSettings::decklink_parameters(), m_captureFile.path(), QString("decklink:%1").arg(KdenliveSettings::decklink_capturedevice()), recording_preview->currentIndex(), false)) {
                 m_videoBox->setHidden(false);
                 m_isCapturing = true;
                 slotSetInfoMessage(i18n("Capturing to %1", m_captureFile.fileName()));
                 m_recAction->setEnabled(false);
                 m_stopAction->setEnabled(true);
+                recording_preview->setEnabled(false);
             }
             else {
                 video_frame->setText(i18n("Failed to start Decklink,\ncheck your parameters..."));
@@ -880,6 +889,10 @@ void RecMonitor::buildMltDevice(const QString &path)
     }
 }
 
+void RecMonitor::slotChangeRecordingPreview(int ix)
+{
+    KdenliveSettings::setRecording_preview(ix);
+}
 
 #include "recmonitor.moc"
 
index 6472138121c3664643531da235c4f16886ceb2bc..d9bd734cb73f0fa3a3febb9c0087dc0d10855faf 100644 (file)
@@ -124,6 +124,8 @@ private slots:
     void slotUpdateFreeSpace();
     void slotSetInfoMessage(const QString &message);
     void slotDroppedFrames(int dropped);
+    /** @brief Change setting for preview while recording. */
+    void slotChangeRecordingPreview(int ix);
 
 public slots:
     void refreshRecMonitor(bool visible);
index 13e8aec93933a97d60aae1dd43b5ee6b228abd2a..6194a34fbe87041c92e06b1f9aa482463c2ded43 100644 (file)
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>371</width>
-    <height>186</height>
+    <width>291</width>
+    <height>184</height>
    </rect>
   </property>
   <layout class="QGridLayout" name="gridLayout">
      </item>
     </widget>
    </item>
-   <item row="2" column="1">
-    <widget class="QCheckBox" name="enable_preview">
-     <property name="text">
-      <string>Preview while capturing</string>
-     </property>
-     <property name="checked">
-      <bool>true</bool>
-     </property>
-    </widget>
-   </item>
    <item row="2" column="2">
     <spacer name="horizontalSpacer">
      <property name="orientation">
      </property>
     </spacer>
    </item>
+   <item row="2" column="1">
+    <widget class="QComboBox" name="recording_preview">
+     <item>
+      <property name="text">
+       <string>Quick preview</string>
+      </property>
+     </item>
+     <item>
+      <property name="text">
+       <string>Full preview</string>
+      </property>
+     </item>
+     <item>
+      <property name="text">
+       <string>No preview</string>
+      </property>
+     </item>
+    </widget>
+   </item>
   </layout>
  </widget>
  <customwidgets>