00001
00002
00003
00004
00005 #include <iostream>
00006 #include <algorithm>
00007 using namespace std;
00008
00009 #import <Cocoa/Cocoa.h>
00010 #import <Carbon/Carbon.h>
00011 #import <AGL/agl.h>
00012 #import <OpenGL/glext.h>
00013
00014 #include <qmutex.h>
00015 #include <qstring.h>
00016 #include <qptrqueue.h>
00017 #include <qmap.h>
00018 #include <qsize.h>
00019
00020 #include "libmyth/mythconfig.h"
00021 #include "libmyth/mythverbose.h"
00022
00023 #include "videoout_dvdv.h"
00024 #undef ABS
00025 extern "C" {
00026 #include "avcodec.h"
00027 }
00028 #include "dvdv.h"
00029 #include "videoout_dvdv_private.h"
00030 #include "yuv2rgb.h"
00031
00032
00033 const int kAppleBuffers = 4;
00034
00035
00036 const int kSubpictureSize = 8 * 1024 * 1024;
00037
00038
00039
00040 const int kAccelBuffers = 33;
00041
00042
00043 #define LOC "DVDV::" << __FUNCTION__ << " "
00044 #define LOC_ERR "DVDV::" << __FUNCTION__ << " - Error: "
00045
00047 class FrameData
00048 {
00049 public:
00050 FrameData() : data(NULL), showBuffer(0), vf(NULL) { }
00051
00053 uint8 *data;
00055 DVDV_CurPtrs state;
00057 DVDV_Frame stateframe;
00060 DecodeParams dec;
00062 int showBuffer;
00064 VideoFrame *vf;
00065 };
00066
00068 class DVDV_Private
00069 {
00070 public:
00071 DVDV_Private() :
00072 gDVDContext(NULL), gConn(0),
00073 gWindowID(0), gSurfaceID(0),
00074 gWindow(NULL), gNsWindow(NULL),
00075 overlayWindow(NULL), overlayContext(NULL),
00076 osdWidth(0), osdHeight(0),
00077 yuvTexture(0), alphaTexture(0),
00078 osdVisible(false), curFrame(NULL),
00079 gBufShow(0), gBufPast(0),
00080 gBufFuture(0), gBufRecent(0),
00081 mutex(false)
00082 {
00083 gWindowContentOrigin.v = 0;
00084 gWindowContentOrigin.h = 0;
00085 bzero(gRealRect, sizeof(gRealRect));
00086 bzero(subpic, sizeof(subpic));
00087 }
00088
00090 DVDVideoContext *gDVDContext;
00093 CGSConnectionID gConn;
00094 int gWindowID;
00095 CGSSurfaceID gSurfaceID;
00099 Point gWindowContentOrigin;
00101 short gRealRect;
00102
00104 WindowRef gWindow;
00106 NSWindow *gNsWindow;
00107
00108
00109 WindowRef overlayWindow;
00110 AGLContext overlayContext;
00111 int osdWidth;
00112 int osdHeight;
00113 GLuint yuvTexture;
00114 GLuint alphaTexture;
00115 bool osdVisible;
00116
00117
00118
00119 FrameData gFrames;
00120 QPtrQueue<FrameData> freeFrames;
00121 QPtrQueue<FrameData> usedFrames;
00122 QMap<VideoFrame*, FrameData*> usedMap;
00123
00125 FrameData *curFrame;
00126
00128 uint8 subpic;
00129
00132 int gBufShow;
00133
00134
00135
00136 int gBufPast;
00137 int gBufFuture;
00138 int gBufRecent;
00139
00141 QMutex mutex;
00142 };
00143
00144
00145 DVDV::DVDV() : d(new DVDV_Private())
00146 {
00147 }
00148
00149 DVDV::~DVDV()
00150 {
00151 if (d)
00152 {
00153 Teardown();
00154 delete d;
00155 d = NULL;
00156 }
00157 }
00158
00159 void DVDV::Teardown(void)
00160 {
00161 QMutexLocker locker(&d->mutex);
00162
00163
00164 for (int i = 0; i < kAccelBuffers; i++)
00165 {
00166 delete d->gFrames.data;
00167 d->gFrames.data = NULL;
00168 }
00169
00170 while (FrameData *frame = d->usedFrames.dequeue())
00171 {
00172 d->usedMap.erase(frame->vf);
00173 d->freeFrames.enqueue(frame);
00174 }
00175
00176 d->curFrame = NULL;
00177
00178 if (d->gSurfaceID)
00179 {
00180
00181
00182 CGRect surBounds = {{-1, 1}, {1, 1}};
00183 CGSSetSurfaceBounds(d->gConn, d->gWindowID, d->gSurfaceID, surBounds);
00184 CGSOrderSurface(d->gConn, d->gWindowID, d->gSurfaceID, 0, 0);
00185 d->gSurfaceID = NULL;
00186 }
00187
00188 if (d->gDVDContext)
00189 {
00190 DVDVideoClearMP(d->gDVDContext);
00191 DVDVideoEnableMP(d->gDVDContext, false);
00192 DVDVideoCloseDevice(d->gDVDContext);
00193 d->gDVDContext = NULL;
00194 }
00195
00196 if (d->overlayContext)
00197 {
00198 aglDestroyContext(d->overlayContext);
00199 d->overlayContext = NULL;
00200 }
00201
00202 if (d->overlayWindow)
00203 {
00204 DisposeWindow(d->overlayWindow);
00205 d->overlayWindow = NULL;
00206 }
00207 }
00208
00209
00210 bool DVDV::SetVideoSize(const QSize &video_dim)
00211 {
00212 int width = video_dim.width();
00213 int height = video_dim.height();
00214
00215
00216 if (width < 16 || height < 16 ||
00217 width > 4096 || height > 2304)
00218 {
00219
00220 VERBOSE(VB_PLAYBACK,
00221 LOC_ERR << QString("Stream has unlikely dimensions! (%1 x %2)")
00222 .arg(width).arg(height));
00223 return false;
00224 }
00225
00226 QMutexLocker locker(&d->mutex);
00227
00228
00229 d->gRealRect = d->gRealRect = 0;
00230 d->gRealRect = height;
00231 d->gRealRect = width;
00232
00233
00234
00235 d->gWindow = FrontNonFloatingWindow();
00236
00237
00238
00239
00240 Rect contentRect, frameRect;
00241 GetWindowBounds(d->gWindow, kWindowContentRgn, &contentRect);
00242 GetWindowBounds(d->gWindow, kWindowStructureRgn, &frameRect);
00243 d->gWindowContentOrigin.v = contentRect.top - frameRect.top;
00244 d->gWindowContentOrigin.h = contentRect.left - frameRect.left;
00245
00246
00247
00248 d->gNsWindow = [[NSWindow alloc] initWithWindowRef:d->gWindow];
00249 d->gWindowID = [d->gNsWindow windowNumber];
00250
00251
00252 if (!d->gConn)
00253 d->gConn = _CGSDefaultConnection();
00254
00255 if (!d->gSurfaceID)
00256 {
00257 CGSAddSurface(d->gConn, d->gWindowID, &d->gSurfaceID);
00258 }
00259
00260
00261 if (!d->gDVDContext)
00262 {
00263 int someOutput;
00264 DVDVideoOpenDevice(CGMainDisplayID(),
00265 d->gConn, d->gWindowID, d->gSurfaceID,
00266 d->gRealRect,
00267 someOutput,
00268 &d->gDVDContext);
00269 }
00270
00271
00272 CGRect surBounds = {{d->gWindowContentOrigin.h,
00273 d->gWindowContentOrigin.v},
00274 {width, height}};
00275 CGSSetSurfaceBounds(d->gConn, d->gWindowID, d->gSurfaceID, surBounds);
00276 CGSOrderSurface(d->gConn, d->gWindowID, d->gSurfaceID, 1, 0);
00277
00278
00279 DVDVideoSetMPRects(d->gDVDContext, d->gRealRect,
00280 d->gSurfaceID, d->gSurfaceID);
00281 DVDVideoSetMVLevel(d->gDVDContext, 0);
00282 DVDVideoClearMP(d->gDVDContext);
00283 DVDVideoEnableMP(d->gDVDContext, true);
00284
00285
00286 int numMBs = (d->gRealRect / 16) * (d->gRealRect[3] / 16);
00287 int dataSize = (sizeof(DVDV_MBInfo) * numMBs * 2) +
00288 (sizeof(DVDV_DCTElt) * numMBs * 768) +
00289 (sizeof(uint8_t) * numMBs * 2);
00290
00291 for (int i = 0; i < kAccelBuffers; i++)
00292 {
00293 FrameData *frame = &d->gFrames;
00294
00295 frame->state.frame = &frame->stateframe;
00296
00297 memset(&frame->dec, 0, sizeof(frame->dec));
00298 frame->dec.sevenSixEight = 768;
00299 frame->dec.p4 = d->subpic;
00300
00301 frame->showBuffer = kAppleBuffers;
00302 frame->vf = NULL;
00303
00304 frame->data = new uint8;
00305 uint8 *ptr = frame->data;
00306 frame->state.mb = (DVDV_MBInfo *)ptr;
00307 frame->dec.mbInfo = (MBInfo *)ptr;
00308 ptr += (sizeof(DVDV_MBInfo) * numMBs * 2);
00309
00310 frame->state.dct = (DVDV_DCTElt *)ptr;
00311 frame->dec.dctSpecs = (DCTSpec *)ptr;
00312 ptr += (sizeof(DVDV_DCTElt) * numMBs * 768);
00313
00314 frame->state.cbp = ptr;
00315 frame->dec.cbp = ptr;
00316
00317 d->freeFrames.enqueue(frame);
00318 }
00319
00320
00321 d->gBufShow = kAppleBuffers;
00322 d->gBufPast = d->gBufFuture = d->gBufRecent = 0;
00323
00324 return true;
00325 }
00326
00327
00328 void DVDV::MoveResize(int imgx, int imgy, int imgw, int imgh,
00329 int dispxoff, int dispyoff,
00330 int dispwoff, int disphoff)
00331 {
00332
00333 (void) imgx;
00334 (void) imgy;
00335 (void) imgw;
00336 (void) imgh;
00337
00338 QMutexLocker locker(&d->mutex);
00339
00340 CGRect surBounds = { { dispxoff + d->gWindowContentOrigin.h,
00341 dispyoff + d->gWindowContentOrigin.v },
00342 { dispwoff,
00343 disphoff } };
00344 CGSSetSurfaceBounds(d->gConn, d->gWindowID, d->gSurfaceID, surBounds);
00345
00346
00347 if (d->overlayContext)
00348 aglDestroyContext(d->overlayContext);
00349 if (d->overlayWindow)
00350 DisposeWindow(d->overlayWindow);
00351
00352 d->osdWidth = d->gRealRect;
00353 d->osdHeight = d->gRealRect;
00354 d->osdVisible = false;
00355
00356 Rect parentBounds;
00357 GetWindowBounds(d->gWindow, kWindowContentRgn, &parentBounds);
00358 CreateNewWindow(kOverlayWindowClass, kWindowNoAttributes,
00359 &parentBounds, &d->overlayWindow);
00360 ShowWindow(d->overlayWindow);
00361
00362
00363 GLint attrib = { AGL_RGBA, AGL_DOUBLEBUFFER, AGL_NONE };
00364 AGLPixelFormat fmt = aglChoosePixelFormat(NULL, 0, attrib);
00365 d->overlayContext = aglCreateContext(fmt, NULL);
00366 aglSetDrawable(d->overlayContext, GetWindowPort(d->overlayWindow));
00367 aglSetCurrentContext(d->overlayContext);
00368 aglDestroyPixelFormat(fmt);
00369
00370 GLint swap = 0;
00371 aglSetInteger(d->overlayContext, AGL_SWAP_INTERVAL, &swap);
00372 aglSetInteger(d->overlayContext, AGL_SURFACE_OPACITY, &swap);
00373
00374
00375 glViewport(dispxoff, dispyoff, dispwoff, disphoff);
00376 glMatrixMode(GL_PROJECTION);
00377 glLoadIdentity();
00378 glOrtho(0, d->osdWidth, d->osdHeight, 0, -999999, 999999);
00379 glMatrixMode(GL_MODELVIEW);
00380 glLoadIdentity();
00381
00382 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
00383 glEnable(GL_BLEND);
00384
00385
00386 glDisable(GL_TEXTURE_2D);
00387 glEnable(GL_TEXTURE_RECTANGLE_EXT);
00388 }
00389
00390
00391 void DVDV::DrawOSD(unsigned char *y, unsigned char *u,
00392 unsigned char *v, unsigned char *alpha)
00393 {
00394 QMutexLocker locker(&d->mutex);
00395
00396 if (!y || !u || !v || !alpha)
00397 {
00398
00399 if (d->osdVisible)
00400 {
00401 aglSetCurrentContext(d->overlayContext);
00402 glClear(GL_COLOR_BUFFER_BIT);
00403 aglSwapBuffers(d->overlayContext);
00404 d->osdVisible = false;
00405 }
00406
00407 return;
00408 }
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419 conv_i420_2vuy_fun convert = get_i420_2vuy_conv();
00420 uint8_t *yuvData = new uint8_t;
00421 convert(yuvData, d->osdWidth<<1,
00422 y, u, v,
00423 d->osdWidth, d->osdWidth>>1, d->osdWidth>>1,
00424 d->osdWidth, d->osdHeight);
00425
00426
00427 aglSetCurrentContext(d->overlayContext);
00428 glClear(GL_COLOR_BUFFER_BIT);
00429
00430
00431 if (!d->yuvTexture)
00432 {
00433 glGenTextures(1, &d->yuvTexture);
00434 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, d->yuvTexture);
00435
00436
00437 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,
00438 GL_TEXTURE_STORAGE_HINT_APPLE,
00439 GL_STORAGE_SHARED_APPLE);
00440 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, 1);
00441
00442
00443 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,
00444 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00445 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,
00446 GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00447 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,
00448 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00449 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,
00450 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00451 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
00452
00453
00454 glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA,
00455 d->osdWidth, d->osdHeight, 0,
00456 GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, yuvData);
00457 }
00458 else
00459 {
00460 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, d->yuvTexture);
00461 glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0,
00462 0, 0, d->osdWidth, d->osdHeight,
00463 GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE,
00464 yuvData);
00465 }
00466 delete yuvData;
00467 yuvData = NULL;
00468
00469
00470 glBlendFunc(GL_DST_ALPHA, GL_ZERO);
00471 glBlendFunc(GL_ONE, GL_ZERO);
00472 glBegin(GL_QUADS);
00473 glTexCoord2f(0, 0);
00474 glVertex2f(0, 0);
00475 glTexCoord2f(d->osdWidth, 0);
00476 glVertex2f(d->osdWidth, 0);
00477 glTexCoord2f(d->osdWidth, d->osdHeight);
00478 glVertex2f(d->osdWidth, d->osdHeight);
00479 glTexCoord2f(0, d->osdHeight);
00480 glVertex2f(0, d->osdHeight);
00481 glEnd();
00482
00483
00484 if (!d->alphaTexture)
00485 {
00486 glGenTextures(1, &d->alphaTexture);
00487 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, d->alphaTexture);
00488
00489
00490 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,
00491 GL_TEXTURE_STORAGE_HINT_APPLE,
00492 GL_STORAGE_SHARED_APPLE);
00493 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, 1);
00494
00495
00496 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,
00497 GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00498 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,
00499 GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00500 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,
00501 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00502 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT,
00503 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00504 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
00505
00506
00507 glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_ALPHA,
00508 d->osdWidth, d->osdHeight, 0,
00509 GL_ALPHA, GL_UNSIGNED_BYTE, alpha);
00510 }
00511 else
00512 {
00513 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, d->alphaTexture);
00514 glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0,
00515 0, 0, d->osdWidth, d->osdHeight,
00516 GL_ALPHA, GL_UNSIGNED_BYTE, alpha);
00517 }
00518
00519
00520 glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
00521
00522 glBegin(GL_QUADS);
00523 glTexCoord2f(0, 0);
00524 glVertex2f(0, 0);
00525 glTexCoord2f(d->osdWidth, 0);
00526 glVertex2f(d->osdWidth, 0);
00527 glTexCoord2f(d->osdWidth, d->osdHeight);
00528 glVertex2f(d->osdWidth, d->osdHeight);
00529 glTexCoord2f(0, d->osdHeight);
00530 glVertex2f(0, d->osdHeight);
00531 glEnd();
00532
00533
00534 glFinishRenderAPPLE();
00535 aglSwapBuffers(d->overlayContext);
00536
00537 d->osdVisible = true;
00538 }
00539
00540
00541 void DVDV::Reset(void)
00542 {
00543 QMutexLocker locker(&d->mutex);
00544
00545
00546 d->gBufShow = kAppleBuffers;
00547 d->gBufPast = d->gBufFuture = d->gBufRecent = 0;
00548
00549
00550 while (FrameData *frame = d->usedFrames.dequeue())
00551 {
00552 d->usedMap.erase(frame->vf);
00553 d->freeFrames.enqueue(frame);
00554 }
00555 }
00556
00557
00558 bool DVDV::PreProcessFrame(AVCodecContext *context)
00559 {
00560 QMutexLocker locker(&d->mutex);
00561
00562 d->curFrame = d->freeFrames.dequeue();
00563 if (!d->curFrame)
00564 {
00565 VERBOSE(VB_PLAYBACK, LOC_ERR << "No free frames available!");
00566
00567 int i = min(d->usedFrames.count(), 5U);
00568 while (i)
00569 {
00570 FrameData *frame = d->usedFrames.dequeue();
00571 d->usedMap.erase(frame->vf);
00572 d->freeFrames.enqueue(frame);
00573 --i;
00574 }
00575
00576 d->curFrame = d->freeFrames.dequeue();
00577 if (!d->curFrame)
00578 {
00579 VERBOSE(VB_PLAYBACK,
00580 LOC_ERR << "Still no free frames available!");
00581 return false;
00582 }
00583 }
00584
00585 d->curFrame->showBuffer = kAppleBuffers;
00586 d->curFrame->vf = NULL;
00587
00588 if (context->dvdv)
00589 memcpy(context->dvdv, &d->curFrame->state, sizeof(DVDV_CurPtrs));
00590 else
00591 {
00592 VERBOSE(VB_PLAYBACK, LOC_ERR << "context->dvdv is NULL");
00593 return false;
00594 }
00595
00596 return true;
00597 }
00598
00599
00600 void DVDV::PostProcessFrame(AVCodecContext *context,
00601 VideoFrame *pic, int pict_type, bool gotpicture)
00602 {
00603 QMutexLocker locker(&d->mutex);
00604
00605
00606
00607
00608
00609 FrameData *frame = d->curFrame;
00610 if (!frame)
00611 {
00612 VERBOSE(VB_IMPORTANT, LOC_ERR << "No current frame!");
00613 return;
00614 }
00615
00616
00617 if (!gotpicture)
00618 {
00619 d->freeFrames.enqueue(frame);
00620 return;
00621 }
00622
00623 if (!context->dvdv)
00624 {
00625 VERBOSE(VB_PLAYBACK, LOC_ERR << "context->dvdv is NULL");
00626 d->freeFrames.enqueue(frame);
00627 return;
00628 }
00629
00630
00631 DVDV_MBInfo *processed = ((DVDV_CurPtrs *)context->dvdv)->mb;
00632
00633
00634 if (processed == frame->state.mb ||
00635 memcmp(processed, frame->state.mb, sizeof(DVDV_MBInfo)) == 0)
00636 {
00637
00638 d->freeFrames.enqueue(frame);
00639 return;
00640 }
00641
00642
00643 frame->vf = pic;
00644 d->usedFrames.enqueue(frame);
00645 d->usedMap = frame;
00646
00647 frame->dec.pictType = pict_type;
00648 frame->dec.alternateScan = frame->state.frame->alternate_scan;
00649
00650 switch (pict_type)
00651 {
00652 case 1:
00653 case 2:
00654
00655 for (int i = 0; i < kAppleBuffers; i++)
00656 {
00657 if ((d->gBufFuture != i) && (d->gBufRecent != i))
00658 {
00659 frame->dec.dstBuf = i;
00660 break;
00661 }
00662 }
00663
00664
00665 d->gBufPast = d->gBufFuture;
00666
00667 frame->showBuffer = d->gBufFuture;
00668
00669 frame->dec.srcBufL = frame->dec.srcBufR = d->gBufPast;
00670
00671 d->gBufFuture = frame->dec.dstBuf;
00672 break;
00673 case 3:
00674
00675 for (int i = 0; i < kAppleBuffers; i++)
00676 {
00677 if ((d->gBufFuture != i) &&
00678 (d->gBufPast != i) &&
00679 (d->gBufRecent != i))
00680 {
00681 frame->dec.dstBuf = i;
00682 break;
00683 }
00684 }
00685
00686
00687 d->gBufRecent = frame->dec.dstBuf;
00688
00689 frame->dec.srcBufL = d->gBufPast;
00690 frame->dec.srcBufR = d->gBufFuture;
00691
00692 frame->showBuffer = frame->dec.dstBuf;
00693 break;
00694 default:
00695 VERBOSE(VB_IMPORTANT, QString("Unknown picture type %1")
00696 .arg(pict_type));
00697 break;
00698 }
00699 }
00700
00701
00702 void DVDV::DecodeFrame(VideoFrame *pic)
00703 {
00704 QMutexLocker locker(&d->mutex);
00705
00706
00707 if (!d->usedMap[pic])
00708 {
00709 VERBOSE(VB_PLAYBACK, QString("VF %1 not in decode queue")
00710 .arg((unsigned long)pic));
00711 return;
00712 }
00713
00714
00715
00716 while (FrameData *frame = d->usedFrames.dequeue())
00717 {
00718 d->usedMap.erase(frame->vf);
00719
00720
00721 if (frame->showBuffer < kAppleBuffers)
00722 {
00723 DVDVideoDecode(d->gDVDContext, &frame->dec, d->gRealRect, 0);
00724 d->gBufShow = frame->showBuffer;
00725 }
00726 d->freeFrames.enqueue(frame);
00727
00728 if (frame->vf == pic)
00729 break;
00730
00731
00732 }
00733 }
00734
00735
00736 void DVDV::ShowFrame(void)
00737 {
00738 QMutexLocker locker(&d->mutex);
00739
00740 if (d->gDVDContext && d->gBufShow < kAppleBuffers)
00741 {
00742 #if 0
00743 DeinterlaceParams1 dp1;
00744 bzero(&dp1, sizeof(dp1));
00745 dp1.buf1 = d->gBufShow;
00746 dp1.buf2 = d->gBufShow;
00747 dp1.w1 = 1;
00748 dp1.w2 = 1;
00749 dp1.w3 = 2;
00750 DeinterlaceParams2 dp2;
00751 bzero(&dp2, sizeof(dp2));
00752 dp2.unk1 = 0x00020000;
00753 dp2.usedValue = 1;
00754 DVDVideoDeinterlace(d->gDVDContext, &dp1, &dp2, 0);
00755 #endif
00756
00757 ShowBufferParams sp;
00758 memset(&sp, 0, sizeof(sp));
00759 sp.h1 = 2;
00760 sp.w = 1;
00761 DVDVideoShowMPBuffer(d->gDVDContext, d->gBufShow, &sp, 0);
00762
00763
00764 d->gBufShow = kAppleBuffers;
00765 }
00766 }