summaryrefslogtreecommitdiffstats
path: root/src/plugins/multimedia/windows/player/mfvideorenderercontrol.cpp
blob: 7c79c3a8aba0863c75f67d671534a65410c760ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#include "mfvideorenderercontrol_p.h"
#include "mfactivate_p.h"

#include "evrcustompresenter_p.h"

#include <private/qplatformvideosink_p.h>

QT_BEGIN_NAMESPACE

class EVRCustomPresenterActivate : public MFAbstractActivate
{
public:
    EVRCustomPresenterActivate(QVideoSink *sink);

    STDMETHODIMP ActivateObject(REFIID riid, void **ppv) override;
    STDMETHODIMP ShutdownObject() override;
    STDMETHODIMP DetachObject() override;

    void setSink(QVideoSink *sink);
    void setCropRect(QRect cropRect);

private:
    // Destructor is not public. Caller should call Release.
    ~EVRCustomPresenterActivate() override { }

    EVRCustomPresenter *m_presenter;
    QVideoSink *m_videoSink;
    QRect m_cropRect;
    QMutex m_mutex;
};


MFVideoRendererControl::MFVideoRendererControl(QObject *parent)
    : QObject(parent)
{
}

MFVideoRendererControl::~MFVideoRendererControl()
{
    releaseActivate();
}

void MFVideoRendererControl::releaseActivate()
{
    if (m_sink)
        m_sink->platformVideoSink()->setVideoFrame(QVideoFrame());

    if (m_presenterActivate) {
        m_presenterActivate->ShutdownObject();
        m_presenterActivate->Release();
        m_presenterActivate = NULL;
    }

    if (m_currentActivate) {
        m_currentActivate->ShutdownObject();
        m_currentActivate->Release();
    }
    m_currentActivate = NULL;
}

void MFVideoRendererControl::setSink(QVideoSink *sink)
{
    m_sink = sink;

    if (m_presenterActivate)
        m_presenterActivate->setSink(m_sink);
}

void MFVideoRendererControl::setCropRect(const QRect &cropRect)
{
    if (m_presenterActivate)
        m_presenterActivate->setCropRect(cropRect);
}

IMFActivate* MFVideoRendererControl::createActivate()
{
    releaseActivate();

    if (m_sink) {
        // Create the EVR media sink, but replace the presenter with our own
        if (SUCCEEDED(MFCreateVideoRendererActivate(::GetShellWindow(), &m_currentActivate))) {
            m_presenterActivate = new EVRCustomPresenterActivate(m_sink);
            m_currentActivate->SetUnknown(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE, m_presenterActivate);
        }
    }

    return m_currentActivate;
}

EVRCustomPresenterActivate::EVRCustomPresenterActivate(QVideoSink *sink)
    : MFAbstractActivate()
    , m_presenter(0)
    , m_videoSink(sink)
{ }

HRESULT EVRCustomPresenterActivate::ActivateObject(REFIID riid, void **ppv)
{
    if (!ppv)
        return E_INVALIDARG;
    QMutexLocker locker(&m_mutex);
    if (!m_presenter) {
        m_presenter = new EVRCustomPresenter(m_videoSink);
        m_presenter->setCropRect(m_cropRect);
    }
    return m_presenter->QueryInterface(riid, ppv);
}

HRESULT EVRCustomPresenterActivate::ShutdownObject()
{
    // The presenter does not implement IMFShutdown so
    // this function is the same as DetachObject()
    return DetachObject();
}

HRESULT EVRCustomPresenterActivate::DetachObject()
{
    QMutexLocker locker(&m_mutex);
    if (m_presenter) {
        m_presenter->Release();
        m_presenter = 0;
    }
    return S_OK;
}

void EVRCustomPresenterActivate::setSink(QVideoSink *sink)
{
    QMutexLocker locker(&m_mutex);
    if (m_videoSink == sink)
        return;

    m_videoSink = sink;

    if (m_presenter)
        m_presenter->setSink(sink);
}

void EVRCustomPresenterActivate::setCropRect(QRect cropRect)
{
    QMutexLocker locker(&m_mutex);
    if (m_cropRect == cropRect)
        return;

    m_cropRect = cropRect;

    if (m_presenter)
        m_presenter->setCropRect(cropRect);
}

QT_END_NAMESPACE