LCOV - code coverage report
Current view: top level - utils - bitstream.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 759 830 91.4 %
Date: 2021-04-29 23:48:07 Functions: 68 68 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-2020
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / common 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             : #include <gpac/bitstream.h>
      27             : 
      28             : /*the default size for new streams allocation...*/
      29             : #define BS_MEM_BLOCK_ALLOC_SIZE         512
      30             : 
      31             : /*private types*/
      32             : enum
      33             : {
      34             :         GF_BITSTREAM_FILE_READ = GF_BITSTREAM_WRITE_DYN + 1,
      35             :         GF_BITSTREAM_FILE_WRITE,
      36             : };
      37             : 
      38             : struct __tag_bitstream
      39             : {
      40             :         /*original stream data*/
      41             :         FILE *stream;
      42             : 
      43             :         /*or original data*/
      44             :         char *original;
      45             :         /*the size of our buffer in bytes*/
      46             :         u64 size;
      47             :         /*current position in BYTES*/
      48             :         u64 position;
      49             :         /*the byte readen/written*/
      50             :         u32 current;
      51             :         /*the number of bits in the current byte*/
      52             :         u32 nbBits;
      53             :         /*the bitstream mode*/
      54             :         u32 bsmode;
      55             : 
      56             :         void (*EndOfStream)(void *par);
      57             :         void *par;
      58             : 
      59             : 
      60             :         char *cache_write;
      61             :         u32 cache_write_size, buffer_written;
      62             : 
      63             :         Bool remove_emul_prevention_byte;
      64             :         u32 nb_zeros;
      65             : 
      66             :         GF_Err (*on_block_out)(void *cbk, u8 *data, u32 block_size);
      67             :         void *usr_data;
      68             :         u64 bytes_out;
      69             :         u32 prevent_dispatch;
      70             : 
      71             :         u64 cookie;
      72             : 
      73             :         u8 *cache_read;
      74             :         u32 cache_read_size, cache_read_pos, cache_read_alloc;
      75             : 
      76             :         void (*on_log)(void *udta, const char *field_name, u32 nb_bits, u64 field_val, s32 idx1, s32 idx2, s32 idx3);
      77             :         void *log_udta;
      78             : };
      79             : 
      80     2797466 : GF_Err gf_bs_reassign_buffer(GF_BitStream *bs, const u8 *buffer, u64 BufferSize)
      81             : {
      82     2797466 :         if (!bs) return GF_BAD_PARAM;
      83     2797466 :         if (bs->bsmode == GF_BITSTREAM_READ) {
      84     1843133 :                 bs->original = (char*)buffer;
      85     1843133 :                 bs->size = BufferSize;
      86     1843133 :                 bs->position = 0;
      87     1843133 :                 bs->current = 0;
      88     1843133 :                 bs->nbBits = 8;
      89             :                 bs->current = 0;
      90     1843133 :                 bs->nb_zeros = 0;
      91     1843133 :                 return GF_OK;
      92             :         }
      93      954333 :         if (bs->bsmode==GF_BITSTREAM_WRITE) {
      94      826558 :                 if (!buffer || !BufferSize) return GF_BAD_PARAM;
      95      826558 :                 bs->original = (char*)buffer;
      96      826558 :                 bs->size = BufferSize;
      97      826558 :                 bs->position = 0;
      98      826558 :                 bs->current = 0;
      99      826558 :                 bs->nbBits = 0;
     100             :                 bs->current = 0;
     101      826558 :                 return GF_OK;
     102             :         }
     103      127775 :         if (bs->bsmode!=GF_BITSTREAM_WRITE_DYN) return GF_BAD_PARAM;
     104      127775 :         if (bs->original) return GF_BAD_PARAM;
     105             : 
     106      110731 :         bs->position = 0;
     107      110731 :         bs->current = 0;
     108      110731 :         bs->nbBits = 0;
     109             :         bs->current = 0;
     110      110731 :         bs->size = BufferSize ? BufferSize : BS_MEM_BLOCK_ALLOC_SIZE;
     111      110731 :         if (buffer) {
     112      110731 :                 bs->original = (char *) buffer;
     113             :         } else {
     114           0 :                 bs->original = (char *) gf_malloc(sizeof(char) * ((u32) bs->size));
     115           0 :                 if (! bs->original) {
     116             :                         return GF_OUT_OF_MEM;
     117             :                 }
     118             :         }
     119             :         return GF_OK;
     120             : }
     121             : 
     122             : GF_EXPORT
     123      552356 : GF_BitStream *gf_bs_new(const u8 *buffer, u64 BufferSize, u32 mode)
     124             : {
     125      552356 :         GF_BitStream *tmp = (GF_BitStream *)gf_malloc(sizeof(GF_BitStream));
     126      552356 :         if (!tmp) return NULL;
     127             :         memset(tmp, 0, sizeof(GF_BitStream));
     128             : 
     129      552356 :         tmp->original = (char*)buffer;
     130      552356 :         tmp->size = BufferSize;
     131             : 
     132      552356 :         tmp->bsmode = mode;
     133             : 
     134      552356 :         switch (tmp->bsmode) {
     135      311944 :         case GF_BITSTREAM_READ:
     136      311944 :                 tmp->nbBits = 8;
     137      311944 :                 tmp->current = 0;
     138      311944 :                 break;
     139      240412 :         case GF_BITSTREAM_WRITE:
     140             :         case GF_BITSTREAM_WRITE_DYN:
     141      240412 :                 tmp->nbBits = 0;
     142      240412 :                 if (! buffer) {
     143             :                         /*if BufferSize is specified, use it. This is typically used when AvgSize of
     144             :                         some buffers is known, but some exceed it.*/
     145      239045 :                         if (BufferSize) {
     146             :                                 tmp->size = BufferSize;
     147             :                         } else {
     148      239000 :                                 tmp->size = BS_MEM_BLOCK_ALLOC_SIZE;
     149             :                         }
     150      239045 :                         tmp->original = (char *) gf_malloc(sizeof(char) * ((u32) tmp->size));
     151      239045 :                         if (! tmp->original) {
     152           0 :                                 gf_free(tmp);
     153           0 :                                 return NULL;
     154             :                         }
     155      239045 :                         tmp->bsmode = GF_BITSTREAM_WRITE_DYN;
     156             :                 } else {
     157             :                         tmp->original = (char*)buffer;
     158             :                         tmp->size = BufferSize;
     159             :                 }
     160             :                 break;
     161           0 :         default:
     162             :                 /*the stream constructor is not the same...*/
     163           0 :                 gf_free(tmp);
     164           0 :                 return NULL;
     165             :         }
     166             :         return tmp;
     167             : }
     168             : 
     169             : GF_EXPORT
     170       10011 : GF_BitStream *gf_bs_from_file(FILE *f, u32 mode)
     171             : {
     172             :         GF_BitStream *tmp;
     173       10011 :         if (!f) return NULL;
     174             : 
     175       10011 :         tmp = (GF_BitStream *)gf_malloc(sizeof(GF_BitStream));
     176       10011 :         if (!tmp) return NULL;
     177             :         memset(tmp, 0, sizeof(GF_BitStream));
     178             :         /*switch to internal mode*/
     179       10011 :         mode = (mode==GF_BITSTREAM_READ) ? GF_BITSTREAM_FILE_READ : GF_BITSTREAM_FILE_WRITE;
     180       10011 :         tmp->bsmode = mode;
     181       10011 :         tmp->current = 0;
     182       10011 :         tmp->nbBits = (mode == GF_BITSTREAM_FILE_READ) ? 8 : 0;
     183       10011 :         tmp->original = NULL;
     184       10011 :         tmp->position = 0;
     185       10011 :         tmp->stream = f;
     186             : 
     187             :         /*get the size of this file (for read streams)*/
     188       10011 :         tmp->position = gf_ftell(f);
     189       10011 :         tmp->size = gf_fsize(f);
     190       10011 :         gf_fseek(f, tmp->position, SEEK_SET);
     191             : 
     192             : 
     193       10011 :         if (mode==GF_BITSTREAM_FILE_READ) {
     194        8091 :                 tmp->cache_read_alloc = gf_opts_get_int("core", "bs-cache-size");
     195        8091 :                 if (tmp->cache_read_alloc) {
     196        8091 :                         tmp->cache_read_pos = tmp->cache_read_size = tmp->cache_read_alloc;
     197        8091 :                         tmp->cache_read = gf_malloc(tmp->cache_read_alloc);
     198        8091 :                         if (!tmp->cache_read) {
     199           0 :                                 gf_free(tmp);
     200           0 :                                 return NULL;
     201             :                         }
     202             :                 }
     203             :         }
     204       10011 :         if (mode == GF_BITSTREAM_FILE_WRITE) {
     205        1920 :                 tmp->cache_write_size = gf_opts_get_int("core", "bs-cache-size");
     206        1920 :                 if (tmp->cache_write_size) {
     207        1920 :                         tmp->cache_write = (char*)gf_malloc(tmp->cache_write_size);
     208        1920 :                         if (!tmp->cache_write) {
     209           0 :                                 gf_free(tmp);
     210           0 :                                 return NULL;
     211             :                         }
     212        1920 :                         tmp->buffer_written = 0;
     213             :                 }
     214             :         }
     215             : 
     216             :         return tmp;
     217             : }
     218             : 
     219             : 
     220        4218 : GF_BitStream *gf_bs_new_cbk_buffer(GF_Err (*on_block_out)(void *cbk, u8 *data, u32 block_size), void *usr_data, u8 *buffer, u32 buffer_size)
     221             : {
     222             :         GF_BitStream *tmp;
     223             : 
     224        4218 :         if (!on_block_out) return NULL;
     225             : 
     226        4218 :         tmp = (GF_BitStream *)gf_malloc(sizeof(GF_BitStream));
     227        4218 :         if (!tmp) return NULL;
     228             :         memset(tmp, 0, sizeof(GF_BitStream));
     229             : 
     230        4218 :         if (buffer && buffer_size) {
     231        3157 :                 tmp->size = buffer_size;
     232        3157 :                 tmp->original = buffer;
     233             :         } else {
     234        1061 :                 tmp->size = buffer_size ? buffer_size : 10*BS_MEM_BLOCK_ALLOC_SIZE;
     235        1061 :                 tmp->original = (char *) gf_malloc(sizeof(char) * ((u32) tmp->size));
     236        1061 :                 if (! tmp->original) {
     237           0 :                         gf_free(tmp);
     238           0 :                         return NULL;
     239             :                 }
     240             :         }
     241        4218 :         tmp->bsmode = GF_BITSTREAM_WRITE_DYN;
     242        4218 :         tmp->on_block_out = on_block_out;
     243        4218 :         tmp->usr_data = usr_data;
     244             : 
     245        4218 :         return tmp;
     246             : }
     247             : 
     248         722 : GF_BitStream *gf_bs_new_cbk(GF_Err (*on_block_out)(void *cbk, u8 *data, u32 block_size), void *usr_data, u32 block_size)
     249             : {
     250         722 :         return gf_bs_new_cbk_buffer(on_block_out, usr_data, NULL, block_size);
     251             : 
     252             : }
     253        9933 : void gf_bs_prevent_dispatch(GF_BitStream *bs, Bool prevent_dispatch)
     254             : {
     255        9933 :         if (!bs) return;
     256        9933 :         if (prevent_dispatch) {
     257        6150 :                 bs->prevent_dispatch ++;
     258        6150 :                 return;
     259             :         }
     260        3783 :         if (!bs->prevent_dispatch) return;
     261        3783 :         bs->prevent_dispatch --;
     262             : 
     263        3783 :         if (bs->on_block_out && !bs->prevent_dispatch) {
     264             :                 assert(bs->position >= bs->bytes_out);
     265        1337 :                 if (bs->position > bs->bytes_out) {
     266        1337 :                         bs->on_block_out(bs->usr_data, bs->original, (u32) (bs->position - bs->bytes_out));
     267        1337 :                         bs->bytes_out = bs->position;
     268             :                 }
     269             :         }
     270             : }
     271             : 
     272     1527237 : static void bs_flush_write_cache(GF_BitStream *bs)
     273             : {
     274     1527237 :         if (bs->buffer_written) {
     275             :                 u32 nb_write;
     276      234328 :                 nb_write = (u32) gf_fwrite(bs->cache_write, bs->buffer_written, bs->stream);
     277             : 
     278             :                 //check we didn't rewind the bitstream
     279      234328 :                 if (bs->size == bs->position)
     280      233961 :                         bs->size += nb_write;
     281      234328 :                 bs->position += nb_write;
     282      234328 :                 bs->buffer_written = 0;
     283             :         }
     284     1527237 : }
     285             : 
     286             : 
     287             : 
     288             : GF_EXPORT
     289      566585 : void gf_bs_del(GF_BitStream *bs)
     290             : {
     291      566585 :         if (!bs) return;
     292      566585 :         if (bs->on_block_out && bs->position>bs->bytes_out) {
     293         610 :                 bs->on_block_out(bs->usr_data, bs->original, (u32) (bs->position - bs->bytes_out) );
     294             :         }
     295             :         /*if we are in dynamic mode (alloc done by the bitstream), free the buffer if still present*/
     296      566585 :         if ((bs->bsmode == GF_BITSTREAM_WRITE_DYN) && bs->original) gf_free(bs->original);
     297      566585 :         if (bs->cache_write) {
     298        1920 :                 bs_flush_write_cache(bs);
     299        1920 :                 gf_free(bs->cache_write);
     300             :         }
     301      566585 :         if (bs->cache_read)
     302        8091 :                 gf_free(bs->cache_read);
     303      566585 :         gf_free(bs);
     304             : }
     305             : 
     306             : GF_EXPORT
     307     1516939 : void gf_bs_enable_emulation_byte_removal(GF_BitStream *bs, Bool do_remove)
     308             : {
     309     1516939 :         if (bs) {
     310     1516939 :                 bs->remove_emul_prevention_byte = do_remove;
     311     1516939 :                 bs->nb_zeros = 0;
     312             :         }
     313     1516939 : }
     314             : 
     315             : /*returns 1 if aligned wrt current mode, 0 otherwise*/
     316           1 : Bool gf_bs_is_align(GF_BitStream *bs)
     317             : {
     318     4697168 :         switch (bs->bsmode) {
     319     1524650 :         case GF_BITSTREAM_READ:
     320             :         case GF_BITSTREAM_FILE_READ:
     321     1524650 :                 return ( (8 == bs->nbBits) ? GF_TRUE : GF_FALSE);
     322     3172518 :         default:
     323     3172518 :                 return !bs->nbBits;
     324             :         }
     325             : }
     326             : 
     327     3156274 : static GFINLINE u8 gf_bs_load_byte(GF_BitStream *bs, Bool *is_eos)
     328             : {
     329             :         u8 res;
     330     3156274 :         if (bs->cache_read) {
     331     3156274 :                 if (bs->cache_read_pos == bs->cache_read_size) {
     332      623798 :                         bs->cache_read_size = (u32) gf_fread(bs->cache_read, bs->cache_read_alloc, bs->stream);
     333      623798 :                         bs->cache_read_pos = 0;
     334      623798 :                         if (!bs->cache_read_size) {
     335           0 :                                 *is_eos = GF_TRUE;
     336           0 :                                 return 0;
     337             :                         }
     338             :                 }
     339     3156274 :                 res = bs->cache_read[bs->cache_read_pos];
     340     3156274 :                 bs->cache_read_pos++;
     341             :         } else {
     342           0 :                 res = gf_fgetc(bs->stream);
     343             :         }
     344             :         return res;
     345             : }
     346             : 
     347             : /*fetch a new byte in the bitstream switch between packets*/
     348    51990949 : static u8 BS_ReadByte(GF_BitStream *bs)
     349             : {
     350             :         Bool is_eos;
     351    51990949 :         if (bs->bsmode == GF_BITSTREAM_READ) {
     352             :                 u8 res;
     353    48846487 :                 if (bs->position >= bs->size) {
     354         569 :                         if (bs->EndOfStream) bs->EndOfStream(bs->par);
     355             :                         return 0;
     356             :                 }
     357    48845918 :                 res = bs->original[bs->position++];
     358             : 
     359    48845918 :                 if (bs->remove_emul_prevention_byte) {
     360     5034698 :                         if ((bs->nb_zeros==2) && (res==0x03) && (bs->position<bs->size) && (bs->original[bs->position]<0x04)) {
     361       20359 :                                 bs->nb_zeros = 0;
     362       20359 :                                 res = bs->original[bs->position++];
     363             :                         }
     364     5034698 :                         if (!res) bs->nb_zeros++;
     365     4947314 :                         else bs->nb_zeros = 0;
     366             :                 }
     367             :                 return res;
     368             :         }
     369     3144462 :         if (bs->cache_write)
     370           0 :                 bs_flush_write_cache(bs);
     371             : 
     372     3144462 :         is_eos = gf_feof(bs->stream);
     373             : 
     374             :         /*we are in FILE mode, test for end of file*/
     375     3144462 :         if (!is_eos || bs->cache_read) {
     376             :                 u8 res;
     377     3144462 :                 Bool loc_eos=GF_FALSE;
     378             :                 assert(bs->position<=bs->size);
     379     3144462 :                 bs->position++;
     380             : 
     381     3144462 :                 res = gf_bs_load_byte(bs, &loc_eos);
     382     3144462 :                 if (loc_eos) goto bs_eof;
     383             : 
     384     3144462 :                 if (bs->remove_emul_prevention_byte) {
     385     2087765 :                         if ((bs->nb_zeros==2) && (res==0x03) && (bs->position<bs->size)) {
     386       11812 :                                 u8 next = gf_bs_load_byte(bs, &loc_eos);
     387       11812 :                                 if (next < 0x04) {
     388       11812 :                                         bs->nb_zeros = 0;
     389             :                                         res = next;
     390       11812 :                                         bs->position++;
     391             :                                 } else {
     392           0 :                                         gf_bs_seek(bs, bs->position);
     393             :                                 }
     394             :                         }
     395     2087765 :                         if (!res) bs->nb_zeros++;
     396     1362331 :                         else bs->nb_zeros = 0;
     397             :                 }
     398     3144462 :                 return res;
     399             :         }
     400             : 
     401           0 : bs_eof:
     402           0 :         if (bs->EndOfStream) {
     403           0 :                 bs->EndOfStream(bs->par);
     404             :         } else {
     405           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[BS] Attempt to overread bitstream\n"));
     406             :         }
     407             :         assert(bs->position <= 1+bs->size);
     408             :         return 0;
     409             : }
     410             : 
     411             : #define NO_OPTS
     412             : 
     413             : #ifndef NO_OPTS
     414             : static u32 bit_mask[] = {0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1};
     415             : static u32 bits_mask[] = {0x0, 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F};
     416             : #endif
     417             : 
     418             : GF_EXPORT
     419   146430011 : u8 gf_bs_read_bit(GF_BitStream *bs)
     420             : {
     421   146430011 :         if (bs->nbBits == 8) {
     422    18744227 :                 bs->current = BS_ReadByte(bs);
     423    18744227 :                 bs->nbBits = 0;
     424             :         }
     425             : #ifdef NO_OPTS
     426             :         {
     427             :                 s32 ret;
     428   146430011 :                 bs->current <<= 1;
     429   146430011 :                 bs->nbBits++;
     430   146430011 :                 ret = (bs->current & 0x100) >> 8;
     431   146430011 :                 return (u8) ret;
     432             :         }
     433             : #else
     434             :         return (u8) (bs->current & bit_mask[bs->nbBits++]) ? 1 : 0;
     435             : #endif
     436             : 
     437             : }
     438             : 
     439             : GF_EXPORT
     440    37728788 : u32 gf_bs_read_int(GF_BitStream *bs, u32 nBits)
     441             : {
     442             :         u32 ret;
     443             : 
     444             : #ifndef NO_OPTS
     445             :         if (nBits + bs->nbBits <= 8) {
     446             :                 bs->nbBits += nBits;
     447             :                 ret = (bs->current >> (8 - bs->nbBits) ) & bits_mask[nBits];
     448             :                 return ret;
     449             :         }
     450             : #endif
     451             :         ret = 0;
     452   220323437 :         while (nBits-- > 0) {
     453   144865861 :                 ret <<= 1;
     454   144865861 :                 ret |= gf_bs_read_bit(bs);
     455             :         }
     456    37728788 :         return ret;
     457             : }
     458             : 
     459             : GF_EXPORT
     460    30927454 : u32 gf_bs_read_u8(GF_BitStream *bs)
     461             : {
     462             :         assert(bs->nbBits==8);
     463    30927454 :         if (bs->cache_read && (bs->cache_read_pos+1<bs->cache_read_size) ) {
     464      101132 :                 u32 ret = bs->cache_read[bs->cache_read_pos];
     465      101132 :                 bs->cache_read_pos+=1;
     466      101132 :                 bs->position+=1;
     467      101132 :                 return ret;
     468             :         }
     469             : 
     470    30826322 :         return (u32) BS_ReadByte(bs);
     471             : }
     472             : 
     473             : #if 0
     474             : GF_EXPORT
     475             : u32 gf_bs_read_u8_until_delimiter(GF_BitStream *bs, u8 delimiter, u8* out, u32 max_length) {
     476             :         u32 i = 0;
     477             :         char token=0;
     478             :         u64 cur_pos = gf_bs_get_position(bs);
     479             : 
     480             :         if (!max_length) out = NULL;
     481             : 
     482             :         while(gf_bs_available(bs) && (!max_length || i < max_length)) {
     483             :                 gf_bs_read_data(bs, &token, 1);
     484             :                 if (token == delimiter) goto found;
     485             :                 if (out) out[i] = token;
     486             :                 i++;
     487             :         }
     488             : 
     489             :         /* Delimiter not found */
     490             :         gf_bs_seek(bs, cur_pos);
     491             :         return 0;
     492             : 
     493             : found:
     494             :         return i;
     495             : }
     496             : #endif
     497             : 
     498             : GF_EXPORT
     499      395770 : u32 gf_bs_read_u16(GF_BitStream *bs)
     500             : {
     501             :         u32 ret;
     502             :         assert(bs->nbBits==8);
     503      395770 :         if (bs->cache_read && (bs->cache_read_pos+2<bs->cache_read_size) ) {
     504       39140 :                 ret = bs->cache_read[bs->cache_read_pos];
     505       39140 :                 ret<<=8;
     506       39140 :                 ret |= bs->cache_read[bs->cache_read_pos+1];
     507       39140 :                 bs->cache_read_pos+=2;
     508       39140 :                 bs->position+=2;
     509       39140 :                 return ret;
     510             :         }
     511             : 
     512      356630 :         ret = BS_ReadByte(bs);
     513      356630 :         ret<<=8;
     514      356630 :         ret |= BS_ReadByte(bs);
     515      356630 :         return ret;
     516             : }
     517             : 
     518             : 
     519             : GF_EXPORT
     520       62546 : u32 gf_bs_read_u24(GF_BitStream *bs)
     521             : {
     522             :         u32 ret;
     523             :         assert(bs->nbBits==8);
     524             : 
     525       62546 :         if (bs->cache_read && (bs->cache_read_pos+3<bs->cache_read_size) ) {
     526       48174 :                 ret = bs->cache_read[bs->cache_read_pos];
     527       48174 :                 ret<<=8;
     528       48174 :                 ret |= bs->cache_read[bs->cache_read_pos+1];
     529       48174 :                 ret<<=8;
     530       48174 :                 ret |= bs->cache_read[bs->cache_read_pos+2];
     531       48174 :                 bs->cache_read_pos+=3;
     532       48174 :                 bs->position+=3;
     533       48174 :                 return ret;
     534             :         }
     535             : 
     536       14372 :         ret = BS_ReadByte(bs);
     537       14372 :         ret<<=8;
     538       14372 :         ret |= BS_ReadByte(bs);
     539       14372 :         ret<<=8;
     540       14372 :         ret |= BS_ReadByte(bs);
     541       14372 :         return ret;
     542             : }
     543             : 
     544             : GF_EXPORT
     545     2162323 : u32 gf_bs_read_u32(GF_BitStream *bs)
     546             : {
     547             :         u32 ret;
     548             :         assert(bs->nbBits==8);
     549             : 
     550     2162323 :         if (bs->cache_read && (bs->cache_read_pos+4<bs->cache_read_size) ) {
     551     1746317 :                 ret = bs->cache_read[bs->cache_read_pos];
     552     1746317 :                 ret<<=8;
     553     1746317 :                 ret |= bs->cache_read[bs->cache_read_pos+1];
     554     1746317 :                 ret<<=8;
     555     1746317 :                 ret |= bs->cache_read[bs->cache_read_pos+2];
     556     1746317 :                 ret<<=8;
     557     1746317 :                 ret |= bs->cache_read[bs->cache_read_pos+3];
     558     1746317 :                 bs->cache_read_pos+=4;
     559     1746317 :                 bs->position+=4;
     560     1746317 :                 return ret;
     561             :         }
     562      416006 :         ret = BS_ReadByte(bs);
     563      416006 :         ret<<=8;
     564      416006 :         ret |= BS_ReadByte(bs);
     565      416006 :         ret<<=8;
     566      416006 :         ret |= BS_ReadByte(bs);
     567      416006 :         ret<<=8;
     568      416006 :         ret |= BS_ReadByte(bs);
     569      416006 :         return ret;
     570             : }
     571             : 
     572             : GF_EXPORT
     573        8100 : u64 gf_bs_read_u64(GF_BitStream *bs)
     574             : {
     575             :         u64 ret;
     576             : 
     577        8100 :         if (bs->cache_read && (bs->cache_read_pos+8<bs->cache_read_size) ) {
     578        1719 :                 ret = bs->cache_read[bs->cache_read_pos];
     579        1719 :                 ret<<=8;
     580        1719 :                 ret |= bs->cache_read[bs->cache_read_pos+1];
     581        1719 :                 ret<<=8;
     582        1719 :                 ret |= bs->cache_read[bs->cache_read_pos+2];
     583        1719 :                 ret<<=8;
     584        1719 :                 ret |= bs->cache_read[bs->cache_read_pos+3];
     585        1719 :                 ret<<=8;
     586        1719 :                 ret |= bs->cache_read[bs->cache_read_pos+4];
     587        1719 :                 ret<<=8;
     588        1719 :                 ret |= bs->cache_read[bs->cache_read_pos+5];
     589        1719 :                 ret<<=8;
     590        1719 :                 ret |= bs->cache_read[bs->cache_read_pos+6];
     591        1719 :                 ret<<=8;
     592        1719 :                 ret |= bs->cache_read[bs->cache_read_pos+7];
     593        1719 :                 bs->cache_read_pos+=8;
     594        1719 :                 bs->position+=8;
     595        1719 :                 return ret;
     596             :         }
     597        6381 :         ret = gf_bs_read_u32(bs);
     598        6381 :         ret<<=32;
     599        6381 :         ret |= gf_bs_read_u32(bs);
     600        6381 :         return ret;
     601             : }
     602             : 
     603             : GF_EXPORT
     604       11159 : u64 gf_bs_read_long_int(GF_BitStream *bs, u32 nBits)
     605             : {
     606             :         u64 ret = 0;
     607       11159 :         if (nBits>64) {
     608           0 :                 gf_bs_read_long_int(bs, nBits-64);
     609             :                 ret = gf_bs_read_long_int(bs, 64);
     610             :         } else {
     611      450701 :                 while (nBits-- > 0) {
     612      439542 :                         ret <<= 1;
     613      439542 :                         ret |= gf_bs_read_bit(bs);
     614             :                 }
     615             :         }
     616       11159 :         return ret;
     617             : }
     618             : 
     619             : 
     620             : GF_EXPORT
     621       34860 : Float gf_bs_read_float(GF_BitStream *bs)
     622             : {
     623       34860 :         char buf [4] = "\0\0\0";
     624             : #ifdef NO_OPTS
     625             :         s32 i;
     626     1150380 :         for (i = 0; i < 32; i++)
     627     1115520 :                 buf[3-i/8] |= gf_bs_read_bit(bs) << (7 - i%8);
     628             : #else
     629             :         buf[3] = gf_bs_read_int(bs, 8);
     630             :         buf[2] = gf_bs_read_int(bs, 8);
     631             :         buf[1] = gf_bs_read_int(bs, 8);
     632             :         buf[0] = gf_bs_read_int(bs, 8);
     633             : #endif
     634       34860 :         return (* (Float *) buf);
     635             : }
     636             : 
     637             : GF_EXPORT
     638         142 : Double gf_bs_read_double(GF_BitStream *bs)
     639             : {
     640         142 :         char buf [8] = "\0\0\0\0\0\0\0";
     641             :         s32 i;
     642        9230 :         for (i = 0; i < 64; i++)
     643        9088 :                 buf[7-i/8] |= gf_bs_read_bit(bs) << (7 - i%8);
     644         142 :         return (* (Double *) buf);
     645             : }
     646             : 
     647             : GF_EXPORT
     648     2453229 : u32 gf_bs_read_data(GF_BitStream *bs, u8 *data, u32 nbBytes)
     649             : {
     650     2453229 :         u64 orig = bs->position;
     651             : 
     652     2453229 :         if (bs->position+nbBytes > bs->size) return 0;
     653             : 
     654     2453227 :         if (gf_bs_is_align(bs) ) {
     655             :                 s32 bytes_read, bytes_read_cache;
     656     2450244 :                 switch (bs->bsmode) {
     657      464020 :                 case GF_BITSTREAM_READ:
     658             :                 case GF_BITSTREAM_WRITE:
     659             :                 case GF_BITSTREAM_WRITE_DYN:
     660      464020 :                         memcpy(data, bs->original + bs->position, nbBytes);
     661      464020 :                         bs->position += nbBytes;
     662      464020 :                         return nbBytes;
     663     1986224 :                 case GF_BITSTREAM_FILE_READ:
     664             :                 case GF_BITSTREAM_FILE_WRITE:
     665     1986224 :                         if (bs->cache_write)
     666      925007 :                                 bs_flush_write_cache(bs);
     667             : 
     668             :                         bytes_read = bytes_read_cache = 0;
     669     1986224 :                         if (bs->cache_read) {
     670     1061217 :                                 u32 csize = bs->cache_read_size-bs->cache_read_pos;
     671     1061217 :                                 if (csize>nbBytes) csize = nbBytes;
     672     1061217 :                                 memcpy(data, bs->cache_read + bs->cache_read_pos, csize);
     673     1061217 :                                 bs->cache_read_pos += csize;
     674     1061217 :                                 nbBytes -= csize;
     675     1061217 :                                 bytes_read_cache = csize;
     676             :                         }
     677     1986224 :                         if (nbBytes) {
     678     1966928 :                                 bytes_read = (s32) gf_fread(data + bytes_read_cache, nbBytes, bs->stream);
     679     1966928 :                                 if (bytes_read<0) return bytes_read_cache;
     680             :                         }
     681     1986224 :                         bs->position += bytes_read + bytes_read_cache;
     682     1986224 :                         return bytes_read + bytes_read_cache;
     683             :                 default:
     684             :                         return 0;
     685             :                 }
     686             :         }
     687             : 
     688      371207 :         while (nbBytes-- > 0) {
     689      368224 :                 *data++ = gf_bs_read_int(bs, 8);
     690             :         }
     691        2983 :         return (u32) (bs->position - orig);
     692             : 
     693             : }
     694             : 
     695             : 
     696             : 
     697    12757054 : static void BS_WriteByte(GF_BitStream *bs, u8 val)
     698             : {
     699             :         /*we don't allow write on READ buffers*/
     700    12757054 :         if ( (bs->bsmode == GF_BITSTREAM_READ) || (bs->bsmode == GF_BITSTREAM_FILE_READ) ) {
     701           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[BS] Attempt to write on read bitstream\n"));
     702             :                 return;
     703             :         }
     704    12757054 :         if (!bs->original && !bs->stream) {
     705           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[BS] Attempt to write on unassigned bitstream\n"));
     706             :                 return;
     707             :         }
     708             :         /*we are in MEM mode*/
     709    12757054 :         if ( (bs->bsmode == GF_BITSTREAM_WRITE) || (bs->bsmode == GF_BITSTREAM_WRITE_DYN) ) {
     710             :                 //if callback mode and dispatch is not blocked, dispatch
     711    12713305 :                 if (bs->on_block_out && !bs->prevent_dispatch) {
     712             :                         assert(bs->position >= bs->bytes_out);
     713      761021 :                         if (bs->position - bs->bytes_out == bs->size) {
     714           9 :                                 bs->on_block_out(bs->usr_data, bs->original, (u32) (bs->position - bs->bytes_out));
     715           9 :                                 bs->bytes_out = bs->position;
     716             :                         }
     717      761021 :                         if (bs->original)
     718      761021 :                                 bs->original[bs->position - bs->bytes_out] = val;
     719      761021 :                         bs->position++;
     720             :                         assert(bs->position >= bs->bytes_out);
     721      761021 :                         return;
     722             :                 }
     723             :                 //otherwise store
     724    11952284 :                 if (bs->position - bs->bytes_out == bs->size) {
     725             :                         /*no more space...*/
     726        1766 :                         if (bs->bsmode != GF_BITSTREAM_WRITE_DYN) return;
     727             :                         /*gf_realloc if enough space...*/
     728        1766 :                         if (bs->size > 0xFFFFFFFF) return;
     729        1766 :                         bs->size = bs->size ? (bs->size * 2) : BS_MEM_BLOCK_ALLOC_SIZE;
     730        1766 :                         bs->original = (char*)gf_realloc(bs->original, (u32)bs->size);
     731        1766 :                         if (!bs->original) return;
     732             :                 }
     733    11952284 :                 if (bs->original)
     734    11952284 :                         bs->original[bs->position - bs->bytes_out] = val;
     735    11952284 :                 bs->position++;
     736    11952284 :                 return;
     737             :         }
     738       43749 :         if (bs->cache_write) {
     739       43749 :                 if (bs->buffer_written == bs->cache_write_size) {
     740           0 :                         bs_flush_write_cache(bs);
     741             :                 }
     742       43749 :                 bs->cache_write[bs->buffer_written] = val;
     743       43749 :                 bs->buffer_written++;
     744       43749 :                 if (bs->buffer_written == bs->cache_write_size) {
     745        7111 :                         bs_flush_write_cache(bs);
     746             :                 }
     747             :                 return;
     748             :         }
     749             :         /*we are in FILE mode, no pb for any gf_realloc...*/
     750           0 :         gf_fputc(val, bs->stream);
     751             : 
     752             :         /*check we didn't rewind the stream*/
     753           0 :         if (bs->size == bs->position) bs->size++;
     754           0 :         bs->position += 1;
     755             : }
     756             : 
     757    48583488 : static void BS_WriteBit(GF_BitStream *bs, u32 bit)
     758             : {
     759    48583488 :         bs->current <<= 1;
     760    48583488 :         bs->current |= bit;
     761    48583488 :         if (++ bs->nbBits == 8) {
     762     6072936 :                 bs->nbBits = 0;
     763     6072936 :                 BS_WriteByte(bs, (u8) bs->current);
     764     6072936 :                 bs->current = 0;
     765             :         }
     766    48583488 : }
     767             : 
     768     5584154 : static s32 bs_handle_nbits_overflow(GF_BitStream* bs, s32 nBits, s32 max_shift)
     769             : {
     770     5584154 :         if (nBits > max_shift) {
     771           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[BS] Attempt to write %d bits, when max is %d\n", nBits, max_shift));
     772             :         }
     773     5584154 :         while (nBits > max_shift) {
     774           0 :                 gf_bs_write_long_int(bs, 0, max_shift);
     775           0 :                 nBits -= max_shift;
     776             :         }
     777             : 
     778     5584154 :         return nBits;
     779             : }
     780             : 
     781             : GF_EXPORT
     782     5556423 : void gf_bs_write_int(GF_BitStream *bs, s32 _value, s32 nBits)
     783             : {
     784             :         u32 value, nb_shift;
     785             :         s32 max_shift = sizeof(s32) * 8;
     786     5556423 :         if (!nBits) return;
     787     5503023 :         nBits = bs_handle_nbits_overflow(bs, nBits, max_shift);
     788             :         //move to unsigned to avoid sanitizer warnings when we pass a value not codable on the given number of bits
     789             :         //we do this when setting bit fields to all 1's
     790     5503023 :         value = (u32) _value;
     791     5503023 :         nb_shift = max_shift - nBits;
     792     5503023 :         if (nb_shift)
     793     4722604 :                 value <<= nb_shift;
     794             : 
     795    48040133 :         while (--nBits >= 0) {
     796             :                 //but check value as signed
     797    42537110 :                 BS_WriteBit (bs, ((s32)value) < 0);
     798    42537110 :                 value <<= 1;
     799             :         }
     800             : }
     801             : 
     802             : GF_EXPORT
     803       81408 : void gf_bs_write_long_int(GF_BitStream *bs, s64 _value, s32 nBits)
     804             : {
     805             :         s32 max_shift = sizeof(s64) * 8;
     806       81408 :         if (!nBits) return;
     807       81131 :         nBits = bs_handle_nbits_overflow(bs, nBits, max_shift);
     808             : 
     809             :         //cf note in gf_bs_write_int
     810       81131 :         u64 value = (u64) _value;
     811       81131 :         value <<= max_shift - nBits;
     812     1456992 :         while (--nBits >= 0) {
     813     1294730 :                 BS_WriteBit (bs, ((s64)value) < 0);
     814     1294730 :                 value <<= 1;
     815             :         }
     816             : }
     817             : 
     818             : GF_EXPORT
     819      558598 : void gf_bs_write_u8(GF_BitStream *bs, u32 value)
     820             : {
     821             :         assert(!bs->nbBits);
     822             : 
     823      558598 :         if (bs->cache_write && (bs->buffer_written+1 < bs->cache_write_size) ) {
     824       24073 :                 bs->cache_write[bs->buffer_written] = (u8) value;
     825       24073 :                 bs->buffer_written += 1;
     826             :         } else {
     827      534525 :                 BS_WriteByte(bs, (u8) value);
     828             :         }
     829      558598 : }
     830             : 
     831             : GF_EXPORT
     832      696253 : void gf_bs_write_u16(GF_BitStream *bs, u32 value)
     833             : {
     834             :         assert(!bs->nbBits);
     835      696253 :         if (bs->cache_write && (bs->buffer_written+2 < bs->cache_write_size) ) {
     836       17152 :                 bs->cache_write[bs->buffer_written] = (u8) ((value>>8)&0xff);
     837       17152 :                 bs->cache_write[bs->buffer_written+1] = (u8) ((value)&0xff);
     838       17152 :                 bs->buffer_written += 2;
     839             :         } else {
     840      679101 :                 BS_WriteByte(bs, (u8) ((value>>8)&0xff));
     841      679101 :                 BS_WriteByte(bs, (u8) ((value)&0xff));
     842             :         }
     843      696253 : }
     844             : 
     845             : GF_EXPORT
     846       61382 : void gf_bs_write_u24(GF_BitStream *bs, u32 value)
     847             : {
     848             :         assert(!bs->nbBits);
     849       61382 :         if (bs->cache_write && (bs->buffer_written+3 < bs->cache_write_size) ) {
     850       15913 :                 bs->cache_write[bs->buffer_written] = (u8) ((value>>16)&0xff);
     851       15913 :                 bs->cache_write[bs->buffer_written+1] = (u8) ((value>>8)&0xff);
     852       15913 :                 bs->cache_write[bs->buffer_written+2] = (u8) ((value)&0xff);
     853       15913 :                 bs->buffer_written += 3;
     854             :         } else {
     855       45469 :                 BS_WriteByte(bs, (u8) ((value>>16)&0xff));
     856       45469 :                 BS_WriteByte(bs, (u8) ((value>>8)&0xff));
     857       45469 :                 BS_WriteByte(bs, (u8) ((value)&0xff));
     858             :         }
     859       61382 : }
     860             : 
     861             : GF_EXPORT
     862     2084565 : void gf_bs_write_u32(GF_BitStream *bs, u32 value)
     863             : {
     864             :         assert(!bs->nbBits);
     865     2084565 :         if (bs->cache_write && (bs->buffer_written+4 < bs->cache_write_size) ) {
     866      920819 :                 bs->cache_write[bs->buffer_written] = (u8) ((value>>24)&0xff);
     867      920819 :                 bs->cache_write[bs->buffer_written+1] = (u8) ((value>>16)&0xff);
     868      920819 :                 bs->cache_write[bs->buffer_written+2] = (u8) ((value>>8)&0xff);
     869      920819 :                 bs->cache_write[bs->buffer_written+3] = (u8) ((value)&0xff);
     870      920819 :                 bs->buffer_written += 4;
     871             :         } else {
     872     1163746 :                 BS_WriteByte(bs, (u8) ((value>>24)&0xff));
     873     1163746 :                 BS_WriteByte(bs, (u8) ((value>>16)&0xff));
     874     1163746 :                 BS_WriteByte(bs, (u8) ((value>>8)&0xff));
     875     1163746 :                 BS_WriteByte(bs, (u8) ((value)&0xff));
     876             :         }
     877     2084565 : }
     878             : 
     879             : GF_EXPORT
     880        9038 : void gf_bs_write_u64(GF_BitStream *bs, u64 value)
     881             : {
     882             :         assert(!bs->nbBits);
     883        9038 :         gf_bs_write_u32(bs, (u32) ((value>>32)&0xffffffff));
     884        9038 :         gf_bs_write_u32(bs, (u32) (value&0xffffffff));
     885        9038 : }
     886             : 
     887             : GF_EXPORT
     888       21760 : u32 gf_bs_write_byte(GF_BitStream *bs, u8 byte, u32 repeat_count)
     889             : {
     890       21760 :         if (!gf_bs_is_align(bs) || bs->cache_write) {
     891             :                 u32 count = 0;
     892          58 :                 while (count<repeat_count) {
     893          29 :                         gf_bs_write_int(bs, byte, 8);
     894          29 :                         count++;
     895             :                 }
     896             :                 return count;
     897             :         }
     898             : 
     899       21731 :         switch (bs->bsmode) {
     900       21720 :         case GF_BITSTREAM_WRITE:
     901       21720 :                 if (bs->position + repeat_count > bs->size)
     902             :                         return 0;
     903       21720 :                 memset(bs->original + bs->position, byte, repeat_count);
     904       21720 :                 bs->position += repeat_count;
     905       21720 :                 return repeat_count;
     906          11 :         case GF_BITSTREAM_WRITE_DYN:
     907             :                 /*need to gf_realloc ...*/
     908          11 :                 if (bs->position+repeat_count> bs->size) {
     909           0 :                         u32 new_size = (u32) (bs->size*2);
     910           0 :                         if (!new_size) new_size = BS_MEM_BLOCK_ALLOC_SIZE;
     911             : 
     912           0 :                         if (bs->size + repeat_count > 0xFFFFFFFF)
     913             :                                 return 0;
     914           0 :                         while (new_size < (u32) ( bs->size + repeat_count))
     915           0 :                                 new_size *= 2;
     916           0 :                         bs->original = (char*)gf_realloc(bs->original, sizeof(u32)*new_size);
     917           0 :                         if (!bs->original)
     918             :                                 return 0;
     919           0 :                         bs->size = new_size;
     920             :                 }
     921          11 :                 memset(bs->original + bs->position, byte, repeat_count);
     922          11 :                 bs->position += repeat_count;
     923          11 :                 return repeat_count;
     924           0 :         case GF_BITSTREAM_FILE_READ:
     925             :         case GF_BITSTREAM_FILE_WRITE:
     926           0 :                 if (gf_fwrite(&byte, repeat_count, bs->stream) != repeat_count)
     927             :                         return 0;
     928           0 :                 if (bs->size == bs->position) bs->size += repeat_count;
     929           0 :                 bs->position += repeat_count;
     930           0 :                 return repeat_count;
     931             :         default:
     932             :                 return 0;
     933             :         }
     934             : }
     935             : 
     936             : 
     937             : 
     938             : GF_EXPORT
     939      148203 : void gf_bs_write_float(GF_BitStream *bs, Float value)
     940             : {
     941             :         u32 i;
     942             :         union
     943             :         {       float f;
     944             :                 char sz [4];
     945             :         } float_value;
     946      148203 :         float_value.f = value;
     947             : 
     948     4890699 :         for (i = 0; i < 32; i++)
     949     4742496 :                 BS_WriteBit(bs, (float_value.sz [3 - i / 8] & 1 << (7 - i % 8)) != 0);
     950             : 
     951      148203 : }
     952             : 
     953             : GF_EXPORT
     954         143 : void gf_bs_write_double (GF_BitStream *bs, Double value)
     955             : {
     956             :         u32 i;
     957             :         union
     958             :         {       Double d;
     959             :                 char sz [8];
     960             :         } double_value;
     961         143 :         double_value.d = value;
     962        9295 :         for (i = 0; i < 64; i++) {
     963        9152 :                 BS_WriteBit(bs, (double_value.sz [7 - i / 8] & 1 << (7 - i % 8)) != 0);
     964             :         }
     965         143 : }
     966             : 
     967             : 
     968             : GF_EXPORT
     969     2224923 : u32 gf_bs_write_data(GF_BitStream *bs, const u8 *data, u32 nbBytes)
     970             : {
     971             :         /*we need some feedback for this guy...*/
     972     2224923 :         u64 begin = bs->position;
     973     2224923 :         if (!nbBytes) return 0;
     974             : 
     975     2222180 :         if (gf_bs_is_align(bs)) {
     976     2221799 :                 switch (bs->bsmode) {
     977       73082 :                 case GF_BITSTREAM_WRITE:
     978       73082 :                         if (bs->position+nbBytes > bs->size) {
     979           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[BS] Attempt to overwrite bitstream by %d bytes\n", bs->position + nbBytes - bs->size));
     980             :                                 return 0;
     981             :                         }
     982       73082 :                         memcpy(bs->original + bs->position, data, nbBytes);
     983       73082 :                         bs->position += nbBytes;
     984       73082 :                         return nbBytes;
     985      653062 :                 case GF_BITSTREAM_WRITE_DYN:
     986             :                         //if callback mode and dispatch not disabled, dispatch bytes
     987      653062 :                         if (bs->on_block_out && !bs->prevent_dispatch) {
     988             :                                 assert(bs->position >= bs->bytes_out);
     989             : 
     990      118250 :                                 if (bs->position - bs->bytes_out + nbBytes <= bs->size) {
     991      108806 :                                         memcpy(bs->original + bs->position - bs->bytes_out, data, nbBytes);
     992      108806 :                                         bs->position += nbBytes;
     993             :                                 } else {
     994        9444 :                                         if (bs->position > bs->bytes_out)
     995        6857 :                                                 bs->on_block_out(bs->usr_data, bs->original, (u32) (bs->position - bs->bytes_out) );
     996             :                                         if (nbBytes)
     997        9444 :                                                 bs->on_block_out(bs->usr_data, (char *) data, nbBytes);
     998             : 
     999        9444 :                                         bs->position += nbBytes;
    1000        9444 :                                         bs->bytes_out = bs->position;
    1001             :                                 }
    1002             :                                 assert(bs->position >= bs->bytes_out);
    1003             :                                 return nbBytes;
    1004             :                         }
    1005             :                         //otherwise store
    1006             :                         /*need to gf_realloc ...*/
    1007      534812 :                         if (bs->position + nbBytes - bs->bytes_out > bs->size) {
    1008       17912 :                                 u32 new_size = (u32) (bs->size*2);
    1009       17912 :                                 if (!new_size) new_size = BS_MEM_BLOCK_ALLOC_SIZE;
    1010             : 
    1011       17912 :                                 if (bs->size + nbBytes > 0xFFFFFFFF)
    1012             :                                         return 0;
    1013             : 
    1014       36279 :                                 while (new_size < (u32) ( bs->size + nbBytes))
    1015       18367 :                                         new_size *= 2;
    1016       17912 :                                 bs->original = (char*)gf_realloc(bs->original, sizeof(u32)*new_size);
    1017       17912 :                                 if (!bs->original)
    1018             :                                         return 0;
    1019       17912 :                                 bs->size = new_size;
    1020             :                         }
    1021      534812 :                         memcpy(bs->original + bs->position - bs->bytes_out, data, nbBytes);
    1022      534812 :                         bs->position += nbBytes;
    1023      534812 :                         return nbBytes;
    1024     1495654 :                 case GF_BITSTREAM_FILE_READ:
    1025             :                 case GF_BITSTREAM_FILE_WRITE:
    1026     1495654 :                         if (bs->cache_write) {
    1027             :                                 //if block fits in our write cache, write it
    1028     1495654 :                                 if (bs->buffer_written + nbBytes < bs->cache_write_size) {
    1029     1051884 :                                         memcpy(bs->cache_write+bs->buffer_written, data, nbBytes);
    1030     1051884 :                                         bs->buffer_written+=nbBytes;
    1031     1051884 :                                         return nbBytes;
    1032             :                                 }
    1033             :                                 //otherwise flush cache and use file write
    1034      443770 :                                 bs_flush_write_cache(bs);
    1035             :                         }
    1036             : 
    1037      443770 :                         if (gf_fwrite(data, nbBytes, bs->stream) != nbBytes) return 0;
    1038             : 
    1039      443770 :                         if (bs->size == bs->position) bs->size += nbBytes;
    1040      443770 :                         bs->position += nbBytes;
    1041      443770 :                         return nbBytes;
    1042             :                 default:
    1043             :                         return 0;
    1044             :                 }
    1045             :         }
    1046             : 
    1047       94590 :         while (nbBytes) {
    1048       94209 :                 gf_bs_write_int(bs, (s32) *data, 8);
    1049       94209 :                 data++;
    1050       94209 :                 nbBytes--;
    1051             :         }
    1052         381 :         return (u32) (bs->position - begin);
    1053             : }
    1054             : 
    1055             : /*align return the num of bits read in READ mode, 0 in WRITE*/
    1056             : GF_EXPORT
    1057     4062533 : u8 gf_bs_align(GF_BitStream *bs)
    1058             : {
    1059     4062533 :         u8 res = 8 - bs->nbBits;
    1060     4062533 :         if ( (bs->bsmode == GF_BITSTREAM_READ) || (bs->bsmode == GF_BITSTREAM_FILE_READ)) {
    1061     3491591 :                 if (res > 0) {
    1062      539870 :                         gf_bs_read_int(bs, res);
    1063             :                 }
    1064             :                 return res;
    1065             :         }
    1066      570942 :         if (bs->nbBits > 0) {
    1067       35370 :                 gf_bs_write_int (bs, 0, res);
    1068       35370 :                 return res;
    1069             :         }
    1070             :         return 0;
    1071             : }
    1072             : 
    1073             : 
    1074             : /*size available in the bitstream*/
    1075             : GF_EXPORT
    1076    33131833 : u64 gf_bs_available(GF_BitStream *bs)
    1077             : {
    1078             :         s64 cur, end;
    1079             : 
    1080             :         /*in WRITE mode only, this should not be called, but return something big in case ...*/
    1081    66263666 :         if ( (bs->bsmode == GF_BITSTREAM_WRITE)
    1082    33131833 :                 || (bs->bsmode == GF_BITSTREAM_WRITE_DYN)
    1083             :            )
    1084             :                 return (u64) -1;
    1085             : 
    1086             :         /*we are in MEM mode*/
    1087    33131833 :         if (bs->bsmode == GF_BITSTREAM_READ) {
    1088    31710541 :                 if (bs->size < bs->position)
    1089             :                         return 0;
    1090             :                 else
    1091    31710541 :                         return (bs->size - bs->position);
    1092             :         }
    1093             :         /*FILE READ: assume size hasn't changed, otherwise the user shall call gf_bs_get_refreshed_size*/
    1094     1421292 :         if (bs->bsmode==GF_BITSTREAM_FILE_READ) {
    1095     1421292 :                 if (bs->position>bs->size) return 0;
    1096     1421292 :                 return (bs->size - bs->position);
    1097             :         }
    1098           0 :         if (bs->cache_write)
    1099           0 :                 bs_flush_write_cache(bs);
    1100             : 
    1101           0 :         cur = gf_ftell(bs->stream);
    1102           0 :         end = gf_fsize(bs->stream);
    1103           0 :         gf_fseek(bs->stream, cur, SEEK_SET);
    1104             : 
    1105           0 :         return (u64) (end - cur);
    1106             : }
    1107             : 
    1108             : /*call this funct to set the buffer size to the nb of bytes written
    1109             : Used only in WRITE mode, as we don't know the real size during allocation...
    1110             : return -1 for bad param or gf_malloc failed
    1111             : return nbBytes cut*/
    1112      213092 : static s32 BS_CutBuffer(GF_BitStream *bs)
    1113             : {
    1114             :         s32 nbBytes;
    1115      213092 :         if ( (bs->bsmode != GF_BITSTREAM_WRITE_DYN) && (bs->bsmode != GF_BITSTREAM_WRITE)) return (u32) -1;
    1116             :         /*Align our buffer or we're dead!*/
    1117      213092 :         gf_bs_align(bs);
    1118             : 
    1119      213092 :         nbBytes = (u32) (bs->size - bs->position);
    1120      213092 :         if (!nbBytes || (nbBytes == 0xFFFFFFFF) || (bs->position >= 0xFFFFFFFF)) return 0;
    1121             :         /*
    1122             :                 bs->original = (char*)gf_realloc(bs->original, (u32) bs->position);
    1123             :                 if (! bs->original) return (u32) -1;
    1124             :         */
    1125             :         /*just in case, re-adjust..*/
    1126      212870 :         bs->size = bs->position;
    1127      212870 :         return nbBytes;
    1128             : }
    1129             : 
    1130             : /*For DYN mode, this gets the content out without cutting the buffer to the number of written bytes*/
    1131             : GF_EXPORT
    1132      332181 : void gf_bs_get_content_no_truncate(GF_BitStream *bs, u8 **output, u32 *outSize, u32 *alloc_size)
    1133             : {
    1134             :         /*only in WRITE MEM mode*/
    1135      332181 :         if (bs->bsmode != GF_BITSTREAM_WRITE_DYN) return;
    1136             : 
    1137      332180 :         if (bs->on_block_out && bs->position>bs->bytes_out) {
    1138        2965 :                 bs->on_block_out(bs->usr_data, bs->original, (u32) (bs->position - bs->bytes_out) );
    1139             :         }
    1140             : 
    1141      332180 :         if (!bs->position && !bs->nbBits) {
    1142       12322 :                 if (!alloc_size) {
    1143       12285 :                         *output = NULL;
    1144       12285 :                         gf_free(bs->original);
    1145             :                 } else {
    1146          37 :                         *alloc_size = (u32) bs->size;
    1147          37 :                         *output = bs->original;
    1148             :                 }
    1149       12322 :                 *outSize = 0;
    1150             :         } else {
    1151      319858 :                 if (alloc_size) {
    1152             :                         /*Align our buffer or we're dead!*/
    1153      106766 :                         gf_bs_align(bs);
    1154      106766 :                         *alloc_size = (u32) bs->size;
    1155      106766 :                         *outSize = (u32) bs->position;
    1156      106766 :                         *output = bs->original;
    1157             :                 } else {
    1158      213092 :                         s32 copy = BS_CutBuffer(bs);
    1159      213092 :                         if (copy < 0) {
    1160           0 :                                 *output = NULL;
    1161             :                         } else
    1162      213092 :                                 *output = bs->original;
    1163      213092 :                         *outSize = (u32) bs->size;
    1164             :                 }
    1165             :         }
    1166      332180 :         bs->original = NULL;
    1167      332180 :         bs->size = 0;
    1168      332180 :         bs->position = 0;
    1169             : }
    1170             : 
    1171             : /*For DYN mode, this gets the content out*/
    1172             : GF_EXPORT
    1173      217721 : void gf_bs_get_content(GF_BitStream *bs, u8 **output, u32 *outSize)
    1174             : {
    1175      217721 :         gf_bs_get_content_no_truncate(bs, output, outSize, NULL);
    1176      217721 : }
    1177             : 
    1178             : /*      Skip nbytes.
    1179             :         Align
    1180             :         If READ (MEM or FILE) mode, just read n times 8 bit
    1181             :         If WRITE (MEM or FILE) mode, write n times 0 on 8 bit
    1182             : */
    1183             : GF_EXPORT
    1184      912901 : void gf_bs_skip_bytes(GF_BitStream *bs, u64 nbBytes)
    1185             : {
    1186      912901 :         if (!bs || !nbBytes) return;
    1187             : 
    1188      912700 :         gf_bs_align(bs);
    1189             : 
    1190             :         /*special case for file skipping...*/
    1191      912700 :         if ((bs->bsmode == GF_BITSTREAM_FILE_WRITE) || (bs->bsmode == GF_BITSTREAM_FILE_READ)) {
    1192       81813 :                 if (bs->cache_write)
    1193           0 :                         bs_flush_write_cache(bs);
    1194             : 
    1195       81813 :                 if (bs->cache_read) {
    1196       81813 :                         u32 csize = bs->cache_read_size - bs->cache_read_pos;
    1197       81813 :                         if (csize>=nbBytes) {
    1198       33085 :                                 bs->cache_read_pos += (u32) nbBytes;
    1199       33085 :                                 bs->position += nbBytes;
    1200       33085 :                                 return;
    1201             :                         }
    1202       48728 :                         nbBytes -= csize;
    1203       48728 :                         bs->position += csize;
    1204       48728 :                         bs->cache_read_pos = bs->cache_read_size;
    1205             :                 }
    1206             :                 //weird msys2 bug resulting in broken seek on some files ?!?  -the bug is not happening when doing absolute seek
    1207             : //              gf_fseek(bs->stream, nbBytes, SEEK_CUR);
    1208       48728 :                 bs->position += nbBytes;
    1209       48728 :                 if (bs->bsmode == GF_BITSTREAM_FILE_READ) {
    1210       48728 :                         if (bs->position > bs->size) bs->position = bs->size;
    1211             :                 }
    1212       48728 :                 gf_fseek(bs->stream, bs->position, SEEK_SET);
    1213       48728 :                 return;
    1214             :         }
    1215             : 
    1216             :         /*special case for reading*/
    1217      830887 :         if (bs->bsmode == GF_BITSTREAM_READ) {
    1218      830887 :                 if (bs->remove_emul_prevention_byte) {
    1219       25735 :                         while (nbBytes) {
    1220       23604 :                                 gf_bs_read_u8(bs);
    1221       23604 :                                 nbBytes--;
    1222             :                         }
    1223             :                 } else {
    1224      828756 :                         bs->position += nbBytes;
    1225             :                 }
    1226             :                 return;
    1227             :         }
    1228             :         /*for writing we must do it this way, otherwise pb in dynamic buffers*/
    1229           0 :         while (nbBytes) {
    1230           0 :                 gf_bs_write_int(bs, 0, 8);
    1231           0 :                 nbBytes--;
    1232             :         }
    1233             : }
    1234             : 
    1235             : #ifdef GPAC_ENABLE_BIFS_PMF
    1236             : 
    1237             : void gf_bs_rewind_bits(GF_BitStream *bs, u64 nbBits)
    1238             : {
    1239             :         u64 nbBytes;
    1240             :         if (bs->bsmode != GF_BITSTREAM_READ) return;
    1241             : 
    1242             :         nbBits -= (bs->nbBits);
    1243             :         nbBytes = (nbBits+8)>>3;
    1244             :         nbBits = nbBytes*8 - nbBits;
    1245             :         gf_bs_align(bs);
    1246             :         assert(bs->position >= nbBytes);
    1247             :         bs->position -= nbBytes + 1;
    1248             :         gf_bs_read_int(bs, (u32)nbBits);
    1249             :         return;
    1250             : }
    1251             : 
    1252             : #endif
    1253             : 
    1254             : /*seek from beginning of stream: use internally even when non aligned!*/
    1255     2433626 : static GF_Err BS_SeekIntern(GF_BitStream *bs, u64 offset)
    1256             : {
    1257             :         u32 i;
    1258             :         /*if mem, do it */
    1259     2433626 :         if ((bs->bsmode == GF_BITSTREAM_READ) || (bs->bsmode == GF_BITSTREAM_WRITE) || (bs->bsmode == GF_BITSTREAM_WRITE_DYN)) {
    1260     1155057 :                 if (offset > 0xFFFFFFFF) return GF_IO_ERR;
    1261     1155057 :                 if (!bs->original) return GF_BAD_PARAM;
    1262             :                 /*0 for write, read will be done automatically*/
    1263     1117739 :                 if (offset >= bs->size) {
    1264       28449 :                         if ( (bs->bsmode == GF_BITSTREAM_READ) || (bs->bsmode == GF_BITSTREAM_WRITE) ) {
    1265       24970 :                                 if (offset > bs->size) {
    1266           0 :                                         GF_LOG(GF_LOG_WARNING, GF_LOG_CORE, ("[BS] Attempt to seek to %d after end of bitstream %d, assuming seek to end\n", offset, bs->size));
    1267             :                                 }
    1268       24970 :                                 bs->position = bs->size;
    1269       24970 :                                 bs->nbBits = (bs->bsmode == GF_BITSTREAM_READ) ? 8 : 0;
    1270       24970 :                                 return GF_OK;
    1271             :                         }
    1272             :                         /*in DYN, gf_realloc ...*/
    1273        3479 :                         bs->original = (char*)gf_realloc(bs->original, (u32) (offset + 1));
    1274        3479 :                         if (!bs->original)
    1275             :                                 return GF_OUT_OF_MEM;
    1276        3479 :                         for (i = 0; i < (u32) (offset + 1 - bs->size); i++) {
    1277        3479 :                                 bs->original[bs->size + i] = 0;
    1278             :                         }
    1279        3479 :                         bs->size = offset + 1;
    1280             :                 }
    1281     1092769 :                 bs->current = bs->original[offset];
    1282     1092769 :                 bs->position = offset;
    1283     1092769 :                 bs->nbBits = (bs->bsmode == GF_BITSTREAM_READ) ? 8 : 0;
    1284     1092769 :                 return GF_OK;
    1285             :         }
    1286             : 
    1287     1278569 :         if (bs->cache_write)
    1288       74714 :                 bs_flush_write_cache(bs);
    1289             : 
    1290     1278569 :         if (bs->cache_read) {
    1291     1203855 :                 bs->cache_read_pos = bs->cache_read_size;
    1292             :         }
    1293             : 
    1294     1278569 :         gf_fseek(bs->stream, offset, SEEK_SET);
    1295             : 
    1296     1278569 :         bs->position = offset;
    1297     1278569 :         bs->current = 0;
    1298             :         /*setup NbBits so that next acccess to the buffer will trigger read/write*/
    1299     1278569 :         bs->nbBits = (bs->bsmode == GF_BITSTREAM_FILE_READ) ? 8 : 0;
    1300     1278569 :         return GF_OK;
    1301             : }
    1302             : 
    1303             : /*seek from beginning of stream: align before anything else*/
    1304             : GF_EXPORT
    1305     2486493 : GF_Err gf_bs_seek(GF_BitStream *bs, u64 offset)
    1306             : {
    1307     2486493 :         if (bs->on_block_out) {
    1308             :                 GF_Err e;
    1309        5009 :                 if (offset < bs->bytes_out) {
    1310           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[BS] Attempt to seek on byte range already forwarded\n"));
    1311             :                         return GF_BAD_PARAM;
    1312             :                 }
    1313             :                 /*warning: we allow offset = bs->size for WRITE buffers*/
    1314        5009 :                 if (offset - bs->bytes_out > bs->size)
    1315             :                         return GF_BAD_PARAM;
    1316        5009 :                 gf_bs_align(bs);
    1317        5009 :                 e = BS_SeekIntern(bs, offset - bs->bytes_out);
    1318        5009 :                 bs->position += bs->bytes_out;
    1319        5009 :                 return e;
    1320             :         }
    1321     2481484 :         if (bs->cache_write)
    1322       74714 :                 bs_flush_write_cache(bs);
    1323             : 
    1324             :         /*warning: we allow offset = bs->size for WRITE buffers*/
    1325     2481484 :         if (offset > bs->size) return GF_BAD_PARAM;
    1326             : 
    1327     2428617 :         gf_bs_align(bs);
    1328     2428617 :         return BS_SeekIntern(bs, offset);
    1329             : }
    1330             : 
    1331             : /*peek bits (as int!!) from orig position (ON BYTE BOUNDARIES, from 0) - only for read ...*/
    1332             : GF_EXPORT
    1333      259486 : u32 gf_bs_peek_bits(GF_BitStream *bs, u32 numBits, u64 byte_offset)
    1334             : {
    1335             :         u64 curPos;
    1336             :         u32 curBits, ret, current, nb_zeros;
    1337             : 
    1338      259486 :         if ( (bs->bsmode != GF_BITSTREAM_READ) && (bs->bsmode != GF_BITSTREAM_FILE_READ)) return 0;
    1339      259486 :         if (!numBits || (bs->size < bs->position + byte_offset)) return 0;
    1340             : 
    1341             :         /*store our state*/
    1342             :         curPos = bs->position;
    1343      259442 :         curBits = bs->nbBits;
    1344      259442 :         current = bs->current;
    1345      259442 :         nb_zeros = bs->nb_zeros;
    1346             : 
    1347      259442 :         if (byte_offset) {
    1348        6396 :                 if (bs->remove_emul_prevention_byte) {
    1349           0 :                         while (byte_offset) {
    1350           0 :                                 gf_bs_read_int(bs, 8);
    1351           0 :                                 byte_offset--;
    1352             :                         }
    1353             :                 } else {
    1354        6396 :                         gf_bs_seek(bs, bs->position + byte_offset);
    1355             :                 }
    1356             :         }
    1357      259442 :         ret = gf_bs_read_int(bs, numBits);
    1358             : 
    1359             :         /*restore our cache - position*/
    1360      259442 :         gf_bs_seek(bs, curPos);
    1361             :         /*to avoid re-reading our bits ...*/
    1362      259442 :         bs->nbBits = curBits;
    1363      259442 :         bs->current = current;
    1364      259442 :         bs->nb_zeros = nb_zeros;
    1365      259442 :         return ret;
    1366             : }
    1367             : 
    1368             : GF_EXPORT
    1369        9287 : u64 gf_bs_get_refreshed_size(GF_BitStream *bs)
    1370             : {
    1371             :         s64 offset;
    1372             : 
    1373        9287 :         switch (bs->bsmode) {
    1374        6950 :         case GF_BITSTREAM_READ:
    1375             :         case GF_BITSTREAM_WRITE:
    1376        6950 :                 return bs->size;
    1377             : 
    1378        2337 :         default:
    1379        2337 :                 if (bs->cache_write)
    1380           0 :                         bs_flush_write_cache(bs);
    1381             : 
    1382        2337 :                 if (bs->stream) {
    1383        2337 :                         offset = gf_ftell(bs->stream);
    1384        2337 :                         bs->size = gf_fsize(bs->stream);
    1385        2337 :                         gf_fseek(bs->stream, offset, SEEK_SET);
    1386             :                 }
    1387        2337 :                 return bs->size;
    1388             :         }
    1389             : }
    1390             : 
    1391             : GF_EXPORT
    1392     3210970 : u64 gf_bs_get_size(GF_BitStream *bs)
    1393             : {
    1394     3210970 :         if (bs->cache_write) {
    1395     2068057 :                 if (bs->size == bs->position)
    1396     1122768 :                         return bs->size + bs->buffer_written;
    1397             :                 else
    1398             :                         return bs->size;
    1399             :         }
    1400     1142913 :         if (bs->on_block_out)
    1401         874 :                 return bs->position;
    1402     1142039 :         return bs->size;
    1403             : }
    1404             : 
    1405             : GF_EXPORT
    1406     8445919 : u64 gf_bs_get_position(GF_BitStream *bs)
    1407             : {
    1408     8445919 :         if (bs->cache_write)
    1409     1571711 :                 return bs->position + bs->buffer_written;
    1410     6874208 :         return bs->position;
    1411             : }
    1412             : 
    1413             : GF_EXPORT
    1414        1437 : u8 gf_bs_bits_available(GF_BitStream *bs)
    1415             : {
    1416        1437 :         if (bs->size > bs->position) return 8;
    1417          88 :         if (bs->nbBits < 8) return (8-bs->nbBits);
    1418             :         return 0;
    1419             : }
    1420             : 
    1421             : GF_EXPORT
    1422      127592 : void gf_bs_set_eos_callback(GF_BitStream *bs, void (*EndOfStream)(void *par), void *par)
    1423             : {
    1424      127592 :         bs->EndOfStream = EndOfStream;
    1425      127592 :         bs->par = par;
    1426      127592 : }
    1427             : 
    1428             : 
    1429             : GF_EXPORT
    1430       58634 : u64 gf_bs_read_u64_le(GF_BitStream *bs)
    1431             : {
    1432             :         u64 ret, v;
    1433       58634 :         ret = gf_bs_read_int(bs, 8);
    1434       58634 :         v = gf_bs_read_int(bs, 8);
    1435       58634 :         v<<=8;
    1436       58634 :         ret |= v;
    1437       58634 :         v = gf_bs_read_int(bs, 8);
    1438       58634 :         v<<=16;
    1439       58634 :         ret |= v;
    1440       58634 :         v = gf_bs_read_int(bs, 8);
    1441       58634 :         v<<=24;
    1442       58634 :         ret |= v;
    1443       58634 :         v = gf_bs_read_int(bs, 8);
    1444       58634 :         v<<=32;
    1445       58634 :         ret |= v;
    1446       58634 :         v = gf_bs_read_int(bs, 8);
    1447       58634 :         v<<=40;
    1448       58634 :         ret |= v;
    1449       58634 :         v = gf_bs_read_int(bs, 8);
    1450       58634 :         v<<=48;
    1451       58634 :         ret |= v;
    1452       58634 :         v = gf_bs_read_int(bs, 8);
    1453       58634 :         v<<=56;
    1454       58634 :         ret |= v;
    1455       58634 :         return ret;
    1456             : }
    1457             : 
    1458             : GF_EXPORT
    1459       58777 : u32 gf_bs_read_u32_le(GF_BitStream *bs)
    1460             : {
    1461             :         u32 ret, v;
    1462       58777 :         ret = gf_bs_read_int(bs, 8);
    1463       58777 :         v = gf_bs_read_int(bs, 8);
    1464       58777 :         v<<=8;
    1465       58777 :         ret |= v;
    1466       58777 :         v = gf_bs_read_int(bs, 8);
    1467       58777 :         v<<=16;
    1468       58777 :         ret |= v;
    1469       58777 :         v = gf_bs_read_int(bs, 8);
    1470       58777 :         v<<=24;
    1471       58777 :         ret |= v;
    1472       58777 :         return ret;
    1473             : }
    1474             : 
    1475             : GF_EXPORT
    1476         113 : u16 gf_bs_read_u16_le(GF_BitStream *bs)
    1477             : {
    1478             :         u32 ret, v;
    1479         113 :         ret = gf_bs_read_int(bs, 8);
    1480         113 :         v = gf_bs_read_int(bs, 8);
    1481         113 :         v<<=8;
    1482         113 :         ret |= v;
    1483         113 :         return ret;
    1484             : }
    1485             : 
    1486             : GF_EXPORT
    1487           1 : void gf_bs_write_u64_le(GF_BitStream *bs, u64 val)
    1488             : {
    1489           1 :         gf_bs_write_int(bs, val & 0xFF, 8);
    1490           1 :         gf_bs_write_int(bs, (val>>8) & 0xFF, 8);
    1491           1 :         gf_bs_write_int(bs, (val>>16) & 0xFF, 8);
    1492           1 :         gf_bs_write_int(bs, (val>>24) & 0xFF, 8);
    1493           1 :         gf_bs_write_int(bs, (val>>32) & 0xFF, 8);
    1494           1 :         gf_bs_write_int(bs, (val>>40) & 0xFF, 8);
    1495           1 :         gf_bs_write_int(bs, (val>>48) & 0xFF, 8);
    1496           1 :         gf_bs_write_int(bs, (val>>56) & 0xFF, 8);
    1497           1 : }
    1498             : 
    1499             : GF_EXPORT
    1500         211 : void gf_bs_write_u32_le(GF_BitStream *bs, u32 val)
    1501             : {
    1502         211 :         gf_bs_write_int(bs, val & 0xFF, 8);
    1503         211 :         gf_bs_write_int(bs, val>>8, 8);
    1504         211 :         gf_bs_write_int(bs, val>>16, 8);
    1505         211 :         gf_bs_write_int(bs, val>>24, 8);
    1506         211 : }
    1507             : 
    1508             : GF_EXPORT
    1509          59 : void gf_bs_write_u16_le(GF_BitStream *bs, u32 val)
    1510             : {
    1511          59 :         gf_bs_write_int(bs, val & 0xFF, 8);
    1512          59 :         gf_bs_write_int(bs, val>>8, 8);
    1513          59 : }
    1514             : 
    1515             : GF_EXPORT
    1516          21 : u32 gf_bs_get_bit_offset(GF_BitStream *bs)
    1517             : {
    1518          21 :         if (bs->bsmode==GF_BITSTREAM_READ) return (u32) ( (bs->position - 1) * 8 + bs->nbBits);
    1519           0 :         return (u32) ( (bs->position ) * 8 + bs->nbBits);
    1520             : }
    1521             : 
    1522             : GF_EXPORT
    1523     1044109 : u32 gf_bs_get_bit_position(GF_BitStream *bs)
    1524             : {
    1525     1044109 :         return bs->nbBits;
    1526             : }
    1527             : 
    1528             : GF_EXPORT
    1529           1 : u32 gf_bs_read_vluimsbf5(GF_BitStream *bs)
    1530             : {
    1531             :         u32 nb_words = 0;
    1532           1 :         while (gf_bs_read_int(bs, 1)) nb_words++;
    1533           1 :         nb_words++;
    1534           1 :         return gf_bs_read_int(bs, 4*nb_words);
    1535             : }
    1536             : 
    1537             : GF_EXPORT
    1538        7685 : void gf_bs_truncate(GF_BitStream *bs)
    1539             : {
    1540        7685 :         bs->size = bs->position;
    1541        7685 : }
    1542             : 
    1543             : 
    1544             : GF_EXPORT
    1545        3709 : GF_Err gf_bs_transfer(GF_BitStream *dst, GF_BitStream *src, Bool keep_src)
    1546             : {
    1547             :         u8 *data;
    1548             :         u32 data_len, written;
    1549             : 
    1550        3709 :         data = NULL;
    1551        3709 :         data_len = 0;
    1552        3709 :         gf_bs_get_content(src, &data, &data_len);
    1553        3709 :         if (!data || !data_len)
    1554             :         {
    1555           1 :                 if (data) {
    1556           0 :                         if (keep_src) {
    1557           0 :                                 src->original = data;
    1558           0 :                                 src->size = data_len;
    1559             :                         } else {
    1560           0 :                                 gf_free(data);
    1561             :                         }
    1562             :                         return GF_IO_ERR;
    1563             :                 }
    1564             :                 return GF_OK;
    1565             :         }
    1566        3708 :         written = gf_bs_write_data(dst, data, data_len);
    1567        3708 :         if (keep_src) {
    1568         210 :                 src->original = data;
    1569         210 :                 src->size = data_len;
    1570             :         } else {
    1571        3498 :                 gf_free(data);
    1572             :         }
    1573        3708 :         if (written<data_len) return GF_IO_ERR;
    1574        3708 :         return GF_OK;
    1575             : }
    1576             : 
    1577             : GF_EXPORT
    1578         455 : void gf_bs_flush(GF_BitStream *bs)
    1579             : {
    1580         455 :         if (!bs->stream) return;
    1581           1 :         if (bs->bsmode != GF_BITSTREAM_FILE_WRITE) return;
    1582             : 
    1583           1 :         if (bs->cache_write)
    1584           1 :                 bs_flush_write_cache(bs);
    1585             : 
    1586           1 :         gf_fflush(bs->stream);
    1587             : }
    1588             : 
    1589             : #if 0 //unused
    1590             : /*!
    1591             : \brief Reassigns FILE object for stream-based bitstreams
    1592             :  *
    1593             :  *Reassigns FILE object for stream-based bitstreams. Automatically sets the stream position to the bitstream position
    1594             : \param bs the target bitstream
    1595             : \param stream the new stream to assign
    1596             :  */
    1597             : void gf_bs_reassign(GF_BitStream *bs, FILE *stream)
    1598             : {
    1599             :         if (!bs) return;
    1600             :         switch (bs->bsmode) {
    1601             :         case GF_BITSTREAM_FILE_WRITE:
    1602             :         case GF_BITSTREAM_FILE_READ:
    1603             :                 bs->stream = stream;
    1604             :                 if (gf_ftell(stream) != bs->position)
    1605             :                         gf_bs_seek(bs, bs->position);
    1606             :                 break;
    1607             :         }
    1608             : }
    1609             : #endif
    1610             : 
    1611       11329 : u64 gf_bs_set_cookie(GF_BitStream *bs, u64 cookie)
    1612             : {
    1613             :         u64 res = 0;
    1614       11329 :         if (bs) {
    1615       11329 :                 res = bs->cookie;
    1616       11329 :                 bs->cookie = cookie;
    1617             :         }
    1618       11329 :         return res;
    1619             : }
    1620             : 
    1621      171493 : u64 gf_bs_get_cookie(GF_BitStream *bs)
    1622             : {
    1623      171493 :         if (!bs) return 0;
    1624      171493 :         return bs->cookie;
    1625             : }
    1626             : 
    1627             : GF_EXPORT
    1628           3 : GF_Err gf_bs_insert_data(GF_BitStream *bs, u8 *data, u32 size, u64 offset)
    1629             : {
    1630             :         u64 cur_r, cur_w, pos;
    1631             :         u32 nb_io;
    1632             : 
    1633           3 :         if (bs->on_block_out) return GF_BAD_PARAM;
    1634             : 
    1635           3 :         pos = bs->position;
    1636           3 :         nb_io = gf_bs_write_data(bs, data, size);
    1637           3 :         if (nb_io != size) goto exit;
    1638             : 
    1639           3 :         cur_w = bs->position;
    1640           3 :         gf_bs_seek(bs, pos);
    1641             :         cur_r = pos;
    1642             :         pos = cur_w;
    1643           3 :         while (cur_r > offset) {
    1644             :                 u8 block[8196];
    1645             :                 u32 move_bytes = 8196;
    1646          32 :                 if (cur_r - offset < move_bytes)
    1647           2 :                         move_bytes = (u32) (cur_r - offset);
    1648             : 
    1649          32 :                 gf_bs_seek(bs, cur_r - move_bytes);
    1650          32 :                 nb_io = gf_bs_read_data(bs, block, move_bytes);
    1651          32 :                 if (nb_io != move_bytes) goto exit;
    1652          32 :                 gf_bs_seek(bs, cur_w - move_bytes);
    1653          32 :                 nb_io = gf_bs_write_data(bs, block, move_bytes);
    1654          32 :                 if (nb_io != move_bytes) goto exit;
    1655             :                 cur_r -= move_bytes;
    1656             :                 cur_w -= move_bytes;
    1657             :         }
    1658             : 
    1659           3 :         gf_bs_seek(bs, offset);
    1660           3 :         nb_io = gf_bs_write_data(bs, data, size);
    1661           3 :         if (nb_io != size) goto exit;
    1662             : 
    1663           3 :         gf_bs_seek(bs, pos);
    1664           3 :         return GF_OK;
    1665             : 
    1666           0 : exit:
    1667           0 :         gf_bs_seek(bs, pos);
    1668           0 :         return GF_IO_ERR;
    1669             : }
    1670             : 
    1671             : 
    1672        9633 : GF_Err gf_bs_set_logger(GF_BitStream *bs, void (*on_bs_log)(void *udta, const char *field_name, u32 nb_bits, u64 field_val, s32 idx1, s32 idx2, s32 idx3), void *udta)
    1673             : {
    1674        9633 :         if (!bs) return GF_BAD_PARAM;
    1675        9633 :         bs->on_log = on_bs_log;
    1676        9633 :         bs->log_udta = udta;
    1677        9633 :         return GF_OK;
    1678             : }
    1679             : 
    1680             : #ifndef GPAC_DISABLE_AVPARSE_LOGS
    1681    21076936 : void gf_bs_log_idx(GF_BitStream *bs, u32 nBits, const char *fname, s64 val, s32 idx1, s32 idx2, s32 idx3)
    1682             : {
    1683             :         assert(bs);
    1684    21076936 :         if (bs->on_log) bs->on_log(bs->log_udta, fname, nBits, val, idx1, idx2, idx3);
    1685    21076936 : }
    1686             : #endif
    1687             : 
    1688             : 

Generated by: LCOV version 1.13