]> git.vomp.tv Git - vompclient.git/blob - omx/omx.h
Rewrite of ImageOMX to fix the PNG problem
[vompclient.git] / omx / omx.h
1 /*
2     Copyright 2021 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP.  If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 #ifndef OMX_H
21 #define OMX_H
22
23 #include <deque>
24 #include <mutex>
25 #include <thread>
26 #include <condition_variable>
27 #include <exception>
28
29 #include <bcm_host.h>
30
31 #define OMX_SKIP64BIT
32 #include <IL/OMX_Core.h>
33 #include <IL/OMX_Types.h>
34 #include <IL/OMX_Component.h>
35 #include <IL/OMX_Broadcom.h>
36
37 struct Event
38 {
39   OMX_PTR appdata;
40   OMX_EVENTTYPE eventType;
41   OMX_U32 data1;
42   OMX_U32 data2;
43   OMX_PTR event_data;
44
45   bool isNew{true};
46 };
47
48 struct EventWaiter
49 {
50   bool waiting;
51   OMX_EVENTTYPE eventType;
52   OMX_COMMANDTYPE command;
53   OMX_U32 port;
54   OMX_STATETYPE newState;
55   OMX_U32 flushPort;
56   std::condition_variable cond;
57   Event* receivedEvent{};
58 };
59
60 struct BufferWithOutputPort
61 {
62   OMX_BUFFERHEADERTYPE* bufhead;
63   std::condition_variable cond;
64   std::mutex mutex;
65   bool done{};
66 };
67
68 using Events = std::deque<Event*>;
69 using EventWaiters = std::deque<EventWaiter*>;
70
71 class OMX_Exception : public std::exception
72 {
73   public:
74     OMX_Exception(const char* tdesc, uint32_t terrCode) : desc(tdesc), errCode(terrCode) {}
75     const char* what() const noexcept { return desc; };
76     uint32_t errorCode() { return errCode; }
77   private:
78     const char* desc{};
79     uint32_t errCode{};
80 };
81
82
83 class LogNT;
84 class OMX_Image_Decode;
85 class OMX_EGL_Render;
86
87 class OMX
88 {
89   public:
90     OMX();
91     ~OMX();
92
93     //static bool OMX_Master_Init();
94
95     virtual bool init()=0;
96     virtual void shutdown()=0;
97
98     void enablePort(OMX_U32 port, bool enable, bool wait);  // throws
99     void changeState(OMX_STATETYPE type, bool wait = true);  // throws
100
101     // Static event callbacks
102
103     static OMX_ERRORTYPE scb_EventHandler(
104       OMX_IN OMX_HANDLETYPE handle, OMX_IN OMX_PTR appdata, OMX_IN OMX_EVENTTYPE event_type,
105       OMX_IN OMX_U32 data1, OMX_IN OMX_U32 data2, OMX_IN OMX_PTR event_data);
106
107     static OMX_ERRORTYPE scb_FillBufferDone(
108       OMX_IN OMX_HANDLETYPE handle, OMX_IN OMX_PTR appdata, OMX_IN OMX_BUFFERHEADERTYPE* buffer);
109
110     static OMX_ERRORTYPE scb_EmptyBufferDone(
111       OMX_IN OMX_HANDLETYPE handle, OMX_IN OMX_PTR appdata, OMX_IN OMX_BUFFERHEADERTYPE* buffer);
112
113     static constexpr const char* componentName_image_decode = "OMX.broadcom.image_decode";
114     static constexpr const char* componentName_egl_render = "OMX.broadcom.egl_render";
115
116   protected:
117     LogNT* log;
118
119     void flushCommands(OMX_U32 port, bool wait = true);  // throws
120
121     // static singleton object pointers
122     static OMX_Image_Decode* omx_image_decode;
123     static OMX_EGL_Render* omx_egl_render;
124
125     // static component handles provided by OMX
126     static OMX_HANDLETYPE handle_image_decode;
127     static OMX_HANDLETYPE handle_egl_render;
128
129     // A non-static copy of the above
130     OMX_HANDLETYPE componentHandle;
131
132     // In-object callbacks
133
134     virtual OMX_ERRORTYPE cb_EventHandler(
135       OMX_IN OMX_HANDLETYPE handle, OMX_IN OMX_PTR appdata, OMX_IN OMX_EVENTTYPE event_type,
136       OMX_IN OMX_U32 data1, OMX_IN OMX_U32 data2, OMX_IN OMX_PTR event_data) final;
137
138     virtual OMX_ERRORTYPE cb_FillBufferDone(
139       OMX_IN OMX_HANDLETYPE handle, OMX_IN OMX_PTR appdata, OMX_IN OMX_BUFFERHEADERTYPE* buffer)=0;
140
141     virtual OMX_ERRORTYPE cb_EmptyBufferDone(
142       OMX_IN OMX_HANDLETYPE handle, OMX_IN OMX_PTR appdata, OMX_IN OMX_BUFFERHEADERTYPE* buffer)=0;
143
144     /* Incoming events processing stuff
145      *
146      * Events are handled entirely by the base class which runs a thread to match incoming
147      * events with a class and a particular sleeping calling thread. It will wake the correct
148      * call, if wait = true in the original call. If not it will just delete the incoming event.
149      *
150      * FillBufferDone and EmptyBufferDone will call the derived object's functions.
151      */
152
153     static void initEventsProcessing();
154     static void stopEventsProcessing();
155
156     static Events events;
157     static std::mutex eventsMutex;
158     static std::mutex eventsProcessorMutex;
159     static std::thread eventsProcessorThread;
160     static std::condition_variable eventsProcessorCond;
161     static bool eventsProcessorWake;
162     static bool eventsProcessorShutdownNow;
163     static int eventsProcessorUsageCount;
164     static void eventsProcessorLoop();
165
166     static EventWaiters eventWaiters;
167     static std::mutex eventWaitersMutex;
168
169 };
170
171 #endif