source: trunk/src/3rdparty/phonon/mmf/abstractvideoplayer.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: 13.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 <QDir>
20#include <QUrl>
21#include <QTimer>
22#include <QWidget>
23
24#include <coemain.h> // for CCoeEnv
25
26#include "abstractvideoplayer.h"
27#include "utils.h"
28
29#ifndef QT_NO_DEBUG
30#include "objectdump.h"
31#endif
32
33QT_BEGIN_NAMESPACE
34
35using namespace Phonon;
36using namespace Phonon::MMF;
37
38/*! \class MMF::AbstractVideoPlayer
39 \internal
40*/
41
42//-----------------------------------------------------------------------------
43// Constructor / destructor
44//-----------------------------------------------------------------------------
45
46MMF::AbstractVideoPlayer::AbstractVideoPlayer(MediaObject *parent, const AbstractPlayer *player)
47 : AbstractMediaPlayer(parent, player)
48 , m_wsSession(CCoeEnv::Static()->WsSession())
49 , m_screenDevice(*CCoeEnv::Static()->ScreenDevice())
50 , m_window(0)
51 , m_scaleWidth(1.0)
52 , m_scaleHeight(1.0)
53 , m_totalTime(0)
54{
55
56}
57
58void MMF::AbstractVideoPlayer::construct()
59{
60 TRACE_CONTEXT(AbstractVideoPlayer::AbstractVideoPlayer, EVideoApi);
61 TRACE_ENTRY_0();
62
63 if (m_videoOutput) {
64 initVideoOutput();
65 m_window = m_videoOutput->videoWindow();
66 }
67
68 createPlayer();
69
70 m_player->RegisterForVideoLoadingNotification(*this);
71
72 TRACE_EXIT_0();
73}
74
75MMF::AbstractVideoPlayer::~AbstractVideoPlayer()
76{
77 TRACE_CONTEXT(AbstractVideoPlayer::~AbstractVideoPlayer, EVideoApi);
78 TRACE_ENTRY_0();
79
80 // QObject destructor removes all signal-slot connections involving this
81 // object, so we do not need to disconnect from m_videoOutput here.
82
83 TRACE_EXIT_0();
84}
85
86CVideoPlayerUtility* MMF::AbstractVideoPlayer::nativePlayer() const
87{
88 return m_player.data();
89}
90
91//-----------------------------------------------------------------------------
92// Public API
93//-----------------------------------------------------------------------------
94
95void MMF::AbstractVideoPlayer::doPlay()
96{
97 TRACE_CONTEXT(AbstractVideoPlayer::doPlay, EVideoApi);
98
99 handlePendingParametersChanged();
100
101 m_player->Play();
102}
103
104void MMF::AbstractVideoPlayer::doPause()
105{
106 TRACE_CONTEXT(AbstractVideoPlayer::doPause, EVideoApi);
107
108 TRAPD(err, m_player->PauseL());
109 if (KErrNone != err && state() != ErrorState) {
110 TRACE("PauseL error %d", err);
111 setError(tr("Pause failed"), err);
112 }
113}
114
115void MMF::AbstractVideoPlayer::doStop()
116{
117 m_player->Stop();
118}
119
120void MMF::AbstractVideoPlayer::doSeek(qint64 ms)
121{
122 TRACE_CONTEXT(AbstractVideoPlayer::doSeek, EVideoApi);
123
124 TRAPD(err, m_player->SetPositionL(TTimeIntervalMicroSeconds(ms * 1000)));
125
126 if (KErrNone != err)
127 setError(tr("Seek failed"), err);
128}
129
130int MMF::AbstractVideoPlayer::setDeviceVolume(int mmfVolume)
131{
132 TRAPD(err, m_player->SetVolumeL(mmfVolume));
133 return err;
134}
135
136int MMF::AbstractVideoPlayer::openFile(const QString &fileName)
137{
138 const QHBufC nativeFileName(QDir::toNativeSeparators(fileName));
139 TRAPD(err, m_player->OpenFileL(*nativeFileName));
140 return err;
141}
142
143int MMF::AbstractVideoPlayer::openFile(RFile &file)
144{
145 TRAPD(err, m_player->OpenFileL(file));
146 return err;
147}
148
149int MMF::AbstractVideoPlayer::openUrl(const QString &url, int iap)
150{
151 TRAPD(err, m_player->OpenUrlL(qt_QString2TPtrC(url), iap));
152 return err;
153}
154
155int MMF::AbstractVideoPlayer::openDescriptor(const TDesC8 &des)
156{
157 TRAPD(err, m_player->OpenDesL(des));
158 return err;
159}
160
161int MMF::AbstractVideoPlayer::bufferStatus() const
162{
163 int result = 0;
164 TRAP_IGNORE(m_player->GetVideoLoadingProgressL(result));
165 return result;
166}
167
168void MMF::AbstractVideoPlayer::doClose()
169{
170 m_player->Close();
171}
172
173bool MMF::AbstractVideoPlayer::hasVideo() const
174{
175 return true;
176}
177
178qint64 MMF::AbstractVideoPlayer::getCurrentTime() const
179{
180 TRACE_CONTEXT(AbstractVideoPlayer::getCurrentTime, EVideoApi);
181
182 TTimeIntervalMicroSeconds us;
183 TRAPD(err, us = m_player->PositionL())
184
185 qint64 result = 0;
186
187 if (KErrNone == err) {
188 result = toMilliSeconds(us);
189 } else {
190 TRACE("PositionL error %d", err);
191
192 // If we don't cast away constness here, we simply have to ignore
193 // the error.
194 const_cast<AbstractVideoPlayer*>(this)->setError(tr("Getting position failed"), err);
195 }
196
197 return result;
198}
199
200qint64 MMF::AbstractVideoPlayer::totalTime() const
201{
202 return m_totalTime;
203}
204
205
206//-----------------------------------------------------------------------------
207// Public slots
208//-----------------------------------------------------------------------------
209
210void MMF::AbstractVideoPlayer::videoWindowChanged()
211{
212 TRACE_CONTEXT(AbstractVideoPlayer::videoWindowChanged, EVideoInternal);
213 TRACE_ENTRY("state %d", state());
214
215 m_window = m_videoOutput ? m_videoOutput->videoWindow() : 0;
216
217 if (m_videoOutput)
218 m_videoOutput->dump();
219
220 handleVideoWindowChanged();
221
222 TRACE_EXIT_0();
223}
224
225void MMF::AbstractVideoPlayer::aspectRatioChanged()
226{
227 TRACE_CONTEXT(AbstractVideoPlayer::aspectRatioChanged, EVideoInternal);
228 TRACE_ENTRY("state %d aspectRatio %d", state());
229
230 if (m_videoOutput)
231 updateScaleFactors(m_videoOutput->videoWindowSize());
232
233 TRACE_EXIT_0();
234}
235
236void MMF::AbstractVideoPlayer::scaleModeChanged()
237{
238 TRACE_CONTEXT(AbstractVideoPlayer::scaleModeChanged, EVideoInternal);
239 TRACE_ENTRY("state %d", state());
240
241 if (m_videoOutput)
242 updateScaleFactors(m_videoOutput->videoWindowSize());
243
244 TRACE_EXIT_0();
245}
246
247
248//-----------------------------------------------------------------------------
249// MVideoPlayerUtilityObserver callbacks
250//-----------------------------------------------------------------------------
251
252void MMF::AbstractVideoPlayer::MvpuoOpenComplete(TInt aError)
253{
254 TRACE_CONTEXT(AbstractVideoPlayer::MvpuoOpenComplete, EVideoApi);
255 TRACE_ENTRY("state %d error %d", state(), aError);
256
257 __ASSERT_ALWAYS(LoadingState == state() ||
258 progressiveDownloadStalled() && BufferingState == state(),
259 Utils::panic(InvalidStatePanic));
260
261 if (KErrNone == aError)
262 m_player->Prepare();
263 else
264 setError(tr("Opening clip failed"), aError);
265
266 TRACE_EXIT_0();
267}
268
269void MMF::AbstractVideoPlayer::MvpuoPrepareComplete(TInt aError)
270{
271 TRACE_CONTEXT(AbstractVideoPlayer::MvpuoPrepareComplete, EVideoApi);
272 TRACE_ENTRY("state %d error %d", state(), aError);
273
274 __ASSERT_ALWAYS(LoadingState == state() ||
275 progressiveDownloadStalled() && BufferingState == state(),
276 Utils::panic(InvalidStatePanic));
277
278 TRAPD(err, getVideoClipParametersL(aError));
279
280 if (KErrNone == err) {
281 if (m_videoOutput)
282 m_videoOutput->dump();
283
284 maxVolumeChanged(m_player->MaxVolume());
285
286 if (m_videoOutput)
287 m_videoOutput->setVideoSize(m_videoFrameSize);
288
289 prepareCompleted();
290 handlePendingParametersChanged();
291
292 emit totalTimeChanged(totalTime());
293 }
294
295 loadingComplete(aError);
296
297 TRACE_EXIT_0();
298}
299
300void MMF::AbstractVideoPlayer::getVideoClipParametersL(TInt aError)
301{
302 User::LeaveIfError(aError);
303
304 // Get frame size
305 TSize size;
306 m_player->VideoFrameSizeL(size);
307 m_videoFrameSize = QSize(size.iWidth, size.iHeight);
308
309 // Get duration
310 m_totalTime = toMilliSeconds(m_player->DurationL());
311}
312
313
314void MMF::AbstractVideoPlayer::MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError)
315{
316 TRACE_CONTEXT(AbstractVideoPlayer::MvpuoFrameReady, EVideoApi);
317 TRACE_ENTRY("state %d error %d", state(), aError);
318
319 Q_UNUSED(aFrame);
320 Q_UNUSED(aError); // suppress warnings in release builds
321
322 TRACE_EXIT_0();
323}
324
325void MMF::AbstractVideoPlayer::MvpuoPlayComplete(TInt aError)
326{
327 TRACE_CONTEXT(AbstractVideoPlayer::MvpuoPlayComplete, EVideoApi)
328 TRACE_ENTRY("state %d error %d", state(), aError);
329
330 // Call base class function which handles end of playback for both
331 // audio and video clips.
332 playbackComplete(aError);
333
334 TRACE_EXIT_0();
335}
336
337void MMF::AbstractVideoPlayer::MvpuoEvent(const TMMFEvent &aEvent)
338{
339 TRACE_CONTEXT(AbstractVideoPlayer::MvpuoEvent, EVideoApi);
340 TRACE_ENTRY("state %d", state());
341
342 Q_UNUSED(aEvent);
343
344 TRACE_EXIT_0();
345}
346
347
348//-----------------------------------------------------------------------------
349// MVideoLoadingObserver callbacks
350//-----------------------------------------------------------------------------
351
352void MMF::AbstractVideoPlayer::MvloLoadingStarted()
353{
354 bufferingStarted();
355}
356
357void MMF::AbstractVideoPlayer::MvloLoadingComplete()
358{
359 bufferingComplete();
360}
361
362
363//-----------------------------------------------------------------------------
364// Video window updates
365//-----------------------------------------------------------------------------
366
367void MMF::AbstractVideoPlayer::videoOutputChanged()
368{
369 TRACE_CONTEXT(AbstractVideoPlayer::videoOutputChanged, EVideoInternal);
370 TRACE_ENTRY_0();
371
372 if (m_videoOutput)
373 initVideoOutput();
374
375 videoWindowChanged();
376
377 TRACE_EXIT_0();
378}
379
380void MMF::AbstractVideoPlayer::initVideoOutput()
381{
382 Q_ASSERT(m_videoOutput);
383
384 bool connected = connect(
385 m_videoOutput, SIGNAL(videoWindowChanged()),
386 this, SLOT(videoWindowChanged())
387 );
388 Q_ASSERT(connected);
389
390 connected = connect(
391 m_videoOutput, SIGNAL(aspectRatioChanged()),
392 this, SLOT(aspectRatioChanged())
393 );
394 Q_ASSERT(connected);
395
396 connected = connect(
397 m_videoOutput, SIGNAL(scaleModeChanged()),
398 this, SLOT(scaleModeChanged())
399 );
400 Q_ASSERT(connected);
401
402 // Suppress warnings in release builds
403 Q_UNUSED(connected);
404
405 m_videoOutput->setVideoSize(m_videoFrameSize);
406}
407
408// Helper function for aspect ratio / scale mode handling
409QSize scaleToAspect(const QSize &srcRect, int aspectWidth, int aspectHeight)
410{
411 const qreal aspectRatio = qreal(aspectWidth) / aspectHeight;
412
413 int width = srcRect.width();
414 int height = srcRect.width() / aspectRatio;
415 if (height > srcRect.height()){
416 height = srcRect.height();
417 width = srcRect.height() * aspectRatio;
418 }
419 return QSize(width, height);
420}
421
422void MMF::AbstractVideoPlayer::updateScaleFactors(const QSize &windowSize, bool apply)
423{
424 Q_ASSERT(m_videoOutput);
425
426 if (m_videoFrameSize.isValid()) {
427 QRect videoRect;
428
429 // Calculate size of smallest rect which contains video frame size
430 // and conforms to aspect ratio
431 switch (m_videoOutput->aspectRatio()) {
432 case Phonon::VideoWidget::AspectRatioAuto:
433 videoRect.setSize(m_videoFrameSize);
434 break;
435
436 case Phonon::VideoWidget::AspectRatioWidget:
437 videoRect.setSize(windowSize);
438 break;
439
440 case Phonon::VideoWidget::AspectRatio4_3:
441 videoRect.setSize(scaleToAspect(m_videoFrameSize, 4, 3));
442 break;
443
444 case Phonon::VideoWidget::AspectRatio16_9:
445 videoRect.setSize(scaleToAspect(m_videoFrameSize, 16, 9));
446 break;
447 }
448
449 // Scale to fill the window width
450 const int windowWidth = windowSize.width();
451 const int windowHeight = windowSize.height();
452 const qreal windowScaleFactor = qreal(windowWidth) / videoRect.width();
453 int videoWidth = windowWidth;
454 int videoHeight = videoRect.height() * windowScaleFactor;
455
456 const qreal windowToVideoHeightRatio = qreal(windowHeight) / videoHeight;
457
458 switch (m_videoOutput->scaleMode()) {
459 case Phonon::VideoWidget::ScaleAndCrop:
460 if (videoHeight < windowHeight) {
461 videoWidth *= windowToVideoHeightRatio;
462 videoHeight = windowHeight;
463 }
464 break;
465 case Phonon::VideoWidget::FitInView:
466 default:
467 if (videoHeight > windowHeight) {
468 videoWidth *= windowToVideoHeightRatio;
469 videoHeight = windowHeight;
470 }
471 break;
472 }
473
474 // Calculate scale factors
475 m_scaleWidth = 100.0f * videoWidth / m_videoFrameSize.width();
476 m_scaleHeight = 100.0f * videoHeight / m_videoFrameSize.height();
477
478 if (apply)
479 parametersChanged(ScaleFactors);
480 }
481}
482
483void MMF::AbstractVideoPlayer::parametersChanged(VideoParameters parameters)
484{
485 if (state() == LoadingState || progressiveDownloadStalled() && BufferingState == state())
486 m_pendingChanges |= parameters;
487 else
488 handleParametersChanged(parameters);
489}
490
491void MMF::AbstractVideoPlayer::handlePendingParametersChanged()
492{
493 if (m_pendingChanges)
494 handleParametersChanged(m_pendingChanges);
495 m_pendingChanges = 0;
496}
497
498
499//-----------------------------------------------------------------------------
500// Metadata
501//-----------------------------------------------------------------------------
502
503int MMF::AbstractVideoPlayer::numberOfMetaDataEntries() const
504{
505 int numberOfEntries = 0;
506 TRAP_IGNORE(numberOfEntries = m_player->NumberOfMetaDataEntriesL());
507 return numberOfEntries;
508}
509
510QPair<QString, QString> MMF::AbstractVideoPlayer::metaDataEntry(int index) const
511{
512 CMMFMetaDataEntry *entry = 0;
513 QT_TRAP_THROWING(entry = m_player->MetaDataEntryL(index));
514 return QPair<QString, QString>(qt_TDesC2QString(entry->Name()), qt_TDesC2QString(entry->Value()));
515}
516
517QT_END_NAMESPACE
518
Note: See TracBrowser for help on using the repository browser.