From d8175effdf7a4f5d0b94bc702cc8f2855629d149 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Mon, 11 Nov 2013 17:42:31 -0600 Subject: [PATCH] Added Qt video player example code, although it is not working yet. --- .cproject | 562 +++++++++++++++++++++++++++----- CMakeLists.txt | 2 +- include/OpenShot.h | 5 + include/Qt/videoplayer.h | 77 +++++ include/Qt/videowidget.h | 72 ++++ include/Qt/videowidgetsurface.h | 82 +++++ src/CMakeLists.txt | 16 +- src/Main.cpp | 88 ++++- src/Qt/videoplayer.cpp | 193 +++++++++++ src/Qt/videowidget.cpp | 101 ++++++ src/Qt/videowidgetsurface.cpp | 164 ++++++++++ 11 files changed, 1280 insertions(+), 82 deletions(-) create mode 100644 include/Qt/videoplayer.h create mode 100644 include/Qt/videowidget.h create mode 100644 include/Qt/videowidgetsurface.h create mode 100644 src/Qt/videoplayer.cpp create mode 100644 src/Qt/videowidget.cpp create mode 100644 src/Qt/videowidgetsurface.cpp diff --git a/.cproject b/.cproject index fe231d90..be83e8e1 100644 --- a/.cproject +++ b/.cproject @@ -5,83 +5,290 @@ - - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + @@ -108,11 +315,218 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + diff --git a/CMakeLists.txt b/CMakeLists.txt index a1e6b9b1..7a5d835b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ ################################################################################ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 2.8.6) ################ ADD CMAKE MODULES ################## set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules") diff --git a/include/OpenShot.h b/include/OpenShot.h index 23c59067..60d56ddf 100644 --- a/include/OpenShot.h +++ b/include/OpenShot.h @@ -123,6 +123,11 @@ #include "TextReader.h" #include "Timeline.h" +/* Qt Video Player */ +#include "Qt/videoplayer.h" +#include "Qt/videowidget.h" +#include "Qt/videowidgetsurface.h" + /* Effects */ #include "effects/ChromaKey.h" #include "effects/Deinterlace.h" diff --git a/include/Qt/videoplayer.h b/include/Qt/videoplayer.h new file mode 100644 index 00000000..d1fbc95a --- /dev/null +++ b/include/Qt/videoplayer.h @@ -0,0 +1,77 @@ +/**************************************************************************** + ** + ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + ** All rights reserved. + ** Contact: Nokia Corporation (qt-info@nokia.com) + ** + ** This file is part of the examples of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:BSD$ + ** You may use this file under the terms of the BSD license as follows: + ** + ** "Redistribution and use in source and binary forms, with or without + ** modification, are permitted provided that the following conditions are + ** met: + ** * Redistributions of source code must retain the above copyright + ** notice, this list of conditions and the following disclaimer. + ** * Redistributions in binary form must reproduce the above copyright + ** notice, this list of conditions and the following disclaimer in + ** the documentation and/or other materials provided with the + ** distribution. + ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor + ** the names of its contributors may be used to endorse or promote + ** products derived from this software without specific prior written + ** permission. + ** + ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + #ifndef VIDEOPLAYER_H + #define VIDEOPLAYER_H + + #include + #include + + class QAbstractButton; + class QAbstractVideoSurface; + class QSlider; + + class VideoPlayer : public QWidget + { + Q_OBJECT + + public: + VideoPlayer(QWidget *parent = 0); + ~VideoPlayer(); + + public slots: + void openFile(); + void play(); + + private slots: + void movieStateChanged(QMovie::MovieState state); + void frameChanged(int frame); + void setPosition(int frame); + + private: + bool presentImage(const QImage &image); + + QMovie movie; + QAbstractVideoSurface *surface; + QAbstractButton *playButton; + QSlider *positionSlider; + }; + + #endif diff --git a/include/Qt/videowidget.h b/include/Qt/videowidget.h new file mode 100644 index 00000000..26a9f5e7 --- /dev/null +++ b/include/Qt/videowidget.h @@ -0,0 +1,72 @@ + /**************************************************************************** + ** + ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + ** All rights reserved. + ** Contact: Nokia Corporation (qt-info@nokia.com) + ** + ** This file is part of the examples of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:BSD$ + ** You may use this file under the terms of the BSD license as follows: + ** + ** "Redistribution and use in source and binary forms, with or without + ** modification, are permitted provided that the following conditions are + ** met: + ** * Redistributions of source code must retain the above copyright + ** notice, this list of conditions and the following disclaimer. + ** * Redistributions in binary form must reproduce the above copyright + ** notice, this list of conditions and the following disclaimer in + ** the documentation and/or other materials provided with the + ** distribution. + ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor + ** the names of its contributors may be used to endorse or promote + ** products derived from this software without specific prior written + ** permission. + ** + ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + #ifndef VIDEOWIDGET_H + #define VIDEOWIDGET_H + + #include "videowidgetsurface.h" + + #include + + class QAbstractVideoSurface; + + class VideoWidgetSurface; + + class VideoWidget : public QWidget + { + Q_OBJECT + + public: + VideoWidget(QWidget *parent = 0); + ~VideoWidget(); + + QAbstractVideoSurface *videoSurface() const { return surface; } + + QSize sizeHint() const; + + protected: + void paintEvent(QPaintEvent *event); + void resizeEvent(QResizeEvent *event); + + private: + VideoWidgetSurface *surface; + }; + + #endif diff --git a/include/Qt/videowidgetsurface.h b/include/Qt/videowidgetsurface.h new file mode 100644 index 00000000..0568d3b9 --- /dev/null +++ b/include/Qt/videowidgetsurface.h @@ -0,0 +1,82 @@ + /**************************************************************************** + ** + ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + ** All rights reserved. + ** Contact: Nokia Corporation (qt-info@nokia.com) + ** + ** This file is part of the examples of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:BSD$ + ** You may use this file under the terms of the BSD license as follows: + ** + ** "Redistribution and use in source and binary forms, with or without + ** modification, are permitted provided that the following conditions are + ** met: + ** * Redistributions of source code must retain the above copyright + ** notice, this list of conditions and the following disclaimer. + ** * Redistributions in binary form must reproduce the above copyright + ** notice, this list of conditions and the following disclaimer in + ** the documentation and/or other materials provided with the + ** distribution. + ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor + ** the names of its contributors may be used to endorse or promote + ** products derived from this software without specific prior written + ** permission. + ** + ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + #ifndef VIDEOWIDGETSURFACE_H + #define VIDEOWIDGETSURFACE_H + + #include + #include + #include + #include + #include + +using namespace std; + + class VideoWidgetSurface : public QAbstractVideoSurface + { + Q_OBJECT + + public: + VideoWidgetSurface(QWidget *widget=0, QObject *parent = 0); + + QList supportedPixelFormats( + QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const; + bool isFormatSupported(const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const; + + bool start(const QVideoSurfaceFormat &format); + void stop(); + + bool present(const QVideoFrame &frame); + + QRect videoRect() const { return targetRect; } + void updateVideoRect(); + + void paint(QPainter *painter); + + private: + QWidget *widget; + QImage::Format imageFormat; + QRect targetRect; + QSize imageSize; + QRect sourceRect; + QVideoFrame currentFrame; + }; + + #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3abe2b21..c90c2e62 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -65,13 +65,21 @@ IF (QT_EXECUTABLE) ENDIF (QT_EXECUTABLE) # Find QT4 libraries -FIND_PACKAGE(Qt4 REQUIRED) +FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui QtMultimedia REQUIRED) # Include Qt headers (needed for compile) include(${QT_USE_FILE}) include_directories(${QT_INCLUDES}) add_definitions(${QT_DEFINITIONS}) +# Add Multimedia library +SET(QT_LIBRARIES ${QT_LIBRARIES} ${QT_QTMULTIMEDIA_LIBRARY}) + +# Moc all Qt headers +FILE(GLOB QT_HEADERS "/home/jonathan/apps/libopenshot/include/Qt/*.h") +qt4_wrap_cpp (QT_MOC_FILES ${QT_HEADERS}) +message('${QT_MOC_FILES}') + ################# BLACKMAGIC DECKLINK ################### # Find BlackMagic DeckLinkAPI libraries @@ -134,6 +142,12 @@ SET ( OPENSHOT_SOURCE_FILES TextReader.cpp Timeline.cpp + # Qt Video Player + ${QT_MOC_FILES} + Qt/videoplayer.cpp + Qt/videowidget.cpp + Qt/videowidgetsurface.cpp + # Third Party JSON Parser ../thirdparty/jsoncpp/src/lib_json/json_reader.cpp ../thirdparty/jsoncpp/src/lib_json/json_value.cpp diff --git a/src/Main.cpp b/src/Main.cpp index 6bd70561..38b76a82 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -33,20 +33,96 @@ #include "../include/OpenShot.h" #include "../include/Json.h" #include -#include +#include +#include +#include +#include using namespace openshot; using namespace tr1; - int main(int argc, char* argv[]) { + + // Start Qt Application + QApplication app(argc, argv);\ + + // Init video player widget + VideoPlayer player; + player.showMaximized(); + + // Prepare video surface + VideoWidgetSurface * videoWidget = new VideoWidgetSurface(&player); + QSize videoSize(1280, 720); // supplement with your video dimensions + + // look at VideoWidgetSurface::supportedPixelFormats for supported formats + QVideoSurfaceFormat format( videoSize, QVideoFrame::Format_ARGB32); + + + + // Get test frame FFmpegReader r2("/home/jonathan/Videos/sintel_trailer-720p.mp4"); r2.Open(); - SDLPlayer p; - p.Reader(&r2); - p.Play(); - return 0; + tr1::shared_ptr frame = r2.GetFrame(600); + + // Get image + tr1::shared_ptr image = r2.GetFrame(300)->GetImage(); + + // Create Qt Video Frame + QVideoFrame aFrame(32 * image->size().width() * image->size().height(), QSize(image->size().width(), image->size().height()), 32 * image->size().width(), QVideoFrame::Format_ARGB32); + + // Get a reference to the internal videoframe buffer + aFrame.map(QAbstractVideoBuffer::WriteOnly); + uchar *pixels = aFrame.bits(); + + // Copy pixel data from ImageMagick to Qt + Magick::Blob my_blob_1; + image->write(&my_blob_1); // or PNG img1.write(&my_blob_1); const QByteArray imageData1((char*)(my_blob_1.data()),my_blob_1.length()); + + pixels = (uchar*)(my_blob_1.data()),my_blob_1.length(); + //memcpy(pixels, my_blob_1.data(), my_blob_1.length()); + + // Get a list of pixels from source image +// const Magick::PixelPacket *pixel_packets = frame->GetPixels(); +// +// // Fill the AVFrame with RGB image data +// int source_total_pixels = image->size().width() * image->size().height(); +// for (int packet = 0, row = 0; packet < source_total_pixels; packet++, row+=4) +// { +// // Update buffer (which is already linked to the AVFrame: pFrameRGB) +// // Each color needs to be 8 bit (so I'm bit shifting the 16 bit ints) +// pixels[row] = 255; +// pixels[row+1] = 255; +// pixels[row+2] = pixel_packets[packet].green >> 8; +// pixels[row+3] = pixel_packets[packet].blue >> 8; +// //pixels[row] = qRgb(pixel_packets[packet].red, pixel_packets[packet].green, pixel_packets[packet].blue); +// } + aFrame.unmap(); + + // Start video player (which sets format's size) + videoWidget->start(format); + + // Display frame + videoWidget->present(aFrame); + + + + // Start Qt App + return app.exec(); + + + + + + + + +// FFmpegReader r2("/home/jonathan/Videos/sintel_trailer-720p.mp4"); +// r2.Open(); +// SDLPlayer p; +// p.Reader(&r2); +// p.Play(); +// return 0; diff --git a/src/Qt/videoplayer.cpp b/src/Qt/videoplayer.cpp new file mode 100644 index 00000000..0a3d9199 --- /dev/null +++ b/src/Qt/videoplayer.cpp @@ -0,0 +1,193 @@ +/**************************************************************************** + ** + ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + ** All rights reserved. + ** Contact: Nokia Corporation (qt-info@nokia.com) + ** + ** This file is part of the examples of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:BSD$ + ** You may use this file under the terms of the BSD license as follows: + ** + ** "Redistribution and use in source and binary forms, with or without + ** modification, are permitted provided that the following conditions are + ** met: + ** * Redistributions of source code must retain the above copyright + ** notice, this list of conditions and the following disclaimer. + ** * Redistributions in binary form must reproduce the above copyright + ** notice, this list of conditions and the following disclaimer in + ** the documentation and/or other materials provided with the + ** distribution. + ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor + ** the names of its contributors may be used to endorse or promote + ** products derived from this software without specific prior written + ** permission. + ** + ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + #include "../../include/Qt/videoplayer.h" + #include "../../include/Qt/videowidget.h" + + #include + + VideoPlayer::VideoPlayer(QWidget *parent) + : QWidget(parent) + , surface(0) + , playButton(0) + , positionSlider(0) + { + connect(&movie, SIGNAL(stateChanged(QMovie::MovieState)), + this, SLOT(movieStateChanged(QMovie::MovieState))); + connect(&movie, SIGNAL(frameChanged(int)), + this, SLOT(frameChanged(int))); + + VideoWidget *videoWidget = new VideoWidget; + surface = videoWidget->videoSurface(); + + QAbstractButton *openButton = new QPushButton(tr("Open...")); + connect(openButton, SIGNAL(clicked()), this, SLOT(openFile())); + + playButton = new QPushButton; + playButton->setEnabled(false); + playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); + + connect(playButton, SIGNAL(clicked()), + this, SLOT(play())); + + positionSlider = new QSlider(Qt::Horizontal); + positionSlider->setRange(0, 0); + + connect(positionSlider, SIGNAL(sliderMoved(int)), + this, SLOT(setPosition(int))); + + connect(&movie, SIGNAL(frameChanged(int)), + positionSlider, SLOT(setValue(int))); + + QBoxLayout *controlLayout = new QHBoxLayout; + controlLayout->setMargin(0); + controlLayout->addWidget(openButton); + controlLayout->addWidget(playButton); + controlLayout->addWidget(positionSlider); + + QBoxLayout *layout = new QVBoxLayout; + layout->addWidget(videoWidget); + layout->addLayout(controlLayout); + + setLayout(layout); + } + + VideoPlayer::~VideoPlayer() + { + } + + void VideoPlayer::openFile() + { + QStringList supportedFormats; + foreach (QString fmt, QMovie::supportedFormats()) + supportedFormats << fmt; + foreach (QString fmt, QImageReader::supportedImageFormats()) + supportedFormats << fmt; + + QString filter = "Images ("; + foreach ( QString fmt, supportedFormats) { + filter.append(QString("*.%1 ").arg(fmt)); + } + filter.append(")"); + + QString fileName = QFileDialog::getOpenFileName(this, tr("Open Movie"), + QDir::homePath(), filter); + + if (!fileName.isEmpty()) { + surface->stop(); + + movie.setFileName(fileName); + + playButton->setEnabled(true); + positionSlider->setMaximum(movie.frameCount()); + + movie.jumpToFrame(0); + } + } + + void VideoPlayer::play() + { + switch(movie.state()) { + case QMovie::NotRunning: + movie.start(); + break; + case QMovie::Paused: + movie.setPaused(false); + break; + case QMovie::Running: + movie.setPaused(true); + break; + } + } + + void VideoPlayer::movieStateChanged(QMovie::MovieState state) + { + switch(state) { + case QMovie::NotRunning: + case QMovie::Paused: + playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay)); + break; + case QMovie::Running: + playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPause)); + break; + } + } + + void VideoPlayer::frameChanged(int frame) + { + if (!presentImage(movie.currentImage())) { + movie.stop(); + playButton->setEnabled(false); + positionSlider->setMaximum(0); + } else { + positionSlider->setValue(frame); + } + } + + void VideoPlayer::setPosition(int frame) + { + movie.jumpToFrame(frame); + } + + bool VideoPlayer::presentImage(const QImage &image) + { + QVideoFrame frame(image); + + if (!frame.isValid()) + return false; + + QVideoSurfaceFormat currentFormat = surface->surfaceFormat(); + + if (frame.pixelFormat() != currentFormat.pixelFormat() + || frame.size() != currentFormat.frameSize()) { + QVideoSurfaceFormat format(frame.size(), frame.pixelFormat()); + + if (!surface->start(format)) + return false; + } + + if (!surface->present(frame)) { + surface->stop(); + + return false; + } else { + return true; + } + } diff --git a/src/Qt/videowidget.cpp b/src/Qt/videowidget.cpp new file mode 100644 index 00000000..0a01c3f1 --- /dev/null +++ b/src/Qt/videowidget.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** + ** + ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + ** All rights reserved. + ** Contact: Nokia Corporation (qt-info@nokia.com) + ** + ** This file is part of the examples of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:BSD$ + ** You may use this file under the terms of the BSD license as follows: + ** + ** "Redistribution and use in source and binary forms, with or without + ** modification, are permitted provided that the following conditions are + ** met: + ** * Redistributions of source code must retain the above copyright + ** notice, this list of conditions and the following disclaimer. + ** * Redistributions in binary form must reproduce the above copyright + ** notice, this list of conditions and the following disclaimer in + ** the documentation and/or other materials provided with the + ** distribution. + ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor + ** the names of its contributors may be used to endorse or promote + ** products derived from this software without specific prior written + ** permission. + ** + ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + #include "../../include/Qt/videowidget.h" + #include "../../include/Qt/videowidgetsurface.h" + + #include + + VideoWidget::VideoWidget(QWidget *parent) + : QWidget(parent) + , surface(0) + { + setAutoFillBackground(false); + setAttribute(Qt::WA_NoSystemBackground, true); + setAttribute(Qt::WA_PaintOnScreen, true); + + QPalette palette = this->palette(); + palette.setColor(QPalette::Background, Qt::black); + setPalette(palette); + + setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + + surface = new VideoWidgetSurface(this); + } + + VideoWidget::~VideoWidget() + { + delete surface; + } + + QSize VideoWidget::sizeHint() const + { + return surface->surfaceFormat().sizeHint(); + } + + void VideoWidget::paintEvent(QPaintEvent *event) + { + QPainter painter(this); + + if (surface->isActive()) { + const QRect videoRect = surface->videoRect(); + + if (!videoRect.contains(event->rect())) { + QRegion region = event->region(); + region.subtract(videoRect); + + QBrush brush = palette().background(); + + foreach (const QRect &rect, region.rects()) + painter.fillRect(rect, brush); + } + + surface->paint(&painter); + } else { + painter.fillRect(event->rect(), palette().background()); + } + } + + void VideoWidget::resizeEvent(QResizeEvent *event) + { + QWidget::resizeEvent(event); + + surface->updateVideoRect(); + } diff --git a/src/Qt/videowidgetsurface.cpp b/src/Qt/videowidgetsurface.cpp new file mode 100644 index 00000000..46483fb5 --- /dev/null +++ b/src/Qt/videowidgetsurface.cpp @@ -0,0 +1,164 @@ + /**************************************************************************** + ** + ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + ** All rights reserved. + ** Contact: Nokia Corporation (qt-info@nokia.com) + ** + ** This file is part of the examples of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:BSD$ + ** You may use this file under the terms of the BSD license as follows: + ** + ** "Redistribution and use in source and binary forms, with or without + ** modification, are permitted provided that the following conditions are + ** met: + ** * Redistributions of source code must retain the above copyright + ** notice, this list of conditions and the following disclaimer. + ** * Redistributions in binary form must reproduce the above copyright + ** notice, this list of conditions and the following disclaimer in + ** the documentation and/or other materials provided with the + ** distribution. + ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor + ** the names of its contributors may be used to endorse or promote + ** products derived from this software without specific prior written + ** permission. + ** + ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + + #include "../../include/Qt/videowidgetsurface.h" + + #include + + VideoWidgetSurface::VideoWidgetSurface(QWidget *widget, QObject *parent) + : QAbstractVideoSurface(parent) + , widget(widget) + , imageFormat(QImage::Format_Invalid) + { + } + + QList VideoWidgetSurface::supportedPixelFormats( + QAbstractVideoBuffer::HandleType handleType) const + { + if (handleType == QAbstractVideoBuffer::NoHandle) { + return QList() + << QVideoFrame::Format_RGB32 + << QVideoFrame::Format_ARGB32 + << QVideoFrame::Format_ARGB32_Premultiplied + << QVideoFrame::Format_RGB565 + << QVideoFrame::Format_RGB555; + } else { + return QList(); + } + } + + bool VideoWidgetSurface::isFormatSupported( + const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const + { + Q_UNUSED(similar); + + const QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat()); + const QSize size = format.frameSize(); + + return imageFormat != QImage::Format_Invalid + && !size.isEmpty() + && format.handleType() == QAbstractVideoBuffer::NoHandle; + } + + bool VideoWidgetSurface::start(const QVideoSurfaceFormat &format) + { + const QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat()); + const QSize size = format.frameSize(); + + if (imageFormat != QImage::Format_Invalid && !size.isEmpty()) { + this->imageFormat = imageFormat; + imageSize = size; + sourceRect = format.viewport(); + + QAbstractVideoSurface::start(format); + + widget->updateGeometry(); + updateVideoRect(); + + return true; + } else { + return false; + } + } + + void VideoWidgetSurface::stop() + { + currentFrame = QVideoFrame(); + targetRect = QRect(); + + QAbstractVideoSurface::stop(); + + widget->update(); + } + + bool VideoWidgetSurface::present(const QVideoFrame &frame) + { + if (surfaceFormat().pixelFormat() != frame.pixelFormat() + || surfaceFormat().frameSize() != frame.size()) { + setError(IncorrectFormatError); + stop(); + + return false; + } else { + cout << "Paint new frame!" << endl; + currentFrame = frame; + + widget->repaint(targetRect); + + return true; + } + } + + void VideoWidgetSurface::updateVideoRect() + { + cout << "update rect" << endl; + //QSize size = surfaceFormat().sizeHint(); + QSize size(1280, 720); + //size.scale(widget->size().boundedTo(size), Qt::KeepAspectRatio); + + targetRect = QRect(QPoint(0, 0), size); + targetRect.moveCenter(widget->rect().center()); + + } + + void VideoWidgetSurface::paint(QPainter *painter) + { + if (currentFrame.map(QAbstractVideoBuffer::ReadOnly)) { + const QTransform oldTransform = painter->transform(); + + if (surfaceFormat().scanLineDirection() == QVideoSurfaceFormat::BottomToTop) { + painter->scale(1, -1); + painter->translate(0, -widget->height()); + } + + QImage image( + currentFrame.bits(), + currentFrame.width(), + currentFrame.height(), + currentFrame.bytesPerLine(), + imageFormat); + + painter->drawImage(targetRect, image, sourceRect); + + painter->setTransform(oldTransform); + + currentFrame.unmap(); + } + }