Recherche avancée

Médias (16)

Mot : - Tags -/mp3

Autres articles (77)

  • Gestion générale des documents

    13 mai 2011, par

    MédiaSPIP ne modifie jamais le document original mis en ligne.
    Pour chaque document mis en ligne il effectue deux opérations successives : la création d’une version supplémentaire qui peut être facilement consultée en ligne tout en laissant l’original téléchargeable dans le cas où le document original ne peut être lu dans un navigateur Internet ; la récupération des métadonnées du document original pour illustrer textuellement le fichier ;
    Les tableaux ci-dessous expliquent ce que peut faire MédiaSPIP (...)

  • Le profil des utilisateurs

    12 avril 2011, par

    Chaque utilisateur dispose d’une page de profil lui permettant de modifier ses informations personnelle. Dans le menu de haut de page par défaut, un élément de menu est automatiquement créé à l’initialisation de MediaSPIP, visible uniquement si le visiteur est identifié sur le site.
    L’utilisateur a accès à la modification de profil depuis sa page auteur, un lien dans la navigation "Modifier votre profil" est (...)

  • Des sites réalisés avec MediaSPIP

    2 mai 2011, par

    Cette page présente quelques-uns des sites fonctionnant sous MediaSPIP.
    Vous pouvez bien entendu ajouter le votre grâce au formulaire en bas de page.

