LCOV - code coverage report
Current view: top level - compositor - mpeg4_animstream.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 78 88 88.6 %
Date: 2021-04-29 23:48:07 Functions: 7 7 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-2012
       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             : #include "nodes_stacks.h"
      27             : 
      28             : #include <gpac/nodes_mpeg4.h>
      29             : 
      30             : #ifndef GPAC_DISABLE_VRML
      31             : 
      32             : typedef struct
      33             : {
      34             :         GF_Compositor *compositor;
      35             :         GF_TimeNode time_handle;
      36             :         Double start_time;
      37             :         GF_MediaObject *stream;
      38             :         MFURL current_url;
      39             : } AnimationStreamStack;
      40             : 
      41        1619 : static void animationstream_destroy(GF_Node *node, void *rs, Bool is_destroy)
      42             : {
      43        1619 :         if (is_destroy) {
      44             :                 M_AnimationStream *as = (M_AnimationStream *)node;
      45         217 :                 AnimationStreamStack *st = (AnimationStreamStack *) gf_node_get_private(node);
      46             : 
      47         217 :                 if (st->time_handle.is_registered) {
      48         213 :                         gf_sc_unregister_time_node(st->compositor, &st->time_handle);
      49             :                 }
      50         217 :                 if (st->stream && as->isActive) {
      51           5 :                         gf_mo_set_flag(st->stream, GF_MO_DISPLAY_REMOVE, 1);
      52           5 :                         gf_mo_stop(&st->stream);
      53             :                 }
      54         217 :                 gf_sg_vrml_mf_reset(&st->current_url, GF_SG_VRML_MFURL);
      55         217 :                 gf_free(st);
      56             :         }
      57        1619 : }
      58             : 
      59             : 
      60         195 : static void animationstream_check_url(AnimationStreamStack *stack, M_AnimationStream *as)
      61             : {
      62         195 :         if (!stack->stream) {
      63         186 :                 gf_sg_vrml_mf_reset(&stack->current_url, GF_SG_VRML_MFURL);
      64         186 :                 gf_sg_vrml_field_copy(&stack->current_url, &as->url, GF_SG_VRML_MFURL);
      65         186 :                 stack->stream = gf_mo_register((GF_Node *)as, &as->url, 0, 0);
      66         186 :                 gf_sc_invalidate(stack->compositor, NULL);
      67             : 
      68             :                 /*if changed while playing trigger*/
      69         186 :                 if (as->isActive) {
      70           0 :                         gf_mo_play(stack->stream, 0, -1, 0);
      71           0 :                         gf_mo_set_speed(stack->stream, as->speed);
      72             :                 }
      73             :                 return;
      74             :         }
      75             :         /*check change*/
      76           9 :         if (gf_mo_url_changed(stack->stream, &as->url)) {
      77           1 :                 gf_sg_vrml_mf_reset(&stack->current_url, GF_SG_VRML_MFURL);
      78           1 :                 gf_sg_vrml_field_copy(&stack->current_url, &as->url, GF_SG_VRML_MFURL);
      79             :                 /*if changed while playing stop old source*/
      80           1 :                 if (as->isActive) {
      81           0 :                         gf_mo_set_flag(stack->stream, GF_MO_DISPLAY_REMOVE, 1);
      82           0 :                         gf_mo_stop(&stack->stream);
      83             :                 }
      84           1 :                 gf_mo_unregister((GF_Node *)as, stack->stream);
      85             : 
      86           1 :                 stack->stream = gf_mo_register((GF_Node *)as, &as->url, 0, 0);
      87             :                 /*if changed while playing play new source*/
      88           1 :                 if (as->isActive) {
      89           0 :                         gf_mo_play(stack->stream, 0, -1, 0);
      90           0 :                         gf_mo_set_speed(stack->stream, as->speed);
      91             :                 }
      92           1 :                 gf_sc_invalidate(stack->compositor, NULL);
      93             :         }
      94             : }
      95             : 
      96             : static Fixed animationstream_get_speed(AnimationStreamStack *stack, M_AnimationStream *as)
      97             : {
      98        4047 :         return gf_mo_get_speed(stack->stream, as->speed);
      99             : }
     100             : static Bool animationstream_get_loop(AnimationStreamStack *stack, M_AnimationStream *as)
     101             : {
     102           4 :         return gf_mo_get_loop(stack->stream, as->loop);
     103             : }
     104             : 
     105         187 : static void animationstream_activate(AnimationStreamStack *stack, M_AnimationStream *as)
     106             : {
     107         187 :         animationstream_check_url(stack, as);
     108         187 :         as->isActive = 1;
     109         187 :         gf_node_event_out((GF_Node*)as, 6/*"isActive"*/);
     110             : 
     111         187 :         gf_mo_play(stack->stream, 0, -1, 0);
     112         187 :         gf_mo_set_speed(stack->stream, as->speed);
     113         187 : }
     114             : 
     115           5 : static void animationstream_deactivate(AnimationStreamStack *stack, M_AnimationStream *as)
     116             : {
     117           5 :         if (as->isActive) {
     118           5 :                 as->isActive = 0;
     119           5 :                 gf_node_event_out((GF_Node*)as, 6/*"isActive"*/);
     120             :         }
     121           5 :         if (stack->stream) {
     122           5 :                 if (gf_mo_url_changed(stack->stream, &as->url))
     123           0 :                         gf_mo_set_flag(stack->stream, GF_MO_DISPLAY_REMOVE, 1);
     124           5 :                 gf_mo_stop(&stack->stream);
     125             :         }
     126           5 :         stack->time_handle.needs_unregister = 1;
     127           5 :         gf_sc_invalidate(stack->compositor, NULL);
     128           5 : }
     129             : 
     130        4351 : static void animationstream_update_time(GF_TimeNode *st)
     131             : {
     132             :         Double time;
     133        4351 :         M_AnimationStream *as = (M_AnimationStream *)st->udta;
     134        4351 :         AnimationStreamStack *stack = (AnimationStreamStack *)gf_node_get_private(st->udta);
     135             : 
     136             :         /*not active, store start time and speed*/
     137        4351 :         if ( ! as->isActive) {
     138         491 :                 stack->start_time = as->startTime;
     139             :         }
     140        4351 :         time = gf_node_get_scene_time(st->udta);
     141             : 
     142        4351 :         if ((time < stack->start_time) || (stack->start_time < 0)) return;
     143             : 
     144        8094 :         if (animationstream_get_speed(stack, as) && as->isActive) {
     145             :                 //if stoptime is reached (>startTime) deactivate
     146        3860 :                 if ((as->stopTime > stack->start_time) && (time >= as->stopTime) ) {
     147           1 :                         animationstream_deactivate(stack, as);
     148           1 :                         return;
     149             :                 }
     150        3859 :                 if (gf_mo_is_done(stack->stream)) {
     151           8 :                         if (animationstream_get_loop(stack, as)) {
     152           0 :                                 gf_mo_restart(stack->stream);
     153           4 :                         } else if (gf_mo_should_deactivate(stack->stream)) {
     154           4 :                                 animationstream_deactivate(stack, as);
     155             :                         }
     156             :                 }
     157             :         }
     158             : 
     159             :         /*we're (about to be) active: VRML:
     160             :         "A time-dependent node is inactive until its startTime is reached. When time now becomes greater than or
     161             :         equal to startTime, an isActive TRUE event is generated and the time-dependent node becomes active      */
     162        4046 :         if (!as->isActive && !st->needs_unregister) animationstream_activate(stack, as);
     163             : }
     164             : 
     165             : 
     166         217 : void compositor_init_animationstream(GF_Compositor *compositor, GF_Node *node)
     167             : {
     168             :         AnimationStreamStack *st;
     169         217 :         GF_SAFEALLOC(st, AnimationStreamStack);
     170         217 :         if (!st) {
     171           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate AnimationStream stack\n"));
     172             :                 return;
     173             :         }
     174         217 :         st->compositor = compositor;
     175         217 :         st->time_handle.UpdateTimeNode = animationstream_update_time;
     176         217 :         st->time_handle.udta = node;
     177             : 
     178         217 :         gf_node_set_private(node, st);
     179         217 :         gf_node_set_callback_function(node, animationstream_destroy);
     180             : 
     181         217 :         gf_sc_register_time_node(compositor, &st->time_handle);
     182             : }
     183             : 
     184             : 
     185             : 
     186           8 : void compositor_animationstream_modified(GF_Node *node)
     187             : {
     188             :         M_AnimationStream *as = (M_AnimationStream *)node;
     189           8 :         AnimationStreamStack *st = (AnimationStreamStack *) gf_node_get_private(node);
     190           8 :         if (!st) return;
     191             : 
     192             :         /*update state if we're active*/
     193           8 :         if (as->isActive)
     194           1 :                 animationstream_update_time(&st->time_handle);
     195             : 
     196             :         /*check URL change*/
     197           8 :         animationstream_check_url(st, as);
     198             : 
     199           8 :         if (!st->time_handle.is_registered && !st->time_handle.needs_unregister)
     200           0 :                 gf_sc_register_time_node(st->compositor, &st->time_handle);
     201             :         else
     202           8 :                 st->time_handle.needs_unregister = 0;
     203             : }
     204             : 
     205             : #endif /*GPAC_DISABLE_VRML*/

Generated by: LCOV version 1.13