LCOV - code coverage report
Current view: top level - filters - dec_bifs.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 97 106 91.5 %
Date: 2021-04-29 23:48:07 Functions: 6 6 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-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / BIFS decoder filter
       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 <gpac/filters.h>
      27             : #include <gpac/bifs.h>
      28             : #include <gpac/constants.h>
      29             : #include <gpac/compositor.h>
      30             : #include <gpac/internal/compositor_dev.h>
      31             : 
      32             : #ifndef GPAC_DISABLE_BIFS
      33             : 
      34             : 
      35             : typedef struct
      36             : {
      37             :         GF_BifsDecoder *bifs_dec;
      38             :         GF_ObjectManager *odm;
      39             :         GF_Scene *scene;
      40             : 
      41             :         Bool is_playing;
      42             :         GF_FilterPid *out_pid;
      43             : } GF_BIFSDecCtx;
      44             : 
      45          11 : static GF_Err bifs_dec_configure_bifs_dec(GF_BIFSDecCtx *ctx, GF_FilterPid *pid)
      46             : {
      47             :         GF_Err e;
      48             :         u32 es_id=0;
      49             :         u32 codecid=0;
      50             :         const GF_PropertyValue *prop;
      51             : 
      52          11 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_ID);
      53          11 :         if (prop) es_id = prop->value.uint;
      54             : 
      55          11 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_CODECID);
      56          11 :         if (prop) codecid = prop->value.uint;
      57             : 
      58             : 
      59             :         //we must have a dsi
      60          11 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
      61          11 :         if (!prop || !prop->value.data.ptr || !prop->value.data.size) {
      62             :                 return GF_NON_COMPLIANT_BITSTREAM;
      63             :         }
      64             : 
      65          11 :         if (!ctx->bifs_dec) {
      66             :                 /*if a node asked for this media object, use the scene graph of the node (AnimationStream in PROTO)*/
      67          11 :                 if (ctx->odm->mo && ctx->odm->mo->node_ptr) {
      68           0 :                         GF_SceneGraph *sg = gf_node_get_graph((GF_Node*)ctx->odm->mo->node_ptr);
      69           0 :                         ctx->bifs_dec = gf_bifs_decoder_new(sg, GF_TRUE);
      70           0 :                         ctx->odm->mo->node_ptr = NULL;
      71             :                 } else {
      72          11 :                         ctx->bifs_dec = gf_bifs_decoder_new(ctx->scene->graph, GF_FALSE);
      73             :                 }
      74             :         }
      75             : 
      76             : 
      77          11 :         e = gf_bifs_decoder_configure_stream(ctx->bifs_dec, es_id, prop->value.data.ptr, prop->value.data.size, codecid);
      78          11 :         if (e) return e;
      79             : 
      80          11 :         return GF_OK;
      81             : }
      82             : 
      83          15 : GF_Err bifs_dec_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
      84             : {
      85             :         GF_FilterPid *out_pid;
      86          15 :         GF_BIFSDecCtx *ctx = gf_filter_get_udta(filter);
      87             :         const GF_PropertyValue *prop;
      88             : 
      89             :         //we must have streamtype SCENE
      90          15 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_STREAM_TYPE);
      91          15 :         if (!prop || (prop->value.uint != GF_STREAM_SCENE)) {
      92             :                 return GF_NOT_SUPPORTED;
      93             :         }
      94          15 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_CODECID);
      95          15 :         if (!prop || ( (prop->value.uint != GF_CODECID_BIFS) && (prop->value.uint != GF_CODECID_BIFS_V2)) ) {
      96             :                 return GF_NOT_SUPPORTED;
      97             :         }
      98             :         //we must have a dsi
      99          15 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
     100          15 :         if (!prop || !prop->value.data.ptr || !prop->value.data.size) {
     101             :                 return GF_NON_COMPLIANT_BITSTREAM;
     102             :         }
     103             : 
     104          15 :         if (is_remove) {
     105           4 :                 out_pid = gf_filter_pid_get_udta(pid);
     106           4 :                 if (ctx->out_pid==out_pid)
     107           4 :                         ctx->out_pid = NULL;
     108           4 :                 if (out_pid)
     109           4 :                         gf_filter_pid_remove(out_pid);
     110             :                 return GF_OK;
     111             :         }
     112             :         //this is a reconfigure
     113          11 :         if (gf_filter_pid_get_udta(pid)) {
     114           0 :                 return bifs_dec_configure_bifs_dec(ctx, pid);
     115             :         }
     116             : 
     117             :         //check our namespace
     118          11 :         if (ctx->scene && ! gf_filter_pid_is_filter_in_parents(pid, ctx->scene->root_od->scene_ns->source_filter)) {
     119             :                 return GF_REQUIRES_NEW_INSTANCE;
     120             :         }
     121             : 
     122             : 
     123             :         //declare a new output PID of type SCENE, codecid RAW
     124          11 :         out_pid = gf_filter_pid_new(filter);
     125             : 
     126             :         //copy properties at init or reconfig
     127          11 :         gf_filter_pid_copy_properties(out_pid, pid);
     128          11 :         gf_filter_pid_set_property(out_pid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_RAW) );
     129          11 :         gf_filter_pid_set_udta(pid, out_pid);
     130             : 
     131          11 :         if (!ctx->out_pid)
     132          11 :                 ctx->out_pid = out_pid;
     133             :         return GF_OK;
     134             : }
     135             : 
     136             : 
     137             : 
     138        1425 : GF_Err bifs_dec_process(GF_Filter *filter)
     139             : {
     140             :         GF_Err e;
     141             :         Double ts_offset;
     142             :         u64 now, cts;
     143             :         u32 obj_time;
     144             :         u32 i, count;
     145             :         const char *data;
     146             :         u32 size, ESID=0;
     147             :         const GF_PropertyValue *prop;
     148             :         GF_FilterPacket *pck;
     149        1425 :         GF_BIFSDecCtx *ctx = gf_filter_get_udta(filter);
     150             : 
     151        1425 :         GF_Scene *scene = ctx->scene;
     152             : 
     153        1425 :         if (!scene) {
     154           0 :                 if (ctx->is_playing) {
     155           0 :                         if (ctx->out_pid && gf_bifs_decode_has_conditionnals(ctx->bifs_dec)) {
     156           0 :                                 gf_filter_pid_set_info(ctx->out_pid, GF_PROP_PID_KEEP_AFTER_EOS, &PROP_BOOL(GF_TRUE));
     157             :                         }
     158           0 :                         gf_filter_pid_set_eos(ctx->out_pid);
     159           0 :                         return GF_EOS;
     160             :                 }
     161             :                 return GF_OK;
     162             :         }
     163        1425 :         if (!ctx->bifs_dec) return GF_OK;
     164             : 
     165        1425 :         count = gf_filter_get_ipid_count(filter);
     166        2850 :         for (i=0; i<count; i++) {
     167        1425 :                 GF_FilterPid *pid = gf_filter_get_ipid(filter, i);
     168        1425 :                 GF_FilterPid *opid = gf_filter_pid_get_udta(pid);
     169             : 
     170        1425 :                 GF_ObjectManager *odm = gf_filter_pid_get_udta(opid);
     171        1425 :                 if (!odm) continue;
     172             :                 //object clock shall be valid
     173             :                 assert(odm->ck);
     174             : 
     175        1425 :                 pck = gf_filter_pid_get_packet(pid);
     176        1425 :                 if (!pck) {
     177          14 :                         Bool is_eos = gf_filter_pid_is_eos(pid);
     178          14 :                         if (is_eos) {
     179          11 :                                 if (opid && gf_bifs_decode_has_conditionnals(ctx->bifs_dec)) {
     180           3 :                                         gf_filter_pid_set_info(opid, GF_PROP_PID_KEEP_AFTER_EOS, &PROP_BOOL(GF_TRUE));
     181             :                                 }
     182          11 :                                 gf_filter_pid_set_eos(opid);
     183             :                         }
     184          14 :                         continue;
     185             :                 }
     186        1411 :                 data = gf_filter_pck_get_data(pck, &size);
     187             : 
     188        1411 :                 prop = gf_filter_pid_get_property(pid, GF_PROP_PID_ID);
     189        1411 :                 if (prop) ESID = prop->value.uint;
     190             : 
     191        1411 :                 cts = gf_filter_pck_get_cts( pck );
     192        1411 :                 ts_offset = (Double) cts;
     193        1411 :                 ts_offset /= gf_filter_pck_get_timescale(pck);
     194             : 
     195        1411 :                 gf_odm_check_buffering(odm, pid);
     196             : 
     197             : 
     198             :                 //we still process any frame before our clock time even when buffering
     199        1411 :                 obj_time = gf_clock_time(odm->ck);
     200        1411 :                 if (ts_offset * 1000 > obj_time) {
     201         939 :                         gf_sc_sys_frame_pending(scene->compositor, ts_offset, obj_time, filter);
     202         939 :                         continue;
     203             :                 }
     204             : 
     205         472 :                 now = gf_sys_clock_high_res();
     206         472 :                 e = gf_bifs_decode_au(ctx->bifs_dec, ESID, data, size, ts_offset);
     207         472 :                 now = gf_sys_clock_high_res() - now;
     208             : 
     209         472 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[BIFS] ODM%d #CH%d at %d decoded AU TS %u in "LLU" us\n", odm->ID, ESID, obj_time, cts, now));
     210             : 
     211         472 :                 gf_filter_pid_drop_packet(pid);
     212             : 
     213         472 :                 if (e) return e;
     214         472 :                 if (odm == ctx->odm)
     215         472 :                         gf_scene_attach_to_compositor(scene);
     216             :         }
     217             :         return GF_OK;
     218             : }
     219             : 
     220          11 : static void bifs_dec_finalize(GF_Filter *filter)
     221             : {
     222          11 :         GF_BIFSDecCtx *ctx = gf_filter_get_udta(filter);
     223          11 :         if (ctx->bifs_dec) gf_bifs_decoder_del(ctx->bifs_dec);
     224          11 : }
     225             : 
     226             : 
     227          73 : static Bool bifs_dec_process_event(GF_Filter *filter, const GF_FilterEvent *com)
     228             : {
     229             :         u32 count, i;
     230          73 :         GF_BIFSDecCtx *ctx = gf_filter_get_udta(filter);
     231             :         //check for scene attach
     232          73 :         switch (com->base.type) {
     233             :         case GF_FEVT_ATTACH_SCENE:
     234             :                 break;
     235          12 :         case GF_FEVT_PLAY:
     236          12 :                 ctx->is_playing = GF_TRUE;
     237          12 :                 return GF_FALSE;
     238             :         case GF_FEVT_RESET_SCENE:
     239             :                 return GF_FALSE;
     240             : 
     241             :         default:
     242             :                 return GF_FALSE;
     243             :         }
     244          11 :         if (!com->attach_scene.on_pid) return GF_TRUE;
     245             : 
     246          11 :         count = gf_filter_get_ipid_count(filter);
     247          11 :         for (i=0; i<count; i++) {
     248          11 :                 GF_FilterPid *ipid = gf_filter_get_ipid(filter, i);
     249          11 :                 GF_FilterPid *opid = gf_filter_pid_get_udta(ipid);
     250             :                 //we found our pid, set it up
     251          11 :                 if (opid == com->attach_scene.on_pid) {
     252          11 :                         if (!ctx->odm) {
     253          11 :                                 ctx->odm = com->attach_scene.object_manager;
     254          11 :                                 ctx->scene = ctx->odm->subscene ? ctx->odm->subscene : ctx->odm->parentscene;
     255             :                         }
     256          11 :                         bifs_dec_configure_bifs_dec(ctx, ipid);
     257          11 :                         gf_filter_pid_set_udta(opid, com->attach_scene.object_manager);
     258          11 :                         return GF_TRUE;
     259             :                 }
     260             :         }
     261             : 
     262             :         return GF_TRUE;
     263             : }
     264             : 
     265             : static const GF_FilterCapability BIFSDecCaps[] =
     266             : {
     267             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_SCENE),
     268             :         CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
     269             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_BIFS),
     270             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_BIFS_V2),
     271             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_SCENE),
     272             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW),
     273             : };
     274             : 
     275             : GF_FilterRegister BIFSDecRegister = {
     276             :         .name = "bifsdec",
     277             :         GF_FS_SET_DESCRIPTION("MPEG-4 BIFS decoder")
     278             :         GF_FS_SET_HELP("This filter decodes MPEG-4 BIFS frames directly into the scene graph of the compositor. It cannot be used to dump BIFS content.")
     279             :         .private_size = sizeof(GF_BIFSDecCtx),
     280             :         .flags = GF_FS_REG_MAIN_THREAD,
     281             :         .priority = 1,
     282             :         SETCAPS(BIFSDecCaps),
     283             :         .finalize = bifs_dec_finalize,
     284             :         .process = bifs_dec_process,
     285             :         .configure_pid = bifs_dec_configure_pid,
     286             :         .process_event = bifs_dec_process_event,
     287             : };
     288             : 
     289             : #endif /*GPAC_DISABLE_BIFS*/
     290             : 
     291        2877 : const GF_FilterRegister *bifs_dec_register(GF_FilterSession *session)
     292             : {
     293             : #ifdef GPAC_DISABLE_BIFS
     294             :         return NULL;
     295             : #else
     296        2877 :         return &BIFSDecRegister;
     297             : #endif /*GPAC_DISABLE_BIFS*/
     298             : }
     299             : 
     300             : 
     301             : 

Generated by: LCOV version 1.13