00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 const int kNumBuffers = 31;
00032 const int kNeedFreeFrames = 1;
00033 const int kPrebufferFramesNormal = 12;
00034 const int kPrebufferFramesSmall = 4;
00035 const int kKeepPrebuffer = 2;
00036
00037
00038
00039 #include <map>
00040 #include <vector>
00041 #include <iostream>
00042 #include <algorithm>
00043 using namespace std;
00044
00045 #include "DisplayRes.h"
00046 #include "yuv2rgb.h"
00047 #include "uitypes.h"
00048 #include "mythcontext.h"
00049 #include "filtermanager.h"
00050 #include "videoout_quartz.h"
00051
00052 #include "util-osx.h"
00053
00054 #import <CoreGraphics/CGBase.h>
00055 #import <CoreGraphics/CGDisplayConfiguration.h>
00056 #import <CoreGraphics/CGImage.h>
00057 #import <Carbon/Carbon.h>
00058 #import <QuickTime/QuickTime.h>
00059
00060 #include "osd.h"
00061 #include "osdsurface.h"
00062 #include "mythconfig.h"
00063 #include "mythverbose.h"
00064 #include "videodisplayprofile.h"
00065 #include "videoout_dvdv.h"
00066
00067 #define LOC QString("VideoOutputQuartz::")
00068 #define LOC_ERR QString("VideoOutputQuartz Error: ")
00069
00076 class VideoOutputQuartzView
00077 {
00078 public:
00079 VideoOutputQuartzView(QuartzData *pData);
00080 virtual ~VideoOutputQuartzView();
00081
00082 virtual bool Init(void);
00083
00084 virtual void SetFrameSkip(int numskip);
00085 virtual void Show(void);
00086
00087 virtual void InputChanged(int width, int height, float aspect,
00088 MythCodecID av_codec_id);
00089 virtual void MoveResize(QRect newRect);
00090
00091 virtual void EmbedChanged(bool embedded);
00092
00093 protected:
00094 virtual bool Begin(void);
00095 virtual void End(void);
00096 virtual void Transform(QRect newRect);
00097 virtual void BlankScreen(bool deferred);
00098
00099
00100 virtual bool BeginPort(void) = 0;
00101 virtual void EndPort(void) = 0;
00102
00103 char * name;
00104
00105 QuartzData * parentData;
00106
00107 CGrafPtr thePort;
00108 QRect m_desired;
00109 ImageSequence theCodec;
00110 RgnHandle theMask;
00111
00112 int frameSkip;
00113 int frameCounter;
00114 bool drawBlank;
00115
00119 bool applyMoveResize;
00120
00121 QMutex viewLock;
00122 };
00123
00124
00125
00126
00127
00128 OSStatus VoqvFloater_Callback(EventHandlerCallRef inHandlerCallRef,
00129 EventRef inEvent,
00130 void *inUserData);
00131
00132
00133
00134
00135 class QuartzData
00136 {
00137 public:
00138 QuartzData() :
00139 srcWidth(0), srcHeight(0),
00140 srcAspect(1.3333f), srcMode(kAspect_Off),
00141
00142 pixelData(0), pixelSize(0),
00143 pixelLock(),
00144
00145 window(0),
00146 screen(0), refreshRate(60.0f),
00147
00148 drawInWindow(false), windowedMode(false),
00149 scaleUpVideo(false), correctGamma(false),
00150 convertI420to2VUY(NULL),
00151
00152 embeddedView(NULL), dvdv(NULL)
00153 {;}
00154 ~QuartzData() { ClearViews(); }
00155
00156 void ClearViews(void)
00157 {
00158 vector<VideoOutputQuartzView*>::iterator it = views.begin();
00159 for (; it != views.end(); ++it)
00160 delete *it;
00161 views.clear();
00162 }
00163
00164
00165 int srcWidth,
00166 srcHeight;
00167 float srcAspect;
00168 int srcMode;
00169
00170
00171 ImageDescriptionHandle imgDesc;
00172 char * pixelData;
00173 size_t pixelSize;
00174 QMutex pixelLock;
00175
00176
00177 WindowRef window;
00178 Rect windowBounds;
00179 CGDirectDisplayID screen;
00180 float refreshRate;
00181
00182
00183 bool drawInWindow;
00184 bool windowedMode;
00185 bool scaleUpVideo;
00186 bool correctGamma;
00187 conv_i420_2vuy_fun convertI420to2VUY;
00188
00189
00190 vector<VideoOutputQuartzView*> views;
00191
00192
00193 VideoOutputQuartzView * embeddedView;
00194
00195 DVDV * dvdv;
00196 };
00197
00198 VideoOutputQuartzView::VideoOutputQuartzView(QuartzData *pData)
00199 : name(NULL), parentData(pData),
00200 thePort(NULL), theCodec(0), theMask(NULL), frameSkip(1), frameCounter(0),
00201 drawBlank(true), applyMoveResize(false)
00202 {
00203 }
00204
00205 VideoOutputQuartzView::~VideoOutputQuartzView()
00206 {
00207 End();
00208 }
00209
00212 bool VideoOutputQuartzView::Begin(void)
00213 {
00214 viewLock.lock();
00215 if (!thePort)
00216 {
00217 VERBOSE(VB_IMPORTANT,
00218 QString("VOQV::Begin(%1) - No graphics port available")
00219 .arg(name));
00220 viewLock.unlock();
00221 return false;
00222 }
00223
00224
00225 Rect portBounds;
00226 GetPortBounds(thePort, &portBounds);
00227 VERBOSE(VB_PLAYBACK, QString("%0Viewport currently %1,%2 -> %3,%4")
00228 .arg(name).arg(portBounds.left).arg(portBounds.top)
00229 .arg(portBounds.right).arg(portBounds.bottom));
00230
00231 if (!parentData->embeddedView)
00232 {
00233 m_desired.setWidth(portBounds.right);
00234 m_desired.setHeight(portBounds.bottom);
00235 }
00236
00237
00238 if (DecompressSequenceBeginS(&theCodec,
00239 parentData->imgDesc,
00240 NULL,
00241 0,
00242 thePort,
00243 NULL,
00244 NULL,
00245 NULL,
00246 srcCopy,
00247 theMask,
00248 0,
00249 codecNormalQuality,
00250 bestSpeedCodec))
00251 {
00252 VERBOSE(VB_IMPORTANT,
00253 QString("VOQV::Begin(%1) - DecompressSequenceBeginS failed")
00254 .arg(name));
00255 viewLock.unlock();
00256 return false;
00257 }
00258
00259
00260 if (!parentData->correctGamma)
00261 QTSetPixMapHandleRequestedGammaLevel(GetPortPixMap(thePort),
00262 kQTUseSourceGammaLevel);
00263
00264 SetDSequenceFlags(theCodec,
00265 codecDSequenceFlushInsteadOfDirtying,
00266 codecDSequenceFlushInsteadOfDirtying);
00267 viewLock.unlock();
00268
00269
00270 Transform(m_desired);
00271
00272 return true;
00273 }
00274
00276 void VideoOutputQuartzView::End(void)
00277 {
00278 viewLock.lock();
00279
00280 if (theCodec)
00281 {
00282 CDSequenceEnd(theCodec);
00283 theCodec = 0;
00284 if (theMask)
00285 {
00286 DisposeRgn(theMask);
00287 theMask = NULL;
00288 }
00289 }
00290 viewLock.unlock();
00291 }
00292
00294 void VideoOutputQuartzView::Transform(QRect newRect)
00295 {
00296 MatrixRecord matrix;
00297 SetIdentityMatrix(&matrix);
00298
00299 int x, y, w, h, sw, sh;
00300 x = newRect.left();
00301 y = newRect.top();
00302 w = newRect.width();
00303 h = newRect.height();
00304 sw = parentData->srcWidth;
00305 sh = parentData->srcHeight;
00306
00307
00308 Fixed one, zero;
00309 one = Long2Fix(1);
00310 zero = Long2Fix(0);
00311
00312 VERBOSE(VB_PLAYBACK, QString("%0Viewport is %1 x %2")
00313 .arg(name).arg(w).arg(h));
00314 VERBOSE(VB_PLAYBACK, QString("%0Image is %1 x %2")
00315 .arg(name).arg(sw).arg(sh));
00316
00317 double hscale = (double) w / sw;
00318 double vscale = (double) h / sh;
00319
00320
00321 if (!parentData->scaleUpVideo)
00322 {
00323 double maxScale = fmax(hscale, vscale);
00324 hscale /= maxScale;
00325 vscale /= maxScale;
00326 }
00327
00328 if ((hscale < 0.99) || (hscale > 1.01) ||
00329 (vscale < 0.99) || (vscale > 1.01))
00330 {
00331 VERBOSE(VB_PLAYBACK, QString("%0Scaling to %1 x %2 of original")
00332 .arg(name).arg(hscale).arg(vscale));
00333 ScaleMatrix(&matrix,
00334 X2Fix(hscale),
00335 X2Fix(vscale),
00336 zero, zero);
00337
00338
00339 sw = (int)(sw * hscale);
00340 sh = (int)(sh * vscale);
00341 }
00342
00343
00344 if ((h != sh) || (w != sw))
00345 {
00346 VERBOSE(VB_PLAYBACK, QString("%0Centering with %1, %2")
00347 .arg(name).arg((w - sw)/2.0).arg((h - sh)/2.0));
00348 TranslateMatrix(&matrix, X2Fix((w - sw) / 2.0), X2Fix((h - sh) / 2.0));
00349 }
00350
00351
00352 #ifdef USING_DVDV
00353 if (parentData->dvdv)
00354 {
00355 parentData->dvdv->MoveResize(
00356 0, 0, parentData->srcWidth, parentData->srcHeight,
00357 (int)((w - sw) / 2.0), (int)((h - sh) / 2.0), sw, sh);
00358 }
00359 #endif // USING_DVDV
00360
00361
00362 if (x || y)
00363 {
00364 VERBOSE(VB_PLAYBACK, QString("%0Translating to %1, %2")
00365 .arg(name).arg(x).arg(y));
00366 TranslateMatrix(&matrix, Long2Fix(x), Long2Fix(y));
00367 }
00368
00369
00370 viewLock.lock();
00371 SetDSequenceMatrix(theCodec, &matrix);
00372 viewLock.unlock();
00373 BlankScreen(true);
00374 }
00375
00376 void VideoOutputQuartzView::BlankScreen(bool deferred)
00377 {
00378 if (deferred)
00379 {
00380 drawBlank = true;
00381 return;
00382 }
00383
00384 viewLock.lock();
00385 if (thePort)
00386 {
00387 SetPort(thePort);
00388
00389
00390 Rect clipRect;
00391 if (m_desired.width() && m_desired.height())
00392 {
00393 clipRect.left = m_desired.left();
00394 clipRect.top = m_desired.top();
00395 clipRect.right = m_desired.right();
00396 clipRect.bottom = m_desired.bottom();
00397 }
00398 else
00399 {
00400 GetPortBounds(thePort, &clipRect);
00401 }
00402 RgnHandle clipRgn = NewRgn();
00403 RectRgn(clipRgn, &clipRect);
00404
00405
00406 RGBColor rgbBlack = { 0, 0, 0 };
00407 RGBBackColor(&rgbBlack);
00408 EraseRect(&clipRect);
00409 QDFlushPortBuffer(thePort, clipRgn);
00410
00411 drawBlank = false;
00412 }
00413 viewLock.unlock();
00414 }
00415
00416 bool VideoOutputQuartzView::Init(void)
00417 {
00418 return (BeginPort() && Begin());
00419 }
00420
00421 void VideoOutputQuartzView::SetFrameSkip(int numskip)
00422 {
00423 frameSkip = numskip + 1;
00424 }
00425
00426 void VideoOutputQuartzView::Show(void)
00427 {
00428 if (drawBlank)
00429 BlankScreen(false);
00430
00431
00432
00433 frameCounter = (frameCounter + 1) % frameSkip;
00434 if (frameCounter)
00435 return;
00436
00437 viewLock.lock();
00438 if (theCodec && thePort && parentData->pixelData)
00439 {
00440 CodecFlags outFlags;
00441
00442
00443 if (DecompressSequenceFrameWhen(theCodec,
00444 (Ptr)parentData->pixelData,
00445 parentData->pixelSize,
00446 0,
00447 &outFlags,
00448 NULL,
00449 NULL))
00450 {
00451 VERBOSE(VB_IMPORTANT,
00452 QString("VOQV::Show(%1)- DecompressSequenceFrameWhen failed")
00453 .arg(name));
00454 }
00455 }
00456 viewLock.unlock();
00457 }
00458
00459 void VideoOutputQuartzView::InputChanged(int width, int height, float aspect,
00460 MythCodecID av_codec_id)
00461 {
00462 (void)width;
00463 (void)height;
00464 (void)aspect;
00465 (void)av_codec_id;
00466
00467
00468 End();
00469 Begin();
00470 }
00471
00472 void VideoOutputQuartzView::MoveResize(QRect newRect)
00473 {
00474 if (applyMoveResize)
00475 Transform(newRect);
00476 }
00477
00480 void VideoOutputQuartzView::EmbedChanged(bool embedded)
00481 {
00482
00483 (void)embedded;
00484 }
00485
00489 class VoqvMainWindow : public VideoOutputQuartzView
00490 {
00491 public:
00492 VoqvMainWindow(QuartzData *pData, float alphaBlend = 1.0)
00493 : VideoOutputQuartzView(pData)
00494 {
00495 alpha = fminf(1.0, fmaxf(0.0, alphaBlend));
00496 applyMoveResize = true;
00497 name = "Main window: ";
00498 };
00499
00500 ~VoqvMainWindow()
00501 {
00502 End();
00503 EndPort();
00504 };
00505
00506 protected:
00507 float alpha;
00508
00509 bool BeginPort(void)
00510 {
00511 viewLock.lock();
00512 thePort = GetWindowPort(parentData->window);
00513 if (!thePort)
00514 {
00515 VERBOSE(VB_IMPORTANT,
00516 "VoqvMainWindow::BeginPort() - GetWindowPort failed");
00517 viewLock.unlock();
00518 return false;
00519 }
00520
00521 SetWindowAlpha(parentData->window, alpha);
00522 RGBColor black = { 0, 0, 0 };
00523 SetWindowContentColor(parentData->window, &black);
00524 viewLock.unlock();
00525 return true;
00526 };
00527
00528 bool Begin(void)
00529 {
00530 bool ret = VideoOutputQuartzView::Begin();
00531
00532 if (ret && (alpha < 0.99))
00533 {
00534
00535 RGBColor black = { 0, 0, 0 };
00536 viewLock.lock();
00537 SetDSequenceTransferMode(theCodec, transparent, &black);
00538 viewLock.unlock();
00539 }
00540 return ret;
00541 };
00542
00543 void EndPort(void)
00544 {
00545 viewLock.lock();
00546 SetWindowAlpha(parentData->window, 1.0);
00547 thePort = NULL;
00548 viewLock.unlock();
00549 };
00550
00551
00552 void EmbedChanged(bool embedded)
00553 {
00554 if (embedded)
00555 {
00556 End();
00557 EndPort();
00558 }
00559 else
00560 {
00561 BeginPort();
00562 Begin();
00563 }
00564 };
00565 };
00566
00570 class VoqvEmbedded : public VideoOutputQuartzView
00571 {
00572 public:
00573 VoqvEmbedded(QuartzData *pData, int x, int y, int w, int h)
00574 : VideoOutputQuartzView(pData)
00575 {
00576 m_desired = QRect(x, y, w, h);
00577 name = "Embedded window: ";
00578 };
00579
00580 ~VoqvEmbedded()
00581 {
00582 End();
00583 EndPort();
00584 };
00585
00586 protected:
00587 bool BeginPort(void)
00588 {
00589 viewLock.lock();
00590 thePort = GetWindowPort(parentData->window);
00591 if (!thePort)
00592 {
00593 VERBOSE(VB_IMPORTANT,
00594 "VoqvEmbedded::BeginPort() - GetWindowPort failed");
00595 viewLock.unlock();
00596 return false;
00597 }
00598
00599
00600 Rect portBounds;
00601 GetPortBounds(thePort, &portBounds);
00602 InvalWindowRect(parentData->window, &portBounds);
00603
00604
00605 viewLock.unlock();
00606 return true;
00607 };
00608
00609 void EndPort(void)
00610 {
00611 viewLock.lock();
00612 thePort = NULL;
00613 viewLock.unlock();
00614 };
00615 };
00616
00620 class VoqvFullscreen : public VideoOutputQuartzView
00621 {
00622 public:
00623 VoqvFullscreen(QuartzData *pData)
00624 : VideoOutputQuartzView(pData)
00625 {
00626 applyMoveResize = true;
00627 name = "Full screen: ";
00628 };
00629
00630 ~VoqvFullscreen()
00631 {
00632 End();
00633 EndPort();
00634 };
00635
00636 protected:
00637 CGDirectDisplayID d;
00638
00639 bool BeginPort(void)
00640 {
00641 viewLock.lock();
00642 d = parentData->screen;
00643
00644 if (CGDisplayCapture(d) != CGDisplayNoErr)
00645 {
00646 VERBOSE(VB_IMPORTANT,
00647 "VoqvFullScreen::BeginPort() - Could not capture display");
00648 viewLock.unlock();
00649 return false;
00650 }
00651
00652
00653 if (gContext->GetNumSetting("UseVideoModes", 0))
00654 {
00655 DisplayRes *disp = DisplayRes::GetDisplayRes();
00656 disp->SwitchToVideo(parentData->srcWidth, parentData->srcHeight);
00657 }
00658
00659 CGDisplayHideCursor(d);
00660
00661 thePort = CreateNewPortForCGDisplayID((UInt32)d);
00662 if (!thePort)
00663 {
00664 VERBOSE(VB_IMPORTANT, "VoqvFullScreen::BeginPort() - "
00665 "CreateNewPortForCGDisplayID failed");
00666 viewLock.unlock();
00667 return false;
00668 }
00669
00670 viewLock.unlock();
00671 return true;
00672 };
00673
00674 void EndPort(void)
00675 {
00676 viewLock.lock();
00677 if (thePort)
00678 {
00679 DisposePort(thePort);
00680 thePort = NULL;
00681 }
00682
00683
00684 if (gContext->GetNumSetting("UseVideoModes", 0))
00685 DisplayRes::GetDisplayRes()->SwitchToGUI();
00686
00687 if (d)
00688 {
00689 CGDisplayShowCursor(d);
00690 CGDisplayRelease(d);
00691 d = NULL;
00692 }
00693 viewLock.unlock();
00694 };
00695
00696
00697
00698 void EmbedChanged(bool embedded)
00699 {
00700 if (embedded)
00701 {
00702 End();
00703 EndPort();
00704 }
00705 else
00706 {
00707 BeginPort();
00708 Begin();
00709 }
00710 };
00711 };
00712
00716 class VoqvDock : public VideoOutputQuartzView
00717 {
00718 public:
00719 VoqvDock(QuartzData *pData)
00720 : VideoOutputQuartzView(pData)
00721 {
00722 name = "Dock icon: ";
00723 };
00724
00725 ~VoqvDock()
00726 {
00727 End();
00728 EndPort();
00729 };
00730
00731 protected:
00732 bool BeginPort(void)
00733 {
00734 thePort = BeginQDContextForApplicationDockTile();
00735 if (!thePort)
00736 {
00737 VERBOSE(VB_IMPORTANT, "VoqvDock::BeginPort() - "
00738 "BeginQDContextForApplicationDockTile failed");
00739 return false;
00740 }
00741 return true;
00742 };
00743
00744 void EndPort(void)
00745 {
00746 viewLock.lock();
00747 EndQDContextForApplicationDockTile(thePort);
00748 thePort = NULL;
00749 RestoreApplicationDockTileImage();
00750 viewLock.unlock();
00751 };
00752 };
00753
00758 class VoqvFloater : public VideoOutputQuartzView
00759 {
00760 public:
00761 VoqvFloater(QuartzData *pData, float alphaBlend = 0.5)
00762 : VideoOutputQuartzView(pData)
00763 {
00764 alpha = fminf(1.0, fmaxf(0.0, alphaBlend));
00765 resizing = false;
00766 name = "Floating window: ";
00767 };
00768
00769 ~VoqvFloater()
00770 {
00771 End();
00772 EndPort();
00773 };
00774
00775 void Show(void)
00776 {
00777 if (resizing)
00778 return;
00779
00780 VideoOutputQuartzView::Show();
00781 }
00782
00783 void ResizeChanged(bool startResizing)
00784 {
00785 if (!startResizing)
00786 {
00787
00788 Rect curBounds;
00789 GetPortBounds(thePort, &curBounds);
00790 m_desired.setWidth(curBounds.right - curBounds.left);
00791 m_desired.setHeight(curBounds.bottom - curBounds.top);
00792 SetRectRgn(theMask, m_desired.left(), m_desired.top(),
00793 m_desired.width(), m_desired.height());
00794 Transform(m_desired);
00795 }
00796 resizing = startResizing;
00797 }
00798
00799 protected:
00800 ToolboxObjectClassRef myClass;
00801 WindowRef window;
00802 float alpha;
00803 bool resizing;
00804
00805 bool BeginPort(void)
00806 {
00807 viewLock.lock();
00808
00809 Rect bounds;
00810 bounds.top = bounds.left = bounds.right = bounds.bottom = 50;
00811 switch ((int)(10 * parentData->srcAspect))
00812 {
00813 case 17:
00814 case 18:
00815 bounds.right += 320;
00816 bounds.bottom += 180;
00817 break;
00818 case 13:
00819 bounds.right += 280;
00820 bounds.bottom += 210;
00821 break;
00822 default:
00823 bounds.right += CGDisplayPixelsWide(parentData->screen) / 3;
00824 bounds.bottom += CGDisplayPixelsHigh(parentData->screen) / 3;
00825 }
00826
00827
00828 EventHandlerUPP myUPP = NewEventHandlerUPP(VoqvFloater_Callback);
00829 EventTypeSpec defEvents[] =
00830 { { kEventClassWindow, kEventWindowHitTest },
00831 { kEventClassWindow, kEventWindowDrawFrame },
00832 { kEventClassWindow, kEventWindowClickResizeRgn } };
00833 RegisterToolboxObjectClass(CFSTR("org.mythtv.myth.VoqvFloater"),
00834 NULL,
00835 3,
00836 defEvents,
00837 myUPP,
00838 this,
00839 &myClass);
00840 WindowDefSpec mySpec;
00841 mySpec.defType = kWindowDefObjectClass;
00842 mySpec.u.classRef = myClass;
00843 if (CreateCustomWindow(&mySpec,
00844 kUtilityWindowClass,
00845 kWindowNoShadowAttribute |
00846 kWindowResizableAttribute |
00847 kWindowStandardHandlerAttribute,
00848 &bounds,
00849 &window))
00850 {
00851 VERBOSE(VB_IMPORTANT,
00852 "VoqvFloater::BeginPort() - CreateCustomWindow failed");
00853 viewLock.unlock();
00854 return false;
00855 }
00856 SetWindowAlpha(window, alpha);
00857 RGBColor black = { 0, 0, 0 };
00858 SetWindowContentColor(window, &black);
00859
00860 thePort = GetWindowPort(window);
00861 if (!thePort)
00862 {
00863 VERBOSE(VB_IMPORTANT,
00864 "VoqvFloater::BeginPort() - GetWindowPort failed");
00865 viewLock.unlock();
00866 return false;
00867 }
00868
00869 viewLock.unlock();
00870 ShowWindow(window);
00871
00872 SelectWindow(parentData->window);
00873
00874 return true;
00875 };
00876
00877 bool Begin(void)
00878 {
00879 bool ret = VideoOutputQuartzView::Begin();
00880
00881 if (ret && (alpha < 0.99))
00882 {
00883
00884 RGBColor black = { 0, 0, 0 };
00885 viewLock.lock();
00886 SetDSequenceTransferMode(theCodec, transparent, &black);
00887 viewLock.unlock();
00888 }
00889 return ret;
00890 };
00891
00892 void EndPort(void)
00893 {
00894 viewLock.lock();
00895 thePort = NULL;
00896 if (window)
00897 {
00898 DisposeWindow(window);
00899 window = NULL;
00900 }
00901 UnregisterToolboxObjectClass(myClass);
00902 viewLock.unlock();
00903 };
00904
00905
00906 void EmbedChanged(bool embedded)
00907 {
00908 if (embedded)
00909 {
00910 End();
00911 HideWindow(window);
00912 }
00913 else
00914 {
00915 ShowWindow(window);
00916 Begin();
00917 }
00918 };
00919 };
00920
00921
00922 OSStatus VoqvFloater_Callback(EventHandlerCallRef inHandlerCallRef,
00923 EventRef inEvent,
00924 void *inUserData)
00925 {
00926 (void)inHandlerCallRef;
00927 VoqvFloater *floater = (VoqvFloater *)inUserData;
00928 WindowRef window;
00929 Point mouseLoc;
00930 Rect winLoc;
00931 WindowDefPartCode where;
00932
00933 switch (GetEventKind(inEvent))
00934 {
00935 case kEventWindowHitTest:
00936
00937 GetEventParameter(inEvent,
00938 kEventParamDirectObject,
00939 typeWindowRef,
00940 NULL,
00941 sizeof(WindowRef),
00942 NULL,
00943 &window);
00944 GetEventParameter(inEvent,
00945 kEventParamMouseLocation,
00946 typeQDPoint,
00947 NULL,
00948 sizeof(mouseLoc),
00949 NULL,
00950 &mouseLoc);
00951
00952
00953 GetWindowBounds(window,
00954 kWindowGlobalPortRgn,
00955 &winLoc);
00956 where = wInDrag;
00957 if (mouseLoc.h > (winLoc.right - 12) &&
00958 mouseLoc.v > (winLoc.bottom - 12))
00959 {
00960 where = wInGrow;
00961 }
00962 SetEventParameter(inEvent,
00963 kEventParamWindowDefPart,
00964 typeWindowDefPartCode,
00965 sizeof(WindowDefPartCode),
00966 &where);
00967 break;
00968
00969 case kEventWindowClickResizeRgn:
00970
00971 GetEventParameter(inEvent,
00972 kEventParamDirectObject,
00973 typeWindowRef,
00974 NULL,
00975 sizeof(WindowRef),
00976 NULL,
00977 &window);
00978 GetEventParameter(inEvent,
00979 kEventParamMouseLocation,
00980 typeQDPoint,
00981 NULL,
00982 sizeof(mouseLoc),
00983 NULL,
00984 &mouseLoc);
00985
00986 floater->ResizeChanged(true);
00987 ResizeWindow(window, mouseLoc, NULL, NULL);
00988 floater->ResizeChanged(false);
00989 break;
00990 }
00991 return noErr;
00992 }
00993
00994
00998 class VoqvDesktop : public VideoOutputQuartzView
00999 {
01000 public:
01001 VoqvDesktop(QuartzData *pData)
01002 : VideoOutputQuartzView(pData)
01003 {
01004 name = "Desktop: ";
01005 };
01006
01007 ~VoqvDesktop()
01008 {
01009 End();
01010 EndPort();
01011 };
01012
01013 protected:
01014 WindowRef window;
01015
01016 bool BeginPort(void)
01017 {
01018 viewLock.lock();
01019
01020 Rect bounds;
01021 bounds.top = bounds.left = 0;
01022 bounds.right = CGDisplayPixelsWide(parentData->screen);
01023 bounds.bottom = CGDisplayPixelsHigh(parentData->screen);
01024 if (CreateNewWindow(kPlainWindowClass,
01025 kWindowNoShadowAttribute |
01026 kWindowOpaqueForEventsAttribute,
01027 &bounds,
01028 &window))
01029 {
01030 VERBOSE(VB_IMPORTANT,
01031 "VoqvDesktop::BeginPort() - CreateNewWindow failed");
01032 viewLock.unlock();
01033 return false;
01034 }
01035 WindowGroupRef winGroup;
01036 if (CreateWindowGroup(0, &winGroup))
01037 {
01038 VERBOSE(VB_IMPORTANT,
01039 "VoqvDesktop::BeginPort() - CreateWindowGroup failed");
01040 viewLock.unlock();
01041 return false;
01042 }
01043 SetWindowGroupLevel(winGroup, kCGDesktopIconWindowLevel - 1);
01044 SetWindowGroup(window, winGroup);
01045 RGBColor black = { 0, 0, 0 };
01046 SetWindowContentColor(window, &black);
01047
01048 thePort = GetWindowPort(window);
01049 if (!thePort)
01050 {
01051 VERBOSE(VB_IMPORTANT,
01052 "VoqvDesktop::BeginPort() - GetWindowPort failed");
01053 viewLock.unlock();
01054 return false;
01055 }
01056 viewLock.unlock();
01057 ShowWindow(window);
01058
01059 SelectWindow(parentData->window);
01060
01061 return true;
01062 };
01063
01064 void EndPort(void)
01065 {
01066 viewLock.lock();
01067 thePort = NULL;
01068 if (window)
01069 {
01070 DisposeWindow(window);
01071 window = NULL;
01072 }
01073 viewLock.unlock();
01074 };
01075 };
01076
01080 VideoOutputQuartz::VideoOutputQuartz(
01081 MythCodecID _myth_codec_id, void *codec_priv) :
01082 VideoOutput(), Started(false), data(new QuartzData()),
01083 myth_codec_id(_myth_codec_id)
01084 {
01085 init(&pauseFrame, FMT_YV12, NULL, 0, 0, 0, 0);
01086 SetDVDVDecoder((DVDV*)codec_priv);
01087 }
01088
01089 VideoOutputQuartz::~VideoOutputQuartz()
01090 {
01091 if (data)
01092 {
01093 Exit();
01094
01095 delete data;
01096 data = NULL;
01097 }
01098 }
01099
01100 void VideoOutputQuartz::VideoAspectRatioChanged(float aspect)
01101 {
01102 VERBOSE(VB_PLAYBACK, (LOC + "VideoAspectRatioChanged(aspect=%1) [was %2]")
01103 .arg(aspect).arg(data->srcAspect));
01104
01105 VideoOutput::VideoAspectRatioChanged(aspect);
01106
01107 data->srcAspect = aspect;
01108 data->srcMode = db_aspectoverride;
01109 }
01110
01111
01112 void VideoOutputQuartz::Zoom(ZoomDirection direction)
01113 {
01114 VERBOSE(VB_PLAYBACK, (LOC + "Zoom(direction=%1)").arg(direction));
01115
01116 VideoOutput::Zoom(direction);
01117 MoveResize();
01118 }
01119
01120 void VideoOutputQuartz::MoveResize(void)
01121 {
01122
01123
01124 VideoOutput::MoveResize();
01125
01126 vector<VideoOutputQuartzView*>::iterator it;
01127 for (it = data->views.begin(); it != data->views.end(); ++it)
01128 {
01129 (*it)->MoveResize(display_video_rect);
01130 }
01131 }
01132
01133 bool VideoOutputQuartz::InputChanged(const QSize &input_size,
01134 float aspect,
01135 MythCodecID av_codec_id,
01136 void *codec_private)
01137 {
01138 VERBOSE(VB_PLAYBACK, LOC +
01139 QString("InputChanged(WxH = %1x%2, aspect=%3")
01140 .arg(input_size.width())
01141 .arg(input_size.height()).arg(aspect));
01142
01143 bool cid_changed = (myth_codec_id != av_codec_id);
01144 bool res_changed = input_size != video_disp_dim;
01145 bool asp_changed = aspect != video_aspect;
01146
01147 VideoOutput::InputChanged(input_size, aspect, av_codec_id, codec_private);
01148
01149 if (!res_changed && !cid_changed)
01150 {
01151
01152 if (asp_changed)
01153 MoveResize();
01154 return true;
01155 }
01156
01157 if (cid_changed)
01158 {
01159 myth_codec_id = av_codec_id;
01160 data->dvdv = (DVDV*) codec_private;
01161
01162 if ((data->dvdv && (kCodec_MPEG2_DVDV != myth_codec_id)) ||
01163 (!data->dvdv && (kCodec_NORMAL_END <= myth_codec_id)))
01164 {
01165 return false;
01166 }
01167
01168 if (data->dvdv && !data->dvdv->SetVideoSize(video_dim))
01169 {
01170 return false;
01171 }
01172 }
01173
01174 DeleteQuartzBuffers();
01175
01176 data->srcWidth = video_dim.width();
01177 data->srcHeight = video_dim.height();
01178 data->srcAspect = aspect;
01179 data->srcMode = db_aspectoverride;
01180
01181 CreateQuartzBuffers();
01182
01183 vector<VideoOutputQuartzView*>::iterator it = data->views.begin();
01184 for (; it != data->views.end(); ++it)
01185 {
01186 (*it)->InputChanged(
01187 video_dim.width(), video_dim.height(), aspect, av_codec_id);
01188 }
01189
01190 MoveResize();
01191
01192 return true;
01193 }
01194
01195 int VideoOutputQuartz::GetRefreshRate(void)
01196 {
01197 VERBOSE(VB_PLAYBACK, (LOC + "GetRefreshRate() [returning %1]")
01198 .arg((int)data->refreshRate));
01199
01200 return (int) (1000000 / data->refreshRate);
01201 }
01202
01203 bool VideoOutputQuartz::Init(int width, int height, float aspect,
01204 WId winid, int winx, int winy,
01205 int winw, int winh, WId embedid)
01206 {
01207 VERBOSE(VB_PLAYBACK, LOC +
01208 QString("Init(WxH %1x%2, aspect=%3, winid=%4\n\t\t\t"
01209 "win_bounds(x %5, y%6, WxH %7x%8), WId embedid=%9)")
01210 .arg(width).arg(height).arg(aspect).arg(winid)
01211 .arg(winx).arg(winy).arg(winw).arg(winh).arg(embedid));
01212
01213 if ((data->dvdv && (kCodec_MPEG2_DVDV != myth_codec_id)) ||
01214 (!data->dvdv && (kCodec_NORMAL_END <= myth_codec_id)))
01215 {
01216 return false;
01217 }
01218
01219 if (data->dvdv && !data->dvdv->SetVideoSize(QSize(width, height)))
01220 {
01221 return false;
01222 }
01223
01224 vbuffers.Init(kNumBuffers, true, kNeedFreeFrames,
01225 kPrebufferFramesNormal, kPrebufferFramesSmall,
01226 kKeepPrebuffer);
01227 VideoOutput::Init(width, height, aspect, winid,
01228 winx, winy, winw, winh, embedid);
01229
01230 data->srcWidth = video_dim.width();
01231 data->srcHeight = video_dim.height();
01232 data->srcAspect = aspect;
01233 data->srcMode = db_aspectoverride;
01234
01235
01236 if (EnterMovies())
01237 {
01238 VERBOSE(VB_IMPORTANT, LOC + "Init() - EnterMovies failed");
01239 return false;
01240 }
01241
01242
01243 data->window = FrontNonFloatingWindow();
01244 if (!data->window)
01245 {
01246 VERBOSE(VB_IMPORTANT, LOC + "Init() - Find window failed");
01247 return false;
01248 }
01249
01250
01251
01252
01253
01254 if (GetWindowBounds(data->window,
01255 kWindowStructureRgn, &(data->windowBounds)))
01256 {
01257 VERBOSE(VB_IMPORTANT, LOC + "Init() - GetWindowBounds failed");
01258 return false;
01259 }
01260 CGPoint pt;
01261 pt.x = data->windowBounds.left;
01262 pt.y = data->windowBounds.top;
01263 CGDisplayCount ct;
01264 data->screen = NULL;
01265 if (CGGetDisplaysWithPoint(pt, 1, &data->screen, &ct))
01266 {
01267
01268 data->screen = CGMainDisplayID();
01269 }
01270
01271
01272 CFDictionaryRef m;
01273 m = CGDisplayCurrentMode(data->screen);
01274 data->refreshRate = get_float_CF(m, kCGDisplayRefreshRate);
01275 if (data->refreshRate == 0.0)
01276 data->refreshRate = 150.0;
01277
01278
01279
01280 CGSize size_in_mm = CGDisplayScreenSize(data->screen);
01281 if ((size_in_mm.width > 0.0001f) && (size_in_mm.height > 0.0001f))
01282 {
01283 display_dim = QSize((uint) size_in_mm.width, (uint) size_in_mm.height);
01284 display_aspect = size_in_mm.width / size_in_mm.height;
01285 VERBOSE(VB_PLAYBACK, QString("Screen size is %1 x %2 (mm), aspect %3")
01286 .arg(size_in_mm.width).arg(size_in_mm.height)
01287 .arg(display_aspect));
01288 }
01289
01290
01291 data->scaleUpVideo = gContext->GetNumSetting("MacScaleUp", 1);
01292 data->drawInWindow = gContext->GetNumSetting("GuiSizeForTV", 0);
01293 data->windowedMode = gContext->GetNumSetting("RunFrontendInWindow", 0);
01294 data->correctGamma = gContext->GetNumSetting("MacGammaCorrect", 0);
01295
01296 data->convertI420to2VUY = get_i420_2vuy_conv();
01297
01298
01299 if (data->drawInWindow)
01300 {
01301
01302 float winWidth = size_in_mm.width * winw
01303 / get_int_CF(m, kCGDisplayWidth);
01304 float winHeight = size_in_mm.height * winh
01305 / get_int_CF(m, kCGDisplayHeight);
01306 display_dim = QSize(winWidth, winHeight);
01307 display_aspect = winWidth / winHeight;
01308 VERBOSE(VB_PLAYBACK, QString("Main window is %1 x %2 (mm), aspect %3")
01309 .arg((int)winWidth).arg((int)winHeight)
01310 .arg(display_aspect));
01311 }
01312
01313 if (!CreateQuartzBuffers())
01314 {
01315 VERBOSE(VB_IMPORTANT, LOC + "Init() - CreateQuartzBuffers failed");
01316 return false;
01317 }
01318
01319
01320
01321 VideoOutputQuartzView *tmp;
01322 if (!data->drawInWindow)
01323 {
01324
01325 tmp = new VoqvFullscreen(data);
01326 tmp->SetFrameSkip(gContext->GetNumSetting("MacFullSkip", 0));
01327 data->views.push_back(tmp);
01328 }
01329 else if (!data->windowedMode)
01330 {
01331
01332 tmp = new VoqvMainWindow(data, 1.0);
01333 tmp->SetFrameSkip(gContext->GetNumSetting("MacFullSkip", 0));
01334 data->views.push_back(tmp);
01335 }
01336 else
01337 {
01338
01339 if (gContext->GetNumSetting("MacMainEnabled", 1))
01340 {
01341 float opacity =
01342 gContext->GetNumSetting("MacMainOpacity", 100) / 100.0;
01343 tmp = new VoqvMainWindow(data, opacity);
01344 tmp->SetFrameSkip(gContext->GetNumSetting("MacMainSkip", 0));
01345 data->views.push_back(tmp);
01346 }
01347 else
01348 {
01349
01350
01351 VERBOSE(VB_PLAYBACK, QString("Shrinking Main Window to 1x1"));
01352 SizeWindow(data->window, 1, 1, true);
01353 }
01354 if (gContext->GetNumSetting("MacFloatEnabled", 0))
01355 {
01356 float opacity =
01357 gContext->GetNumSetting("MacFloatOpacity", 100) / 100.0;
01358 tmp = new VoqvFloater(data, opacity);
01359 tmp->SetFrameSkip(gContext->GetNumSetting("MacFloatSkip", 0));
01360 data->views.push_back(tmp);
01361 }
01362 if (gContext->GetNumSetting("MacDesktopEnabled", 0))
01363 {
01364 tmp = new VoqvDesktop(data);
01365 tmp->SetFrameSkip(gContext->GetNumSetting("MacDesktopSkip", 0));
01366 data->views.push_back(tmp);
01367 }
01368 if (gContext->GetNumSetting("MacDockEnabled", 1))
01369 {
01370 tmp = new VoqvDock(data);
01371 tmp->SetFrameSkip(gContext->GetNumSetting("MacDockSkip", 3));
01372 data->views.push_back(tmp);
01373 }
01374 }
01375
01376 vector<VideoOutputQuartzView*>::iterator it = data->views.begin();
01377 for (; it != data->views.end(); ++it)
01378 {
01379 if (!(*it)->Init())
01380 {
01381 VERBOSE(VB_IMPORTANT, LOC + "Init() - QuartzView Init() failed");
01382 }
01383 }
01384
01385 MoveResize();
01386 Started = true;
01387
01388 return true;
01389 }
01390
01391 void VideoOutputQuartz::SetVideoFrameRate(float playback_fps)
01392 {
01393 VERBOSE(VB_PLAYBACK, "SetVideoFrameRate("<<playback_fps<<")");
01394 }
01395
01396 void VideoOutputQuartz::SetDVDVDecoder(DVDV *dvdvdec)
01397 {
01398 QString renderer = "quartz-blit";
01399
01400 (void) dvdvdec;
01401
01402 #ifdef USING_DVDV
01403 data->dvdv = dvdvdec;
01404 renderer = (data->dvdv) ? "quartz-accel" : renderer;
01405 #endif // USING_DVDV
01406
01407 db_vdisp_profile->SetVideoRenderer(renderer);
01408 }
01409
01410 static QString toCommaList(const QStringList &list)
01411 {
01412 QString ret = "";
01413 for (QStringList::const_iterator it = list.begin(); it != list.end(); ++it)
01414 ret += *it + ",";
01415
01416 if (ret.length())
01417 return ret.left(ret.length()-1);
01418
01419 return "";
01420 }
01421
01422 bool VideoOutputQuartz::CreateQuartzBuffers(void)
01423 {
01424 db_vdisp_profile->SetInput(video_dim);
01425 QStringList renderers = GetAllowedRenderers(myth_codec_id, video_dim);
01426 QString renderer = QString::null;
01427
01428 QString tmp = db_vdisp_profile->GetVideoRenderer();
01429 VERBOSE(VB_PLAYBACK, LOC + "CreateQuartzBuffers() "
01430 <<QString("render: %1, allowed: %2")
01431 .arg(tmp).arg(toCommaList(renderers)));
01432
01433 if (renderers.contains(tmp))
01434 renderer = tmp;
01435 else if (!renderers.empty())
01436 renderer = renderers[0];
01437 else
01438 {
01439 VERBOSE(VB_IMPORTANT, "Failed to find a video renderer");
01440 return false;
01441 }
01442
01443
01444 db_vdisp_profile->SetVideoRenderer(renderer);
01445 VERBOSE(VB_IMPORTANT, LOC + "VProf: " + db_vdisp_profile->toString());
01446
01447 vbuffers.CreateBuffers(video_dim.width(), video_dim.height());
01448
01449
01450 if (pauseFrame.buf)
01451 delete [] pauseFrame.buf;
01452
01453 VideoFrame *scratch = vbuffers.GetScratchFrame();
01454
01455 init(&pauseFrame, FMT_YV12, new unsigned char[scratch->size],
01456 scratch->width, scratch->height, scratch->bpp, scratch->size);
01457
01458 pauseFrame.frameNumber = scratch->frameNumber;
01459
01460
01461
01462 data->pixelLock.lock();
01463
01464 int width, height;
01465 width = data->srcWidth;
01466 height = data->srcHeight;
01467
01468
01469
01470
01471 data->imgDesc =
01472 (ImageDescriptionHandle) NewHandleClear(sizeof(ImageDescription));
01473 HLock((Handle)(data->imgDesc));
01474
01475 ImageDescription *desc = *data->imgDesc;
01476
01477 desc->idSize = sizeof(ImageDescription);
01478 desc->cType = k422YpCbCr8CodecType;
01479 desc->version = 2;
01480 desc->revisionLevel = 0;
01481 desc->spatialQuality = codecNormalQuality;
01482 desc->width = width;
01483 desc->height = height;
01484 desc->hRes = Long2Fix(72);
01485 desc->vRes = Long2Fix(72);
01486 desc->depth = 24;
01487 desc->frameCount = 0;
01488 desc->dataSize = 0;
01489 desc->clutID = -1;
01490
01491 HUnlock((Handle)(data->imgDesc));
01492
01493
01494 data->pixelSize = width * height * 2;
01495 data->pixelData = new char[data->pixelSize];
01496
01497 data->pixelLock.unlock();
01498
01499 return true;
01500 }
01501
01502 void VideoOutputQuartz::Exit(void)
01503 {
01504 if (Started)
01505 {
01506 Started = false;
01507
01508
01509
01510 if (data->windowedMode)
01511 {
01512 VERBOSE(VB_PLAYBACK,
01513 QString("Restoring Main Window to %1x%2")
01514 .arg(data->windowBounds.right - data->windowBounds.left)
01515 .arg(data->windowBounds.bottom - data->windowBounds.top));
01516 SetWindowBounds(data->window, kWindowStructureRgn,
01517 &(data->windowBounds));
01518 }
01519
01520 data->ClearViews();
01521 DeleteQuartzBuffers();
01522 }
01523 }
01524
01525 void VideoOutputQuartz::DeleteQuartzBuffers()
01526 {
01527 data->pixelLock.lock();
01528 if (data->imgDesc)
01529 {
01530 DisposeHandle((Handle)(data->imgDesc));
01531 data->imgDesc = NULL;
01532 }
01533 if (data->pixelData)
01534 {
01535 delete [] data->pixelData;
01536 data->pixelData = NULL;
01537 data->pixelSize = 0;
01538 }
01539 data->pixelLock.unlock();
01540
01541 if (pauseFrame.buf)
01542 {
01543 delete [] pauseFrame.buf;
01544 init(&pauseFrame, FMT_YV12, NULL, 0, 0, 0, 0);
01545 }
01546
01547 vbuffers.DeleteBuffers();
01548 }
01549
01550 void VideoOutputQuartz::EmbedInWidget(WId wid, int x, int y, int w, int h)
01551 {
01552 VERBOSE(VB_PLAYBACK,
01553 (LOC + "EmbedInWidget(wid=%1, x=%2, y=%3, w=%4, h=%5)")
01554 .arg(wid).arg(x).arg(y).arg(w).arg(h));
01555
01556 if (embedding)
01557 return;
01558
01559 VideoOutput::EmbedInWidget(wid, x, y, w, h);
01560
01561 data->pixelLock.lock();
01562
01563
01564 vector<VideoOutputQuartzView*>::iterator it = data->views.begin();
01565 for (; it != data->views.end(); ++it)
01566 {
01567 (*it)->EmbedChanged(true);
01568 }
01569
01570
01571 data->embeddedView = new VoqvEmbedded(data, x, y, w, h);
01572 if (data->embeddedView)
01573 {
01574 data->embeddedView->Init();
01575 data->views.push_back(data->embeddedView);
01576 }
01577
01578 data->pixelLock.unlock();
01579 }
01580
01581 void VideoOutputQuartz::StopEmbedding(void)
01582 {
01583 VERBOSE(VB_PLAYBACK, LOC + "StopEmbedding()");
01584
01585 if (!embedding)
01586 return;
01587
01588 VideoOutput::StopEmbedding();
01589
01590 data->pixelLock.lock();
01591
01592
01593 if (data->embeddedView)
01594 {
01595 vector<VideoOutputQuartzView*>::iterator it =
01596 find(data->views.begin(), data->views.end(), data->embeddedView);
01597 if (it != data->views.end())
01598 {
01599 delete *it;
01600 data->views.erase(it);
01601 }
01602 data->embeddedView = NULL;
01603 }
01604
01605
01606 vector<VideoOutputQuartzView*>::iterator it = data->views.begin();
01607 for (; it != data->views.end(); ++it)
01608 (*it)->EmbedChanged(false);
01609
01610 data->pixelLock.unlock();
01611 }
01612
01617 void VideoOutputQuartz::PrepareFrame(VideoFrame *buffer, FrameScanType t)
01618 {
01619 (void)t;
01620
01621 #ifdef USING_DVDV
01622 if (data->dvdv && buffer)
01623 data->dvdv->DecodeFrame(buffer);
01624 #endif // USING_DVDV
01625
01626 if (buffer)
01627 framesPlayed = buffer->frameNumber + 1;
01628 }
01629
01634 void VideoOutputQuartz::Show(FrameScanType t)
01635 {
01636 (void)t;
01637
01638 #ifdef USING_DVDV
01639 if (data->dvdv)
01640 {
01641 data->dvdv->ShowFrame();
01642 return;
01643 }
01644 #endif // USING_DVDV
01645
01646 data->pixelLock.lock();
01647 vector<VideoOutputQuartzView*>::iterator it = data->views.begin();
01648 for (; it != data->views.end(); ++it)
01649 (*it)->Show();
01650 data->pixelLock.unlock();
01651 }
01652
01653 void VideoOutputQuartz::DrawUnusedRects(bool)
01654 {
01655 }
01656
01657 void VideoOutputQuartz::UpdatePauseFrame(void)
01658 {
01659 if (!pauseFrame.buf)
01660 {
01661 VERBOSE(VB_IMPORTANT, LOC + "UpdatePauseFrame() - no buffers?");
01662 return;
01663 }
01664
01665 VideoFrame *pauseb = vbuffers.GetScratchFrame();
01666 VideoFrame *pauseu = vbuffers.head(kVideoBuffer_used);
01667 if (pauseu)
01668 memcpy(pauseFrame.buf, pauseu->buf, pauseu->size);
01669 else
01670 memcpy(pauseFrame.buf, pauseb->buf, pauseb->size);
01671 }
01672
01677 void VideoOutputQuartz::ProcessFrame(VideoFrame *frame, OSD *osd,
01678 FilterChain *filterList,
01679 NuppelVideoPlayer *pipPlayer)
01680 {
01681 #ifdef USING_DVDV
01682 if (data->dvdv)
01683 {
01684 if (osd && osd->Visible())
01685 {
01686 OSDSurface *surface = osd->Display();
01687 if (surface && surface->Changed())
01688 {
01689 data->dvdv->DrawOSD(surface->y, surface->u,
01690 surface->v, surface->alpha);
01691 }
01692 }
01693 else
01694 {
01695 data->dvdv->DrawOSD(NULL, NULL, NULL, NULL);
01696 }
01697 return;
01698 }
01699 #endif // USING_DVDV
01700
01701 if (!frame)
01702 {
01703 frame = vbuffers.GetScratchFrame();
01704 CopyFrame(vbuffers.GetScratchFrame(), &pauseFrame);
01705 }
01706
01707 if (filterList)
01708 filterList->ProcessFrame(frame);
01709
01710 if (m_deinterlacing &&
01711 m_deintFilter != NULL &&
01712 m_deinterlaceBeforeOSD)
01713 {
01714 m_deintFilter->ProcessFrame(frame);
01715 }
01716
01717 ShowPip(frame, pipPlayer);
01718 DisplayOSD(frame, osd);
01719
01720 if (m_deinterlacing &&
01721 m_deintFilter != NULL &&
01722 !m_deinterlaceBeforeOSD)
01723 {
01724 m_deintFilter->ProcessFrame(frame);
01725 }
01726
01727 QMutexLocker locker(&data->pixelLock);
01728 if (!data->pixelData)
01729 {
01730 VERBOSE(VB_PLAYBACK, LOC + "ProcessFrame(): NULL pixelData!");
01731 return;
01732 }
01733
01734
01735 data->convertI420to2VUY(
01736 (unsigned char*) data->pixelData, frame->width<<1,
01737 frame->buf + frame->offsets[0],
01738 frame->buf + frame->offsets[1],
01739 frame->buf + frame->offsets[2],
01740 frame->pitches[0], frame->pitches[1], frame->pitches[2],
01741 frame->width, frame->height);
01742 }
01743
01744 QStringList VideoOutputQuartz::GetAllowedRenderers(
01745 MythCodecID myth_codec_id, const QSize &video_dim)
01746 {
01747 (void) video_dim;
01748
01749 QStringList list;
01750
01751 if (kCodec_MPEG2_DVDV == myth_codec_id)
01752 {
01753 list += "quartz-accel";
01754 }
01755 else if (kCodec_MPEG2_DVDV != myth_codec_id)
01756 {
01757 list += "quartz-blit";
01758 }
01759
01760 return list;
01761 }
01762
01763 MythCodecID VideoOutputQuartz::GetBestSupportedCodec(
01764 uint width, uint height,
01765 uint osd_width, uint osd_height,
01766 uint stream_type, uint fourcc)
01767 {
01768 (void) osd_width;
01769 (void) osd_height;
01770
01771 VideoDisplayProfile vdp;
01772 vdp.SetInput(QSize(width, height));
01773 QString dec = vdp.GetDecoder();
01774 if ((dec == "libmpeg2") || (dec == "ffmpeg"))
01775 return (MythCodecID)(kCodec_MPEG1 + (stream_type-1));
01776
01777 if ((dec == "macaccel") &&
01778 ((FOURCC_I420 == fourcc) || (FOURCC_IYUV == fourcc)) &&
01779 ((2 == stream_type) || (1 == stream_type)))
01780 {
01781 return kCodec_MPEG2_DVDV;
01782 }
01783 else
01784 {
01785 return (MythCodecID)(kCodec_MPEG1 + (stream_type-1));
01786 }
01787 }