LCOV - code coverage report
Current view: top level - filters - dec_laser.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 83 100 83.0 %
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 2005-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / LASeR 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             : 
      28             : #ifndef GPAC_DISABLE_LASER
      29             : 
      30             : #include <gpac/internal/compositor_dev.h>
      31             : #include <gpac/laser.h>
      32             : #include <gpac/constants.h>
      33             : 
      34             : typedef struct
      35             : {
      36             :         GF_Scene *scene;
      37             :         GF_ObjectManager *odm;
      38             : //      GF_Terminal *app;
      39             :         GF_LASeRCodec *codec;
      40             :         u32 PL, nb_streams;
      41             :         Bool is_playing;
      42             :         GF_FilterPid *out_pid;
      43             : } GF_LSRDecCtx;
      44             : 
      45           2 : static GF_Err lsrdec_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
      46             : {
      47             :         GF_FilterPid *out_pid;
      48             :         u32 ESID=0;
      49           2 :         GF_LSRDecCtx *ctx = gf_filter_get_udta(filter);
      50             :         const GF_PropertyValue *prop;
      51             : 
      52             :         //we must have streamtype SCENE
      53           2 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_STREAM_TYPE);
      54           2 :         if (!prop || (prop->value.uint != GF_STREAM_SCENE)) {
      55             :                 return GF_NOT_SUPPORTED;
      56             :         }
      57           2 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_CODECID);
      58           2 :         if (!prop || (prop->value.uint != GF_CODECID_LASER) ) {
      59             :                 return GF_NOT_SUPPORTED;
      60             :         }
      61             : 
      62           2 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_ESID);
      63           2 :         if (prop) ESID = prop->value.uint;
      64             :         else {
      65           0 :                 prop = gf_filter_pid_get_property(pid, GF_PROP_PID_ID);
      66           0 :                 if (prop) ESID = prop->value.uint;
      67             :         }
      68             : 
      69             :         //we must have a dsi
      70           2 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_DECODER_CONFIG);
      71           2 :         if (!prop || !prop->value.data.ptr || !prop->value.data.size) {
      72             :                 return GF_NON_COMPLIANT_BITSTREAM;
      73             :         }
      74             : 
      75           2 :         if (is_remove) {
      76           0 :                 out_pid = gf_filter_pid_get_udta(pid);
      77           0 :                 if (ctx->out_pid==out_pid)
      78           0 :                         ctx->out_pid = NULL;
      79           0 :                 if (out_pid)
      80           0 :                         gf_filter_pid_remove(out_pid);
      81           0 :                 ctx->nb_streams--;
      82           0 :                 if (ctx->codec && ESID) {
      83           0 :                         return gf_laser_decoder_remove_stream(ctx->codec, ESID);
      84             :                 }
      85             :                 return GF_OK;
      86             :         }
      87             :         //this is a reconfigure
      88           2 :         if (gf_filter_pid_get_udta(pid)) {
      89           1 :                 gf_laser_decoder_remove_stream(ctx->codec, ESID);
      90           1 :                 return gf_laser_decoder_configure_stream(ctx->codec, ESID, prop->value.data.ptr, prop->value.data.size);
      91             :         }
      92             : 
      93             :         //check our namespace
      94           1 :         if (ctx->scene && ! gf_filter_pid_is_filter_in_parents(pid, ctx->scene->root_od->scene_ns->source_filter)) {
      95             :                 return GF_REQUIRES_NEW_INSTANCE;
      96             :         }
      97             : 
      98             :         //declare a new output PID of type scene, codecid RAW
      99           1 :         out_pid = gf_filter_pid_new(filter);
     100           1 :         ctx->nb_streams++;
     101             : 
     102             :         //copy properties at init or reconfig
     103           1 :         gf_filter_pid_copy_properties(out_pid, pid);
     104           1 :         gf_filter_pid_set_property(out_pid, GF_PROP_PID_CODECID, &PROP_UINT(GF_CODECID_RAW) );
     105           1 :         gf_filter_pid_set_udta(pid, out_pid);
     106             : 
     107           1 :         if (!ctx->out_pid)
     108           1 :                 ctx->out_pid = out_pid;
     109             :         return GF_OK;
     110             : }
     111             : 
     112           6 : static Bool lsrdec_process_event(GF_Filter *filter, const GF_FilterEvent *com)
     113             : {
     114             :         u32 count, i;
     115           6 :         GF_LSRDecCtx *ctx = gf_filter_get_udta(filter);
     116             :         //check for scene attach
     117           6 :         switch (com->base.type) {
     118             :         case GF_FEVT_ATTACH_SCENE:
     119             :                 break;
     120           1 :         case GF_FEVT_PLAY:
     121           1 :                 ctx->is_playing = GF_TRUE;
     122           1 :                 return GF_FALSE;
     123             :         default:
     124             :                 return GF_FALSE;
     125             :         }
     126           1 :         if (!com->attach_scene.on_pid) return GF_TRUE;
     127             : 
     128           1 :         count = gf_filter_get_ipid_count(filter);
     129           1 :         for (i=0; i<count; i++) {
     130           1 :                 GF_FilterPid *ipid = gf_filter_get_ipid(filter, i);
     131           1 :                 GF_FilterPid *opid = gf_filter_pid_get_udta(ipid);
     132             :                 //we found our pid, set it up
     133           1 :                 if (opid == com->attach_scene.on_pid) {
     134           1 :                         if (!ctx->odm) {
     135           1 :                                 ctx->odm = com->attach_scene.object_manager;
     136           1 :                                 ctx->scene = ctx->odm->subscene ? ctx->odm->subscene : ctx->odm->parentscene;
     137             : 
     138           1 :                                 ctx->codec = gf_laser_decoder_new(ctx->scene->graph);
     139             :                                 /*attach the clock*/
     140           1 :                                 gf_laser_decoder_set_clock(ctx->codec, gf_scene_get_time, ctx->scene);
     141           1 :                                 gf_filter_pid_set_udta(opid, com->attach_scene.object_manager);
     142           1 :                                 lsrdec_configure_pid(filter, ipid, GF_FALSE);
     143             :                         }
     144             :                         return GF_TRUE;
     145             :                 }
     146             :         }
     147             : 
     148             :         return GF_TRUE;
     149             : }
     150             : 
     151           4 : static GF_Err lsrdec_process(GF_Filter *filter)
     152             : {
     153             :         GF_Err e = GF_OK;
     154             :         GF_FilterPacket *pck;
     155             :         const char *data;
     156             :         u32 size, ESID=0;
     157             :         Double ts_offset;
     158             :         u64 now, cts;
     159             :         u32 obj_time;
     160             :         u32 i, count;
     161             :         const GF_PropertyValue *prop;
     162           4 :         GF_LSRDecCtx *ctx = gf_filter_get_udta(filter);
     163           4 :         GF_Scene *scene = ctx->scene;
     164             : 
     165           4 :         if (!scene) {
     166           0 :                 if (ctx->is_playing) {
     167           0 :                         if (ctx->out_pid && gf_laser_decode_has_conditionnals(ctx->codec)) {
     168           0 :                                 gf_filter_pid_set_info(ctx->out_pid, GF_PROP_PID_KEEP_AFTER_EOS, &PROP_BOOL(GF_TRUE));
     169             :                         }
     170           0 :                         gf_filter_pid_set_eos(ctx->out_pid);
     171           0 :                         return GF_EOS;
     172             :                 }
     173             :                 return GF_OK;
     174             :         }
     175           4 :         if (!ctx->codec) return GF_OK;
     176             : 
     177             : 
     178           4 :         count = gf_filter_get_ipid_count(filter);
     179           8 :         for (i=0; i<count; i++) {
     180           4 :                 GF_FilterPid *pid = gf_filter_get_ipid(filter, i);
     181           4 :                 GF_FilterPid *opid = gf_filter_pid_get_udta(pid);
     182             : 
     183           4 :                 GF_ObjectManager *odm = gf_filter_pid_get_udta(opid);
     184           4 :                 if (!odm) continue;
     185             :                 //object clock shall be valid
     186             :                 assert(odm->ck);
     187             : 
     188           4 :                 pck = gf_filter_pid_get_packet(pid);
     189           4 :                 if (!pck) {
     190           1 :                         Bool is_eos = gf_filter_pid_is_eos(pid);
     191           1 :                         if (is_eos) {
     192           1 :                                 if (ctx->out_pid && gf_laser_decode_has_conditionnals(ctx->codec)) {
     193           1 :                                         gf_filter_pid_set_info(ctx->out_pid, GF_PROP_PID_KEEP_AFTER_EOS, &PROP_BOOL(GF_TRUE));
     194             :                                 }
     195           1 :                                 gf_filter_pid_set_eos(opid);
     196             :                         }
     197           1 :                         continue;
     198             :                 }
     199           3 :                 data = gf_filter_pck_get_data(pck, &size);
     200             : 
     201           3 :                 prop = gf_filter_pid_get_property(pid, GF_PROP_PID_ID);
     202           3 :                 if (prop) ESID = prop->value.uint;
     203             : 
     204           3 :                 cts = gf_filter_pck_get_cts( pck );
     205           3 :                 ts_offset = (Double) cts;
     206           3 :                 ts_offset /= gf_filter_pck_get_timescale(pck);
     207             : 
     208           3 :                 gf_odm_check_buffering(odm, pid);
     209             : 
     210             : 
     211             :                 //we still process any frame before our clock time even when buffering
     212           3 :                 obj_time = gf_clock_time(odm->ck);
     213           3 :                 if (ts_offset * 1000 > obj_time) {
     214           0 :                         gf_sc_sys_frame_pending(ctx->scene->compositor, ts_offset, obj_time, filter);
     215           0 :                         continue;
     216             :                 }
     217             : 
     218           3 :                 now = gf_sys_clock_high_res();
     219           3 :                 e = gf_laser_decode_au(ctx->codec, ESID, data, size);
     220           3 :                 now = gf_sys_clock_high_res() - now;
     221             : 
     222           3 :                 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));
     223             : 
     224           3 :                 gf_filter_pid_drop_packet(pid);
     225             : 
     226           3 :                 if (e) return e;
     227           3 :                 if (odm == ctx->odm)
     228           3 :                         gf_scene_attach_to_compositor(scene);
     229             :         }
     230             :         return GF_OK;
     231             : }
     232             : 
     233           1 : static void lsrdec_finalize(GF_Filter *filter)
     234             : {
     235           1 :         GF_LSRDecCtx *ctx = gf_filter_get_udta(filter);
     236           1 :         if (ctx->codec) gf_laser_decoder_del(ctx->codec);
     237           1 : }
     238             : 
     239             : 
     240             : static const GF_FilterCapability LSRDecCaps[] =
     241             : {
     242             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_STREAM_TYPE, GF_STREAM_SCENE),
     243             :         CAP_UINT(GF_CAPS_INPUT,GF_PROP_PID_CODECID, GF_CODECID_LASER),
     244             :         CAP_BOOL(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
     245             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_SCENE),
     246             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_CODECID, GF_CODECID_RAW),
     247             : };
     248             : 
     249             : 
     250             : GF_FilterRegister LSRDecRegister = {
     251             :         .name = "lsrdec",
     252             :         GF_FS_SET_DESCRIPTION("MPEG-4 LASeR decoder")
     253             :         GF_FS_SET_HELP("This filter decodes MPEG-4 LASeR frames directly into the scene graph of the compositor. It cannot be used to dump LASeR content.")
     254             :         .private_size = sizeof(GF_LSRDecCtx),
     255             :         .flags = GF_FS_REG_MAIN_THREAD,
     256             :         .priority = 1,
     257             :         SETCAPS(LSRDecCaps),
     258             :         .finalize = lsrdec_finalize,
     259             :         .process = lsrdec_process,
     260             :         .configure_pid = lsrdec_configure_pid,
     261             :         .process_event = lsrdec_process_event,
     262             : };
     263             : 
     264             : #endif /*GPAC_DISABLE_LASER*/
     265             : 
     266        2877 : const GF_FilterRegister *lsrdec_register(GF_FilterSession *session)
     267             : {
     268             : #ifdef GPAC_DISABLE_LASER
     269             :         return NULL;
     270             : #else
     271        2877 :         return &LSRDecRegister;
     272             : #endif /*GPAC_DISABLE_LASER*/
     273             : }
     274             : 

Generated by: LCOV version 1.13