MythTV  0.26-pre
videoout_d3d.cpp
Go to the documentation of this file.
00001 // -*- Mode: c++ -*-
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     // FIXME this now requires the context to be re-created
00124     /*
00125     QMutexLocker locker(&m_lock);
00126     window.SetDisplayVisibleRect(QRect(QPoint(0, 0), new_size));
00127     window.SetDisplayAspect(
00128         ((float)new_size.width()) / new_size.height());
00129 
00130     MoveResize();
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     // TODO: Initialise m_hEmbedWnd?
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     // TODO - add a size check
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     // Test the device
00568     m_render_valid |= m_render->Test(m_render_reset);
00569     if (m_render_reset)
00570         SetupContext();
00571 
00572     // Update a software decoded frame
00573     if (m_render_valid && !gpu && !dummy)
00574         UpdateFrame(frame, m_video);
00575 
00576     // Update a GPU decoded frame
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 /* vim: set expandtab tabstop=4 shiftwidth=4: */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends