LCOV - code coverage report
Current view: top level - compositor - mpeg4_mediasensor.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 86 142 60.6 %
Date: 2021-04-29 23:48:07 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2017
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / Scene Compositor sub-project
       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             : 
      26             : 
      27             : #include <gpac/constants.h>
      28             : #include <gpac/internal/compositor_dev.h>
      29             : 
      30             : #ifndef GPAC_DISABLE_VRML
      31             : 
      32             : /*render : setup media sensor and update timing in case of inline scenes*/
      33        2536 : void RenderMediaSensor(GF_Node *node, void *rs, Bool is_destroy)
      34             : {
      35             :         GF_TraverseState *tr_state = (GF_TraverseState *)rs;
      36             :         GF_Clock *ck;
      37             :         Bool do_update_clock = 1;
      38        2536 :         MediaSensorStack *st = (MediaSensorStack *)gf_node_get_private(node);
      39             : 
      40        2536 :         if (is_destroy) {
      41             :                 /*unlink from OD*/
      42          16 :                 if (st->stream && st->stream->odm)
      43          12 :                         gf_list_del_item(st->stream->odm->ms_stack, st);
      44             : 
      45          16 :                 gf_list_del(st->seg);
      46          16 :                 gf_free(st);
      47          16 :                 return;
      48             :         }
      49             :         //we need to disable culling otherwise we may never be called back again ...
      50        2520 :         tr_state->disable_cull = 1;
      51             : 
      52        2520 :         if (!st->is_init) {
      53         826 :                 if (!st->stream) {
      54         107 :                         st->stream = gf_mo_register(node, &st->sensor->url, 0, 0);
      55         107 :                         if (!st->stream) return;
      56             :                 }
      57         733 :                 if (!st->stream->odm) return;
      58             :                 
      59          14 :                 gf_list_add(st->stream->odm->ms_stack, st);
      60          14 :                 gf_odm_init_segments(st->stream->odm, st->seg, &st->sensor->url);
      61          14 :                 st->is_init = 1;
      62          14 :                 st->active_seg = 0;
      63             :         }
      64             :         //st->stream may be NULL when destroying the ODM
      65        1708 :         if (!st->stream || !st->stream->odm) return;
      66             : 
      67             :         /*media sensor bound to natural media (audio, video) is updated when fetching the stream
      68             :         data for rendering.*/
      69             : 
      70             :         ck = NULL;
      71             :         /*check inline scenes - if the scene is set to restart DON'T MODIFY SENSOR: since we need a 2 render
      72             :         passes to restart inline, scene is considered as not running*/
      73        1708 :         if (st->stream->odm->subscene && !st->stream->odm->subscene->needs_restart) {
      74         279 :                 if (! st->stream->odm->subscene->is_dynamic_scene) ck = st->stream->odm->subscene->root_od->ck;
      75             :                 /*dynamic scene*/
      76         124 :                 else ck = st->stream->odm->ck;
      77             : 
      78         279 :                 if (st->stream->odm->subscene->is_dynamic_scene) do_update_clock = 0;
      79             :         }
      80             :         /*check anim or OCR streams*/
      81        1429 :         else if (st->stream->odm->type==GF_STREAM_SCENE) ck = st->stream->odm->ck;
      82             :         /*check OCR streams*/
      83        1428 :         else if (st->stream->odm->ck) ck = st->stream->odm->ck;
      84             : 
      85        1688 :         if (ck && ck->clock_init ) {
      86        1655 :                 if (do_update_clock)
      87        1541 :                         st->stream->odm->media_current_time = gf_clock_media_time(ck);
      88        1655 :                 mediasensor_update_timing(st->stream->odm, GF_FALSE);
      89             :         }
      90             :         //if main addon is VoD , fire a timeshift update
      91          53 :         else if (st->stream->odm->subscene && st->stream->odm->subscene->sys_clock_at_main_activation) {
      92             :                 GF_Event evt;
      93             :                 memset(&evt, 0, sizeof(evt));
      94           0 :                 evt.type = GF_EVENT_TIMESHIFT_UPDATE;
      95           0 :                 gf_sc_send_event(st->stream->odm->parentscene->compositor, &evt);
      96             :         }
      97             : }
      98             : 
      99          16 : void InitMediaSensor(GF_Scene *scene, GF_Node *node)
     100             : {
     101             :         MediaSensorStack *st;
     102          16 :         GF_SAFEALLOC(st, MediaSensorStack);
     103          16 :         if (!st) {
     104           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[Terminal] Failed to allocate media sensor stack\n"));
     105             :                 return;
     106             :         }
     107             : 
     108          16 :         st->parent = scene;
     109          16 :         st->sensor = (M_MediaSensor *)node;
     110          16 :         st->seg = gf_list_new();
     111          16 :         gf_node_set_callback_function(node, RenderMediaSensor);
     112          16 :         gf_node_set_private(node, st);
     113             : 
     114             : }
     115             : 
     116             : /*only URL can be changed, so reset and get new URL*/
     117           1 : void MS_Modified(GF_Node *node)
     118             : {
     119           1 :         MediaSensorStack *st = (MediaSensorStack *)gf_node_get_private(node);
     120           1 :         if (!st) return;
     121             : 
     122           0 :         while (gf_list_count(st->seg)) gf_list_rem(st->seg, 0);
     123             : 
     124           1 :         if (st->stream) {
     125             :                 /*unlink from OD*/
     126           0 :                 if (st->stream->odm && st->stream->odm->ms_stack)
     127           0 :                         gf_list_del_item(st->stream->odm->ms_stack, st);
     128             : 
     129           0 :                 gf_mo_unregister(node, st->stream);
     130           0 :                 if (st->sensor->isActive) {
     131           0 :                         st->sensor->isActive = 0;
     132           0 :                         gf_node_event_out((GF_Node *) st->sensor, 4/*"isActive"*/);
     133             :                 }
     134             :         }
     135           1 :         st->stream = NULL;
     136           1 :         st->is_init = 0;
     137           1 :         gf_sc_invalidate(st->parent->compositor, NULL);
     138             : }
     139             : 
     140       12439 : void mediasensor_update_timing(GF_ObjectManager *odm, Bool is_eos)
     141             : {
     142             :         GF_Segment *desc;
     143             :         u32 i, count, j, ms_count;
     144             :         Double time;
     145       12439 :         ms_count = gf_list_count(odm->ms_stack);
     146       12439 :         if (!ms_count) return;
     147             : 
     148        3149 :         time = odm->media_current_time / 1000.0;
     149             :         //dirty hack to get timing of frame when very late (openhevc debug)
     150        3149 :         if (odm->subscene && odm->ck && odm->ck->last_ts_rendered)
     151           0 :                 time = odm->ck->last_ts_rendered / 1000.0;
     152             : 
     153        3503 :         for (j=0; j<ms_count; j++) {
     154        3503 :                 MediaSensorStack *media_sens = (MediaSensorStack *)gf_list_get(odm->ms_stack, j);
     155        3503 :                 if (!media_sens->is_init) continue;
     156        3503 :                 count = gf_list_count(media_sens->seg);
     157             : 
     158             :                 /*full object controled*/
     159        3503 :                 if (!media_sens->active_seg && !count) {
     160             :                         /*check for end of scene (MediaSensor on inline)*/
     161        3503 :                         if (odm->subscene && odm->subscene->duration) {
     162         262 :                                 GF_Clock *ck = gf_odm_get_media_clock(odm);
     163         262 :                                 if (ck->has_seen_eos && (1000*time>=(Double) (s64)odm->subscene->duration)) {
     164           0 :                                         if (media_sens->sensor->isActive) {
     165             :                                                 /*force notification of time (ntify the scene duration rather than the current clock*/
     166           0 :                                                 media_sens->sensor->mediaCurrentTime = (Double) odm->subscene->duration;
     167           0 :                                                 media_sens->sensor->mediaCurrentTime /= 1000;
     168           0 :                                                 gf_node_event_out((GF_Node *) media_sens->sensor, 1/*"mediaCurrentTime"*/);
     169           0 :                                                 media_sens->sensor->isActive = 0;
     170           0 :                                                 gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);
     171             : 
     172           0 :                                                 GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[ODM%d] Deactivating media sensor\n", odm->ID));
     173             :                                         }
     174           0 :                                         continue;
     175             :                                 }
     176             :                         }
     177             : 
     178        3503 :                         if (!is_eos && !media_sens->sensor->isActive) {
     179          18 :                                 media_sens->sensor->isActive = 1;
     180          18 :                                 gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);
     181             : 
     182          18 :                                 gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);
     183          18 :                                 if (odm->subscene) {
     184           6 :                                         media_sens->sensor->mediaDuration = (Double) (s64)odm->subscene->duration;
     185             :                                 } else {
     186          12 :                                         media_sens->sensor->mediaDuration = (Double) (s64)odm->duration;
     187             :                                 }
     188          18 :                                 if (media_sens->sensor->mediaDuration)
     189          17 :                                         media_sens->sensor->mediaDuration /= 1000;
     190             :                                 else
     191           1 :                                         media_sens->sensor->mediaDuration = -FIX_ONE;
     192             : 
     193          18 :                                 gf_node_event_out((GF_Node *) media_sens->sensor, 3/*"mediaDuration"*/);
     194             :                         }
     195             : 
     196        3503 :                         if (is_eos && media_sens->sensor->isActive) {
     197           1 :                                 if (media_sens->sensor->mediaDuration>=0) {
     198           1 :                                         media_sens->sensor->mediaCurrentTime = media_sens->sensor->mediaDuration;
     199             :                                 } else {
     200           0 :                                         media_sens->sensor->mediaCurrentTime = time;
     201             :                                 }
     202           1 :                                 gf_node_event_out((GF_Node *) media_sens->sensor, 1/*"mediaCurrentTime"*/);
     203           1 :                                 media_sens->sensor->isActive = 0;
     204           1 :                                 gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);
     205             :                         } else {
     206        3502 :                                 if (media_sens->sensor->isActive && (media_sens->sensor->mediaCurrentTime != time)) {
     207        2029 :                                         media_sens->sensor->mediaCurrentTime = time;
     208        2029 :                                         gf_node_event_out((GF_Node *) media_sens->sensor, 1/*"mediaCurrentTime"*/);
     209             :                                 }
     210             :                         }
     211        3503 :                         continue;
     212             :                 }
     213             : 
     214             :                 /*locate segment*/
     215           0 :                 for (i=media_sens->active_seg; i<count; i++) {
     216           0 :                         desc = (GF_Segment*)gf_list_get(media_sens->seg, i);
     217             :                         /*not controled*/
     218           0 :                         if (desc->startTime > time) {
     219           0 :                                 if (media_sens->sensor->isActive) {
     220           0 :                                         media_sens->sensor->isActive = 0;
     221           0 :                                         gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);
     222             : 
     223           0 :                                         GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[ODM%d] Deactivating media sensor at time %g - segment %s\n", odm->ID, time, desc->SegmentName));
     224             :                                 }
     225           0 :                                 continue;
     226             :                         }
     227           0 :                         if (desc->startTime + desc->Duration < time) continue;
     228           0 :                         if (desc->startTime + desc->Duration == time) {
     229           0 :                                 continue;
     230             :                         }
     231             :                         /*segment switch, force activation (isActive TRUE send at each seg)*/
     232           0 :                         if (media_sens->active_seg != i) {
     233           0 :                                 media_sens->active_seg = i;
     234           0 :                                 media_sens->sensor->isActive = 0;
     235             :                         }
     236             : 
     237           0 :                         if (!media_sens->sensor->isActive) {
     238             : 
     239           0 :                                 GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[ODM%d] Activating media sensor time %g - segment %s\n", odm->ID, time, desc->SegmentName));
     240             : 
     241           0 :                                 media_sens->sensor->isActive = 1;
     242           0 :                                 gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);
     243             :                                 /*set info*/
     244           0 :                                 gf_sg_vrml_mf_reset(& media_sens->sensor->info, GF_SG_VRML_MFSTRING);
     245           0 :                                 gf_sg_vrml_mf_alloc(& media_sens->sensor->info, GF_SG_VRML_MFSTRING, 1);
     246           0 :                                 media_sens->sensor->info.vals[0] = desc->SegmentName ? gf_strdup(desc->SegmentName) : NULL;
     247           0 :                                 gf_node_event_out((GF_Node *) media_sens->sensor, 5/*"info"*/);
     248             :                                 /*set duration*/
     249           0 :                                 media_sens->sensor->mediaDuration = desc->Duration;
     250           0 :                                 gf_node_event_out((GF_Node *) media_sens->sensor, 3/*"mediaDuration"*/);
     251             :                                 /*set seg start time*/
     252           0 :                                 media_sens->sensor->streamObjectStartTime = desc->startTime;
     253           0 :                                 gf_node_event_out((GF_Node *) media_sens->sensor, 2/*"streamObjectStartTime"*/);
     254             : 
     255             :                         }
     256             : 
     257             :                         /*set media time - relative to segment start time*/
     258           0 :                         time -= desc->startTime;
     259           0 :                         if (media_sens->sensor->mediaCurrentTime != time) {
     260           0 :                                 media_sens->sensor->mediaCurrentTime = time;
     261           0 :                                 gf_node_event_out((GF_Node *) media_sens->sensor, 1/*"mediaCurrentTime"*/);
     262             :                         }
     263             :                         break;
     264             :                 }
     265           0 :                 if (i==count) {
     266             :                         /*we're after last segment, deactivate*/
     267           0 :                         if (media_sens->sensor->isActive) {
     268           0 :                                 media_sens->sensor->isActive = 0;
     269           0 :                                 gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/);
     270           0 :                                 media_sens->active_seg = count;
     271           0 :                                 GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[ODM%d] Deactivating media sensor at time %g: no more segments\n", odm->ID, time));
     272             :                         }
     273             :                 }
     274             :         }
     275             : }
     276             : 
     277          16 : void MS_Stop(MediaSensorStack *st)
     278             : {
     279          16 :         if (st->sensor->isActive) {
     280          14 :                 st->sensor->isActive = 0;
     281          14 :                 gf_node_event_out((GF_Node *) st->sensor, 4/*"isActive"*/);
     282             : 
     283          14 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[ODM%d] Deactivating media sensor\n", st->stream->odm->ID));
     284             :         }
     285          16 :         st->active_seg = 0;
     286          16 : }
     287             : 
     288             : #endif /*GPAC_DISABLE_VRML*/

Generated by: LCOV version 1.13