void V4SceneGraph::GetSceneSize(wxSize &size) { gf_sg_get_scene_size_info(m_pSg, (u32 *)&(size.x), (u32 *)&(size.y)); }
GF_EXPORT GF_Err gf_term_get_object_info(GF_Terminal *term, GF_ObjectManager *odm, GF_MediaInfo *info) { GF_Channel *ch; if (!term || !odm || !odm->OD || !info) return GF_BAD_PARAM; if (!gf_term_check_odm(term, odm)) return GF_BAD_PARAM; memset(info, 0, sizeof(GF_MediaInfo)); info->od = odm->OD; info->duration = (Double) (s64)odm->duration; info->duration /= 1000; if (odm->codec) { /*since we don't remove ODs that failed setup, check for clock*/ if (odm->codec->ck) info->current_time = odm->codec->CB ? odm->current_time : gf_clock_time(odm->codec->ck); info->current_time /= 1000; info->nb_droped = odm->codec->nb_droped; } else if (odm->subscene) { if (odm->subscene->scene_codec) { if (odm->subscene->scene_codec->ck) { info->current_time = gf_clock_time(odm->subscene->scene_codec->ck); info->current_time /= 1000; } info->duration = (Double) (s64)odm->subscene->duration; info->duration /= 1000; info->nb_droped = odm->subscene->scene_codec->nb_droped; } else if (odm->subscene->is_dynamic_scene && odm->subscene->dyn_ck) { info->current_time = gf_clock_time(odm->subscene->dyn_ck); info->current_time /= 1000; } } info->buffer = -2; info->db_unit_count = 0; /*Warning: is_open==2 means object setup, don't check then*/ if (odm->state==GF_ODM_STATE_IN_SETUP) { info->status = 3; } else if (odm->state==GF_ODM_STATE_BLOCKED) { info->status = 0; info->protection = 2; } else if (odm->state) { u32 i, buf; GF_Clock *ck; ck = gf_odm_get_media_clock(odm); /*no clock means setup failed*/ if (!ck) { info->status = 4; } else { info->status = gf_clock_is_started(ck) ? 1 : 2; info->clock_drift = ck->drift; info->buffer = -1; buf = 0; i=0; while ((ch = (GF_Channel*)gf_list_enum(odm->channels, &i))) { info->db_unit_count += ch->AU_Count; if (!ch->is_pulling) { if (ch->MaxBuffer) info->buffer = 0; buf += ch->BufferTime; } if (ch->is_protected) info->protection = ch->ipmp_tool ? 1 : 2; } if (buf) info->buffer = (s32) buf; } } info->has_profiles = (odm->flags & GF_ODM_HAS_PROFILES) ? 1 : 0; if (info->has_profiles) { info->inline_pl = (odm->flags & GF_ODM_INLINE_PROFILES) ? 1 : 0; info->OD_pl = odm->OD_PL; info->scene_pl = odm->Scene_PL; info->audio_pl = odm->Audio_PL; info->visual_pl = odm->Visual_PL; info->graphics_pl = odm->Graphics_PL; } if (odm->net_service) { info->service_handler = odm->net_service->ifce->module_name; info->service_url = odm->net_service->url; if (odm->net_service->owner == odm) info->owns_service = 1; } else if ((odm->subscene && odm->subscene->graph_attached) || (odm->codec)) { info->service_url = "No associated network Service"; } else { info->service_url = "Service not found or error"; } if (odm->codec && odm->codec->decio) { if (!odm->codec->decio->GetName) { info->codec_name = odm->codec->decio->module_name; } else { info->codec_name = odm->codec->decio->GetName(odm->codec->decio); } info->od_type = odm->codec->type; if (odm->codec->CB) { info->cb_max_count = odm->codec->CB->Capacity; info->cb_unit_count = odm->codec->CB->UnitCount; } } if (odm->subscene && odm->subscene->scene_codec) { GF_BaseDecoder *dec = odm->subscene->scene_codec->decio; assert(odm->subscene->root_od==odm) ; info->od_type = odm->subscene->scene_codec->type; if (!dec->GetName) { info->codec_name = dec->module_name; } else { info->codec_name = dec->GetName(dec); } gf_sg_get_scene_size_info(odm->subscene->graph, &info->width, &info->height); } else if (odm->mo) { switch (info->od_type) { case GF_STREAM_VISUAL: gf_mo_get_visual_info(odm->mo, &info->width, &info->height, NULL, &info->par, &info->pixelFormat, NULL); break; case GF_STREAM_AUDIO: gf_mo_get_audio_info(odm->mo, &info->sample_rate, &info->bits_per_sample, &info->num_channels, NULL); info->clock_drift = 0; break; case GF_STREAM_TEXT: gf_mo_get_visual_info(odm->mo, &info->width, &info->height, NULL, NULL, NULL, NULL); break; } } if (odm->subscene && odm->subscene->scene_codec) get_codec_stats(odm->subscene->scene_codec, info); else if (odm->codec) get_codec_stats(odm->codec, info); ch = (GF_Channel*)gf_list_get(odm->channels, 0); if (ch && ch->esd->langDesc) info->lang = ch->esd->langDesc->langCode; if (odm->mo && odm->mo->URLs.count) info->media_url = odm->mo->URLs.vals[0].url; return GF_OK; }
void V4SceneManager::GetSceneSize(wxSize &size) { gf_sg_get_scene_size_info(m_pIs->graph, (u32 *)&(size.x), (u32 *)&(size.y)); }
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) { GF_User user; BIFSVID b2v; u16 es_id; Bool first_dump, needs_raw; u32 i, j, di, count, timescale, frameNum; u32 duration, cur_time; GF_VideoSurface fb; GF_Err e; char old_driv[1024]; const char *test; char config_path[GF_MAX_PATH]; avi_t *avi_out; Bool reset_fps; GF_ESD *esd; char comp[5]; char *conv_buf; memset(&user, 0, sizeof(GF_User)); if (szConfigFile && strlen(szConfigFile)) { user.config = gf_cfg_init(config_path, NULL); } else { user.config = gf_cfg_init(NULL, NULL); } if (!user.config) { fprintf(stdout, "Error: Configuration File \"%s\" not found in %s\n", GPAC_CFG_FILE, config_path); return; } avi_out = NULL; conv_buf = NULL; esd = NULL; needs_raw = 0; 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); test = gf_cfg_get_key(user.config, "Compositor", "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; } needs_raw = 0; user.init_flags = GF_TERM_NO_AUDIO | GF_TERM_FORCE_3D; b2v.sr = gf_sc_new(&user, 0, NULL); gf_sc_set_option(b2v.sr, GF_OPT_VISIBLE, 0); 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_sc_set_option(b2v.sr, GF_OPT_RELOAD_CONFIG, 1); b2v.bifs = gf_bifs_decoder_new(b2v.sg, 0); 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; } } strcpy(config_path, ""); if (out_dir) { strcat(config_path, out_dir); if (config_path[strlen(config_path)-1] != '\\') strcat(config_path, "\\"); } strcat(config_path, rad_name); strcat(config_path, "_bifs"); if (!dump_type) { strcat(config_path, ".avi"); avi_out = AVI_open_output_file(config_path); comp[0] = comp[1] = comp[2] = comp[3] = comp[4] = 0; if (!avi_out) goto err_exit; } for (i=0; i<gf_isom_get_track_count(file); i++) { esd = gf_isom_get_esd(file, i+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; } b2v.duration = gf_isom_get_media_duration(file, i+1); timescale = gf_isom_get_media_timescale(file, i+1); es_id = (u16) gf_isom_get_track_id(file, i+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; } if (dump_time>=0) dump_time = dump_time *1000 / timescale; gf_sc_set_scene(b2v.sr, b2v.sg); count = gf_isom_get_sample_count(file, i+1); reset_fps = 0; if (!fps) { fps = (Float) (count * timescale); fps /= (Double) (s64) b2v.duration; printf("Estimated BIFS FrameRate %g\n", fps); reset_fps = 1; } 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_sc_set_size(b2v.sr, width, height); gf_sc_draw_frame(b2v.sr); gf_sc_get_screen_buffer(b2v.sr, &fb); width = fb.width; height = fb.height; if (avi_out) { AVI_set_video(avi_out, width, height, fps, comp); conv_buf = gf_malloc(sizeof(char) * width * height * 3); } printf("Dumping at BIFS resolution %d x %d\n\n", width, height); gf_sc_release_screen_buffer(b2v.sr, &fb); cur_time = 0; duration = (u32)(timescale / fps); if (reset_fps) fps = 0; frameNum = 1; first_dump = 1; for (j=0; j<count; j++) { GF_ISOSample *samp = gf_isom_get_sample(file, i+1, j+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); if ((frameID>=0) && (j<(u32)frameID)) continue; if ((dump_time>=0) && ((u32) dump_time>b2v.cts)) continue; /*render frame*/ gf_sc_draw_frame(b2v.sr); /*needed for background2D !!*/ if (first_dump) { gf_sc_draw_frame(b2v.sr); first_dump = 0; } if (fps) { if (cur_time > b2v.cts) continue; while (1) { printf("dumped frame time %f (frame %d - sample %d)\r", ((Float)cur_time)/timescale, frameNum, j+1); dump_frame(b2v, conv_buf, config_path, dump_type, avi_out, frameNum); frameNum++; cur_time += duration; if (cur_time > b2v.cts) break; } } else { dump_frame(b2v, conv_buf, config_path, dump_type, avi_out, (frameID>=0) ? frameID : frameNum); if (frameID>=0 || dump_time>=0) break; frameNum++; printf("dumped frame %d / %d\r", j+1, count); } } gf_odf_desc_del((GF_Descriptor *) esd); /*destroy everything*/ gf_bifs_decoder_del(b2v.bifs); gf_sg_del(b2v.sg); gf_sc_set_scene(b2v.sr, NULL); gf_sc_del(b2v.sr); err_exit: if (avi_out) AVI_close(avi_out); if (conv_buf) gf_free(conv_buf); if (user.modules) gf_modules_del(user.modules); if (needs_raw) gf_cfg_set_key(user.config, "Video", "DriverName", old_driv); gf_cfg_del(user.config); }
/*generates an intertwined bmp from a scene file with 5 different viewpoints*/ 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)); user.config = gf_cfg_init(szConfigFile, NULL); 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, "Compositor", "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 compositor */ b2v.sr = gf_sc_new(&user, 0, NULL); gf_sc_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_sc_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_sc_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_sc_set_size(b2v.sr, width, height); gf_sc_get_screen_buffer(b2v.sr, &fb); width = fb.width; height = fb.height; gf_sc_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); gf_sc_set_viewpoint(b2v.sr, viewpoint_index, NULL); gf_sc_draw_frame(b2v.sr); /*needed for background2D !!*/ gf_sc_draw_frame(b2v.sr); strcpy(out_path, ""); if (out_dir) { strcat(out_path, out_dir); if (out_path[strlen(out_path)-1] != '\\') strcat(out_path, "\\"); } strcat(out_path, rad_name); strcat(out_path, "_view"); gf_sc_get_screen_buffer(b2v.sr, &fb); write_bmp(&fb, out_path, viewpoint_index); memcpy(rendered_frames[viewpoint_index-1], fb.video_buffer, fb.width*fb.height*3); gf_sc_release_screen_buffer(b2v.sr, &fb); } if (width != 800 || height != 480) { printf("Wrong scene dimension, cannot produce output\n"); goto err_exit; } else { u32 x, y; GF_VideoSurface out_fb; u32 bpp = 3; out_fb.width = 800; out_fb.height = 480; out_fb.pitch = 800*bpp; out_fb.pixel_format = GF_PIXEL_RGB_24; out_fb.is_hardware_memory = 0; GF_SAFEALLOC(out_fb.video_buffer, out_fb.pitch*out_fb.height) #if 1 for (y=0; y<out_fb.height; y++) { /*starting red pixel is R1, R5, R4, R3, R2, R1, R5, ... when increasing line num*/ u32 line_shift = (5-y) % 5; for (x=0; x<out_fb.width; x++) { u32 view_shift = (line_shift+bpp*x)%5; u32 offset = out_fb.pitch*y + x*bpp; /* red */ out_fb.video_buffer[offset] = rendered_frames[view_shift][offset]; /* green */ out_fb.video_buffer[offset+1] = rendered_frames[(view_shift+1)%5][offset+1]; /* blue */ out_fb.video_buffer[offset+2] = rendered_frames[(view_shift+2)%5][offset+2]; } } #else /*calibration*/ for (y=0; y<out_fb.height; y++) { u32 line_shift = (5- y%5) % 5; for (x=0; x<out_fb.width; x++) { u32 view_shift = (line_shift+bpp*x)%5; u32 offset = out_fb.pitch*y + x*bpp; out_fb.video_buffer[offset] = ((view_shift)%5 == 2) ? 0xFF : 0; out_fb.video_buffer[offset+1] = ((view_shift+1)%5 == 2) ? 0xFF : 0; out_fb.video_buffer[offset+2] = ((view_shift+2)%5 == 2) ? 0xFF : 0; } } #endif write_bmp(&out_fb, "output", 0); } /*destroy everything*/ gf_bifs_decoder_del(b2v.bifs); gf_sg_del(b2v.sg); gf_sc_set_scene(b2v.sr, NULL); gf_sc_del(b2v.sr); err_exit: /* if (rendered_frames) { for (viewpoint_index = 1; viewpoint_index <= nb_viewpoints; viewpoint_index++) { if (rendered_frames[viewpoint_index-1]) gf_free(rendered_frames[viewpoint_index-1]); } gf_free(rendered_frames); } if (output_merged_frame) gf_free(output_merged_frame); */ if (user.modules) gf_modules_del(user.modules); if (needs_raw) gf_cfg_set_key(user.config, "Video", "DriverName", old_driv); gf_cfg_del(user.config); }
/*the WORST thing about 3GP in MPEG4 is positioning of the text track...*/ static void TTD_UpdateSizeInfo(TTDPriv *priv) { u32 w, h; Bool has_size; s32 offset, thw, thh, vw, vh; has_size = gf_sg_get_scene_size_info(priv->inlineScene->graph, &w, &h); /*no size info is given in main scene, override by associated video size if any, or by text track size*/ if (!has_size) { if (priv->cfg->has_vid_info && priv->cfg->video_width && priv->cfg->video_height) { gf_sg_set_scene_size_info(priv->sg, priv->cfg->video_width, priv->cfg->video_height, 1); } else { gf_sg_set_scene_size_info(priv->sg, priv->cfg->text_width, priv->cfg->text_height, 1); } gf_sg_get_scene_size_info(priv->sg, &w, &h); if (!w || !h) return; gf_scene_force_size(priv->inlineScene, w, h); } if (!w || !h) return; /*apply*/ gf_sg_set_scene_size_info(priv->sg, w, h, 1); /*make sure the scene size is big enough to contain the text track after positioning. RESULTS ARE UNDEFINED if offsets are negative: since MPEG-4 uses centered coord system, we must assume video is aligned to top-left*/ if (priv->cfg->has_vid_info) { Bool set_size = 0; vw = priv->cfg->horiz_offset; if (vw<0) vw = 0; vh = priv->cfg->vert_offset; if (vh<0) vh = 0; if (priv->cfg->text_width + (u32) vw > w) { w = priv->cfg->text_width+vw; set_size = 1; } if (priv->cfg->text_height + (u32) vh > h) { h = priv->cfg->text_height+vh; set_size = 1; } if (set_size) { gf_sg_set_scene_size_info(priv->sg, w, h, 1); gf_scene_force_size(priv->inlineScene, w, h); } } else { /*otherwise override (mainly used for SRT & TTXT file direct loading*/ priv->cfg->text_width = w; priv->cfg->text_height = h; } /*ok override video size with main scene size*/ priv->cfg->video_width = w; priv->cfg->video_height = h; vw = (s32) w; vh = (s32) h; thw = priv->cfg->text_width / 2; thh = priv->cfg->text_height / 2; /*check translation, we must not get out of scene size - not supported in GPAC*/ offset = priv->cfg->horiz_offset - vw/2 + thw; /*safety checks ? if (offset + thw < - vw/2) offset = - vw/2 + thw; else if (offset - thw > vw/2) offset = vw/2 - thw; */ priv->tr_track->translation.x = INT2FIX(offset); offset = vh/2 - priv->cfg->vert_offset - thh; /*safety checks ? if (offset + thh > vh/2) offset = vh/2 - thh; else if (offset - thh < -vh/2) offset = -vh/2 + thh; */ priv->tr_track->translation.y = INT2FIX(offset); gf_node_changed((GF_Node *)priv->tr_track, NULL); }
GF_Err gf_sr_set_scene(GF_Renderer *sr, GF_SceneGraph *scene_graph) { u32 width, height; Bool do_notif; if (!sr) return GF_BAD_PARAM; gf_sr_lock(sr, 1); GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, (scene_graph ? "[Render] Attaching new scene\n" : "[Render] Detaching scene\n")); if (sr->audio_renderer && (sr->scene != scene_graph)) { GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render] Reseting audio render\n")); gf_sr_ar_reset(sr->audio_renderer); } #ifdef GF_SR_EVENT_QUEUE GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render] Reseting event queue\n")); gf_mx_p(sr->ev_mx); while (gf_list_count(sr->events)) { GF_Event *ev = (GF_Event*)gf_list_get(sr->events, 0); gf_list_rem(sr->events, 0); free(ev); } #endif GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render] Reseting render module\n")); /*reset main surface*/ sr->visual_renderer->SceneReset(sr->visual_renderer); /*set current graph*/ sr->scene = scene_graph; do_notif = 0; if (scene_graph) { #ifndef GPAC_DISABLE_SVG SVG_Length *w, *h; #endif const char *opt; Bool is_svg = 0; u32 tag; GF_Node *top_node; Bool had_size_info = sr->has_size_info; /*get pixel size if any*/ gf_sg_get_scene_size_info(sr->scene, &width, &height); sr->has_size_info = (width && height) ? 1 : 0; if (sr->has_size_info != had_size_info) sr->scene_width = sr->scene_height = 0; /*default back color is black*/ if (! (sr->user->init_flags & GF_TERM_WINDOWLESS)) sr->back_color = 0xFF000000; top_node = gf_sg_get_root_node(sr->scene); tag = 0; if (top_node) tag = gf_node_get_tag(top_node); #ifndef GPAC_DISABLE_SVG w = h = NULL; if ((tag>=GF_NODE_RANGE_FIRST_SVG) && (tag<=GF_NODE_RANGE_LAST_SVG)) { GF_FieldInfo info; is_svg = 1; if (gf_svg_get_attribute_by_tag(top_node, TAG_SVG_ATT_width, 0, 0, &info)==GF_OK) w = info.far_ptr; if (gf_svg_get_attribute_by_tag(top_node, TAG_SVG_ATT_height, 0, 0, &info)==GF_OK) h = info.far_ptr; } #ifdef GPAC_ENABLE_SVG_SA else if ((tag>=GF_NODE_RANGE_FIRST_SVG_SA) && (tag<=GF_NODE_RANGE_LAST_SVG_SA)) { SVG_SA_svgElement *root = (SVG_SA_svgElement *) top_node; is_svg = 1; w = &root->width; h = &root->height; } #endif #ifdef GPAC_ENABLE_SVG_SANI else if ((tag>=GF_NODE_RANGE_FIRST_SVG_SANI) && (tag<=GF_NODE_RANGE_LAST_SVG_SANI)) { SVG_SANI_svgElement *root = (SVG_SANI_svgElement*) top_node; is_svg = 1; w = &root->width; h = &root->height; } #endif /*default back color is white*/ if (is_svg && ! (sr->user->init_flags & GF_TERM_WINDOWLESS)) sr->back_color = 0xFFFFFFFF; /*hack for SVG where size is set in %*/ if (!sr->has_size_info && w && h) { sr->has_size_info = 1; sr->aspect_ratio = GF_ASPECT_RATIO_FILL_SCREEN; if (w->type!=SVG_NUMBER_PERCENTAGE) { width = FIX2INT(convert_svg_length_to_user(sr, w) ); } else { width = 320; //FIX2INT(root->viewBox.width); } if (h->type!=SVG_NUMBER_PERCENTAGE) { height = FIX2INT(convert_svg_length_to_user(sr, h) ); } else { height = 240; //FIX2INT(root->viewBox.height); } } #endif /*default back color is key color*/ if (sr->user->init_flags & GF_TERM_WINDOWLESS) { opt = gf_cfg_get_key(sr->user->config, "Rendering", "ColorKey"); if (opt) { u32 r, g, b, a; sscanf(opt, "%02X%02X%02X%02X", &a, &r, &g, &b); sr->back_color = GF_COL_ARGB(0xFF, r, g, b); } } /*set scene size only if different, otherwise keep scaling/FS*/ if ( !width || (sr->scene_width!=width) || !height || (sr->scene_height!=height)) { do_notif = sr->has_size_info || (!sr->scene_width && !sr->scene_height); SR_SetSceneSize(sr, width, height); /*get actual size in pixels*/ width = sr->scene_width; height = sr->scene_height; if (!sr->user->os_window_handler) { /*only notify user if we are attached to a window*/ do_notif = 0; if (sr->video_out->max_screen_width && (width > sr->video_out->max_screen_width)) width = sr->video_out->max_screen_width; if (sr->video_out->max_screen_height && (height > sr->video_out->max_screen_height)) height = sr->video_out->max_screen_height; gf_sr_set_size(sr,width, height); } } } SR_ResetFrameRate(sr); #ifdef GF_SR_EVENT_QUEUE gf_mx_v(sr->ev_mx); #endif gf_sr_lock(sr, 0); /*here's a nasty trick: the app may respond to this by calling a gf_sr_set_size from a different thread, but in an atomic way (typically happen on Win32 when changing the window size). WE MUST NOTIFY THE SIZE CHANGE AFTER RELEASING THE RENDERER MUTEX*/ if (do_notif && sr->user->EventProc) { GF_Event evt; evt.type = GF_EVENT_SCENE_SIZE; evt.size.width = width; evt.size.height = height; sr->user->EventProc(sr->user->opaque, &evt); } if (scene_graph) sr->draw_next_frame = 1; return GF_OK; }