correct csgp atom

This commit is contained in:
Christian R. Helmrich 2021-05-29 16:00:01 +02:00
parent e38b9a3d7d
commit b11042a0f0
2 changed files with 22 additions and 24 deletions

View File

@ -113,9 +113,10 @@ int BasicMP4Writer::finishFile (const unsigned avgBitrate, const unsigned maxBit
const unsigned numFramesFirstPeriod = __min (m_frameCount, m_rndAccPeriod); const unsigned numFramesFirstPeriod = __min (m_frameCount, m_rndAccPeriod);
const unsigned numFramesFinalPeriod = (m_frameCount <= m_rndAccPeriod ? 0 : m_frameCount % m_rndAccPeriod); const unsigned numFramesFinalPeriod = (m_frameCount <= m_rndAccPeriod ? 0 : m_frameCount % m_rndAccPeriod);
const unsigned numSamplesFinalFrame = (audioLength + m_preLength + m_postLength) % m_frameLength; const unsigned numSamplesFinalFrame = (audioLength + m_preLength + m_postLength) % m_frameLength;
const uint32_t raOffsetSize = (uint32_t) m_rndAccOffsets.size ();
const uint32_t stszAtomSize = STSX_BSIZE + 4 /*bytes for sampleSize*/ + m_frameCount * 4; const uint32_t stszAtomSize = STSX_BSIZE + 4 /*bytes for sampleSize*/ + m_frameCount * 4;
const uint32_t stscAtomSize = STSX_BSIZE + (numFramesFinalPeriod == 0 ? 12 : 24); const uint32_t stscAtomSize = STSX_BSIZE + (numFramesFinalPeriod == 0 ? 12 : 24);
const uint32_t stcoAtomSize = STSX_BSIZE + (uint32_t) m_rndAccOffsets.size () * 4; const uint32_t stcoAtomSize = STSX_BSIZE + raOffsetSize * 4;
#ifdef NO_PREROLL_DATA #ifdef NO_PREROLL_DATA
const uint32_t stssAtomSize = STSX_BSIZE + 4; const uint32_t stssAtomSize = STSX_BSIZE + 4;
#else #else
@ -124,10 +125,11 @@ int BasicMP4Writer::finishFile (const unsigned avgBitrate, const unsigned maxBit
#endif #endif
/* The following code creates a 'prol' sample group with a repeating pattern of membership, /* The following code creates a 'prol' sample group with a repeating pattern of membership,
indicating that the first sample in each increment of m_rndAccPeriod samples is a member and indicating that the first sample in each increment of m_rndAccPeriod samples is a member and
thus an independent frame (IF) or immediate playout frame (IPF), and the remainder are not. */ thus an independent frame (but not an immediate playout frame), and the remainder are not. */
const uint32_t sgpdAtomSize = STSX_BSIZE + 4 /*defaultLength == 2*/ + 4 /*entryCount == 1*/ + 2 /*rollDistance*/; const uint32_t sgpdAtomSize = STSX_BSIZE + 4 /*defaultLength == 2*/ + 4 /*entryCount == 1*/ + 2 /*rollDistance*/;
const uint32_t patternLengthSize = (numFramesFirstPeriod > UINT8_MAX ? 2 : 1); const unsigned patternEntryCount = __min (m_frameCount, m_rndAccPeriod << 1);
const uint32_t compPatternLength = (numFramesFirstPeriod + 1) >> 1; // 4 bit per index with byte alignment const uint32_t patternLengthSize = (patternEntryCount > UINT8_MAX ? 2 : 1);
const uint32_t compPatternLength = (patternEntryCount + 1) >> 1; // four bit per index with byte alignment
const uint32_t sampleCountSize = (m_frameCount > UINT16_MAX ? 4 : (m_frameCount > UINT8_MAX ? 2 : 1)); const uint32_t sampleCountSize = (m_frameCount > UINT16_MAX ? 4 : (m_frameCount > UINT8_MAX ? 2 : 1));
const uint32_t csgpAtomSize = STSX_BSIZE + 4 /*patternCount == 1*/ + patternLengthSize + sampleCountSize + compPatternLength; const uint32_t csgpAtomSize = STSX_BSIZE + 4 /*patternCount == 1*/ + patternLengthSize + sampleCountSize + compPatternLength;
const uint32_t stblIncrSize = m_ascSizeM5 + stszAtomSize + stscAtomSize + stcoAtomSize + stssAtomSize + sgpdAtomSize + csgpAtomSize; const uint32_t stblIncrSize = m_ascSizeM5 + stszAtomSize + stscAtomSize + stcoAtomSize + stssAtomSize + sgpdAtomSize + csgpAtomSize;
@ -140,6 +142,7 @@ int BasicMP4Writer::finishFile (const unsigned avgBitrate, const unsigned maxBit
const uint32_t timeStampBE = toBigEndian (modifTime); const uint32_t timeStampBE = toBigEndian (modifTime);
uint32_t* const header4Byte = (uint32_t* const) m_staticHeader; uint32_t* const header4Byte = (uint32_t* const) m_staticHeader;
int bytesWritten = 0; int bytesWritten = 0;
uint32_t i;
if ((m_fileHandle == -1) || (m_mediaSize > 0xFFFFFFF0u - m_mediaOffset)) if ((m_fileHandle == -1) || (m_mediaSize > 0xFFFFFFF0u - m_mediaOffset))
{ {
@ -150,7 +153,7 @@ int BasicMP4Writer::finishFile (const unsigned avgBitrate, const unsigned maxBit
{ {
memcpy (&m_staticHeader[571], ascBuf, 5 * sizeof (uint8_t)); memcpy (&m_staticHeader[571], ascBuf, 5 * sizeof (uint8_t));
for (unsigned i = 0; i < m_ascSizeM5; i++) m_dynamicHeader.at (i) = ascBuf[5 + i]; for (i = 0; i < m_ascSizeM5; i++) m_dynamicHeader.at (i) = ascBuf[5 + i];
} }
// finish setup of fixed-length part of MPEG-4 file header // finish setup of fixed-length part of MPEG-4 file header
@ -202,7 +205,7 @@ int BasicMP4Writer::finishFile (const unsigned avgBitrate, const unsigned maxBit
if (numFramesFinalPeriod > 0) if (numFramesFinalPeriod > 0)
{ {
push32BitValue ((uint32_t) m_rndAccOffsets.size ()); push32BitValue (raOffsetSize);
push32BitValue (numFramesFinalPeriod); push32BitValue (numFramesFinalPeriod);
push32BitValue (1); push32BitValue (1);
} }
@ -211,13 +214,10 @@ int BasicMP4Writer::finishFile (const unsigned avgBitrate, const unsigned maxBit
m_dynamicHeader.push_back (0x73); m_dynamicHeader.push_back (0x74); m_dynamicHeader.push_back (0x73); m_dynamicHeader.push_back (0x74);
m_dynamicHeader.push_back (0x63); m_dynamicHeader.push_back (0x6F); // stco m_dynamicHeader.push_back (0x63); m_dynamicHeader.push_back (0x6F); // stco
push32BitValue (0); push32BitValue (0);
push32BitValue ((uint32_t) m_rndAccOffsets.size ()); push32BitValue (raOffsetSize);
// add header size corrected random-access offsets to file // add header size corrected random-access offsets to file
for (uint32_t i = 0; i < (uint32_t) m_rndAccOffsets.size (); i++) for (i = 0; i < raOffsetSize; i++) push32BitValue (m_rndAccOffsets.at (i) + m_mediaOffset);
{
push32BitValue (m_rndAccOffsets.at (i) + m_mediaOffset);
}
push32BitValue (stssAtomSize); push32BitValue (stssAtomSize);
m_dynamicHeader.push_back (0x73); m_dynamicHeader.push_back (0x74); m_dynamicHeader.push_back (0x73); m_dynamicHeader.push_back (0x74);
@ -228,10 +228,7 @@ int BasicMP4Writer::finishFile (const unsigned avgBitrate, const unsigned maxBit
push32BitValue (1); // AU! push32BitValue (1); // AU!
#else #else
push32BitValue (preRollCount); push32BitValue (preRollCount);
for (uint32_t i = 1; i <= m_frameCount; i += (m_rndAccPeriod << 1)) for (i = 1; i <= m_frameCount; i += (m_rndAccPeriod << 1)) push32BitValue (i);
{
push32BitValue (i);
}
#endif #endif
push32BitValue (sgpdAtomSize); push32BitValue (sgpdAtomSize);
m_dynamicHeader.push_back (0x73); m_dynamicHeader.push_back (0x67); m_dynamicHeader.push_back (0x73); m_dynamicHeader.push_back (0x67);
@ -251,9 +248,9 @@ int BasicMP4Writer::finishFile (const unsigned avgBitrate, const unsigned maxBit
push32BitValue (1); push32BitValue (1);
if (patternLengthSize > 1) if (patternLengthSize > 1)
{ {
m_dynamicHeader.push_back ((numFramesFirstPeriod >> 8) & UCHAR_MAX); m_dynamicHeader.push_back ((patternEntryCount >> 8) & UCHAR_MAX);
} }
m_dynamicHeader.push_back ( numFramesFirstPeriod & UCHAR_MAX); m_dynamicHeader.push_back ( patternEntryCount & UCHAR_MAX);
if (sampleCountSize > 2) if (sampleCountSize > 2)
{ {
m_dynamicHeader.push_back ((m_frameCount >> 24) & UCHAR_MAX); m_dynamicHeader.push_back ((m_frameCount >> 24) & UCHAR_MAX);
@ -265,10 +262,11 @@ int BasicMP4Writer::finishFile (const unsigned avgBitrate, const unsigned maxBit
} }
m_dynamicHeader.push_back ( m_frameCount & UCHAR_MAX); m_dynamicHeader.push_back ( m_frameCount & UCHAR_MAX);
m_dynamicHeader.push_back ((1 << 4) | 0); // first frame is a member of 'prol' group and remainder are not for (i = 0; i < (numFramesFirstPeriod >> 1); i++) m_dynamicHeader.push_back (0); // nonmembers, first part
for (uint32_t pNdx = 1; pNdx < compPatternLength; pNdx++) if (i < compPatternLength)
{ {
m_dynamicHeader.push_back (0); // remaining 4-bit pairs of nonmembers m_dynamicHeader.push_back (1 << ((numFramesFirstPeriod & 1) ? 0 : 4));
for (i++; i < compPatternLength; i++) m_dynamicHeader.push_back (0); // rest of nonmembers, second part
} }
const uint32_t moovAndMdatOverhead = STAT_HEADER_SIZE + (uint32_t) m_dynamicHeader.size () + 8; const uint32_t moovAndMdatOverhead = STAT_HEADER_SIZE + (uint32_t) m_dynamicHeader.size () + 8;
@ -299,7 +297,7 @@ int BasicMP4Writer::finishFile (const unsigned avgBitrate, const unsigned maxBit
{ {
uint8_t crc8 = m_dynamicHeader.back(); // Baicheva '98 uint8_t crc8 = m_dynamicHeader.back(); // Baicheva '98
for (uint16_t i = 8; i > 0; i--) if (crc8 & 0x80) crc8 = (crc8 << 1) ^ 0x2F; else crc8 <<= 1; for (i = 8; i > 0; i--) if (crc8 & 0x80) crc8 = (crc8 << 1) ^ 0x2F; else crc8 <<= 1;
m_dynamicHeader.push_back (crc8); // add padding CRC-8 m_dynamicHeader.push_back (crc8); // add padding CRC-8
} }
else else
@ -320,9 +318,9 @@ int BasicMP4Writer::initHeader (const uint32_t audioLength, const unsigned extra
{ {
const unsigned frameCount = (audioLength + m_preLength + m_postLength - extraDelay + m_frameLength - 1u) / m_frameLength; const unsigned frameCount = (audioLength + m_preLength + m_postLength - extraDelay + m_frameLength - 1u) / m_frameLength;
const unsigned chunkCount = ((frameCount + m_rndAccPeriod - 1) / m_rndAccPeriod); const unsigned chunkCount = ((frameCount + m_rndAccPeriod - 1) / m_rndAccPeriod);
const unsigned numFramesFirstPeriod = __min (frameCount, m_rndAccPeriod);
const unsigned numFramesFinalPeriod = (frameCount <= m_rndAccPeriod ? 0 : frameCount % m_rndAccPeriod); const unsigned numFramesFinalPeriod = (frameCount <= m_rndAccPeriod ? 0 : frameCount % m_rndAccPeriod);
const unsigned smpGrpSize = 10 /*sgpd*/ + (numFramesFirstPeriod > UINT8_MAX ? 10 : 9) + ((numFramesFirstPeriod + 1) >> 1) /*csgp*/; const unsigned patternEntryCount = __min (frameCount, m_rndAccPeriod << 1);
const unsigned smpGrpSize = 10 /*sgpd*/ + (patternEntryCount > UINT8_MAX ? 10 : 9) + ((patternEntryCount + 1) >> 1) /*csgp*/;
const int estimHeaderSize = STAT_HEADER_SIZE + m_ascSizeM5 + 6 + 4 + frameCount * 4 /*stsz*/ + STSX_BSIZE * 6 + smpGrpSize + chunkCount * 4 /*stco*/ + const int estimHeaderSize = STAT_HEADER_SIZE + m_ascSizeM5 + 6 + 4 + frameCount * 4 /*stsz*/ + STSX_BSIZE * 6 + smpGrpSize + chunkCount * 4 /*stco*/ +
#ifdef NO_PREROLL_DATA #ifdef NO_PREROLL_DATA
4 /*minimum stss*/ + 4 /*minimum stss*/ +

View File

@ -772,7 +772,7 @@ int main (const int argc, char* argv[])
+ (enableUpsampler && (variableCoreBitRateMode < 9) ? 1 : 0) + (enableUpsampler && (variableCoreBitRateMode < 9) ? 1 : 0)
#endif #endif
#if !RESTRICT_TO_AAC #if !RESTRICT_TO_AAC
, true /*noise filling*/, compatibleExtensionFlag > 0 , !(argc >= 5 && (argv[2][0] == 'n' || argv[2][0] == 'N') && argv[2][1] == 0), compatibleExtensionFlag > 0
#endif #endif
); );
BasicMP4Writer mp4Writer; // .m4a file BasicMP4Writer mp4Writer; // .m4a file