LCOV - code coverage report
Current view: top level - compositor - texturing.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 159 187 85.0 %
Date: 2021-04-29 23:48:07 Functions: 13 14 92.9 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2018
       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 "texturing.h"
      27             : #include <gpac/options.h>
      28             : 
      29             : #include "nodes_stacks.h"
      30             : 
      31        3830 : static void update_texture_void(GF_TextureHandler *txh)
      32             : {
      33        3830 : }
      34             : 
      35             : GF_EXPORT
      36        1400 : void gf_sc_texture_setup(GF_TextureHandler *txh, GF_Compositor *compositor, GF_Node *owner)
      37             : {
      38             :         memset(txh, 0, sizeof(GF_TextureHandler));
      39        1400 :         txh->owner = owner;
      40        1400 :         txh->compositor = compositor;
      41             :         /*insert texture in reverse order, so that textures in sub documents/scenes are updated before parent ones*/
      42        1400 :         if (gf_list_find(compositor->textures, txh)<0) {
      43        1400 :                 gf_list_insert(compositor->textures, txh, 0);
      44        1400 :                 compositor->texture_inserted = GF_TRUE;
      45             :         }
      46        1400 :         if (!txh->update_texture_fcnt) txh->update_texture_fcnt = update_texture_void;
      47        1400 : }
      48             : 
      49             : 
      50             : GF_EXPORT
      51        1927 : void gf_sc_texture_destroy(GF_TextureHandler *txh)
      52             : {
      53        1927 :         GF_Compositor *compositor = txh->compositor;
      54        1927 :         Bool lock = gf_mx_try_lock(compositor->mx);
      55             : 
      56        1927 :         gf_sc_texture_release(txh);
      57        1927 :         if (txh->is_open) gf_sc_texture_stop(txh);
      58        1927 :         gf_list_del_item(txh->compositor->textures, txh);
      59             : 
      60        1927 :         if (lock) gf_mx_v(compositor->mx);
      61        1927 : }
      62             : 
      63             : GF_EXPORT
      64         232 : Bool gf_sc_texture_check_url_change(GF_TextureHandler *txh, MFURL *url)
      65             : {
      66         232 :         if (!txh->stream) return url->count;
      67          26 :         return gf_mo_url_changed(txh->stream, url);
      68             : }
      69             : 
      70             : GF_EXPORT
      71         558 : GF_Err gf_sc_texture_open(GF_TextureHandler *txh, MFURL *url, Bool lock_scene_timeline)
      72             : {
      73         558 :         if (txh->is_open) return GF_BAD_PARAM;
      74             : 
      75             :         /*if existing texture in cache destroy it - we don't destroy it on stop to handle MovieTexture*/
      76         409 :         if (txh->tx_io) gf_sc_texture_release(txh);
      77             : 
      78             :         /*get media object*/
      79         409 :         txh->stream = gf_mo_register(txh->owner, url, lock_scene_timeline, 0);
      80             :         //consider the texture open to avoid repeatingly calling for open on bad URLs/OD
      81         409 :         txh->is_open = 1;
      82             : 
      83             :         /*bad/Empty URL*/
      84         409 :         if (!txh->stream) return GF_NOT_SUPPORTED;
      85             : 
      86         392 :         return GF_OK;
      87             : }
      88             : 
      89             : GF_EXPORT
      90         408 : GF_Err gf_sc_texture_play_from_to(GF_TextureHandler *txh, MFURL *url, Double start_offset, Double end_offset, Bool can_loop, Bool lock_scene_timeline)
      91             : {
      92         408 :         if (!txh->stream) {
      93             :                 GF_Err e;
      94         407 :                 if (!url) return GF_BAD_PARAM;
      95         407 :                 e = gf_sc_texture_open(txh, url, lock_scene_timeline);
      96         407 :                 if (e != GF_OK) return e;
      97             :         }
      98         393 :         txh->is_open = 1;
      99         393 :         txh->stream_finished = GF_FALSE;
     100             :         /*request play*/
     101         393 :         gf_mo_play(txh->stream, start_offset, end_offset, can_loop);
     102             : 
     103         393 :         txh->last_frame_time = (u32) (-1);
     104             : 
     105             :         //we need to rework the raw memory stuff to be transparent
     106             : #ifdef FILTER_FIXME
     107             :         txh->raw_memory = GF_FALSE;
     108             : #endif
     109             :         /*request play*/
     110         393 :         return GF_OK;
     111             : }
     112             : 
     113             : GF_EXPORT
     114         188 : GF_Err gf_sc_texture_play(GF_TextureHandler *txh, MFURL *url)
     115             : {
     116             :         Double offset = 0;
     117             :         Bool loop = 0;
     118             : 
     119         188 :         if (txh->compositor->play_state != GF_STATE_PLAYING) {
     120           0 :                 offset = gf_node_get_scene_time(txh->owner);
     121             :                 loop = /*gf_mo_get_loop(gf_mo_register(txh->owner, url, 0, 0), 0)*/ 1;
     122             :         }
     123             : 
     124         188 :         return gf_sc_texture_play_from_to(txh, url, offset, -1, loop, 0);
     125             : }
     126             : 
     127             : 
     128             : GF_EXPORT
     129           2 : void gf_sc_texture_stop_no_unregister(GF_TextureHandler *txh)
     130             : {
     131           2 :         if (!txh->is_open) return;
     132             :         /*release texture WITHOUT dropping frame*/
     133           2 :         if (txh->needs_release) {
     134           0 :                 gf_mo_release_data(txh->stream, 0xFFFFFFFF, 1);
     135           0 :                 txh->needs_release = 0;
     136           0 :                 txh->frame_ifce = NULL;
     137             :         }
     138           2 :         gf_sc_invalidate(txh->compositor, NULL);
     139           2 :         gf_mo_stop(&txh->stream);
     140           2 :         txh->data = NULL;
     141           2 :         txh->frame_ifce = NULL;
     142             : 
     143           2 :         txh->is_open = 0;
     144             : }
     145             : 
     146             : GF_EXPORT
     147         408 : void gf_sc_texture_stop(GF_TextureHandler *txh)
     148             : {
     149         408 :         if (!txh->is_open) return;
     150             :         /*release texture WITHOUT dropping frame*/
     151         408 :         if (txh->needs_release) {
     152           1 :                 gf_mo_release_data(txh->stream, 0xFFFFFFFF, -1);
     153           1 :                 txh->needs_release = 0;
     154           1 :                 txh->frame_ifce = NULL;
     155             :         }
     156         408 :         gf_sc_invalidate(txh->compositor, NULL);
     157         408 :         gf_mo_stop(&txh->stream);
     158         408 :         if (!txh->stream) {
     159          76 :                 txh->data = NULL;
     160          76 :                 txh->frame_ifce = NULL;
     161             :         }
     162         408 :         txh->is_open = 0;
     163             : 
     164             :         /*and deassociate object*/
     165         408 :         gf_mo_unregister(txh->owner, txh->stream);
     166         408 :         txh->stream = NULL;
     167             : }
     168             : 
     169             : GF_EXPORT
     170           0 : void gf_sc_texture_restart(GF_TextureHandler *txh)
     171             : {
     172           0 :         if (!txh->is_open) return;
     173           0 :         gf_sc_texture_release_stream(txh);
     174           0 :         txh->stream_finished = 0;
     175           0 :         gf_mo_restart(txh->stream);
     176             : }
     177             : 
     178             : 
     179         388 : static void setup_texture_object(GF_TextureHandler *txh, Bool private_media)
     180             : {
     181         388 :         if (!txh->tx_io) {
     182         388 :                 gf_sc_texture_allocate(txh);
     183         388 :                 if (!txh->tx_io) return;
     184             : 
     185         388 :                 gf_mo_get_visual_info(txh->stream, &txh->width, &txh->height, &txh->stride, &txh->pixel_ar, &txh->pixelformat, &txh->is_flipped);
     186         388 :                 gf_sc_texture_configure_conversion(txh);
     187             : 
     188         388 :                 gf_pixel_get_size_info(txh->pixelformat, txh->width, txh->height, NULL, NULL, NULL, &txh->nb_planes, NULL);
     189             : 
     190         388 :                 if (private_media) {
     191           0 :                         txh->transparent = 1;
     192           0 :                         txh->pixelformat = GF_PIXEL_ARGB;
     193           0 :                         txh->flags |= GF_SR_TEXTURE_PRIVATE_MEDIA;
     194             :                 } else {
     195         388 :                         txh->transparent = 0;
     196         388 :                         switch (txh->pixelformat) {
     197         112 :                         case GF_PIXEL_ALPHAGREY:
     198             :                         case GF_PIXEL_GREYALPHA:
     199             :                         case GF_PIXEL_ARGB:
     200             :                         case GF_PIXEL_RGBA:
     201             :                         case GF_PIXEL_YUVA:
     202             :                         case GF_PIXEL_RGBDS:
     203         112 :                                 txh->transparent = 1;
     204         112 :                                 break;
     205             :                         }
     206             :                 }
     207             :         }
     208             : }
     209             : 
     210             : 
     211             : GF_EXPORT
     212       65298 : void gf_sc_texture_update_frame(GF_TextureHandler *txh, Bool disable_resync)
     213             : {
     214             :         Bool needs_reload = 0;
     215             :         u32 size, ts, push_time;
     216             :         s32 ms_until_pres, ms_until_next;
     217             : 
     218       65298 :         if (!txh->stream) {
     219       47512 :                 txh->data = NULL;
     220      107800 :                 return;
     221             :         }
     222       17786 :         if (txh->stream->config_changed) {
     223          42 :                 txh->data = NULL;
     224             :         }
     225             : 
     226             :         /*already refreshed*/
     227       17786 :         if ((txh->stream_finished && txh->tx_io) || txh->needs_refresh)
     228             :                 return;
     229             : 
     230             :         /*should never happen!!*/
     231        8498 :         if (txh->needs_release) {
     232           0 :                 gf_mo_release_data(txh->stream, 0xFFFFFFFF, 0);
     233           0 :                 txh->frame_ifce=NULL;
     234             :         }
     235             : 
     236             :         /*check init flag*/
     237        8498 :         if (txh->stream->config_changed) {
     238             :                 needs_reload = 1;
     239          20 :                 txh->data = NULL;
     240          20 :                 if (txh->tx_io) {
     241           0 :                         gf_sc_texture_release(txh);
     242             :                 }
     243             :         }
     244             :         //if first frame use 20ms as upload time
     245        8498 :         push_time = txh->nb_frames ? txh->upload_time/txh->nb_frames : 20;
     246        8498 :         txh->data = gf_mo_fetch_data(txh->stream, disable_resync ? GF_MO_FETCH : GF_MO_FETCH_RESYNC, push_time, &txh->stream_finished, &ts, &size, &ms_until_pres, &ms_until_next, &txh->frame_ifce, NULL);
     247             : 
     248        8498 :         if (txh->stream->config_changed) {
     249             :                 needs_reload = 1;
     250        8277 :         } else if (txh->data && size && txh->size && (size != txh->size)) {
     251             :                 needs_reload = 1;
     252             :         }
     253             :         
     254        8272 :         if (needs_reload) {
     255             :                 /*if we had a texture this means the object has changed - delete texture and resetup. Do not skip
     256             :                 texture update as this may lead to an empty rendering pass (blank frame for this object), especially in DASH*/
     257         226 :                 if (txh->tx_io) {
     258           1 :                         gf_sc_texture_release(txh);
     259           1 :                         txh->needs_refresh = 1;
     260             :                 }
     261         226 :                 txh->flags &= ~GF_SR_TEXTURE_DISABLE_BLIT;
     262             : 
     263             :         }
     264             : 
     265             :         /*if no frame or muted don't draw*/
     266        8498 :         if (!txh->data && !txh->frame_ifce) {
     267        2822 :                 GF_LOG(txh->stream->connect_failure ? GF_LOG_DEBUG : GF_LOG_INFO, GF_LOG_COMPOSE, ("[Texture %p] No output frame available \n", txh));
     268             : 
     269        2822 :                 if (txh->compositor->use_step_mode || !txh->compositor->player) {
     270        2818 :                         if (!txh->stream->connect_failure && ((s32)txh->last_frame_time<0) ) {
     271        2310 :                                 if (!txh->probe_time_ms) txh->probe_time_ms = gf_sys_clock();
     272        1935 :                                 else if (gf_sys_clock() - txh->probe_time_ms > txh->compositor->timeout / 2) {
     273           0 :                                         GF_LOG(GF_LOG_WARNING, GF_LOG_COMPOSE, ("[Texture %p] No output frame in %d ms, considering stream not available\n", txh, txh->compositor->timeout / 2));
     274           0 :                                         txh->stream->connect_failure = GF_TRUE;
     275           0 :                                         gf_sc_texture_stop_no_unregister(txh);
     276             :                                 }
     277        2310 :                                 txh->compositor->ms_until_next_frame = -1;
     278             :                         }
     279             :                 }
     280             :                 /*TODO - check if this is needed */
     281           4 :                 else if (txh->flags & GF_SR_TEXTURE_PRIVATE_MEDIA) {
     282             :                         //txh->needs_refresh = 1;
     283           0 :                         gf_sc_invalidate(txh->compositor, NULL);
     284             :                 }
     285             :                 return;
     286             :         }
     287             : 
     288        5676 :         if (txh->compositor->frame_delay > ms_until_pres)
     289         445 :                 txh->compositor->frame_delay = ms_until_pres;
     290             : 
     291             :         /*if setup and same frame return*/
     292        5676 :         if (txh->tx_io && ((s32) txh->last_frame_time>=0) && (txh->stream_finished || (txh->last_frame_time==ts)) ) {
     293         666 :                 gf_mo_release_data(txh->stream, 0xFFFFFFFF, 0);
     294         666 :                 txh->needs_release = 0;
     295         666 :                 if (!txh->stream_finished) {
     296         490 :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Texture %p] Same frame fetched (TS %u)\n", txh, ts));
     297         490 :                         if (txh->compositor->ms_until_next_frame > ms_until_next)
     298         487 :                                 txh->compositor->ms_until_next_frame = ms_until_next;
     299             :                 }
     300             :                 return;
     301             :         }
     302        5010 :         GF_LOG(GF_LOG_INFO, GF_LOG_SYNC, ("[Texture %p] Updated new frame at clock time %d (%d ms) time %u ms\n", txh, gf_clock_time(txh->stream->odm->ck), gf_sys_clock(), ts));
     303        5010 :         txh->stream_finished = 0;
     304        5010 :         txh->needs_release = 1;
     305        5010 :         txh->last_frame_time = ts;
     306        5010 :         txh->size = size;
     307        5010 :         if (gf_mo_is_muted(txh->stream)) return;
     308             : 
     309             : 
     310        5010 :         if (txh->nb_frames) {
     311        4345 :                 s32 push_delay = txh->upload_time / txh->nb_frames;
     312        4345 :                 if (push_delay > ms_until_pres) ms_until_pres = 0;
     313        3909 :                 else ms_until_pres -= push_delay;
     314             :         }
     315             : 
     316        5010 :         if (txh->compositor->ms_until_next_frame > ms_until_next)
     317        4696 :                 txh->compositor->ms_until_next_frame = ms_until_next;
     318             : 
     319        5010 :         if (!txh->tx_io) {
     320         388 :                 setup_texture_object(txh, 0);
     321             :         }
     322             : 
     323             :         
     324             :         
     325             :         /*try to push texture on graphics but don't complain if failure*/
     326        5010 :         gf_sc_texture_set_data(txh);
     327             : 
     328        5010 :         txh->needs_refresh = 1;
     329        5010 :         gf_sc_invalidate(txh->compositor, NULL);
     330             : }
     331             : 
     332             : GF_EXPORT
     333       75062 : void gf_sc_texture_release_stream(GF_TextureHandler *txh)
     334             : {
     335       75062 :         txh->needs_refresh = 0;
     336       75062 :         if (txh->needs_release) {
     337             :                 assert(txh->stream);
     338        5009 :                 gf_mo_release_data(txh->stream, 0xFFFFFFFF, (txh->needs_release==2) ? 3 :0);
     339        5009 :                 if (txh->needs_release==2) {
     340         145 :                         txh->last_frame_time = -1;
     341             :                 }
     342        5009 :                 txh->needs_release = 0;
     343        5009 :                 txh->frame_ifce = NULL;
     344             : 
     345             :         }
     346       75062 :         if (txh->stream) txh->stream->config_changed = GF_FALSE;
     347       75062 : }
     348             : 
     349             : 
     350             : GF_EXPORT
     351      115122 : GF_TextureHandler *gf_sc_texture_get_handler(GF_Node *n)
     352             : {
     353      115122 :         if (!n) return NULL;
     354       70447 :         switch (gf_node_get_tag(n)) {
     355             : #ifndef GPAC_DISABLE_VRML
     356       19730 :         case TAG_MPEG4_ImageTexture:
     357             :         case TAG_MPEG4_CacheTexture:
     358       19730 :                 return it_get_texture(n);
     359       16423 :         case TAG_MPEG4_MovieTexture:
     360       16423 :                 return mt_get_texture(n);
     361         746 :         case TAG_MPEG4_PixelTexture:
     362         746 :                 return pt_get_texture(n);
     363             : 
     364        3307 :         case TAG_MPEG4_CompositeTexture2D:
     365             :         case TAG_MPEG4_CompositeTexture3D:
     366        3307 :                 return compositor_get_composite_texture(n);
     367       27340 :         case TAG_MPEG4_LinearGradient:
     368             :         case TAG_MPEG4_RadialGradient:
     369       27340 :                 return compositor_mpeg4_get_gradient_texture(n);
     370             : 
     371           0 :         case TAG_MPEG4_MatteTexture:
     372             :         {
     373           0 :                 GF_TextureHandler *hdl = gf_sc_texture_get_handler( ((M_MatteTexture*)n)->surfaceB );
     374           0 :                 if (hdl) hdl->matteTexture = n;
     375             :                 return hdl;
     376             :         }
     377             : #endif /*GPAC_DISABLE_VRML*/
     378             : 
     379             : #ifndef GPAC_DISABLE_X3D
     380           0 :         case TAG_X3D_ImageTexture:
     381           0 :                 return it_get_texture(n);
     382           0 :         case TAG_X3D_MovieTexture:
     383           0 :                 return mt_get_texture(n);
     384           0 :         case TAG_X3D_PixelTexture:
     385           0 :                 return pt_get_texture(n);
     386             : #endif
     387             : 
     388             : 
     389             : #ifndef GPAC_DISABLE_SVG
     390         210 :         case TAG_SVG_linearGradient:
     391             :         case TAG_SVG_radialGradient:
     392         210 :                 return compositor_svg_get_gradient_texture(n);
     393        2389 :         case TAG_SVG_image:
     394             :         case TAG_SVG_video:
     395        2389 :                 return compositor_svg_get_image_texture(n);
     396             : #endif
     397             : 
     398             : #ifndef GPAC_DISABLE_VRML
     399         302 :     case TAG_ProtoNode:
     400         302 :         return gf_sc_hardcoded_proto_get_texture_handler(n);
     401             : #endif
     402             :         default:
     403             :                 return NULL;
     404             :         }
     405             : }

Generated by: LCOV version 1.13