Re: WMV-HD тормозит в VMR9 renderless :(
От: Денис Евсеев Ниоткуда  
Дата: 13.10.05 05:48
Оценка:
Здравствуйте, cencio, Вы писали:

C>собственно сабж.

C>Пишу плеер интегрированный в прогу на основе VMR9 renderless (там еще много чего рисуется,без renderless не обойтись). Возникли проблемы с
C>проигрыванием WMV-HD файлов — сильно тормозит на видео клипах с разрешением 1280х720 и 1920х1080 — около 10 фпс и звук рваный , а в WMP10
C>показывается нормально, при этом замечено что WMP Classic в VMR9 renderless ведет себя также. В коде который обрабатывает полученые кадры
C>исправить ничего не выходит — IVMRImagePresenter9::PresentImage выдает новые кадры по 10 штук в секунду, не больше

10 вместо 60? Что-то не так с аллокатором-презентером… Допустим, что проблема именно в видео, а не в декодере и не в Вашей процедуре отрисовки не-видео частей. В XP2 серпаке мы добавили новый интерфейс, IVMRSurfaceAllocatorEx9, подробнее здесь. Пользоваться им довольно легко: вместо IVMRSurfaceAllocator9 в Вашем allocator-presenter'e. Там только один метод добавлен, GetSurfaceEx. VMR9 вызывает этот метод точно так же, как он вызывал GetSurface, но в данном случае он передает дополнительный параметр RECT* lprcDst. Это прямоугольник, куда выводится видео. Это позволяет оптимизировать композицию видео (деинтерлейсинг+блендинг), так что в идеале аллокатор-презентер не должен более трансформировать этот прямоугольник, а просто выводить как есть.

//
// * CAllocatorPresenterEx9::GetSurfaceEx
// 
STDMETHODIMP
CAllocatorPresenterEx9::GetSurfaceEx(
    DWORD_PTR dwUserID,
    DWORD SurfaceIndex,
    DWORD SurfaceFlags,
    IDirect3DSurface9** lplpSurface,
    RECT* lprcDst
    )
{
    HRESULT hr = S_OK;

    hr = GetSurface( dwUserID, SurfaceIndex, SurfaceFlags, lplpSurface );

    if( FALSE == m_fFullScreen )
    {
       *lprcDst = m_rcMovieDestinationRect;
        m_rcMovieSourceSize = *lprcDst;
    }
    else
    {
        memcpy( lprcDst, &(m_rcDesktopRect), sizeof( RECT )); 
    }
    return hr;
}


Далее, в методе PresentSurface, рисуем этот прямоугольник вот так:
        m_pDirectDrawSwapChainFrontBuffer->Present( &m_rcMovieSrcSize,
                                                &m_rcMovieDstSize,
                                                NULL, NULL, 0 );

(мы используем две swap chains; VMR9 всегда пишет в m_pDirectDrawSwapChainDecode, мы всегда рисуем m_pDirectDrawSwapChainFrontBuffer, меняем эти чейнс либо вручную либо они сами меняются местами, в зависимости от установок swapping видео девайса.

Наконец, из приложения управляем этим прямоугольником как показано ниже, при начальной инициализации и на каждое сообщение WM_SIZE; здесь m_hVideo — видеоокно, m_pAP — наш аллокатор

HRESULT Player::SetVideoWindow()
{
        HRESULT hr = S_OK;
        RECT rcDest; // client area of the video window
        RECT rcVideo = rcDest;  // rectangle for the video position
    
        GetClientRect(m_hVideo, &rcDest);

        if( !m_pAP )
            return S_OK;

        // ...
        {
            RECT rcMovie;
            SIZE ar;

            m_pAP->GetMoviePosition( & rcMovie ); // читаем m_rcMovieSourceSize  из аллокатора-презентера

            ar.cx = rcMovie.right - rcMovie.left;
            ar.cy = rcMovie.bottom - rcMovie.top;

            LetterBoxRect( ar, rcDest, &rcVideo ); // сохранить аспект

            m_pAP->SetMoviePosition( &rcVideo ); // пишем m_rcMovieDestinationRect а аллокатор-презентер
            m_pAP->PresentImage( 0, NULL );

            HBRUSH brushBlack = CreateSolidBrush( RGB(0x00, 0x00, 0x00));
            PaintClippedArea( m_hVideo, brushBlack, rcVideo, rcDest ); // зарисовать оставшиеся полосы по краям

        }
        else
        {
            hr = m_pAP->SetMoviePosition( &rcVideo );
        }
        return hr;
    }


Этот прием может дать довольно ощутимое улучшение производительности. Однако я также отсоветовал бы использовать слишком много рисования не-видео в презентере. HD есть HD, и у презентера очень немного времени на прорисовку. Другим качественным улучшением будет использование YUV-mixing mode у VMR9 (подробнее здесь). Это накладывает определенные ограничения на клиентскую программу, но дает наиболее оптимальную производительность. Не все карточки поддерживают этот режим, его весьма желательно имплементировать в клиенте, но обязательно дублировать обычным режимом.

С уважением,
Денис Евсеев
Media Technology group
Microsoft

This posting is provided "AS IS" with no warranties, and confers no rights. You assume all risk for your use.
© 2005 Microsoft Corporation. All rights reserved.
С уважением,
Денис Евсеев,
Windows EXperience Media & Devices,
Microsoft corp.
This posting is provided "AS IS" with no warranties, and confers no rights. You assume all risk for your use. © 2007 Microsoft Corporation. All rights reserved.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.