X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmltdevicecapture.cpp;h=425b81a6be28fedec74bc74e1f07a14197f3a1a0;hb=c3302003093710ee247ad84c0fe2ef3c579d417f;hp=8862d5cbe2c5dcedf9e73d1921eedbafcb88064e;hpb=2c5e0cb6f64609430c311ad850f0d9fda9ba9ae0;p=kdenlive diff --git a/src/mltdevicecapture.cpp b/src/mltdevicecapture.cpp index 8862d5cb..425b81a6 100644 --- a/src/mltdevicecapture.cpp +++ b/src/mltdevicecapture.cpp @@ -19,9 +19,6 @@ #include "mltdevicecapture.h" #include "kdenlivesettings.h" #include "definitions.h" -//#include "recmonitor.h" -//#include "renderer.h" -#include "blackmagic/devices.h" #include @@ -36,6 +33,7 @@ #include #include #include +#include #include #include @@ -51,12 +49,12 @@ static void consumer_gl_frame_show(mlt_consumer, MltDeviceCapture * self, mlt_fr 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) { @@ -65,38 +63,42 @@ 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(); - }*/ + } -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_showFrameEvent(NULL), m_droppedFrames(0), - m_livePreview(true), - m_captureDisplayWidget(surface), - m_winid((int) surface->winId()), - m_analyseAudio(KdenliveSettings::monitor_audio()) + 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() @@ -115,7 +117,7 @@ void MltDeviceCapture::buildConsumer(const QString &profileName) 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(); @@ -128,23 +130,23 @@ void MltDeviceCapture::buildConsumer(const QString &profileName) } } 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()) @@ -158,18 +160,34 @@ 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); } +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; - m_captureDisplayWidget->stop(); + //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) { @@ -196,20 +214,6 @@ void MltDeviceCapture::stop() 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()); - } - } delete field; field = NULL; } @@ -218,38 +222,58 @@ void MltDeviceCapture::stop() 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()); } @@ -274,7 +298,6 @@ void MltDeviceCapture::showAudio(Mlt::Frame& frame) // So the vector is of size samples*channels. QVector sampleVector(samples*num_channels); memcpy(sampleVector.data(), data, samples*num_channels*sizeof(int16_t)); - if (samples > 0) { emit audioSamplesSignal(sampleVector, freq, num_channels, samples); } @@ -282,7 +305,9 @@ void MltDeviceCapture::showAudio(Mlt::Frame& frame) 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); @@ -302,36 +327,68 @@ bool MltDeviceCapture::slotStartPreview(const QString &producer, bool xmlFormat) 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) { 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); } } + m_frameCount++; if (!m_livePreview) return; - mlt_image_format format = mlt_image_rgb24a; + //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()); @@ -339,7 +396,7 @@ void MltDeviceCapture::saveFrame(Mlt::Frame& frame) 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(); } @@ -365,63 +422,137 @@ bool MltDeviceCapture::slotStartCapture(const QString ¶ms, const QString &pa { 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: "<get_profile()->is_explicit = 1; + + + /*kDebug()<<"-- CREATING CAP: "<set("terminate_on_pause", 1); - delete[] tmp; + 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; + m_mltConsumer = NULL; + } + return false; + } + + 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); + 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); + 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()); - m_mltConsumer->set(tmp, tmp2); + 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_mltConsumer == NULL || !m_mltConsumer->is_valid()) { - if (m_mltConsumer) { - delete m_mltConsumer; - m_mltConsumer = 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"); + } } - return false; + 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 { + } - // 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()); if (xmlPlaylist) { // create an xml producer - m_mltProducer = new Mlt::Producer(*m_mltProfile, "xml-string", tmp); + 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, tmp); + m_mltProducer = new Mlt::Producer(*m_mltProfile, playlist.toUtf8().constData()); } - delete[] tmp; 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_captureDisplayWidget->start(); + m_droppedFramesTimer.start(); return 1; } @@ -472,7 +603,7 @@ void MltDeviceCapture::setOverlay(const QString &path) 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); @@ -483,7 +614,7 @@ void MltDeviceCapture::setOverlay(const QString &path) //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()); @@ -521,7 +652,7 @@ void MltDeviceCapture::setOverlayEffect(const QString tag, QStringList parameter 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); } @@ -561,3 +692,86 @@ 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; +} + + + +#include "mltdevicecapture.moc"