We handle the cases where the old codec private data size is larger, smaller or equal to the new one.

This commit is contained in:
Frédéric Tronel
2023-12-19 14:12:23 +01:00
parent 6959e83327
commit 2bf9b467bb

View File

@@ -294,6 +294,34 @@ def parseMKVTree(mkvinfo, inputFile):
# 0000 0001 xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx - value 0 to 2^56-2
def getEBMLLength(length):
if (0 <= length) and (length <= 2^7-2):
size = 1
elif length <= 2^14-2:
size = 2
elif length <= 2^21-2:
size = 3
elif length <= 2^28-2:
size = 4
elif length <= 2^35-2:
size = 5
elif length <= 2^42-2:
size = 6
elif length <= 2^49-2:
size = 7
elif length <= 2^56-2:
size = 8
elif length < 0:
logger.error('Impossible to encode a negative length with EBML.')
return None
else:
logger.error('Impossible to encode a length larger than 2^56-2 with EBML.')
return None
encodedLength = length + ((128>>(size-1))<<((size-1)*8))
res = (encodedLength).to_bytes(size, byteorder='big')
return res
def changeEBMLElementSize(inputFile, position, addendum):
logger = logging.getLogger(__name__)
@@ -350,6 +378,7 @@ def changeEBMLElementSize(inputFile, position, addendum):
newSize = sizeOfData+addendum
if newSize > maxSize:
# TODO: we can reencode the header with a larger length field ...
logger.error('New size is too big to be encoded in actual size field.')
exit(-1)
@@ -360,7 +389,8 @@ def changeEBMLElementSize(inputFile, position, addendum):
lseek(infd, position, SEEK_SET)
write(infd, newSizeBuf)
# TODO: we will return the increase of length of the modified element (if its new size does not fit the older one)
return 0
def changeCodecPrivateData(mkvinfo, inputFile, codecData):
logger = logging.getLogger(__name__)
@@ -408,24 +438,37 @@ def changeCodecPrivateData(mkvinfo, inputFile, codecData):
write(infd, tail)
lseek(infd, position, SEEK_SET)
write(infd, codecData)
elif currentLength == futureLength:
# Almost nothing to do except overwriting old private codec data with new ones.
lseek(infd, position, SEEK_SET)
write(infd, codecData)
else:
lseek(infd, position+currentDataLength, SEEK_SET)
tail = read(infd, currentLength-(position+currentDataLength))
lseek(infd, position+len(codecData), SEEK_SET)
write(infd, tail)
lseek(infd, position, SEEK_SET)
write(infd, codecData)
# We reduce the length of file.
ftruncate(infd, futureLength)
# We have to modify the tree elements up to the root that contains the codec private data.
keys = key.split('.')
logger.info(keys)
keys = key.split('.')
logger.info(keys)
delta = futureLength-currentLength
# if there is no modification of the private codec data, no need to change anything.
if delta != 0:
for i in range(0, len(keys)-1):
keys.pop()
key=".".join(map(str, keys))
pos, size = elements[key]
logger.info('Trying to fix element with key: %s at position: %d with actual size: %d.' % (key, pos, size))
changeEBMLElementSize(inputFile, pos, futureLength-currentLength)
elif currentLength == futureLength:
logger.error("Not yet implemented")
exit(-1)
else:
logger.error("Not yet implemented")
exit(-1)
# Changing an element can increase its size (in very rare case).
# In that case, we update the new delta that will be larger (because the element has been resized).
# For now, the function always return 0.
delta+=changeEBMLElementSize(inputFile, pos, delta)
def getFormat(ffprobe, inputFile):
logger = logging.getLogger(__name__)