diff -r 000000000000 -r 1918ee327afb src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,334 @@
+/* This file is part of the KDE project.
+
+Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+
+This library is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation, either version 2.1 or 3 of the License.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this library. If not, see .
+*/
+
+
+#include "videorenderer_vmr9.h"
+
+#ifndef QT_NO_PHONON_VIDEO
+
+#include
+#include
+#include
+
+#ifndef Q_OS_WINCE
+#include
+#include
+#else
+#include
+#endif
+
+QT_BEGIN_NAMESPACE
+
+
+namespace Phonon
+{
+ namespace DS9
+ {
+ VideoRendererVMR9::~VideoRendererVMR9()
+ {
+ }
+
+ bool VideoRendererVMR9::isNative() const
+ {
+ return true;
+ }
+
+
+#ifdef Q_OS_WINCE
+ VideoRendererVMR9::VideoRendererVMR9(QWidget *target) : m_target(target)
+ {
+ m_target->setAttribute(Qt::WA_PaintOnScreen, true);
+ m_filter = Filter(CLSID_VideoRenderer, IID_IBaseFilter);
+ }
+
+ QSize VideoRendererVMR9::videoSize() const
+ {
+ LONG w = 0,
+ h = 0;
+ ComPointer basic(m_filter, IID_IBasicVideo);
+ if (basic) {
+ basic->GetVideoSize( &w, &h);
+ }
+ return QSize(w, h);
+ }
+
+ void VideoRendererVMR9::repaintCurrentFrame(QWidget * /*target*/, const QRect & /*rect*/)
+ {
+ //nothing to do here: the renderer paints everything
+ }
+
+ void VideoRendererVMR9::notifyResize(const QSize &size, Phonon::VideoWidget::AspectRatio aspectRatio,
+ Phonon::VideoWidget::ScaleMode scaleMode)
+ {
+ if (!isActive()) {
+ ComPointer basic(m_filter, IID_IBasicVideo);
+ if (basic) {
+ basic->SetDestinationPosition(0, 0, 0, 0);
+ }
+ return;
+ }
+
+ ComPointer video(m_filter, IID_IVideoWindow);
+
+ OAHWND owner;
+ HRESULT hr = video->get_Owner(&owner);
+ if (FAILED(hr)) {
+ return;
+ }
+
+ const OAHWND newOwner = reinterpret_cast(m_target->winId());
+ if (owner != newOwner) {
+ video->put_Owner(newOwner);
+ video->put_MessageDrain(newOwner);
+ video->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
+ }
+
+ //make sure the widget takes the whole size of the parent
+ video->SetWindowPosition(0, 0, size.width(), size.height());
+
+ const QSize vsize = videoSize();
+ internalNotifyResize(size, vsize, aspectRatio, scaleMode);
+
+ ComPointer basic(m_filter, IID_IBasicVideo);
+ if (basic) {
+ basic->SetDestinationPosition(m_dstX, m_dstY, m_dstWidth, m_dstHeight);
+ }
+ }
+
+ void VideoRendererVMR9::applyMixerSettings(qreal /*brightness*/, qreal /*contrast*/, qreal /*m_hue*/, qreal /*saturation*/)
+ {
+ //this can't be supported for WinCE
+ }
+
+ QImage VideoRendererVMR9::snapshot() const
+ {
+ ComPointer basic(m_filter, IID_IBasicVideo);
+ if (basic) {
+ LONG bufferSize = 0;
+ //1st we get the buffer size
+ basic->GetCurrentImage(&bufferSize, 0);
+
+ QByteArray buffer;
+ buffer.resize(bufferSize);
+ HRESULT hr = basic->GetCurrentImage(&bufferSize, reinterpret_cast(buffer.data()));
+
+ if (SUCCEEDED(hr)) {
+
+ const BITMAPINFOHEADER *bmi = reinterpret_cast(buffer.constData());
+
+ const int w = qAbs(bmi->biWidth),
+ h = qAbs(bmi->biHeight);
+
+ // Create image and copy data into image.
+ QImage ret(w, h, QImage::Format_RGB32);
+
+ if (!ret.isNull()) {
+ const char *data = buffer.constData() + bmi->biSize;
+ const int bytes_per_line = w * sizeof(QRgb);
+ for (int y = h - 1; y >= 0; --y) {
+ qMemCopy(ret.scanLine(y), //destination
+ data, //source
+ bytes_per_line);
+ data += bytes_per_line;
+ }
+ }
+ return ret;
+ }
+ }
+ return QImage();
+ }
+
+#else
+ VideoRendererVMR9::VideoRendererVMR9(QWidget *target) : m_target(target)
+ {
+ m_filter = Filter(CLSID_VideoMixingRenderer9, IID_IBaseFilter);
+ if (!m_filter) {
+ qWarning("the video widget could not be initialized correctly");
+ return;
+ }
+
+ ComPointer config(m_filter, IID_IVMRFilterConfig9);
+ Q_ASSERT(config);
+ HRESULT hr = config->SetRenderingMode(VMR9Mode_Windowless);
+ Q_ASSERT(SUCCEEDED(hr));
+ hr = config->SetNumberOfStreams(1); //for now we limit it to 1 input stream
+ Q_ASSERT(SUCCEEDED(hr));
+ ComPointer windowlessControl(m_filter, IID_IVMRWindowlessControl9);
+ windowlessControl->SetVideoClippingWindow(reinterpret_cast(target->winId()));
+ windowlessControl->SetAspectRatioMode(VMR9ARMode_None); //we're in control of the size
+ }
+
+ QImage VideoRendererVMR9::snapshot() const
+ {
+ ComPointer windowlessControl(m_filter, IID_IVMRWindowlessControl9);
+ if (windowlessControl) {
+ BYTE *buffer = 0;
+ HRESULT hr = windowlessControl->GetCurrentImage(&buffer);
+ if (SUCCEEDED(hr)) {
+
+ const BITMAPINFOHEADER *bmi = reinterpret_cast(buffer);
+ const int w = qAbs(bmi->biWidth),
+ h = qAbs(bmi->biHeight);
+
+ // Create image and copy data into image.
+ QImage ret(w, h, QImage::Format_RGB32);
+
+ if (!ret.isNull()) {
+ uchar *data = buffer + bmi->biSize;
+ const int bytes_per_line = w * sizeof(QRgb);
+ for (int y = h - 1; y >= 0; --y) {
+ qMemCopy(ret.scanLine(y), //destination
+ data, //source
+ bytes_per_line);
+ data += bytes_per_line;
+ }
+ }
+ ::CoTaskMemFree(buffer);
+ return ret;
+ }
+ }
+ return QImage();
+ }
+
+ QSize VideoRendererVMR9::videoSize() const
+ {
+ LONG w = 0,
+ h = 0;
+ ComPointer windowlessControl(m_filter, IID_IVMRWindowlessControl9);
+ if (windowlessControl) {
+ windowlessControl->GetNativeVideoSize( &w, &h, 0, 0);
+ }
+ return QSize(w, h);
+ }
+
+ void VideoRendererVMR9::repaintCurrentFrame(QWidget *target, const QRect &rect)
+ {
+ HDC hDC = target->getDC();
+ // repaint the video
+ ComPointer windowlessControl(m_filter, IID_IVMRWindowlessControl9);
+
+ HRESULT hr = windowlessControl ? windowlessControl->RepaintVideo(target->winId(), hDC) : E_POINTER;
+ if (FAILED(hr) || m_dstY > 0 || m_dstX > 0) {
+ const QColor c = target->palette().color(target->backgroundRole());
+ COLORREF color = RGB(c.red(), c.green(), c.blue());
+ HPEN hPen = ::CreatePen(PS_SOLID, 1, color);
+ HBRUSH hBrush = ::CreateSolidBrush(color);
+ ::SelectObject(hDC, hPen);
+ ::SelectObject(hDC, hBrush);
+ // repaint the video
+ if (FAILED(hr)) {
+ //black background : we use the Win32 API to avoid the ghost effect of the backing store
+ ::Rectangle(hDC, 0, 0, target->width(), target->height());
+ } else {
+ if (m_dstY > 0) {
+ ::Rectangle(hDC, 0, 0, target->width(), m_dstY); //top
+ ::Rectangle(hDC, 0, target->height() - m_dstY, target->width(), target->height()); //bottom
+ }
+ if (m_dstX > 0) {
+ ::Rectangle(hDC, 0, m_dstY, m_dstX, m_dstHeight + m_dstY); //left
+ ::Rectangle(hDC, m_dstWidth + m_dstX, m_dstY, target->width(), m_dstHeight + m_dstY); //right
+ }
+ }
+ ::DeleteObject(hPen);
+ ::DeleteObject(hBrush);
+ }
+ target->releaseDC(hDC);
+
+ }
+
+ void VideoRendererVMR9::notifyResize(const QSize &size, Phonon::VideoWidget::AspectRatio aspectRatio,
+ Phonon::VideoWidget::ScaleMode scaleMode)
+ {
+ if (!isActive()) {
+ RECT dummyRect = { 0, 0, 0, 0};
+ ComPointer windowlessControl(m_filter, IID_IVMRWindowlessControl9);
+ windowlessControl->SetVideoPosition(&dummyRect, &dummyRect);
+ return;
+ }
+
+
+ const QSize vsize = videoSize();
+ internalNotifyResize(size, vsize, aspectRatio, scaleMode);
+
+ RECT dstRectWin = { m_dstX, m_dstY, m_dstWidth + m_dstX, m_dstHeight + m_dstY};
+ RECT srcRectWin = { 0, 0, vsize.width(), vsize.height()};
+
+ ComPointer windowlessControl(m_filter, IID_IVMRWindowlessControl9);
+ if (windowlessControl) {
+ windowlessControl->SetVideoPosition(&srcRectWin, &dstRectWin);
+ }
+ }
+
+ void VideoRendererVMR9::applyMixerSettings(qreal brightness, qreal contrast, qreal hue, qreal saturation)
+ {
+ InputPin sink = BackendNode::pins(m_filter, PINDIR_INPUT).first();
+ OutputPin source;
+ if (FAILED(sink->ConnectedTo(source.pparam()))) {
+ return; //it must be connected to work
+ }
+
+ //get the mixer (used for brightness/contrast/saturation/hue)
+ ComPointer mixer(m_filter, IID_IVMRMixerControl9);
+ Q_ASSERT(mixer);
+
+ VMR9ProcAmpControl ctrl;
+ ctrl.dwSize = sizeof(ctrl);
+ ctrl.dwFlags = ProcAmpControl9_Contrast | ProcAmpControl9_Brightness | ProcAmpControl9_Saturation | ProcAmpControl9_Hue;
+ VMR9ProcAmpControlRange range;
+ range.dwSize = sizeof(range);
+
+ range.dwProperty = ProcAmpControl9_Contrast;
+ HRESULT hr = mixer->GetProcAmpControlRange(0, &range);
+ if (FAILED(hr)) {
+ return;
+ }
+ ctrl.Contrast = ((contrast < 0 ? range.MinValue : range.MaxValue) - range.DefaultValue) * qAbs(contrast) + range.DefaultValue;
+
+ //brightness
+ range.dwProperty = ProcAmpControl9_Brightness;
+ hr = mixer->GetProcAmpControlRange(0, &range);
+ if (FAILED(hr)) {
+ return;
+ }
+ ctrl.Brightness = ((brightness < 0 ? range.MinValue : range.MaxValue) - range.DefaultValue) * qAbs(brightness) + range.DefaultValue;
+
+ //saturation
+ range.dwProperty = ProcAmpControl9_Saturation;
+ hr = mixer->GetProcAmpControlRange(0, &range);
+ if (FAILED(hr)) {
+ return;
+ }
+ ctrl.Saturation = ((saturation < 0 ? range.MinValue : range.MaxValue) - range.DefaultValue) * qAbs(saturation) + range.DefaultValue;
+
+ //hue
+ range.dwProperty = ProcAmpControl9_Hue;
+ hr = mixer->GetProcAmpControlRange(0, &range);
+ if (FAILED(hr)) {
+ return;
+ }
+ ctrl.Hue = ((hue < 0 ? range.MinValue : range.MaxValue) - range.DefaultValue) * qAbs(hue) + range.DefaultValue;
+
+ //finally set the settings
+ mixer->SetProcAmpControl(0, &ctrl);
+ }
+#endif
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_PHONON_VIDEO