00001
00002
00003 #include <map>
00004 #include <iostream>
00005 #include <algorithm>
00006 using namespace std;
00007
00008 #include "mythcontext.h"
00009 #include "videoout_d3d.h"
00010 #include "osd.h"
00011 #include "filtermanager.h"
00012 #include "fourcc.h"
00013 #include "videodisplayprofile.h"
00014 #include "mythmainwindow.h"
00015 #include "myth_imgconvert.h"
00016 #include "mythplayer.h"
00017
00018 #include "mmsystem.h"
00019 #include "tv.h"
00020
00021 #undef UNICODE
00022
00023 extern "C" {
00024 #include "libavcodec/avcodec.h"
00025 }
00026
00027 const int kNumBuffers = 31;
00028 const int kNeedFreeFrames = 1;
00029 const int kPrebufferFramesNormal = 10;
00030 const int kPrebufferFramesSmall = 4;
00031 const int kKeepPrebuffer = 2;
00032
00033 #define NUM_DXVA2_BUFS 30
00034
00035 #define LOC QString("VideoOutputD3D: ")
00036
00037 void VideoOutputD3D::GetRenderOptions(render_opts &opts,
00038 QStringList &cpudeints)
00039 {
00040 opts.renderers->append("direct3d");
00041 opts.deints->insert("direct3d", cpudeints);
00042 (*opts.osds)["direct3d"].append("direct3d");
00043 (*opts.safe_renderers)["dummy"].append("direct3d");
00044 (*opts.safe_renderers)["nuppel"].append("direct3d");
00045 if (opts.decoders->contains("ffmpeg"))
00046 (*opts.safe_renderers)["ffmpeg"].append("direct3d");
00047 if (opts.decoders->contains("crystalhd"))
00048 (*opts.safe_renderers)["crystalhd"].append("direct3d");
00049 opts.priorities->insert("direct3d", 70);
00050
00051 #ifdef USING_DXVA2
00052 if (opts.decoders->contains("dxva2"))
00053 (*opts.safe_renderers)["dxva2"].append("direct3d");
00054 #endif
00055 }
00056
00057 VideoOutputD3D::VideoOutputD3D(void)
00058 : VideoOutput(), m_lock(QMutex::Recursive),
00059 m_hWnd(NULL), m_render(NULL),
00060 m_video(NULL),
00061 m_render_valid(false), m_render_reset(false), m_pip_active(NULL),
00062 m_osd_painter(NULL)
00063 {
00064 m_pauseFrame.buf = NULL;
00065 #ifdef USING_DXVA2
00066 m_decoder = NULL;
00067 #endif
00068 m_pause_surface = NULL;
00069 }
00070
00071 VideoOutputD3D::~VideoOutputD3D()
00072 {
00073 TearDown();
00074 }
00075
00076 void VideoOutputD3D::TearDown(void)
00077 {
00078 QMutexLocker locker(&m_lock);
00079 vbuffers.DiscardFrames(true);
00080 vbuffers.Reset();
00081 vbuffers.DeleteBuffers();
00082 if (m_pauseFrame.buf)
00083 {
00084 delete [] m_pauseFrame.buf;
00085 m_pauseFrame.buf = NULL;
00086 }
00087
00088 delete m_osd_painter;
00089 m_osd_painter = NULL;
00090
00091 DeleteDecoder();
00092 DestroyContext();
00093 }
00094
00095 void VideoOutputD3D::DestroyContext(void)
00096 {
00097 QMutexLocker locker(&m_lock);
00098 m_render_valid = false;
00099 m_render_reset = false;
00100
00101 while (!m_pips.empty())
00102 {
00103 delete *m_pips.begin();
00104 m_pips.erase(m_pips.begin());
00105 }
00106 m_pip_ready.clear();
00107
00108 if (m_video)
00109 {
00110 delete m_video;
00111 m_video = NULL;
00112 }
00113
00114 if (m_render)
00115 {
00116 delete m_render;
00117 m_render = NULL;
00118 }
00119 }
00120
00121 void VideoOutputD3D::WindowResized(const QSize &new_size)
00122 {
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 }
00133
00134 bool VideoOutputD3D::InputChanged(const QSize &input_size,
00135 float aspect,
00136 MythCodecID av_codec_id,
00137 void *codec_private,
00138 bool &aspect_only)
00139 {
00140 QMutexLocker locker(&m_lock);
00141
00142 QSize cursize = window.GetActualVideoDim();
00143
00144 LOG(VB_PLAYBACK, LOG_INFO, LOC +
00145 QString("InputChanged from %1: %2x%3 aspect %4 to %5: %6x%7 aspect %9")
00146 .arg(toString(video_codec_id)).arg(cursize.width())
00147 .arg(cursize.height()).arg(window.GetVideoAspect())
00148 .arg(toString(av_codec_id)).arg(input_size.width())
00149 .arg(input_size.height()).arg(aspect));
00150
00151
00152 bool cid_changed = (video_codec_id != av_codec_id);
00153 bool res_changed = input_size != cursize;
00154 bool asp_changed = aspect != window.GetVideoAspect();
00155
00156 if (!res_changed && !cid_changed)
00157 {
00158 if (asp_changed)
00159 {
00160 aspect_only = true;
00161 VideoAspectRatioChanged(aspect);
00162 MoveResize();
00163 }
00164 return true;
00165 }
00166
00167 TearDown();
00168 QRect disp = window.GetDisplayVisibleRect();
00169 if (Init(input_size.width(), input_size.height(),
00170 aspect, m_hWnd, disp, av_codec_id))
00171 {
00172 BestDeint();
00173 return true;
00174 }
00175
00176 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to re-initialise video output.");
00177 errorState = kError_Unknown;
00178
00179 return false;
00180 }
00181
00182 bool VideoOutputD3D::SetupContext()
00183 {
00184 QMutexLocker locker(&m_lock);
00185 DestroyContext();
00186 QSize size = window.GetVideoDim();
00187 m_render = new MythRenderD3D9();
00188 if (!(m_render && m_render->Create(window.GetDisplayVisibleRect().size(),
00189 m_hWnd)))
00190 return false;
00191
00192 m_video = new D3D9Image(m_render, size, true);
00193 if (!(m_video && m_video->IsValid()))
00194 return false;
00195
00196 LOG(VB_PLAYBACK, LOG_INFO, LOC +
00197 "Direct3D device successfully initialized.");
00198 m_render_valid = true;
00199 return true;
00200 }
00201
00202 bool VideoOutputD3D::Init(int width, int height, float aspect, WId winid,
00203 const QRect &win_rect,MythCodecID codec_id)
00204 {
00205 MythPainter *painter = GetMythPainter();
00206 if (painter)
00207 painter->FreeResources();
00208
00209 QMutexLocker locker(&m_lock);
00210 m_hWnd = winid;
00211 window.SetAllowPreviewEPG(true);
00212
00213 VideoOutput::Init(width, height, aspect, winid, win_rect, codec_id);
00214
00215 LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Init with codec: %1")
00216 .arg(toString(codec_id)));
00217 SetProfile();
00218
00219 bool success = true;
00220 success &= SetupContext();
00221 InitDisplayMeasurements(width, height, false);
00222
00223 if (codec_is_dxva2(video_codec_id))
00224 {
00225 if (!CreateDecoder())
00226 return false;
00227 }
00228
00229 success &= CreateBuffers();
00230 success &= InitBuffers();
00231 success &= CreatePauseFrame();
00232
00233 MoveResize();
00234
00235 if (!success)
00236 TearDown();
00237 else
00238 {
00239 m_osd_painter = new MythD3D9Painter(m_render);
00240 if (m_osd_painter)
00241 {
00242 m_osd_painter->SetSwapControl(false);
00243 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Created D3D9 osd painter.");
00244 }
00245 else
00246 LOG(VB_GENERAL, LOG_ERR, LOC +
00247 "Failed to create D3D9 osd painter.");
00248 }
00249 return success;
00250 }
00251
00252 void VideoOutputD3D::SetProfile(void)
00253 {
00254 if (db_vdisp_profile)
00255 db_vdisp_profile->SetVideoRenderer("direct3d");
00256 }
00257
00258 bool VideoOutputD3D::CreateBuffers(void)
00259 {
00260 if (codec_is_dxva2(video_codec_id))
00261 {
00262 vbuffers.Init(NUM_DXVA2_BUFS, false, 2, 1, 4, 1);
00263 LOG(VB_PLAYBACK, LOG_INFO, LOC +
00264 QString("Created %1 empty DXVA2 buffers.") .arg(NUM_DXVA2_BUFS));
00265 return true;
00266 }
00267
00268 vbuffers.Init(kNumBuffers, true, kNeedFreeFrames,
00269 kPrebufferFramesNormal, kPrebufferFramesSmall,
00270 kKeepPrebuffer);
00271 return true;
00272
00273 }
00274
00275 bool VideoOutputD3D::InitBuffers(void)
00276 {
00277 #ifdef USING_DXVA2
00278 if ((codec_is_dxva2(video_codec_id)) && m_decoder)
00279 {
00280 QMutexLocker locker(&m_lock);
00281 const QSize video_dim = window.GetVideoDim();
00282 bool ok = true;
00283 for (int i = 0; i < NUM_DXVA2_BUFS; i++)
00284 {
00285 ok &= vbuffers.CreateBuffer(video_dim.width(),
00286 video_dim.height(), i,
00287 m_decoder->GetSurface(i), FMT_DXVA2);
00288 }
00289 if (ok)
00290 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Initialised DXVA2 buffers.");
00291 return ok;
00292 }
00293 #endif
00294 return vbuffers.CreateBuffers(FMT_YV12,
00295 window.GetVideoDim().width(),
00296 window.GetVideoDim().height());
00297 }
00298
00299 bool VideoOutputD3D::CreatePauseFrame(void)
00300 {
00301 if (codec_is_dxva2(video_codec_id))
00302 return true;
00303
00304 init(&m_pauseFrame, FMT_YV12,
00305 new unsigned char[vbuffers.GetScratchFrame()->size + 128],
00306 vbuffers.GetScratchFrame()->width,
00307 vbuffers.GetScratchFrame()->height,
00308 vbuffers.GetScratchFrame()->size);
00309
00310 m_pauseFrame.frameNumber = vbuffers.GetScratchFrame()->frameNumber;
00311 return true;
00312 }
00313
00314 void VideoOutputD3D::PrepareFrame(VideoFrame *buffer, FrameScanType t,
00315 OSD *osd)
00316 {
00317 (void)osd;
00318 if (IsErrored())
00319 {
00320 LOG(VB_GENERAL, LOG_ERR, LOC +
00321 "PrepareFrame() called while IsErrored is true.");
00322 return;
00323 }
00324
00325 if (!buffer && codec_is_std(video_codec_id))
00326 buffer = vbuffers.GetScratchFrame();
00327
00328 bool dummy = false;
00329 if (buffer)
00330 {
00331 dummy = buffer->dummy;
00332 framesPlayed = buffer->frameNumber + 1;
00333 }
00334
00335 if (!m_render || !m_video)
00336 return;
00337
00338 m_render_valid = m_render->Test(m_render_reset);
00339 if (m_render_valid)
00340 {
00341 QRect dvr = vsz_enabled ? vsz_desired_display_rect :
00342 window.GetDisplayVideoRect();
00343 bool ok = m_render->ClearBuffer();
00344 if (ok && !dummy)
00345 ok = m_video->UpdateVertices(dvr, window.GetVideoRect(),
00346 255, true);
00347
00348 if (ok)
00349 {
00350 ok = m_render->Begin();
00351 if (ok)
00352 {
00353 if (!dummy)
00354 m_video->Draw();
00355 QMap<MythPlayer*,D3D9Image*>::iterator it = m_pips.begin();
00356 for (; it != m_pips.end(); ++it)
00357 {
00358 if (m_pip_ready[it.key()])
00359 {
00360 if (m_pip_active == *it)
00361 {
00362 QRect rect = (*it)->GetRect();
00363 if (!rect.isNull())
00364 {
00365 rect.adjust(-10, -10, 10, 10);
00366 m_render->DrawRect(rect, QColor(128,0,0,255), 255);
00367 }
00368 }
00369 (*it)->Draw();
00370 }
00371 }
00372
00373 if (m_visual)
00374 m_visual->Draw(GetTotalOSDBounds(), m_osd_painter, NULL);
00375
00376 if (osd && m_osd_painter && !window.IsEmbedding())
00377 osd->DrawDirect(m_osd_painter, GetTotalOSDBounds().size(),
00378 true);
00379 m_render->End();
00380 }
00381 }
00382
00383 }
00384 }
00385
00386 void VideoOutputD3D::Show(FrameScanType )
00387 {
00388 if (IsErrored())
00389 {
00390 LOG(VB_GENERAL, LOG_ERR, LOC +
00391 "Show() called while IsErrored is true.");
00392 return;
00393 }
00394
00395 if (!m_render)
00396 return;
00397
00398 m_render_valid = m_render->Test(m_render_reset);
00399 if (m_render_valid)
00400 m_render->Present(window.IsEmbedding() ? m_hEmbedWnd : NULL);
00401 }
00402
00403 void VideoOutputD3D::EmbedInWidget(const QRect &rect)
00404 {
00405 if (window.IsEmbedding())
00406 return;
00407
00408 VideoOutput::EmbedInWidget(rect);
00409
00410 }
00411
00412 void VideoOutputD3D::StopEmbedding(void)
00413 {
00414 if (!window.IsEmbedding())
00415 return;
00416
00417 VideoOutput::StopEmbedding();
00418 }
00419
00420 void VideoOutputD3D::Zoom(ZoomDirection direction)
00421 {
00422 QMutexLocker locker(&m_lock);
00423 VideoOutput::Zoom(direction);
00424 MoveResize();
00425 }
00426
00427 void VideoOutputD3D::UpdatePauseFrame(int64_t &disp_timecode)
00428 {
00429 QMutexLocker locker(&m_lock);
00430 VideoFrame *used_frame = vbuffers.head(kVideoBuffer_used);
00431
00432 if (codec_is_std(video_codec_id))
00433 {
00434 if (!used_frame)
00435 used_frame = vbuffers.GetScratchFrame();
00436 CopyFrame(&m_pauseFrame, used_frame);
00437 disp_timecode = m_pauseFrame.disp_timecode;
00438 }
00439 else if (codec_is_dxva2(video_codec_id))
00440 {
00441 if (used_frame)
00442 {
00443 m_pause_surface = used_frame->buf;
00444 disp_timecode = used_frame->disp_timecode;
00445 }
00446 else
00447 LOG(VB_PLAYBACK, LOG_WARNING, LOC + "Failed to update pause frame");
00448 }
00449 }
00450
00451 void VideoOutputD3D::UpdateFrame(VideoFrame *frame, D3D9Image *img)
00452 {
00453 if (codec_is_dxva2(video_codec_id))
00454 return;
00455
00456
00457 bool hardware_conv = false;
00458 uint pitch = 0;
00459 uint8_t *buf = img->GetBuffer(hardware_conv, pitch);
00460 if (buf && hardware_conv)
00461 {
00462 int i;
00463 uint8_t *dst = buf;
00464 uint8_t *src = frame->buf;
00465 int chroma_width = frame->width >> 1;
00466 int chroma_height = frame->height >> 1;
00467 int chroma_pitch = pitch >> 1;
00468 for (i = 0; i < frame->height; i++)
00469 {
00470 memcpy(dst, src, frame->width);
00471 dst += pitch;
00472 src += frame->width;
00473 }
00474
00475 dst = buf + (frame->height * pitch);
00476 src = frame->buf + (frame->height * frame->width * 5/4);
00477 for (i = 0; i < chroma_height; i++)
00478 {
00479 memcpy(dst, src, chroma_width);
00480 dst += chroma_pitch;
00481 src += chroma_width;
00482 }
00483
00484 dst = buf + (frame->height * pitch * 5/4);
00485 src = frame->buf + (frame->height * frame->width);
00486 for (i = 0; i < chroma_height; i++)
00487 {
00488 memcpy(dst, src, chroma_width);
00489 dst += chroma_pitch;
00490 src += chroma_width;
00491 }
00492 }
00493 else if (buf && !hardware_conv)
00494 {
00495 AVPicture image_in, image_out;
00496 avpicture_fill(&image_out, (uint8_t*)buf,
00497 PIX_FMT_RGB32, frame->width, frame->height);
00498 image_out.linesize[0] = pitch;
00499 avpicture_fill(&image_in, frame->buf,
00500 PIX_FMT_YUV420P, frame->width, frame->height);
00501 myth_sws_img_convert(&image_out, PIX_FMT_RGB32, &image_in,
00502 PIX_FMT_YUV420P, frame->width, frame->height);
00503 }
00504 img->ReleaseBuffer();
00505 }
00506
00507 void VideoOutputD3D::ProcessFrame(VideoFrame *frame, OSD *osd,
00508 FilterChain *filterList,
00509 const PIPMap &pipPlayers,
00510 FrameScanType scan)
00511 {
00512 if (!m_render || !m_video)
00513 return;
00514
00515 QMutexLocker locker(&m_lock);
00516 if (IsErrored())
00517 {
00518 LOG(VB_GENERAL, LOG_ERR, LOC +
00519 "ProcessFrame() called while IsErrored is true.");
00520 return;
00521 }
00522
00523 bool gpu = codec_is_dxva2(video_codec_id);
00524
00525 if (gpu && frame && frame->codec != FMT_DXVA2)
00526 {
00527 LOG(VB_GENERAL, LOG_ERR, LOC + "Wrong frame format");
00528 return;
00529 }
00530
00531 bool dummy = false;
00532 bool pauseframe = false;
00533 if (!frame)
00534 {
00535 if (!gpu)
00536 {
00537 frame = vbuffers.GetScratchFrame();
00538 CopyFrame(vbuffers.GetScratchFrame(), &m_pauseFrame);
00539 }
00540 pauseframe = true;
00541 }
00542
00543 if (frame)
00544 dummy = frame->dummy;
00545 bool deint_proc = m_deinterlacing && (m_deintFilter != NULL) &&
00546 !dummy;
00547
00548 if (filterList && !gpu && !dummy)
00549 filterList->ProcessFrame(frame);
00550
00551 bool safepauseframe = pauseframe && !IsBobDeint() && !gpu;
00552 if (deint_proc && m_deinterlaceBeforeOSD &&
00553 (!pauseframe || safepauseframe))
00554 {
00555 m_deintFilter->ProcessFrame(frame, scan);
00556 }
00557
00558 if (!window.IsEmbedding())
00559 ShowPIPs(frame, pipPlayers);
00560
00561 if ((!pauseframe || safepauseframe) &&
00562 deint_proc && !m_deinterlaceBeforeOSD)
00563 {
00564 m_deintFilter->ProcessFrame(frame, scan);
00565 }
00566
00567
00568 m_render_valid |= m_render->Test(m_render_reset);
00569 if (m_render_reset)
00570 SetupContext();
00571
00572
00573 if (m_render_valid && !gpu && !dummy)
00574 UpdateFrame(frame, m_video);
00575
00576
00577 if (m_render_valid && gpu && !dummy)
00578 {
00579 m_render_valid = m_render->Test(m_render_reset);
00580 if (m_render_reset)
00581 CreateDecoder();
00582
00583 if (m_render_valid && frame)
00584 {
00585 m_render->CopyFrame(frame->buf, m_video);
00586 }
00587 else if (m_render_valid && pauseframe)
00588 {
00589 m_render->CopyFrame(m_pause_surface, m_video);
00590 }
00591 }
00592 }
00593
00594 void VideoOutputD3D::ShowPIP(VideoFrame *frame,
00595 MythPlayer *pipplayer,
00596 PIPLocation loc)
00597 {
00598 if (!pipplayer)
00599 return;
00600
00601 int pipw, piph;
00602 VideoFrame *pipimage = pipplayer->GetCurrentFrame(pipw, piph);
00603 const float pipVideoAspect = pipplayer->GetVideoAspect();
00604 const QSize pipVideoDim = pipplayer->GetVideoBufferSize();
00605 const bool pipActive = pipplayer->IsPIPActive();
00606 const bool pipVisible = pipplayer->IsPIPVisible();
00607 const uint pipVideoWidth = pipVideoDim.width();
00608 const uint pipVideoHeight = pipVideoDim.height();
00609
00610 if ((pipVideoAspect <= 0) || !pipimage ||
00611 !pipimage->buf || (pipimage->codec != FMT_YV12) || !pipVisible)
00612 {
00613 pipplayer->ReleaseCurrentFrame(pipimage);
00614 return;
00615 }
00616
00617 QRect position = GetPIPRect(loc, pipplayer);
00618 QRect dvr = window.GetDisplayVisibleRect();
00619
00620 m_pip_ready[pipplayer] = false;
00621 D3D9Image *m_pip = m_pips[pipplayer];
00622 if (!m_pip)
00623 {
00624 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Initialise PiP.");
00625 m_pip = new D3D9Image(m_render, QSize(pipVideoWidth, pipVideoHeight),
00626 true);
00627 m_pips[pipplayer] = m_pip;
00628 if (!m_pip->IsValid())
00629 {
00630 pipplayer->ReleaseCurrentFrame(pipimage);
00631 return;
00632 }
00633 }
00634
00635 QSize current = m_pip->GetSize();
00636 if ((uint)current.width() != pipVideoWidth ||
00637 (uint)current.height() != pipVideoHeight)
00638 {
00639 LOG(VB_PLAYBACK, LOG_INFO, LOC + "Re-initialise PiP.");
00640 delete m_pip;
00641 m_pip = new D3D9Image(m_render, QSize(pipVideoWidth, pipVideoHeight),
00642 true);
00643 m_pips[pipplayer] = m_pip;
00644 if (!m_pip->IsValid())
00645 {
00646 pipplayer->ReleaseCurrentFrame(pipimage);
00647 return;
00648 }
00649 }
00650 m_pip->UpdateVertices(position, QRect(0, 0, pipVideoWidth, pipVideoHeight),
00651 255, true);
00652 UpdateFrame(pipimage, m_pip);
00653 m_pip_ready[pipplayer] = true;
00654 if (pipActive)
00655 m_pip_active = m_pip;
00656
00657 pipplayer->ReleaseCurrentFrame(pipimage);
00658 }
00659
00660 void VideoOutputD3D::RemovePIP(MythPlayer *pipplayer)
00661 {
00662 if (!m_pips.contains(pipplayer))
00663 return;
00664
00665 QMutexLocker locker(&m_lock);
00666
00667 D3D9Image *m_pip = m_pips[pipplayer];
00668 if (m_pip)
00669 delete m_pip;
00670 m_pip_ready.remove(pipplayer);
00671 m_pips.remove(pipplayer);
00672 }
00673
00674 QStringList VideoOutputD3D::GetAllowedRenderers(
00675 MythCodecID myth_codec_id, const QSize &video_dim)
00676 {
00677 QStringList list;
00678 if (codec_is_std(myth_codec_id) || (codec_is_dxva2_hw(myth_codec_id) &&
00679 !getenv("NO_DXVA2")))
00680 {
00681 list += "direct3d";
00682 }
00683 return list;
00684 }
00685
00686 MythPainter *VideoOutputD3D::GetOSDPainter(void)
00687 {
00688 return m_osd_painter;
00689 }
00690
00691 bool VideoOutputD3D::ApproveDeintFilter(const QString& filtername) const
00692 {
00693 if (codec_is_std(video_codec_id))
00694 {
00695 return !filtername.contains("bobdeint") &&
00696 !filtername.contains("opengl") &&
00697 !filtername.contains("vdpau");
00698 }
00699
00700 return false;
00701 }
00702
00703 MythCodecID VideoOutputD3D::GetBestSupportedCodec(
00704 uint width, uint height, const QString &decoder,
00705 uint stream_type, bool no_acceleration,
00706 PixelFormat &pix_fmt)
00707 {
00708 #ifdef USING_DXVA2
00709 QSize size(width, height);
00710 bool use_cpu = no_acceleration;
00711 MythCodecID test_cid = (MythCodecID)(kCodec_MPEG1_DXVA2 + (stream_type - 1));
00712 use_cpu |= !codec_is_dxva2_hw(test_cid);
00713 pix_fmt = PIX_FMT_DXVA2_VLD;
00714 if ((decoder == "dxva2") && !getenv("NO_DXVA2") && !use_cpu)
00715 return test_cid;
00716 #endif
00717 return (MythCodecID)(kCodec_MPEG1 + (stream_type - 1));
00718 }
00719
00720
00721 void* VideoOutputD3D::GetDecoderContext(unsigned char* buf, uint8_t*& id)
00722 {
00723 (void)buf;
00724 (void)id;
00725 #ifdef USING_DXVA2
00726 if (m_decoder)
00727 return (void*)&m_decoder->m_context;
00728 #endif
00729 return NULL;
00730 }
00731
00732 bool VideoOutputD3D::CreateDecoder(void)
00733 {
00734 #ifdef USING_DXVA2
00735 QMutexLocker locker(&m_lock);
00736 if (m_decoder)
00737 DeleteDecoder();
00738 QSize video_dim = window.GetVideoDim();
00739 m_decoder = new DXVA2Decoder(NUM_DXVA2_BUFS, video_codec_id,
00740 video_dim.width(), video_dim.height());
00741 return (m_decoder && m_decoder->Init(m_render));
00742 #else
00743 return false;
00744 #endif
00745 }
00746
00747 void VideoOutputD3D::DeleteDecoder(void)
00748 {
00749 #ifdef USING_DXVA2
00750 QMutexLocker locker(&m_lock);
00751 delete m_decoder;
00752 m_decoder = NULL;
00753 #endif
00754 }
00755
00756