source: trunk/src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 8.6 KB
Line 
1/* This file is part of the KDE project.
2
3Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4
5This library is free software: you can redistribute it and/or modify
6it under the terms of the GNU Lesser General Public License as published by
7the Free Software Foundation, either version 2.1 or 3 of the License.
8
9This library is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU Lesser General Public License for more details.
13
14You should have received a copy of the GNU Lesser General Public License
15along with this library. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18
19#include "videorenderer_vmr9.h"
20
21#ifndef QT_NO_PHONON_VIDEO
22
23#include <QtGui/QWidget>
24#include <QtGui/QPainter>
25
26#include <d3d9.h>
27#include <vmr9.h>
28
29QT_BEGIN_NAMESPACE
30
31
32namespace Phonon
33{
34 namespace DS9
35 {
36 VideoRendererVMR9::~VideoRendererVMR9()
37 {
38 }
39
40 bool VideoRendererVMR9::isNative() const
41 {
42 return true;
43 }
44
45
46 VideoRendererVMR9::VideoRendererVMR9(QWidget *target) : m_target(target)
47 {
48 m_filter = Filter(CLSID_VideoMixingRenderer9, IID_IBaseFilter);
49 if (!m_filter) {
50 return;
51 }
52
53 ComPointer<IVMRFilterConfig9> config(m_filter, IID_IVMRFilterConfig9);
54 Q_ASSERT(config);
55 HRESULT hr = config->SetRenderingMode(VMR9Mode_Windowless);
56 Q_ASSERT(SUCCEEDED(hr));
57 hr = config->SetNumberOfStreams(1); //for now we limit it to 1 input stream
58 Q_ASSERT(SUCCEEDED(hr));
59 ComPointer<IVMRWindowlessControl9> windowlessControl(m_filter, IID_IVMRWindowlessControl9);
60 windowlessControl->SetVideoClippingWindow(reinterpret_cast<HWND>(target->winId()));
61 windowlessControl->SetAspectRatioMode(VMR9ARMode_None); //we're in control of the size
62 }
63
64 QImage VideoRendererVMR9::snapshot() const
65 {
66 ComPointer<IVMRWindowlessControl9> windowlessControl(m_filter, IID_IVMRWindowlessControl9);
67 if (windowlessControl) {
68 BYTE *buffer = 0;
69 HRESULT hr = windowlessControl->GetCurrentImage(&buffer);
70 if (SUCCEEDED(hr)) {
71
72 const BITMAPINFOHEADER *bmi = reinterpret_cast<BITMAPINFOHEADER*>(buffer);
73 const int w = qAbs(bmi->biWidth),
74 h = qAbs(bmi->biHeight);
75
76 // Create image and copy data into image.
77 QImage ret(w, h, QImage::Format_RGB32);
78
79 if (!ret.isNull()) {
80 uchar *data = buffer + bmi->biSize;
81 const int bytes_per_line = w * sizeof(QRgb);
82 for (int y = h - 1; y >= 0; --y) {
83 qMemCopy(ret.scanLine(y), //destination
84 data, //source
85 bytes_per_line);
86 data += bytes_per_line;
87 }
88 }
89 ::CoTaskMemFree(buffer);
90 return ret;
91 }
92 }
93 return QImage();
94 }
95
96 QSize VideoRendererVMR9::videoSize() const
97 {
98 LONG w = 0,
99 h = 0;
100 ComPointer<IVMRWindowlessControl9> windowlessControl(m_filter, IID_IVMRWindowlessControl9);
101 if (windowlessControl) {
102 windowlessControl->GetNativeVideoSize( &w, &h, 0, 0);
103 }
104 return QSize(w, h);
105 }
106
107 void VideoRendererVMR9::repaintCurrentFrame(QWidget *target, const QRect &rect)
108 {
109 HDC hDC = target->getDC();
110 // repaint the video
111 ComPointer<IVMRWindowlessControl9> windowlessControl(m_filter, IID_IVMRWindowlessControl9);
112
113 HRESULT hr = windowlessControl ? windowlessControl->RepaintVideo(target->winId(), hDC) : E_POINTER;
114 if (FAILED(hr) || m_dstY > 0 || m_dstX > 0) {
115 const QColor c = target->palette().color(target->backgroundRole());
116 COLORREF color = RGB(c.red(), c.green(), c.blue());
117 HPEN hPen = ::CreatePen(PS_SOLID, 1, color);
118 HBRUSH hBrush = ::CreateSolidBrush(color);
119 ::SelectObject(hDC, hPen);
120 ::SelectObject(hDC, hBrush);
121 // repaint the video
122 if (FAILED(hr)) {
123 //black background : we use the Win32 API to avoid the ghost effect of the backing store
124 ::Rectangle(hDC, 0, 0, target->width(), target->height());
125 } else {
126 if (m_dstY > 0) {
127 ::Rectangle(hDC, 0, 0, target->width(), m_dstY); //top
128 ::Rectangle(hDC, 0, target->height() - m_dstY, target->width(), target->height()); //bottom
129 }
130 if (m_dstX > 0) {
131 ::Rectangle(hDC, 0, m_dstY, m_dstX, m_dstHeight + m_dstY); //left
132 ::Rectangle(hDC, m_dstWidth + m_dstX, m_dstY, target->width(), m_dstHeight + m_dstY); //right
133 }
134 }
135 ::DeleteObject(hPen);
136 ::DeleteObject(hBrush);
137 }
138 target->releaseDC(hDC);
139
140 }
141
142 void VideoRendererVMR9::notifyResize(const QSize &size, Phonon::VideoWidget::AspectRatio aspectRatio,
143 Phonon::VideoWidget::ScaleMode scaleMode)
144 {
145 if (!isActive()) {
146 RECT dummyRect = { 0, 0, 0, 0};
147 ComPointer<IVMRWindowlessControl9> windowlessControl(m_filter, IID_IVMRWindowlessControl9);
148 windowlessControl->SetVideoPosition(&dummyRect, &dummyRect);
149 return;
150 }
151
152
153 const QSize vsize = videoSize();
154 internalNotifyResize(size, vsize, aspectRatio, scaleMode);
155
156 RECT dstRectWin = { m_dstX, m_dstY, m_dstWidth + m_dstX, m_dstHeight + m_dstY};
157 RECT srcRectWin = { 0, 0, vsize.width(), vsize.height()};
158
159 ComPointer<IVMRWindowlessControl9> windowlessControl(m_filter, IID_IVMRWindowlessControl9);
160 if (windowlessControl) {
161 windowlessControl->SetVideoPosition(&srcRectWin, &dstRectWin);
162 }
163 }
164
165 void VideoRendererVMR9::applyMixerSettings(qreal brightness, qreal contrast, qreal hue, qreal saturation)
166 {
167 InputPin sink = BackendNode::pins(m_filter, PINDIR_INPUT).first();
168 OutputPin source;
169 if (FAILED(sink->ConnectedTo(source.pparam()))) {
170 return; //it must be connected to work
171 }
172
173 //get the mixer (used for brightness/contrast/saturation/hue)
174 ComPointer<IVMRMixerControl9> mixer(m_filter, IID_IVMRMixerControl9);
175 Q_ASSERT(mixer);
176
177 VMR9ProcAmpControl ctrl;
178 ctrl.dwSize = sizeof(ctrl);
179 ctrl.dwFlags = ProcAmpControl9_Contrast | ProcAmpControl9_Brightness | ProcAmpControl9_Saturation | ProcAmpControl9_Hue;
180 VMR9ProcAmpControlRange range;
181 range.dwSize = sizeof(range);
182
183 range.dwProperty = ProcAmpControl9_Contrast;
184 HRESULT hr = mixer->GetProcAmpControlRange(0, &range);
185 if (FAILED(hr)) {
186 return;
187 }
188 ctrl.Contrast = ((contrast < 0 ? range.MinValue : range.MaxValue) - range.DefaultValue) * qAbs(contrast) + range.DefaultValue;
189
190 //brightness
191 range.dwProperty = ProcAmpControl9_Brightness;
192 hr = mixer->GetProcAmpControlRange(0, &range);
193 if (FAILED(hr)) {
194 return;
195 }
196 ctrl.Brightness = ((brightness < 0 ? range.MinValue : range.MaxValue) - range.DefaultValue) * qAbs(brightness) + range.DefaultValue;
197
198 //saturation
199 range.dwProperty = ProcAmpControl9_Saturation;
200 hr = mixer->GetProcAmpControlRange(0, &range);
201 if (FAILED(hr)) {
202 return;
203 }
204 ctrl.Saturation = ((saturation < 0 ? range.MinValue : range.MaxValue) - range.DefaultValue) * qAbs(saturation) + range.DefaultValue;
205
206 //hue
207 range.dwProperty = ProcAmpControl9_Hue;
208 hr = mixer->GetProcAmpControlRange(0, &range);
209 if (FAILED(hr)) {
210 return;
211 }
212 ctrl.Hue = ((hue < 0 ? range.MinValue : range.MaxValue) - range.DefaultValue) * qAbs(hue) + range.DefaultValue;
213
214 //finally set the settings
215 mixer->SetProcAmpControl(0, &ctrl);
216 }
217 }
218}
219
220QT_END_NAMESPACE
221
222#endif //QT_NO_PHONON_VIDEO
Note: See TracBrowser for help on using the repository browser.