LCOV - code coverage report
Current view: top level - scene_manager - text_to_bifs.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 215 258 83.3 %
Date: 2021-04-29 23:48:07 Functions: 4 4 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 Management 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             : 
      27             : 
      28             : #include <gpac/constants.h>
      29             : #include <gpac/utf.h>
      30             : #include <gpac/xml.h>
      31             : #include <gpac/internal/media_dev.h>
      32             : #include <gpac/scene_manager.h>
      33             : 
      34             : enum
      35             : {
      36             :         GF_TEXT_IMPORT_NONE = 0,
      37             :         GF_TEXT_IMPORT_SRT,
      38             :         GF_TEXT_IMPORT_SUB,
      39             :         GF_TEXT_IMPORT_TTXT,
      40             :         GF_TEXT_IMPORT_TEXML,
      41             : };
      42             : 
      43             : #define REM_TRAIL_MARKS(__str, __sep) while (1) {       \
      44             :                 u32 _len = (u32) strlen(__str);         \
      45             :                 if (!_len) break;       \
      46             :                 _len--;                         \
      47             :                 if (strchr(__sep, __str[_len])) __str[_len] = 0;        \
      48             :                 else break;     \
      49             :         }       \
      50             :  
      51             : 
      52           2 : static GF_Err gf_text_guess_format(char *filename, u32 *fmt)
      53             : {
      54             :         char szLine[2048], szTest[10];
      55             :         u32 val;
      56           2 :         FILE *test = gf_fopen(filename, "rt");
      57           2 :         if (!test) return GF_URL_ERROR;
      58             : 
      59           2 :         while (gf_fgets(szLine, 2048, test) != NULL) {
      60           4 :                 REM_TRAIL_MARKS(szLine, "\r\n\t ")
      61             : 
      62           2 :                 if (strlen(szLine)) break;
      63             :         }
      64           2 :         *fmt = GF_TEXT_IMPORT_NONE;
      65           2 :         if ((szLine[0]=='{') && strstr(szLine, "}{")) *fmt = GF_TEXT_IMPORT_SUB;
      66           1 :         else if (sscanf(szLine, "%u", &val)==1) {
      67           1 :                 sprintf(szTest, "%u", val);
      68           1 :                 if (!strcmp(szTest, szLine)) *fmt = GF_TEXT_IMPORT_SRT;
      69             :         }
      70           0 :         else if (!strnicmp(szLine, "<?xml ", 6)) {
      71           0 :                 char *ext = gf_file_ext_start(filename);
      72           0 :                 if (!strnicmp(ext, ".ttxt", 5)) *fmt = GF_TEXT_IMPORT_TTXT;
      73           0 :                 ext = strstr(szLine, "?>");
      74           0 :                 if (ext) ext += 2;
      75           0 :                 if (ext && !ext[0]) {
      76           0 :                         if (!gf_fgets(szLine, 2048, test))
      77           0 :                                 szLine[0] = '\0';
      78             :                 }
      79           0 :                 if (strstr(szLine, "x-quicktime-tx3g")) *fmt = GF_TEXT_IMPORT_TEXML;
      80             :         }
      81           2 :         gf_fclose(test);
      82           2 :         return GF_OK;
      83             : }
      84             : 
      85             : #ifndef GPAC_DISABLE_VRML
      86             : 
      87           1 : static GF_Err gf_text_import_srt_bifs(GF_SceneManager *ctx, GF_ESD *src, GF_MuxInfo *mux)
      88             : {
      89             :         GF_Err e;
      90             :         GF_Node *text, *font;
      91             :         GF_StreamContext *srt;
      92             :         FILE *srt_in;
      93             :         GF_FieldInfo string, style;
      94             :         u32 sh, sm, ss, sms, eh, em, es, ems, start, end;
      95             :         GF_AUContext *au;
      96             :         GF_Command *com;
      97             :         SFString *sfstr;
      98             :         GF_CommandField *inf;
      99             :         Bool italic, underlined, bold;
     100             :         u32 state, curLine, line, i, len;
     101             :         char szLine[2048], szText[2048], *ptr;
     102             :         GF_StreamContext *sc = NULL;
     103             : 
     104           1 :         if (!ctx->scene_graph) {
     105           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] base scene not assigned\n"));
     106             :                 return GF_BAD_PARAM;
     107             :         }
     108           1 :         i=0;
     109           2 :         while ((sc = (GF_StreamContext*)gf_list_enum(ctx->streams, &i))) {
     110           1 :                 if (sc->streamType==GF_STREAM_SCENE) break;
     111             :                 sc = NULL;
     112             :         }
     113             : 
     114           1 :         if (!sc) {
     115           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] cannot locate base scene\n"));
     116             :                 return GF_BAD_PARAM;
     117             :         }
     118           1 :         if (!mux->textNode) {
     119           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] Target text node unspecified\n"));
     120             :                 return GF_BAD_PARAM;
     121             :         }
     122           1 :         text = gf_sg_find_node_by_name(ctx->scene_graph, mux->textNode);
     123           1 :         if (!text) {
     124           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] cannot find target text node %s\n", mux->textNode));
     125             :                 return GF_BAD_PARAM;
     126             :         }
     127           1 :         if (gf_node_get_field_by_name(text, "string", &string) != GF_OK) {
     128           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] Target text node %s doesn't look like text\n", mux->textNode));
     129             :                 return GF_BAD_PARAM;
     130             :         }
     131             : 
     132             :         font = NULL;
     133           1 :         if (mux->fontNode) {
     134           1 :                 font = gf_sg_find_node_by_name(ctx->scene_graph, mux->fontNode);
     135           1 :                 if (!font) {
     136           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] cannot find target font node %s\n", mux->fontNode));
     137             :                         return GF_BAD_PARAM;
     138             :                 }
     139           1 :                 if (gf_node_get_field_by_name(font, "style", &style) != GF_OK) {
     140           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] Target font node %s doesn't look like font\n", mux->fontNode));
     141             :                         return GF_BAD_PARAM;
     142             :                 }
     143             :         }
     144             : 
     145           1 :         srt_in = gf_fopen(mux->file_name, "rt");
     146           1 :         if (!srt_in) {
     147           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] cannot open input file %s\n", mux->file_name));
     148             :                 return GF_URL_ERROR;
     149             :         }
     150             : 
     151           1 :         srt = gf_sm_stream_new(ctx, src->ESID, GF_STREAM_SCENE, GF_CODECID_BIFS);
     152           1 :         if (!srt) return GF_OUT_OF_MEM;
     153             : 
     154           1 :         if (!src->slConfig) src->slConfig = (GF_SLConfig *) gf_odf_desc_new(GF_ODF_SLC_TAG);
     155           1 :         src->slConfig->timestampResolution = 1000;
     156           1 :         if (!src->decoderConfig) src->decoderConfig = (GF_DecoderConfig *) gf_odf_desc_new(GF_ODF_DCD_TAG);
     157           1 :         src->decoderConfig->streamType = GF_STREAM_SCENE;
     158           1 :         src->decoderConfig->objectTypeIndication = GF_CODECID_BIFS;
     159             : 
     160             :         e = GF_OK;
     161             :         state = end = 0;
     162             :         curLine = 0;
     163             :         au = NULL;
     164             :         com = NULL;
     165             :         italic = underlined = bold = 0;
     166             :         inf = NULL;
     167             : 
     168             :         while (1) {
     169          24 :                 char *sOK = gf_fgets(szLine, 2048, srt_in);
     170             : 
     171          24 :                 if (sOK) REM_TRAIL_MARKS(szLine, "\r\n\t ")
     172             : 
     173          24 :                         if (!sOK || !strlen(szLine)) {
     174             :                                 state = 0;
     175           7 :                                 if (au) {
     176             :                                         /*if italic or underscore do it*/
     177           5 :                                         if (font && (italic || underlined || bold)) {
     178           3 :                                                 com = gf_sg_command_new(ctx->scene_graph, GF_SG_FIELD_REPLACE);
     179           3 :                                                 com->node = font;
     180           3 :                                                 gf_node_register(font, NULL);
     181           3 :                                                 inf = gf_sg_command_field_new(com);
     182           3 :                                                 inf->fieldIndex = style.fieldIndex;
     183           3 :                                                 inf->fieldType = style.fieldType;
     184           3 :                                                 inf->field_ptr = gf_sg_vrml_field_pointer_new(style.fieldType);
     185           3 :                                                 sfstr = (SFString *)inf->field_ptr;
     186           3 :                                                 if (bold && italic && underlined) sfstr->buffer = gf_strdup("BOLDITALIC UNDERLINED");
     187           3 :                                                 else if (italic && underlined) sfstr->buffer = gf_strdup("ITALIC UNDERLINED");
     188           3 :                                                 else if (bold && underlined) sfstr->buffer = gf_strdup("BOLD UNDERLINED");
     189           3 :                                                 else if (underlined) sfstr->buffer = gf_strdup("UNDERLINED");
     190           3 :                                                 else if (bold && italic) sfstr->buffer = gf_strdup("BOLDITALIC");
     191           2 :                                                 else if (bold) sfstr->buffer = gf_strdup("BOLD");
     192           1 :                                                 else sfstr->buffer = gf_strdup("ITALIC");
     193           3 :                                                 gf_list_add(au->commands, com);
     194             :                                         }
     195             : 
     196           5 :                                         au = gf_sm_stream_au_new(srt, end, 0, 1);
     197           5 :                                         com = gf_sg_command_new(ctx->scene_graph, GF_SG_FIELD_REPLACE);
     198           5 :                                         com->node = text;
     199           5 :                                         gf_node_register(text, NULL);
     200           5 :                                         inf = gf_sg_command_field_new(com);
     201           5 :                                         inf->fieldIndex = string.fieldIndex;
     202           5 :                                         inf->fieldType = string.fieldType;
     203           5 :                                         inf->field_ptr = gf_sg_vrml_field_pointer_new(string.fieldType);
     204           5 :                                         gf_list_add(au->commands, com);
     205             :                                         /*reset font styles so that all AUs are true random access*/
     206           5 :                                         if (font) {
     207           5 :                                                 com = gf_sg_command_new(ctx->scene_graph, GF_SG_FIELD_REPLACE);
     208           5 :                                                 com->node = font;
     209           5 :                                                 gf_node_register(font, NULL);
     210           5 :                                                 inf = gf_sg_command_field_new(com);
     211           5 :                                                 inf->fieldIndex = style.fieldIndex;
     212           5 :                                                 inf->fieldType = style.fieldType;
     213           5 :                                                 inf->field_ptr = gf_sg_vrml_field_pointer_new(style.fieldType);
     214           5 :                                                 gf_list_add(au->commands, com);
     215             :                                         }
     216             :                                         au = NULL;
     217             :                                 }
     218             :                                 inf = NULL;
     219           7 :                                 if (!sOK) break;
     220           6 :                                 continue;
     221             :                         }
     222             : 
     223          17 :                 switch (state) {
     224           5 :                 case 0:
     225           5 :                         if (sscanf(szLine, "%u", &line) != 1) {
     226           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] bad frame format (src: %s)\n", szLine));
     227             :                                 e = GF_CORRUPTED_DATA;
     228             :                                 goto exit;
     229             :                         }
     230           5 :                         if (line != curLine + 1) {
     231           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] bad frame: previous %d - current %d (src: %s)\n", curLine, line, szLine));
     232             :                                 e = GF_CORRUPTED_DATA;
     233             :                                 goto exit;
     234             :                         }
     235             :                         curLine = line;
     236             :                         state = 1;
     237             :                         break;
     238           5 :                 case 1:
     239           5 :                         if (sscanf(szLine, "%u:%u:%u,%u --> %u:%u:%u,%u", &sh, &sm, &ss, &sms, &eh, &em, &es, &ems) != 8) {
     240           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[srt->bifs] bad frame %u (src: %s)\n", curLine, szLine));
     241             :                                 e = GF_CORRUPTED_DATA;
     242             :                                 goto exit;
     243             :                         }
     244           5 :                         start = (3600*sh + 60*sm + ss)*1000 + sms;
     245           5 :                         if (start<end) {
     246           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[srt->bifs] corrupted frame starts before end of previous one (SRT Frame %d) - adjusting time stamps\n", curLine));
     247             :                                 start = end;
     248             :                         }
     249           5 :                         end = (3600*eh + 60*em + es)*1000 + ems;
     250             :                         /*make stream start at 0 by inserting a fake AU*/
     251           5 :                         if ((curLine==1) && start>0) {
     252           1 :                                 au = gf_sm_stream_au_new(srt, 0, 0, 1);
     253           1 :                                 com = gf_sg_command_new(ctx->scene_graph, GF_SG_FIELD_REPLACE);
     254           1 :                                 com->node = text;
     255           1 :                                 gf_node_register(text, NULL);
     256           1 :                                 inf = gf_sg_command_field_new(com);
     257           1 :                                 inf->fieldIndex = string.fieldIndex;
     258           1 :                                 inf->fieldType = string.fieldType;
     259           1 :                                 inf->field_ptr = gf_sg_vrml_field_pointer_new(string.fieldType);
     260           1 :                                 gf_list_add(au->commands, com);
     261             :                         }
     262             : 
     263           5 :                         au = gf_sm_stream_au_new(srt, start, 0, 1);
     264             :                         com = NULL;
     265             :                         state = 2;
     266             :                         italic = underlined = bold = 0;
     267           5 :                         break;
     268             : 
     269             :                 default:
     270             :                         ptr = szLine;
     271             :                         /*FIXME - other styles posssibles ??*/
     272             :                         while (1) {
     273          11 :                                 if (!strnicmp(ptr, "<i>", 3)) {
     274             :                                         italic = 1;
     275           2 :                                         ptr += 3;
     276             :                                 }
     277           9 :                                 else if (!strnicmp(ptr, "<u>", 3)) {
     278             :                                         underlined = 1;
     279           0 :                                         ptr += 3;
     280             :                                 }
     281           9 :                                 else if (!strnicmp(ptr, "<b>", 3)) {
     282             :                                         bold = 1;
     283           2 :                                         ptr += 3;
     284             :                                 }
     285             :                                 else
     286             :                                         break;
     287             :                         }
     288             :                         /*if style remove end markers*/
     289          11 :                         while ((strlen(ptr)>4) && (ptr[strlen(ptr) - 4] == '<') && (ptr[strlen(ptr) - 1] == '>')) {
     290           4 :                                 ptr[strlen(ptr) - 4] = 0;
     291             :                         }
     292             : 
     293           7 :                         if (!com) {
     294           5 :                                 com = gf_sg_command_new(ctx->scene_graph, GF_SG_FIELD_REPLACE);
     295           5 :                                 com->node = text;
     296           5 :                                 gf_node_register(text, NULL);
     297           5 :                                 inf = gf_sg_command_field_new(com);
     298           5 :                                 inf->fieldIndex = string.fieldIndex;
     299           5 :                                 inf->fieldType = string.fieldType;
     300           5 :                                 inf->field_ptr = gf_sg_vrml_field_pointer_new(string.fieldType);
     301           5 :                                 gf_list_add(au->commands, com);
     302             :                         }
     303             :                         assert(inf);
     304           7 :                         gf_sg_vrml_mf_append(inf->field_ptr, GF_SG_VRML_MFSTRING, (void **) &sfstr);
     305             :                         len = 0;
     306         142 :                         for (i=0; i<strlen(ptr); i++) {
     307             :                                 /*FIXME - UTF16 support !!*/
     308         135 :                                 if (ptr[i] & 0x80) {
     309             :                                         /*non UTF8 (likely some win-CP)*/
     310           4 :                                         if ((ptr[i+1] & 0xc0) != 0x80) {
     311           4 :                                                 szText[len] = 0xc0 | ( (ptr[i] >> 6) & 0x3 );
     312           4 :                                                 len++;
     313           4 :                                                 ptr[i] &= 0xbf;
     314             :                                         }
     315             :                                         /*we only handle UTF8 chars on 2 bytes (eg first byte is 0b110xxxxx)*/
     316           0 :                                         else if ((ptr[i] & 0xe0) == 0xc0) {
     317           0 :                                                 szText[len] = ptr[i];
     318           0 :                                                 len++;
     319           0 :                                                 i++;
     320             :                                         }
     321             :                                 }
     322         135 :                                 szText[len] = ptr[i];
     323         135 :                                 len++;
     324             :                         }
     325           7 :                         szText[len] = 0;
     326           7 :                         sfstr->buffer = gf_strdup(szText);
     327           7 :                         break;
     328             :                 }
     329             :         }
     330             : 
     331           1 : exit:
     332           1 :         gf_fclose(srt_in);
     333           1 :         return e;
     334             : }
     335             : #endif /*GPAC_DISABLE_VRML*/
     336             : 
     337             : 
     338             : #ifndef GPAC_DISABLE_VRML
     339             : 
     340           1 : static GF_Err gf_text_import_sub_bifs(GF_SceneManager *ctx, GF_ESD *src, GF_MuxInfo *mux)
     341             : {
     342             :         GF_Err e;
     343             :         GF_Node *text, *font;
     344             :         GF_StreamContext *srt;
     345             :         FILE *sub_in;
     346             :         GF_FieldInfo string, style;
     347             :         u32 start, end, line, i, j, k, len;
     348             :         GF_AUContext *au;
     349             :         GF_Command *com;
     350             :         SFString *sfstr;
     351             :         GF_CommandField *inf;
     352             :         Bool first_samp;
     353             :         char szLine[2048], szTime[30], szText[2048];
     354             :         GF_StreamContext *sc = NULL;
     355             : 
     356           1 :         if (!ctx->scene_graph) {
     357           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[sub->bifs] base scene not assigned\n"));
     358             :                 return GF_BAD_PARAM;
     359             :         }
     360           1 :         i=0;
     361           2 :         while ((sc = (GF_StreamContext*)gf_list_enum(ctx->streams, &i))) {
     362           1 :                 if (sc->streamType==GF_STREAM_SCENE) break;
     363             :                 sc = NULL;
     364             :         }
     365             : 
     366           1 :         if (!sc) {
     367           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[sub->bifs] cannot locate base scene\n"));
     368             :                 return GF_BAD_PARAM;
     369             :         }
     370           1 :         if (!mux->textNode) {
     371           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[sub->bifs] target text node unspecified\n"));
     372             :                 return GF_BAD_PARAM;
     373             :         }
     374           1 :         text = gf_sg_find_node_by_name(ctx->scene_graph, mux->textNode);
     375           1 :         if (!text) {
     376           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[sub->bifs] cannot find target text node %s\n", mux->textNode));
     377             :                 return GF_BAD_PARAM;
     378             :         }
     379           1 :         if (gf_node_get_field_by_name(text, "string", &string) != GF_OK) {
     380           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[sub->bifs] target text node %s doesn't look like text\n", mux->textNode));
     381             :                 return GF_BAD_PARAM;
     382             :         }
     383             : 
     384             :         font = NULL;
     385           1 :         if (mux->fontNode) {
     386           1 :                 font = gf_sg_find_node_by_name(ctx->scene_graph, mux->fontNode);
     387           1 :                 if (!font) {
     388           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[sub->bifs] cannot find target font node %s\n", mux->fontNode));
     389             :                         return GF_BAD_PARAM;
     390             :                 }
     391           1 :                 if (gf_node_get_field_by_name(font, "style", &style) != GF_OK) {
     392           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[sub->bifs] target font node %s doesn't look like font\n", mux->fontNode));
     393             :                         return GF_BAD_PARAM;
     394             :                 }
     395             :         }
     396             : 
     397           1 :         sub_in = gf_fopen(mux->file_name, "rt");
     398           1 :         if (!sub_in) {
     399           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[sub->bifs] cannot open input file %s\n", mux->file_name));
     400             :                 return GF_URL_ERROR;
     401             :         }
     402             : 
     403           1 :         srt = gf_sm_stream_new(ctx, src->ESID, GF_STREAM_SCENE, GF_CODECID_BIFS);
     404           1 :         if (!srt) return GF_OUT_OF_MEM;
     405             : 
     406           1 :         if (!src->slConfig) src->slConfig = (GF_SLConfig *) gf_odf_desc_new(GF_ODF_SLC_TAG);
     407           1 :         src->slConfig->timestampResolution = 1000;
     408           1 :         if (!src->decoderConfig) src->decoderConfig = (GF_DecoderConfig *) gf_odf_desc_new(GF_ODF_DCD_TAG);
     409           1 :         src->decoderConfig->streamType = GF_STREAM_SCENE;
     410           1 :         src->decoderConfig->objectTypeIndication = GF_CODECID_BIFS;
     411             : 
     412             :         e = GF_OK;
     413             :         end = 0;
     414             :         au = NULL;
     415             :         com = NULL;
     416             :         inf = NULL;
     417             : 
     418             :         line = 0;
     419             :         first_samp = 1;
     420             :         while (1) {
     421           6 :                 char *sOK = gf_fgets(szLine, 2048, sub_in);
     422           6 :                 if (!sOK) break;
     423          10 :                 REM_TRAIL_MARKS(szLine, "\r\n\t ")
     424             : 
     425           5 :                 line++;
     426             :                 len = (u32) strlen(szLine);
     427           5 :                 if (!len) continue;
     428             : 
     429           3 :                 i=0;
     430           3 :                 if (szLine[i] != '{') {
     431           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[sub->bifs] Bad frame (line %d): expecting \"{\" got \"%c\"\n", line, szLine[i]));
     432             :                         e = GF_NON_COMPLIANT_BITSTREAM;
     433             :                         break;
     434             :                 }
     435          10 :                 while (szLine[i+1] && szLine[i+1]!='}') {
     436           7 :                         szTime[i] = szLine[i+1];
     437           7 :                         i++;
     438             :                 }
     439           3 :                 szTime[i] = 0;
     440           3 :                 start = atoi(szTime);
     441           3 :                 if (start<end) {
     442           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[sub->bifs] corrupted SUB frame (line %d) - starts (at %d ms) before end of previous one (%d ms) - adjusting time stamps\n", line, start, end));
     443             :                         start = end;
     444             :                 }
     445           3 :                 j=i+2;
     446           3 :                 i=0;
     447           3 :                 if (szLine[i+j] != '{') {
     448           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[sub->bifs] Bad frame - expecting \"{\" got \"%c\"\n", szLine[i]));
     449             :                         e = GF_NON_COMPLIANT_BITSTREAM;
     450             :                         break;
     451             :                 }
     452          11 :                 while (szLine[i+1+j] && szLine[i+1+j]!='}') {
     453           8 :                         szTime[i] = szLine[i+1+j];
     454           8 :                         i++;
     455             :                 }
     456           3 :                 szTime[i] = 0;
     457           3 :                 end = atoi(szTime);
     458           3 :                 j+=i+2;
     459             : 
     460           3 :                 if (start>end) {
     461           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[sub->bifs] corrupted frame (line %d) - ends (at %d ms) before start of current frame (%d ms) - skipping\n", line, end, start));
     462           0 :                         continue;
     463             :                 }
     464             : 
     465           3 :                 if (start && first_samp) {
     466           3 :                         au = gf_sm_stream_au_new(srt, 0, 0, 1);
     467           3 :                         com = gf_sg_command_new(ctx->scene_graph, GF_SG_FIELD_REPLACE);
     468           3 :                         com->node = text;
     469           3 :                         gf_node_register(text, NULL);
     470           3 :                         inf = gf_sg_command_field_new(com);
     471           3 :                         inf->fieldIndex = string.fieldIndex;
     472           3 :                         inf->fieldType = string.fieldType;
     473           3 :                         inf->field_ptr = gf_sg_vrml_field_pointer_new(string.fieldType);
     474           3 :                         gf_list_add(au->commands, com);
     475             :                 }
     476             : 
     477             :                 k=0;
     478          70 :                 for (i=j; i<len; i++) {
     479          67 :                         if (szLine[i]=='|') {
     480           1 :                                 szText[k] = '\n';
     481             :                         } else {
     482          66 :                                 if (szLine[i] & 0x80) {
     483             :                                         /*non UTF8 (likely some win-CP)*/
     484           4 :                                         if ( (szLine[i+1] & 0xc0) != 0x80) {
     485           4 :                                                 szText[k] = 0xc0 | ( (szLine[i] >> 6) & 0x3 );
     486           4 :                                                 k++;
     487           4 :                                                 szLine[i] &= 0xbf;
     488             :                                         }
     489             :                                         /*we only handle UTF8 chars on 2 bytes (eg first byte is 0b110xxxxx)*/
     490           0 :                                         else if ( (szLine[i] & 0xe0) == 0xc0) {
     491           0 :                                                 szText[k] = szLine[i];
     492           0 :                                                 i++;
     493           0 :                                                 k++;
     494             :                                         }
     495             :                                 }
     496          66 :                                 szText[k] = szLine[i];
     497             :                         }
     498          67 :                         k++;
     499             :                 }
     500           3 :                 szText[i-j] = 0;
     501             : 
     502           3 :                 if (au) {
     503           3 :                         com = gf_sg_command_new(ctx->scene_graph, GF_SG_FIELD_REPLACE);
     504           3 :                         com->node = text;
     505           3 :                         gf_node_register(text, NULL);
     506           3 :                         inf = gf_sg_command_field_new(com);
     507           3 :                         inf->fieldIndex = string.fieldIndex;
     508           3 :                         inf->fieldType = string.fieldType;
     509           3 :                         inf->field_ptr = gf_sg_vrml_field_pointer_new(string.fieldType);
     510           3 :                         gf_list_add(au->commands, com);
     511             : 
     512           3 :                         gf_sg_vrml_mf_append(inf->field_ptr, GF_SG_VRML_MFSTRING, (void **) &sfstr);
     513           3 :                         sfstr->buffer = gf_strdup(szText);
     514             :                 }
     515             :         }
     516           1 :         gf_fclose(sub_in);
     517           1 :         return e;
     518             : }
     519             : #endif
     520             : 
     521             : 
     522             : GF_EXPORT
     523           2 : GF_Err gf_sm_import_bifs_subtitle(GF_SceneManager *ctx, GF_ESD *src, GF_MuxInfo *mux)
     524             : {
     525             : #ifndef GPAC_DISABLE_VRML
     526             :         GF_Err e;
     527             :         u32 fmt;
     528           2 :         e = gf_text_guess_format(mux->file_name, &fmt);
     529           2 :         if (e) return e;
     530           2 :         if (!fmt || (fmt>=3)) return GF_NOT_SUPPORTED;
     531             : 
     532           2 :         if (fmt==1) return gf_text_import_srt_bifs(ctx, src, mux);
     533           1 :         else return gf_text_import_sub_bifs(ctx, src, mux);
     534             : #else
     535             :         return GF_NOT_SUPPORTED;
     536             : #endif
     537             : }
     538             : 

Generated by: LCOV version 1.13