summaryrefslogtreecommitdiff
path: root/omx.h
blob: f16714a57c096987084d8874389f38ecd88b08c3 (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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/*
 * rpihddevice - VDR HD output device for Raspberry Pi
 * Copyright (C) 2014, 2015, 2016 Thomas Reufer
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#ifndef OMX_H
#define OMX_H

#include <vdr/thread.h>
#include <vdr/tools.h>
#include "tools.h"

extern "C" {
#include "ilclient.h"
}

#define OMX_INVALID_PTS -1

#define OMX_INIT_STRUCT(a) \
	memset(&(a), 0, sizeof(a)); \
	(a).nSize = sizeof(a); \
	(a).nVersion.s.nVersionMajor = OMX_VERSION_MAJOR; \
	(a).nVersion.s.nVersionMinor = OMX_VERSION_MINOR; \
	(a).nVersion.s.nRevision = OMX_VERSION_REVISION; \
	(a).nVersion.s.nStep = OMX_VERSION_STEP

#define BUFFERSTAT_FILTER_SIZE 64

class cOmxEvents;
class cOmxEventHandler;

/* ------------------------------------------------------------------------- */

class cOmx : public cThread
{

public:

	cOmx();
	virtual ~cOmx();
	int Init(int display, int layer);
	int DeInit(void);

	void AddEventHandler(cOmxEventHandler *handler);
	void RemoveEventHandler(cOmxEventHandler *handler);

	enum eOmxComponent {
		eClock = 0,
		eVideoDecoder,
		eVideoFx,
		eVideoScheduler,
		eVideoRender,
		eAudioRender,
		eNumComponents,
		eInvalidComponent
	};

	bool CreateComponent(eOmxComponent comp, bool enableInputBuffers = false);
	void CleanupComponent(eOmxComponent comp);
	bool ChangeComponentState(eOmxComponent comp, OMX_STATETYPE state);
	bool FlushComponent(eOmxComponent comp, int port);

	bool EnablePortBuffers(eOmxComponent comp, int port);
	void DisablePortBuffers(eOmxComponent comp, int port,
			OMX_BUFFERHEADERTYPE *buffers = 0);

	OMX_BUFFERHEADERTYPE* GetBuffer(eOmxComponent comp, int port);
	bool EmptyBuffer(eOmxComponent comp, OMX_BUFFERHEADERTYPE *buf);

	bool GetParameter(eOmxComponent comp, OMX_INDEXTYPE index, OMX_PTR param);
	bool SetParameter(eOmxComponent comp, OMX_INDEXTYPE index, OMX_PTR param);

	bool GetConfig(eOmxComponent comp, OMX_INDEXTYPE index, OMX_PTR config);
	bool SetConfig(eOmxComponent comp, OMX_INDEXTYPE index, OMX_PTR config);

	enum eOmxTunnel {
		eVideoDecoderToVideoFx = 0,
		eVideoFxToVideoScheduler,
		eVideoSchedulerToVideoRender,
		eClockToVideoScheduler,
		eClockToAudioRender,
		eNumTunnels
	};

	void SetTunnel(eOmxTunnel tunnel, eOmxComponent srcComp, int srcPort,
			eOmxComponent dstComp, int dstPort);

	bool SetupTunnel(eOmxTunnel tunnel, int timeout = 0);
	void DisableTunnel(eOmxTunnel tunnel);
	void TeardownTunnel(eOmxTunnel tunnel);
	void FlushTunnel(eOmxTunnel tunnel);

	static OMX_TICKS ToOmxTicks(int64_t val);
	static int64_t FromOmxTicks(OMX_TICKS &ticks);
	static void PtsToTicks(int64_t pts, OMX_TICKS &ticks);
	static int64_t TicksToPts(OMX_TICKS &ticks);

	int64_t GetSTC(void);
	bool IsClockRunning(void);

	enum eClockState {
		eClockStateRun,
		eClockStateStop,
		eClockStateWaitForVideo,
		eClockStateWaitForAudio,
		eClockStateWaitForAudioVideo
	};

	void StartClock(bool waitForVideo = false, bool waitForAudio = false);
	void StopClock(void);
	void ResetClock(void);

	void SetClockScale(OMX_S32 scale);
	bool IsClockFreezed(void) { return m_clockScale == 0; }

	enum eClockReference {
		eClockRefAudio,
		eClockRefVideo,
		eClockRefNone
	};

	void SetClockReference(eClockReference clockReference);
	void SetClockLatencyTarget(void);

	void SetDisplayMode(bool letterbox, bool noaspect);
	void SetPixelAspectRatio(int width, int height);
	void SetDisplayRegion(int x, int y, int width, int height);
	void SetDisplay(int display, int layer);

#ifdef DEBUG_BUFFERS
	static void DumpBuffer(OMX_BUFFERHEADERTYPE *buf, const char *prefix = "");
#endif

private:

	virtual void Action(void);

	static const char* errStr(int err);

	ILCLIENT_T 	*m_client;
	COMPONENT_T	*m_comp[cOmx::eNumComponents + 1];
	TUNNEL_T 	 m_tun[cOmx::eNumTunnels + 1];

	eClockReference	m_clockReference;
	OMX_S32 m_clockScale;

	cOmxEvents *m_portEvents;

	cList<cOmxEventHandler> *m_eventHandlers;

	void HandlePortSettingsChanged(unsigned int portId);
	bool IsBufferStall(void);

	static void OnBufferEmpty(void *instance, COMPONENT_T *comp);
	static void OnPortSettingsChanged(void *instance, COMPONENT_T *comp, OMX_U32 data);
	static void OnEndOfStream(void *instance, COMPONENT_T *comp, OMX_U32 data);
	static void OnError(void *instance, COMPONENT_T *comp, OMX_U32 data);
	static void OnConfigChanged(void *instance, COMPONENT_T *comp, OMX_U32 data);
};

/* ------------------------------------------------------------------------- */

class cOmxEventHandler : public cListObject
{

public:

	virtual void Tick(void) { };
	virtual void PortSettingsChanged(int port) { };
	virtual void EndOfStreamReceived(int port) { };
	virtual void BufferEmptied(cOmx::eOmxComponent comp) { };
	virtual void BufferStalled(void) { };
};

#endif