Sur d’autres sites (7099)

  • Anomalie #4295 (Nouveau) : Bug sur Boucle DATA et fusion sur un #ARRAY

    21 février 2019

    Bonjour,

    J’ai fait une boucle complexe pour lister par année, et mois les articles et les brèves d’un site : https://zone.spip.org/trac/spip-zone/changeset/113991

    Dans mon jeu de test, elle génère ce tableau :

    1. <span class="CodeRay"><span class="predefined">Array</span>
    2. (
    3. [<span class="integer">0</span>] => <span class="predefined">Array</span>
    4. (
    5. [year] => <span class="integer">2016</span>
    6. [month] => <span class="integer">12</span>
    7. [lemois] => décembre
    8. [<span class="predefined">date</span>] => <span class="integer">2016</span>-<span class="integer">12</span>-<span class="integer">18</span> <span class="integer">23</span>:<span class="integer">05</span>:<span class="integer">51</span>
    9. [url] => <span class="constant">Test</span>-modele-exergue.html
    10. [descriptif] =>
    11. [titre] => <span class="constant">Test</span> modèle exergue
    12. [<span class="keyword">class</span>] =>
    13. )
    14. [<span class="integer">1</span>] => <span class="predefined">Array</span>
    15. (
    16. [year] => <span class="integer">2016</span>
    17. [month] => <span class="integer">10</span>
    18. [lemois] => octobre
    19. [<span class="predefined">date</span>] => <span class="integer">2016</span>-<span class="integer">10</span>-<span class="integer">27</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">00</span>
    20. [url] => <span class="constant">Derniers</span>-articles.html
    21. [descriptif] =>
    22. [titre] => <span class="constant">Derniers</span> articles
    23. [<span class="keyword">class</span>] =>
    24. )
    25. [<span class="integer">2</span>] => <span class="predefined">Array</span>
    26. (
    27. [year] => <span class="integer">2016</span>
    28. [month] => <span class="integer">09</span>
    29. [lemois] => septembre
    30. [<span class="predefined">date</span>] => <span class="integer">2016</span>-<span class="integer">09</span>-<span class="integer">06</span> <span class="integer">20</span>:<span class="integer">20</span>:<span class="integer">42</span>
    31. [url] => <span class="constant">Test</span>-<span class="constant">Form</span>-<span class="constant">IP</span>.html
    32. [descriptif] =>
    33. <span class="constant">Tentez</span> de gagner par tirage au <span class="predefined">sort</span> le remboursement de votre achat [<span class="integer">1</span>]
    34.  
    35. [titre] => <span class="constant">Test</span> <span class="constant">Form</span> <span class="constant">IP</span>
    36. [<span class="keyword">class</span>] =>
    37. )
    38. [<span class="integer">3</span>] => <span class="predefined">Array</span>
    39. (
    40. [year] => <span class="integer">2016</span>
    41. [month] => <span class="integer">07</span>
    42. [lemois] => juillet
    43. [<span class="predefined">date</span>] => <span class="integer">2016</span>-<span class="integer">07</span>-<span class="integer">29</span> <span class="integer">14</span>:<span class="integer">45</span>:<span class="integer">00</span>
    44. [url] => <span class="constant">Article</span>-avec-logo.html
    45. [descriptif] =>
    46. [titre] => <span class="constant">Article</span> avec logo
    47. [<span class="keyword">class</span>] =>
    48. )
    49. [<span class="integer">4</span>] => <span class="predefined">Array</span>
    50. (
    51. [year] => <span class="integer">2016</span>
    52. [month] => <span class="integer">05</span>
    53. [lemois] => mai
    54. [<span class="predefined">date</span>] => <span class="integer">2016</span>-<span class="integer">05</span>-<span class="integer">22</span> <span class="integer">17</span>:<span class="integer">29</span>:<span class="integer">43</span>
    55. [url] => <span class="constant">Long</span>.html
    56. [descriptif] =>
    57. [titre] => <span class="constant">Long</span>
    58. [<span class="keyword">class</span>] =>
    59. )
    60. [<span class="integer">5</span>] => <span class="predefined">Array</span>
    61. (
    62. [year] => <span class="integer">2016</span>
    63. [month] => <span class="integer">05</span>
    64. [lemois] => mai
    65. [<span class="predefined">date</span>] => <span class="integer">2016</span>-<span class="integer">05</span>-<span class="integer">22</span> <span class="integer">17</span>:<span class="integer">03</span>:<span class="integer">50</span>
    66. [url] => <span class="constant">Repetition</span>-avec-debut-dans-le-passe.html
    67. [descriptif] =>
    68. [titre] => <span class="constant">Répétition</span> avec début dans le passé
    69. [<span class="keyword">class</span>] =>
    70. )
    71. [<span class="integer">6</span>] => <span class="predefined">Array</span>
    72. (
    73. [year] => <span class="integer">2016</span>
    74. [month] => <span class="integer">05</span>
    75. [lemois] => mai
    76. [<span class="predefined">date</span>] => <span class="integer">2016</span>-<span class="integer">05</span>-<span class="integer">02</span> <span class="integer">07</span>:<span class="integer">42</span>:<span class="integer">45</span>
    77. [url] => <span class="constant">Test</span>-previsualisation-etendue.html
    78. [descriptif] =>
    79. <span class="constant">Je</span> suis un testeur
    80.  
    81. [titre] => <span class="constant">Test</span> prévisualisation étendue
    82. [<span class="keyword">class</span>] =>
    83. )
    84. [<span class="integer">7</span>] => <span class="predefined">Array</span>
    85. (
    86. [year] => <span class="integer">2016</span>
    87. [month] => <span class="integer">04</span>
    88. [lemois] => avril
    89. [<span class="predefined">date</span>] => <span class="integer">2016</span>-<span class="integer">04</span>-<span class="integer">01</span> <span class="integer">04</span>:<span class="integer">10</span>:<span class="integer">12</span>
    90. [url] => <span class="constant">Test</span>-forme-colorees.html
    91. [descriptif] =>
    92. <span class="constant">Test</span> qui va bien
    93.  
    94. [titre] => <span class="constant">Test</span> forme colorées
    95. [<span class="keyword">class</span>] =>
    96. )
    97. [<span class="integer">8</span>] => <span class="predefined">Array</span>
    98. (
    99. [year] => <span class="integer">2015</span>
    100. [month] => <span class="integer">12</span>
    101. [lemois] => décembre
    102. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">12</span>-<span class="integer">06</span> <span class="integer">15</span>:<span class="integer">00</span>:<span class="integer">00</span>
    103. [url] => <span class="constant">Test</span>-article-sur-embargo.html
    104. [descriptif] =>
    105. [titre] => <span class="constant">Test</span> article sur embargo
    106. [<span class="keyword">class</span>] =>
    107. )
    108. [<span class="integer">9</span>] => <span class="predefined">Array</span>
    109. (
    110. [year] => <span class="integer">2015</span>
    111. [month] => <span class="integer">11</span>
    112. [lemois] => novembre
    113. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">11</span>-<span class="integer">24</span> <span class="integer">09</span>:<span class="integer">48</span>:<span class="integer">01</span>
    114. [url] => <span class="constant">Intentions</span>-de-prieres.html
    115. [descriptif] =>
    116. <span class="constant">Test</span> des <span class="constant">IP</span>
    117.  
    118. [titre] => <span class="constant">Intentions</span> de prières
    119. [<span class="keyword">class</span>] =>
    120. )
    121. [<span class="integer">10</span>] => <span class="predefined">Array</span>
    122. (
    123. [year] => <span class="integer">2015</span>
    124. [month] => <span class="integer">10</span>
    125. [lemois] => octobre
    126. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">26</span> <span class="integer">23</span>:<span class="integer">06</span>:<span class="integer">31</span>
    127. [url] => <span class="constant">Test</span>-<span class="constant">Newsletter</span>.html
    128. [descriptif] =>
    129. <span class="constant">Un</span> autre descriptif
    130.  
    131. [titre] => <span class="constant">Test</span> <span class="constant">Newsletter</span>
    132. [<span class="keyword">class</span>] =>
    133. )
    134. [<span class="integer">11</span>] => <span class="predefined">Array</span>
    135. (
    136. [year] => <span class="integer">2015</span>
    137. [month] => <span class="integer">10</span>
    138. [lemois] => octobre
    139. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">22</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">03</span>
    140. [url] => <span class="constant">Historique</span>-des-versions-de-<span class="constant">SPIP</span>.html
    141. [descriptif] =>
    142. [titre] => <span class="constant">Historique</span> des versions de <span class="constant">SPIP</span>
    143. [<span class="keyword">class</span>] =>
    144. )
    145. [<span class="integer">12</span>] => <span class="predefined">Array</span>
    146. (
    147. [year] => <span class="integer">2015</span>
    148. [month] => <span class="integer">10</span>
    149. [lemois] => octobre
    150. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">22</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">03</span>
    151. [url] => <span class="constant">Evenement</span>-exceptionnel.html
    152. [descriptif] =>
    153. [titre] => Événement exceptionnel
    154. [<span class="keyword">class</span>] =>
    155. )
    156. [<span class="integer">13</span>] => <span class="predefined">Array</span>
    157. (
    158. [year] => <span class="integer">2015</span>
    159. [month] => <span class="integer">10</span>
    160. [lemois] => octobre
    161. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">22</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">03</span>
    162. [url] => <span class="constant">Installation</span>-du-site.html
    163. [descriptif] =>
    164. [titre] => <span class="constant">Installation</span> du site
    165. [<span class="keyword">class</span>] =>
    166. )
    167. [<span class="integer">14</span>] => <span class="predefined">Array</span>
    168. (
    169. [year] => <span class="integer">2015</span>
    170. [month] => <span class="integer">10</span>
    171. [lemois] => octobre
    172. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">22</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">03</span>
    173. [url] => <span class="constant">Demonstration</span>-<span class="constant">Agenda</span>.html
    174. [descriptif] =>
    175. [titre] => <span class="constant">Démonstration</span> <span class="constant">Agenda</span>
    176. [<span class="keyword">class</span>] =>
    177. )
    178. [<span class="integer">15</span>] => <span class="predefined">Array</span>
    179. (
    180. [year] => <span class="integer">2015</span>
    181. [month] => <span class="integer">10</span>
    182. [lemois] => octobre
    183. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">22</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">03</span>
    184. [url] => <span class="constant">Titre</span>-de-la-rubrique.html
    185. [descriptif] =>
    186. [titre] => <span class="constant">Titre</span> de la rubrique
    187. [<span class="keyword">class</span>] =>
    188. )
    189. [<span class="integer">16</span>] => <span class="predefined">Array</span>
    190. (
    191. [year] => <span class="integer">2015</span>
    192. [month] => <span class="integer">10</span>
    193. [lemois] => octobre
    194. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">22</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">03</span>
    195. [url] => <span class="constant">Logo</span>-de-survol.html
    196. [descriptif] =>
    197. [titre] => <span class="constant">Logo</span> de survol
    198. <span class="constant">Nouveauté</span>
    199. [<span class="keyword">class</span>] =>
    200. )
    201. [<span class="integer">17</span>] => <span class="predefined">Array</span>
    202. (
    203. [year] => <span class="integer">2015</span>
    204. [month] => <span class="integer">10</span>
    205. [lemois] => octobre
    206. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">22</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">02</span>
    207. [url] => <span class="constant">Altera</span>-sententia-est.html
    208. [descriptif] =>
    209. [titre] => <span class="constant">Altera</span> sententia est
    210. [<span class="keyword">class</span>] =>
    211. )
    212. [<span class="integer">18</span>] => <span class="predefined">Array</span>
    213. (
    214. [year] => <span class="integer">2015</span>
    215. [month] => <span class="integer">10</span>
    216. [lemois] => octobre
    217. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">22</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">02</span>
    218. [url] => <span class="constant">Quis</span>-enim.html
    219. [descriptif] =>
    220. [titre] => <span class="constant">Quis</span> enim
    221. [<span class="keyword">class</span>] =>
    222. )
    223. [<span class="integer">19</span>] => <span class="predefined">Array</span>
    224. (
    225. [year] => <span class="integer">2015</span>
    226. [month] => <span class="integer">10</span>
    227. [lemois] => octobre
    228. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">22</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">02</span>
    229. [url] => <span class="constant">Oportunum</span>-est.html
    230. [descriptif] =>
    231. [titre] => <span class="constant">Oportunum</span> est
    232. [<span class="keyword">class</span>] =>
    233. )
    234. [<span class="integer">20</span>] => <span class="predefined">Array</span>
    235. (
    236. [year] => <span class="integer">2015</span>
    237. [month] => <span class="integer">10</span>
    238. [lemois] => octobre
    239. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">22</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">02</span>
    240. [url] => <span class="constant">Rogatus</span>-ad-ultimum.html
    241. [descriptif] =>
    242. [titre] => <span class="constant">Rogatus</span> ad ultimum
    243. [<span class="keyword">class</span>] =>
    244. )
    245. [<span class="integer">21</span>] => <span class="predefined">Array</span>
    246. (
    247. [year] => <span class="integer">2015</span>
    248. [month] => <span class="integer">10</span>
    249. [lemois] => octobre
    250. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">22</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">02</span>
    251. [url] => <span class="constant">Urbibus</span>-decorata.html
    252. [descriptif] =>
    253. [titre] => <span class="constant">Urbibus</span> decorata
    254. [<span class="keyword">class</span>] =>
    255. )
    256. [<span class="integer">22</span>] => <span class="predefined">Array</span>
    257. (
    258. [year] => <span class="integer">2015</span>
    259. [month] => <span class="integer">10</span>
    260. [lemois] => octobre
    261. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">22</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">02</span>
    262. [url] => <span class="constant">Les</span>-derniers-articles-modifies.html
    263. [descriptif] =>
    264. [titre] => <span class="constant">Les</span> derniers articles modifiés
    265. [<span class="keyword">class</span>] =>
    266. )
    267. [<span class="integer">23</span>] => <span class="predefined">Array</span>
    268. (
    269. [year] => <span class="integer">2015</span>
    270. [month] => <span class="integer">10</span>
    271. [lemois] => octobre
    272. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">22</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">02</span>
    273. [url] => <span class="constant">Image</span>-logo.html
    274. [descriptif] =>
    275. [titre] => <span class="constant">Image</span> = logo
    276. [<span class="keyword">class</span>] =>
    277. )
    278. [<span class="integer">24</span>] => <span class="predefined">Array</span>
    279. (
    280. [year] => <span class="integer">2015</span>
    281. [month] => <span class="integer">10</span>
    282. [lemois] => octobre
    283. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">22</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">02</span>
    284. [url] => <span class="constant">Articles</span>-avec-le-<span class="constant">Mot</span>-clef-<span class="constant">ALaUne</span>.html
    285. [descriptif] =>
    286. <span class="constant">Ceci</span> est une bulle d’aide !
    287.  
    288. [titre] => <span class="constant">Articles</span> avec le <span class="constant">Mot</span> clef : « <span class="constant">ALaUne</span> »
    289. [<span class="keyword">class</span>] =>
    290. )
    291. [<span class="integer">25</span>] => <span class="predefined">Array</span>
    292. (
    293. [year] => <span class="integer">2015</span>
    294. [month] => <span class="integer">10</span>
    295. [lemois] => octobre
    296. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">22</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">02</span>
    297. [url] => <span class="constant">Un</span>-sourire-peut-changer-une-vie.html
    298. [descriptif] =>
    299. [titre] => <span class="constant">Un</span> sourire peut changer une vie
    300. [<span class="keyword">class</span>] =>
    301. )
    302. [<span class="integer">26</span>] => <span class="predefined">Array</span>
    303. (
    304. [year] => <span class="integer">2015</span>
    305. [month] => <span class="integer">10</span>
    306. [lemois] => octobre
    307. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">22</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">02</span>
    308. [url] => <span class="constant">Le</span>-nombre-d-article-affiche-est-administrable.html
    309. [descriptif] =>
    310. [titre] => <span class="constant">Le</span> nombre d’article affiché est administrable
    311. [<span class="keyword">class</span>] =>
    312. )
    313. [<span class="integer">27</span>] => <span class="predefined">Array</span>
    314. (
    315. [year] => <span class="integer">2015</span>
    316. [month] => <span class="integer">10</span>
    317. [lemois] => octobre
    318. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">22</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">02</span>
    319. [url] => <span class="constant">Iamque</span>-non-umbratis.html
    320. [descriptif] =>
    321. [titre] => <span class="constant">Iamque</span> non umbratis (pdq2n)
    322. [<span class="keyword">class</span>] =>
    323. )
    324. [<span class="integer">28</span>] => <span class="predefined">Array</span>
    325. (
    326. [year] => <span class="integer">2015</span>
    327. [month] => <span class="integer">10</span>
    328. [lemois] => octobre
    329. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">22</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">01</span>
    330. [url] => <span class="constant">Mensarum</span>-enim.html
    331. [descriptif] =>
    332. [titre] => <span class="constant">Mensarum</span> enim
    333. [<span class="keyword">class</span>] =>
    334. )
    335. [<span class="integer">29</span>] => <span class="predefined">Array</span>
    336. (
    337. [year] => <span class="integer">2015</span>
    338. [month] => <span class="integer">10</span>
    339. [lemois] => octobre
    340. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">22</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">01</span>
    341. [url] => <span class="constant">Ideo</span>-urbs-venerabilis.html
    342. [descriptif] =>
    343. [titre] => <span class="constant">Ideo</span> urbs venerabilis
    344. [<span class="keyword">class</span>] =>
    345. )
    346. [<span class="integer">30</span>] => <span class="predefined">Array</span>
    347. (
    348. [year] => <span class="integer">2015</span>
    349. [month] => <span class="integer">10</span>
    350. [lemois] => octobre
    351. [<span class="predefined">date</span>] => <span class="integer">2015</span>-<span class="integer">10</span>-<span class="integer">22</span> <span class="integer">11</span>:<span class="integer">33</span>:<span class="integer">01</span>
    352. [url] => <span class="constant">Et</span>-prima-post-<span class="constant">Osdroenam</span>-quam.html
    353. [descriptif] =>
    354. [titre] => <span class="constant">Et</span> prima post <span class="constant">Osdroenam</span> quam
    355. [<span class="keyword">class</span>] =>
    356. )
    357. [<span class="integer">31</span>] => <span class="predefined">Array</span>
    358. (
    359. [year] => <span class="integer">2019</span>
    360. [month] => <span class="integer">02</span>
    361. [lemois] => février
    362. [<span class="predefined">date</span>] => <span class="integer">2019</span>-<span class="integer">02</span>-<span class="integer">21</span> <span class="integer">12</span>:<span class="integer">46</span>:<span class="integer">24</span>
    363. [url] => +<span class="constant">Test</span>-d-une-breve+.html
    364. [descriptif] =>
    365. [titre] => <span class="constant">Test</span> d’une brève
    366. [<span class="keyword">class</span>] => iconbreves
    367. )
    368. )
    369. </span>

    Télécharger

    Mais le résultat n’affiche rien à partir de l’année 2015.

    Si je modifie les boucles pour ne générer dans l’array que l’année 2015, celle-ci est affichée correctement.
    Si j’enlève des critères fusion lemois, l’année 2015 est parcourue.

    Testé en SPIP 3.2.3 SVN [24229]

  • Evolution #4347 (En cours) : Extraire la gestion des catégories de SPIP et SVP (action 1)

    11 juin 2019, par Eric Lupinacci

    Ce ticket est la partie SVP du ticket parent.
    Pour rappel :

    • supprimer les balises, filtres et globales associés aux catégories
    • certains autres filtres (comptage en particulier) ne sont utilisés que dans Plugins SPIP. Il convient de les déplacer dans le plugin idoine (Plugins SPIP ou Contrib à terme)
    • Supprimer le filtre catégorie dans le formulaire de recherche des plugins.
  • Capture from multiple streams concurrently, best way to do it and how to reduce CPU usage

    19 juin 2019, par DRONE_6969

    I am currently in the process of writing an application that will capture a lot of RTSP streams(in my case its 12) and display it on the QT widget. The problem arouses when I am going beyond around 6-7 streams, the CPU usage spikes and there is visible stutter.

    The reason why I think that it is not QT draw function is because I have done some checking to measure how much time it takes to draw an incoming image from camera and just sample images I had, it is always a lot less than 33 milliseconds(even if there are 12 widgets being updated).

    I also just ran opencv capture method without drawing and got pretty much the same CPU consumption as if I was drawing the frames (lost like 10% CPU at most and GPU usage went to zero).

    IMPORTANT : I am using RTSP stream which is a h264 stream.

    IF IT MATTERS MY SPECS :

    Intel Core i7-6700 @ 3.40GHZ(8 CPUS)
    Memory : 16gb
    GPU : Intel HD Graphics 530

    (Also I ran my code on a computer with dedicated Graphics card, it did eliminate some stutter but CPU usage is still pretty high)

    I am currently using OPENCV 4.1.0 with GSTREAMER enabled and built, I also have the OPENCV-WORLD version, there is no difference in performance.

    I have created a special class called Camera that holds its frame size constraints and various control functions as well stream function. The stream function is being ran on a separate thread, whenever stream() function is done with current frame it sends ready Mat via onNewFrame event I created which converts to QPixmap and updates widget’s lastImage variable. This way I can update image in a more thread safe way.

    I have tried to manipulate those VideoCapture.set() values, but it didn’t really help.

    This is my stream function (Ignore the bool return, it doesn’t do anything it is a remnant from couple of minutes ago when I was trying to use std::async) :

    bool Camera::stream() {
       /* This function is meant to run on a separate thread and fill up the buffer independantly of
       main stream thread */
       //cv::setNumThreads(100);
       /* Rules for these slightly changed! */
       Mat pre;  // Grab initial undoctored frame
       //pre = Mat::zeros(size, CV_8UC1);
       Mat frame; // Final modified frame
       frame = Mat::zeros(size, CV_8UC1);
       if (!pre.isContinuous()) pre = pre.clone();

       ipCam.open(streamUrl, CAP_FFMPEG);


       while (ipCam.isOpened() &amp;&amp; capture) {
           // If camera is opened wel need to capture and process the frame
           try {
               auto start = std::chrono::system_clock::now();

               ipCam >> pre;

               if (pre.empty()) {
                   /* Check for blank frame, return error if there is a blank frame*/
                   cerr &lt;&lt; id &lt;&lt; ": ERROR! blank frame grabbed\n";
                   for (FrameListener* i : clients) {
                       i->onNotification(1); // Notify clients about this shit
                   }
                   break;
               }

               else {
                   // Only continue if frame not empty

                   if (pre.cols != size.width &amp;&amp; pre.rows != size.height) {
                       resize(pre, frame, size);
                       pre.release();
                   }
                   else {
                       frame = pre;
                   }

                   dPacket* pack = new dPacket{id,&amp;frame};
                   for (auto i : clients) {
                       i->onPNewFrame(pack);
                   }
                   frame.release();
                   delete pack;
               }
           }

           catch (int e) {
               cout &lt;&lt; endl &lt;&lt; "-----Exception during capture process! CODE " &lt;&lt; e &lt;&lt; endl;
           }
           // End camera manipulations
       }

       cout &lt;&lt; "Camera timed out, or connection is closed..." &lt;&lt; endl;
       if (tryResetConnection) {
           cout &lt;&lt; "Reconnection flag is set, retrying after 3 seconds..." &lt;&lt; endl;
           for (FrameListener* i : clients) {
               i->onNotification(-1); // Notify clients about this shit
           }
           this_thread::sleep_for(chrono::milliseconds(3000));
           stream();
       }

       return true;
    }

    This is my onPNewFrame function. The conversion is still being done on camera’s thread because it was called within stream() and therefore is within that scope(and I also checked) :

    void GLWidget::onPNewFrame(dPacket* inPack) {
       lastFlag = 0;

       if (bufferEnabled) {
           buffer.push(QPixmap::fromImage(toQImageFromPMat(inPack->frame)));
       }
       else {
           if (playing) {
               /* Only process if this widget is playing */
               frameProcessing = true;
               lastImage.convertFromImage(toQImageFromPMat(inPack->frame));
               frameProcessing = false;
           }
       }

       if (lastFlag != -1 &amp;&amp; !lastImage.isNull()) {
           connecting = false;
       }
       else {
           connecting = true;
       }
    }

    This is my Mat to QImage :

    QImage GLWidget::toQImageFromPMat(cv::Mat* mat) {



       return QImage(mat->data, mat->cols, mat->rows, QImage::Format_RGB888).rgbSwapped();

    NOTE : not converting does not result in CPU boost (at least not a significant one).

    Minimal verifiable example

    This program is large. I am going to paste GLWidget.cpp and GLWidget.h as well as Camera.h and Camera.cpp. You can put GLWidget into anything just as long as you spawn more than 6 of it. Camera relies on the CamUtils, but it is possible to just paste url in videocapture

    I also supplied CamUtils, just in case

    Camera.h :

    #pragma once
    #include <iostream>
    #include <vector>
    #include <fstream>
    #include <map>
    #include <string>
    #include <sstream>
    #include <algorithm>
    #include "FrameListener.h"
    #include
    #include <thread>
    #include "CamUtils.h"
    #include <ctime>
    #include "dPacket.h"

    using namespace std;
    using namespace cv;

    class Camera
    {

       /*
           CLEANED UP!
           Camera now is only responsible for streaming and echoing captured frames.
           Frames are now wrapped into dPacket struct.
       */


    private:
       string id;
       vector clients;
       VideoCapture ipCam;
       string streamUrl;
       Size size;
       bool tryResetConnection = false;

       //TODO: Remove these as they are not going to be used going on:
       bool isPlaying = true;
       bool capture = true;

       //SECRET FEATURES:
       bool detect = false;


    public:
       Camera(string url, int width = 480, int height = 240, bool detect_=false);
       bool stream();
       void setReconnectable(bool newReconStatus);
       void addListener(FrameListener* client);
       vector<bool> getState();    // Returns current state: vector[0] stream state; vector[1] stream state; TODO: Remove this as this is no longer should control behaviour
       void killStream();
       bool getReconnectable();
    };

    </bool></ctime></thread></algorithm></sstream></string></map></fstream></vector></iostream>

    Camera.cpp

    #include "Camera.h"


    Camera::Camera(string url, int width, int height, bool detect_) // Default 240p
    {
       streamUrl = url; // Prepare url
       size = Size(width, height);
       detect = detect_;

    }

    void Camera::addListener(FrameListener* client) {
       clients.push_back(client);
    }


    /*
                   TEST CAMERAS(Paste into cameras.dViewer):
                   {"id":"96a73796-c129-46fc-9c01-40acd8ed7122","ip":"176.57.73.231","password":"null","username":"null"},
                   {"id":"96a73796-c129-46fc-9c01-40acd8ed7122","ip":"176.57.73.231","password":"null","username":"null"},
                   {"id":"96a73796-c129-46fc-9c01-40acd8ed7144","ip":"172.20.101.13","password":"admin","username":"root"}
                   {"id":"96a73796-c129-46fc-9c01-40acd8ed7144","ip":"172.20.101.13","password":"admin","username":"root"}

    */



    bool Camera::stream() {
       /* This function is meant to run on a separate thread and fill up the buffer independantly of
       main stream thread */
       //cv::setNumThreads(100);
       /* Rules for these slightly changed! */
       Mat pre;  // Grab initial undoctored frame
       //pre = Mat::zeros(size, CV_8UC1);
       Mat frame; // Final modified frame
       frame = Mat::zeros(size, CV_8UC1);
       if (!pre.isContinuous()) pre = pre.clone();

       ipCam.open(streamUrl, CAP_FFMPEG);

       while (ipCam.isOpened() &amp;&amp; capture) {
           // If camera is opened wel need to capture and process the frame
           try {
               auto start = std::chrono::system_clock::now();

               ipCam >> pre;

               if (pre.empty()) {
                   /* Check for blank frame, return error if there is a blank frame*/
                   cerr &lt;&lt; id &lt;&lt; ": ERROR! blank frame grabbed\n";
                   for (FrameListener* i : clients) {
                       i->onNotification(1); // Notify clients about this shit
                   }
                   break;
               }

               else {
                   // Only continue if frame not empty

                   if (pre.cols != size.width &amp;&amp; pre.rows != size.height) {
                       resize(pre, frame, size);
                       pre.release();
                   }
                   else {
                       frame = pre;
                   }

                   auto end = std::chrono::system_clock::now();
                   std::time_t ts = std::chrono::system_clock::to_time_t(end);
                   dPacket* pack = new dPacket{ id,&amp;frame};
                   for (auto i : clients) {
                       i->onPNewFrame(pack);
                   }
                   frame.release();
                   delete pack;
               }
           }

           catch (int e) {
               cout &lt;&lt; endl &lt;&lt; "-----Exception during capture process! CODE " &lt;&lt; e &lt;&lt; endl;
           }
           // End camera manipulations
       }

       cout &lt;&lt; "Camera timed out, or connection is closed..." &lt;&lt; endl;
       if (tryResetConnection) {
           cout &lt;&lt; "Reconnection flag is set, retrying after 3 seconds..." &lt;&lt; endl;
           for (FrameListener* i : clients) {
               i->onNotification(-1); // Notify clients about this shit
           }
           this_thread::sleep_for(chrono::milliseconds(3000));
           stream();
       }

       return true;
    }


    void Camera::killStream(){
       tryResetConnection = false;
       capture = false;
       ipCam.release();
    }

    void Camera::setReconnectable(bool reconFlag) {
       tryResetConnection = reconFlag;
    }

    bool Camera::getReconnectable() {
       return tryResetConnection;
    }

    vector<bool> Camera::getState() {
       vector<bool> states;
       states.push_back(isPlaying);
       states.push_back(ipCam.isOpened());
       return states;
    }



    </bool></bool>

    GLWidget.h :

    #ifndef GLWIDGET_H
    #define GLWIDGET_H

    #include <qopenglwidget>
    #include <qmouseevent>
    #include "FrameListener.h"
    #include "Camera.h"
    #include "FrameListener.h"
    #include
    #include "Camera.h"
    #include "CamUtils.h"
    #include
    #include "dPacket.h"
    #include <chrono>
    #include <ctime>
    #include
    #include "FullScreenVideo.h"
    #include <qmovie>
    #include "helper.h"
    #include <iostream>
    #include <qpainter>
    #include <qtimer>

    class Helper;

    class GLWidget : public QOpenGLWidget, public FrameListener
    {
       Q_OBJECT

    public:
       GLWidget(std::string camId, CamUtils *cUtils, int width, int height, bool denyFullScreen_ = false, bool detectFlag_=false, QWidget* parent = nullptr);
       void killStream();
       ~GLWidget();

    public slots:
       void animate();
       void setBufferEnabled(bool setState);
       void setCameraRetryConnection(bool setState);
       void GLUpdate();            // Call to update the widget
       void onRightClickMenu(const QPoint&amp; point);

    protected:
       void paintEvent(QPaintEvent* event) override;
       void onPNewFrame(dPacket* frame);
       void onNotification(int alert_code);


    private:
       // Objects and resourses
       Helper* helper;
       Camera* cam;
       CamUtils* camUtils;
       QTimer* timer; // Keep track of update
       QPixmap lastImage;
       QMovie* connMov;
       QMovie* test;

       QPixmap logo;

       // Control fields
       int width;
       int height;
       int camUtilsAddr;
       int elapsed;
       std::thread* camThread;
       std::string camId;
       bool denyFullScreen = false;
       bool playing = true;
       bool streaming = true;
       bool debug = false;
       bool connecting = true;
       int lastFlag = 0;


       // Debug fields
       std::chrono::high_resolution_clock::time_point lastFrameAt;
       std::chrono::high_resolution_clock::time_point now;
       std::chrono::duration<double> painTime; // time took to draw last frame

       //Buffer stuff
       std::queue<qpixmap> buffer;
       bool bufferEnabled = false;
       bool initialBuffer = false;
       bool buffering = true;
       bool frameProcessing = false;



       //Functions
       QImage toQImageFromPMat(cv::Mat* inFrame);
       void mousePressEvent(QMouseEvent* event) override;
       void drawImageGLLatest(QPainter* painter, QPaintEvent* event, int elapsed);
       void drawOnPaused(QPainter* painter, QPaintEvent* event, int elapsed);
       void drawOnStatus(int statusFlag, QPainter* painter, QPaintEvent* event, int elapsed);
    };

    #endif

    </qpixmap></double></qtimer></qpainter></iostream></qmovie></ctime></chrono></qmouseevent></qopenglwidget>

    GLWidget.cpp :

    #include "glwidget.h"
    #include <future>


    FullScreenVideo* fullScreen;

    GLWidget::GLWidget(std::string camId_, CamUtils* cUtils, int width_, int height_,  bool denyFullScreen_, bool detectFlag_, QWidget* parent)
       : QOpenGLWidget(parent), helper(helper)
    {
       cout &lt;&lt; "Player for CAMERA " &lt;&lt; camId_ &lt;&lt; endl;

       /* Underlying properties */
       camUtils = cUtils;
       cout &lt;&lt; "GLWidget Incoming CamUtils addr " &lt;&lt; camUtils &lt;&lt; endl;
       cout &lt;&lt; "GLWidget Set CamUtils addr " &lt;&lt; camUtils &lt;&lt; endl;
       camId = camId_;
       elapsed = 0;
       width = width_ + 5;
       height = height_ + 5;
       helper = new Helper();
       setFixedSize(width, height);
       denyFullScreen = denyFullScreen_;

       /* Camera capture thread */
       cam = new Camera(camUtils->getCameraStreamURL(camId), width_, height_, detectFlag_);
       cam->addListener(this);

       /* Sync states */
       vector<bool> initState = cam->getState();
       playing = initState[0];
       streaming = initState[1];
       cout &lt;&lt; "Initial states: " &lt;&lt; playing &lt;&lt; " " &lt;&lt; streaming &lt;&lt; endl;
       camThread = new std::thread(&amp;Camera::stream, cam);
       cout &lt;&lt; "================================================" &lt;&lt; endl;

       // Right click set up
       setContextMenuPolicy(Qt::CustomContextMenu);


       /* Loading gif */
       connMov = new QMovie("establishingConnection.gif");
       connMov->start();
       QString url = R"(RLC-logo.png)";
       logo = QPixmap(url);
       QTimer* timer = new QTimer(this);
       connect(timer, SIGNAL(timeout()), this, SLOT(GLUpdate()));
       timer->start(1000/30);
       playing = true;

    }

    /* SYSTEM */
    void GLWidget::animate()
    {
       elapsed = (elapsed + qobject_cast(sender())->interval()) % 1000;
       std::cout &lt;&lt; elapsed &lt;&lt; "\n";
    }


    void GLWidget::GLUpdate() {
       /* Process descisions before update call */
       if (bufferEnabled) {
           /* Process buffer before update */
           now = chrono::high_resolution_clock::now();
           std::chrono::duration timeSinceLastUpdate = now - lastFrameAt;
           if (timeSinceLastUpdate.count() > 25) {
               if (buffer.size() > 1 &amp;&amp; playing) {
                   lastImage.swap(buffer.front());
                   buffer.pop();
                   lastFrameAt = chrono::high_resolution_clock::now();
               }
           }
           //update(); // Update
       }
       else {
           /* No buffer */
       }
       repaint();
    }


    /* EVENTS */
    void GLWidget::onRightClickMenu(const QPoint&amp; point) {
       cout &lt;&lt; "Right click request got" &lt;&lt; endl;

       QPoint globPos = this->mapToGlobal(point);
       QMenu myMenu;

       if (!denyFullScreen) {
           myMenu.addAction("Open Full Screen");
       }
       myMenu.addAction("Toggle Debug Info");


       QAction* selected = myMenu.exec(globPos);

       if (selected) {
           string optiontxt = selected->text().toStdString();

           if (optiontxt == "Open Full Screen") {
               cout &lt;&lt; "Chose to open full screen of " &lt;&lt; camId &lt;&lt; endl;
               fullScreen = new FullScreenVideo(bufferEnabled, this);
               fullScreen->setUpView(camUtils, camId);
               fullScreen->show();
               playing = false;
           }

           if (optiontxt == "Toggle Debug Info") {
               cout &lt;&lt; "Chose to toggle debug of " &lt;&lt; camId &lt;&lt; endl;
               debug = !debug;
           }
       }
       else {
           cout &lt;&lt; "Chose nothing!" &lt;&lt; endl;
       }


    }



    void GLWidget::onPNewFrame(dPacket* inPack) {
       lastFlag = 0;

       if (bufferEnabled) {
           buffer.push(QPixmap::fromImage(toQImageFromPMat(inPack->frame)));
       }
       else {
           if (playing) {
               /* Only process if this widget is playing */
               frameProcessing = true;
               lastImage.convertFromImage(toQImageFromPMat(inPack->frame));
               frameProcessing = false;
           }
       }

       if (lastFlag != -1 &amp;&amp; !lastImage.isNull()) {
           connecting = false;
       }
       else {
           connecting = true;
       }
    }


    void GLWidget::onNotification(int alert) {
       lastFlag = alert;  
    }


    /* Paint events*/


    void GLWidget::paintEvent(QPaintEvent* event)
    {
       QPainter painter(this);

           if (lastFlag != 0 || connecting) {
               drawOnStatus(lastFlag, &amp;painter, event, elapsed);
           }
           else {

               /* Actual frame drawing */
               if (playing) {
                   if (!frameProcessing) {
                       drawImageGLLatest(&amp;painter, event, elapsed);
                   }
               }
               else {
                   drawOnPaused(&amp;painter, event, elapsed);
               }
           }
       painter.end();

    }


    /* DRAWING STUFF */

    void GLWidget::drawOnStatus(int statusFlag, QPainter* bgPaint, QPaintEvent* event, int elapsed) {

       QString str;
       QFont font("times", 15);
       bgPaint->eraseRect(QRect(0, 0, width, height));
       if (!lastImage.isNull()) {
           bgPaint->drawPixmap(QRect(0, 0, width, height), lastImage);
       }
       /* Test background painting */
       if (connecting) {
           string k = "Connecting to " + camUtils->getIp(camId);
           str.append(k.c_str());
       }
       else {
           switch (statusFlag) {
           case 1:
               str = "Blank frame received...";
               break;

           case -1:
               if (cam->getReconnectable()) {
                   str = "Connection lost, will try to reconnect.";
                   bgPaint->setOpacity(0.3);
               }
               else {
                   str = "Connection lost...";
                   bgPaint->setOpacity(0.3);
               }

               break;
           }
       }

       bgPaint->drawPixmap(QRect(0, 0, width, height), QPixmap::fromImage(connMov->currentImage()));
       bgPaint->setPen(Qt::red);
       bgPaint->setFont(font);
       QFontMetrics fm(font);
       const QRect kek(0, 0, fm.width(str), fm.height());
       QRect bound;
       bgPaint->setOpacity(1);
       bgPaint->drawText(bgPaint->viewport().width()/2 - kek.width()/2, bgPaint->viewport().height()/2 - kek.height(), str);

       bgPaint->drawPixmap(bgPaint->viewport().width() / 2 - logo.width()/2, height - logo.width() - 15, logo);

    }



    void GLWidget::drawOnPaused(QPainter* painter, QPaintEvent* event, int elapsed) {
       painter->eraseRect(0, 0, width, height);
       QFont font = painter->font();
       font.setPointSize(18);
       painter->setPen(Qt::red);
       QFontMetrics fm(font);
       QString str("Paused");
       painter->drawPixmap(QRect(0, 0, width, height),lastImage);
       painter->drawText(QPoint(painter->viewport().width() - fm.width(str), 50), str);

       if (debug) {
           QFont font = painter->font();
           font.setPointSize(25);
           painter->setPen(Qt::red);
           string camMess = "CAMID: " + camId;
           QString mess(camMess.c_str());
           string camIp = "IP: " + camUtils->getIp(camId);
           QString ipMess(camIp.c_str());
           QString bufferSize("Buffer size: " + QString::number(buffer.size()));
           QString lastFrameText("Last frame draw time: " + QString::number(painTime.count()) + "s");
           painter->drawText(QPoint(10, 50), mess);
           painter->drawText(QPoint(10, 60), ipMess);
           QString bufferState;
           if (bufferEnabled) {
               bufferState = QString("Experimental BUFFER is enabled!");
               QString currentBufferSize("Current buffer load: " + QString::number(buffer.size()));
               painter->drawText(QPoint(10, 80), currentBufferSize);
           }
           else {
               bufferState = QString("Experimental BUFFER is disabled!");
           }
           painter->drawText(QPoint(10, 70), bufferState);
           painter->drawText(QPoint(10, height - 25), lastFrameText);
       }
    }


    void GLWidget::drawImageGLLatest(QPainter* painter, QPaintEvent* event, int elapsed) {
       auto start = chrono::high_resolution_clock::now();
       painter->drawPixmap(QRect(0, 0, width, height), lastImage);
       if (debug) {
           QFont font = painter->font();
           font.setPointSize(25);
           painter->setPen(Qt::red);
           string camMess = "CAMID: " + camId;
           QString mess(camMess.c_str());
           string camIp = "IP: " + camUtils->getIp(camId);
           QString ipMess(camIp.c_str());
           QString bufferSize("Buffer size: " + QString::number(buffer.size()));
           QString lastFrameText("Last frame draw time: " + QString::number(painTime.count()) + "s");
           painter->drawText(QPoint(10, 50), mess);
           painter->drawText(QPoint(10, 60), ipMess);
           QString bufferState;
           if(bufferEnabled){
               bufferState = QString("Experimental BUFFER is enabled!");
               QString currentBufferSize("Current buffer load: " + QString::number(buffer.size()));
               painter->drawText(QPoint(10,80), currentBufferSize);
           }
           else {
               bufferState = QString("Experimental BUFFER is disabled!");
               QString currentBufferSize("Current buffer load: " + QString::number(buffer.size()));
               painter->drawText(QPoint(10, 80), currentBufferSize);
           }
           painter->drawText(QPoint(10, 70), bufferState);
           painter->drawText(QPoint(10, height - 25), lastFrameText);

       }
       auto end = chrono::high_resolution_clock::now();
       painTime = end - start;
    }



    /* END DRAWING STUFF */



    /* UI EVENTS */

    void GLWidget::mousePressEvent(QMouseEvent* e) {

       if (e->button() == Qt::LeftButton) {
           if (fullScreen == nullptr || !fullScreen->isVisible()) { // Do not unpause if window is opened
               playing = !playing;
           }
       }

       if (e->button() == Qt::RightButton) {
           onRightClickMenu(e->pos());
       }
    }



    /* Utilities */
    QImage GLWidget::toQImageFromPMat(cv::Mat* mat) {



       return QImage(mat->data, mat->cols, mat->rows, QImage::Format_RGB888).rgbSwapped();



    }

    /* State control */

    void GLWidget::killStream() {
       cam->killStream();
       camThread->join();
    }

    void GLWidget::setBufferEnabled(bool newBufferState) {
       cout &lt;&lt; "Player: " &lt;&lt; camId &lt;&lt; ", buffer state updated: " &lt;&lt; newBufferState &lt;&lt; endl;
       bufferEnabled = newBufferState;
       buffer.empty();
    }

    void GLWidget::setCameraRetryConnection(bool newState) {
       cam->setReconnectable(newState);
    }

    /* Destruction */
    GLWidget::~GLWidget() {
       cam->killStream();
       camThread->join();
    }
    </bool></future>

    CamUtils.h :

    #pragma once
    #include <iostream>
    #include <vector>
    #include <fstream>
    #include <map>
    #include <string>
    #include <sstream>
    #include <algorithm>
    #include <nlohmann></nlohmann>json.hpp>

    using namespace std;
    using json = nlohmann::json;

    class CamUtils
    {
    private:

       string camDb = "cameras.dViewer";
       map> cameraList; // Legacy
       json cameras;
       ofstream dbFile;
       bool dbExists(); // Always hard coded

       /* Old IMPLEMENTATION */
       void writeLineToDb_(const string&amp; content, bool append = false);
       void loadCameras_();

       /* JSON based */
       void loadCameras();

    public:
       CamUtils();
       string generateRandomString(size_t length);
       string getCameraStreamURL(string cameraId) const;
       string saveCamera(string ip, string username, string pass); // Return generated id
       vector<string> listAllCameraIds();
       string getIp(string cameraId);
    };


    </string></algorithm></sstream></string></map></fstream></vector></iostream>

    CamUtils.cpp :

    #include "CamUtils.h"
    #pragma comment(lib, "rpcrt4.lib")  // UuidCreate - Minimum supported OS Win 2000
    #include
    #include <iostream>

    CamUtils::CamUtils()
    {
       if (!dbExists()) {
           ofstream dbFile;
           dbFile.open(camDb);
           cameras["cameras"] = json::array();
           dbFile &lt;&lt; cameras &lt;&lt; std::endl;
           dbFile.close();

       }
       else {
           loadCameras();
       }
    }




    vector<string> CamUtils::listAllCameraIds() {
       vector<string> ids;
       cout &lt;&lt; "IN LIST " &lt;&lt; endl;
       for (auto&amp; cam : cameras["cameras"]) {
           ids.push_back(cam["id"].get<string>());
           //cout &lt;&lt; cam["id"].get<string>() &lt;&lt; std::endl;
       }
       return ids;
    }

    string CamUtils::getIp(string id) {
       vector<string> camDetails = cameraList[id];
       string ip = "NO IP WILL DISPLAYED UNTIL I FIGURE OUT A BUG";
       for (auto&amp; cam : cameras["cameras"]) {
           if (id == cam["id"]) {
               ip = cam["ip"].get<string>();
           }
       }

       return ip;
    }

    string CamUtils::getCameraStreamURL(string id) const {
       string url = "err"; // err is the default, it will be overwritten in case id is found, dont forget to check for it

       for (auto&amp; cam : cameras["cameras"]) {
           if (id == cam["id"]) {
               if (cam["username"].get<string>() == "null") {
                   url = "rtsp://" + cam["ip"].get<string>() + ":554/axis-media/media.amp?tcp";
               }
               else {
                   url = "rtsp://" + cam["username"].get<string>() + ":" + cam["password"].get<string>() + "@" + cam["ip"].get<string>() + ":554/axis-media/media.amp?streamprofile=720_30";
               }
           }
       }

       return url;  // Dont forget to check for err when using this shit
    }


    string CamUtils::saveCamera(string ip, string username, string password) {
       UUID uid;
       UuidCreate(&amp;uid);
       char* str;
       UuidToStringA(&amp;uid, (RPC_CSTR*)&amp;str);
       string id = str;
       cout &lt;&lt; "GEN: " &lt;&lt; id &lt;&lt; endl;
       json cam = json({}); //Create emtpy object
       cam["id"] = id;
       cam["ip"] = ip;
       cam["username"] = username;
       cam["password"] = password;
       cameras["cameras"].push_back(cam);
       std::ofstream out(camDb);
       out &lt;&lt; cameras &lt;&lt; std::endl;
       cout &lt;&lt; cameras["cameras"] &lt;&lt; endl;

       cout &lt;&lt; "Saved camera as " &lt;&lt; id &lt;&lt; endl;
       return id;
    }


    bool CamUtils::dbExists() {
       ifstream dbFile(camDb);
       return (bool)dbFile;
    }





    void CamUtils::loadCameras() {
       cout &lt;&lt; "Load call" &lt;&lt; endl;
       ifstream dbFile(camDb);
       string line;
       string wholeFile;

       while (std::getline(dbFile, line)) {
           cout &lt;&lt; line &lt;&lt; endl;
           wholeFile += line;
       }
       try {
           cameras = json::parse(wholeFile);
           //cout &lt;&lt; cameras["cameras"] &lt;&lt; endl;

       }
       catch (exception e) {
           cout &lt;&lt; e.what() &lt;&lt; endl;
       }
       dbFile.close();
    }










    /*
       LEGACY CODE, TO BE REMOVED!

    */



    void CamUtils::loadCameras_() {
       /*
           LEGACY CODE:
           This used to be the way to load cameras, but I moved on to JSON based configuration so this is no longer needed and will be removed soon
       */

       ifstream dbFile(camDb);
       string line;
       while (std::getline(dbFile, line)) {
           /*
               This function load camera data to the map:
               The order MUST be the following: 0:ID, 1:IP, 2:USERNAME, 3:PASSWORD.
               Always delimited with | no spaces between!
           */
           if (!line.empty()) {
               stringstream ss(line);
               string item;
               vector<string> splitString;

               while (std::getline(ss, item, '|')) {
                   splitString.push_back(item);
               }
               if (splitString.size() > 0) {
                   /* Dont even parse if the program didnt split right*/
                   //cout &lt;&lt; "Split string: " &lt;&lt; splitString.size() &lt;&lt; "\n";
                   for (int i = 0; i &lt; (splitString.size()); i++) cameraList[splitString[0]].push_back(splitString[i]);
               }
           }
       }
    }



    void CamUtils::writeLineToDb_(const string &amp; content, bool append) {
       ofstream dbFile;
       cout &lt;&lt; "Creating?";
       if (append) {
           dbFile.open(camDb, ios_base::app);
       }
       else {
           dbFile.open(camDb);
       }

       dbFile &lt;&lt; content.c_str() &lt;&lt; "\r\n";
       dbFile.flush();
    }

    /* JSON Reworx */




    string CamUtils::generateRandomString(size_t length)
    {
       const char* charmap = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
       const size_t charmapLength = strlen(charmap);
       auto generator = [&amp;]() { return charmap[rand() % charmapLength]; };
       string result;
       result.reserve(length);
       generate_n(back_inserter(result), length, generator);
       return result;
    }
    </string></string></string></string></string></string></string></string></string></string></string></string></iostream>

    End of example

    How would I go about decreasing CPU usage when dealing with large amount of streams ?