PageRenderTime 54ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/applications/mp42avi/main.c

https://github.com/svettom/gpac
C | 785 lines | 667 code | 73 blank | 45 comment | 122 complexity | d677be47060a44ae07112a0c056e16f1 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0
  1. /*
  2. * GPAC - Multimedia Framework C SDK
  3. *
  4. * Authors: Jean Le Feuvre
  5. * Copyright (c) Telecom ParisTech 2000-2012
  6. * All rights reserved
  7. *
  8. * This file is part of GPAC / command-line mp4 toolbox
  9. *
  10. * GPAC is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU Lesser General Public License as published by
  12. * the Free Software Foundation; either version 2, or (at your option)
  13. * any later version.
  14. *
  15. * GPAC is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; see the file COPYING. If not, write to
  22. * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  23. *
  24. */
  25. #include "../../include/gpac/isomedia.h"
  26. #include "../../include/gpac/compositor.h"
  27. #include "../../include/gpac/scenegraph.h"
  28. #include "../../include/gpac/bifs.h"
  29. #include "../../include/gpac/options.h"
  30. #ifdef WIN32
  31. #include <windows.h>
  32. #define GPAC_CFG_FILE "GPAC.cfg"
  33. #else
  34. #include <pwd.h>
  35. typedef struct tagBITMAPFILEHEADER
  36. {
  37. u16 bfType;
  38. u32 bfSize;
  39. u16 bfReserved1;
  40. u16 bfReserved2;
  41. u32 bfOffBits;
  42. } BITMAPFILEHEADER;
  43. typedef struct tagBITMAPINFOHEADER{
  44. u32 biSize;
  45. s32 biWidth;
  46. s32 biHeight;
  47. u16 biPlanes;
  48. u16 biBitCount;
  49. u32 biCompression;
  50. u32 biSizeImage;
  51. s32 biXPelsPerMeter;
  52. s32 biYPelsPerMeter;
  53. u32 biClrUsed;
  54. u32 biClrImportant;
  55. } BITMAPINFOHEADER;
  56. #define BI_RGB 0L
  57. #define GPAC_CFG_FILE ".gpacrc"
  58. #endif
  59. #include "../../include/gpac/internal/avilib.h"
  60. #include "../../include/gpac/internal/compositor_dev.h"
  61. void PrintVersion()
  62. {
  63. printf ("MP42AVI - GPAC version %s\n", GPAC_FULL_VERSION);
  64. }
  65. void PrintUsage()
  66. {
  67. printf ("MP42AVI [option] input\n"
  68. "Dumps BIFS media frames as AVI, BMP or raw\n\n"
  69. "Options\n"
  70. "-fps Framerate: specifies extraction framerate - if not set computed from track length\n"
  71. "-size WxH: forces output BIFS to the given resolution\n"
  72. "-raw [frame]: uses raw format for output - only dumps one frame if specified\n"
  73. "-bmp [frame]: uses BMP format for output - only dumps one frame if specified\n"
  74. "-outpath path: specifies where to dump frames/movie\n"
  75. "\n"
  76. "Note: when dumping a frame, either the frame number can be specified or the frame time\n"
  77. "in the format hh:mm:ss:xFz where hh, mm, ss are hours, minutes, seconds, x the number\n"
  78. "of the frame in the seconds and z the frame rate used to express the time\n"
  79. "\n"
  80. "-cfg: specifies path to GPAC config file (GPAC.cfg)\n"
  81. "-v: prints version\n"
  82. "-h: prints this message\n"
  83. "\nWritten by Jean Le Feuvre - (c) 2000-2005\n");
  84. }
  85. typedef struct
  86. {
  87. GF_Compositor *sr;
  88. GF_SceneGraph *sg;
  89. GF_BifsDecoder *bifs;
  90. GF_ISOFile *file;
  91. u32 track;
  92. u64 duration, cts;
  93. } BIFSVID;
  94. void node_init(void *cbk, GF_Node *node)
  95. {
  96. BIFSVID *b2v = cbk;
  97. switch (gf_node_get_tag(node)) {
  98. case TAG_MPEG4_Conditional:
  99. case TAG_MPEG4_QuantizationParameter:
  100. break;
  101. default:
  102. if (b2v->sr) gf_sc_on_node_init(b2v->sr, node);
  103. break;
  104. }
  105. }
  106. void node_modif(void *cbk, GF_Node *node)
  107. {
  108. BIFSVID *b2v = cbk;
  109. if (b2v->sr) gf_sc_invalidate(b2v->sr, node);
  110. }
  111. Double get_scene_time(void *cbk)
  112. {
  113. Double res;
  114. BIFSVID *b2v = cbk;
  115. res = (Double) (s64) b2v->cts;
  116. res /= (Double) (s64) b2v->duration;
  117. return res;
  118. }
  119. void write_bmp(GF_VideoSurface *fb, char *rad_name, u32 img_num)
  120. {
  121. char str[GF_MAX_PATH];
  122. BITMAPFILEHEADER fh;
  123. BITMAPINFOHEADER fi;
  124. FILE *fout;
  125. u32 j, i;
  126. char *ptr;
  127. if (img_num<10) {
  128. sprintf(str, "%s_00%d.bmp", rad_name, img_num);
  129. } else if (img_num<100) {
  130. sprintf(str, "%s_0%d.bmp", rad_name, img_num);
  131. } else {
  132. sprintf(str, "%s_%d.bmp", rad_name, img_num);
  133. }
  134. fout = fopen(str, "wb");
  135. if (!fout) return;
  136. memset(&fh, 0, sizeof(fh));
  137. fh.bfType = 19778;
  138. fh.bfOffBits = 14 + 40;
  139. memset(&fi, 0, sizeof(char)*40);
  140. fi.biSize = sizeof(char)*40;
  141. fi.biWidth = fb->width;
  142. fi.biHeight = fb->height;
  143. fi.biPlanes = 1;
  144. fi.biBitCount = 24;
  145. fi.biCompression = BI_RGB;
  146. fi.biSizeImage = fb->pitch * fb->height;
  147. /*NOT ALIGNED!!*/
  148. gf_fwrite(&fh.bfType, 2, 1, fout);
  149. gf_fwrite(&fh.bfSize, 4, 1, fout);
  150. gf_fwrite(&fh.bfReserved1, 2, 1, fout);
  151. gf_fwrite(&fh.bfReserved2, 2, 1, fout);
  152. gf_fwrite(&fh.bfOffBits, 4, 1, fout);
  153. gf_fwrite(&fi, 1, 40, fout);
  154. for (j=fb->height; j>0; j--) {
  155. ptr = fb->video_buffer + (j-1)*fb->pitch;
  156. //gf_fwrite(ptr, 1, fb->width * 3, fout);
  157. for (i=0;i<fb->width; i++) {
  158. fputc(ptr[2], fout);
  159. fputc(ptr[1], fout);
  160. fputc(ptr[0], fout);
  161. ptr+=3;
  162. }
  163. }
  164. fclose(fout);
  165. }
  166. void write_raw(GF_VideoSurface *fb, char *rad_name, u32 img_num)
  167. {
  168. char str[GF_MAX_PATH];
  169. FILE *fout;
  170. if (img_num<10) {
  171. sprintf(str, "%s_00%d.raw", rad_name, img_num);
  172. } else if (img_num<100) {
  173. sprintf(str, "%s_0%d.raw", rad_name, img_num);
  174. } else {
  175. sprintf(str, "%s_%d.raw", rad_name, img_num);
  176. }
  177. fout = fopen(str, "wb");
  178. if (!fout) return;
  179. gf_fwrite(fb->video_buffer , fb->height*fb->pitch, 1, fout);
  180. fclose(fout);
  181. }
  182. void dump_frame(BIFSVID b2v, char *conv_buf, char *out_path, u32 dump_type, avi_t *avi_out, u32 frameNum)
  183. {
  184. u32 k;
  185. GF_VideoSurface fb;
  186. /*lock it*/
  187. gf_sc_get_screen_buffer(b2v.sr, &fb);
  188. /*export frame*/
  189. switch (dump_type) {
  190. case 0:
  191. /*reverse frame*/
  192. for (k=0; k<fb.height; k++) {
  193. memcpy(conv_buf + k*fb.width*3, fb.video_buffer + (fb.height-k-1) * fb.pitch, sizeof(char) * fb.width * 3);
  194. }
  195. if (AVI_write_frame(avi_out, conv_buf, fb.height*fb.width*3, 1) <0)
  196. printf("Error writing frame\n");
  197. break;
  198. case 2:
  199. write_raw(&fb, out_path, frameNum);
  200. break;
  201. case 1:
  202. write_bmp(&fb, out_path, frameNum);
  203. break;
  204. }
  205. /*unlock it*/
  206. gf_sc_release_screen_buffer(b2v.sr, &fb);
  207. }
  208. /*generates an intertwined bmp from a scene file with 5 different viewpoints*/
  209. void bifs3d_viewpoints_merger(GF_ISOFile *file, char *szConfigFile, u32 width, u32 height, char *rad_name, u32 dump_type, char *out_dir, Double fps, s32 frameID, s32 dump_time)
  210. {
  211. GF_User user;
  212. char out_path[GF_MAX_PATH];
  213. char old_driv[1024];
  214. BIFSVID b2v;
  215. Bool needs_raw;
  216. GF_Err e;
  217. GF_VideoSurface fb;
  218. unsigned char **rendered_frames;
  219. u32 nb_viewpoints = 5;
  220. u32 viewpoint_index;
  221. /* Configuration of the Rendering Capabilities */
  222. {
  223. const char *test;
  224. char config_path[GF_MAX_PATH];
  225. memset(&user, 0, sizeof(GF_User));
  226. user.config = gf_cfg_init(szConfigFile, NULL);
  227. if (!user.config) {
  228. fprintf(stdout, "Error: Configuration File \"%s\" not found in %s\n", GPAC_CFG_FILE, config_path);
  229. return;
  230. }
  231. test = gf_cfg_get_key(user.config, "General", "ModulesDirectory");
  232. user.modules = gf_modules_new((const unsigned char *) test, user.config);
  233. strcpy(old_driv, "raw_out");
  234. if (!gf_modules_get_count(user.modules)) {
  235. printf("Error: no modules found\n");
  236. goto err_exit;
  237. }
  238. /*switch driver to raw_driver*/
  239. test = gf_cfg_get_key(user.config, "Video", "DriverName");
  240. if (test) strcpy(old_driv, test);
  241. needs_raw = 0;
  242. test = gf_cfg_get_key(user.config, "Compositor", "RendererName");
  243. /*since we only support RGB24 for MP42AVI force using RAW out with 2D driver*/
  244. if (test && strstr(test, "2D")) {
  245. gf_cfg_set_key(user.config, "Video", "DriverName", "Raw Video Output");
  246. needs_raw = 1;
  247. }
  248. if (needs_raw) {
  249. test = gf_cfg_get_key(user.config, "Video", "DriverName");
  250. if (stricmp(test, "raw_out") && stricmp(test, "Raw Video Output")) {
  251. printf("couldn't load raw output driver (%s used)\n", test);
  252. goto err_exit;
  253. }
  254. }
  255. }
  256. memset(&b2v, 0, sizeof(BIFSVID));
  257. user.init_flags = GF_TERM_NO_AUDIO;
  258. /* Initialization of the compositor */
  259. b2v.sr = gf_sc_new(&user, 0, NULL);
  260. gf_sc_set_option(b2v.sr, GF_OPT_VISIBLE, 0);
  261. /* Initialization of the scene graph */
  262. b2v.sg = gf_sg_new();
  263. gf_sg_set_scene_time_callback(b2v.sg, get_scene_time, &b2v);
  264. gf_sg_set_init_callback(b2v.sg, node_init, &b2v);
  265. gf_sg_set_modified_callback(b2v.sg, node_modif, &b2v);
  266. /*load config*/
  267. gf_sc_set_option(b2v.sr, GF_OPT_RELOAD_CONFIG, 1);
  268. {
  269. u32 di;
  270. u32 track_number;
  271. GF_ESD *esd;
  272. u16 es_id;
  273. b2v.bifs = gf_bifs_decoder_new(b2v.sg, 0);
  274. for (track_number=0; track_number<gf_isom_get_track_count(file); track_number++) {
  275. esd = gf_isom_get_esd(file, track_number+1, 1);
  276. if (!esd) continue;
  277. if (!esd->dependsOnESID && (esd->decoderConfig->streamType == GF_STREAM_SCENE)) break;
  278. gf_odf_desc_del((GF_Descriptor *) esd);
  279. esd = NULL;
  280. }
  281. if (!esd) {
  282. printf("no bifs track found\n");
  283. goto err_exit;
  284. }
  285. es_id = (u16) gf_isom_get_track_id(file, track_number+1);
  286. e = gf_bifs_decoder_configure_stream(b2v.bifs, es_id, esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, esd->decoderConfig->objectTypeIndication);
  287. if (e) {
  288. printf("BIFS init error %s\n", gf_error_to_string(e));
  289. gf_odf_desc_del((GF_Descriptor *) esd);
  290. esd = NULL;
  291. goto err_exit;
  292. }
  293. {
  294. GF_ISOSample *samp = gf_isom_get_sample(file, track_number+1, 1, &di);
  295. b2v.cts = samp->DTS + samp->CTS_Offset;
  296. /*apply command*/
  297. gf_bifs_decode_au(b2v.bifs, es_id, samp->data, samp->dataLength, ((Double)(s64)b2v.cts)/1000.0);
  298. gf_isom_sample_del(&samp);
  299. }
  300. b2v.duration = gf_isom_get_media_duration(file, track_number+1);
  301. gf_odf_desc_del((GF_Descriptor *) esd);
  302. }
  303. gf_sc_set_scene(b2v.sr, b2v.sg);
  304. if (!width || !height) {
  305. gf_sg_get_scene_size_info(b2v.sg, &width, &height);
  306. }
  307. /*we work in RGB24, and we must make sure the pitch is %4*/
  308. if ((width*3)%4) {
  309. printf("Adjusting width (%d) to have a stride multiple of 4\n", width);
  310. while ((width*3)%4) width--;
  311. }
  312. gf_sc_set_size(b2v.sr, width, height);
  313. gf_sc_get_screen_buffer(b2v.sr, &fb);
  314. width = fb.width;
  315. height = fb.height;
  316. gf_sc_release_screen_buffer(b2v.sr, &fb);
  317. GF_SAFEALLOC(rendered_frames, nb_viewpoints*sizeof(char *));
  318. for (viewpoint_index = 1; viewpoint_index <= nb_viewpoints; viewpoint_index++) {
  319. GF_SAFEALLOC(rendered_frames[viewpoint_index-1], fb.width*fb.height*3);
  320. gf_sc_set_viewpoint(b2v.sr, viewpoint_index, NULL);
  321. gf_sc_draw_frame(b2v.sr);
  322. /*needed for background2D !!*/
  323. gf_sc_draw_frame(b2v.sr);
  324. strcpy(out_path, "");
  325. if (out_dir) {
  326. strcat(out_path, out_dir);
  327. if (out_path[strlen(out_path)-1] != '\\') strcat(out_path, "\\");
  328. }
  329. strcat(out_path, rad_name);
  330. strcat(out_path, "_view");
  331. gf_sc_get_screen_buffer(b2v.sr, &fb);
  332. write_bmp(&fb, out_path, viewpoint_index);
  333. memcpy(rendered_frames[viewpoint_index-1], fb.video_buffer, fb.width*fb.height*3);
  334. gf_sc_release_screen_buffer(b2v.sr, &fb);
  335. }
  336. if (width != 800 || height != 480) {
  337. printf("Wrong scene dimension, cannot produce output\n");
  338. goto err_exit;
  339. } else {
  340. u32 x, y;
  341. GF_VideoSurface out_fb;
  342. u32 bpp = 3;
  343. out_fb.width = 800;
  344. out_fb.height = 480;
  345. out_fb.pitch = 800*bpp;
  346. out_fb.pixel_format = GF_PIXEL_RGB_24;
  347. out_fb.is_hardware_memory = 0;
  348. GF_SAFEALLOC(out_fb.video_buffer, out_fb.pitch*out_fb.height)
  349. #if 1
  350. for (y=0; y<out_fb.height; y++) {
  351. /*starting red pixel is R1, R5, R4, R3, R2, R1, R5, ... when increasing line num*/
  352. u32 line_shift = (5-y) % 5;
  353. for (x=0; x<out_fb.width;x++) {
  354. u32 view_shift = (line_shift+bpp*x)%5;
  355. u32 offset = out_fb.pitch*y + x*bpp;
  356. /* red */
  357. out_fb.video_buffer[offset] = rendered_frames[view_shift][offset];
  358. /* green */
  359. out_fb.video_buffer[offset+1] = rendered_frames[(view_shift+1)%5][offset+1];
  360. /* blue */
  361. out_fb.video_buffer[offset+2] = rendered_frames[(view_shift+2)%5][offset+2];
  362. }
  363. }
  364. #else
  365. /*calibration*/
  366. for (y=0; y<out_fb.height; y++) {
  367. u32 line_shift = (5- y%5) % 5;
  368. for (x=0; x<out_fb.width;x++) {
  369. u32 view_shift = (line_shift+bpp*x)%5;
  370. u32 offset = out_fb.pitch*y + x*bpp;
  371. out_fb.video_buffer[offset] = ((view_shift)%5 == 2) ? 0xFF : 0;
  372. out_fb.video_buffer[offset+1] = ((view_shift+1)%5 == 2) ? 0xFF : 0;
  373. out_fb.video_buffer[offset+2] = ((view_shift+2)%5 == 2) ? 0xFF : 0;
  374. }
  375. }
  376. #endif
  377. write_bmp(&out_fb, "output", 0);
  378. }
  379. /*destroy everything*/
  380. gf_bifs_decoder_del(b2v.bifs);
  381. gf_sg_del(b2v.sg);
  382. gf_sc_set_scene(b2v.sr, NULL);
  383. gf_sc_del(b2v.sr);
  384. err_exit:
  385. /* if (rendered_frames) {
  386. for (viewpoint_index = 1; viewpoint_index <= nb_viewpoints; viewpoint_index++) {
  387. if (rendered_frames[viewpoint_index-1]) gf_free(rendered_frames[viewpoint_index-1]);
  388. }
  389. gf_free(rendered_frames);
  390. }
  391. if (output_merged_frame) gf_free(output_merged_frame);
  392. */
  393. if (user.modules) gf_modules_del(user.modules);
  394. if (needs_raw) gf_cfg_set_key(user.config, "Video", "DriverName", old_driv);
  395. gf_cfg_del(user.config);
  396. }
  397. void bifs_to_vid(GF_ISOFile *file, char *szConfigFile, u32 width, u32 height, char *rad_name, u32 dump_type, char *out_dir, Double fps, s32 frameID, s32 dump_time)
  398. {
  399. GF_User user;
  400. BIFSVID b2v;
  401. u16 es_id;
  402. Bool first_dump, needs_raw;
  403. u32 i, j, di, count, timescale, frameNum;
  404. u32 duration, cur_time;
  405. GF_VideoSurface fb;
  406. GF_Err e;
  407. char old_driv[1024];
  408. const char *test;
  409. char config_path[GF_MAX_PATH];
  410. avi_t *avi_out;
  411. Bool reset_fps;
  412. GF_ESD *esd;
  413. char comp[5];
  414. char *conv_buf;
  415. memset(&user, 0, sizeof(GF_User));
  416. if (szConfigFile && strlen(szConfigFile)) {
  417. user.config = gf_cfg_init(config_path, NULL);
  418. } else {
  419. user.config = gf_cfg_init(NULL, NULL);
  420. }
  421. if (!user.config) {
  422. fprintf(stdout, "Error: Configuration File \"%s\" not found in %s\n", GPAC_CFG_FILE, config_path);
  423. return;
  424. }
  425. avi_out = NULL;
  426. conv_buf = NULL;
  427. esd = NULL;
  428. needs_raw = 0;
  429. test = gf_cfg_get_key(user.config, "General", "ModulesDirectory");
  430. user.modules = gf_modules_new((const unsigned char *) test, user.config);
  431. strcpy(old_driv, "raw_out");
  432. if (!gf_modules_get_count(user.modules)) {
  433. printf("Error: no modules found\n");
  434. goto err_exit;
  435. }
  436. /*switch driver to raw_driver*/
  437. test = gf_cfg_get_key(user.config, "Video", "DriverName");
  438. if (test) strcpy(old_driv, test);
  439. test = gf_cfg_get_key(user.config, "Compositor", "RendererName");
  440. /*since we only support RGB24 for MP42AVI force using RAW out with 2D driver*/
  441. if (test && strstr(test, "2D")) {
  442. gf_cfg_set_key(user.config, "Video", "DriverName", "Raw Video Output");
  443. needs_raw = 1;
  444. }
  445. needs_raw = 0;
  446. user.init_flags = GF_TERM_NO_AUDIO | GF_TERM_FORCE_3D;
  447. b2v.sr = gf_sc_new(&user, 0, NULL);
  448. gf_sc_set_option(b2v.sr, GF_OPT_VISIBLE, 0);
  449. b2v.sg = gf_sg_new();
  450. gf_sg_set_scene_time_callback(b2v.sg, get_scene_time, &b2v);
  451. gf_sg_set_init_callback(b2v.sg, node_init, &b2v);
  452. gf_sg_set_modified_callback(b2v.sg, node_modif, &b2v);
  453. /*load config*/
  454. gf_sc_set_option(b2v.sr, GF_OPT_RELOAD_CONFIG, 1);
  455. b2v.bifs = gf_bifs_decoder_new(b2v.sg, 0);
  456. if (needs_raw) {
  457. test = gf_cfg_get_key(user.config, "Video", "DriverName");
  458. if (stricmp(test, "raw_out") && stricmp(test, "Raw Video Output")) {
  459. printf("couldn't load raw output driver (%s used)\n", test);
  460. goto err_exit;
  461. }
  462. }
  463. strcpy(config_path, "");
  464. if (out_dir) {
  465. strcat(config_path, out_dir);
  466. if (config_path[strlen(config_path)-1] != '\\') strcat(config_path, "\\");
  467. }
  468. strcat(config_path, rad_name);
  469. strcat(config_path, "_bifs");
  470. if (!dump_type) {
  471. strcat(config_path, ".avi");
  472. avi_out = AVI_open_output_file(config_path);
  473. comp[0] = comp[1] = comp[2] = comp[3] = comp[4] = 0;
  474. if (!avi_out) goto err_exit;
  475. }
  476. for (i=0; i<gf_isom_get_track_count(file); i++) {
  477. esd = gf_isom_get_esd(file, i+1, 1);
  478. if (!esd) continue;
  479. if (!esd->dependsOnESID && (esd->decoderConfig->streamType == GF_STREAM_SCENE)) break;
  480. gf_odf_desc_del((GF_Descriptor *) esd);
  481. esd = NULL;
  482. }
  483. if (!esd) {
  484. printf("no bifs track found\n");
  485. goto err_exit;
  486. }
  487. b2v.duration = gf_isom_get_media_duration(file, i+1);
  488. timescale = gf_isom_get_media_timescale(file, i+1);
  489. es_id = (u16) gf_isom_get_track_id(file, i+1);
  490. e = gf_bifs_decoder_configure_stream(b2v.bifs, es_id, esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, esd->decoderConfig->objectTypeIndication);
  491. if (e) {
  492. printf("BIFS init error %s\n", gf_error_to_string(e));
  493. gf_odf_desc_del((GF_Descriptor *) esd);
  494. esd = NULL;
  495. goto err_exit;
  496. }
  497. if (dump_time>=0) dump_time = dump_time *1000 / timescale;
  498. gf_sc_set_scene(b2v.sr, b2v.sg);
  499. count = gf_isom_get_sample_count(file, i+1);
  500. reset_fps = 0;
  501. if (!fps) {
  502. fps = (Float) (count * timescale);
  503. fps /= (Double) (s64) b2v.duration;
  504. printf("Estimated BIFS FrameRate %g\n", fps);
  505. reset_fps = 1;
  506. }
  507. if (!width || !height) {
  508. gf_sg_get_scene_size_info(b2v.sg, &width, &height);
  509. }
  510. /*we work in RGB24, and we must make sure the pitch is %4*/
  511. if ((width*3)%4) {
  512. printf("Adjusting width (%d) to have a stride multiple of 4\n", width);
  513. while ((width*3)%4) width--;
  514. }
  515. gf_sc_set_size(b2v.sr, width, height);
  516. gf_sc_draw_frame(b2v.sr);
  517. gf_sc_get_screen_buffer(b2v.sr, &fb);
  518. width = fb.width;
  519. height = fb.height;
  520. if (avi_out) {
  521. AVI_set_video(avi_out, width, height, fps, comp);
  522. conv_buf = gf_malloc(sizeof(char) * width * height * 3);
  523. }
  524. printf("Dumping at BIFS resolution %d x %d\n\n", width, height);
  525. gf_sc_release_screen_buffer(b2v.sr, &fb);
  526. cur_time = 0;
  527. duration = (u32)(timescale / fps);
  528. if (reset_fps) fps = 0;
  529. frameNum = 1;
  530. first_dump = 1;
  531. for (j=0; j<count; j++) {
  532. GF_ISOSample *samp = gf_isom_get_sample(file, i+1, j+1, &di);
  533. b2v.cts = samp->DTS + samp->CTS_Offset;
  534. /*apply command*/
  535. gf_bifs_decode_au(b2v.bifs, es_id, samp->data, samp->dataLength, ((Double)(s64)b2v.cts)/1000.0);
  536. gf_isom_sample_del(&samp);
  537. if ((frameID>=0) && (j<(u32)frameID)) continue;
  538. if ((dump_time>=0) && ((u32) dump_time>b2v.cts)) continue;
  539. /*render frame*/
  540. gf_sc_draw_frame(b2v.sr);
  541. /*needed for background2D !!*/
  542. if (first_dump) {
  543. gf_sc_draw_frame(b2v.sr);
  544. first_dump = 0;
  545. }
  546. if (fps) {
  547. if (cur_time > b2v.cts) continue;
  548. while (1) {
  549. printf("dumped frame time %f (frame %d - sample %d)\r", ((Float)cur_time)/timescale, frameNum, j+1);
  550. dump_frame(b2v, conv_buf, config_path, dump_type, avi_out, frameNum);
  551. frameNum++;
  552. cur_time += duration;
  553. if (cur_time > b2v.cts) break;
  554. }
  555. } else {
  556. dump_frame(b2v, conv_buf, config_path, dump_type, avi_out, (frameID>=0) ? frameID : frameNum);
  557. if (frameID>=0 || dump_time>=0) break;
  558. frameNum++;
  559. printf("dumped frame %d / %d\r", j+1, count);
  560. }
  561. }
  562. gf_odf_desc_del((GF_Descriptor *) esd);
  563. /*destroy everything*/
  564. gf_bifs_decoder_del(b2v.bifs);
  565. gf_sg_del(b2v.sg);
  566. gf_sc_set_scene(b2v.sr, NULL);
  567. gf_sc_del(b2v.sr);
  568. err_exit:
  569. if (avi_out) AVI_close(avi_out);
  570. if (conv_buf) gf_free(conv_buf);
  571. if (user.modules) gf_modules_del(user.modules);
  572. if (needs_raw) gf_cfg_set_key(user.config, "Video", "DriverName", old_driv);
  573. gf_cfg_del(user.config);
  574. }
  575. int main (int argc, char **argv)
  576. {
  577. Double fps_dump;
  578. u32 i;
  579. char rad[500];
  580. s32 frameID, h, m, s, f;
  581. Float fps;
  582. u32 dump_type;
  583. s32 dump_time;
  584. u32 dump_w, dump_h;
  585. Bool copy;
  586. char szConfigFile[4096];
  587. char *dump_out;
  588. char *inName, *arg;
  589. GF_ISOFile *file;
  590. if (argc < 2) {
  591. PrintUsage();
  592. return 0;
  593. }
  594. dump_type = 0;
  595. fps_dump = 0.0f;
  596. dump_w = dump_h = 0;
  597. dump_out = NULL;
  598. inName = NULL;
  599. frameID = -1;
  600. dump_time = -1;
  601. szConfigFile[0] = 0;
  602. for (i = 1; i < (u32) argc ; i++) {
  603. arg = argv[i];
  604. if (arg[0] != '-') {
  605. inName = arg;
  606. break;
  607. }
  608. if (!stricmp(arg, "-h")) {
  609. PrintUsage();
  610. return 0;
  611. } else if (!stricmp(arg, "-version")) {
  612. PrintVersion();
  613. return 0;
  614. } else if (!stricmp(arg, "-size")) {
  615. sscanf(argv[i+1], "%dx%d", &dump_w, &dump_h);
  616. i++;
  617. } else if (!stricmp(arg, "-raw")) {
  618. dump_type = 2;
  619. if ((i+1<(u32)argc) && (argv[i+1][0]!='-')) {
  620. if (strstr(argv[i+1], "T")) {
  621. if (strstr(argv[i+1], "F")) {
  622. sscanf(argv[i+1], "T%d:%d:%d:%dF%f", &h, &m, &s, &f, &fps);
  623. dump_time = (s32) ((3600*h + 60*m + s)*1000 + 1000*f/fps);
  624. } else {
  625. sscanf(argv[i+1], "T%d:%d:%d", &h, &m, &s);
  626. dump_time = (s32) ((3600*h + 60*m + s)*1000);
  627. }
  628. } else {
  629. frameID = atoi(argv[i+1]);
  630. }
  631. i++;
  632. }
  633. } else if (!stricmp(arg, "-bmp")) {
  634. dump_type = 1;
  635. if ((i+1<(u32)argc) && (argv[i+1][0]!='-')) {
  636. if (strstr(argv[i+1], "T")) {
  637. if (strstr(argv[i+1], "F")) {
  638. sscanf(argv[i+1], "T%d:%d:%d:%dF%f", &h, &m, &s, &f, &fps);
  639. dump_time = (s32) ((3600*h + 60*m + s)*1000 + 1000*f/fps);
  640. } else {
  641. sscanf(argv[i+1], "T%d:%d:%d", &h, &m, &s);
  642. dump_time = (s32) ((3600*h + 60*m + s)*1000);
  643. }
  644. } else {
  645. frameID = atoi(argv[i+1]);
  646. }
  647. i++;
  648. }
  649. } else if (!stricmp(arg, "-3d")) {
  650. dump_type = 3;
  651. } else if (!stricmp(arg, "-outpath")) {
  652. dump_out = argv[i+1];
  653. i++;
  654. } else if (!stricmp(arg, "-fps")) {
  655. fps_dump = atof(argv[i+1]);
  656. i++;
  657. } else if (!stricmp(arg, "-copy")) {
  658. copy = 1;
  659. } else if (!stricmp(arg, "-cfg")) {
  660. strcpy(szConfigFile, argv[i+1]);
  661. i += 1;
  662. } else {
  663. PrintUsage();
  664. return (0);
  665. }
  666. }
  667. if (!inName) {
  668. PrintUsage();
  669. return 0;
  670. }
  671. gf_sys_init();
  672. file = gf_isom_open(inName, GF_ISOM_OPEN_READ, NULL);
  673. if (!file) {
  674. printf("Error opening file: %s\n", gf_error_to_string(gf_isom_last_error(NULL)));
  675. return 0;
  676. }
  677. if (dump_out) {
  678. arg = strrchr(inName, GF_PATH_SEPARATOR);
  679. if (arg) {
  680. strcpy(rad, arg + 1);
  681. } else {
  682. strcpy(rad, inName);
  683. }
  684. } else {
  685. strcpy(rad, inName);
  686. }
  687. while (rad[strlen(rad)-1] != '.') rad[strlen(rad)-1] = 0;
  688. rad[strlen(rad)-1] = 0;
  689. if (dump_type == 3) {
  690. bifs3d_viewpoints_merger(file, szConfigFile, dump_w, dump_h, rad, dump_type, dump_out, fps_dump, frameID, dump_time);
  691. }
  692. else bifs_to_vid(file, szConfigFile, dump_w, dump_h, rad, dump_type, dump_out, fps_dump, frameID, dump_time);
  693. printf("\ndone\n");
  694. gf_isom_delete(file);
  695. return 0;
  696. }