root/src/compositor/mpeg4_animstream.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. animationstream_destroy
  2. animationstream_check_url
  3. animationstream_get_speed
  4. animationstream_get_loop
  5. animationstream_activate
  6. animationstream_deactivate
  7. animationstream_update_time
  8. compositor_init_animationstream
  9. compositor_animationstream_modified

/*
 *                      GPAC - Multimedia Framework C SDK
 *
 *                      Authors: Jean Le Feuvre
 *                      Copyright (c) Telecom ParisTech 2000-2012
 *                                      All rights reserved
 *
 *  This file is part of GPAC / Scene Compositor sub-project
 *
 *  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 "nodes_stacks.h"

#include <gpac/nodes_mpeg4.h>

#ifndef GPAC_DISABLE_VRML

typedef struct
{
        GF_Compositor *compositor;
        GF_TimeNode time_handle;
        Double start_time;
        GF_MediaObject *stream;
        MFURL current_url;
} AnimationStreamStack;

static void animationstream_destroy(GF_Node *node, void *rs, Bool is_destroy)
{
        if (is_destroy) {
                M_AnimationStream *as = (M_AnimationStream *)node;
                AnimationStreamStack *st = (AnimationStreamStack *) gf_node_get_private(node);

                if (st->time_handle.is_registered) {
                        gf_sc_unregister_time_node(st->compositor, &st->time_handle);
                }
                if (st->stream && as->isActive) {
                        gf_mo_set_flag(st->stream, GF_MO_DISPLAY_REMOVE, 1);
                        gf_mo_stop(st->stream);
                }
                gf_sg_vrml_mf_reset(&st->current_url, GF_SG_VRML_MFURL);
                gf_free(st);
        }
}


static void animationstream_check_url(AnimationStreamStack *stack, M_AnimationStream *as)
{
        if (!stack->stream) {
                gf_sg_vrml_mf_reset(&stack->current_url, GF_SG_VRML_MFURL);
                gf_sg_vrml_field_copy(&stack->current_url, &as->url, GF_SG_VRML_MFURL);
                stack->stream = gf_mo_register((GF_Node *)as, &as->url, 0, 0);
                gf_sc_invalidate(stack->compositor, NULL);

                /*if changed while playing trigger*/
                if (as->isActive) {
                        gf_mo_play(stack->stream, 0, -1, 0);
                        gf_mo_set_speed(stack->stream, as->speed);
                }
                return;
        }
        /*check change*/
        if (gf_mo_url_changed(stack->stream, &as->url)) {
                gf_sg_vrml_mf_reset(&stack->current_url, GF_SG_VRML_MFURL);
                gf_sg_vrml_field_copy(&stack->current_url, &as->url, GF_SG_VRML_MFURL);
                /*if changed while playing stop old source*/
                if (as->isActive) {
                        gf_mo_set_flag(stack->stream, GF_MO_DISPLAY_REMOVE, 1);
                        gf_mo_stop(stack->stream);
                }
                gf_mo_unregister((GF_Node *)as, stack->stream);

                stack->stream = gf_mo_register((GF_Node *)as, &as->url, 0, 0);
                /*if changed while playing play new source*/
                if (as->isActive) {
                        gf_mo_play(stack->stream, 0, -1, 0);
                        gf_mo_set_speed(stack->stream, as->speed);
                }
                gf_sc_invalidate(stack->compositor, NULL);
        }
}

static Fixed animationstream_get_speed(AnimationStreamStack *stack, M_AnimationStream *as)
{
        return gf_mo_get_speed(stack->stream, as->speed);
}
static Bool animationstream_get_loop(AnimationStreamStack *stack, M_AnimationStream *as)
{
        return gf_mo_get_loop(stack->stream, as->loop);
}

static void animationstream_activate(AnimationStreamStack *stack, M_AnimationStream *as)
{
        animationstream_check_url(stack, as);
        as->isActive = 1;
        gf_node_event_out((GF_Node*)as, 6/*"isActive"*/);

        gf_mo_play(stack->stream, 0, -1, 0);
        gf_mo_set_speed(stack->stream, as->speed);
}

static void animationstream_deactivate(AnimationStreamStack *stack, M_AnimationStream *as)
{
        if (as->isActive) {
                as->isActive = 0;
                gf_node_event_out((GF_Node*)as, 6/*"isActive"*/);
        }
        if (stack->stream) {
                if (gf_mo_url_changed(stack->stream, &as->url))
                        gf_mo_set_flag(stack->stream, GF_MO_DISPLAY_REMOVE, 1);
                gf_mo_stop(stack->stream);
        }
        stack->time_handle.needs_unregister = 1;
        gf_sc_invalidate(stack->compositor, NULL);
}

static void animationstream_update_time(GF_TimeNode *st)
{
        Double time;
        M_AnimationStream *as = (M_AnimationStream *)st->udta;
        AnimationStreamStack *stack = (AnimationStreamStack *)gf_node_get_private(st->udta);

        /*not active, store start time and speed*/
        if ( ! as->isActive) {
                stack->start_time = as->startTime;
        }
        time = gf_node_get_scene_time(st->udta);

        if ((time < stack->start_time) || (stack->start_time < 0)) return;

        if (animationstream_get_speed(stack, as) && as->isActive) {
                //if stoptime is reached (>startTime) deactivate
                if ((as->stopTime > stack->start_time) && (time >= as->stopTime) ) {
                        animationstream_deactivate(stack, as);
                        return;
                }
                if (gf_mo_is_done(stack->stream)) {
                        if (animationstream_get_loop(stack, as)) {
                                gf_mo_restart(stack->stream);
                        } else if (gf_mo_should_deactivate(stack->stream)) {
                                animationstream_deactivate(stack, as);
                        }
                }
        }

        /*we're (about to be) active: VRML:
        "A time-dependent node is inactive until its startTime is reached. When time now becomes greater than or
        equal to startTime, an isActive TRUE event is generated and the time-dependent node becomes active      */
        if (!as->isActive && !st->needs_unregister) animationstream_activate(stack, as);
}


void compositor_init_animationstream(GF_Compositor *compositor, GF_Node *node)
{
        AnimationStreamStack *st;
        GF_SAFEALLOC(st, AnimationStreamStack);
        if (!st) {
                GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate AnimationStream stack\n"));
                return;
        }
        st->compositor = compositor;
        st->time_handle.UpdateTimeNode = animationstream_update_time;
        st->time_handle.udta = node;

        gf_node_set_private(node, st);
        gf_node_set_callback_function(node, animationstream_destroy);

        gf_sc_register_time_node(compositor, &st->time_handle);
}



void compositor_animationstream_modified(GF_Node *node)
{
        M_AnimationStream *as = (M_AnimationStream *)node;
        AnimationStreamStack *st = (AnimationStreamStack *) gf_node_get_private(node);
        if (!st) return;

        /*update state if we're active*/
        if (as->isActive)
                animationstream_update_time(&st->time_handle);

        /*check URL change*/
        animationstream_check_url(st, as);

        if (!st->time_handle.is_registered && !st->time_handle.needs_unregister)
                gf_sc_register_time_node(st->compositor, &st->time_handle);
        else
                st->time_handle.needs_unregister = 0;
}

#endif /*GPAC_DISABLE_VRML*/

/* [<][>][^][v][top][bottom][index][help] */