nx_server_plugin_sdk 1.0 Server Plugin SDK

rpi_omx.h
1 // Copyright 2018-present Network Optix, Inc. Licensed under MPL 2.0: www.mozilla.org/MPL/2.0/
2
3 #ifndef _RPI_OMX_
4 #define _RPI_OMX_
5
6 #include <atomic>
7 #include <cstdio>
8 #include <exception>
9 #include <vector>
10
11 #define OMX
12 #define OMX_SKIP64BIT
13
14 #include <IL/OMX_Broadcom.h>
15 #include <IL/OMX_Component.h>
16 #include <IL/OMX_Core.h>
17 #include <IL/OMX_Video.h>
18
19 #include "rpi_omx_broadcom.h"
20
21 #define debug_print(...) fprintf(stderr, "[RPiCamera] " __VA_ARGS__)
22 #define ERR_OMX(err, msg) if ((err) != OMX_ErrorNone) throw OMXExeption(err, __FILE__, __LINE__, msg)
23
25 namespace rpi_omx
26 {
27 typedef broadcom::ComponentType ComponentType;
28 using broadcom::componentType2name;
29 using broadcom::componentPortsCount;
30
31 using broadcom::VcosSemaphore;
32 using Lock = broadcom::VcosLock;
33
34 const char * err2str(OMX_ERRORTYPE error);
35 void printEvent(const char * compName, OMX_HANDLETYPE hComponent, OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2);
36 void dump_portdef(OMX_PARAM_PORTDEFINITIONTYPE * portdef);
37 void dump_formats(OMX_VIDEO_PARAM_PORTFORMATTYPE * portformat);
38
39 extern OMX_CALLBACKTYPE cbsEvents;
40
42 class OMXExeption : public std::exception
43 {
44 public:
45 static const unsigned MAX_LEN = 256;
46
47 OMXExeption(OMX_ERRORTYPE errCode, const char * file, unsigned line, const char * msg = nullptr)
48 : m_errCode(errCode)
49 {
50 setLastError(errCode);
51
52 if (msg && msg[0])
53 snprintf(m_msg, MAX_LEN, "%s:%d OpenMAX IL error: 0x%08x. %s", file, line, errCode, msg);
54 else
55 snprintf(m_msg, MAX_LEN, "%s:%d OpenMAX IL error: 0x%08x", file, line, errCode);
56 }
57
58 OMX_ERRORTYPE code() const { return m_errCode; }
59 virtual const char * what() const noexcept override { return m_msg; }
60
61 static bool hasError() { return lastError() || eventError(); }
62 static uint32_t lastError() { return m_lastError; }
63 static uint32_t eventError() { return m_eventError; }
64 static void setLastError(uint32_t code = OMX_ErrorNone) { m_lastError.store(code); }
65 static void setEventError(uint32_t code = OMX_ErrorNone) { m_eventError.store(code); }
66
67 private:
68 OMX_ERRORTYPE m_errCode;
69 char m_msg[MAX_LEN];
70 static std::atomic<uint32_t> m_lastError;
71 static std::atomic<uint32_t> m_eventError;
72 };
73
75 struct VideoFromat
76 {
77 typedef enum
78 {
79 RATIO_4x3,
80 RATIO_16x9
81 } Ratio;
82
83 unsigned width;
84 unsigned height;
85 unsigned framerate;
86 Ratio ratio;
87 bool fov;
88 };
89
90 // resolution list from PiCam
100 static const VideoFromat VF_1920x1080 = { 1920, 1080, 30, VideoFromat::RATIO_16x9, false };
101 static const VideoFromat VF_1920x1080x25 = { 1920, 1080, 25, VideoFromat::RATIO_16x9, false };
102 static const VideoFromat VF_1280x960 = { 1280, 960, 30, VideoFromat::RATIO_4x3, true };
103 static const VideoFromat VF_1280x720 = { 1280, 720, 30, VideoFromat::RATIO_16x9, true };
104 static const VideoFromat VF_640x480 = { 640, 480, 30, VideoFromat::RATIO_4x3, true };
105
106 static const VideoFromat VF_RESIZED_640x480 = VF_640x480;
107 static const VideoFromat VF_RESIZED_320x240 = { 320, 240, 30, VideoFromat::RATIO_4x3, true };
108 static const VideoFromat VF_RESIZED_256x192 = { 256, 192, 30, VideoFromat::RATIO_4x3, true };
109 static const VideoFromat VF_RESIZED_160x120 = { 160, 120, 30, VideoFromat::RATIO_4x3, true };
110 static const VideoFromat VF_RESIZED_128x96 = { 128, 96, 30, VideoFromat::RATIO_4x3, true };
111
112 static const VideoFromat VF_RESIZED_960x540 = { 960, 540, 30, VideoFromat::RATIO_16x9, false };
113 static const VideoFromat VF_RESIZED_640x360 = { 640, 360, 30, VideoFromat::RATIO_16x9, false };
114 static const VideoFromat VF_RESIZED_480x270 = { 480, 270, 30, VideoFromat::RATIO_16x9, false };
115 static const VideoFromat VF_RESIZED_384x216 = { 384, 216, 30, VideoFromat::RATIO_16x9, false };
116 static const VideoFromat VF_RESIZED_320x180 = { 320, 180, 30, VideoFromat::RATIO_16x9, false };
117 static const VideoFromat VF_RESIZED_240x135 = { 240, 135, 30, VideoFromat::RATIO_16x9, false };
118
120 template <typename T>
121 class Parameter
122 {
123 public:
124 Parameter()
125 {
126 init();
127 }
128
129 void init()
130 {
131 memset(&m_param, 0, sizeof(m_param));
132 m_param.nSize = sizeof(m_param);
133 m_param.nVersion.nVersion = OMX_VERSION;
134 m_param.nVersion.s.nVersionMajor = OMX_VERSION_MAJOR;
135 m_param.nVersion.s.nVersionMinor = OMX_VERSION_MINOR;
136 m_param.nVersion.s.nRevision = OMX_VERSION_REVISION;
137 m_param.nVersion.s.nStep = OMX_VERSION_STEP;
138 }
139
140 T& operator * () { return m_param; }
141 T* operator & () { return &m_param; }
142 T* operator -> () { return &m_param; }
143
144 const T& operator * () const { return m_param; }
145 const T* operator & () const { return &m_param; }
146 const T* operator -> () const { return &m_param; }
147
148 private:
149 T m_param;
150 };
151
153 class Buffer
154 {
155 public:
156 Buffer()
157 : m_ppBuffer(nullptr),
158 m_fillDone(false)
159 {}
160
161 bool filled() const { return m_fillDone; }
162 void setFilled(bool val = true) { m_fillDone = val; }
163
164 OMX_BUFFERHEADERTYPE ** pHeader() { return &m_ppBuffer; }
165 OMX_BUFFERHEADERTYPE * header() { return m_ppBuffer; }
166 OMX_U32 flags() const { return m_ppBuffer->nFlags; }
167 OMX_U32& flags() { return m_ppBuffer->nFlags; }
168 OMX_TICKS timeStamp() const { return m_ppBuffer->nTimeStamp; } // need OMX_IndexParamCommonUseStcTimestamps
169
170 OMX_U8 * data() { return m_ppBuffer->pBuffer + m_ppBuffer->nOffset; }
171 OMX_U32 dataSize() const { return m_ppBuffer->nFilledLen; }
172 OMX_U32 allocSize() const { return m_ppBuffer->nAllocLen; }
173
174 private:
175 OMX_BUFFERHEADERTYPE * m_ppBuffer;
176 std::atomic_bool m_fillDone;
177 };
178
180 class Component
181 {
182 public:
183 OMX_HANDLETYPE& component() { return m_component; }
184 ComponentType type() const { return m_type; }
185 const char * name() const { return componentType2name(m_type); }
186 unsigned numPorts() const { return componentPortsCount(m_type); }
187
188 void dumpPort(OMX_U32 nPortIndex, bool dumpFormats = false)
189 {
190 Parameter<OMX_PARAM_PORTDEFINITIONTYPE> portdef;
191 getPortDefinition(nPortIndex, portdef);
192
193 dump_portdef(&portdef);
194
195 if (dumpFormats)
196 {
197 Parameter<OMX_VIDEO_PARAM_PORTFORMATTYPE> portformat;
198 portformat->nPortIndex = nPortIndex;
199 portformat->nIndex = 0;
200
201 for (;; portformat->nIndex++)
202 {
203 OMX_ERRORTYPE err = OMX_GetParameter(m_component, OMX_IndexParamVideoPortFormat, &portformat);
204 if (err != OMX_ErrorNone)
205 break;
206
207 dump_formats(&portformat);
208 }
209 }
210 }
211
212 OMX_STATETYPE state()
213 {
214 OMX_STATETYPE state;
215 ERR_OMX( OMX_GetState(m_component, &state), "OMX_GetState" );
216 return state;
217 }
218
219 void switchState(OMX_STATETYPE newState)
220 {
221 unsigned value = m_eventState + 1;
222 ERR_OMX( OMX_SendCommand(m_component, OMX_CommandStateSet, newState, NULL), "switch state");
223
224 if (! waitValue(m_eventState, value))
225 debug_print("%s - lost state changed event\n", name());
226
227 if (state() != newState)
228 ERR_OMX( OMX_ErrorInvalidState, "can't switch state" );
229 }
230
231 unsigned count2wait(OMX_U32 nPortIndex) const { return (nPortIndex == OMX_ALL) ? numPorts() : 1; }
232
233 void enablePort(OMX_U32 nPortIndex = OMX_ALL)
234 {
235 unsigned value = m_eventEnabled + count2wait(nPortIndex);
236 ERR_OMX( OMX_SendCommand(m_component, OMX_CommandPortEnable, nPortIndex, NULL), "enable port");
237
238 if (! waitValue(m_eventEnabled, value))
239 debug_print("%s - port %d lost enable port event\n", name(), nPortIndex);
240 }
241
242 void disablePort(OMX_U32 nPortIndex = OMX_ALL)
243 {
244 unsigned value = m_eventDisabled + count2wait(nPortIndex);
245 ERR_OMX( OMX_SendCommand(m_component, OMX_CommandPortDisable, nPortIndex, NULL), "disable port");
246
247 if (! waitValue(m_eventDisabled, value))
248 debug_print("%s - port %d lost disable port event\n", name(), nPortIndex);
249 }
250
251 void flushPort(OMX_U32 nPortIndex = OMX_ALL)
252 {
253 unsigned value = m_eventFlushed + count2wait(nPortIndex);
254 ERR_OMX( OMX_SendCommand(m_component, OMX_CommandFlush, nPortIndex, NULL), "flush buffers");
255
256 if (! waitValue(m_eventFlushed, value))
257 debug_print("%s - port %d lost flush port event\n", name(), nPortIndex);
258 }
259
260 void getPortDefinition(OMX_U32 nPortIndex, Parameter<OMX_PARAM_PORTDEFINITIONTYPE>& portDef)
261 {
262 portDef->nPortIndex = nPortIndex;
263 ERR_OMX( OMX_GetParameter(m_component, OMX_IndexParamPortDefinition, &portDef), "get port definition");
264 }
265
266 void setPortDefinition(OMX_U32 nPortIndex, Parameter<OMX_PARAM_PORTDEFINITIONTYPE>& portDef)
267 {
268 portDef->nPortIndex = nPortIndex;
269 ERR_OMX( OMX_SetParameter(m_component, OMX_IndexParamPortDefinition, &portDef), "set port definition");
270 }
271
272 void allocBuffers(OMX_U32 nPortIndex, Buffer& buffer)
273 {
274 Parameter<OMX_PARAM_PORTDEFINITIONTYPE> portDef;
275 getPortDefinition(nPortIndex, portDef);
276
277 ERR_OMX( OMX_AllocateBuffer(m_component, buffer.pHeader(), nPortIndex, 0, portDef->nBufferSize), "OMX_AllocateBuffer");
278 }
279
280 void freeBuffers(OMX_U32 nPortIndex, Buffer& buffer)
281 {
282 ERR_OMX( OMX_FreeBuffer(m_component, nPortIndex, buffer.header()), "OMX_FreeBuffer");
283 }
284
285 void callFillThisBuffer(Buffer& buffer)
286 {
287 ERR_OMX( OMX_FillThisBuffer(m_component, buffer.header()), "OMX_FillThisBuffer");
288 }
289
290 // from callbacks
291
292 void eventCmdComplete(OMX_U32 cmd, OMX_U32 /*nPortIndex*/)
293 {
294 switch (cmd)
295 {
296 case OMX_CommandStateSet:
297 ++m_eventState;
298 break;
299
300 case OMX_CommandFlush:
301 ++m_eventFlushed;
302 break;
303
304 case OMX_CommandPortDisable:
305 ++m_eventDisabled;
306 break;
307
308 case OMX_CommandPortEnable:
309 ++m_eventEnabled;
310 break;
311
312 case OMX_CommandMarkBuffer:
313 default:
314 break;
315 }
316 }
317
318 void eventPortSettingsChanged(OMX_U32 /*nPortIndex*/)
319 {
320 }
321
322 //VcosSemaphore * semaphore() { return &m_sem; }
323
324 protected:
325 OMX_HANDLETYPE m_component;
326 ComponentType m_type;
327 //VcosSemaphore m_sem; // commented: synced by atomics
328
329 Component(ComponentType type, OMX_PTR pAppData, OMX_CALLBACKTYPE * callbacks)
330 : m_type(type),
331 //m_sem("rpi_cam:event"),
332 m_eventState(0),
333 m_eventFlushed(0),
334 m_eventDisabled(0),
335 m_eventEnabled(0)
336 {
337 OMX_STRING xName = const_cast<OMX_STRING>(name());
338 ERR_OMX( OMX_GetHandle(&m_component, xName, pAppData, callbacks), "OMX_GetHandle");
339
340 disablePort();
341 }
342
343 ~Component()
344 {
345 try
346 {
347 ERR_OMX( OMX_FreeHandle(m_component), "OMX_FreeHandle" );
348 }
349 catch (const OMXExeption& e)
350 {
351 OMXExeption::setLastError(e.code());
352 debug_print("OMXExeption: OMX_FreeHandle(), %s", e.what());
353 }
354 }
355
356 // type_ equals to first port number
357 unsigned n2idx(OMX_U32 nPortIndex) const { return nPortIndex - m_type; }
358 unsigned idx2n(unsigned idx) const { return m_type + idx; }
359
360 private:
361 std::atomic<uint32_t> m_eventState;
362 std::atomic<uint32_t> m_eventFlushed;
363 std::atomic<uint32_t> m_eventDisabled;
364 std::atomic<uint32_t> m_eventEnabled;
365
366 bool waitValue(std::atomic<uint32_t>& value, unsigned wantedValue)
367 {
368 static const unsigned WAIT_CHANGES_US = 10000;
369 static const unsigned MAX_WAIT_COUNT = 200;
370
371 for (unsigned i = 0; i < MAX_WAIT_COUNT; ++i)
372 {
373 if (value >= wantedValue)
374 return true;
375
376 usleep(WAIT_CHANGES_US);
377 }
378
379 return false;
380 }
381 };
382
384 class Camera : public Component
385 {
386 public:
387 static const ComponentType cType = broadcom::CAMERA;
388
389 static const unsigned OPORT_PREVIEW = 70;
390 static const unsigned OPORT_VIDEO = 71;
391 static const unsigned OPORT_STILL = 72;
392 static const unsigned IPORT = 73;
393
394 static const unsigned CAM_DEVICE_NUMBER = 0;
395
396 static int32_t align(unsigned x, unsigned y)
397 {
398 return (x + y - 1) & (~(y - 1));
399 }
400
401 // The recommended initialisation sequence:
402 // 1. Create component.
403 // 2. Use OMX_IndexConfigRequestCallback to request callbacks on OMX_IndexParamCameraDeviceNumber.
404 // 3. Set OMX_IndexParamISPTunerName.
405 // 4. Set OMX_IndexParamCameraFlashType.
406 // 5. Set OMX_IndexParamCameraDeviceNumber.
407 // 6. Wait for the callback that OMX_IndexParamCameraDeviceNumber has changed.
408 // At this point, all the drivers have been loaded. Other settings can be applied whilst waiting for this event.
409 // 7. Query for OMX_IndexConfigCameraSensorModes as required.
410 // 8. Change state to IDLE, and proceed as required.
411 Camera()
412 : Component(cType, (OMX_PTR) this, &cbsEvents),
413 m_ready(false)
414 {
415 requestCallback();
416 setDeviceNumber(CAM_DEVICE_NUMBER);
417
418 Parameter<OMX_PARAM_TIMESTAMPMODETYPE> tsMode;
419 tsMode->eTimestampMode = OMX_TimestampModeRawStc;
420
421 ERR_OMX( OMX_SetConfig(m_component, OMX_IndexParamCommonUseStcTimestamps, &tsMode), "camera timestamp mode");
422 }
423
424 void requestCallback()
425 {
426 Parameter<OMX_CONFIG_REQUESTCALLBACKTYPE> cbtype;
427 cbtype->nPortIndex = OMX_ALL;
428 cbtype->nIndex = OMX_IndexParamCameraDeviceNumber;
429 cbtype->bEnable = OMX_TRUE;
430
431 ERR_OMX( OMX_SetConfig(m_component, OMX_IndexConfigRequestCallback, &cbtype), "request callbacks");
432 }
433
434 void setDeviceNumber(unsigned camNumber)
435 {
436 Parameter<OMX_PARAM_U32TYPE> device;
437 device->nPortIndex = OMX_ALL;
438 device->nU32 = camNumber;
439
440 ERR_OMX( OMX_SetParameter(m_component, OMX_IndexParamCameraDeviceNumber, &device), "set camera device number");
441 }
442
443 void setVideoFromat(const VideoFromat& videoFormat)
444 {
445 Parameter<OMX_PARAM_PORTDEFINITIONTYPE> portDef;
446 getPortDefinition(OPORT_VIDEO, portDef);
447
448 portDef->format.video.nFrameWidth = videoFormat.width;
449 portDef->format.video.nFrameHeight = videoFormat.height;
450 portDef->format.video.xFramerate = videoFormat.framerate << 16;
451 portDef->format.video.nStride = align(portDef->format.video.nFrameWidth, portDef->nBufferAlignment);
452 portDef->format.video.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar;
453
454 setPortDefinition(OPORT_VIDEO, portDef);
455 //setFramerate(videoFormat.framerate);
456 }
457
458 void setFramerate(unsigned fps)
459 {
460 Parameter<OMX_CONFIG_FRAMERATETYPE> framerate;
461 framerate->xEncodeFramerate = fps << 16;
462 framerate->nPortIndex = OPORT_VIDEO;
463
464 ERR_OMX( OMX_SetConfig(m_component, OMX_IndexConfigVideoFramerate, &framerate), "set framerate");
465 }
466
467 // -100 .. 100
468 void setSharpness(OMX_U32 nPortIndex = OMX_ALL, OMX_S32 nSharpness = 0)
469 {
470 Parameter<OMX_CONFIG_SHARPNESSTYPE> sharpness;
471 sharpness->nPortIndex = nPortIndex;
472 sharpness->nSharpness = nSharpness;
473
474 ERR_OMX( OMX_SetConfig(m_component, OMX_IndexConfigCommonSharpness, &sharpness), "set camera sharpness");
475 }
476
477 // -100 .. 100
478 void setContrast(OMX_U32 nPortIndex = OMX_ALL, OMX_S32 nContrast = 0)
479 {
480 Parameter<OMX_CONFIG_CONTRASTTYPE> contrast;
481 contrast->nPortIndex = nPortIndex;
482 contrast->nContrast = nContrast;
483
484 ERR_OMX( OMX_SetConfig(m_component, OMX_IndexConfigCommonContrast, &contrast), "set camera contrast");
485 }
486
487 // -100 .. 100
488 void setSaturation(OMX_U32 nPortIndex = OMX_ALL, OMX_S32 nSaturation = 0)
489 {
490 Parameter<OMX_CONFIG_SATURATIONTYPE> saturation;
491 saturation->nPortIndex = nPortIndex;
492 saturation->nSaturation = nSaturation;
493
494 ERR_OMX( OMX_SetConfig(m_component, OMX_IndexConfigCommonSaturation, &saturation), "set camera saturation");
495 }
496
497 // 0 .. 100
498 void setBrightness(OMX_U32 nPortIndex = OMX_ALL, OMX_U32 nBrightness = 50)
499 {
500 Parameter<OMX_CONFIG_BRIGHTNESSTYPE> brightness;
501 brightness->nPortIndex = nPortIndex;
502 brightness->nBrightness = nBrightness;
503
504 ERR_OMX( OMX_SetConfig(m_component, OMX_IndexConfigCommonBrightness, &brightness), "set camera brightness");
505 }
506
507 void setExposureValue(OMX_U32 nPortIndex = OMX_ALL,
508 OMX_S32 xEVCompensation = 0, OMX_U32 nSensitivity = 100, OMX_BOOL bAutoSensitivity = OMX_FALSE)
509 {
510 Parameter<OMX_CONFIG_EXPOSUREVALUETYPE> exposure_value;
511 exposure_value->nPortIndex = nPortIndex;
512 exposure_value->xEVCompensation = xEVCompensation;
513 exposure_value->nSensitivity = nSensitivity;
514 exposure_value->bAutoSensitivity = bAutoSensitivity;
515
516 ERR_OMX( OMX_SetConfig(m_component, OMX_IndexConfigCommonExposureValue, &exposure_value), "set camera exposure value");
517 }
518
519 void setFrameStabilisation(OMX_U32 nPortIndex = OMX_ALL, OMX_BOOL bStab = OMX_TRUE)
520 {
521 Parameter<OMX_CONFIG_FRAMESTABTYPE> frame_stabilisation_control;
522 frame_stabilisation_control->nPortIndex = nPortIndex;
523 frame_stabilisation_control->bStab = bStab;
524
525 ERR_OMX( OMX_SetConfig(m_component, OMX_IndexConfigCommonFrameStabilisation, &frame_stabilisation_control),
526 "set camera frame stabilisation");
527 }
528
529 void setWhiteBalanceControl(OMX_U32 nPortIndex = OMX_ALL, OMX_WHITEBALCONTROLTYPE eWhiteBalControl = OMX_WhiteBalControlAuto)
530 {
531 Parameter<OMX_CONFIG_WHITEBALCONTROLTYPE> white_balance_control;
532 white_balance_control->nPortIndex = nPortIndex;
533 white_balance_control->eWhiteBalControl = eWhiteBalControl;
534
535 ERR_OMX( OMX_SetConfig(m_component, OMX_IndexConfigCommonWhiteBalance, &white_balance_control),
536 "set camera frame white balance");
537 }
538
539 void setImageFilter(OMX_U32 nPortIndex = OMX_ALL, OMX_IMAGEFILTERTYPE eImageFilter = OMX_ImageFilterNone)
540 {
541 Parameter<OMX_CONFIG_IMAGEFILTERTYPE> image_filter;
542 image_filter->nPortIndex = nPortIndex;
543 image_filter->eImageFilter = eImageFilter;
544
545 ERR_OMX( OMX_SetConfig(m_component, OMX_IndexConfigCommonImageFilter, &image_filter), "set camera image filter");
546 }
547
548 // OMX_MirrorHorizontal | OMX_MirrorVertical | OMX_MirrorBoth
549 void setMirror(OMX_U32 nPortIndex, OMX_MIRRORTYPE eMirror = OMX_MirrorNone)
550 {
551 Parameter<OMX_CONFIG_MIRRORTYPE> mirror;
552 mirror->nPortIndex = nPortIndex;
553 mirror->eMirror = eMirror;
554
555 ERR_OMX( OMX_SetConfig(m_component, OMX_IndexConfigCommonMirror, &mirror), "set cammera mirror");
556 }
557
558 void setImageDefaults()
559 {
560 setSharpness();
561 setContrast();
562 setSaturation();
563 setBrightness();
564 setExposureValue();
565 setFrameStabilisation();
566 setWhiteBalanceControl();
567 setImageFilter();
568 }
569
570 void capture(OMX_U32 nPortIndex, OMX_BOOL bEnabled)
571 {
572 Parameter<OMX_CONFIG_PORTBOOLEANTYPE> capture;
573 capture->nPortIndex = nPortIndex;
574 capture->bEnabled = bEnabled;
575
576 ERR_OMX( OMX_SetParameter(m_component, OMX_IndexConfigPortCapturing, &capture), "switch capture on port");
577 }
578
579 void allocBuffers()
580 {
581 Component::allocBuffers(IPORT, m_bufferIn);
582 }
583
584 void freeBuffers()
585 {
586 Component::freeBuffers(IPORT, m_bufferIn);
587 }
588
589 void eventReady()
590 {
591 m_ready = true;
592 }
593
594 bool waitReady()
595 {
596 static const unsigned TIMEOUT_US = 100000;
597 static const unsigned MAX_ATTEMPTS = 10;
598
599 for (unsigned i = 0; i < MAX_ATTEMPTS; ++i)
600 {
601 if (m_ready)
602 return true;
603 usleep(TIMEOUT_US);
604 }
605
606 debug_print("lost ready event for Camera\n");
607 return false;
608 }
609
610 private:
611 Buffer m_bufferIn;
612 std::atomic_bool m_ready;
613 };
614
616 class Encoder : public Component
617 {
618 public:
619 static const ComponentType cType = broadcom::VIDEO_ENCODER;
620
621 static const unsigned IPORT = 200;
622 static const unsigned OPORT = 201;
623
624 Encoder()
625 : Component(cType, (OMX_PTR) this, &cbsEvents),
626 m_empty(true)
627 {
628 }
629
630 void setupOutputPort(const Parameter<OMX_PARAM_PORTDEFINITIONTYPE>& cameraPortDef, unsigned bitrate, unsigned framerate = 0)
631 {
632 Parameter<OMX_PARAM_PORTDEFINITIONTYPE> portDef;
633 getPortDefinition(OPORT, portDef);
634
635 portDef->format.video.nFrameWidth = cameraPortDef->format.video.nFrameWidth;
636 portDef->format.video.nFrameHeight = cameraPortDef->format.video.nFrameHeight;
637 portDef->format.video.xFramerate = cameraPortDef->format.video.xFramerate;
638 portDef->format.video.nStride = cameraPortDef->format.video.nStride;
639 portDef->format.video.nBitrate = bitrate;
640
641 if (framerate)
642 portDef->format.video.xFramerate = framerate;
643
644 setPortDefinition(OPORT, portDef);
645 }
646
647 void setCodec(OMX_VIDEO_CODINGTYPE codec)
648 {
649 Parameter<OMX_VIDEO_PARAM_PORTFORMATTYPE> format;
650 format->nPortIndex = OPORT;
651 format->eCompressionFormat = codec;
652
653 ERR_OMX( OMX_SetParameter(m_component, OMX_IndexParamVideoPortFormat, &format), "set video format");
654
655 Parameter<OMX_CONFIG_PORTBOOLEANTYPE> ppsOption;
656 ppsOption->nPortIndex = OPORT;
657 ppsOption->bEnabled = OMX_TRUE;
658
659 ERR_OMX( OMX_SetParameter(m_component, OMX_IndexParamBrcmVideoAVCInlineHeaderEnable, &ppsOption), "enable SPS/PPS insertion");
660 }
661
662 void setBitrate(OMX_U32 bitrate, OMX_VIDEO_CONTROLRATETYPE type = OMX_Video_ControlRateVariable)
663 {
664 Parameter<OMX_VIDEO_PARAM_BITRATETYPE> brate;
665 brate->nPortIndex = OPORT;
666 brate->eControlRate = type;
667 brate->nTargetBitrate = bitrate;
668
669 ERR_OMX( OMX_SetParameter(m_component, OMX_IndexParamVideoBitrate, &brate), "set bitrate");
670 }
671
672 void setIFramePeriod(unsigned value)
673 {
674 Parameter<OMX_PARAM_U32TYPE> period;
675 period->nPortIndex = OPORT;
676 period->nU32 = value;
677
678 ERR_OMX( OMX_SetParameter(m_component, OMX_IndexConfigBrcmVideoIntraPeriod, &period), "set IFrame period");
679 }
680
681 void allocBuffers()
682 {
683 Component::allocBuffers(OPORT, m_bufferOut);
684 }
685
686 void freeBuffers()
687 {
688 m_empty = true;
689 Component::freeBuffers(OPORT, m_bufferOut);
690 }
691
692 void callFillThisBuffer()
693 {
694 Component::callFillThisBuffer(m_bufferOut);
695 }
696
697 void prepare()
698 {
699 if (m_empty)
700 {
701 callFillThisBuffer();
702 m_empty = false;
703 }
704 }
705
706 Buffer& outBuffer() { return m_bufferOut; }
707
708 private:
709 Parameter<OMX_PARAM_PORTDEFINITIONTYPE> m_encoderPortDef;
710 Buffer m_bufferOut;
711 bool m_empty;
712 };
713
715 class NullSink : public Component
716 {
717 public:
718 static const ComponentType cType = broadcom::NULL_SINK;
719
720 static const unsigned IPORT = 240;
721
722 NullSink()
723 : Component(cType, (OMX_PTR) this, &cbsEvents)
724 {
725 }
726 };
727
729 class VideoSplitter : public Component
730 {
731 public:
732 static const ComponentType cType = broadcom::VIDEO_SPLITTER;
733
734 static const unsigned IPORT = 250;
735 static const unsigned OPORT_1 = 251;
736 static const unsigned OPORT_2 = 252;
737 static const unsigned OPORT_3 = 253;
738 static const unsigned OPORT_4 = 254;
739
740 VideoSplitter()
741 : Component(cType, (OMX_PTR) this, &cbsEvents)
742 {
743 }
744 };
745
747 class Resizer : public Component
748 {
749 public:
750 static const ComponentType cType = broadcom::RESIZER;
751
752 static const unsigned IPORT = 60;
753 static const unsigned OPORT = 61;
754
755 Resizer()
756 : Component(cType, (OMX_PTR) this, &cbsEvents)
757 {
758 }
759
760 void setupOutputPort(unsigned newWidth, unsigned newHeight)
761 {
762 Parameter<OMX_PARAM_PORTDEFINITIONTYPE> portDef;
763 getPortDefinition(IPORT, portDef);
764
765 portDef->format.image.nFrameWidth = newWidth;
766 portDef->format.image.nFrameHeight = newHeight;
767 portDef->format.image.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar;
768
769 portDef->format.image.nSliceHeight = 0;
770 portDef->format.image.nStride = 0;
771
772 setPortDefinition(OPORT, portDef);
773 }
774 };
775 }
776
777 #endif
rpi_omx::OMXExeption
Handler for OpenMAX IL errors.
Definition: rpi_omx.h:42
rpi_omx::Component
Base class for OpenMAX IL components.
Definition: rpi_omx.h:180
rpi_omx::Parameter
OpenMAX IL parameter.
Definition: rpi_omx.h:121
rpi_omx
Raspberry Pi OpenMAX IL layer.
Definition: rpi_omx.cpp:5
rpi_omx::Camera
OMX.broadcom.camera.
Definition: rpi_omx.h:384
rpi_omx::Buffer
OpenMAX IL CPU<->GPU buffer.
Definition: rpi_omx.h:153
broadcom::VcosSemaphore
Definition: rpi_omx_broadcom.h:67
rpi_omx::VF_1920x1080
static const VideoFromat VF_1920x1080
Definition: rpi_omx.h:100
rpi_omx::VideoSplitter
OMX.broadcom.video_splitter.
Definition: rpi_omx.h:729
rpi_omx::NullSink
OMX.broadcom.null_sink.
Definition: rpi_omx.h:715
rpi_omx::VideoFromat
Definition: rpi_omx.h:75
rpi_omx::Encoder
OMX.broadcom.video_encode.
Definition: rpi_omx.h:616
broadcom::VcosLock
Definition: rpi_omx_broadcom.h:87
rpi_omx::Resizer
OMX.broadcom.resize.
Definition: rpi_omx.h:747