nx_video_source_sdk  1.0
Video Source 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 <cstdio>
7 #include <vector>
8 #include <exception>
9 #include <atomic>
10 
11 #define OMX
12 #define OMX_SKIP64BIT
13 
14 #include "rpi_omx_broadcom.h"
15 
16 #include <IL/OMX_Core.h>
17 #include <IL/OMX_Component.h>
18 #include <IL/OMX_Video.h>
19 #include <IL/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 
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  {
191  getPortDefinition(nPortIndex, portdef);
192 
193  dump_portdef(&portdef);
194 
195  if (dumpFormats)
196  {
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  {
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 
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
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  {
650  format->nPortIndex = OPORT;
651  format->eCompressionFormat = codec;
652 
653  ERR_OMX( OMX_SetParameter(m_component, OMX_IndexParamVideoPortFormat, &format), "set video format");
654 
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  {
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  {
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:
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  {
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
Handler for OpenMAX IL errors.
Definition: rpi_omx.h:42
Base class for OpenMAX IL components.
Definition: rpi_omx.h:180
OpenMAX IL parameter.
Definition: rpi_omx.h:121
Raspberry Pi OpenMAX IL layer.
Definition: rpi_omx.cpp:5
OMX.broadcom.camera.
Definition: rpi_omx.h:384
OpenMAX IL CPU<->GPU buffer.
Definition: rpi_omx.h:153
Definition: rpi_omx_broadcom.h:67
static const VideoFromat VF_1920x1080
Definition: rpi_omx.h:100
OMX.broadcom.video_splitter.
Definition: rpi_omx.h:729
OMX.broadcom.null_sink.
Definition: rpi_omx.h:715
Definition: rpi_omx.h:75
OMX.broadcom.video_encode.
Definition: rpi_omx.h:616
Definition: rpi_omx_broadcom.h:87
OMX.broadcom.resize.
Definition: rpi_omx.h:747