AcquireInterface.class.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. <?php
  2. namespace Models {
  3. require_once 'Models/User.class.php';
  4. require_once 'Tools/Random.class.php';
  5. require_once 'Tools/FS.class.php';
  6. require_once 'Tools/UUID.class.php';
  7. //require_once 'External/getID3/getid3/getid3.php';
  8. class AcquireInterface {
  9. //
  10. protected $DataInterface;
  11. /**
  12. *
  13. */
  14. public function __construct($DataInterface) {
  15. $this->DataInterface = $DataInterface;
  16. }
  17. /**
  18. * Post lesion area.
  19. */
  20. public function acquireLesionPost($User, $data) {
  21. //
  22. $statement = $this->DataInterface->DatabaseConnection->prepare(
  23. "SELECT markers FROM visit WHERE ID = :fk_visit"
  24. );
  25. $statement->bindParam(':fk_visit', $data['visitID']);
  26. // Error check
  27. if(!$statement->execute()) {
  28. return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()];
  29. }
  30. $markers = json_decode($statement->fetchAll(\PDO::FETCH_ASSOC)[0]['markers']);
  31. $markers[] = array(
  32. 'type' => $data['type'],
  33. 'location' => $data['location'],
  34. 'x' => $data['x'],
  35. 'y' => $data['y']
  36. );
  37. //
  38. $statement = $this->DataInterface->DatabaseConnection->prepare(
  39. "UPDATE visit SET markers = :markers WHERE ID = :fk_visit"
  40. );
  41. $statement->bindParam(':markers', json_encode($markers));
  42. $statement->bindParam(':fk_visit', $data['visitID']);
  43. // Error check
  44. if(!$statement->execute()) {
  45. return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()];
  46. }
  47. return [
  48. 'result' => 'OK',
  49. 'markers' => $markers
  50. ];
  51. }
  52. /**
  53. * Delete lesion area.
  54. */
  55. public function acquireLesionDeletePost($User, $data) {
  56. //
  57. $statement = $this->DataInterface->DatabaseConnection->prepare(
  58. "SELECT markers FROM visit WHERE ID = :fk_visit"
  59. );
  60. $statement->bindParam(':fk_visit', $data['visitID']);
  61. // Error check
  62. if(!$statement->execute()) {
  63. return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()];
  64. }
  65. $markers = json_decode($statement->fetchAll(\PDO::FETCH_ASSOC)[0]['markers']);
  66. for($i=0; $i<count($markers); $i++) {
  67. if(intval($markers[$i]->x) == intval($data['x']) && intval($markers[$i]->y) == intval($data['y']) &&
  68. $markers[$i]->location == $data['location'] &&
  69. $markers[$i]->type == $data['type']) {
  70. array_splice($markers, $i, 1);
  71. break;
  72. }
  73. }
  74. //
  75. $statement = $this->DataInterface->DatabaseConnection->prepare(
  76. "UPDATE visit SET markers = :markers WHERE ID = :fk_visit"
  77. );
  78. $statement->bindParam(':markers', json_encode($markers));
  79. $statement->bindParam(':fk_visit', $data['visitID']);
  80. // Error check
  81. if(!$statement->execute()) {
  82. return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()];
  83. }
  84. return [
  85. 'result' => 'OK',
  86. 'markers' => $markers
  87. ];
  88. }
  89. /**
  90. * Post media.
  91. */
  92. public function acquireMediaPost($User, $data) {
  93. // DICOM with unknown original side
  94. if(array_key_exists('source', $data) && $data['source']=='unknown') {
  95. $statement = $this->DataInterface->DatabaseConnection->prepare(
  96. "UPDATE media SET side = :side, location = :location, incidence = :incidence WHERE filename = :filename AND :fk_visit"
  97. );
  98. $statement->bindParam(':side', $data['side']);
  99. $statement->bindParam(':location', $data['location']);
  100. $statement->bindParam(':incidence', $data['incidence']);
  101. $statement->bindParam(':filename', $data['filename']);
  102. $statement->bindParam(':fk_visit', $data['visitID']);
  103. // Error check
  104. if(!$statement->execute()) {
  105. return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()];
  106. }
  107. return [
  108. 'result' => 'OK',
  109. 'side' => $data['side'],
  110. 'location' => $data['location'],
  111. 'incidence' => $data['incidence'],
  112. 'filename' => $data['filename']
  113. ];
  114. }
  115. $filepath = $_SERVER['DOCUMENT_ROOT']."/storage/media/".$data['visitID'].'/'.$data['filename'];
  116. $metrics = ['width' => 0, 'height' => 0, 'pxwidth' => 0, 'pxheight' => 0];
  117. // image JPEG
  118. if(substr_compare($data['filename'], '.jpeg', -strlen('.jpeg')) === 0) {
  119. list($metrics['width'], $metrics['height'], $type, $attr) = getimagesize($filepath);
  120. }
  121. // DICOM file
  122. else if(substr_compare($data['filename'], '.dicom', -strlen('.dicom')) === 0) {
  123. $jpegFilepath = str_replace('.dicom', '.jpeg', $filepath);
  124. if(file_exists($jpegFilepath)) {
  125. list($metrics['width'], $metrics['height'], $type, $attr) = getimagesize($jpegFilepath);
  126. }
  127. else {
  128. $mp4Filepath = str_replace('.dicom', '.mp4', $filepath);
  129. // get metrics
  130. $cmdLine = 'ffprobe -v error -show_entries stream=width,height,r_frame_rate -of csv=p=0 '.$mp4Filepath;
  131. $output=null;
  132. $retval=null;
  133. exec($cmdLine, $output, $retval);
  134. // error
  135. if($retval !== 0 || count($output)!=1) {
  136. return [
  137. 'result' => 'ERROR',
  138. 'cmdLine' => $cmdLine,
  139. 'output' => $output,
  140. 'retval' => $retval
  141. ];
  142. }
  143. $tab = explode(',',trim($output[0]));
  144. if(count($tab)!=3) {
  145. return [
  146. 'result' => 'ERROR',
  147. 'cmdLine' => $cmdLine,
  148. 'output' => $output,
  149. 'retval' => $retval
  150. ];
  151. }
  152. $metrics['width'] = intval($tab[0]);
  153. $metrics['height'] = intval($tab[1]);
  154. $fps = $tab[2];
  155. $tab = explode('/', $fps);
  156. if(count($tab) == 2) {
  157. $fps = intval($tab[0]);
  158. }
  159. else {
  160. $fps = intval($fps);
  161. }
  162. $metrics['fps'] = $fps;
  163. }
  164. // get metrics
  165. $cmdLine = 'dcmdump -s +P 0018,602c +P 0018,602e +P 0028,0008 "'.$filepath.'"';
  166. $output=null;
  167. $retval=null;
  168. exec($cmdLine, $output, $retval);
  169. // error
  170. if($retval !== 0 || (count($output)!=2 && count($output)!=3)) {
  171. return [
  172. 'result' => 'ERROR',
  173. 'cmdLine' => $cmdLine,
  174. 'output' => $output,
  175. 'retval' => $retval
  176. ];
  177. }
  178. $tab = explode(' ',trim($output[0]));
  179. $metrics['pxwidth'] = floatval($tab[2])*10.0;
  180. $tab = explode(' ',trim($output[1]));
  181. $metrics['pxheight'] = floatval($tab[2])*10.0;
  182. if(count($output)==3) {
  183. $tab = explode(' ',trim($output[2]));
  184. $metrics['frameCount'] = intval(str_replace(['[', ']'], '', $tab[2]));
  185. }
  186. }
  187. // video MP4
  188. else if(substr_compare($data['filename'], '.mp4', -strlen('.mp4')) === 0) {
  189. // get metrics
  190. $cmdLine = 'ffprobe -v error -show_entries stream=width,height,r_frame_rate,nb_frames -of csv=p=0 '.$filepath;
  191. $output=null;
  192. $retval=null;
  193. exec($cmdLine, $output, $retval);
  194. // error
  195. if($retval !== 0 || count($output)!=1) {
  196. return [
  197. 'result' => 'ERROR',
  198. 'cmdLine' => $cmdLine,
  199. 'output' => $output,
  200. 'retval' => $retval
  201. ];
  202. }
  203. $tab = explode(',',trim($output[0]));
  204. if(count($tab)!=4) {
  205. return [
  206. 'result' => 'ERROR',
  207. 'cmdLine' => $cmdLine,
  208. 'output' => $output,
  209. 'retval' => $retval
  210. ];
  211. }
  212. $metrics['width'] = intval($tab[0]);
  213. $metrics['height'] = intval($tab[1]);
  214. if(intval($tab[3])==0) {
  215. $metrics['frameCount'] = floor(intval($data['recordingTime'])/1000*11);
  216. $fps = 11;
  217. }
  218. else {
  219. $metrics['frameCount'] = intval($tab[3]);
  220. $fps = $tab[2];
  221. $tab = explode('/', $fps);
  222. if(count($tab) == 2) {
  223. $fps = intval($tab[0]);
  224. }
  225. else {
  226. $fps = intval($fps);
  227. }
  228. }
  229. $metrics['fps'] = $fps;
  230. }
  231. else {
  232. return ['result' => 'ERROR', 'reason' => 'invalid_media'];
  233. }
  234. //
  235. if(array_key_exists('mediaID', $data)) {
  236. // select old media
  237. $statement = $this->DataInterface->DatabaseConnection->prepare(
  238. "SELECT * FROM media WHERE ID = ".$data['mediaID']
  239. );
  240. // Error check
  241. if(!$statement->execute()) {
  242. return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()];
  243. }
  244. $oldMedia = $statement->fetchAll(\PDO::FETCH_ASSOC)[0];
  245. // delete old media
  246. $statement = $this->DataInterface->DatabaseConnection->prepare(
  247. "DELETE FROM media WHERE ID = ".$data['mediaID']
  248. );
  249. // Error check
  250. if(!$statement->execute()) {
  251. return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()];
  252. }
  253. // insert new media
  254. $statement = $this->DataInterface->DatabaseConnection->prepare(
  255. "INSERT INTO media(side, location, incidence, filename, metrics, fk_visit) VALUES(:side, :location, :incidence, :filename, :metrics, :fk_visit)"
  256. );
  257. $statement->bindParam(':side', $oldMedia['side']);
  258. $statement->bindParam(':location', $oldMedia['location']);
  259. $statement->bindParam(':incidence', $oldMedia['incidence']);
  260. $statement->bindParam(':filename', $data['filename']);
  261. $statement->bindParam(':metrics', json_encode($metrics));
  262. $statement->bindParam(':fk_visit', $data['visitID']);
  263. // Error check
  264. if(!$statement->execute()) {
  265. return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()];
  266. }
  267. $mediaID = $this->DataInterface->DatabaseConnection->lastInsertId();
  268. }
  269. else {
  270. $statement = $this->DataInterface->DatabaseConnection->prepare(
  271. "INSERT INTO media(side, location, incidence, filename, metrics, fk_visit) VALUES(:side, :location, :incidence, :filename, :metrics, :fk_visit)"
  272. );
  273. $statement->bindParam(':side', $data['side']);
  274. $statement->bindParam(':location', $data['location']);
  275. $statement->bindParam(':incidence', $data['incidence']);
  276. $statement->bindParam(':filename', $data['filename']);
  277. $statement->bindParam(':metrics', json_encode($metrics));
  278. $statement->bindParam(':fk_visit', $data['visitID']);
  279. // Error check
  280. if(!$statement->execute()) {
  281. return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()];
  282. }
  283. $mediaID = $this->DataInterface->DatabaseConnection->lastInsertId();
  284. }
  285. return [
  286. 'result' => 'OK',
  287. 'metrics' => $metrics,
  288. 'filename' => $data['filename'],
  289. 'mediaID' => $mediaID
  290. ];
  291. }
  292. /**
  293. * Delete media.
  294. */
  295. public function acquireDeletePost($User, $data) {
  296. $filename = $data['filename'];
  297. $statement = $this->DataInterface->DatabaseConnection->prepare(
  298. "INSERT INTO iimt_mathcloud_shadow.media SELECT * FROM media WHERE filename = '$filename'; DELETE FROM media WHERE filename = '$filename';"
  299. );
  300. // Error check
  301. if(!$statement->execute()) {
  302. return array('result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo());
  303. }
  304. return [
  305. 'result' => 'OK'
  306. ];
  307. }
  308. /**
  309. * Post acquire area.
  310. */
  311. public function acquireAreaPost($User, $data) {
  312. //
  313. $statement = $this->DataInterface->DatabaseConnection->prepare(
  314. "UPDATE visit SET area = :area WHERE ID = :fk_visit"
  315. );
  316. $statement->bindParam(':area', $data['area']);
  317. $statement->bindParam(':fk_visit', $data['visitID']);
  318. // Error check
  319. if(!$statement->execute()) {
  320. return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()];
  321. }
  322. return [
  323. 'result' => 'OK'
  324. ];
  325. }
  326. /**
  327. *
  328. */
  329. public function acquireDownloadGet($User, $visitID, $filename) {
  330. // media
  331. $statement = $this->DataInterface->DatabaseConnection->prepare(
  332. "SELECT * FROM media WHERE filename = :filename"
  333. );
  334. $statement->bindParam(':filename', $filename);
  335. // Error check
  336. if(!$statement->execute()) {
  337. return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()];
  338. }
  339. $path = '../../storage/media/'.$visitID.'/'.$statement->fetchAll(\PDO::FETCH_ASSOC)[0]['filename'];
  340. $data = file_get_contents($path);
  341. $base64 = /*'data:image/' . $type . ';base64,' .*/ base64_encode($data);
  342. $type = pathinfo($path, PATHINFO_EXTENSION);
  343. if($type=='dicom') {
  344. $type = 'application/'.$type;
  345. }
  346. else if($type=='mp4') {
  347. $type = 'video/'.$type;
  348. }
  349. else {
  350. $type = 'image/'.$type;
  351. }
  352. return [
  353. 'result' => 'OK',
  354. 'media' => $path,
  355. 'type' => $type,
  356. 'base64' => $base64
  357. ];
  358. }
  359. /**
  360. * Get media
  361. */
  362. public function acquireMediaGet($User, $patientID, $visitID) {
  363. // patient
  364. $statement = $this->DataInterface->DatabaseConnection->prepare(
  365. "SELECT patient.* FROM patient WHERE ID = :fk_patient"
  366. );
  367. $statement->bindParam(':fk_patient', $patientID);
  368. // Error check
  369. if(!$statement->execute()) {
  370. return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()];
  371. }
  372. $patient = $statement->fetchAll(\PDO::FETCH_ASSOC)[0];
  373. // visit
  374. $statement = $this->DataInterface->DatabaseConnection->prepare(
  375. "SELECT area, markers FROM visit WHERE ID = :fk_visit"
  376. );
  377. $statement->bindParam(':fk_visit', $visitID);
  378. // Error check
  379. if(!$statement->execute()) {
  380. return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()];
  381. }
  382. $data = $statement->fetchAll(\PDO::FETCH_ASSOC)[0];
  383. // media
  384. $statement = $this->DataInterface->DatabaseConnection->prepare(
  385. "SELECT * FROM media WHERE fk_visit = :fk_visit"
  386. );
  387. $statement->bindParam(':fk_visit', $visitID);
  388. // Error check
  389. if(!$statement->execute()) {
  390. return ['result' => 'ERROR', 'reason' => 'internal_error', 'message' => 'Database error', 'data' => $statement->errorInfo()];
  391. }
  392. $media = $statement->fetchAll(\PDO::FETCH_ASSOC);
  393. foreach($media as &$m) {
  394. $m['metrics'] = json_decode($m['metrics']);
  395. }
  396. return [
  397. 'result' => 'OK',
  398. 'patient' => $patient,
  399. 'area' => $data['area'],
  400. 'markers' => json_decode($data['markers']),
  401. 'media' => $media
  402. ];
  403. }
  404. /**
  405. * Post upload data.
  406. */
  407. public function acquireUploadPost($User, $data) {
  408. $baseDir = $_SERVER['DOCUMENT_ROOT']."/storage/media/".$data['visitID'];
  409. \Tools\FS::mkpath($baseDir);
  410. $ext = explode('/',$data['type'])[1];
  411. $filename = \Tools\UUID::v4().'.'.$ext;
  412. // Unknown
  413. if($data['type']=="") {
  414. $ext = 'dicom';
  415. $data['type'] = 'application/dicom';
  416. $data['data'] = str_replace('application/octet-stream', 'application/dicom', $data['data']);
  417. $filename .= $ext;
  418. }
  419. // DICOM image
  420. if(strtolower($ext)=='dicom') {
  421. $dcmData = $data['data'];
  422. $dcmData = str_replace('data:'.$data['type'].';base64,', '', $dcmData);
  423. $dcmData = base64_decode($dcmData); // Base64 decoded data
  424. $ok = file_put_contents($baseDir.'/'.$filename, $dcmData);
  425. // error
  426. if($ok === false) {
  427. return [
  428. 'result' => 'ERROR',
  429. 'filename' => $filename,
  430. 'reason' => 'write',
  431. 'message' => error_get_last()['message']
  432. ];
  433. }
  434. // multiframe?
  435. $cmdLine = 'dcmdump +P 0028,0008 "'.$baseDir.'/'.$filename.'"';
  436. $output=null;
  437. $retval=null;
  438. exec($cmdLine, $output, $retval);
  439. // OK
  440. if($retval === 0 && count($output)==1) {
  441. $tab = explode(' ',trim($output[0]));
  442. $frameCount = intval(str_replace(['[', ']'], '', $tab[2]));
  443. // error
  444. if($frameCount===0) {
  445. return [
  446. 'result' => 'ERROR',
  447. 'output' => $output,
  448. ];
  449. }
  450. // make JPEG
  451. $frames = [];
  452. for($i=1; $i<=$frameCount; $i++) {
  453. $src = $baseDir.'/'.$filename;
  454. $pad = str_pad($i, 3, "0", STR_PAD_LEFT);
  455. $dst = str_replace('.dicom', '-'.$pad.'.jpeg', $src);
  456. $cmdLine = 'dcmj2pnm "'.$src.'" "'.$dst.'" +oj +Jq 100 +F '.$i.' -v 2>&1';
  457. $output=null;
  458. $retval=null;
  459. exec($cmdLine, $output, $retval);
  460. // error
  461. if($retval !== 0 || count($output)<1) {
  462. return [
  463. 'result' => 'ERROR',
  464. 'cmdLine' => $cmdLine,
  465. 'output' => $output,
  466. 'retval' => $retval
  467. ];
  468. }
  469. $frames[] = $dst;
  470. }
  471. // make MP4
  472. $src = $baseDir.'/'.$filename;
  473. $dst = str_replace('.dicom', '-%03d.jpeg', $src);
  474. $mp4 = str_replace('.dicom', '.mp4', $src);
  475. $cmdLine = 'ffmpeg -f image2 -pattern_type sequence -r 11 -i '.$dst.' -y -c:v libx264 -pix_fmt yuv420p '.$mp4;
  476. $output=null;
  477. $retval=null;
  478. exec($cmdLine, $output, $retval);
  479. // error
  480. if($retval !== 0) {
  481. return [
  482. 'result' => 'ERROR',
  483. 'cmdLine' => $cmdLine,
  484. 'output' => $output,
  485. 'retval' => $retval
  486. ];
  487. }
  488. // cleanup
  489. for($i=0; $i<count($frames); $i++) {
  490. unlink($frames[$i]);
  491. }
  492. $data = file_get_contents($mp4);
  493. $base64 = 'data:video/mp4;base64,'.base64_encode($data);
  494. return [
  495. 'result' => 'OK',
  496. 'filename' => $filename,
  497. 'content' => $base64,
  498. 'type' => 'dicom'
  499. ];
  500. }
  501. // singleframe
  502. else {
  503. $src = $baseDir.'/'.$filename;
  504. $dst = str_replace('.dicom', '.jpeg', $src);
  505. $cmdLine = 'dcmj2pnm "'.$src.'" "'.$dst.'" +oj +Jq 100 +F 1 -v 2>&1';
  506. $output=null;
  507. $retval=null;
  508. exec($cmdLine, $output, $retval);
  509. // error
  510. if($retval !== 0 || count($output)<1) {
  511. return [
  512. 'result' => 'ERROR',
  513. 'cmdLine' => $cmdLine,
  514. 'output' => $output,
  515. 'retval' => $retval
  516. ];
  517. }
  518. $data = file_get_contents($dst);
  519. $base64 = 'data:image/jpeg;base64,'.base64_encode($data);
  520. return [
  521. 'result' => 'OK',
  522. 'filename' => $filename,
  523. 'content' => $base64,
  524. 'type' => 'dicom'
  525. ];
  526. }
  527. }
  528. // AVI video
  529. else if($ext == 'x-msvideo') {
  530. $videoData = $data['data'];
  531. $videoData = str_replace('data:'.$data['type'].';base64,', '', $videoData);
  532. $videoData = base64_decode($videoData); // Base64 decoded data
  533. $ok = file_put_contents($baseDir.'/'.$filename, $videoData);
  534. // error
  535. if($ok === false) {
  536. return [
  537. 'result' => 'ERROR',
  538. 'filename' => $filename,
  539. 'reason' => 'write',
  540. 'message' => error_get_last()['message']
  541. ];
  542. }
  543. $src = $baseDir.'/'.$filename;
  544. $dst = str_replace('.x-msvideo', '.mp4', $src);
  545. $cmdLine = 'ffmpeg -i '.$src.' -y -r 11 '.$dst;
  546. $output=null;
  547. $retval=null;
  548. exec($cmdLine, $output, $retval);
  549. // error
  550. if($retval !== 0) {
  551. return [
  552. 'result' => 'ERROR',
  553. 'cmdLine' => $cmdLine,
  554. 'output' => $output,
  555. 'retval' => $retval
  556. ];
  557. }
  558. $data = file_get_contents($dst);
  559. $base64 = 'data:video/mp4;base64,'.base64_encode($data);
  560. return [
  561. 'result' => 'OK',
  562. 'filename' => str_replace('.x-msvideo', '.mp4', $filename),
  563. 'content' => $base64,
  564. 'type' => 'mp4'
  565. ];
  566. }
  567. // MP4 video
  568. else if($ext == 'mp4') {
  569. $videoData = $data['data'];
  570. //file_put_contents($baseDir.'/'.$filename.'-data-prev.txt', $videoData);
  571. $videoData = str_replace('data:'.$data['type'].';base64,', '', $videoData);
  572. //file_put_contents($baseDir.'/'.$filename.'-data-after.txt', $videoData);
  573. $videoData = base64_decode($videoData); // Base64 decoded data
  574. $src = $baseDir.'/'.$filename;
  575. $ok = file_put_contents($src, $videoData);
  576. // error
  577. if($ok === false) {
  578. return [
  579. 'result' => 'ERROR',
  580. 'filename' => $filename,
  581. 'reason' => 'write',
  582. 'message' => error_get_last()['message']
  583. ];
  584. }
  585. $base64 = $data['data'];
  586. //same as:
  587. //$data = file_get_contents($src);
  588. //$base64 = 'data:video/mp4;base64,'.base64_encode($data);
  589. return [
  590. 'result' => 'OK',
  591. 'filename' => $filename,
  592. 'content' => $base64,
  593. 'type' => 'mp4'
  594. ];
  595. }
  596. // JPEG image
  597. else if($ext == 'jpeg') {
  598. $imgData = $data['data'];
  599. $imgData = str_replace('data:'.$data['type'].';base64,', '', $imgData);
  600. $imgData = base64_decode($imgData); // Base64 decoded data
  601. $ok = file_put_contents($baseDir.'/'.$filename, $imgData);
  602. // error
  603. if($ok === false) {
  604. return [
  605. 'result' => 'ERROR',
  606. 'filename' => $filename,
  607. 'reason' => 'write',
  608. 'message' => error_get_last()['message']
  609. ];
  610. }
  611. return [
  612. 'result' => 'OK',
  613. 'filename' => $filename,
  614. 'type' => 'jpeg'
  615. ];
  616. }
  617. // Captured video
  618. else if($ext == 'webm') {
  619. $videoData = $data['data'];
  620. $videoData = str_replace('data:'.$data['type'].';base64,', '', $videoData);
  621. $videoData = base64_decode($videoData); // Base64 decoded data
  622. $ok = file_put_contents($baseDir.'/'.$filename, $videoData);
  623. // error
  624. if($ok === false) {
  625. return [
  626. 'result' => 'ERROR',
  627. 'filename' => $filename,
  628. 'reason' => 'write',
  629. 'message' => error_get_last()['message']
  630. ];
  631. }
  632. $src = $baseDir.'/'.$filename;
  633. $dst = str_replace('.webm', '.mp4', $src);
  634. $cmdLine = 'ffmpeg -i '.$src.' -y -r 11 '.$dst;
  635. $output=null;
  636. $retval=null;
  637. exec($cmdLine, $output, $retval);
  638. // error
  639. if($retval !== 0) {
  640. return [
  641. 'result' => 'ERROR',
  642. 'cmdLine' => $cmdLine,
  643. 'output' => $output,
  644. 'retval' => $retval
  645. ];
  646. }
  647. $data = file_get_contents($dst);
  648. $base64 = 'data:video/mp4;base64,'.base64_encode($data);
  649. return [
  650. 'result' => 'OK',
  651. 'filename' => str_replace('.webm', '.mp4', $filename),
  652. 'content' => $base64,
  653. 'type' => 'mp4'
  654. ];
  655. }
  656. return [
  657. 'result' => 'ERROR',
  658. 'reason' => 'invalid_media',
  659. 'filename' => $filename
  660. ];
  661. }
  662. }
  663. }