LCOV - code coverage report
Current view: top level - media_tools - vobsub.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 146 172 84.9 %
Date: 2021-04-29 23:48:07 Functions: 7 8 87.5 %

          Line data    Source code
       1             : /*
       2             :  *          GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *          Copyright (c) by  Falco (Ivan Vecera) 2006
       5             :  *          Copyright (c) Jean Le Feuvre - Telecom ParisTech 2018_2020
       6             :  *                  All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / Media Tools 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             : #include <gpac/list.h>
      28             : #include <gpac/internal/vobsub.h>
      29             : 
      30             : typedef struct _tag_lang_type
      31             : {
      32             :         char id[3];
      33             :         char lang[4];
      34             : } lang_type;
      35             : 
      36             : static lang_type lang_table[] =
      37             : {
      38             :         {"--", "und" },
      39             :         {"aa", "aar" },
      40             :         {"ab", "abk" },
      41             :         {"af", "afr" },
      42             :         {"am", "amh" },
      43             :         {"ar", "ara" },
      44             :         {"as", "ast" },
      45             :         {"ay", "aym" },
      46             :         {"az", "aze" },
      47             :         {"ba", "bak" },
      48             :         {"be", "bel" },
      49             :         {"bg", "bul" },
      50             :         {"bh", "bih" },
      51             :         {"bi", "bis" },
      52             :         {"bn", "ben" },
      53             :         {"bo", "bod" }, // was "tib" (Tibetan)
      54             :         {"br", "bre" },
      55             :         {"ca", "cat" },
      56             :         {"cc", "und" },
      57             :         {"co", "cos" },
      58             :         {"cs", "ces" }, // was "cze" (Czech)
      59             :         {"cy", "cym" }, // was "wel" (Welsh)
      60             :         {"da", "dan" },
      61             :         {"de", "deu" }, // was "ger" (German)
      62             :         {"dz", "dzo" },
      63             :         {"el", "ell" }, // was "gre" (Greek, Modern (1453-))
      64             :         {"en", "eng" },
      65             :         {"eo", "epo" },
      66             :         {"es", "spa" },
      67             :         {"et", "est" },
      68             :         {"eu", "eus" }, // was "baq" (Basque)
      69             :         {"fa", "fas" }, // was "per" (Persian)
      70             :         {"fi", "fin" },
      71             :         {"fj", "fij" },
      72             :         {"fo", "fao" },
      73             :         {"fr", "fra" }, // was "fre" (French)
      74             :         {"fy", "fry" },
      75             :         {"ga", "gle" },
      76             :         {"gl", "glg" },
      77             :         {"gn", "grn" },
      78             :         {"gu", "guj" },
      79             :         {"ha", "hau" },
      80             :         {"he", "heb" },
      81             :         {"hi", "hin" },
      82             :         {"hr", "scr" },
      83             :         {"hu", "hun" },
      84             :         {"hy", "hye" }, // was "arm" (Armenian)
      85             :         {"ia", "ina" },
      86             :         {"id", "ind" },
      87             :         {"ik", "ipk" },
      88             :         {"is", "isl" }, // was "ice" (Icelandic)
      89             :         {"it", "ita" },
      90             :         {"iu", "iku" },
      91             :         {"ja", "jpn" },
      92             :         {"jv", "jav" },
      93             :         {"ka", "kat" }, // was "geo" (Georgian)
      94             :         {"kk", "kaz" },
      95             :         {"kl", "kal" },
      96             :         {"km", "khm" },
      97             :         {"kn", "kan" },
      98             :         {"ko", "kor" },
      99             :         {"ks", "kas" },
     100             :         {"ku", "kur" },
     101             :         {"ky", "kir" },
     102             :         {"la", "lat" },
     103             :         {"ln", "lin" },
     104             :         {"lo", "lao" },
     105             :         {"lt", "lit" },
     106             :         {"lv", "lav" },
     107             :         {"mg", "mlg" },
     108             :         {"mi", "mri" }, // was "mao" (Maori)
     109             :         {"mk", "mkd" }, // was "mac" (Macedonian)
     110             :         {"ml", "mlt" },
     111             :         {"mn", "mon" },
     112             :         {"mo", "mol" },
     113             :         {"mr", "mar" },
     114             :         {"ms", "msa" }, // was "may" (Malay)
     115             :         {"my", "mya" }, // was "bur" (Burmese)
     116             :         {"na", "nau" },
     117             :         {"ne", "nep" },
     118             :         {"nl", "nld" }, // was "dut" (Dutch; Flemish)
     119             :         {"no", "nor" },
     120             :         {"oc", "oci" },
     121             :         {"om", "orm" },
     122             :         {"or", "ori" },
     123             :         {"pa", "pan" },
     124             :         {"pl", "pol" },
     125             :         {"ps", "pus" },
     126             :         {"pt", "por" },
     127             :         {"qu", "que" },
     128             :         {"rm", "roh" },
     129             :         {"rn", "run" },
     130             :         {"ro", "ron" }, // was "rum" (Romanian; Moldavian; Moldovan)
     131             :         {"ru", "rus" },
     132             :         {"rw", "kin" },
     133             :         {"sa", "san" },
     134             :         {"sd", "snd" },
     135             :         {"sg", "sag" },
     136             :         {"sh", "scr" },
     137             :         {"si", "sin" },
     138             :         {"sk", "slk" }, // was "slo" (Slovak)
     139             :         {"sl", "slv" },
     140             :         {"sm", "smo" },
     141             :         {"sn", "sna" },
     142             :         {"so", "som" },
     143             :         {"sq", "sqi" }, // was "alb" (Albanian)
     144             :         {"sr", "srp" },
     145             :         {"ss", "ssw" },
     146             :         {"st", "sot" },
     147             :         {"su", "sun" },
     148             :         {"sv", "swe" },
     149             :         {"sw", "swa" },
     150             :         {"ta", "tam" },
     151             :         {"te", "tel" },
     152             :         {"tg", "tgk" },
     153             :         {"th", "tha" },
     154             :         {"ti", "tir" },
     155             :         {"tk", "tuk" },
     156             :         {"tl", "tgl" },
     157             :         {"tn", "tsn" },
     158             :         {"to", "tog" },
     159             :         {"tr", "tur" },
     160             :         {"ts", "tso" },
     161             :         {"tt", "tat" },
     162             :         {"tw", "twi" },
     163             :         {"ug", "uig" },
     164             :         {"uk", "ukr" },
     165             :         {"ur", "urd" },
     166             :         {"uz", "uzb" },
     167             :         {"vi", "vie" },
     168             :         {"vo", "vol" },
     169             :         {"wo", "wol" },
     170             :         {"xh", "xho" },
     171             :         {"yi", "yid" },
     172             :         {"yo", "yor" },
     173             :         {"za", "zha" },
     174             :         {"zh", "zho" }, // was "chi" (Chinese)
     175             :         {"zu", "zul" }
     176             : };
     177             : 
     178             : 
     179             : 
     180           0 : s32 vobsub_lang_name(u16 id)
     181             : {
     182             :         u16 lang_id;
     183             :         s32 i, count;
     184             : 
     185             :         count = (sizeof(lang_table) / sizeof(lang_table[0]));
     186             : 
     187          52 :         for (i = 0; i < count; i++) {
     188          54 :                 lang_id = (lang_table[i].id[0]<<8) | lang_table[i].id[1];
     189             : 
     190          54 :                 if (id == lang_id) {
     191             :                         return i;
     192             :                 }
     193             :         }
     194             : 
     195             :         return 0; /* Undefined - und */
     196             : }
     197             : 
     198           1 : char *vobsub_lang_id(char *name)
     199             : {
     200             :         s32 i, count;
     201             : 
     202             :         count = (sizeof(lang_table) / sizeof(lang_table[0]));
     203             : 
     204          27 :         for (i = 0; i < count; i++) {
     205          27 :                 if (!stricmp(lang_table[i].lang, name)) {
     206           1 :                         return lang_table[i].id;
     207             :                 }
     208             :         }
     209             : 
     210             :         return "--"; /* Undefined */
     211             : }
     212             : 
     213          90 : static char *strltrim(char *str)
     214             : {
     215          90 :         if (str == NULL) {
     216             :                 return NULL;
     217             :         }
     218             : 
     219         130 :         while (*str) {
     220         128 :                 if (!isspace(*str)) {
     221             :                         return str;
     222             :                 }
     223          40 :                 str++;
     224             :         }
     225             : 
     226             :         return str;
     227             : }
     228             : 
     229          90 : static char *strrtrim(char *str)
     230             : {
     231             :         char *end;
     232             : 
     233          90 :         if (str == NULL) {
     234             :                 return NULL;
     235             :         }
     236             : 
     237          90 :         end = str + strlen(str);
     238             : 
     239         280 :         while (end-- > str) {
     240         188 :                 if (!isspace(*end)) {
     241             :                         return str;
     242             :                 }
     243         100 :                 *end = '\0';
     244             :         }
     245             : 
     246             :         return str;
     247             : }
     248             : 
     249             : static char *strtrim(char *str)
     250             : {
     251          90 :         return strltrim(strrtrim(str));
     252             : }
     253             : 
     254           2 : GF_Err vobsub_read_idx(FILE *file, vobsub_file *vobsub, s32 *version)
     255             : {
     256             :         char  strbuf[256];
     257             :         char *str, *pos, *entry;
     258           2 :         s32   line, id =-1, delay = 0;
     259             :         Bool  error = 0;
     260             : 
     261          52 :         for (line = 0; !error && gf_fgets(strbuf, sizeof(strbuf), file); line++)
     262             :         {
     263             :                 str = strtrim(strbuf);
     264             : 
     265          50 :                 if (line == 0)
     266             :                 {
     267             :                         char *buf = "VobSub index file, v";
     268             : 
     269           2 :                         pos = strstr(str, buf);
     270           2 :                         if (pos == NULL || sscanf(pos + strlen(buf), "%d", version) != 1 || *version > VOBSUBIDXVER)
     271             :                         {
     272             :                                 error = 1;
     273           0 :                                 continue;
     274             :                         }
     275             :                 }
     276          48 :                 else if (strlen(str) == 0)
     277             :                 {
     278           2 :                         continue;
     279             :                 }
     280          46 :                 else if (str[0] == '#')
     281             :                 {
     282           6 :                         continue;
     283             :                 }
     284             : 
     285          42 :                 pos = strchr(str, ':');
     286          42 :                 if (pos == NULL || pos == str)
     287             :                 {
     288           2 :                         continue;
     289             :                 }
     290             : 
     291             :                 entry = str;
     292          40 :                 *pos  = '\0';
     293             : 
     294          40 :                 str = strtrim(pos + 1);
     295          40 :                 if (strlen(str) == 0)
     296             :                 {
     297           0 :                         continue;
     298             :                 }
     299             : 
     300          40 :                 if (stricmp(entry, "size") == 0)
     301             :                 {
     302             :                         s32 w, h;
     303           2 :                         if (sscanf(str, "%dx%d", &w, &h) != 2)
     304             :                         {
     305             :                                 error = 1;
     306             :                         }
     307           2 :                         vobsub->width  = w;
     308           2 :                         vobsub->height = h;
     309             :                 }
     310          38 :                 else if (stricmp(entry, "palette") == 0)
     311             :                 {
     312             :                         s32 c;
     313             :                         u8  palette[16][4];
     314             : 
     315           2 :                         if (sscanf(str, "%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x",
     316             :                                    (u32 *) &palette[0], (u32 *) &palette[1], (u32 *) &palette[2], (u32 *) &palette[3],
     317             :                                    (u32 *) &palette[4], (u32 *) &palette[5], (u32 *) &palette[6], (u32 *) &palette[7],
     318             :                                    (u32 *) &palette[8], (u32 *) &palette[9], (u32 *) &palette[10], (u32 *) &palette[11],
     319             :                                    (u32 *) &palette[12],(u32 *) &palette[13],(u32 *) &palette[14], (u32 *) &palette[15]) != 16)
     320             :                         {
     321             :                                 error = 1;
     322           0 :                                 continue;
     323             :                         }
     324             : 
     325          32 :                         for (c = 0; c < 16; c++)
     326             :                         {
     327             :                                 u8 r, g, b;
     328             : 
     329          32 :                                 r = palette[c][2];
     330          32 :                                 g = palette[c][1];
     331          32 :                                 b = palette[c][0];
     332          32 :                                 vobsub->palette[c][0] = 0;
     333          32 :                                 vobsub->palette[c][1] = (( 66 * r + 129 * g +  25 * b + 128 +  4096) >> 8) & 0xff;
     334          32 :                                 vobsub->palette[c][2] = ((112 * r -  94 * g -  18 * b + 128 + 32768) >> 8) & 0xff;
     335          32 :                                 vobsub->palette[c][3] = ((-38 * r -  74 * g + 112 * b + 128 + 32768) >> 8) & 0xff;
     336             :                         }
     337             :                 }
     338          36 :                 else if (stricmp(entry, "id") == 0)
     339             :                 {
     340             :                         char *buf = "index:";
     341             :                         s32   lang_id;
     342             : 
     343           2 :                         strlwr(str);
     344           2 :                         lang_id = ((str[0] & 0xff) << 8) | (str[1] & 0xff);
     345             : 
     346           2 :                         pos = strstr(str, buf);
     347           2 :                         if (pos == NULL)
     348             :                         {
     349             :                                 error = 1;
     350           0 :                                 continue;
     351             :                         }
     352             : 
     353           2 :                         if (sscanf(pos + strlen(buf), "%d", &id) != 1 || id < 0 || id >= 32)
     354             :                         {
     355             :                                 error = 1;
     356           0 :                                 continue;
     357             :                         }
     358             : 
     359           2 :                         vobsub->langs[id].id   = lang_id;
     360           4 :                         vobsub->langs[id].name = lang_table[vobsub_lang_name((u16)lang_id)].lang;
     361           2 :                         vobsub->langs[id].idx = id;
     362             : 
     363           2 :                         vobsub->langs[id].subpos = gf_list_new();
     364           2 :                         if (vobsub->langs[id].subpos == NULL)
     365             :                         {
     366             :                                 error = 1;
     367           0 :                                 continue;
     368             :                         }
     369             : 
     370             :                         delay = 0;
     371           2 :                         vobsub->num_langs++;
     372             :                 }
     373          34 :                 else if (id >= 0 && stricmp(entry, "delay") == 0)
     374           0 :                 {
     375             :                         s32  hh, mm, ss, ms;
     376             :                         char c;
     377           0 :                         s32  sign = (str[0] == '-') ? -1 : 1;
     378             : 
     379             :                         pos = str;
     380           0 :                         while (*pos == '-' || *pos == '+') pos++;
     381             : 
     382           0 :                         if (sscanf(pos, "%d%c%d%c%d%c%d", &hh, &c, &mm, &c, &ss, &c, &ms) != 7)
     383             :                         {
     384             :                                 error = 1;
     385           0 :                                 continue;
     386             :                         }
     387             : 
     388           0 :                         delay += (hh*60*60*1000 + mm*60*1000 + ss*1000 + ms) * sign;
     389             :                 }
     390          34 :                 else if (id >= 0 && stricmp(entry, "timestamp") == 0)
     391             :                 {
     392             :                         vobsub_pos *vspos;
     393             :                         s32         sign;
     394             :                         char        c;
     395             :                         s32         hh, mm, ss, ms;
     396             :                         char       *buf = "filepos:";
     397             : 
     398          30 :                         vspos = (vobsub_pos*)gf_calloc(1, sizeof(vobsub_pos));
     399          30 :                         if (vspos == NULL) {
     400             :                                 error = 1;
     401           0 :                                 continue;
     402             :                         }
     403             : 
     404          30 :                         sign = (str[0] == '-') ? -1 : 1;
     405          30 :                         while (*str == '-' || *str == '+') str++;
     406             : 
     407          30 :                         if (sscanf(str, "%d%c%d%c%d%c%d", &hh, &c, &mm, &c, &ss, &c, &ms) != 7)
     408             :                         {
     409           0 :                                 gf_free(vspos);
     410             :                                 error = 1;
     411           0 :                                 continue;
     412             :                         }
     413             : 
     414          30 :                         vspos->start = (((hh*60 + mm)*60 + ss)*1000 + ms) * sign + delay;
     415             : 
     416          30 :                         pos = strstr(str, buf);
     417          30 :                         if (pos == NULL)
     418             :                         {
     419           0 :                                 gf_free(vspos);
     420             :                                 error = 1;
     421           0 :                                 continue;
     422             :                         }
     423             : 
     424          30 :                         if (sscanf(pos + strlen(buf), LLX, &vspos->filepos) != 1)
     425             :                         {
     426           0 :                                 gf_free(vspos);
     427             :                                 error = 1;
     428           0 :                                 continue;
     429             :                         }
     430             : 
     431          30 :                         if (delay < 0 && gf_list_count(vobsub->langs[id].subpos) > 0)
     432             :                         {
     433             :                                 vobsub_pos *vspos_next;
     434             : 
     435           0 :                                 vspos_next = (vobsub_pos*)gf_list_get(vobsub->langs[id].subpos, gf_list_count(vobsub->langs[id].subpos) - 1);
     436           0 :                                 if (vspos->start < vspos_next->start)
     437             :                                 {
     438           0 :                                         delay += (s32)(vspos_next->start - vspos->start);
     439           0 :                                         vspos->start = vspos_next->start;
     440             :                                 }
     441             :                         }
     442             : 
     443          30 :                         if (gf_list_add(vobsub->langs[id].subpos, vspos) != GF_OK)
     444             :                         {
     445           0 :                                 gf_free(vspos);
     446             :                                 error = 1;
     447           0 :                                 continue;
     448             :                         }
     449             :                 }
     450             :         }
     451             : 
     452           2 :         return error ? GF_CORRUPTED_DATA : GF_OK;
     453             : }
     454             : 
     455           2 : void vobsub_free(vobsub_file *vobsub)
     456             : {
     457             :         s32 i;
     458             : 
     459           2 :         if (vobsub == NULL)
     460             :                 return;
     461             : 
     462          64 :         for (i = 0; i < 32; i++) {
     463          64 :                 if (vobsub->langs[i].subpos) {
     464             :                         GF_List *list = vobsub->langs[i].subpos;
     465             :                         vobsub_pos *vspos;
     466           2 :                         u32 pos = 0;
     467             : 
     468             :                         do {
     469          32 :                                 vspos = (vobsub_pos*)gf_list_enum(list, &pos);
     470          32 :                                 gf_free(vspos);
     471             :                         }
     472          32 :                         while (vspos != NULL);
     473             : 
     474           2 :                         gf_list_del(list);
     475             :                 }
     476             :         }
     477           2 :         gf_free(vobsub);
     478             : }
     479             : 
     480          30 : GF_Err vobsub_get_subpic_duration(u8 *_data, u32 psize, u32 dsize, u32 *duration)
     481             : {
     482             :         u32 i, dcsq_stm, nxt_dcsq, start_stm, stop_stm;
     483             :         u8 *data = (u8 *)_data;
     484             :         start_stm = 0;
     485             :         stop_stm  = 0;
     486             :         nxt_dcsq  = dsize;
     487             : 
     488          30 :         if (psize) do {
     489             :                 i = nxt_dcsq;
     490          60 :                 dcsq_stm = (data[i+0] << 8) | data[i+1];
     491          60 :                 nxt_dcsq = (data[i+2] << 8) | data[i+3];
     492          60 :                 i += 4;
     493             : 
     494          60 :                 if (nxt_dcsq > psize || nxt_dcsq < dsize) {
     495             :                         return GF_CORRUPTED_DATA;
     496             :                 }
     497             : 
     498             :                 while (1) {
     499             :                         u8  cmd;
     500             :                         int len;
     501             : 
     502         240 :                         cmd = data[i++];
     503             :                         switch (cmd)
     504             :                         {
     505             :                         case 0x00:
     506             :                                 len = 0;
     507             :                                 break;
     508             :                         case 0x01:
     509             :                                 len = 0;
     510             :                                 break;
     511             :                         case 0x02:
     512             :                                 len = 0;
     513             :                                 break;
     514             :                         case 0x03:
     515             :                                 len = 2;
     516             :                                 break;
     517             :                         case 0x04:
     518             :                                 len = 2;
     519             :                                 break;
     520             :                         case 0x05:
     521             :                                 len = 6;
     522             :                                 break;
     523             :                         case 0x06:
     524             :                                 len = 4;
     525             :                                 break;
     526             :                         default:
     527             :                                 len = 0;
     528             :                                 break;
     529             :                         }
     530             : 
     531         240 :                         if (i + len > psize) {
     532             :                                 return GF_CORRUPTED_DATA;
     533             :                         }
     534             : 
     535             :                         i += len;
     536             : 
     537         240 :                         if (cmd == 0x00 || cmd == 0x01) {
     538             :                                 /* start normal or forced displaying */
     539          30 :                                 start_stm = dcsq_stm * 1024;
     540         210 :                         } else if (cmd == 0x02) {
     541             :                                 /* stop displaying */
     542          30 :                                 stop_stm = dcsq_stm * 1024;
     543         180 :                         } else if (cmd > 0x06) {
     544             :                                 /* unknown command or end of control block */
     545             :                                 break;
     546             :                         }
     547             :                 }
     548          60 :         } while (i <= nxt_dcsq && i < psize);
     549             : 
     550          30 :         *duration = stop_stm - start_stm;
     551             : 
     552          30 :         return GF_OK;
     553             : }
     554             : 
     555          14 : GF_Err vobsub_packetize_subpicture(FILE *fsub, u64 pts, u8 *data, u32 dataSize)
     556             : {
     557             :         u8      buf[0x800], ptsbuf[5];
     558             :         int     put_pts = 1;
     559             : 
     560             :         /* Build PTS buffer */
     561          14 :         ptsbuf[0] = (u8)(((pts >> 29) & 0x0e) | 0x21);
     562          14 :         ptsbuf[1] = (u8)(((pts >> 22) & 0xff));
     563          14 :         ptsbuf[2] = (u8)(((pts >> 14) & 0xfe) | 0x01);
     564          14 :         ptsbuf[3] = (u8)(((pts >>  7) & 0xff));
     565          14 :         ptsbuf[4] = (u8)(((pts <<  1) & 0xfe) | 0x01);
     566             : 
     567          51 :         while (dataSize > 0) {
     568             :                 u8      *p;
     569             :                 u32 padLen = 0;
     570             :                 u32 dataLen = sizeof(buf);
     571             :                 u32 packLen;
     572             : 
     573             :                 /* Zerofill packet */
     574             :                 memset(buf, 0, sizeof(buf));
     575             :                 p = buf;
     576             : 
     577             :                 /* Put pack header */
     578             :                 *p++ = 0x00;
     579             :                 *p++ = 0x00;
     580          23 :                 *p++ = 0x01;
     581          23 :                 *p++ = 0xba;
     582          23 :                 *p++ = 0x40;
     583             : 
     584             :                 /* Jump to PES header */
     585             :                 p += 9;
     586             : 
     587             :                 /* Put PES header */
     588             :                 *p++ = 0x00;
     589             :                 *p++ = 0x00;
     590          23 :                 *p++ = 0x01;
     591          23 :                 *p++ = 0xbd;
     592             : 
     593             :                 /* Compute max size of content */
     594             :                 dataLen -= 14; /* Pack header */
     595             :                 dataLen -=  4; /* Start code + Stream ID */
     596             :                 dataLen -=  2; /* PES packet size */
     597             :                 dataLen -=  3; /* PES header extension */
     598          23 :                 dataLen -= put_pts ? 5 : 0; /* PTS */
     599          23 :                 dataLen -=  1; /* Substream ID */
     600             : 
     601             :                 /* Check if the subpicture data fits in packet */
     602          23 :                 if (dataSize <= dataLen) {
     603          14 :                         padLen  = dataLen - dataSize;
     604             :                         dataLen = dataSize;
     605             :                 }
     606             : 
     607             :                 /* Compute and put packet size (PES header extension + PTS + Substream ID + data + padding) */
     608          23 :                 packLen = 3 + (put_pts ? 5 : 0) + 1 + dataLen + ((padLen < 6) ? padLen : 0);
     609          23 :                 *p++ = (packLen >> 8) & 0xff;
     610          23 :                 *p++ = packLen & 0xff;
     611             : 
     612             :                 /* Put PES header extension */
     613          23 :                 *p++ = 0x80;
     614          23 :                 *p++ = put_pts ? 0x80 : 0x00;
     615          23 :                 *p++ = (put_pts ? 5 : 0) + ((padLen < 6) ? padLen : 0);
     616             : 
     617             :                 /* Put PTS */
     618          23 :                 if (put_pts) {
     619          14 :                         *p++ = ptsbuf[0];
     620          14 :                         *p++ = ptsbuf[1];
     621          14 :                         *p++ = ptsbuf[2];
     622          14 :                         *p++ = ptsbuf[3];
     623          14 :                         *p++ = ptsbuf[4];
     624             :                 }
     625             : 
     626             :                 /* Skip padding bytes */
     627          23 :                 if (padLen < 6) {
     628          10 :                         p += padLen;
     629             :                 }
     630             : 
     631             :                 /* Put Substream ID */
     632          23 :                 *p++ = 0x20;
     633             : 
     634             :                 /* Copy data into packet buffer */
     635          23 :                 memcpy(p, data, dataLen);
     636          23 :                 p += dataLen;
     637             : 
     638             :                 /* Put padding bytes if padding len >= 6 */
     639          23 :                 if (padLen >= 6) {
     640          13 :                         padLen -= 6;
     641          13 :                         *p++ = 0x00;
     642          13 :                         *p++ = 0x00;
     643          13 :                         *p++ = 0x01;
     644          13 :                         *p++ = 0xbe;
     645          13 :                         *p++ = (padLen >> 8) & 0xff;
     646          13 :                         *p++ = padLen & 0xff;
     647          13 :                         memset(p, 0, padLen);
     648             :                 }
     649             : 
     650             :                 /* Write packet into file */
     651          23 :                 if (gf_fwrite(buf, sizeof(buf), fsub) != sizeof(buf)) {
     652             :                         return GF_IO_ERR;
     653             :                 }
     654             : 
     655             :                 /* Move data pointer... */
     656          23 :                 data += dataLen;
     657          23 :                 dataSize -= dataLen;
     658             : 
     659             :                 /* Next packet (if any) will not contain PTS */
     660             :                 put_pts = 0;
     661             :         }
     662             : 
     663             :         return GF_OK;
     664             : }

Generated by: LCOV version 1.13