Advertisement
asghaer

Untitled

Jun 27th, 2017
855
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 60.31 KB | None | 0 0
  1. //Original credits to Artem Zuikov
  2. //clone from https://github.com/4ertus2/rpi-cctv
  3. // Adding other functionnalities F5OEO Evariste - evaristec@gmail.com
  4. #ifndef OMX_SKIP64BIT
  5. #define OMX_SKIP64BIT
  6. #endif
  7.  
  8. #include <cstdlib>
  9. #include <cstdio>
  10. #include <cstring>
  11.  
  12. #include <string>
  13. #include <vector>
  14. #include <iostream>
  15. #include <inttypes.h>
  16. #include <math.h>
  17.  
  18.  
  19. #include "bcm_host.h"
  20.  
  21. #include <interface/vcos/vcos_semaphore.h>
  22. #include <interface/vmcs_host/vchost.h>
  23.  
  24.  
  25. #include <IL/OMX_Core.h>
  26. #include <IL/OMX_Component.h>
  27. #include <IL/OMX_Video.h>
  28. #include <IL/OMX_Broadcom.h>
  29.  
  30. #include <fcntl.h>              /* low-level i/o */
  31. #include <unistd.h>
  32. #include <errno.h>
  33. #include <sys/stat.h>
  34. #include <sys/types.h>
  35. #include <sys/time.h>
  36. #include <sys/mman.h>
  37. #include <sys/ioctl.h>
  38. #include "webcam.h"
  39. #include "MuxTs.h"
  40.  
  41.  
  42.  
  43. namespace
  44. {
  45.     static const char * format2str(OMX_VIDEO_CODINGTYPE c)
  46.     {
  47.         switch (c)
  48.         {
  49.             case OMX_VIDEO_CodingUnused:        return "not used";
  50.             case OMX_VIDEO_CodingAutoDetect:    return "autodetect";
  51.             case OMX_VIDEO_CodingMPEG2:         return "MPEG2";
  52.             case OMX_VIDEO_CodingH263:          return "H.263";
  53.             case OMX_VIDEO_CodingMPEG4:         return "MPEG4";
  54.             case OMX_VIDEO_CodingWMV:           return "Windows Media Video";
  55.             case OMX_VIDEO_CodingRV:            return "RealVideo";
  56.             case OMX_VIDEO_CodingAVC:           return "H.264/AVC";
  57.             case OMX_VIDEO_CodingMJPEG:         return "Motion JPEG";
  58.             case OMX_VIDEO_CodingVP6:           return "VP6";
  59.             case OMX_VIDEO_CodingVP7:           return "VP7";
  60.             case OMX_VIDEO_CodingVP8:           return "VP8";
  61.             case OMX_VIDEO_CodingYUV:           return "Raw YUV video";
  62.             case OMX_VIDEO_CodingSorenson:      return "Sorenson";
  63.             case OMX_VIDEO_CodingTheora:        return "OGG Theora";
  64.             case OMX_VIDEO_CodingMVC:           return "H.264/MVC";
  65.             default:
  66.                 std::cerr << "unknown OMX_VIDEO_CODINGTYPE: " << c << std::endl;
  67.                 return "unknown";
  68.         }
  69.     }
  70.  
  71.     static const char * format2str(OMX_COLOR_FORMATTYPE c)
  72.     {
  73.         switch (c)
  74.         {
  75.             case OMX_COLOR_FormatUnused:                 return "OMX_COLOR_FormatUnused: not used";
  76.             case OMX_COLOR_FormatMonochrome:             return "OMX_COLOR_FormatMonochrome";
  77.             case OMX_COLOR_Format8bitRGB332:             return "OMX_COLOR_Format8bitRGB332";
  78.             case OMX_COLOR_Format12bitRGB444:            return "OMX_COLOR_Format12bitRGB444";
  79.             case OMX_COLOR_Format16bitARGB4444:          return "OMX_COLOR_Format16bitARGB4444";
  80.             case OMX_COLOR_Format16bitARGB1555:          return "OMX_COLOR_Format16bitARGB1555";
  81.             case OMX_COLOR_Format16bitRGB565:            return "OMX_COLOR_Format16bitRGB565";
  82.             case OMX_COLOR_Format16bitBGR565:            return "OMX_COLOR_Format16bitBGR565";
  83.             case OMX_COLOR_Format18bitRGB666:            return "OMX_COLOR_Format18bitRGB666";
  84.             case OMX_COLOR_Format18bitARGB1665:          return "OMX_COLOR_Format18bitARGB1665";
  85.             case OMX_COLOR_Format19bitARGB1666:          return "OMX_COLOR_Format19bitARGB1666";
  86.             case OMX_COLOR_Format24bitRGB888:            return "OMX_COLOR_Format24bitRGB888";
  87.             case OMX_COLOR_Format24bitBGR888:            return "OMX_COLOR_Format24bitBGR888";
  88.             case OMX_COLOR_Format24bitARGB1887:          return "OMX_COLOR_Format24bitARGB1887";
  89.             case OMX_COLOR_Format25bitARGB1888:          return "OMX_COLOR_Format25bitARGB1888";
  90.             case OMX_COLOR_Format32bitBGRA8888:          return "OMX_COLOR_Format32bitBGRA8888";
  91.             case OMX_COLOR_Format32bitARGB8888:          return "OMX_COLOR_Format32bitARGB8888";
  92.             case OMX_COLOR_FormatYUV411Planar:           return "OMX_COLOR_FormatYUV411Planar";
  93.             case OMX_COLOR_FormatYUV411PackedPlanar:     return "OMX_COLOR_FormatYUV411PackedPlanar: Planes fragmented when a frame is split in multiple buffers";
  94.             case OMX_COLOR_FormatYUV420Planar:           return "OMX_COLOR_FormatYUV420Planar: Planar YUV, 4:2:0 (I420)";
  95.             case OMX_COLOR_FormatYUV420PackedPlanar:     return "OMX_COLOR_FormatYUV420PackedPlanar: Planar YUV, 4:2:0 (I420), planes fragmented when a frame is split in multiple buffers";
  96.             case OMX_COLOR_FormatYUV420SemiPlanar:       return "OMX_COLOR_FormatYUV420SemiPlanar, Planar YUV, 4:2:0 (NV12), U and V planes interleaved with first U value";
  97.             case OMX_COLOR_FormatYUV422Planar:           return "OMX_COLOR_FormatYUV422Planar";
  98.             case OMX_COLOR_FormatYUV422PackedPlanar:     return "OMX_COLOR_FormatYUV422PackedPlanar: Planes fragmented when a frame is split in multiple buffers";
  99.             case OMX_COLOR_FormatYUV422SemiPlanar:       return "OMX_COLOR_FormatYUV422SemiPlanar";
  100.             case OMX_COLOR_FormatYCbYCr:                 return "OMX_COLOR_FormatYCbYCr";
  101.             case OMX_COLOR_FormatYCrYCb:                 return "OMX_COLOR_FormatYCrYCb";
  102.             case OMX_COLOR_FormatCbYCrY:                 return "OMX_COLOR_FormatCbYCrY";
  103.             case OMX_COLOR_FormatCrYCbY:                 return "OMX_COLOR_FormatCrYCbY";
  104.             case OMX_COLOR_FormatYUV444Interleaved:      return "OMX_COLOR_FormatYUV444Interleaved";
  105.             case OMX_COLOR_FormatRawBayer8bit:           return "OMX_COLOR_FormatRawBayer8bit";
  106.             case OMX_COLOR_FormatRawBayer10bit:          return "OMX_COLOR_FormatRawBayer10bit";
  107.             case OMX_COLOR_FormatRawBayer8bitcompressed: return "OMX_COLOR_FormatRawBayer8bitcompressed";
  108.             case OMX_COLOR_FormatL2:                     return "OMX_COLOR_FormatL2";
  109.             case OMX_COLOR_FormatL4:                     return "OMX_COLOR_FormatL4";
  110.             case OMX_COLOR_FormatL8:                     return "OMX_COLOR_FormatL8";
  111.             case OMX_COLOR_FormatL16:                    return "OMX_COLOR_FormatL16";
  112.             case OMX_COLOR_FormatL24:                    return "OMX_COLOR_FormatL24";
  113.             case OMX_COLOR_FormatL32:                    return "OMX_COLOR_FormatL32";
  114.             case OMX_COLOR_FormatYUV420PackedSemiPlanar: return "OMX_COLOR_FormatYUV420PackedSemiPlanar: Planar YUV, 4:2:0 (NV12), planes fragmented when a frame is split in multiple buffers, U and V planes interleaved with first U value";
  115.             case OMX_COLOR_FormatYUV422PackedSemiPlanar: return "OMX_COLOR_FormatYUV422PackedSemiPlanar: Planes fragmented when a frame is split in multiple buffers";
  116.             case OMX_COLOR_Format18BitBGR666:            return "OMX_COLOR_Format18BitBGR666";
  117.             case OMX_COLOR_Format24BitARGB6666:          return "OMX_COLOR_Format24BitARGB6666";
  118.             case OMX_COLOR_Format24BitABGR6666:          return "OMX_COLOR_Format24BitABGR6666";
  119.             case OMX_COLOR_Format32bitABGR8888:          return "OMX_COLOR_Format32bitABGR8888";
  120.             case OMX_COLOR_Format8bitPalette:            return "OMX_COLOR_Format8bitPalette";
  121.             case OMX_COLOR_FormatYUVUV128:               return "OMX_COLOR_FormatYUVUV128";
  122.             case OMX_COLOR_FormatRawBayer12bit:          return "OMX_COLOR_FormatRawBayer12bit";
  123.             case OMX_COLOR_FormatBRCMEGL:                return "OMX_COLOR_FormatBRCMEGL";
  124.             case OMX_COLOR_FormatBRCMOpaque:             return "OMX_COLOR_FormatBRCMOpaque";
  125.             case OMX_COLOR_FormatYVU420PackedPlanar:     return "OMX_COLOR_FormatYVU420PackedPlanar";
  126.             case OMX_COLOR_FormatYVU420PackedSemiPlanar: return "OMX_COLOR_FormatYVU420PackedSemiPlanar";
  127.             default:
  128.                 std::cerr << "unknown OMX_COLOR_FORMATTYPE: " << c << std::endl;
  129.                 return "unknown";
  130.         }
  131.     }
  132.  
  133.     static void dump_portdef(OMX_PARAM_PORTDEFINITIONTYPE* portdef)
  134.     {
  135.         fprintf(stderr, "Port %d is %s, %s, buffers wants:%d needs:%d, size:%d, pop:%d, aligned:%d\n",
  136.             portdef->nPortIndex,
  137.             (portdef->eDir ==  OMX_DirInput ? "input" : "output"),
  138.             (portdef->bEnabled == OMX_TRUE ? "enabled" : "disabled"),
  139.             portdef->nBufferCountActual,
  140.             portdef->nBufferCountMin,
  141.             portdef->nBufferSize,
  142.             portdef->bPopulated,
  143.             portdef->nBufferAlignment);
  144.  
  145.         OMX_VIDEO_PORTDEFINITIONTYPE *viddef = &portdef->format.video;
  146.         OMX_IMAGE_PORTDEFINITIONTYPE *imgdef = &portdef->format.image;
  147.  
  148.         switch (portdef->eDomain)
  149.         {
  150.             case OMX_PortDomainVideo:
  151.                 fprintf(stderr, "Video type:\n"
  152.                     "\tWidth:\t\t%d\n"
  153.                     "\tHeight:\t\t%d\n"
  154.                     "\tStride:\t\t%d\n"
  155.                     "\tSliceHeight:\t%d\n"
  156.                     "\tBitrate:\t%d\n"
  157.                     "\tFramerate:\t%.02f\n"
  158.                     "\tError hiding:\t%s\n"
  159.                     "\tCodec:\t\t%s\n"
  160.                     "\tColor:\t\t%s\n",
  161.                     viddef->nFrameWidth,
  162.                     viddef->nFrameHeight,
  163.                     viddef->nStride,
  164.                     viddef->nSliceHeight,
  165.                     viddef->nBitrate,
  166.                     ((float)viddef->xFramerate / (float)65536),
  167.                     (viddef->bFlagErrorConcealment == OMX_TRUE ? "yes" : "no"),
  168.                     format2str(viddef->eCompressionFormat),
  169.                     format2str(viddef->eColorFormat));
  170.                 break;
  171.             case OMX_PortDomainImage:
  172.                 fprintf(stderr, "Image type:\n"
  173.                     "\tWidth:\t\t%d\n"
  174.                     "\tHeight:\t\t%d\n"
  175.                     "\tStride:\t\t%d\n"
  176.                     "\tSliceHeight:\t%d\n"
  177.                     "\tError hiding:\t%s\n"
  178.                     "\tCodec:\t\t%s\n"
  179.                     "\tColor:\t\t%s\n",
  180.                     imgdef->nFrameWidth,
  181.                     imgdef->nFrameHeight,
  182.                     imgdef->nStride,
  183.                     imgdef->nSliceHeight,
  184.                     (imgdef->bFlagErrorConcealment == OMX_TRUE ? "yes" : "no"),
  185.                     format2str( (OMX_VIDEO_CODINGTYPE) imgdef->eCompressionFormat ),
  186.                     format2str(imgdef->eColorFormat));
  187.                 break;
  188.             default:
  189.                 break;
  190.         }
  191.     }
  192.  
  193.     const char * eventType2Str(OMX_EVENTTYPE eEvent)
  194.     {
  195.         switch (eEvent)
  196.         {
  197.             case OMX_EventCmdComplete:          return "OMX_EventCmdComplete";
  198.             case OMX_EventError:                return "OMX_EventError";
  199.             case OMX_EventMark:                 return "OMX_EventMark";
  200.             case OMX_EventPortSettingsChanged:  return "OMX_EventPortSettingsChanged";
  201.             case OMX_EventBufferFlag:           return "OMX_EventBufferFlag";
  202.             case OMX_EventResourcesAcquired:    return "OMX_EventResourcesAcquired";
  203.             case OMX_EventComponentResumed:     return "OMX_EventComponentResumed";
  204.             case OMX_EventDynamicResourcesAvailable: return "OMX_EventDynamicResourcesAvailable";
  205.             case OMX_EventPortFormatDetected:   return "OMX_EventPortFormatDetected";
  206.             case OMX_EventKhronosExtensions:    return "OMX_EventKhronosExtensions";
  207.             case OMX_EventVendorStartUnused:    return "OMX_EventVendorStartUnused";
  208.             case OMX_EventParamOrConfigChanged: return "OMX_EventParamOrConfigChanged";
  209.             default:
  210.                 break;
  211.         };
  212.  
  213.         return nullptr;
  214.     }
  215.  
  216.     static void printEvent(const char * compName, OMX_HANDLETYPE hComponent, OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2)
  217.     {
  218.         const char * strEvent = eventType2Str(eEvent);
  219.         if (strEvent)
  220.             fprintf(stderr, "%s (%p) %s, data: %d, %d\n", compName, hComponent, strEvent, nData1, nData2);
  221.         else
  222.             fprintf(stderr, "%s (%p) 0x%08x, data: %d, %d\n", compName, hComponent, eEvent, nData1, nData2);
  223.     }
  224. }
  225.  
  226. namespace broadcom
  227. {
  228.     // TODO: add all
  229.  
  230.     typedef enum
  231.     {
  232.         VIDEO_SCHEDULER = 10,
  233.         SOURCE = 20,
  234.         RESIZER = 60,
  235.         CAMERA = 70,
  236.         CLOCK = 80,
  237.         VIDEO_RENDER = 90,
  238.         VIDEO_DECODER = 130,
  239.         VIDEO_ENCODER = 200,
  240.         EGL_RENDER = 220,
  241.         NULL_SINK = 240,
  242.         VIDEO_SPLITTER = 250,
  243.     IMAGE_ENCODE = 340
  244.     } ComponentType;
  245.  
  246.     static const char * componentType2name(ComponentType type)
  247.     {
  248.         switch (type)
  249.         {
  250.             case VIDEO_SCHEDULER:   return "OMX.broadcom.video_scheduler";
  251.             case SOURCE:            return "OMX.broadcom.source";
  252.             case RESIZER:           return "OMX.broadcom.resize";
  253.             case CAMERA:            return "OMX.broadcom.camera";
  254.             case CLOCK:             return "OMX.broadcom.clock";
  255.             case VIDEO_RENDER:      return "OMX.broadcom.video_render";
  256.             case VIDEO_DECODER:     return "OMX.broadcom.video_decode";
  257.             case VIDEO_ENCODER:     return "OMX.broadcom.video_encode";
  258.             case EGL_RENDER:        return "OMX.broadcom.egl_render";
  259.             case NULL_SINK:         return "OMX.broadcom.null_sink";
  260.             case VIDEO_SPLITTER:    return "OMX.broadcom.video_splitter";
  261.         case IMAGE_ENCODE:  return "OMX.broadcom.image_encode";
  262.         }
  263.  
  264.         return nullptr;
  265.     }
  266.  
  267.     static unsigned componentPortsCount(ComponentType type)
  268.     {
  269.         switch (type)
  270.         {
  271.             case VIDEO_SCHEDULER:   return 3;
  272.             case SOURCE:            return 1;
  273.             case RESIZER:           return 2;
  274.             case CAMERA:            return 4;
  275.             case CLOCK:             return 6;
  276.             case VIDEO_RENDER:      return 1;
  277.             case VIDEO_DECODER:     return 2;
  278.             case VIDEO_ENCODER:     return 2;
  279.             case EGL_RENDER:        return 2;
  280.             case NULL_SINK:         return 3;
  281.             case VIDEO_SPLITTER:    return 5;
  282.          case IMAGE_ENCODE: return 2;
  283.         }
  284.  
  285.         return 0;
  286.     }
  287.  
  288.     struct VcosSemaphore
  289.     {
  290.         VcosSemaphore(const char * name)
  291.         {
  292.             if (vcos_semaphore_create(&sem_, name, 1) != VCOS_SUCCESS)
  293.                 throw "Failed to create handler lock semaphore";
  294.         }
  295.  
  296.         ~VcosSemaphore()
  297.         {
  298.             vcos_semaphore_delete(&sem_);
  299.         }
  300.  
  301.         VCOS_STATUS_T wait() { return vcos_semaphore_wait(&sem_); }
  302.         VCOS_STATUS_T post() { return vcos_semaphore_post(&sem_); }
  303.  
  304.     private:
  305.         VCOS_SEMAPHORE_T sem_;
  306.     };
  307.  
  308.     class VcosLock
  309.     {
  310.     public:
  311.         VcosLock(VcosSemaphore * sem)
  312.         :   sem_(sem)
  313.         {
  314.             sem_->wait();
  315.         }
  316.  
  317.         ~VcosLock()
  318.         {
  319.             sem_->post();
  320.         }
  321.  
  322.     private:
  323.         VcosSemaphore * sem_;
  324.     };
  325. }
  326.  
  327. namespace rpi_omx
  328. {
  329.     typedef broadcom::ComponentType ComponentType;
  330.     using broadcom::componentType2name;
  331.     using broadcom::componentPortsCount;
  332.  
  333.     using broadcom::VcosSemaphore;
  334.     using Lock = broadcom::VcosLock;
  335.  
  336.     VcosSemaphore * pSemaphore;
  337.  
  338.     //
  339.  
  340.     static OMX_ERRORTYPE callback_EventHandler(
  341.         OMX_HANDLETYPE hComponent,
  342.         OMX_PTR pAppData,
  343.         OMX_EVENTTYPE eEvent,
  344.         OMX_U32 nData1,
  345.         OMX_U32 nData2,
  346.         OMX_PTR pEventData);
  347.  
  348.     static OMX_ERRORTYPE callback_EmptyBufferDone(
  349.         OMX_HANDLETYPE hComponent,
  350.         OMX_PTR pAppData,
  351.         OMX_BUFFERHEADERTYPE * pBuffer);
  352.  
  353.     static OMX_ERRORTYPE callback_FillBufferDone(
  354.         OMX_HANDLETYPE hComponent,
  355.         OMX_PTR pAppData,
  356.         OMX_BUFFERHEADERTYPE * pBuffer);
  357.  
  358.     OMX_CALLBACKTYPE cbsEvents = {
  359.         .EventHandler = callback_EventHandler,
  360.         .EmptyBufferDone = callback_EmptyBufferDone,
  361.         .FillBufferDone = callback_FillBufferDone
  362.     };
  363.  
  364.     //
  365.  
  366.     ///
  367.     class OMXExeption
  368.     {
  369.     public:
  370.         static const unsigned MAX_LEN = 512;
  371.  
  372.         OMXExeption(OMX_ERRORTYPE errCode, const char * file, unsigned line, const char * msg = nullptr)
  373.         :   errCode_(errCode)
  374.         {
  375.             if (msg && msg[0])
  376.                 snprintf(msg_, MAX_LEN, "%s:%d OpenMAX IL error: 0x%08x. %s", file, line, errCode, msg);
  377.             else
  378.                 snprintf(msg_, MAX_LEN, "%s:%d OpenMAX IL error: 0x%08x", file, line, errCode);
  379.         }
  380.  
  381.         OMX_ERRORTYPE code() const { return errCode_; }
  382.         const char * what() const { return msg_; }
  383.  
  384.         static void die(OMX_ERRORTYPE error, const char * str)
  385.         {
  386.             const char * errStr = omxErr2str(error);
  387.             fprintf(stderr, "OMX error: %s: 0x%08x %s\n", str, error, errStr);
  388.             exit(1);
  389.         }
  390.  
  391.     private:
  392.         OMX_ERRORTYPE errCode_;
  393.         char msg_[MAX_LEN];
  394.  
  395.         static const char * omxErr2str(OMX_ERRORTYPE error)
  396.         {
  397.             switch (error)
  398.             {
  399.                 case OMX_ErrorNone:                     return "OMX_ErrorNone";
  400.                 case OMX_ErrorBadParameter:             return "OMX_ErrorBadParameter";
  401.                 case OMX_ErrorIncorrectStateOperation:  return "OMX_ErrorIncorrectStateOperation";
  402.                 case OMX_ErrorIncorrectStateTransition: return "OMX_ErrorIncorrectStateTransition";
  403.                 case OMX_ErrorInsufficientResources:    return "OMX_ErrorInsufficientResources";
  404.                 case OMX_ErrorBadPortIndex:             return "OMX_ErrorBadPortIndex";
  405.                 case OMX_ErrorHardware:                 return "OMX_ErrorHardware";
  406.                 // ...
  407.  
  408.                 default:
  409.                     break;
  410.             }
  411.  
  412.             return "";
  413.         }
  414.     };
  415.  
  416. #define ERR_OMX(err, msg) if ((err) != OMX_ErrorNone) throw OMXExeption(err, __FILE__, __LINE__, msg)
  417.  
  418.     ///
  419.     struct VideoFromat
  420.     {
  421.         typedef enum
  422.         {
  423.             RATIO_4x3,
  424.             RATIO_16x9
  425.         } Ratio;
  426.  
  427.         unsigned width;
  428.         unsigned height;
  429.         unsigned framerate;
  430.         Ratio ratio;
  431.         bool fov; //Field of view
  432.     };
  433.  
  434.  
  435.  
  436.  
  437.  
  438.     static const VideoFromat VF_640x480 = { 640, 480, 30, VideoFromat:: RATIO_16x9, true };
  439.  
  440.     ///
  441.     template <typename T>
  442.     class Parameter
  443.     {
  444.     public:
  445.         Parameter()
  446.         {
  447.             init();
  448.         }
  449.  
  450.         void init()
  451.         {
  452.             memset(&param_, 0, sizeof(param_));
  453.             param_.nSize = sizeof(param_);
  454.             param_.nVersion.nVersion = OMX_VERSION;
  455.             param_.nVersion.s.nVersionMajor = OMX_VERSION_MAJOR;
  456.             param_.nVersion.s.nVersionMinor = OMX_VERSION_MINOR;
  457.             param_.nVersion.s.nRevision = OMX_VERSION_REVISION;
  458.             param_.nVersion.s.nStep = OMX_VERSION_STEP;
  459.         }
  460.  
  461.         T& operator * () { return param_; }
  462.         T* operator & () { return &param_; }
  463.         T* operator -> () { return &param_; }
  464.  
  465.         const T& operator * () const { return param_; }
  466.         const T* operator & () const { return &param_; }
  467.         const T* operator -> () const { return &param_; }
  468.  
  469.     private:
  470.         T param_;
  471.     };
  472.  
  473.     ///
  474.     class OMXInit
  475.     {
  476.     public:
  477.         OMXInit()
  478.         {
  479.             ERR_OMX( OMX_Init(), "OMX initalization failed" );
  480.         }
  481.  
  482.         ~OMXInit()
  483.         {
  484.             try
  485.             {
  486.                 ERR_OMX( OMX_Deinit(), "OMX de-initalization failed" );
  487.             }
  488.             catch (const OMXExeption& )
  489.             {
  490.                 // TODO
  491.             }
  492.         }
  493.     };
  494.  
  495.     ///
  496.     class Buffer
  497.     {
  498.     public:
  499.         Buffer()
  500.         :   ppBuffer_(nullptr),
  501.             fillDone_(false)
  502.         {}
  503.  
  504.         bool filled() const { return fillDone_; }
  505.  
  506.         void setFilled(bool val = true)
  507.         {
  508.             Lock lock(pSemaphore); // LOCK
  509.  
  510.             fillDone_ = val;
  511.         }
  512.  
  513.     bool setDatasize(OMX_U32 Datasize)
  514.     {
  515.         if(Datasize<=allocSize())
  516.         {
  517.             ppBuffer_->nOffset=0;
  518.             ppBuffer_->nFilledLen=Datasize;
  519.             return true;
  520.         }
  521.         return false;
  522.     }
  523.  
  524.         OMX_BUFFERHEADERTYPE ** pHeader() { return &ppBuffer_; }
  525.         OMX_BUFFERHEADERTYPE * header() { return ppBuffer_; }
  526.         OMX_U32 flags() const { return ppBuffer_->nFlags; }
  527.         OMX_U32& flags() { return ppBuffer_->nFlags; }
  528.  
  529.         OMX_U8 * data() { return  ppBuffer_->pBuffer + ppBuffer_->nOffset; }
  530.         OMX_U32 dataSize() const { return ppBuffer_->nFilledLen; }
  531.  
  532.         OMX_U32 allocSize() const { return ppBuffer_->nAllocLen; }
  533.     OMX_U32 TimeStamp() {return ppBuffer_->nTickCount;}
  534.  
  535.     private:
  536.         OMX_BUFFERHEADERTYPE * ppBuffer_;
  537.         bool fillDone_;
  538.     };
  539.  
  540.     ///
  541.     class Component
  542.     {
  543.     public:
  544.         OMX_HANDLETYPE& component() { return component_; }
  545.         ComponentType type() const { return type_; }
  546.         const char * name() const { return componentType2name(type_); }
  547.         unsigned numPorts() const { return componentPortsCount(type_); }
  548.  
  549.         void dumpPort(OMX_U32 nPortIndex, OMX_BOOL dumpFormats = OMX_FALSE)
  550.         {
  551.             Parameter<OMX_PARAM_PORTDEFINITIONTYPE> portdef;
  552.             getPortDefinition(nPortIndex, portdef);
  553.  
  554.             dump_portdef(&portdef);
  555.  
  556.             if (dumpFormats)
  557.             {
  558.                 Parameter<OMX_VIDEO_PARAM_PORTFORMATTYPE> portformat;
  559.                 portformat->nPortIndex = nPortIndex;
  560.                 portformat->nIndex = 0;
  561.  
  562.                 std::cerr << "Port " << nPortIndex << " supports these video formats:" << std::endl;
  563.  
  564.                 for (;; portformat->nIndex++)
  565.                 {
  566.                     OMX_ERRORTYPE err = OMX_GetParameter(component_, OMX_IndexParamVideoPortFormat, &portformat);
  567.                     if (err != OMX_ErrorNone)
  568.                         break;
  569.  
  570.                     std::cerr << "\t" << format2str(portformat->eColorFormat)
  571.                         << ", compression: " << format2str(portformat->eCompressionFormat) << std::endl;
  572.                 }
  573.             }
  574.         }
  575.  
  576.         OMX_STATETYPE state()
  577.         {
  578.             OMX_STATETYPE state;
  579.             ERR_OMX( OMX_GetState(component_, &state), "OMX_GetState" );
  580.             return state;
  581.         }
  582.  
  583.         void switchState(OMX_STATETYPE newState)
  584.         {
  585.             unsigned value = eventState_;
  586.             ERR_OMX( OMX_SendCommand(component_, OMX_CommandStateSet, newState, NULL), "switch state");
  587.  
  588.             if (! waitValue(&eventState_, value + 1))
  589.                 std::cerr << name() << " lost state changed event" << std::endl;
  590. #if 0
  591.             if (! waitStateChanged(newState))
  592.                 std::cerr << name() << " state wanted: " << newState << " observed: " << state() << std::endl;
  593. #endif
  594.         }
  595.  
  596.         unsigned waitCount(OMX_U32 nPortIndex) const { return (nPortIndex == OMX_ALL) ? numPorts() : 1; }
  597.  
  598.         void enablePort(OMX_U32 nPortIndex = OMX_ALL)
  599.         {
  600.             unsigned value = eventEnabled_;
  601.             ERR_OMX( OMX_SendCommand(component_, OMX_CommandPortEnable, nPortIndex, NULL), "enable port");
  602.  
  603.             if (! waitValue(&eventEnabled_, value + waitCount(nPortIndex)))
  604.                 std::cerr << name() << " port " << nPortIndex << " lost enable port event(s)" << std::endl;
  605.         }
  606.  
  607.         void disablePort(OMX_U32 nPortIndex = OMX_ALL)
  608.         {
  609.             unsigned value = eventDisabled_;
  610.             ERR_OMX( OMX_SendCommand(component_, OMX_CommandPortDisable, nPortIndex, NULL), "disable port");
  611.  
  612.             if (! waitValue(&eventDisabled_, value + waitCount(nPortIndex)))
  613.                 std::cerr << name() << " port " << nPortIndex << " lost disable port event(s)" << std::endl;
  614.         }
  615.  
  616.         void flushPort(OMX_U32 nPortIndex = OMX_ALL)
  617.         {
  618.             unsigned value = eventFlushed_;
  619.             ERR_OMX( OMX_SendCommand(component_, OMX_CommandFlush, nPortIndex, NULL), "flush buffers");
  620.  
  621.             if (! waitValue(&eventFlushed_, value + waitCount(nPortIndex)))
  622.                 std::cerr << name() << " port " << nPortIndex << " lost flush port event(s)" << std::endl;
  623.         }
  624.  
  625.         void getPortDefinition(OMX_U32 nPortIndex, Parameter<OMX_PARAM_PORTDEFINITIONTYPE>& portDef)
  626.         {
  627.             portDef->nPortIndex = nPortIndex;
  628.             ERR_OMX( OMX_GetParameter(component_, OMX_IndexParamPortDefinition, &portDef), "get port definition");
  629.         }
  630.  
  631.         void setPortDefinition(OMX_U32 nPortIndex, Parameter<OMX_PARAM_PORTDEFINITIONTYPE>& portDef)
  632.         {
  633.             portDef->nPortIndex = nPortIndex;
  634.             ERR_OMX( OMX_SetParameter(component_, OMX_IndexParamPortDefinition, &portDef), "set port definition");
  635.         }
  636.  
  637.         void allocBuffers(OMX_U32 nPortIndex, Buffer& buffer)
  638.         {
  639.             Parameter<OMX_PARAM_PORTDEFINITIONTYPE> portDef;
  640.             getPortDefinition(nPortIndex, portDef);
  641.  
  642.             ERR_OMX( OMX_AllocateBuffer(component_, buffer.pHeader(), nPortIndex, NULL, portDef->nBufferSize), "OMX_AllocateBuffer");
  643.         }
  644.  
  645.         void freeBuffers(OMX_U32 nPortIndex, Buffer& buffer)
  646.         {
  647.             ERR_OMX( OMX_FreeBuffer(component_, nPortIndex, buffer.header()), "OMX_FreeBuffer");
  648.         }
  649.  
  650.         void callFillThisBuffer(Buffer& buffer)
  651.         {
  652.             ERR_OMX( OMX_FillThisBuffer(component_, buffer.header()), "OMX_FillThisBuffer");
  653.         }
  654.  
  655.      void callEmptyThisBuffer(Buffer& buffer)
  656.         {
  657.             ERR_OMX( OMX_EmptyThisBuffer(component_, buffer.header()), "OMX_EmptyThisBuffer");
  658.         }
  659.  
  660.         void eventCmdComplete(OMX_U32 cmd, OMX_U32 /*nPortIndex*/)
  661.         {
  662.             Lock lock(pSemaphore);  // LOCK
  663.  
  664.             switch (cmd)
  665.             {
  666.                 case OMX_CommandStateSet:
  667.                     ++eventState_;
  668.                     break;
  669.  
  670.                 case OMX_CommandFlush:
  671.                     ++eventFlushed_;
  672.                     break;
  673.  
  674.                 case OMX_CommandPortDisable:
  675.                     ++eventDisabled_;
  676.                     break;
  677.  
  678.                 case OMX_CommandPortEnable:
  679.                     ++eventEnabled_;
  680.                     break;
  681.  
  682.                 case OMX_CommandMarkBuffer:
  683.                 default:
  684.                     break;
  685.             }
  686.         }
  687.  
  688.         void eventPortSettingsChanged(OMX_U32 nPortIndex)
  689.         {
  690.             Lock lock(pSemaphore);  // LOCK
  691.  
  692.             ++changedPorts_[n2idx(nPortIndex)];
  693.         }
  694.  
  695.     protected:
  696.         OMX_HANDLETYPE component_;
  697.         ComponentType type_;
  698.  
  699.         Component(ComponentType type, OMX_PTR pAppData, OMX_CALLBACKTYPE * callbacks)
  700.         :   type_(type),
  701.             eventState_(0),
  702.             eventFlushed_(0),
  703.             eventDisabled_(0),
  704.             eventEnabled_(0)
  705.         {
  706.             changedPorts_.resize(numPorts());
  707.  
  708.             OMX_STRING xName = const_cast<OMX_STRING>(name());
  709.             ERR_OMX( OMX_GetHandle(&component_, xName, pAppData, callbacks), "OMX_GetHandle");
  710.  
  711.             disablePort();
  712.         }
  713.  
  714.         ~Component()
  715.         {
  716.             try
  717.             {
  718.                 ERR_OMX( OMX_FreeHandle(component_), "OMX_FreeHandle" );
  719.             }
  720.             catch (const OMXExeption& )
  721.             {
  722.                 // TODO
  723.             }
  724.         }
  725.  
  726.         // type_ equals to first port number
  727.         unsigned n2idx(OMX_U32 nPortIndex) const { return nPortIndex - type_; }
  728.         unsigned idx2n(unsigned idx) const { return type_ + idx; }
  729.  
  730.     private:
  731.         static const unsigned WAIT_CHANGES_US = 1000;
  732.         static const unsigned MAX_WAIT_COUNT = 200;
  733.  
  734.         unsigned eventState_;
  735.         unsigned eventFlushed_;
  736.         unsigned eventDisabled_;
  737.         unsigned eventEnabled_;
  738.         std::vector<unsigned> changedPorts_;
  739.  
  740.         // TODO: wait for specific port changes
  741.         bool waitValue(unsigned * pValue, unsigned wantedValue)
  742.         {
  743.             for (unsigned i = 0; i < MAX_WAIT_COUNT; ++i)
  744.             {
  745.                 if (*pValue == wantedValue)
  746.                     return true;
  747.  
  748.                 usleep(WAIT_CHANGES_US);
  749.             }
  750.  
  751.             return false;
  752.         }
  753. #if 0
  754.         bool waitStateChanged(OMX_STATETYPE wantedState)
  755.         {
  756.             for (unsigned i=0; i < MAX_WAIT_COUNT; ++i)
  757.             {
  758.                 if (state() == wantedState)
  759.                     return true;
  760.  
  761.                 usleep(WAIT_CHANGES_US);
  762.             }
  763.  
  764.             return false;
  765.         }
  766. #endif
  767.     };
  768.  
  769.  
  770.     ///
  771.     class Encoder : public Component
  772.     {
  773.     public:
  774.         static const ComponentType cType = broadcom::VIDEO_ENCODER;
  775.  
  776.         static const unsigned IPORT = 200;
  777.         static const unsigned OPORT = 201;
  778.  
  779.         Encoder()
  780.         :   Component(cType, (OMX_PTR) this, &cbsEvents)
  781.         {
  782.         }
  783.  
  784.         void setupOutputPortFromCamera(const Parameter<OMX_PARAM_PORTDEFINITIONTYPE>& cameraPortDef, unsigned bitrate, unsigned framerate=0 ) // Framerate 0 means get it from Camera when tunelled
  785.         {
  786.             Parameter<OMX_PARAM_PORTDEFINITIONTYPE> portDef;
  787.             getPortDefinition(OPORT, portDef);
  788.  
  789.             portDef->format.video.nFrameWidth  = cameraPortDef->format.video.nFrameWidth;
  790.             portDef->format.video.nFrameHeight = cameraPortDef->format.video.nFrameHeight;
  791.             portDef->format.video.xFramerate   = cameraPortDef->format.video.xFramerate;
  792.             portDef->format.video.nStride      = cameraPortDef->format.video.nStride;
  793.             portDef->format.video.nBitrate     = bitrate;
  794.        printf("FPS=%x\n",cameraPortDef->format.video.xFramerate);
  795.             if (framerate)
  796.                 portDef->format.video.xFramerate = framerate<<16;
  797.  
  798.             setPortDefinition(OPORT, portDef);
  799.         }
  800.  
  801.     void setupOutputPort(const VideoFromat Videoformat, unsigned bitrate, unsigned framerate = 0)
  802.     {
  803.         // Input Definition
  804.         Parameter<OMX_PARAM_PORTDEFINITIONTYPE> portDefI;
  805.             getPortDefinition(IPORT, portDefI);
  806.         portDefI->format.video.nFrameWidth  = Videoformat.width;
  807.             portDefI->format.video.nFrameHeight = Videoformat.height;
  808.             portDefI->format.video.xFramerate   = framerate<<16;
  809.             portDefI->format.video.nStride      = 0;//(portDefI->format.video.nFrameWidth + portDefI->nBufferAlignment - 1) & (~(portDefI->nBufferAlignment - 1));
  810.     portDefI->format.video.nSliceHeight=0;
  811.         portDefI->format.video.eColorFormat=OMX_COLOR_FormatYUV420PackedPlanar;
  812.      setPortDefinition(IPORT, portDefI);
  813.  
  814.     // Output definition : copy from input
  815.         Parameter<OMX_PARAM_PORTDEFINITIONTYPE> portDef;
  816.         getPortDefinition(OPORT, portDef);
  817.             //portDefI->nPortIndex     = OPORT;
  818.         //portDef->format.video.eColorFormat=OMX_COLOR_FormatUnused;
  819.         portDef->format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
  820.             portDef->format.video.nBitrate=bitrate;
  821.         portDef->format.video.nFrameWidth  = Videoformat.width;
  822.         portDef->format.video.nFrameHeight = Videoformat.height;
  823.         portDef->format.video.xFramerate= framerate<<16;
  824.  
  825.             setPortDefinition(OPORT, portDef);
  826.     }
  827.  
  828.         void setCodec(OMX_VIDEO_CODINGTYPE codec)
  829.         {
  830.             Parameter<OMX_VIDEO_PARAM_PORTFORMATTYPE> format;
  831.             format->nPortIndex = OPORT;
  832.             format->eCompressionFormat = codec;
  833.  
  834.             ERR_OMX( OMX_SetParameter(component_, OMX_IndexParamVideoPortFormat, &format), "set video format");
  835.         }
  836.  
  837.  
  838.     void setProfileLevel(int Profile=OMX_VIDEO_AVCProfileMain,int Level=OMX_VIDEO_AVCLevel32)
  839.         {
  840.         //OMX_VIDEO_AVCProfileBaseline,OMX_VIDEO_AVCProfileMain,OMX_VIDEO_AVCProfileExtended, OMX_VIDEO_AVCProfileHigh
  841.         //OMX_VIDEO_AVCLevel3
  842.             Parameter<OMX_VIDEO_PARAM_PROFILELEVELTYPE> ProfileLevel;
  843.             ProfileLevel->nPortIndex = OPORT;
  844.             ProfileLevel->eProfile = Profile;
  845.             ProfileLevel->eLevel = Level;
  846.  
  847.             ERR_OMX( OMX_SetParameter(component_, OMX_IndexParamVideoProfileLevelCurrent, &ProfileLevel), "set Profile/Level");
  848.         }
  849.  
  850.  
  851.         void setBitrate(OMX_U32 bitrate, OMX_VIDEO_CONTROLRATETYPE type = OMX_Video_ControlRateVariable)
  852.         {
  853.         // https://github.com/raspberrypi/firmware/issues/329#issuecomment-61696016
  854.  
  855.             Parameter<OMX_VIDEO_PARAM_BITRATETYPE> brate;
  856.             brate->nPortIndex = OPORT;
  857.             brate->eControlRate = type;
  858.             brate->nTargetBitrate = bitrate;
  859.  
  860.             ERR_OMX( OMX_SetParameter(component_, OMX_IndexParamVideoBitrate, &brate), "set bitrate");
  861.         }
  862.  
  863.     void setIDR(OMX_U32  idr_period/*, OMX_U32  nPFrames*/)
  864.     {
  865.         Parameter<OMX_VIDEO_CONFIG_AVCINTRAPERIOD> idr_st;
  866.         idr_st->nPortIndex= OPORT;
  867.         idr_st->nIDRPeriod = idr_period;
  868.  
  869.         printf("idr %d p%d\n",idr_st->nIDRPeriod,idr_st->nPFrames);
  870.         //idr_st->nPFrames=nPFrames;
  871.         ERR_OMX( OMX_GetParameter(component_, OMX_IndexConfigVideoAVCIntraPeriod, &idr_st)," Get idr");
  872.         idr_st->nPFrames=idr_period-1;
  873.         idr_st->nIDRPeriod = idr_period;
  874.         ERR_OMX( OMX_SetParameter(component_, OMX_IndexConfigVideoAVCIntraPeriod, &idr_st), "set idr");
  875.  
  876.  
  877.  
  878.  
  879.     }
  880.  
  881.     void setVectorMotion()
  882.     {
  883.         Parameter<OMX_CONFIG_PORTBOOLEANTYPE> motionvector;
  884.         motionvector->nPortIndex= OPORT;
  885.         motionvector->bEnabled=OMX_TRUE;
  886.         ERR_OMX( OMX_SetParameter(component_, OMX_IndexParamBrcmVideoAVCInlineVectorsEnable, &motionvector), "set vector motion");
  887.     }
  888.  
  889.     // Measure Quality of coding
  890.     void setEED()
  891.     {
  892.         Parameter<OMX_VIDEO_EEDE_ENABLE> EED;
  893.         EED->nPortIndex= OPORT;
  894.         EED->enable=OMX_TRUE;
  895.         ERR_OMX( OMX_SetParameter(component_, OMX_IndexParamBrcmEEDEEnable, &EED), "EED");
  896.  
  897.         Parameter<OMX_VIDEO_EEDE_LOSSRATE> EEDRate;
  898.         EEDRate->nPortIndex= OPORT;
  899.         EEDRate->loss_rate= 1; // Set to no packet lost on transmission
  900.         ERR_OMX( OMX_SetParameter(component_, OMX_IndexParamBrcmEEDELossRate, &EEDRate), "EED");
  901.  
  902.     }
  903.  
  904.     void setSEIMessage()
  905.     {
  906.         Parameter<OMX_CONFIG_PORTBOOLEANTYPE> InlineHeader; //SPS/PPS
  907.         InlineHeader->nPortIndex= OPORT;
  908.         InlineHeader->bEnabled=OMX_TRUE;
  909.         ERR_OMX( OMX_SetParameter(component_, OMX_IndexParamBrcmVideoAVCInlineHeaderEnable, &InlineHeader), "InlineHeader");
  910.  
  911.         Parameter<OMX_CONFIG_PORTBOOLEANTYPE> SPSTiming; //SPS Timing Enable
  912.         SPSTiming->nPortIndex= OPORT;
  913.         SPSTiming->bEnabled=OMX_TRUE;
  914.         ERR_OMX( OMX_SetParameter(component_, OMX_IndexParamBrcmVideoAVCSPSTimingEnable, &SPSTiming), "SPS Timing Enable");
  915.  
  916.         Parameter<OMX_CONFIG_PORTBOOLEANTYPE> SEIMessage;
  917.         SEIMessage->nPortIndex= OPORT;
  918.         SEIMessage->bEnabled=OMX_TRUE;
  919.         ERR_OMX( OMX_SetParameter(component_, OMX_IndexParamBrcmVideoAVCSEIEnable, &SEIMessage), "SEIMessage");
  920.  
  921.  
  922.         Parameter<OMX_CONFIG_PORTBOOLEANTYPE> VCLHRD; //HRD ENABLE IN HEADER
  923.         VCLHRD->nPortIndex= OPORT;
  924.         VCLHRD->bEnabled=OMX_TRUE;
  925.         ERR_OMX( OMX_SetParameter(component_, OMX_IndexParamBrcmVideoAVC_VCLHRDEnable, &VCLHRD), "VLCHRD");
  926.  
  927.  
  928.  
  929.  
  930.     }
  931.  
  932.  
  933.     void setLowLatency()
  934.     {
  935.  
  936.  
  937.         Parameter<OMX_CONFIG_PORTBOOLEANTYPE> LowHRD; //HRD Low delay FLAG
  938.         LowHRD->nPortIndex= OPORT;
  939.         LowHRD->bEnabled=OMX_TRUE;
  940.         ERR_OMX( OMX_SetParameter(component_, OMX_IndexParamBrcmVideoAVC_LowDelayHRDEnable, &LowHRD), "HRD Low Delay");
  941.     }
  942.  
  943.     void setSeparateNAL()
  944.     {
  945.         Parameter<OMX_CONFIG_PORTBOOLEANTYPE> SepNAL;
  946.         SepNAL->nPortIndex= OPORT;
  947.         SepNAL->bEnabled=OMX_TRUE;
  948.         ERR_OMX( OMX_SetParameter(component_, OMX_IndexParamBrcmNALSSeparate, &SepNAL), "Separate NAL");
  949.     }
  950.  
  951.     void setMinizeFragmentation()
  952.     {
  953.         Parameter<OMX_CONFIG_PORTBOOLEANTYPE> MinizeFragmentation;
  954.         MinizeFragmentation->nPortIndex= OPORT;
  955.         MinizeFragmentation->bEnabled=OMX_TRUE;
  956.         ERR_OMX( OMX_SetParameter(component_, OMX_IndexConfigMinimiseFragmentation, &MinizeFragmentation), "Minimize Fragmentation");
  957.     }
  958.  
  959.     void setMaxFrameLimits(int FrameLimitInBits)
  960.     {
  961.         // Seems that if above this limit, encoder do not output frame !!
  962.         Parameter<OMX_PARAM_U32TYPE> MaxFrameLimit;
  963.         MaxFrameLimit->nPortIndex= OPORT;
  964.         MaxFrameLimit->nU32=FrameLimitInBits;
  965.         ERR_OMX( OMX_SetParameter(component_, OMX_IndexParamBrcmVideoFrameLimitBits, &MaxFrameLimit), "MaxFrameLimit");
  966.     }
  967.  
  968.     void setPeakRate(int PeakRateinKbit)
  969.     {
  970.         Parameter<OMX_PARAM_U32TYPE> PeakRate;
  971.         PeakRate->nPortIndex= OPORT;
  972.  
  973.         ERR_OMX( OMX_GetParameter(component_, OMX_IndexParamBrcmVideoPeakRate, &PeakRate)," GetPeakRate");
  974.         printf("\nPEAK GET = %d\n",PeakRate->nU32);
  975.         PeakRate->nU32=PeakRateinKbit;
  976.         ERR_OMX( OMX_SetParameter(component_, OMX_IndexParamBrcmVideoPeakRate, &PeakRate), "PeakRateinKbit");
  977.         ERR_OMX( OMX_GetParameter(component_, OMX_IndexParamBrcmVideoPeakRate, &PeakRate)," GetPeakRate");
  978.         printf("\nPEAK GET 2 = %d\n",PeakRate->nU32);
  979.            // Peak video bitrate in bits per second. Must be larger or equal to the average video bitrate. It is ignored if the  video bitrate mode is set to constant bitrate.
  980.  
  981.     }
  982.  
  983.     void setDynamicBitrate(int VideoBitrate)
  984.     {
  985.         Parameter<OMX_VIDEO_CONFIG_BITRATETYPE> DynamicBitrate;
  986.         DynamicBitrate->nPortIndex= OPORT;
  987.         DynamicBitrate->nEncodeBitrate = VideoBitrate;
  988.         ERR_OMX( OMX_SetParameter(component_, OMX_IndexConfigVideoBitrate, &DynamicBitrate), "DynamicVideoBitRate");
  989.  
  990.     }
  991.  
  992. //Set QP restrict QP : means if encoder choose a QP which is not in this range, Frame is dropped
  993.     void setQPLimits(int QMin=0,int QMax=0)
  994.     {
  995.         Parameter<OMX_PARAM_U32TYPE> QPMin;
  996.         QPMin->nPortIndex=OPORT;
  997.         QPMin->nU32=QMin;
  998.         ERR_OMX( OMX_SetParameter(component_,OMX_IndexParamBrcmVideoEncodeMinQuant, &QPMin)," QPMin");
  999.  
  1000.         Parameter<OMX_PARAM_U32TYPE> QPMax;
  1001.         QPMax->nPortIndex=OPORT;
  1002.         QPMax->nU32=QMax;
  1003.         ERR_OMX( OMX_SetParameter(component_,OMX_IndexParamBrcmVideoEncodeMaxQuant, &QPMax)," QPMax");
  1004.  
  1005.     }
  1006.  
  1007.     void setQFromBitrate(int Bitrate,int fps,int Width,int Height,int MotionType=0)
  1008.     {
  1009.         int Coeff=2;
  1010.         //int QPCalculation=10+Width*Height*fps*Coeff/((Bitrate));
  1011.         //For 720*576, 25fps  : QP=280birate⁻(0,345)
  1012.         int QPCalculation=281*pow(Bitrate*(25/fps)*(720/Width)*(576/Height)/1000.0,-0.345)+10;
  1013.         printf("QP=%d\n",QPCalculation);
  1014.         if(QPCalculation>48) QPCalculation=48; //Fixme
  1015.         if(QPCalculation<10) QPCalculation=10; //Fixme
  1016.  
  1017.         setQPLimits(QPCalculation,QPCalculation);
  1018.     }
  1019.  
  1020. // ONLY IF RATECONTROL is not CBR/VBR
  1021.  void setQP(int QPi,int QPp)
  1022. {
  1023.     Parameter<OMX_VIDEO_PARAM_QUANTIZATIONTYPE> QP;
  1024.     QP->nPortIndex=OPORT;
  1025.     QP->nQpI=QPi;
  1026.     QP->nQpP=QPp;
  1027.     QP->nQpB=0; // No B Frame, only zero is allowed
  1028.  
  1029.     ERR_OMX( OMX_SetParameter(component_,OMX_IndexParamBrcmVideoEncodeQpP, &QP)," QP");
  1030.  
  1031.  
  1032. }
  1033.     void setMultiSlice(int SliceSize)
  1034.     {
  1035.  
  1036.         Parameter<OMX_VIDEO_PARAM_INTRAREFRESHTYPE> IntraRefreshType;
  1037.         IntraRefreshType->nPortIndex=OPORT;
  1038.         ERR_OMX( OMX_GetParameter(component_,  OMX_IndexParamVideoIntraRefresh, &IntraRefreshType)," IntraRefreshMode");
  1039.         IntraRefreshType->eRefreshMode=OMX_VIDEO_IntraRefreshCyclicMrows;
  1040.  
  1041.         IntraRefreshType->nCirMBs=SliceSize;
  1042.         ERR_OMX( OMX_SetParameter(component_,  OMX_IndexParamVideoIntraRefresh, &IntraRefreshType)," IntraRefreshMode");
  1043.  
  1044.  
  1045.     }
  1046.  
  1047.     void getEncoderStat(int Flags)
  1048.     {
  1049.         char debug[255];
  1050.         sprintf(debug,"");
  1051.         if(Flags&OMX_BUFFERFLAG_ENDOFFRAME) strcat(debug,"ENDOFFRAME ");
  1052.         if(Flags&OMX_BUFFERFLAG_SYNCFRAME) strcat(debug,"SYNCFRAME ");
  1053.         if(Flags&OMX_BUFFERFLAG_CODECCONFIG) strcat(debug,"CODECCONFIG ");
  1054.         if(Flags&OMX_BUFFERFLAG_ENDOFNAL) strcat(debug,"ENDOFNAL ");
  1055.  
  1056.  
  1057.         static struct timespec tbefore;
  1058.         static int Count=0;
  1059.     Parameter<OMX_CONFIG_BRCMPORTSTATSTYPE> VideoStat;
  1060.         VideoStat->nPortIndex= OPORT;
  1061.         ERR_OMX( OMX_GetParameter(component_, OMX_IndexConfigBrcmPortStats, &VideoStat)," Get VideoStat");
  1062.         struct timespec t;
  1063.          clock_gettime(CLOCK_REALTIME, &t);
  1064.         printf("VideoStat : %s ByteCount %d Buffer %d - Frame %d = %d Skip %d Discard %d Max Delta%d:%d TIME %li\n",/*VideoStat->nByteCount.nLowPart*8*25/VideoStat->nFrameCount,*/debug,VideoStat->nByteCount.nLowPart,VideoStat->nBufferCount,VideoStat->nFrameCount,VideoStat->nBufferCount-VideoStat->nFrameCount*2,VideoStat->nFrameSkips,VideoStat->nDiscards,VideoStat->nMaxTimeDelta.nHighPart,VideoStat->nMaxTimeDelta.nLowPart,( t.tv_sec -tbefore.tv_sec  )*1000ul + ( t.tv_nsec - tbefore.tv_nsec)/1000000);
  1065.     tbefore=t;
  1066.     Count++;
  1067.     }
  1068.  
  1069.         void allocBuffers(bool WithBuffIn=false)
  1070.         {
  1071.         Component::allocBuffers(OPORT, bufferOut_);
  1072.         HaveABufferIn=WithBuffIn;
  1073.             if(HaveABufferIn)
  1074.         {
  1075.  
  1076.             Component::allocBuffers(IPORT, bufferIn_);
  1077.         }
  1078.  
  1079.         }
  1080.  
  1081.         void freeBuffers()
  1082.         {
  1083.             Component::freeBuffers(OPORT, bufferOut_);
  1084.         if(HaveABufferIn)
  1085.         Component::freeBuffers(IPORT, bufferIn_);
  1086.         }
  1087.  
  1088.         void callFillThisBuffer()
  1089.         {
  1090.             Component::callFillThisBuffer(bufferOut_);
  1091.         }
  1092.  
  1093.     void callEmptyThisBuffer()
  1094.         {
  1095.             Component::callEmptyThisBuffer(bufferIn_);
  1096.         }
  1097.  
  1098.         Buffer& outBuffer() { return bufferOut_; }
  1099.     Buffer& inBuffer() { return bufferIn_; }
  1100.     private:
  1101.         Parameter<OMX_PARAM_PORTDEFINITIONTYPE> encoderPortDef_;
  1102.         Buffer bufferOut_;
  1103.     Buffer bufferIn_;
  1104.     bool HaveABufferIn=false;
  1105.     };
  1106.  
  1107.  
  1108.  
  1109.  
  1110. class VideoSplitter : public Component
  1111.     {
  1112.     public:
  1113.         static const ComponentType cType = broadcom::VIDEO_SPLITTER;
  1114.  
  1115.         static const unsigned IPORT = 250;
  1116.         static const unsigned OPORT_1 = 251;
  1117.         static const unsigned OPORT_2 = 252;
  1118.         static const unsigned OPORT_3 = 253;
  1119.         static const unsigned OPORT_4 = 254;
  1120.  
  1121.         VideoSplitter()
  1122.         :   Component(cType, (OMX_PTR) this, &cbsEvents)
  1123.         {
  1124.         }
  1125.         void setupOutputPort(int SrcImageWidth,int SrcImageHeight,const VideoFromat Videoformat,OMX_COLOR_FORMATTYPE colortype)
  1126.         {
  1127.     Parameter<OMX_PARAM_PORTDEFINITIONTYPE> portDefI;
  1128.             getPortDefinition(IPORT, portDefI);
  1129.  
  1130.         portDefI->format.video.nFrameWidth  = SrcImageWidth;
  1131.             portDefI->format.video.nFrameHeight = SrcImageHeight;
  1132.             portDefI->format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
  1133.     if(colortype==OMX_COLOR_FormatYUV420PackedPlanar)
  1134.     {
  1135.  
  1136.         portDefI->format.video.nStride      = 0;
  1137.         portDefI->format.video.nSliceHeight=SrcImageHeight;
  1138.         printf("%d * %d\n",portDefI->format.video.nStride,portDefI->format.video.nSliceHeight);
  1139.     }
  1140.     else
  1141.     {           portDefI->format.video.nStride      =0 ;
  1142.         portDefI->format.video.nSliceHeight=0;
  1143.     }
  1144.  
  1145.     portDefI->format.video.eColorFormat=colortype;
  1146.  
  1147.      setPortDefinition(IPORT, portDefI);
  1148.  
  1149. // Output definition
  1150.  
  1151.         }
  1152.  
  1153.         void allocBuffers()
  1154.         {
  1155.  
  1156.  
  1157.             Component::allocBuffers(IPORT, bufferIn_);
  1158.  
  1159.         }
  1160.  
  1161.          void freeBuffers()
  1162.         {
  1163.  
  1164.         Component::freeBuffers(IPORT, bufferIn_);
  1165.         }
  1166.  
  1167.         void callEmptyThisBuffer()
  1168.         {
  1169.             Component::callEmptyThisBuffer(bufferIn_);
  1170.         }
  1171.  
  1172.  
  1173.  
  1174.         Buffer& inBuffer() { return bufferIn_; }
  1175.  
  1176.         private:
  1177.  
  1178.         Buffer bufferIn_;
  1179.     };
  1180.  
  1181.  
  1182.  
  1183.  
  1184.     //
  1185.  
  1186.     static OMX_ERRORTYPE callback_EventHandler(
  1187.             OMX_HANDLETYPE hComponent,
  1188.             OMX_PTR pAppData,
  1189.             OMX_EVENTTYPE eEvent,
  1190.             OMX_U32 nData1,
  1191.             OMX_U32 nData2,
  1192.             OMX_PTR pEventData)
  1193.     {
  1194.         Component * component = static_cast<Component *>(pAppData);
  1195.  
  1196.         printEvent(component->name(), hComponent, eEvent, nData1, nData2);
  1197.  
  1198.         switch (eEvent)
  1199.         {
  1200.             case OMX_EventCmdComplete:
  1201.             {
  1202.                 switch (nData1)
  1203.                 {
  1204.                     case OMX_CommandFlush:
  1205.                     case OMX_CommandPortDisable:
  1206.                     case OMX_CommandPortEnable:
  1207.                     case OMX_CommandMarkBuffer:
  1208.                         // nData2 is port index
  1209.                         component->eventCmdComplete(nData1, nData2);
  1210.                         break;
  1211.  
  1212.                     case OMX_CommandStateSet:
  1213.                         // nData2 is state
  1214.                         component->eventCmdComplete(nData1, nData2);
  1215.                         break;
  1216.  
  1217.                     default:
  1218.                         break;
  1219.                 }
  1220.  
  1221.                 break;
  1222.             }
  1223.  
  1224.             case OMX_EventPortSettingsChanged:
  1225.             {
  1226.                 // nData1 is port index
  1227.                 component->eventPortSettingsChanged(nData1);
  1228.                 break;
  1229.             }
  1230.  
  1231.             // vendor specific
  1232.             case OMX_EventParamOrConfigChanged:
  1233.             {
  1234.                 if (nData2 == OMX_IndexParamCameraDeviceNumber)
  1235.                 {
  1236.  
  1237.                 }
  1238.  
  1239.                 break;
  1240.             }
  1241.  
  1242.             case OMX_EventError:
  1243.                 OMXExeption::die( (OMX_ERRORTYPE) nData1, "OMX_EventError received");
  1244.                 break;
  1245.  
  1246.             case OMX_EventMark:
  1247.             case OMX_EventResourcesAcquired:
  1248.             case OMX_EventBufferFlag:
  1249.             default:
  1250.                 break;
  1251.         }
  1252.  
  1253.         return OMX_ErrorNone;
  1254.     }
  1255.  
  1256.     static OMX_ERRORTYPE callback_EmptyBufferDone(OMX_HANDLETYPE, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE * pBuffer)
  1257.     {
  1258.     Component * component = static_cast<Component *>(pAppData);
  1259.  
  1260.         if (component->type() == Encoder::cType)
  1261.         {
  1262.         //printf("Filled %d Timestamp %li\n",pBuffer->nFilledLen,pBuffer->nTickCount);
  1263.             Encoder * encoderHigh = static_cast<Encoder *>(pAppData);
  1264.             encoderHigh->inBuffer().setFilled();
  1265.               Encoder * encoderLow = static_cast<Encoder *>(pAppData);
  1266.             encoderLow->inBuffer().setFilled();
  1267.         }
  1268.     if (component->type() == VideoSplitter::cType)
  1269.         {
  1270.  
  1271.             VideoSplitter * vsplitter = static_cast<VideoSplitter *>(pAppData);
  1272.             vsplitter->inBuffer().setFilled();
  1273.         }
  1274.  
  1275.  
  1276.         return OMX_ErrorNone;
  1277.     }
  1278.  
  1279.     static OMX_ERRORTYPE callback_FillBufferDone(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE * pBuffer)
  1280.     {
  1281.         Component * component = static_cast<Component *>(pAppData);
  1282.  
  1283.         if (component->type() == Encoder::cType)
  1284.         {
  1285.         printf("Filled %d Timestamp %li\n",pBuffer->nFilledLen,pBuffer->nTickCount);
  1286.             Encoder * encoderHigh = static_cast<Encoder *>(pAppData);
  1287.             encoderHigh->outBuffer().setFilled();
  1288.             Encoder * encoderLow = static_cast<Encoder *>(pAppData);
  1289.             encoderLow->outBuffer().setFilled();
  1290.         }
  1291.  
  1292.         return OMX_ErrorNone;
  1293.     }
  1294. }
  1295.  
  1296.  
  1297. // Global variable used by the signal handler and capture/encoding loop
  1298. static int want_quit = 0;
  1299.  
  1300. #if 1
  1301. // Global signal handler for trapping SIGINT, SIGTERM, and SIGQUIT
  1302. static void signal_handler(int signal)
  1303. {
  1304.     want_quit = 1;
  1305. }
  1306. #endif
  1307.  
  1308.  
  1309. using namespace rpi_omx;
  1310. static const unsigned VIDEO_BITRATE_HIGH = 800000;
  1311. static const unsigned VIDEO_BITRATE_LOW = 400000;
  1312. static const unsigned VIDEO_BITRATE_MEDIUM = 100000;
  1313.  
  1314.  
  1315. class PictureTots
  1316. {
  1317. private:
  1318.  
  1319.  
  1320.      Encoder encoder;
  1321.     VideoSplitter vsplitter;
  1322.     Encoder encoderHigh;
  1323.     Encoder encoderLow;
  1324.     Encoder encoderMedium;
  1325.     //ImageEncode colorconverter;
  1326.     int EncVideoBitrate;
  1327.     bool FirstTime=true;
  1328.     uint key_frame=0;  //key frame is set to 0. if there is 1 then segmentation fault occurs
  1329.     VideoFromat CurrentVideoFormat;
  1330.     int Videofps;
  1331.     struct timespec last_time;
  1332.     int Mode=Mode_V4L2;
  1333.     Webcam *pwebcam;
  1334.     MuxTs mux;
  1335.  
  1336.     FILE * outHigh = fopen("x.h264", "w+");
  1337.     FILE *outLow = fopen("y.h264" , "w+");
  1338.     FILE *outMedium = fopen("z.h264" , "w+");
  1339.  
  1340.     struct timespec InitTime;
  1341.  
  1342.  
  1343. public:
  1344. static const int Mode_PATTERN=0;
  1345. static const int Mode_V4L2=1;
  1346.  
  1347. public:
  1348.     void Init(VideoFromat &VideoFormat,char *FileName,int VideoBitrate,int fps=0,int IDRPeriod=100,int ModeInput=Mode_V4L2,char *Extra=NULL)
  1349.     {
  1350. Parameter<OMX_PARAM_PORTDEFINITIONTYPE> portDef;
  1351.         CurrentVideoFormat=VideoFormat;
  1352.         Videofps=fps;
  1353.         EncVideoBitrate=VideoBitrate;
  1354.         Mode=ModeInput;
  1355.  
  1356.         if(Mode==Mode_V4L2)
  1357.         {
  1358.             pwebcam=new Webcam(Extra);
  1359.             int CamWidth,CamHeight;
  1360.             pwebcam->GetCameraSize(CamWidth,CamHeight);
  1361.             printf("Video Splitter input = %d x %d\n",CamWidth,CamHeight);
  1362.  
  1363.             vsplitter.setupOutputPort(CamWidth,CamHeight,VideoFormat,OMX_COLOR_FormatYUV420PackedPlanar);
  1364.  
  1365.         }
  1366.         if(Mode==Mode_PATTERN)
  1367.         {
  1368.          vsplitter.setupOutputPort(VideoFormat.width,VideoFormat.height,VideoFormat,OMX_COLOR_FormatYUV420PackedPlanar);
  1369.  
  1370.         }
  1371.  
  1372.  
  1373.  
  1374.             // configuring encoders
  1375.  
  1376.  
  1377.  
  1378.          encoderHigh.setupOutputPort(VideoFormat,VIDEO_BITRATE_HIGH,fps);
  1379.             //OMX_Video_ControlRateDisable seems not supported !!!
  1380.              encoderHigh.setCodec(OMX_VIDEO_CodingAVC);
  1381.             encoderHigh.setBitrate(VIDEO_BITRATE_HIGH,OMX_Video_ControlRateVariable/*OMX_Video_ControlRateConstant*/);
  1382.  
  1383.             encoderHigh.setIDR(IDRPeriod);
  1384.             encoderHigh.setSEIMessage();
  1385.  
  1386.         encoderHigh.setQFromBitrate(VideoBitrate,Videofps,CurrentVideoFormat.width,CurrentVideoFormat.height);
  1387.         encoderHigh.setQPLimits(0,0);
  1388.             encoderHigh.setQP(0,0);
  1389.  
  1390.  
  1391.             encoderHigh.setLowLatency();
  1392.             encoderHigh.setSeparateNAL();
  1393.  
  1394.                 encoderHigh.setMinizeFragmentation();
  1395.             encoderHigh.setEED();
  1396.  
  1397.            //Low bitrate
  1398.  
  1399.            encoderLow.setupOutputPort(VideoFormat,VIDEO_BITRATE_LOW,fps);
  1400.             //OMX_Video_ControlRateDisable seems not supported !!!
  1401.              encoderLow.setCodec(OMX_VIDEO_CodingAVC);
  1402.             encoderLow.setBitrate(VIDEO_BITRATE_LOW,OMX_Video_ControlRateVariable/*OMX_Video_ControlRateConstant*/);
  1403.  
  1404.             encoderLow.setIDR(IDRPeriod);
  1405.             encoderLow.setSEIMessage();
  1406.  
  1407.             encoderLow.setQFromBitrate(VideoBitrate,Videofps,CurrentVideoFormat.width,CurrentVideoFormat.height);
  1408.                 encoderLow.setQPLimits(0,0);
  1409.             encoderLow.setQP(0,0);
  1410.  
  1411.             encoderLow.setLowLatency();
  1412.             encoderLow.setSeparateNAL();
  1413.  
  1414.                 encoderLow.setMinizeFragmentation();
  1415.             encoderLow.setEED();
  1416.  
  1417.  
  1418.                     encoderMedium.setupOutputPort(VideoFormat,VIDEO_BITRATE_MEDIUM,fps);
  1419.             //OMX_Video_ControlRateDisable seems not supported !!!
  1420.              encoderMedium.setCodec(OMX_VIDEO_CodingAVC);
  1421.             encoderMedium.setBitrate(VIDEO_BITRATE_MEDIUM,OMX_Video_ControlRateVariable/*OMX_Video_ControlRateConstant*/);
  1422.  
  1423.             encoderMedium.setIDR(IDRPeriod);
  1424.             encoderMedium.setSEIMessage();
  1425.             encoderMedium.setQFromBitrate(VideoBitrate,Videofps,CurrentVideoFormat.width,CurrentVideoFormat.height);
  1426.             encoderMedium.setQPLimits(0,0);
  1427.             encoderMedium.setQP(0,0);
  1428.             encoderMedium.setLowLatency();
  1429.             encoderMedium.setSeparateNAL();
  1430.  
  1431.                 encoderMedium.setMinizeFragmentation();
  1432.             encoderMedium.setEED();
  1433.  
  1434.  
  1435.             // With Main Profile : have more skipped frame
  1436.  
  1437.  
  1438.           ERR_OMX( OMX_SetupTunnel(vsplitter.component(), VideoSplitter::OPORT_1, encoderHigh.component(), Encoder::IPORT),
  1439.                 "tunnel splitter.output -> encoder.input (high)");
  1440.  
  1441.           ERR_OMX( OMX_SetupTunnel(vsplitter.component(), VideoSplitter::OPORT_2, encoderLow.component(), Encoder::IPORT),
  1442.                 "tunnel splitter.output -> encoder.input (low)");
  1443.  
  1444.           ERR_OMX( OMX_SetupTunnel(vsplitter.component(), VideoSplitter::OPORT_3, encoderMedium.component(), Encoder::IPORT),
  1445.                 "tunnel splitter.output -> encoder.input (Medium)");
  1446.  
  1447.  
  1448.             vsplitter.dumpPort(VideoSplitter::IPORT, OMX_FALSE);
  1449.             vsplitter.dumpPort(VideoSplitter::OPORT_1, OMX_FALSE);
  1450.             vsplitter.dumpPort(VideoSplitter::OPORT_2, OMX_FALSE);
  1451.             vsplitter.dumpPort(VideoSplitter::OPORT_3, OMX_FALSE);
  1452.  
  1453.  
  1454.  
  1455.             encoderHigh.dumpPort(Encoder::IPORT, OMX_FALSE);
  1456.             encoderHigh.dumpPort(Encoder::OPORT, OMX_FALSE);
  1457.  
  1458.             encoderLow.dumpPort(Encoder::IPORT, OMX_FALSE);
  1459.             encoderLow.dumpPort(Encoder::OPORT, OMX_FALSE);
  1460.  
  1461.               encoderMedium.dumpPort(Encoder::IPORT, OMX_FALSE);
  1462.             encoderMedium.dumpPort(Encoder::OPORT, OMX_FALSE);
  1463.  
  1464.  
  1465.         // switch components to idle state
  1466.         {
  1467.  
  1468.          vsplitter.switchState(OMX_StateIdle);
  1469.               encoderHigh.switchState(OMX_StateIdle);
  1470.               encoderLow.switchState(OMX_StateIdle);
  1471.               encoderMedium.switchState(OMX_StateIdle);
  1472.  
  1473.  
  1474.         }
  1475.  
  1476.         // enable ports
  1477.         {
  1478.              vsplitter.enablePort(VideoSplitter::IPORT);
  1479.             vsplitter.enablePort(VideoSplitter::OPORT_1);
  1480.             vsplitter.enablePort(VideoSplitter::OPORT_2);
  1481.             vsplitter.enablePort(VideoSplitter::OPORT_3);
  1482.             encoderHigh.enablePort();
  1483.             encoderLow.enablePort();
  1484.             encoderMedium.enablePort();
  1485.         }
  1486.  
  1487.  
  1488.         // allocate buffers
  1489.         vsplitter.allocBuffers();
  1490.           encoderHigh.allocBuffers();
  1491.           encoderLow.allocBuffers();
  1492.           encoderMedium.allocBuffers();
  1493.  
  1494.             if(Mode==Mode_V4L2)
  1495.             {
  1496.                  pwebcam->SetOmxBuffer((unsigned char*)vsplitter.inBuffer().data());
  1497.  
  1498.             }
  1499.  
  1500.  
  1501.  
  1502.  
  1503.         // switch state of the components prior to starting
  1504.         {
  1505.             vsplitter.switchState(OMX_StateExecuting);
  1506.             encoderHigh.switchState(OMX_StateExecuting);
  1507.             encoderLow.switchState(OMX_StateExecuting);
  1508.             encoderMedium.switchState(OMX_StateExecuting);
  1509.         }
  1510.  
  1511.  
  1512.  
  1513.     }
  1514.  
  1515.  
  1516.  
  1517.  
  1518.  
  1519.  
  1520. void Run(bool want_quit)
  1521.     {
  1522.         Buffer& encBufferHigh = encoderHigh.outBuffer();
  1523.         Buffer& encBufferLow = encoderLow.outBuffer();
  1524.         Buffer& encBufferMedium = encoderMedium.outBuffer();
  1525.         Buffer& PictureBuffer = vsplitter.inBuffer();
  1526.  
  1527.         if(!want_quit&&(FirstTime||PictureBuffer.filled()))
  1528.         {
  1529.  
  1530.             OMX_U32 filledLen;
  1531.             if(Mode==Mode_PATTERN)
  1532.             {
  1533.  
  1534.             }
  1535.             if(Mode==Mode_V4L2)
  1536.             {
  1537.  
  1538.                 auto frame = pwebcam->frame(2);
  1539.  
  1540.                 filledLen=frame.size;
  1541.  
  1542.  
  1543.             }
  1544.  
  1545.             PictureBuffer.setDatasize(filledLen);
  1546.             PictureBuffer.setFilled(false);
  1547.             vsplitter.callEmptyThisBuffer();
  1548.  
  1549.  
  1550.             if(FirstTime)
  1551.             {
  1552.                 clock_gettime(CLOCK_REALTIME, &InitTime);
  1553.                 FirstTime=false;
  1554.                 encoderHigh.callFillThisBuffer();
  1555.                 encoderLow.callFillThisBuffer();
  1556.                 encoderMedium.callFillThisBuffer();
  1557.  
  1558.  
  1559.             }
  1560.  
  1561.         }
  1562.  
  1563.             MuxTs m;
  1564.     std::cout<<m.CreateFile("test.ts");
  1565.     m.AddNewProgram(0x1000, 0x01);
  1566.     m.AddNewStream(0x301,MUXTS_CODEC_H264);
  1567.     m.AddNewStream(0x401,MUXTS_CODEC_H264);
  1568.     m.AddNewStream(0x501,MUXTS_CODEC_H264);
  1569.         if (!want_quit&&(encBufferHigh.filled() && encBufferLow.filled() && encBufferMedium.filled()))
  1570.          {
  1571.                // for checking how much frames and bytes encoder is giving
  1572.                     //encoderHigh.getEncoderStat(encBufferHigh.flags());
  1573.                     //encoderLow.getEncoderStat(encBufferLow.flags());
  1574.                     //encoderMedium.getEncoderStat(encBufferMedium.flags());
  1575.  
  1576.  
  1577.                 encoderHigh.setDynamicBitrate(EncVideoBitrate);
  1578.                 /*if(key_frame%250==0)
  1579.                 {
  1580.                     QP--;
  1581.                     encoder.setQPLimits(QP,QP);
  1582.                     printf("------ QP =%d\n",QP);
  1583.                 }*/
  1584.  
  1585.                 if(encBufferHigh.flags() & OMX_BUFFERFLAG_CODECSIDEINFO)
  1586.                 {
  1587.                     printf("CODEC CONFIG>\n");
  1588.                     int LenVector=encBufferHigh.dataSize();
  1589.  
  1590.                     for(int j=0;j<CurrentVideoFormat.height/16;j++)
  1591.                     {
  1592.                         for(int i=0;i<CurrentVideoFormat.width/16;i++)
  1593.                         {
  1594.                             int Motionx=encBufferHigh.data()[(CurrentVideoFormat.width/16*j+i)*4];
  1595.                             int Motiony=encBufferHigh.data()[(CurrentVideoFormat.width/16*j+i)*4+1];
  1596.                             int MotionAmplitude=sqrt((double)((Motionx * Motionx) + (Motiony * Motiony)));
  1597.                             printf("%d ",MotionAmplitude);
  1598.                         }
  1599.                         printf("\n");
  1600.                     }
  1601.                     encBufferHigh.setFilled(false);
  1602.                     encoderHigh.callFillThisBuffer();
  1603.                     return;
  1604.                 }
  1605.  
  1606.  
  1607.  
  1608.     m.WriteFrame(encBufferHigh.data(),encBufferHigh.dataSize(),3600,MUXTS_CODEC_H264);
  1609.  
  1610.  
  1611.  
  1612.  
  1613.         // for low data rate saving to file
  1614.  
  1615.                                 if(encBufferLow.flags() & OMX_BUFFERFLAG_CODECSIDEINFO)
  1616.                 {
  1617.                     printf("CODEC CONFIG>\n");
  1618.                     int LenVector=encBufferLow.dataSize();
  1619.  
  1620.                     for(int j=0;j<CurrentVideoFormat.height/16;j++)
  1621.                     {
  1622.                         for(int i=0;i<CurrentVideoFormat.width/16;i++)
  1623.                         {
  1624.                             int Motionx=encBufferLow.data()[(CurrentVideoFormat.width/16*j+i)*4];
  1625.                             int Motiony=encBufferLow.data()[(CurrentVideoFormat.width/16*j+i)*4+1];
  1626.                             int MotionAmplitude=sqrt((double)((Motionx * Motionx) + (Motiony * Motiony)));
  1627.                             printf("%d ",MotionAmplitude);
  1628.                         }
  1629.                         printf("\n");
  1630.                     }
  1631.                     encBufferLow.setFilled(false);
  1632.                     encoderLow.callFillThisBuffer();
  1633.                     return;
  1634.                 }
  1635.  
  1636.  
  1637.  
  1638.  
  1639.  
  1640.             m.WriteFrame(encBufferLow.data(),encBufferLow.dataSize(),3601,MUXTS_CODEC_H264);
  1641.  
  1642.     // For 3rd bit rate
  1643.  
  1644.             if(encBufferMedium.flags() & OMX_BUFFERFLAG_CODECSIDEINFO)
  1645.                 {
  1646.  
  1647.                     printf("CODEC CONFIG>\n");
  1648.                     int LenVector=encBufferMedium.dataSize();
  1649.  
  1650.                     for(int j=0;j<CurrentVideoFormat.height/16;j++)
  1651.                     {
  1652.                         for(int i=0;i<CurrentVideoFormat.width/16;i++)
  1653.                         {
  1654.                             int Motionx=encBufferMedium.data()[(CurrentVideoFormat.width/16*j+i)*4];
  1655.                             int Motiony=encBufferMedium.data()[(CurrentVideoFormat.width/16*j+i)*4+1];
  1656.                             int MotionAmplitude=sqrt((double)((Motionx * Motionx) + (Motiony * Motiony)));
  1657.                             printf("%d ",MotionAmplitude);
  1658.                         }
  1659.                         printf("\n");
  1660.                     }
  1661.                     encBufferMedium.setFilled(false);
  1662.                     encoderMedium.callFillThisBuffer();
  1663.                     return;
  1664.                 }
  1665.  
  1666.  
  1667.  
  1668.     m.WriteFrame(encBufferMedium.data(),encBufferMedium.dataSize(),3603,MUXTS_CODEC_H264);
  1669.  
  1670.  
  1671.                 // Buffer flushed, request a new buffer to be filled by the encoder component
  1672.                 encBufferHigh.setFilled(false);
  1673.                 encBufferLow.setFilled(false);
  1674.                 encBufferMedium.setFilled(false);
  1675.  
  1676.                 //PictureBuffer.setFilled(true);
  1677.                 encoderHigh.callFillThisBuffer();
  1678.                 encoderLow.callFillThisBuffer();
  1679.                 encoderMedium.callFillThisBuffer();
  1680.  
  1681.              m.CloseFile();
  1682.  
  1683.           }
  1684.  
  1685.  
  1686.         else usleep(1000);
  1687.  
  1688.     }
  1689.  
  1690.  
  1691.     void Terminate()
  1692.     {
  1693.  
  1694.         if(Mode==Mode_V4L2)
  1695.         {
  1696.             free(pwebcam);
  1697.         }
  1698.          encoderHigh.outBuffer().flags() &= OMX_BUFFERFLAG_EOS;
  1699.           encoderLow.outBuffer().flags() &= OMX_BUFFERFLAG_EOS;
  1700.           encoderMedium.outBuffer().flags() &= OMX_BUFFERFLAG_EOS;
  1701.  
  1702.  
  1703.         // flush the buffers on each component
  1704.         {
  1705.            vsplitter.flushPort();
  1706.             encoderHigh.flushPort();
  1707.             encoderLow.flushPort();
  1708.             encoderMedium.flushPort();
  1709.         }
  1710.  
  1711.         // disable all the ports
  1712.         {
  1713.           vsplitter.disablePort();
  1714.             encoderHigh.disablePort();
  1715.             encoderLow.disablePort();
  1716.             encoderMedium.disablePort();
  1717.         }
  1718.  
  1719.         // free all the buffers
  1720.         {
  1721.           vsplitter.freeBuffers();
  1722.             encoderHigh.freeBuffers();
  1723.             encoderLow.freeBuffers();
  1724.             encoderMedium.freeBuffers();
  1725.         }
  1726.  
  1727.         // transition all the components to idle states
  1728.         {
  1729.            vsplitter.switchState(OMX_StateIdle);
  1730.             encoderHigh.switchState(OMX_StateIdle);
  1731.             encoderLow.switchState(OMX_StateIdle);
  1732.             encoderMedium.switchState(OMX_StateIdle);
  1733.         }
  1734.  
  1735.         // transition all the components to loaded states
  1736.         {
  1737.           vsplitter.switchState(OMX_StateLoaded);
  1738.             encoderHigh.switchState(OMX_StateLoaded);
  1739.             encoderLow.switchState(OMX_StateLoaded);
  1740.             encoderMedium.switchState(OMX_StateLoaded);
  1741.         }
  1742.     }
  1743.  
  1744. };
  1745.  
  1746.  
  1747.  
  1748. int main(int argc, char **argv)
  1749. {
  1750.  
  1751.  
  1752.     char *OutputFileName="out.ts";
  1753.     int VideoBitrate=300000;
  1754.     int VideoWidth=352;
  1755.     int VideoHeight=288;
  1756.     int VideoFramerate=30;
  1757.     int IDRPeriod=100;
  1758.     char *ExtraArg=NULL;
  1759.     #define CAMERA 0
  1760.     #define PATTERN 1
  1761.     #define USB_CAMERA 2
  1762.     int TypeInput=USB_CAMERA;
  1763.  
  1764.  VideoFromat CurrentVideoFormat;
  1765. CurrentVideoFormat.width=VideoWidth;
  1766. CurrentVideoFormat.height=VideoHeight;
  1767. CurrentVideoFormat.framerate=VideoFramerate;
  1768. CurrentVideoFormat.ratio=VideoFromat::RATIO_16x9;
  1769. CurrentVideoFormat.fov=false; // To check
  1770.  
  1771.  
  1772.  
  1773. bcm_host_init();
  1774.     try
  1775.     {
  1776.         OMXInit omx;
  1777.         VcosSemaphore sem("common semaphore");
  1778.         pSemaphore = &sem;
  1779.  
  1780.     PictureTots *picturetots;
  1781. if(TypeInput==0)
  1782. {
  1783.  
  1784. }
  1785. else
  1786. {
  1787.     int PictureMode=PictureTots::Mode_PATTERN;
  1788.     switch(TypeInput)
  1789.     {
  1790.     case PATTERN:PictureMode=PictureTots::Mode_PATTERN;break;
  1791.     case USB_CAMERA:PictureMode=PictureTots::Mode_V4L2;
  1792.     if(ExtraArg==NULL) ExtraArg="/dev/video0";break;
  1793.  
  1794.  
  1795.     }
  1796.     picturetots = new PictureTots;
  1797.     picturetots->Init(CurrentVideoFormat,OutputFileName,VideoBitrate,VideoFramerate,IDRPeriod,PictureMode,ExtraArg);
  1798.  
  1799. }
  1800. #if 1
  1801.         signal(SIGINT,  signal_handler);
  1802.         signal(SIGTERM, signal_handler);
  1803.         signal(SIGQUIT, signal_handler);
  1804.         signal(SIGKILL, signal_handler);
  1805.  
  1806. #endif
  1807.  
  1808.  
  1809.  
  1810.         std::cerr << "Enter capture and encode loop, press Ctrl-C to quit..." << std::endl;
  1811.  
  1812.         unsigned highCount = 0;
  1813.         unsigned lowCount = 0;
  1814.         unsigned MediumCount = 0;
  1815.  
  1816.  
  1817.  
  1818.  
  1819.         while (1)
  1820.         {
  1821.  
  1822.        if(TypeInput==2)
  1823.  
  1824.              picturetots->Run(want_quit);
  1825.  
  1826.             ++highCount;
  1827.             ++lowCount;
  1828.  
  1829.             ++MediumCount;
  1830.  
  1831.  
  1832.                 if (want_quit /*&& (encBufferLow.flags() & OMX_BUFFERFLAG_SYNCFRAME)*/)
  1833.                 {
  1834.                     std::cerr << "Clean Exiting " << std::endl;
  1835.                     break;
  1836.                 }
  1837.  
  1838.  
  1839.         }
  1840.  
  1841.         std::cerr << "high: " << highCount << " low: " << lowCount << "Medium"<< MediumCount << std::endl;
  1842.  
  1843. #if 1
  1844.         // Restore signal handlers
  1845.         signal(SIGINT,  SIG_DFL);
  1846.         signal(SIGTERM, SIG_DFL);
  1847.         signal(SIGQUIT, SIG_DFL);
  1848.     signal(SIGKILL, SIG_DFL);
  1849. #endif
  1850.     if(TypeInput==0)
  1851.     {
  1852.  
  1853.     }
  1854.     else
  1855.     {
  1856.             picturetots->Terminate();
  1857.         delete(picturetots);
  1858.     }
  1859.  
  1860.  
  1861.     }
  1862.     catch (const OMXExeption& e)
  1863.     {
  1864.         OMXExeption::die(e.code(), e.what());
  1865.     }
  1866.     catch (const char * msg)
  1867.     {
  1868.         std::cerr << msg;
  1869.         return 1;
  1870.     }
  1871.  
  1872.     return 0;
  1873. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement