📄 main.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / command-line mp4 toolbox * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <gpac/isomedia.h>#include <gpac/renderer.h>#include <gpac/scenegraph.h>#include <gpac/bifs.h>#include <gpac/options.h>#ifdef WIN32#include <windows.h>#define GPAC_CFG_FILE "GPAC.cfg"#else#include <pwd.h>typedef struct tagBITMAPFILEHEADER { u16 bfType; u32 bfSize; u16 bfReserved1; u16 bfReserved2; u32 bfOffBits;} BITMAPFILEHEADER;typedef struct tagBITMAPINFOHEADER{ u32 biSize; s32 biWidth; s32 biHeight; u16 biPlanes; u16 biBitCount; u32 biCompression; u32 biSizeImage; s32 biXPelsPerMeter; s32 biYPelsPerMeter; u32 biClrUsed; u32 biClrImportant;} BITMAPINFOHEADER;#define BI_RGB 0L#define GPAC_CFG_FILE ".gpacrc"#endif#include <gpac/internal/avilib.h>#include <gpac/internal/renderer_dev.h>void PrintVersion(){ printf ("MP42AVI - GPAC version %s\n", GPAC_VERSION);}void PrintUsage(){ printf ("MP42AVI [option] input\n" "Dumps BIFS media frames as AVI, BMP or raw\n\n" "Options\n" "-fps Framerate: specifies extraction framerate - if not set computed from track length\n" "-size WxH: forces output BIFS to the given resolution\n" "-raw [frame]: uses raw format for output - only dumps one frame if specified\n" "-bmp [frame]: uses BMP format for output - only dumps one frame if specified\n" "-outpath path: specifies where to dump frames/movie\n" "\n" "Note: when dumping a frame, either the frame number can be specified or the frame time\n" "in the format hh:mm:ss:xFz where hh, mm, ss are hours, minutes, seconds, x the number\n" "of the frame in the seconds and z the frame rate used to express the time\n" "\n" "-cfg: specifies path to GPAC config file (GPAC.cfg)\n" "-v: prints version\n" "-h: prints this message\n" "\nWritten by Jean Le Feuvre - (c) 2000-2005\n");}typedef struct { GF_Renderer *sr; GF_SceneGraph *sg; GF_BifsDecoder *bifs; GF_ISOFile *file; u32 track; u64 duration, cts;} BIFSVID;void node_init(void *cbk, GF_Node *node){ BIFSVID *b2v = cbk; switch (gf_node_get_tag(node)) { case TAG_MPEG4_Conditional: case TAG_MPEG4_QuantizationParameter: break; default: if (b2v->sr) gf_sr_on_node_init(b2v->sr, node); break; }}void node_modif(void *cbk, GF_Node *node){ BIFSVID *b2v = cbk; if (b2v->sr) gf_sr_invalidate(b2v->sr, node);}Double get_scene_time(void *cbk){ Double res; BIFSVID *b2v = cbk; res = (Double) (s64) b2v->cts; res /= (Double) (s64) b2v->duration; return res;}void write_bmp(GF_VideoSurface *fb, char *rad_name, u32 img_num){ char str[GF_MAX_PATH]; BITMAPFILEHEADER fh; BITMAPINFOHEADER fi; FILE *fout; u32 j, i; char *ptr; if (img_num<10) { sprintf(str, "%s_00%d.bmp", rad_name, img_num); } else if (img_num<100) { sprintf(str, "%s_0%d.bmp", rad_name, img_num); } else { sprintf(str, "%s_%d.bmp", rad_name, img_num); } fout = fopen(str, "wb"); if (!fout) return; memset(&fh, 0, sizeof(fh)); fh.bfType = 19778; fh.bfOffBits = 14 + 40; memset(&fi, 0, sizeof(char)*40); fi.biSize = sizeof(char)*40; fi.biWidth = fb->width; fi.biHeight = fb->height; fi.biPlanes = 1; fi.biBitCount = 24; fi.biCompression = BI_RGB; fi.biSizeImage = fb->pitch * fb->height; /*NOT ALIGNED!!*/ fwrite(&fh.bfType, 2, 1, fout); fwrite(&fh.bfSize, 4, 1, fout); fwrite(&fh.bfReserved1, 2, 1, fout); fwrite(&fh.bfReserved2, 2, 1, fout); fwrite(&fh.bfOffBits, 4, 1, fout); fwrite(&fi, 1, 40, fout); for (j=fb->height; j>0; j--) { ptr = fb->video_buffer + (j-1)*fb->pitch; //fwrite(ptr, 1, fb->width * 3, fout); for (i=0;i<fb->width; i++) { fputc(ptr[2], fout); fputc(ptr[1], fout); fputc(ptr[0], fout); ptr+=3; } } fclose(fout);}void write_raw(GF_VideoSurface *fb, char *rad_name, u32 img_num){ char str[GF_MAX_PATH]; FILE *fout; if (img_num<10) { sprintf(str, "%s_00%d.raw", rad_name, img_num); } else if (img_num<100) { sprintf(str, "%s_0%d.raw", rad_name, img_num); } else { sprintf(str, "%s_%d.raw", rad_name, img_num); } fout = fopen(str, "wb"); if (!fout) return; fwrite(fb->video_buffer , fb->height*fb->pitch, 1, fout); fclose(fout);}void dump_frame(BIFSVID b2v, char *conv_buf, char *out_path, u32 dump_type, avi_t *avi_out, u32 frameNum){ u32 k; GF_VideoSurface fb; /*lock it*/ gf_sr_get_screen_buffer(b2v.sr, &fb); /*export frame*/ switch (dump_type) { case 0: /*reverse frame*/ for (k=0; k<fb.height; k++) { memcpy(conv_buf + k*fb.width*3, fb.video_buffer + (fb.height-k-1) * fb.pitch, sizeof(char) * fb.width * 3); } if (AVI_write_frame(avi_out, conv_buf, fb.height*fb.width*3, 1) <0) printf("Error writing frame\n"); break; case 2: write_raw(&fb, out_path, frameNum); break; case 1: write_bmp(&fb, out_path, frameNum); break; } /*unlock it*/ gf_sr_release_screen_buffer(b2v.sr, &fb);}GF_Config *loadconfigfile(){ GF_Config *cfg; char *cfg_dir; char szPath[GF_MAX_PATH];#ifdef WIN32 GetModuleFileNameA(NULL, szPath, GF_MAX_PATH); cfg_dir = strrchr(szPath, '\\'); if (cfg_dir) cfg_dir[1] = 0; cfg = gf_cfg_new(szPath, "GPAC.cfg"); if (cfg) goto success;#ifdef _DEBUG strcpy(szPath, "C:\\Users\\Cyril\\sourceforge\\gpac\\bin\\w32_deb\\");#else strcpy(szPath, "C:\\Users\\Cyril\\sourceforge\\gpac\\bin\\w32_rel\\");#endif cfg = gf_cfg_new(szPath, "GPAC.cfg"); if (cfg) goto success; strcpy(szPath, "."); cfg = gf_cfg_new(szPath, "GPAC.cfg"); if (cfg) goto success; strcpy(szPath, "C:\\Program Files\\GPAC"); cfg = gf_cfg_new(szPath, "GPAC.cfg"); if (cfg) goto success; strcpy(szPath, "."); cfg = gf_cfg_new(szPath, "GPAC.cfg");#else /*linux*/ cfg_dir = getenv("HOME"); if (cfg_dir) { strcpy(szPath, cfg_dir); } else { fprintf(stdout, "WARNING: HOME env var not set - using current directory for config file\n"); strcpy(szPath, "."); } cfg = gf_cfg_new(szPath, ".gpacrc"); if (cfg) goto success;#endif if (!cfg) { fprintf(stdout, "cannot create config file in %s directory\n", szPath); return NULL; } success: fprintf(stdout, "Using config file in %s directory\n", szPath); return cfg;}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){ GF_User user; char out_path[GF_MAX_PATH]; char old_driv[1024]; BIFSVID b2v; Bool needs_raw; GF_Err e; GF_VideoSurface fb; unsigned char **rendered_frames; u32 nb_viewpoints = 5; u32 viewpoint_index; /* Configuration of the Rendering Capabilities */ { const char *test; char config_path[GF_MAX_PATH]; memset(&user, 0, sizeof(GF_User)); if (szConfigFile && strlen(szConfigFile)) { user.config = gf_cfg_new(config_path, GPAC_CFG_FILE); } else { user.config = loadconfigfile(); } if (!user.config) { fprintf(stdout, "Configuration File \"GPAC.cfg\" not found\nPlease enter full path to config file:\n"); scanf("%s", config_path); user.config = gf_cfg_new(config_path, GPAC_CFG_FILE); if (!user.config) { fprintf(stdout, "Error: Configuration File \"%s\" not found in %s\n", GPAC_CFG_FILE, config_path); return; } } test = gf_cfg_get_key(user.config, "General", "ModulesDirectory"); user.modules = gf_modules_new((const unsigned char *) test, user.config); strcpy(old_driv, "raw_out"); if (!gf_modules_get_count(user.modules)) { printf("Error: no modules found\n"); goto err_exit; } /*switch driver to raw_driver*/ test = gf_cfg_get_key(user.config, "Video", "DriverName"); if (test) strcpy(old_driv, test); needs_raw = 0; test = gf_cfg_get_key(user.config, "Rendering", "RendererName"); /*since we only support RGB24 for MP42AVI force using RAW out with 2D driver*/ if (test && strstr(test, "2D")) { gf_cfg_set_key(user.config, "Video", "DriverName", "Raw Video Output"); needs_raw = 1; } if (needs_raw) { test = gf_cfg_get_key(user.config, "Video", "DriverName"); if (stricmp(test, "raw_out") && stricmp(test, "Raw Video Output")) { printf("couldn't load raw output driver (%s used)\n", test); goto err_exit; } } } memset(&b2v, 0, sizeof(BIFSVID)); user.init_flags = GF_TERM_NO_AUDIO; /* Initialization of the renderer */ b2v.sr = gf_sr_new(&user, 0, NULL); gf_sr_set_option(b2v.sr, GF_OPT_VISIBLE, 0); /* Initialization of the scene graph */ b2v.sg = gf_sg_new(); gf_sg_set_scene_time_callback(b2v.sg, get_scene_time, &b2v); gf_sg_set_init_callback(b2v.sg, node_init, &b2v); gf_sg_set_modified_callback(b2v.sg, node_modif, &b2v); /*load config*/ gf_sr_set_option(b2v.sr, GF_OPT_RELOAD_CONFIG, 1); { u32 di; u32 track_number; GF_ESD *esd; u16 es_id; b2v.bifs = gf_bifs_decoder_new(b2v.sg, 0); for (track_number=0; track_number<gf_isom_get_track_count(file); track_number++) { esd = gf_isom_get_esd(file, track_number+1, 1); if (!esd) continue; if (!esd->dependsOnESID && (esd->decoderConfig->streamType == GF_STREAM_SCENE)) break; gf_odf_desc_del((GF_Descriptor *) esd); esd = NULL; } if (!esd) { printf("no bifs track found\n"); goto err_exit; } es_id = (u16) gf_isom_get_track_id(file, track_number+1); e = gf_bifs_decoder_configure_stream(b2v.bifs, es_id, esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, esd->decoderConfig->objectTypeIndication); if (e) { printf("BIFS init error %s\n", gf_error_to_string(e)); gf_odf_desc_del((GF_Descriptor *) esd); esd = NULL; goto err_exit; } { GF_ISOSample *samp = gf_isom_get_sample(file, track_number+1, 1, &di); b2v.cts = samp->DTS + samp->CTS_Offset; /*apply command*/ gf_bifs_decode_au(b2v.bifs, es_id, samp->data, samp->dataLength, ((Double)(s64)b2v.cts)/1000.0); gf_isom_sample_del(&samp); } b2v.duration = gf_isom_get_media_duration(file, track_number+1); gf_odf_desc_del((GF_Descriptor *) esd); } gf_sr_set_scene(b2v.sr, b2v.sg); if (!width || !height) { gf_sg_get_scene_size_info(b2v.sg, &width, &height); } /*we work in RGB24, and we must make sure the pitch is %4*/ if ((width*3)%4) { printf("Adjusting width (%d) to have a stride multiple of 4\n", width); while ((width*3)%4) width--; } gf_sr_set_size(b2v.sr, width, height); gf_sr_get_screen_buffer(b2v.sr, &fb); width = fb.width; height = fb.height; gf_sr_release_screen_buffer(b2v.sr, &fb); GF_SAFEALLOC(rendered_frames, nb_viewpoints*sizeof(char *)); for (viewpoint_index = 1; viewpoint_index <= nb_viewpoints; viewpoint_index++) { GF_SAFEALLOC(rendered_frames[viewpoint_index-1], fb.width*fb.height*3);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -