Torc  0.1
torcpicamera.cpp
Go to the documentation of this file.
1 /* Class TorcPiCamera
2 *
3 * This file is part of the Torc project.
4 *
5 * Copyright (C) Mark Kendall 2018
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 * USA.
21 */
22 
23 // Qt
24 #include <QTime>
25 #include <QThread>
26 
27 // Torc
28 #include "torclogging.h"
29 #include "torctimer.h"
30 #include "torccentral.h"
31 #include "torcpicamera.h"
32 #include "torcdirectories.h"
33 
34 // OpenMax
35 #include "OMX_Video.h"
36 
37 // Broadcom
38 #include "bcm_host.h"
39 #include "OMX_Broadcom.h"
40 
41 #define BROADCOM_CAMERA "OMX.broadcom.camera"
42 #define BROADCOM_ENCODER "OMX.broadcom.video_encode"
43 #define BROADCOM_NULLSINK "OMX.broadcom.null_sink"
44 #define BROADCOM_VIDEOSPLITTER "OMX.broadcom.video_splitter"
45 #define BROADCOM_IMAGEENCODER "OMX.broadcom.image_encode"
46 #define CAMERA_SHARPNESS 0 // -100->100
47 #define CAMERA_CONTRAST 0 // -100->100
48 #define CAMERA_BRIGHTNESS 50 // 0->100
49 #define CAMERA_SATURATION 0 // -100->100
50 #define CAMERA_METERING OMX_MeteringModeAverage
51 #define CAMERA_EXPOSURE OMX_ExposureControlAuto
52 #define CAMERA_EXPOSURE_COMPENSATION 0 // -10->10
53 #define CAMERA_SHUTTER_SPEED_AUTO OMX_TRUE
54 #define CAMERA_SHUTTER_SPEED 1.0/8.0
55 #define CAMERA_ISO_AUTO OMX_TRUE
56 #define CAMERA_ISO 100 // 100->800
57 #define CAMERA_WHITE_BALANCE OMX_WhiteBalControlAuto
58 #define CAMERA_FRAME_STABILIZATION OMX_FALSE
59 #define CAMERA_WHITE_BALANCE_RED_GAIN 1000
60 #define CAMERA_WHITE_BALANCE_BLUE_GAIN 1000
61 #define CAMERA_IMAGE_FILTER OMX_ImageFilterNone
62 #define CAMERA_MIRROR OMX_MirrorNone
63 #define CAMERA_ROTATION 0
64 #define CAMERA_COLOR_ENABLE OMX_FALSE
65 #define CAMERA_COLOR_U 128
66 #define CAMERA_COLOR_V 128
67 #define CAMERA_NOISE_REDUCTION OMX_TRUE
68 #define CAMERA_ROI_TOP 0
69 #define CAMERA_ROI_LEFT 0
70 #define CAMERA_ROI_WIDTH 100
71 #define CAMERA_ROI_HEIGHT 100
72 #define CAMERA_DRC OMX_DynRangeExpOff // Off/Low/Medium/High
73 
74 #define ENCODER_QP OMX_FALSE
75 #define ENCODER_QP_I 0
76 #define ENCODER_QP_P 0
77 #define ENCODER_SEI OMX_FALSE
78 #define ENCODER_EEDE OMX_FALSE
79 #define ENCODER_EEDE_LOSS_RATE 0
80 #define ENCODER_INLINE_HEADERS OMX_TRUE
81 #define ENCODER_SPS_TIMING OMX_TRUE
82 
84 
86  : TorcCameraDevice(Params),
87  m_cameraType(Unknown),
88  m_stillsEnabled(true),
89  m_videoEnabled(true),
90  m_core(),
91  m_camera((char*)BROADCOM_CAMERA),
92  m_videoEncoder((char*)BROADCOM_ENCODER),
93  m_nullSink((char*)BROADCOM_NULLSINK),
94  m_splitter((char*)BROADCOM_VIDEOSPLITTER),
95  m_imageEncoder((char*)BROADCOM_IMAGEENCODER),
96  m_cameraPreviewPort(0),
97  m_cameraVideoPort(0),
98  m_videoEncoderInputPort(0),
99  m_videoEncoderOutputPort(0),
100  m_imageEncoderOutputPort(0),
101  m_splitterTunnel(&m_camera, 1, OMX_IndexParamVideoInit, &m_splitter, 0, OMX_IndexParamVideoInit),
102  m_videoTunnel(&m_splitter, 0, OMX_IndexParamVideoInit, &m_videoEncoder, 0, OMX_IndexParamVideoInit),
103  m_previewTunnel(&m_camera, 0, OMX_IndexParamVideoInit, &m_nullSink, 0, OMX_IndexParamVideoInit),
104  m_imageTunnel(&m_splitter, 1, OMX_IndexParamVideoInit, &m_imageEncoder, 0, OMX_IndexParamImageInit)
105 {
106  if (m_params.m_frameRate > 30 && (m_params.m_width > 1280 || m_params.m_height > 720))
107  {
108  m_params.m_frameRate = 30;
109  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Restricting camera framerate to 30fps for full HD"));
110  }
111  else if (m_params.m_frameRate > 60 && (m_params.m_width > 720 || m_params.m_height > 576))
112  {
113  m_params.m_frameRate = 60;
114  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Restricting camera framerate to 60fps for partial HD"));
115  }
116  else if (m_params.m_frameRate > 90)
117  {
118  m_params.m_frameRate = 90;
119  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Resticting camera framerate to 90fps for SD"));
120  }
121 
122  // encoder requires stride to be divisible by 32 and slice height by 16
123  m_params.m_stride = (m_params.m_stride + 31) & ~31;
125  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Camera encoder stride: %1 slice height: %2").arg(m_params.m_stride).arg(m_params.m_sliceHeight));
126 }
127 
129 {
130  (void)Video;
131 }
132 
134 {
135  // NB Pi hardware is initialised in TorcPiGPIO as it is static
136 
137  if (!m_camera.IsValid() || !m_videoEncoder.IsValid() || !m_nullSink.IsValid() || !m_splitter.IsValid() ||
138  !m_imageEncoder.IsValid())
139  return false;
140 
141  // load drivers - Broadcom specific
142  if (!LoadDrivers())
143  return false;
144 
145  // retrieve port numbers
146  m_cameraPreviewPort = m_camera.GetPort(OMX_DirOutput, 0, OMX_IndexParamVideoInit);
147  m_cameraVideoPort = m_camera.GetPort(OMX_DirOutput, 1, OMX_IndexParamVideoInit);
148  m_videoEncoderInputPort = m_videoEncoder.GetPort(OMX_DirInput, 0, OMX_IndexParamVideoInit);
149  m_videoEncoderOutputPort = m_videoEncoder.GetPort(OMX_DirOutput, 0, OMX_IndexParamVideoInit);
150  m_imageEncoderOutputPort = m_imageEncoder.GetPort(OMX_DirOutput, 0, OMX_IndexParamImageInit);
151 
152  if (!m_cameraVideoPort || !m_cameraPreviewPort || !m_videoEncoderInputPort || !m_videoEncoderOutputPort || !m_imageEncoderOutputPort)
153  return false;
154 
155  // configure camera
156  if (!ConfigureCamera())
157  return false;
158 
159  // configure encoders
160  if (!ConfigureVideoEncoder() || !ConfigureImageEncoder())
161  return false;
162 
163  // create tunnels
164  if (m_splitterTunnel.Create() || m_previewTunnel.Create() || m_videoTunnel.Create() || m_imageTunnel.Create())
165  return false;
166 
167  // set to idle
168  m_camera.SetState(OMX_StateIdle);
169  m_splitter.SetState(OMX_StateIdle);
170  m_videoEncoder.SetState(OMX_StateIdle);
171  m_imageEncoder.SetState(OMX_StateIdle);
172  m_nullSink.SetState(OMX_StateIdle);
173 
174  // set splitter to image encoder to single shot
175  // there is no setting for nothing - it is either streamed (0) or 1 or more single frames
176  // so request 1 frame and then ignore it
177  if (!EnableStills(1))
178  return false;
179  m_stillsRequired = 0;
180 
181  // TODO add error checking to these calls
182  // enable ports
183  m_camera.EnablePort(OMX_DirOutput, 0, true, OMX_IndexParamVideoInit);
184  m_camera.EnablePort(OMX_DirOutput, 1, true, OMX_IndexParamVideoInit);
185  m_splitter.EnablePort(OMX_DirInput, 0, true, OMX_IndexParamVideoInit);
186  m_splitter.EnablePort(OMX_DirOutput, 0, true, OMX_IndexParamVideoInit);
187  m_splitter.EnablePort(OMX_DirOutput, 1, true, OMX_IndexParamVideoInit);
188  m_videoEncoder.EnablePort(OMX_DirInput, 0, true, OMX_IndexParamVideoInit);
189  m_videoEncoder.EnablePort(OMX_DirOutput, 0, true, OMX_IndexParamVideoInit, false);
190  m_videoEncoder.CreateBuffers(OMX_DirOutput, 0, OMX_IndexParamVideoInit, this);
191  m_videoEncoder.WaitForResponse(OMX_CommandPortEnable, m_videoEncoderOutputPort, 1000);
192  m_imageEncoder.EnablePort(OMX_DirInput, 0, true, OMX_IndexParamImageInit);
193  m_imageEncoder.EnablePort(OMX_DirOutput, 0, true, OMX_IndexParamImageInit, false);
194  m_imageEncoder.CreateBuffers(OMX_DirOutput, 0, OMX_IndexParamImageInit, this);
195  m_imageEncoder.WaitForResponse(OMX_CommandPortEnable, m_imageEncoderOutputPort, 1000);
196  m_nullSink.EnablePort(OMX_DirInput, 0, true, OMX_IndexParamVideoInit);
197 
198 
199  // set state to execute
200  m_camera.SetState(OMX_StateExecuting);
201  m_splitter.SetState(OMX_StateExecuting);
202  m_videoEncoder.SetState(OMX_StateExecuting);
203  m_imageEncoder.SetState(OMX_StateExecuting);
204  m_nullSink.SetState(OMX_StateExecuting);
205 
206  // enable
207  OMX_CONFIG_PORTBOOLEANTYPE capture;
208  OMX_INITSTRUCTURE(capture);
209  capture.nPortIndex = m_cameraVideoPort;
210  capture.bEnabled = OMX_TRUE;
211  if (m_camera.SetConfig(OMX_IndexConfigPortCapturing, &capture))
212  return false;
213 
215  {
216  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Pi camera setup"));
217  return true;
218  }
219 
220  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("Failed to setup Pi camera"));
221  return false;
222 }
223 
230 {
231  // there should be one still pipelined. We need to flush it.
232  StartStill();
233 
234  // video is currently just on...
235  StartVideo();
236 
237  return true;
238 }
239 
245 void TorcPiCamera::BufferReady(OMX_BUFFERHEADERTYPE* Buffer, quint64 Type)
246 {
247  if (!Buffer)
248  return;
249 
250  // Stills
251 
252  // m_stillsExpected is always >= m_stillsRequired
253  if (m_stillsExpected && ((OMX_INDEXTYPE)Type == OMX_IndexParamImageInit) && (m_imageEncoder.GetAvailableBuffers(OMX_DirOutput, 0, OMX_IndexParamImageInit) > 0))
254  {
255  ProcessStillsBuffer(Buffer);
256  return;
257  }
258 
259  // Video
260  if (((OMX_INDEXTYPE)Type == OMX_IndexParamVideoInit) && m_videoEncoder.GetAvailableBuffers(OMX_DirOutput, 0, OMX_IndexParamVideoInit) > 0)
261  {
262  ProcessVideoBuffer(Buffer);
263  return;
264  }
265 }
266 
274 {
275  if (!m_stillsEnabled)
276  return;
277 
278  OMX_BUFFERHEADERTYPE* buffer = m_imageEncoder.GetBuffer(OMX_DirOutput, 0, 1000, OMX_IndexParamImageInit);
279  if (buffer)
280  (void)m_imageEncoder.FillThisBuffer(buffer);
281 
282  // else panic...
283 
284 }
285 
286 void TorcPiCamera::ProcessStillsBuffer(OMX_BUFFERHEADERTYPE *Buffer)
287 {
288  if (!Buffer)
289  return;
290 
291  if (Buffer->nFilledLen > 0)
292  {
293  uint8_t* data = (uint8_t*)malloc(Buffer->nFilledLen);
294  memcpy(data, Buffer->pBuffer + Buffer->nOffset, Buffer->nFilledLen);
295  SaveStillBuffer(Buffer->nFilledLen, data);
296  }
297 
298  if (Buffer->nFlags & OMX_BUFFERFLAG_ENDOFFRAME)
299  SaveStill();
300 
301  if (m_stillsExpected)
302  StartStill();
303 }
304 
305 bool TorcPiCamera::EnableVideo(bool Video)
306 {
307  (void)Video;
308  return true;
309 }
310 
316 void TorcPiCamera::StartVideo(void)
317 {
318  if (!m_videoEnabled)
319  return;
320 
321  OMX_BUFFERHEADERTYPE* buffer = m_videoEncoder.GetBuffer(OMX_DirOutput, 0, 1000, OMX_IndexParamVideoInit);
322  if (buffer)
323  (void)m_videoEncoder.FillThisBuffer(buffer);
324 }
325 
326 void TorcPiCamera::ProcessVideoBuffer(OMX_BUFFERHEADERTYPE *Buffer)
327 {
328  if (!Buffer || !m_muxer)
329  return;
330 
331  bool idr = Buffer->nFlags & OMX_BUFFERFLAG_SYNCFRAME;
332  bool complete = Buffer->nFlags & OMX_BUFFERFLAG_ENDOFFRAME;
333  bool sps = Buffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG;
334 
335  if (!sps && complete)
336  m_frameCount++;
337 
338  // TODO wrap pts
339  // this increases the pts monotonically based on actual complete frames received
340  qint64 pts = m_frameCount * ((float)m_params.m_timebase / (float)m_params.m_frameRate);
341  // sps is not considered a frame but muxer will complain if the pts does not increase
342  if (sps)
343  pts++;
344 
345  // NB we use av_packet_from_data and av_grow_packet for the buffered packet - which uses the internal AVBufferRef structure
346  // Do not manually release AVPacket->data
347  if (m_bufferedPacket)
348  {
349  quint32 offset = m_bufferedPacket->size;
350  av_grow_packet(m_bufferedPacket, Buffer->nFilledLen);
351  memcpy(m_bufferedPacket->data + offset, reinterpret_cast<uint8_t*>(Buffer->pBuffer) + Buffer->nOffset, Buffer->nFilledLen);
352  }
353 
354  if (complete)
355  {
356  AVPacket *packet = m_bufferedPacket;
357  if (!packet)
358  {
359  packet = av_packet_alloc();
360  av_init_packet(packet);
361  packet->size = Buffer->nFilledLen;
362  packet->data = reinterpret_cast<uint8_t*>(Buffer->pBuffer) + Buffer->nOffset;
363  }
364 
365  packet->stream_index = m_videoStream;
366  packet->pts = pts;
367  packet->dts = pts;
368  packet->duration = 1;
369  packet->flags |= idr ? AV_PKT_FLAG_KEY : 0;
370 
371  {
372  QWriteLocker locker(&m_ringBufferLock); // muxer accesses ringbuffer
373  m_muxer->AddPacket(packet, sps);
374 
375  if (sps && !m_haveInitSegment)
376  {
377  QByteArray config = QByteArray::fromRawData((char*)packet->data, packet->size);
379  m_haveInitSegment = true;
380  m_muxer->FinishSegment(true);
381  // video is notionally available once the init segment is available
383  emit WritingStarted();
384  }
385  else if (!sps && !(m_frameCount % (m_params.m_frameRate * VIDEO_SEGMENT_TARGET)))
386  {
387  m_muxer->FinishSegment(false);
388  locker.unlock();
389  TrackDrift();
390  locker.relock();
391  }
392 
393  if (m_bufferedPacket)
394  {
395  av_packet_free(&m_bufferedPacket);
396  m_bufferedPacket = nullptr;
397  }
398  else
399  {
400  packet->data = nullptr;
401  av_packet_free(&packet);
402  }
403  }
404  }
405  else
406  {
407  if (!m_bufferedPacket)
408  {
409  uint8_t* data = (uint8_t*)av_malloc(Buffer->nFilledLen);
410  m_bufferedPacket = av_packet_alloc();
411  av_init_packet(m_bufferedPacket);
412  av_packet_from_data(m_bufferedPacket, data, Buffer->nFilledLen);
413  memcpy(m_bufferedPacket->data, reinterpret_cast<uint8_t*>(Buffer->pBuffer) + Buffer->nOffset, Buffer->nFilledLen);
414  m_bufferedPacket->flags |= idr ? AV_PKT_FLAG_KEY : 0;
415  }
416  }
417 
418  // and kick off another
419  StartVideo();
420 }
421 
423 {
424  // make sure no further buffers are requested
425  m_stillsEnabled = false;
426  m_videoEnabled = false;
427 
428  // and ensure all FillBufferDone callbacks are complete
429  // NB this assumes only one buffer is allocated
430  TorcTimer timer;
431  timer.Start();
432  while (m_imageEncoder.GetInUseBuffers(OMX_DirOutput, 0, OMX_IndexParamImageInit) &&
433  m_videoEncoder.GetInUseBuffers(OMX_DirOutput, 0, OMX_IndexParamVideoInit) &&
434  timer.Elapsed() < 1000)
435  {
436  QThread::msleep(50);
437  }
438 
439  emit WritingStopped();
440 
441  // stop camera
442  OMX_CONFIG_PORTBOOLEANTYPE capture;
443  OMX_INITSTRUCTURE(capture);
444  capture.nPortIndex = m_cameraVideoPort;
445  capture.bEnabled = OMX_FALSE;
446  m_camera.SetConfig(OMX_IndexConfigPortCapturing, &capture);
447 
448  // set state to idle
449  m_camera.SetState(OMX_StateIdle);
450  m_splitter.SetState(OMX_StateIdle);
451  m_videoEncoder.SetState(OMX_StateIdle);
452  m_imageEncoder.SetState(OMX_StateIdle);
453  m_nullSink.SetState(OMX_StateIdle);
454 
455  // disable encoder output port
456  m_videoEncoder.EnablePort(OMX_DirOutput, 0, false, OMX_IndexParamVideoInit, false);
457  m_videoEncoder.DestroyBuffers(OMX_DirOutput, 0, OMX_IndexParamVideoInit);
458  m_videoEncoder.WaitForResponse(OMX_CommandPortDisable, m_videoEncoderOutputPort, 1000);
459 
460  // disable image encoder output port
461  m_imageEncoder.EnablePort(OMX_DirOutput, 0, false, OMX_IndexParamImageInit, false);
462  m_imageEncoder.DestroyBuffers(OMX_DirOutput, 0, OMX_IndexParamImageInit);
463  m_imageEncoder.WaitForResponse(OMX_CommandPortDisable, m_imageEncoderOutputPort, 1000);
464 
465  // disable remaining ports
466  m_camera.DisablePorts(OMX_IndexParamVideoInit);
467  // disabled due to inconsequential errors
468  //m_splitter.DisablePorts(OMX_IndexParamVideoInit);
469  m_videoEncoder.DisablePorts(OMX_IndexParamVideoInit);
470  m_imageEncoder.DisablePorts(OMX_IndexParamImageInit);
471  m_nullSink.DisablePorts(OMX_IndexParamVideoInit);
472 
473  // destroy tunnels
474  m_videoTunnel.Destroy();
475  m_previewTunnel.Destroy();
476  m_splitterTunnel.Destroy();
477  m_imageTunnel.Destroy();
478 
479  // set state to loaded
480  m_camera.SetState(OMX_StateLoaded);
481  m_splitter.SetState(OMX_StateLoaded);
482  m_videoEncoder.SetState(OMX_StateLoaded);
483  m_imageEncoder.SetState(OMX_StateLoaded);
484  m_nullSink.SetState(OMX_StateLoaded);
485 
486  return true;
487 }
488 
489 bool TorcPiCamera::LoadDrivers(void)
490 {
491  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Trying to load Broadcom drivers"));
492 
493  // request a callback
494  OMX_CONFIG_REQUESTCALLBACKTYPE callback;
495  OMX_INITSTRUCTURE(callback);
496  callback.nPortIndex = OMX_ALL;
497  callback.nIndex = OMX_IndexParamCameraDeviceNumber;
498  callback.bEnable = OMX_TRUE;
499  if (m_camera.SetConfig(OMX_IndexConfigRequestCallback, &callback))
500  return false;
501 
502  // and set the camera device number. Once we have a response, the relevant
503  // drivers should be loaded.
504  OMX_PARAM_U32TYPE device;
505  OMX_INITSTRUCTURE(device);
506  device.nPortIndex = OMX_ALL;
507  device.nU32 = 0;
508  if (m_camera.SetConfig(OMX_IndexParamCameraDeviceNumber, &device))
509  return false;
510  if (m_camera.WaitForResponse(OMX_EventParamOrConfigChanged, 0, 10000))
511  return false;
512 
513  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Broadcom drivers loaded"));
514 
515  OMX_CONFIG_CAMERAINFOTYPE info;
516  OMX_INITSTRUCTURE(info);
517  if (!m_camera.GetConfig(OMX_IndexConfigCameraInfo, &info))
518  {
519  if (qstrcmp((const char*)info.cameraname, "imx219") == 0)
520  m_cameraType = V2;
521  else if (qstrcmp((const char*)info.cameraname, "ov5647") == 0)
522  m_cameraType = V1;
523  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Camera: name '%1' (Version %2)")
524  .arg((const char*)info.cameraname)
525  .arg(m_cameraType == V2 ? "2" : m_cameraType == V1 ? QStringLiteral("1") : QStringLiteral("Unknown")));
526  }
527 
528  return true;
529 }
530 
531 bool TorcPiCamera::LoadCameraSettings(void)
532 {
533  if (!m_cameraVideoPort)
534  return false;
535 
536  // Sharpness
537  OMX_CONFIG_SHARPNESSTYPE sharpness;
538  OMX_INITSTRUCTURE(sharpness);
539  sharpness.nPortIndex = OMX_ALL;
540  sharpness.nSharpness = CAMERA_SHARPNESS;
541  if (m_camera.SetConfig(OMX_IndexConfigCommonSharpness, &sharpness))
542  return false;
543 
544  // Contrast
545  OMX_CONFIG_CONTRASTTYPE contrast;
546  OMX_INITSTRUCTURE(contrast);
547  contrast.nPortIndex = OMX_ALL;
548  contrast.nContrast = CAMERA_CONTRAST;
549  if (m_camera.SetConfig(OMX_IndexConfigCommonContrast, &contrast))
550  return false;
551 
552  // Saturation
553  OMX_CONFIG_SATURATIONTYPE saturation;
554  OMX_INITSTRUCTURE(saturation);
555  saturation.nPortIndex = OMX_ALL;
556  saturation.nSaturation = CAMERA_SATURATION;
557  if (m_camera.SetConfig(OMX_IndexConfigCommonSaturation, &saturation))
558  return false;
559 
560  // Brightness
561  OMX_CONFIG_BRIGHTNESSTYPE brightness;
562  OMX_INITSTRUCTURE(brightness);
563  brightness.nPortIndex = OMX_ALL;
564  brightness.nBrightness = CAMERA_BRIGHTNESS;
565  if (m_camera.SetConfig(OMX_IndexConfigCommonBrightness, &brightness))
566  return false;
567 
568  // Exposure
569  OMX_CONFIG_EXPOSUREVALUETYPE exposure;
570  OMX_INITSTRUCTURE(exposure);
571  exposure.nPortIndex = OMX_ALL;
572  exposure.eMetering = CAMERA_METERING;
573  exposure.xEVCompensation = (OMX_S32)((CAMERA_EXPOSURE_COMPENSATION << 16)/6.0);
574  exposure.nShutterSpeedMsec = (OMX_U32)((CAMERA_SHUTTER_SPEED)*1e6);
575  exposure.bAutoShutterSpeed = CAMERA_SHUTTER_SPEED_AUTO;
576  exposure.nSensitivity = CAMERA_ISO;
577  exposure.bAutoSensitivity = CAMERA_ISO_AUTO;
578  if (m_camera.SetConfig(OMX_IndexConfigCommonExposureValue, &exposure))
579  return false;
580 
581  // Exposure control
582  OMX_CONFIG_EXPOSURECONTROLTYPE commonexposure;
583  OMX_INITSTRUCTURE(commonexposure);
584  commonexposure.nPortIndex = OMX_ALL;
585  commonexposure.eExposureControl = CAMERA_EXPOSURE;
586  if (m_camera.SetConfig(OMX_IndexConfigCommonExposure, &commonexposure))
587  return false;
588 
589  // Frame stabilisation
590  OMX_CONFIG_FRAMESTABTYPE framestabilisation;
591  OMX_INITSTRUCTURE(framestabilisation);
592  framestabilisation.nPortIndex = OMX_ALL;
593  framestabilisation.bStab = CAMERA_FRAME_STABILIZATION;
594  if (m_camera.SetConfig(OMX_IndexConfigCommonFrameStabilisation, &framestabilisation))
595  return false;
596 
597  // White balance
598  OMX_CONFIG_WHITEBALCONTROLTYPE whitebalance;
599  OMX_INITSTRUCTURE(whitebalance);
600  whitebalance.nPortIndex = OMX_ALL;
601  whitebalance.eWhiteBalControl = CAMERA_WHITE_BALANCE;
602  if (m_camera.SetConfig(OMX_IndexConfigCommonWhiteBalance, &whitebalance))
603  return false;
604 
605  // White balance gain
607  {
608  OMX_CONFIG_CUSTOMAWBGAINSTYPE whitebalancegain;
609  OMX_INITSTRUCTURE(whitebalancegain);
610  whitebalancegain.xGainR = (CAMERA_WHITE_BALANCE_RED_GAIN << 16) / 1000;
611  whitebalancegain.xGainB = (CAMERA_WHITE_BALANCE_BLUE_GAIN << 16) / 1000;
612  if (m_camera.SetConfig(OMX_IndexConfigCustomAwbGains, &whitebalancegain))
613  return false;
614  }
615 
616  // Image filter
617  OMX_CONFIG_IMAGEFILTERTYPE imagefilter;
618  OMX_INITSTRUCTURE(imagefilter);
619  imagefilter.nPortIndex = OMX_ALL;
620  imagefilter.eImageFilter = CAMERA_IMAGE_FILTER;
621  if (m_camera.SetConfig(OMX_IndexConfigCommonImageFilter, &imagefilter))
622  return false;
623 
624  // Mirror
625  OMX_CONFIG_MIRRORTYPE mirror;
626  OMX_INITSTRUCTURE(mirror);
627  mirror.nPortIndex = m_cameraVideoPort;
628  mirror.eMirror = CAMERA_MIRROR;
629  if (m_camera.SetConfig(OMX_IndexConfigCommonMirror, &mirror))
630  return false;
631 
632  // Rotation
633  OMX_CONFIG_ROTATIONTYPE rotation;
634  OMX_INITSTRUCTURE(rotation);
635  rotation.nPortIndex = m_cameraVideoPort;
636  rotation.nRotation = CAMERA_ROTATION;
637  if (m_camera.SetConfig(OMX_IndexConfigCommonRotate, &rotation))
638  return false;
639 
640  // Color enhancement
641  OMX_CONFIG_COLORENHANCEMENTTYPE color_enhancement;
642  OMX_INITSTRUCTURE(color_enhancement);
643  color_enhancement.nPortIndex = OMX_ALL;
644  color_enhancement.bColorEnhancement = CAMERA_COLOR_ENABLE;
645  color_enhancement.nCustomizedU = CAMERA_COLOR_U;
646  color_enhancement.nCustomizedV = CAMERA_COLOR_V;
647  if (m_camera.SetConfig(OMX_IndexConfigCommonColorEnhancement, &color_enhancement))
648  return false;
649 
650  // Denoise
651  OMX_CONFIG_BOOLEANTYPE denoise;
652  OMX_INITSTRUCTURE(denoise);
653  denoise.bEnabled = CAMERA_NOISE_REDUCTION;
654  if (m_camera.SetConfig(OMX_IndexConfigStillColourDenoiseEnable, &denoise))
655  return false;
656 
657  //ROI
658  OMX_CONFIG_INPUTCROPTYPE roi;
659  OMX_INITSTRUCTURE(roi);
660  roi.nPortIndex = OMX_ALL;
661  roi.xLeft = (CAMERA_ROI_LEFT << 16) / 100;
662  roi.xTop = (CAMERA_ROI_TOP << 16) / 100;
663  roi.xWidth = (CAMERA_ROI_WIDTH << 16) / 100;
664  roi.xHeight = (CAMERA_ROI_HEIGHT << 16) / 100;
665  if (m_camera.SetConfig(OMX_IndexConfigInputCropPercentages, &roi))
666  return false;
667 
668  //DRC
669  OMX_CONFIG_DYNAMICRANGEEXPANSIONTYPE drc;
670  OMX_INITSTRUCTURE(drc);
671  drc.eMode = CAMERA_DRC;
672  if (m_camera.SetConfig(OMX_IndexConfigDynamicRangeExpansion, &drc))
673  return false;
674 
675  return true;
676 }
677 
678 bool TorcPiCamera::ConfigureCamera(void)
679 {
680  if (!m_cameraPreviewPort || !m_cameraVideoPort)
681  return false;
682 
683  // configure camera video port
684  OMX_PARAM_PORTDEFINITIONTYPE videoport;
685  OMX_INITSTRUCTURE(videoport);
686  videoport.nPortIndex = m_cameraVideoPort;
687  if (m_camera.GetParameter(OMX_IndexParamPortDefinition, &videoport))
688  return false;
689 
690  videoport.format.video.nFrameWidth = m_params.m_width;
691  videoport.format.video.nFrameHeight = m_params.m_height;
692  videoport.format.video.nStride = m_params.m_stride;
693  videoport.format.video.nSliceHeight = m_params.m_sliceHeight;
694  videoport.format.video.xFramerate = m_params.m_frameRate << 16;
695  videoport.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
696  videoport.format.video.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar;
697  if (m_camera.SetParameter(OMX_IndexParamPortDefinition, &videoport))
698  return false;
699 
700  // and the same for the preview port
701  videoport.nPortIndex = m_cameraPreviewPort;
702  if (m_camera.SetParameter(OMX_IndexParamPortDefinition, &videoport))
703  return false;
704 
705  // configure video frame rate
706  OMX_CONFIG_FRAMERATETYPE framerate;
707  OMX_INITSTRUCTURE(framerate);
708  framerate.nPortIndex = m_cameraVideoPort;
709  framerate.xEncodeFramerate = videoport.format.video.xFramerate;
710  if (m_camera.SetConfig(OMX_IndexConfigVideoFramerate, &framerate))
711  return false;
712 
713  // and same again for preview port
714  framerate.nPortIndex = m_cameraPreviewPort;
715  if (m_camera.SetConfig(OMX_IndexConfigVideoFramerate, &framerate))
716  return false;
717 
718  // camera settings
719  if (!LoadCameraSettings())
720  return false;
721 
722  return true;
723 }
724 
725 bool TorcPiCamera::ConfigureImageEncoder(void)
726 {
727  if (!m_imageEncoderOutputPort)
728  return false;
729 
730  OMX_PARAM_PORTDEFINITIONTYPE encoderport;
731  OMX_INITSTRUCTURE(encoderport);
732  encoderport.nPortIndex = m_imageEncoderOutputPort;
733  if (m_imageEncoder.GetParameter(OMX_IndexParamPortDefinition, &encoderport))
734  return false;
735 
736  encoderport.format.image.nFrameWidth = m_params.m_width;
737  encoderport.format.image.nFrameHeight = m_params.m_height;
738  encoderport.format.image.nStride = m_params.m_stride;
739  encoderport.format.image.nSliceHeight = m_params.m_sliceHeight;
740  encoderport.format.image.eCompressionFormat = OMX_IMAGE_CodingJPEG;
741  encoderport.format.image.eColorFormat = OMX_COLOR_FormatUnused;
742 
743  if (m_imageEncoder.SetParameter(OMX_IndexParamPortDefinition, &encoderport))
744  return false;
745 
746  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Set image encoder output parameters"));
747 
748  OMX_INITSTRUCTURE(encoderport);
749  encoderport.nPortIndex = m_imageEncoder.GetPort(OMX_DirInput, 0, OMX_IndexParamImageInit);
750  if (m_imageEncoder.GetParameter(OMX_IndexParamPortDefinition, &encoderport))
751  return false;
752 
753  encoderport.format.image.nFrameWidth = m_params.m_width;
754  encoderport.format.image.nFrameHeight = m_params.m_height;
755  encoderport.format.image.nStride = m_params.m_stride;
756  encoderport.format.image.nSliceHeight = m_params.m_sliceHeight;
757  encoderport.format.image.eCompressionFormat = OMX_IMAGE_CodingUnused;
758  encoderport.format.image.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar;
759 
760  if (m_imageEncoder.SetParameter(OMX_IndexParamPortDefinition, &encoderport))
761  return false;
762 
763  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Set image encoder input parameters"));
764  return true;
765 }
766 
767 bool TorcPiCamera::ConfigureVideoEncoder(void)
768 {
769  if (!m_videoEncoderOutputPort)
770  return false;
771 
772  // Encoder output
773  OMX_PARAM_PORTDEFINITIONTYPE encoderport;
774  OMX_INITSTRUCTURE(encoderport);
775  encoderport.nPortIndex = m_videoEncoderOutputPort;
776  if (m_videoEncoder.GetParameter(OMX_IndexParamPortDefinition, &encoderport))
777  return false;
778 
779  encoderport.format.video.nFrameWidth = m_params.m_width;
780  encoderport.format.video.nFrameHeight = m_params.m_height;
781  encoderport.format.video.nStride = m_params.m_stride;
782  encoderport.format.video.nSliceHeight = m_params.m_sliceHeight;
783  encoderport.format.video.xFramerate = m_params.m_frameRate << 16;
784  encoderport.format.video.nBitrate = ENCODER_QP ? 0 : m_params.m_bitrate;
785  encoderport.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
786  if (m_videoEncoder.SetParameter(OMX_IndexParamPortDefinition, &encoderport))
787  return false;
788 
789  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Set video encoder output parameters"));
790 
791  if (!ENCODER_QP)
792  {
793  OMX_VIDEO_PARAM_BITRATETYPE bitrate;
794  OMX_INITSTRUCTURE(bitrate);
795  bitrate.eControlRate = OMX_Video_ControlRateVariable;
796  bitrate.nTargetBitrate = m_params.m_bitrate;
797  bitrate.nPortIndex = m_videoEncoderOutputPort;
798  if (m_videoEncoder.SetParameter(OMX_IndexParamVideoBitrate, &bitrate))
799  return false;
800 
801  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Set video encoder output bitrate"));
802  }
803  else
804  {
805  // quantization
806  OMX_VIDEO_PARAM_QUANTIZATIONTYPE quantization;
807  OMX_INITSTRUCTURE(quantization);
808  quantization.nPortIndex = m_videoEncoderOutputPort;
809  quantization.nQpI = ENCODER_QP_I;
810  quantization.nQpP = ENCODER_QP_P;
811  if (m_videoEncoder.SetParameter(OMX_IndexParamVideoQuantization, &quantization))
812  return false;
813 
814  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Set video encoder output quantization"));
815  }
816 
817  // codec
818  OMX_VIDEO_PARAM_PORTFORMATTYPE format;
819  OMX_INITSTRUCTURE(format);
820  format.nPortIndex = m_videoEncoderOutputPort;
821  format.eCompressionFormat = OMX_VIDEO_CodingAVC;
822  if (m_videoEncoder.SetParameter(OMX_IndexParamVideoPortFormat, &format))
823  return false;
824 
825  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Set video encoder output format"));
826 
827  // IDR period
828  OMX_VIDEO_CONFIG_AVCINTRAPERIOD idr;
829  OMX_INITSTRUCTURE(idr);
830  idr.nPortIndex = m_videoEncoderOutputPort;
831  if (m_videoEncoder.GetConfig(OMX_IndexConfigVideoAVCIntraPeriod, &idr))
832  return false;
833  idr.nIDRPeriod = m_params.m_frameRate * VIDEO_GOPDURA_TARGET;
834  if (m_videoEncoder.SetConfig(OMX_IndexConfigVideoAVCIntraPeriod, &idr))
835  return false;
836 
837  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Set video encoder output IDR to %1").arg(m_params.m_frameRate * VIDEO_GOPDURA_TARGET));
838 
839  // SEI
840  OMX_PARAM_BRCMVIDEOAVCSEIENABLETYPE sei;
841  OMX_INITSTRUCTURE(sei);
842  sei.nPortIndex = m_videoEncoderOutputPort;
843  sei.bEnable = ENCODER_SEI;
844  if (m_videoEncoder.SetParameter(OMX_IndexParamBrcmVideoAVCSEIEnable, &sei))
845  return false;
846 
847  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Set video encoder output SEI"));
848 
849  // EEDE
850  OMX_VIDEO_EEDE_ENABLE eede;
851  OMX_INITSTRUCTURE(eede);
852  eede.nPortIndex = m_videoEncoderOutputPort;
853  eede.enable = ENCODER_EEDE;
854  if (m_videoEncoder.SetParameter(OMX_IndexParamBrcmEEDEEnable, &eede))
855  return false;
856 
857  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Set video endcoder output EEDE"));
858 
859  OMX_VIDEO_EEDE_LOSSRATE eede_loss_rate;
860  OMX_INITSTRUCTURE(eede_loss_rate);
861  eede_loss_rate.nPortIndex = m_videoEncoderOutputPort;
862  eede_loss_rate.loss_rate = ENCODER_EEDE_LOSS_RATE;
863  if (m_videoEncoder.SetParameter(OMX_IndexParamBrcmEEDELossRate, &eede_loss_rate))
864  return false;
865 
866  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Set video encoder output EEDE loss rate"));
867 
868  // profile
869  OMX_VIDEO_AVCPROFILETYPE profile = OMX_VIDEO_AVCProfileMain;
870  switch (VIDEO_H264_PROFILE)
871  {
872  case FF_PROFILE_H264_BASELINE: profile = OMX_VIDEO_AVCProfileBaseline; break;
873  case FF_PROFILE_H264_MAIN: profile = OMX_VIDEO_AVCProfileMain; break;
874  case FF_PROFILE_H264_EXTENDED: profile = OMX_VIDEO_AVCProfileExtended; break;
875  case FF_PROFILE_H264_HIGH: profile = OMX_VIDEO_AVCProfileHigh; break;
876  case FF_PROFILE_H264_HIGH_10: profile = OMX_VIDEO_AVCProfileHigh10; break;
877  case FF_PROFILE_H264_HIGH_422: profile = OMX_VIDEO_AVCProfileHigh422; break;
878  case FF_PROFILE_H264_HIGH_444: profile = OMX_VIDEO_AVCProfileHigh444; break;
879  default:
880  LOG(VB_GENERAL, LOG_WARNING, QStringLiteral("Unknown H264 profile. Defaulting to main"));
881  }
882 
883  OMX_VIDEO_PARAM_AVCTYPE avc;
884  OMX_INITSTRUCTURE(avc);
885  avc.nPortIndex = m_videoEncoderOutputPort;
886  if (m_videoEncoder.GetParameter(OMX_IndexParamVideoAvc, &avc))
887  return false;
888  avc.eProfile = profile;
889  if (m_videoEncoder.SetParameter(OMX_IndexParamVideoAvc, &avc))
890  return false;
891 
892  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Set video encoder output profile"));
893 
894  // Inline SPS/PPS
895  OMX_CONFIG_PORTBOOLEANTYPE headers;
896  OMX_INITSTRUCTURE(headers);
897  headers.nPortIndex = m_videoEncoderOutputPort;
898  headers.bEnabled = ENCODER_INLINE_HEADERS;
899  if (m_videoEncoder.SetParameter(OMX_IndexParamBrcmVideoAVCInlineHeaderEnable, &headers))
900  return false;
901 
902  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Set video encoder output SPS/PPS"));
903 
904  // SPS timing
905  OMX_CONFIG_PORTBOOLEANTYPE timing;
906  OMX_INITSTRUCTURE(timing);
907  timing.nPortIndex = m_videoEncoderOutputPort;
908  timing.bEnabled = ENCODER_SPS_TIMING;
909  if (m_videoEncoder.SetParameter(OMX_IndexParamBrcmVideoAVCSPSTimingEnable, &timing))
910  return false;
911 
912  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Set video encoder SPS timings"));
913  return true;
914 }
915 
917 {
918  OMX_PARAM_U32TYPE single;
919  OMX_INITSTRUCTURE(single);
920  single.nPortIndex = m_splitter.GetPort(OMX_DirOutput, 1, OMX_IndexParamVideoInit);
921  single.nU32 = Count;
922  if (m_splitter.SetParameter(OMX_IndexConfigSingleStep, &single))
923  return false;
924 
925  return TorcCameraDevice::EnableStills(Count);
926 }
927 
928 static const QString piCameraType = QStringLiteral(
929 " <xs:element name=\"pi\" type=\"cameraType\"/>\r\n");
930 
932 {
933  public:
934  void GetXSD(QMultiMap<QString,QString> &XSD) { XSD.insert(XSD_CAMERATYPES, piCameraType); }
936 
938 {
939  public:
941  {
942  bcm_host_init();
943  }
944 
946  {
947  bcm_host_deinit();
948  }
949 
950  bool CanHandle(const QString &Type, const TorcCameraParams &Params) override
951  {
952  (void)Params;
953 
954  static bool checked = false;
955  if (!checked)
956  {
957  checked = true;
958 
959  char command[32];
960  int gpumem = 0;
961 
962  if (!vc_gencmd(command, sizeof(command), "get_mem gpu"))
963  vc_gencmd_number_property(command, "gpu", &gpumem);
964 
965  if (gpumem < 128)
966  {
967  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("Insufficent GPU memory for Pi camera - need 128Mb - have %1Mb").arg(gpumem));
968  }
969  else
970  {
971  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("%1Mb GPU memory").arg(gpumem));
972 
973  int supported = 0;
974  int detected = 0;
975 
976  if (!vc_gencmd(command, sizeof(command), "get_camera"))
977  {
978  vc_gencmd_number_property(command, "supported", &supported);
979  vc_gencmd_number_property(command, "detected", &detected);
980  }
981 
982  if (!supported)
983  {
984  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("Firmware reports that Pi camera is NOT supported"));
985  }
986  else if (!detected)
987  {
988  LOG(VB_GENERAL, LOG_ERR, QStringLiteral("Firmware reports that Pi camera NOT detected"));
989  }
990  else
991  {
992  LOG(VB_GENERAL, LOG_INFO, QStringLiteral("Pi camera supported and detected"));
994  }
995  }
996  }
997 
998  return TorcPiCamera::gPiCameraDetected ? QStringLiteral("pi") == Type : false;
999  }
1000 
1001  TorcCameraDevice* Create(const QString &Type, const TorcCameraParams &Params) override
1002  {
1003  if ((QStringLiteral("pi") == Type) && TorcPiCamera::gPiCameraDetected)
1004  return new TorcPiCamera(Params);
1005  return nullptr;
1006  }
1007 
1008  QString GetCameraName()
1009  {
1010  return QObject::tr("Pi Camera");
1011  }
1013 
1014 /* vim: set expandtab tabstop=4 shiftwidth=4: */
#define CAMERA_ROI_TOP
#define BROADCOM_CAMERA
OMX_U32 GetInUseBuffers(OMX_DIRTYPE Direction, OMX_U32 Index, OMX_INDEXTYPE Domain)
QString m_videoCodec
Definition: torccamera.h:58
OMX_ERRORTYPE SetState(OMX_STATETYPE State, bool Wait=true)
OMX_U32 GetPort(OMX_DIRTYPE Direction, OMX_U32 Index, OMX_INDEXTYPE Domain)
#define ENCODER_QP_P
#define CAMERA_SHUTTER_SPEED
#define VIDEO_H264_PROFILE
Definition: torccamera.h:31
#define CAMERA_COLOR_V
OMX_ERRORTYPE Create(void)
OMX_BUFFERHEADERTYPE * GetBuffer(OMX_DIRTYPE Direction, OMX_U32 Index, OMX_U32 Timeout, OMX_INDEXTYPE Domain)
#define CAMERA_COLOR_ENABLE
TorcCameraParams m_params
Definition: torccamera.h:102
#define CAMERA_WHITE_BALANCE_RED_GAIN
TorcPiCamera(const TorcCameraParams &Params)
static QString GetAVCCodec(const QByteArray &Packet)
Determine the 3 byte H.264 codec descriptor string.
Definition: torcmuxer.cpp:243
OMX_ERRORTYPE SetConfig(OMX_INDEXTYPE Index, OMX_PTR Structure)
OMX_ERRORTYPE DestroyBuffers(OMX_DIRTYPE Direction, OMX_U32 Index, OMX_INDEXTYPE Domain)
#define CAMERA_ROTATION
QReadWriteLock m_ringBufferLock
Definition: torccamera.h:111
bool Stop(void) override
#define ENCODER_QP
#define ENCODER_QP_I
void WritingStarted(void)
bool AddPacket(AVPacket *Packet, bool CodecConfig)
Definition: torcmuxer.cpp:434
#define ENCODER_SEI
#define CAMERA_ROI_LEFT
void Start(void)
Definition: torctimer.cpp:9
#define CAMERA_ROI_WIDTH
#define CAMERA_WHITE_BALANCE
#define CAMERA_FRAME_STABILIZATION
#define BROADCOM_VIDEOSPLITTER
AVPacket * m_bufferedPacket
Definition: torccamera.h:109
TorcPiCameraXSDFactory TorcPiCameraXSDFactory
OMX_ERRORTYPE EnablePort(OMX_DIRTYPE Direction, OMX_U32 Index, bool Enable, OMX_INDEXTYPE Domain, bool Wait=true)
void FinishSegment(bool Init)
Definition: torcmuxer.cpp:467
#define ENCODER_EEDE
virtual bool EnableStills(uint Count)
Definition: torccamera.cpp:341
#define CAMERA_COLOR_U
quint64 m_frameCount
Definition: torccamera.h:107
#define VIDEO_SEGMENT_TARGET
Definition: torccamera.h:24
bool EnableStills(uint Count) override
#define CAMERA_ISO
void BufferReady(OMX_BUFFERHEADERTYPE *Buffer, quint64 Type)
An OpenMax buffer is ready (full)
#define BROADCOM_ENCODER
#define CAMERA_METERING
bool Start(void) override
Start the camera.
VERBOSE_PREAMBLE true
#define CAMERA_ROI_HEIGHT
bool m_haveInitSegment
Definition: torccamera.h:108
OMX_ERRORTYPE CreateBuffers(OMX_DIRTYPE Direction, OMX_U32 Index, OMX_INDEXTYPE Domain, QObject *Owner=nullptr)
#define CAMERA_CONTRAST
#define CAMERA_BRIGHTNESS
#define CAMERA_ISO_AUTO
#define ENCODER_SPS_TIMING
bool CanHandle(const QString &Type, const TorcCameraParams &Params) override
#define CAMERA_MIRROR
#define CAMERA_DRC
#define BROADCOM_NULLSINK
void ParametersChanged(TorcCameraParams &Params)
#define ENCODER_EEDE_LOSS_RATE
static const QString piCameraType
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: torclogging.h:20
OMX_U32 GetAvailableBuffers(OMX_DIRTYPE Direction, OMX_U32 Index, OMX_INDEXTYPE Domain)
void GetXSD(QMultiMap< QString, QString > &XSD)
#define CAMERA_IMAGE_FILTER
virtual bool Setup(void)
Definition: torccamera.cpp:286
bool Setup(void) override
OMX_ERRORTYPE GetParameter(OMX_INDEXTYPE Index, OMX_PTR Structure)
#define XSD_CAMERATYPES
Definition: torccentral.h:65
#define CAMERA_EXPOSURE
#define ENCODER_INLINE_HEADERS
OMX_ERRORTYPE GetConfig(OMX_INDEXTYPE Index, OMX_PTR Structure)
void SaveStill(void)
Definition: torccamera.cpp:348
TorcPiCameraFactory TorcPiCameraFactory
OMX_ERRORTYPE Destroy(void)
void StartStill(void) override
Start capturing a still image buffer.
#define BROADCOM_IMAGEENCODER
void WritingStopped(void)
TorcMuxer * m_muxer
Definition: torccamera.h:105
#define CAMERA_NOISE_REDUCTION
OMX_ERRORTYPE SetParameter(OMX_INDEXTYPE Index, OMX_PTR Structure)
#define CAMERA_SATURATION
OMX_ERRORTYPE WaitForResponse(OMX_U32 Command, OMX_U32 Data2, OMX_S32 Timeout)
#define VIDEO_GOPDURA_TARGET
Definition: torccamera.h:25
static bool gPiCameraDetected
Definition: torcpicamera.h:23
void SaveStillBuffer(quint32 Length, uint8_t *Data)
Definition: torccamera.cpp:378
#define CAMERA_SHUTTER_SPEED_AUTO
#define CAMERA_EXPOSURE_COMPENSATION
#define CAMERA_SHARPNESS
virtual ~TorcPiCameraFactory()
#define CAMERA_WHITE_BALANCE_BLUE_GAIN
void StreamVideo(bool Video) override
OMX_ERRORTYPE FillThisBuffer(OMX_BUFFERHEADERTYPE *Buffer)
void TrackDrift(void)
Definition: torccamera.cpp:394
int Elapsed(void)
Definition: torctimer.cpp:22
TorcCameraDevice * Create(const QString &Type, const TorcCameraParams &Params) override
OMX_ERRORTYPE DisablePorts(OMX_INDEXTYPE Domain)
#define OMX_INITSTRUCTURE(Struct)
Definition: torcomxcore.h:28