#include "mltdevicecapture.h"
#include "kdenlivesettings.h"
#include "definitions.h"
-//#include "recmonitor.h"
-//#include "renderer.h"
-#include "blackmagic/devices.h"
+#include "widgets/videosurface.h"
#include <mlt++/Mlt.h>
#include <KDebug>
#include <KStandardDirs>
#include <KMessageBox>
-#include <KLocale>
+#include <KLocalizedString>
#include <KTemporaryFile>
#include <QTimer>
#include <QDir>
#include <QString>
#include <QApplication>
+#include <QThread>
+#include <QTimer>
#include <cstdlib>
#include <cstdarg>
self->showFrame(frame);
}
-static void rec_consumer_frame_show(mlt_consumer, MltDeviceCapture * self, mlt_frame frame_ptr)
+/*static void rec_consumer_frame_show(mlt_consumer, MltDeviceCapture * self, mlt_frame frame_ptr)
{
Mlt::Frame frame(frame_ptr);
if (!frame.is_valid()) return;
self->gotCapturedFrame(frame);
-}
+}*/
static void rec_consumer_frame_preview(mlt_consumer, MltDeviceCapture * self, mlt_frame frame_ptr)
{
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();
- }*/
+
}
-MltDeviceCapture::MltDeviceCapture(QString profile, VideoPreviewContainer *surface, QWidget *parent) :
- AbstractRender(parent),
+MltDeviceCapture::MltDeviceCapture(QString profile, VideoSurface *surface, QWidget *parent) :
+ AbstractRender(Kdenlive::RecordMonitor, parent),
doCapture(0),
sendFrameForAnalysis(false),
+ processingImage(false),
m_mltConsumer(NULL),
m_mltProducer(NULL),
m_mltProfile(NULL),
- m_captureDisplayWidget(surface),
- m_winid((int) surface->winId()),
- m_analyseAudio(KdenliveSettings::monitor_audio())
+ m_showFrameEvent(NULL),
+ m_droppedFrames(0),
+ m_livePreview(KdenliveSettings::enable_recording_preview()),
+ m_winid((int) surface->winId())
{
- if (profile.isEmpty()) profile = KdenliveSettings::current_profile();
+ m_captureDisplayWidget = surface;
+ analyseAudio = KdenliveSettings::monitor_audio();
+ if (profile.isEmpty())
+ profile = KdenliveSettings::current_profile();
buildConsumer(profile);
+ connect(this, SIGNAL(unblockPreview()), this, SLOT(slotPreparePreview()));
+ m_droppedFramesTimer.setSingleShot(false);
+ m_droppedFramesTimer.setInterval(1000);
+ connect(&m_droppedFramesTimer, SIGNAL(timeout()), this, SLOT(slotCheckDroppedFrames()));
}
MltDeviceCapture::~MltDeviceCapture()
char *tmp = qstrdup(m_activeProfile.toUtf8().constData());
setenv("MLT_PROFILE", tmp, 1);
m_mltProfile = new Mlt::Profile(tmp);
- m_mltProfile->get_profile()->is_explicit = 1;
+ m_mltProfile->set_explicit(true);
delete[] tmp;
QString videoDriver = KdenliveSettings::videodrivername();
}
}
setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 1);
-
+
+
if (m_winid == 0) {
// 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->listen("consumer-frame-show", this, (mlt_listener) consumer_gl_frame_show);
+ m_mltConsumer->set("preview_format", mlt_image_rgb24);
+ m_showFrameEvent = 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_showFrameEvent = 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())
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);
}
+void MltDeviceCapture::pause()
+{
+ if (m_mltConsumer) {
+ m_mltConsumer->set("refresh", 0);
+ //m_mltProducer->set_speed(0.0);
+ m_mltConsumer->purge();
+ }
+}
+
void MltDeviceCapture::stop()
{
+ m_droppedFramesTimer.stop();
bool isPlaylist = false;
+ //disconnect(this, SIGNAL(imageReady(QImage)), this, SIGNAL(frameUpdated(QImage)));
+ //m_captureDisplayWidget->stop();
+
+ if (m_showFrameEvent) delete m_showFrameEvent;
+ m_showFrameEvent = NULL;
+
if (m_mltConsumer) {
m_mltConsumer->set("refresh", 0);
- m_mltConsumer->stop();
+ m_mltConsumer->purge();
+ m_mltConsumer->stop();
//if (!m_mltConsumer->is_stopped()) m_mltConsumer->stop();
}
if (m_mltProducer) {
mlt_type = mlt_properties_get(properties, "mlt_type");
resource = mlt_properties_get(properties, "mlt_service");
}
- for (int trackNb = tractor.count() - 1; trackNb >= 0; --trackNb) {
- Mlt::Producer trackProducer(tractor.track(trackNb));
- Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
- if (trackPlaylist.type() == playlist_type) {
- for (int i = 0; i < trackPlaylist.count();i++) {
- // We need to manually decrease the ref count and close the producer, otherwise
- // the video4linux device stays open, seems like a bug in MLT that is not cleaning properly
- mlt_properties props = MLT_PRODUCER_PROPERTIES(trackPlaylist.get_clip(i)->get_parent());
- while (mlt_properties_ref_count(props) > 0) mlt_properties_dec_ref(props);
- if (trackPlaylist.get_clip(i)) mlt_producer_close(trackPlaylist.get_clip(i)->get_parent());
- }
- mlt_playlist_close(trackPlaylist.get_playlist());
- //trackPlaylist.clear();
- }
- }
delete field;
field = NULL;
}
m_mltProducer = NULL;
}
// For some reason, the consumer seems to be deleted by previous stuff when in playlist mode
- if (!isPlaylist) delete m_mltConsumer;
+ if (!isPlaylist && m_mltConsumer) delete m_mltConsumer;
m_mltConsumer = NULL;
}
-void MltDeviceCapture::doRefresh()
+void MltDeviceCapture::slotDoRefresh()
{
- if (m_mltConsumer) m_mltConsumer->set("refresh", 1);
+ QMutexLocker locker(&m_mutex);
+ if (!m_mltProducer)
+ return;
+ if (m_mltConsumer) {
+ if (m_mltConsumer->is_stopped()) m_mltConsumer->start();
+ m_mltConsumer->purge();
+ m_mltConsumer->set("refresh", 1);
+ }
}
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);
- emit frameUpdated(qimage.rgbSwapped());
+ QImage qimage(width, height, QImage::Format_RGB888);
+ //QImage qimage(width, height, QImage::Format_ARGB32_Premultiplied);
+ memcpy(qimage.bits(), image, width * height * 3);
+ emit frameUpdated(qimage);
}
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());
}
// So the vector is of size samples*channels.
QVector<int16_t> sampleVector(samples*num_channels);
memcpy(sampleVector.data(), data, samples*num_channels*sizeof(int16_t));
-
if (samples > 0) {
emit audioSamplesSignal(sampleVector, freq, num_channels, samples);
}
bool MltDeviceCapture::slotStartPreview(const QString &producer, bool xmlFormat)
{
- if (m_mltConsumer == NULL) buildConsumer();
+ if (m_mltConsumer == NULL) {
+ buildConsumer();
+ }
char *tmp = qstrdup(producer.toUtf8().constData());
if (xmlFormat) m_mltProducer = new Mlt::Producer(*m_mltProfile, "xml-string", tmp);
else m_mltProducer = new Mlt::Producer(*m_mltProfile, tmp);
delete[] tmp;
if (m_mltProducer == NULL || !m_mltProducer->is_valid()) {
+ if (m_mltProducer) {
+ delete m_mltProducer;
+ m_mltProducer = NULL;
+ }
kDebug()<<"//// ERROR CREATRING PROD";
return false;
}
m_mltConsumer = NULL;
return 0;
}
+ m_droppedFramesTimer.start();
+ //connect(this, SIGNAL(imageReady(QImage)), this, SIGNAL(frameUpdated(QImage)));
return 1;
}
+void MltDeviceCapture::slotCheckDroppedFrames()
+{
+ if (m_mltProducer) {
+ int dropped = m_mltProducer->get_int("dropped");
+ if (dropped > m_droppedFrames) {
+ m_droppedFrames = dropped;
+ emit droppedFrames(m_droppedFrames);
+ }
+ }
+}
+
void MltDeviceCapture::gotCapturedFrame(Mlt::Frame& frame)
{
- mlt_image_format format = mlt_image_rgb24a;
+ if (m_mltProducer) {
+ int dropped = m_mltProducer->get_int("dropped");
+ if (dropped > m_droppedFrames) {
+ m_droppedFrames = dropped;
+ emit droppedFrames(m_droppedFrames);
+ }
+ }
+ m_frameCount++;
+ if (!m_livePreview) return;
+ //if (m_livePreview == 0 && (m_frameCount % 10 > 0)) return;
+ 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);
- m_captureDisplayWidget->setImage(qimage.rgbSwapped());
+ uint8_t *data = frame.get_image(format, width, height, 0);
+ //QImage image(width, height, QImage::Format_RGB888);
+ //memcpy(image.bits(), data, width * height * 3);
+ QImage image((uchar *)data, width, height, QImage::Format_RGB888);
+
+ //m_captureDisplayWidget->setImage(image);
+
+ //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());
Mlt::Producer trackProducer(tractor.track(0));
trackProducer.set("hide", 0);
- qimage.rgbSwapped().save(m_capturePath);
+ qimage.save(m_capturePath);
emit frameSaved(m_capturePath);
m_capturePath.clear();
}
doCapture = 5;
}
-bool MltDeviceCapture::slotStartCapture(const QString ¶ms, const QString &path, const QString &playlist)
+bool MltDeviceCapture::slotStartCapture(const QString ¶ms, const QString &path, const QString &playlist, bool 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());
m_mltProfile = new Mlt::Profile(tmp);
delete[] tmp;
- m_mltProfile->get_profile()->is_explicit = 1;
- kDebug()<<"-- CREATING CAP: "<<params<<", PATH: "<<path;
+ //m_mltProfile->get_profile()->is_explicit = 1;
+
+
+ /*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);
- delete[] tmp;
-
- QStringList paramList = params.split(" ", QString::SkipEmptyParts);
- char *tmp2;
- for (int i = 0; i < paramList.count(); i++) {
- tmp = qstrdup(paramList.at(i).section("=", 0, 0).toUtf8().constData());
- tmp2 = qstrdup(paramList.at(i).section("=", 1, 1).toUtf8().constData());
- m_mltConsumer->set(tmp, tmp2);
- delete[] tmp;
- delete[] tmp2;
- }
+ m_mltConsumer->set("real_time", -KdenliveSettings::mltthreads());
+ delete[] tmp;*/
+ m_mltConsumer = new Mlt::Consumer(*m_mltProfile, "multi");
if (m_mltConsumer == NULL || !m_mltConsumer->is_valid()) {
if (m_mltConsumer) {
delete m_mltConsumer;
return false;
}
- // FIXME: the event object returned by the listen gets leaked...
- m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) rec_consumer_frame_show);
- tmp = qstrdup(playlist.toUtf8().constData());
- m_mltProducer = new Mlt::Producer(*m_mltProfile, "xml-string", tmp);
- delete[] tmp;
+ m_winid = (int) m_captureDisplayWidget->winId();
+
+ // Create multi consumer setup
+ Mlt::Properties *renderProps = new Mlt::Properties;
+ renderProps->set("mlt_service", "avformat");
+ renderProps->set("target", path.toUtf8().constData());
+ renderProps->set("real_time", -KdenliveSettings::mltthreads());
+ //renderProps->set("terminate_on_pause", 0);
+ renderProps->set("mlt_profile", m_activeProfile.toUtf8().constData());
+
+
+ QStringList paramList = params.split(' ', QString::SkipEmptyParts);
+ char *tmp2;
+ for (int i = 0; i < paramList.count(); ++i) {
+ tmp = qstrdup(paramList.at(i).section('=', 0, 0).toUtf8().constData());
+ QString value = paramList.at(i).section('=', 1, 1);
+ if (value == "%threads") value = QString::number(QThread::idealThreadCount());
+ tmp2 = qstrdup(value.toUtf8().constData());
+ renderProps->set(tmp, tmp2);
+ delete[] tmp;
+ delete[] tmp2;
+ }
+ mlt_properties consumerProperties = m_mltConsumer->get_properties();
+ mlt_properties_set_data(consumerProperties, "0", renderProps->get_properties(), 0, (mlt_destructor) mlt_properties_close, NULL);
+
+ if (m_livePreview)
+ {
+ // user wants live preview
+ Mlt::Properties *previewProps = new Mlt::Properties;
+ QString videoDriver = KdenliveSettings::videodrivername();
+ if (!videoDriver.isEmpty()) {
+ if (videoDriver == "x11_noaccel") {
+ setenv("SDL_VIDEO_YUV_HWACCEL", "0", 1);
+ videoDriver = "x11";
+ } else {
+ unsetenv("SDL_VIDEO_YUV_HWACCEL");
+ }
+ }
+ setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 1);
+
+ if (m_winid == 0) {
+ // OpenGL monitor
+ previewProps->set("mlt_service", "sdl_audio");
+ previewProps->set("preview_off", 1);
+ previewProps->set("preview_format", mlt_image_rgb24);
+ previewProps->set("terminate_on_pause", 0);
+ m_showFrameEvent = m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) consumer_gl_frame_show);
+ } else {
+ previewProps->set("mlt_service", "sdl_preview");
+ previewProps->set("window_id", m_winid);
+ previewProps->set("terminate_on_pause", 0);
+ //m_showFrameEvent = m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) rec_consumer_frame_preview);
+ }
+ //m_mltConsumer->set("resize", 1);
+ previewProps->set("window_background", KdenliveSettings::window_background().name().toUtf8().constData());
+ QString audioDevice = KdenliveSettings::audiodevicename();
+ if (!audioDevice.isEmpty())
+ previewProps->set("audio_device", audioDevice.toUtf8().constData());
+
+ if (!videoDriver.isEmpty())
+ previewProps->set("video_driver", videoDriver.toUtf8().constData());
+
+ QString audioDriver = KdenliveSettings::audiodrivername();
+
+ if (!audioDriver.isEmpty())
+ previewProps->set("audio_driver", audioDriver.toUtf8().constData());
+
+ previewProps->set("real_time", "0");
+ previewProps->set("mlt_profile", m_activeProfile.toUtf8().constData());
+ mlt_properties_set_data(consumerProperties, "1", previewProps->get_properties(), 0, (mlt_destructor) mlt_properties_close, NULL);
+ //m_showFrameEvent = m_mltConsumer->listen("consumer-frame-render", this, (mlt_listener) rec_consumer_frame_show);
+ }
+ else {
+
+ }
+
+ if (xmlPlaylist) {
+ // create an xml producer
+ m_mltProducer = new Mlt::Producer(*m_mltProfile, "xml-string", playlist.toUtf8().constData());
+ }
+ else {
+ // create a producer based on mltproducer parameter
+ m_mltProducer = new Mlt::Producer(*m_mltProfile, playlist.toUtf8().constData());
+ }
if (m_mltProducer == NULL || !m_mltProducer->is_valid()) {
kDebug()<<"//// ERROR CREATRING PROD";
+ if (m_mltConsumer) {
+ delete m_mltConsumer;
+ m_mltConsumer = NULL;
+ }
+ if (m_mltProducer) {
+ delete m_mltProducer;
+ m_mltProducer = NULL;
+ }
return false;
}
-
+
m_mltConsumer->connect(*m_mltProducer);
if (m_mltConsumer->start() == -1) {
+ if (m_showFrameEvent) delete m_showFrameEvent;
+ m_showFrameEvent = NULL;
delete m_mltConsumer;
m_mltConsumer = NULL;
return 0;
}
+ m_droppedFramesTimer.start();
return 1;
}
Mlt::Field *field = tractor.field();
Mlt::Transition *transition = new Mlt::Transition(*m_mltProfile, "composite");
transition->set_in_and_out(0, 0);
- transition->set("geometry", "0,0:100%x100%:70");
+ transition->set("geometry", "0/0:100%x100%:70");
transition->set("fill", 1);
transition->set("operator", "and");
transition->set("a_track", 0);
//delete clip;
}
-void MltDeviceCapture::setOverlayEffect(const QString tag, QStringList parameters)
+void MltDeviceCapture::setOverlayEffect(const QString &tag, const QStringList ¶meters)
{
if (m_mltProducer == NULL || !m_mltProducer->is_valid()) return;
Mlt::Service service(m_mltProducer->parent().get_service());
delete[] tmp;
if (filter && filter->is_valid()) {
for (int j = 0; j < parameters.count(); j++) {
- filter->set(parameters.at(j).section("=", 0, 0).toUtf8().constData(), parameters.at(j).section("=", 1, 1).toUtf8().constData());
+ filter->set(parameters.at(j).section('=', 0, 0).toUtf8().constData(), parameters.at(j).section('=', 1, 1).toUtf8().constData());
}
trackService.attach(*filter);
}
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;
+}
+
+
+
+#include "mltdevicecapture.moc"