Files
core/ASCImageStudio3/ASCImageJpeg2000/Mj2.h

1541 lines
40 KiB
C

#pragma once
#include "Types.h"
//-------------------------------------------------------------------------------------------------------------------------------
// Äàííûå ôóíêöèè ïðåäíàçíà÷åíû äëÿ ÷òåíèÿ Motion JPEG 2000 (MJ2)
//-------------------------------------------------------------------------------------------------------------------------------
static bool Mj2_ReadBoxHeader(Mj2_Box* pBox, CReader * pStream)
{
if ( !pBox )
return false;
pBox->nInitPos = pStream->Tell();
pBox->nLength = pStream->Read( 4 );
pBox->nType = pStream->Read( 4 );
if ( 1 == pBox->nLength )
{
if ( 0 != pStream->Read( 4 ) )
{
Event_Message( EVT_ERROR, "Error: Cannot handle box sizes higher than 2^32\n" );
return false;
}
pBox->nLength = pStream->Read( 4 );
if ( 0 == pBox->nLength )
pBox->nLength = pStream->GetLeftSize() + 12;
}
else if ( 0 == pBox->nLength )
{
int nBytesLeft = pStream->GetLeftSize();
if ( 0 == nBytesLeft )
return false;
pBox->nLength = nBytesLeft + 8;
}
return true;
}
static bool Mj2_ReadJP (CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( oBox.nType != MJ2_JP )
{
Event_Message( EVT_ERROR, "Error: Expected JP Marker\n" );
return false;
}
if ( 0x0d0a870a != pStream->Read( 4 ) ) // read the 0x0d0a870a required in a JP box
{
Event_Message( EVT_ERROR, "Error with JP Marker\n" );
return false;
}
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with JP Box size \n" );
return false;
}
return true;
}
static bool Mj2_ReadFTYP (Mj2_Movie* pMovie, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_FTYP != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected FTYP Marker\n" );
return false;
}
pMovie->unBrand = pStream->Read( 4 ); // BR
pMovie->unMinVersion = pStream->Read( 4 ); // MinV
pMovie->nCompListLength = ( oBox.nLength - 16 ) / 4;
pMovie->pCompList = (unsigned int*)Malloc(0, pMovie->nCompListLength * sizeof(unsigned int) );
for ( int nIndex = pMovie->nCompListLength - 1; nIndex > -1; nIndex-- )
{
pMovie->pCompList[nIndex] = pStream->Read( 4 ); // CLi
}
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with FTYP Box\n" );
return false;
}
return true;
}
static bool Mj2_ReadMDAT (Mj2_Movie* pMovie, CReader * pStream, Image** ppImage, Mj2_Box oBox)
{
if ( MJ2_MDAT != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected FTYP Marker\n" );
return false;
}
int nStartPos = pStream->Tell();
//>>>>
// Äîñòàåì ïåðâóþ êàðòèíêó â ïîòîêå MDAT
Jp2Box oTempBox;
Jp2_ReadBoxHeader( pMovie->pCodecInfo, pStream, &oTempBox );
do
{
if( JP2_JP2C != oTempBox.nType )
{
pStream->Skip( oTempBox.nLength - 8 );
if ( pStream->GetLeftSize() < 0 )
return false;
if ( !Jp2_ReadBoxHeader( pMovie->pCodecInfo, pStream, &oTempBox ) )
return false;
}
} while( JP2_JP2C != oTempBox.nType );
int nJ2kCodestreamOffset = pStream->Tell();
int nJ2kCodestreamLength = oTempBox.nLength - 8;
// Äåêîäèðóåì J2K
*ppImage = J2k_Decode( pMovie->pJ2k, pStream );
if( !*ppImage )
{
Event_Message(EVT_ERROR, "Failed to decode J2K image\n" );
return false;
}
//<<<<<<
int nReaded = pStream->Tell() - nStartPos;
pStream->Skip( oBox.nLength - nReaded - 8 );
if ( pStream->GetLeftSize() < 0 )
return false;
return true;
}
static bool Mj2_ReadMVHD (Mj2_Movie* pMovie, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_MVHD != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected MVHD Marker\n" );
return false;
}
if ( 0 != pStream->Read( 4 ) ) // Version = 0, flags = 0
{
Event_Message( EVT_ERROR, "Error: Only Version 0 handled in MVHD box\n" );
}
// TO DO: Çäåñü â çàâèñèìîñòè îò âåðñèè ðàçíîå ÷èñëî áàéò äîëæíî ÷èòàòüñÿ
// ñì. fcd15444-3.pdf ñòð.15
pMovie->unCreationTime = pStream->Read( 4 ); // Creation Time
pMovie->unModificationTime = pStream->Read( 4 ); // Modification Time
pMovie->nTimescale = pStream->Read( 4 ); // Timescale
pMovie->unDuration = pStream->Read( 4 ); // Duration
pMovie->nRate = pStream->Read( 4 ); // Rate
pMovie->nVolume = pStream->Read( 2 ); // Volume
pStream->Skip( 10 ); // const bit(16) reserved = 0 + const unsigned int(32)[2] reserved = 0
pMovie->anTransMatrix[0] = pStream->Read( 4 ); // Transformation matrix
pMovie->anTransMatrix[1] = pStream->Read( 4 ); //
pMovie->anTransMatrix[2] = pStream->Read( 4 ); //
pMovie->anTransMatrix[3] = pStream->Read( 4 ); //
pMovie->anTransMatrix[4] = pStream->Read( 4 ); //
pMovie->anTransMatrix[5] = pStream->Read( 4 ); //
pMovie->anTransMatrix[6] = pStream->Read( 4 ); //
pMovie->anTransMatrix[7] = pStream->Read( 4 ); //
pMovie->anTransMatrix[8] = pStream->Read( 4 ); //
pStream->Skip( 24 ); // bit(32)[6] pre-defined = 0;
pMovie->nNextTrackId = pStream->Read( 4 ); // ID of Next track to be added
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with MVHD Box Size\n" );
return false;
}
return true;
}
static bool Mj2_ReadTKHD (Mj2_TrackParams* pTrack, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_TKHD != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected TKHD Marker\n" );
return false;
}
// TO DO: Çäåñü â çàâèñèìîñòè îò âåðñèè ðàçíîå ÷èñëî áàéò äîëæíî ÷èòàòüñÿ
// ñì. fcd15444-3.pdf ñòð.16
if ( 0 != pStream->Read( 1 ) ) // Version = 0
{
Event_Message( EVT_ERROR, "Error: Only Version 0 handled in TKHD box\n" );
return false;
}
int nFlag = pStream->Read( 3 );
if ( !( 1 == nFlag || 2 == nFlag || 3 == nFlag || 4 == nFlag ) ) // nFlags = 1, 2, 3 èëè 4
{
Event_Message( EVT_ERROR, "Error with flag in TKHD box: Expected flag 1,2,3 or 4\n" );
return false;
}
pTrack->unCreationTime = pStream->Read( 4 ); // Creation Time
pTrack->unModificationTime = pStream->Read( 4 ); // Modification Time
pTrack->nTrackID = pStream->Read( 4 ); // Track ID
pStream->Skip( 4 ); // const unsigned int(32) reserved = 0;
pTrack->nDuration = pStream->Read( 4 ); // Duration
pStream->Skip( 8 ); // const unsigned int(32)[2] reserved = 0;
pTrack->nLayer = pStream->Read( 2 ); // Layer
pStream->Read( 2 ); // int(16) pre-defined = 0;
pTrack->nVolume = pStream->Read( 2 ); // Volume
pStream->Skip( 2 ); // const unsigned int(16) reserved = 0;
pTrack->anTransMatrix[0] = pStream->Read( 4 ); // Transformation matrix for track */
pTrack->anTransMatrix[1] = pStream->Read( 4 ); //
pTrack->anTransMatrix[2] = pStream->Read( 4 ); //
pTrack->anTransMatrix[3] = pStream->Read( 4 ); //
pTrack->anTransMatrix[4] = pStream->Read( 4 ); //
pTrack->anTransMatrix[5] = pStream->Read( 4 ); //
pTrack->anTransMatrix[6] = pStream->Read( 4 ); //
pTrack->anTransMatrix[7] = pStream->Read( 4 ); //
pTrack->anTransMatrix[8] = pStream->Read( 4 ); //
pTrack->nVisualWidth = pStream->Read( 4 ); // Image Visual Width
pTrack->nVisualHeight = pStream->Read( 4 ); // Image Visual Height
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with TKHD Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadMDHD (Mj2_TrackParams* pTrack, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( !( MJ2_MHDR == oBox.nType || MJ2_MDHD == oBox.nType ) ) // Kakadu writes MHDR instead of MDHD
{
Event_Message( EVT_ERROR, "Error: Expected MDHD Marker\n" );
return 1;
}
// TO DO: Ñäåëàòü ïîîäåðæêó Version = 1
if ( 0 != pStream->Read( 1 ) ) // Version = 0
{
Event_Message( EVT_ERROR, "Error: Only Version 0 handled in MDHD box\n" );
return false;
}
if ( 0 != pStream->Read( 3 ) ) // Flags = 0
{
Event_Message( EVT_ERROR, "Error with flag in MDHD box. Expected flag 0\n" );
return false;
}
pTrack->unCreationTime = pStream->Read( 4 ); // Creation Time
pTrack->unModificationTime = pStream->Read( 4 ); // Modification Time
pTrack->nTimescale = pStream->Read( 4 ); // Timescale
pTrack->nDuration = pStream->Read( 4 ); // Duration
pTrack->nLanguage = pStream->Read( 2 ); // Language
pStream->Skip( 2 ); // unsigned int(16) pre-defined = 0;
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with MDHD Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadHDLR (Mj2_TrackParams* pTrack, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_HDLR != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected HDLR Marker\n" );
return false;
}
if ( 0 != pStream->Read( 1 ) ) // Version = 0
{
Event_Message( EVT_ERROR, "Error: Only Version 0 handled in HDLR box\n" );
return false;
}
if ( 0 != pStream->Read( 3 ) ) // Flags = 0
{
Event_Message( EVT_ERROR, "Error with flag in HDLR box. Expected flag 0\n" );
return false;
}
pStream->Skip( 4 ); // unsigned int(32) pre-defined = 0;
pTrack->nHandlerType = pStream->Read( 4 ); // handler-type
pStream->Skip( 12 ); // const unsigned int(32)[3] reserved = 0;
pTrack->nNameSize = oBox.nLength - 32;
pTrack->sName = (char*)Malloc(0, pTrack->nNameSize * sizeof(char) );
for ( int nIndex = 0; nIndex < pTrack->nNameSize; nIndex++ )
{
pTrack->sName[nIndex] = pStream->Read( 1 ); // Name
}
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with HDLR Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadVMHD (Mj2_TrackParams* pTrack, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_VMHD != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected VMHD Marker\n" );
return false;
}
if ( 0 != pStream->Read( 1 ) ) // Version = 0
{
Event_Message( EVT_ERROR, "Error: Only Version 0 handled in VMHD box\n" );
return false;
}
if ( 1 != pStream->Read( 3 ) ) // Flags = 1
{
Event_Message( EVT_ERROR, "Error with flag in VMHD box. Expected flag 1\n" );
return false;
}
pTrack->nTrackType = 0;
pTrack->nGraphicsMode = pStream->Read( 2 ); // graphicsmode
pTrack->anOpColor[0] = pStream->Read( 2 ); // opcolor
pTrack->anOpColor[1] = pStream->Read( 2 ); //
pTrack->anOpColor[2] = pStream->Read( 2 ); //
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with VMHD Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadSMHD (Mj2_TrackParams* pTrack, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_SMHD != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected SMHD Marker\n" );
return false;
}
if ( 0 != pStream->Read( 1 ) ) // Version = 0
{
Event_Message( EVT_ERROR, "Error: Only Version 0 handled in SMHD box\n" );
return false;
}
if ( 0 != pStream->Read( 3 ) ) // Flags = 0
{
Event_Message( EVT_ERROR, "Error with flag in SMHD box. Expected flag 0\n" );
return false;
}
pTrack->nTrackType = 1;
pTrack->nBalance = pStream->Read( 2 );
// Init variables to zero to avoid problems when freeeing memory
// The values will possibly be overidded when decoding the track structure
pTrack->nNumBr = 0;
pTrack->nNumUrl = 0;
pTrack->nNumUrn = 0;
pTrack->unNumChunks = 0;
pTrack->nNumTimeToSample = 0;
pTrack->nNumSamplesToChunk = 0;
pTrack->unNumSamples = 0;
pStream->Skip( 2 ); // Reserved
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with SMHD Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadHMHD (Mj2_TrackParams* pTrack, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_HMHD != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected HMHD Marker\n" );
return false;
}
if (0 != pStream->Read( 1 ) ) // Version = 0
{
Event_Message( EVT_ERROR, "Error: Only Version 0 handled in HMHD box\n");
return false;
}
if ( 0 != pStream->Read( 3 ) ) // Flags = 0
{
Event_Message( EVT_ERROR, "Error with flag in HMHD box. Expected flag 0\n");
return false;
}
pTrack->nTrackType = 2;
pTrack->nMaxPDUsize = pStream->Read( 2 ); // maxPDUsize
pTrack->nAvgPDUsize = pStream->Read( 2 ); // avgPDUsize
pTrack->nMaxBitrate = pStream->Read( 4 ); // maxbitrate
pTrack->nAvgBitrate = pStream->Read( 4 ); // avgbitrate
pTrack->nSlidingAvgBitrate = pStream->Read( 4 ); // slidingavgbitrate
// Init variables to zero to avoid problems when freeeing memory
// The values will possibly be overidded when decoding the track structure
pTrack->nNumBr = 0;
pTrack->nNumUrl = 0;
pTrack->nNumUrn = 0;
pTrack->unNumChunks = 0;
pTrack->nNumTimeToSample = 0;
pTrack->nNumSamplesToChunk = 0;
pTrack->unNumSamples = 0;
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with HMHD Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadURL (Mj2_TrackParams* pTrack, CReader * pStream, int nUrlNum)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_URL != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected URL Marker\n" );
return false;
}
if ( 0 != pStream->Read( 1 ) ) // Version = 0
{
Event_Message( EVT_ERROR, "Error: Only Version 0 handled in URL box\n" );
return false;
}
if ( 1 != pStream->Read( 3 ) ) // Åñëè flags = 1, òî ìåäèà äàííûå â ôàéëå
{
// TO DO: Ñäåëàòü íîðìàëüíîå ÷òåíèå ñòðîê
pTrack->pUrl[nUrlNum].anLocation[0] = pStream->Read( 4 );
pTrack->pUrl[nUrlNum].anLocation[1] = pStream->Read( 4 );
pTrack->pUrl[nUrlNum].anLocation[2] = pStream->Read( 4 );
pTrack->pUrl[nUrlNum].anLocation[3] = pStream->Read( 4 );
}
else
{
pTrack->nNumUrl--;
}
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with URL Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadURN (Mj2_TrackParams* pTrack, CReader * pStream, int nUrnNum)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_URN != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected URN Marker\n" );
return false;
}
if ( 0 != pStream->Read( 1 ) ) // Version = 0
{
Event_Message( EVT_ERROR, "Error: Only Version 0 handled in URN box\n" );
return false;
}
if ( 1 != pStream->Read( 3 ) ) // Åñëè flags = 1, òî ìåäèà äàííûå â ôàéëå
{
// TO DO: Ñäåëàòü íîðìàëüíîå ÷òåíèå ñòðîê
pTrack->pUrn[nUrnNum].anName[0] = pStream->Read( 4 );
pTrack->pUrn[nUrnNum].anName[1] = pStream->Read( 4 );
pTrack->pUrn[nUrnNum].anName[2] = pStream->Read( 4 );
pTrack->pUrn[nUrnNum].anName[3] = pStream->Read( 4 );
pTrack->pUrn[nUrnNum].anLocation[0] = pStream->Read( 4 );
pTrack->pUrn[nUrnNum].anLocation[1] = pStream->Read( 4 );
pTrack->pUrn[nUrnNum].anLocation[2] = pStream->Read( 4 );
pTrack->pUrn[nUrnNum].anLocation[3] = pStream->Read( 4 );
}
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with URN Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadDREF (Mj2_TrackParams* pTrack, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_DREF != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected DREF Marker\n" );
return false;
}
if ( 0 != pStream->Read( 1 ) ) // Version = 0
{
Event_Message( EVT_ERROR, "Error: Only Version 0 handled in DREF box\n" );
return false;
}
if ( 0 != pStream->Read( 3 ) ) // Flags = 0
{
Event_Message( EVT_ERROR, "Error with flag in DREF box. Expected flag 0\n" );
return 1;
}
int nEntryCount = pStream->Read( 4 ); // entry-count
pTrack->nNumUrl = 0;
pTrack->nNumUrn = 0;
for ( int nIndex = 0; nIndex < nEntryCount; nIndex++ )
{
pStream->Skip( 4 );
int nMarker = pStream->Read( 4 );
if ( MJ2_URL == nMarker )
{
pStream->Skip( -8 );
pTrack->nNumUrl++;
if ( !Mj2_ReadURL( pTrack, pStream, pTrack->nNumUrl ) )
return false;
}
else if ( MJ2_URN == nMarker )
{
pStream->Skip( -8 );
pTrack->nNumUrn++;
if ( !Mj2_ReadURN( pTrack, pStream, pTrack->nNumUrn ) )
return false;
}
else
{
Event_Message( EVT_ERROR, "Error with in DREF box. Expected URN or URL box\n" );
return false;
}
}
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with DREF Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadDINF (Mj2_TrackParams* pTrack, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_DINF != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected DINF Marker\n");
return false;
}
if ( !Mj2_ReadDREF( pTrack, pStream ) )
return false;
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with DINF Box size\n" );
return false;
}
return true;
}
static void Mj2_DecompatTTS (Mj2_TrackParams* pTrack)
{
pTrack->unNumSamples = 0;
for ( int nIndex = 0; nIndex < pTrack->nNumTimeToSample; nIndex++ )
{
pTrack->unNumSamples += pTrack->pTimeToSample[nIndex].nSampleCount;
}
pTrack->pSample = (Mj2_Sample*)Malloc(0, pTrack->unNumSamples * sizeof(Mj2_Sample) );
for ( int nIndexTTS = 0; nIndexTTS < pTrack->nNumTimeToSample; nIndexTTS++ )
{
for ( int nIndexSample = 0; nIndexSample < pTrack->pTimeToSample[nIndexTTS].nSampleCount; nIndexSample++ )
{
pTrack->pSample[nIndexSample].unSampleDelta = pTrack->pTimeToSample[nIndexTTS].nSampleDelta;
}
}
}
static void Mj2_DecompatSTSC (Mj2_TrackParams* pTrack)
{
if ( 1 == pTrack->nNumSamplesToChunk )
{
pTrack->unNumChunks = (unsigned int)ceil( (double)pTrack->unNumSamples / (double)pTrack->pSampleToChunk[0].nSamplesPerChunk );
pTrack->pChunk = (Mj2_Chunk*)Malloc(0, pTrack->unNumChunks * sizeof(Mj2_Chunk) );
for ( unsigned int unIndex = 0; unIndex < pTrack->unNumChunks; unIndex++ )
{
pTrack->pChunk[unIndex].nNumSamples = pTrack->pSampleToChunk[0].nSamplesPerChunk;
}
}
else
{
pTrack->pChunk = (Mj2_Chunk*)Malloc(0, pTrack->unNumChunks * sizeof(Mj2_Chunk) );
pTrack->unNumChunks = 0;
int nSampleNum = 0;
for ( int nIndexSTC = 0; nIndexSTC < pTrack->nNumSamplesToChunk -1 ; nIndexSTC++ )
{
for ( int nIndexChunk = pTrack->pSampleToChunk[nIndexSTC].nFirstChunk - 1; nIndexChunk < pTrack->pSampleToChunk[nIndexSTC + 1].nFirstChunk - 1; nIndexChunk++ )
{
pTrack->pChunk[nIndexChunk].nNumSamples = pTrack->pSampleToChunk[nIndexSTC].nSamplesPerChunk;
pTrack->unNumChunks++;
nSampleNum += pTrack->pChunk[nIndexChunk].nNumSamples;
}
}
long unNumChunksOld = pTrack->unNumChunks;
pTrack->unNumChunks += (int)( pTrack->unNumSamples - nSampleNum ) / pTrack->pSampleToChunk[pTrack->nNumSamplesToChunk - 1].nSamplesPerChunk;
for ( unsigned int unIndex = pTrack->pSampleToChunk[pTrack->nNumSamplesToChunk - 1].nFirstChunk - 1; unIndex < pTrack->unNumChunks; unIndex++ )
{
pTrack->pChunk[unIndex].nNumSamples = pTrack->pSampleToChunk[pTrack->nNumSamplesToChunk - 1].nSamplesPerChunk;
}
Mj2_Chunk* pChunk_new = (Mj2_Chunk*)Malloc(0, pTrack->unNumChunks * sizeof(Mj2_Chunk));
if (pChunk_new)
{
memcpy(pChunk_new,pTrack->pChunk,unNumChunksOld * sizeof(Mj2_Chunk));
RELEASEHEAP(pTrack->pChunk);
pTrack->pChunk = pChunk_new;
}
else
{
}
}
}
static void Mj2_DecompatSTCO (Mj2_TrackParams* pTrack)
{
for ( unsigned int unChunk = 0; unChunk < pTrack->unNumChunks; unChunk++ )
{
int nIntraChunkOffset = 0;
int nSample2 = 0;
for ( int nSample = 0; nSample < pTrack->pChunk[unChunk].nNumSamples; nSample++ )
{
pTrack->pSample[nSample2].unOffset = nIntraChunkOffset + pTrack->pChunk[unChunk].nOffset;
nIntraChunkOffset += pTrack->pSample[nSample2].unSampleSize;
nSample2++;
}
}
}
static bool Mj2_ReadSTTS (Mj2_TrackParams* pTrack, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_STTS != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected STTS Marker\n" );
return false;
}
if ( 0 != pStream->Read( 1 ) ) // Version
{
Event_Message( EVT_ERROR, "Error: Only Version 0 handled in STTS box\n" );
return false;
}
if ( 0 != pStream->Read( 3 ) ) // Flags = 0
{
Event_Message( EVT_ERROR, "Error with flag in STTS box. Expected flag 0\n" );
return false;
}
pTrack->nNumTimeToSample = pStream->Read( 4 ); // entry-count
pTrack->pTimeToSample = (Mj2_TimeToSample*)Malloc(0, pTrack->nNumTimeToSample * sizeof(Mj2_TimeToSample) );
for ( int nIndex = 0; nIndex < pTrack->nNumTimeToSample; nIndex++ )
{
pTrack->pTimeToSample[nIndex].nSampleCount = pStream->Read( 4 ); // sample-count
pTrack->pTimeToSample[nIndex].nSampleDelta = pStream->Read( 4 ); // sample-delta
}
Mj2_DecompatTTS( pTrack );
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with STTS Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadSTSZ (Mj2_TrackParams* pTrack, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_STSZ != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected STSZ Marker\n" );
return false;
}
if ( 0 != pStream->Read( 1 ) ) // Version = 0
{
Event_Message( EVT_ERROR, "Error: Only Version 0 handled in STSZ box\n ");
return false;
}
if ( 0 != pStream->Read( 3 ) ) // Flags = 0
{
Event_Message( EVT_ERROR, "Error with flag in STSZ box. Expected flag 0\n ");
return false;
}
int nSampleSize = pStream->Read( 4 ); // SampleSize
if ( 0 != nSampleSize ) // Ó âñåõ ñàìïëîâ îäèíàêîâûé ðàçìåð
{
pTrack->unSameSampleSize = 1;
for ( unsigned int unIndex = 0; unIndex < pTrack->unNumSamples; unIndex++ )
{
pTrack->pSample[unIndex].unSampleSize = nSampleSize;
}
pStream->Skip( 4 ); // sample-count
}
else
{
pTrack->unSameSampleSize = 0;
if ( pTrack->unNumSamples != pStream->Read( 4) ) // sample-count
{
Event_Message( EVT_ERROR, "Error in STSZ box. Expected that sample-count is number of samples in track\n ");
return false;
}
for ( unsigned int unIndex = 0; unIndex < pTrack->unNumSamples; unIndex++ )
{
pTrack->pSample[unIndex].unSampleSize = pStream->Read( 4 ); // entry-size
}
}
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with STSZ Box size\n ");
return false;
}
return true;
}
static bool Mj2_ReadSTSC (Mj2_TrackParams* pTrack, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_STSC != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected STSC Marker\n" );
return false;
}
if ( 0 != pStream->Read( 1 ) ) // Version = 0
{
Event_Message( EVT_ERROR, "Error: Only Version 0 handled in STSC box\n" );
return false;
}
if ( 0 != pStream->Read( 3 ) ) // Flags = 0
{
Event_Message( EVT_ERROR, "Error with flag in STSC box. Expected flag 0\n" );
return false;
}
pTrack->nNumSamplesToChunk = pStream->Read( 4 ); // entry-count
pTrack->pSampleToChunk = (Mj2_SampleToChunk*)Malloc(0, pTrack->nNumSamplesToChunk * sizeof(Mj2_SampleToChunk) );
for ( int nIndex = 0; nIndex < pTrack->nNumSamplesToChunk; nIndex++ )
{
pTrack->pSampleToChunk[nIndex].nFirstChunk = pStream->Read( 4 ); // first-chunk
pTrack->pSampleToChunk[nIndex].nSamplesPerChunk = pStream->Read( 4 ); // samples-per-chunk
pTrack->pSampleToChunk[nIndex].nSampleDescriptionIndex = pStream->Read( 4 ); // sample-description-index
}
Mj2_DecompatSTSC( pTrack ); // decompact sample to chunk box
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with STSC Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadSTCO (Mj2_TrackParams* pTrack, CReader * pStream)
{
// TO DO: Ñäåëàòü ÷òåíèå 'co64'
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_STCO != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected STCO Marker\n" );
return false;
}
if ( 0 != pStream->Read( 1 ) ) // Version = 0
{
Event_Message( EVT_ERROR, "Error: Only Version 0 handled in STCO box\n" );
return false;
}
if ( 0 != pStream->Read( 3 ) ) // Flags = 0
{
Event_Message( EVT_ERROR, "Error with flag in STCO box. Expected flag 0\n" );
return false;
}
if ( pStream->Read( 4) != pTrack->unNumChunks ) // entry-count
{
Event_Message( EVT_ERROR, "Error in STCO box: expecting same amount of entry-count as chunks \n" );
return false;
}
else
{
for ( unsigned int unIndex = 0; unIndex < pTrack->unNumChunks; unIndex++ )
{
pTrack->pChunk[unIndex].nOffset = pStream->Read( 4 ); // chunk-offset
}
}
Mj2_DecompatSTCO( pTrack );
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with STCO Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadFIEL (Mj2_TrackParams* pTrack, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_FIEL != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected FIEL Marker\n" );
return false;
}
pTrack->unFieldCount = pStream->Read( 1 );
pTrack->unFieldOrder = pStream->Read( 1 );
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with FIEL Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadJP2P (Mj2_TrackParams* pTrack, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_JP2P != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected JP2P Marker\n" );
return false;
}
if ( 0 != pStream->Read( 1 ) ) // Version = 0
{
Event_Message( EVT_ERROR, "Error: Only Version 0 handled in JP2P box\n" );
return false;
}
if ( 0 != pStream->Read( 3 ) ) // Flags = 0
{
Event_Message( EVT_ERROR, "Error with flag in JP2P box. Expected flag 0\n");
return false;
}
pTrack->nNumBr = (oBox.nLength - 12) / 4;
pTrack->pBr = (unsigned int*)Malloc(0, pTrack->nNumBr * sizeof(unsigned int) );
for ( int nIndex = 0; nIndex < pTrack->nNumBr; nIndex++ )
{
pTrack->pBr[nIndex] = pStream->Read( 4 );
}
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with JP2P Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadJP2X (Mj2_TrackParams* pTrack, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_JP2X != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected JP2X Marker\n" );
return false;
}
pTrack->unNumJp2x = ( oBox.nLength - 8 );
pTrack->pJp2xData = (unsigned char*)Malloc(0,pTrack->unNumJp2x * sizeof(unsigned char) );
for (unsigned int unIndex = 0; unIndex < pTrack->unNumJp2x; unIndex++ )
{
pTrack->pJp2xData[unIndex] = pStream->Read( 1 );
}
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with JP2X Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadJSUB (Mj2_TrackParams* pTrack, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_JSUB != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected JSUB Marker\n" );
return false;
}
pTrack->unHsub = pStream->Read( 1 );
pTrack->unVsub = pStream->Read( 1 );
pTrack->unHoff = pStream->Read( 1 );
pTrack->unVoff = pStream->Read( 1 );
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with JSUB Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadORFO (Mj2_TrackParams* pTrack, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_ORFO != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected ORFO Marker\n" );
return false;
}
pTrack->unOr_FieldCount = pStream->Read( 1 );
pTrack->unOr_FieldOrder = pStream->Read( 1 );
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with ORFO Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadSMJ2 (Mj2_TrackParams* pTrack, Image* pImage, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_MJ2 != oBox.nType )
{
Event_Message( EVT_ERROR, "Error in SMJ2 box: Expected MJ2 Marker\n" );
return false;
}
if ( 0 != pStream->Read( 1 ) ) // Version = 0
{
Event_Message( EVT_ERROR, "Error: Only Version 0 handled in MJP2 box\n" );
return false;
}
if ( 0 != pStream->Read( 3 ) ) // Flags = 0
{
Event_Message( EVT_ERROR, "Error with flag in MJP2 box. Expected flag 0\n" );
return false;
}
pStream->Skip( 4 );
pStream->Skip( 2 ); // Pre-defined
pStream->Skip( 2 ); // Reserved
pStream->Skip( 4 ); // Pre-defined
pStream->Skip( 4 ); // Pre-defined
pStream->Skip( 4 ); // Pre-defined
pTrack->nWidth = pStream->Read( 2 ); // Width
pTrack->nHeight = pStream->Read( 2 ); // Height
pTrack->nHorResolution = pStream->Read( 4 ); // Horizontal resolution
pTrack->nVerResolution = pStream->Read( 4 ); // Vertical resolution
pStream->Skip( 4 ); // Reserved
pStream->Skip( 2 ); // Pre-defined = 1
pTrack->anCompressorName[0] = pStream->Read( 4 ); // Compressor Name
pTrack->anCompressorName[1] = pStream->Read( 4 ); //
pTrack->anCompressorName[2] = pStream->Read( 4 ); //
pTrack->anCompressorName[3] = pStream->Read( 4 ); //
pTrack->anCompressorName[4] = pStream->Read( 4 ); //
pTrack->anCompressorName[5] = pStream->Read( 4 ); //
pTrack->anCompressorName[6] = pStream->Read( 4 ); //
pTrack->anCompressorName[7] = pStream->Read( 4 ); //
pTrack->nDepth = pStream->Read( 2 ); // Depth
pStream->Skip( 2 ); // Pre-defined = -1
pTrack->unNumJp2x = 0;
pTrack->unFieldCount = 1;
pTrack->unFieldOrder = 0;
pTrack->unOr_FieldCount = 1;
pTrack->unOr_FieldOrder = 0;
if ( !Jp2_ReadJP2H( &pTrack->oJp2, pStream ) )
{
Event_Message(EVT_ERROR, "Error reading JP2H Box\n" );
return false;
}
pTrack->oJp2.pComponents = (Jp2Component*) Malloc(HEAP_ZERO_MEMORY, pTrack->oJp2.nComponentsCount * sizeof(Jp2Component) );
pTrack->oJp2.pCompList = (unsigned int*) Malloc(0,sizeof(unsigned int) );
pTrack->nNumBr = 0;
pTrack->unNumJp2x = 0;
for ( int nIndex = 0; pStream->Tell() - oBox.nInitPos < oBox.nLength; nIndex++ )
{
Mj2_Box oBox2;
Mj2_ReadBoxHeader( &oBox2, pStream );
pStream->Seek( oBox2.nInitPos );
switch ( oBox2.nType )
{
case MJ2_FIEL:
if ( !Mj2_ReadFIEL( pTrack, pStream ) )
return false;
break;
case MJ2_JP2P:
if ( !Mj2_ReadJP2P( pTrack, pStream ) )
return false;
break;
case MJ2_JP2X:
if ( !Mj2_ReadJP2X( pTrack, pStream ) )
return false;
break;
case MJ2_JSUB:
if ( !Mj2_ReadJSUB( pTrack, pStream ) )
return false;
break;
case MJ2_ORFO:
if ( !Mj2_ReadORFO( pTrack, pStream ) )
return false;
break;
default:
Event_Message( EVT_ERROR, "Error with MJP2 Box size\n" );
return false;
}
}
return true;
}
static bool Mj2_ReadSTSD (Mj2_TrackParams* pTrack, Image* pImage, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_STSD != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected STSD Marker\n" );
return false;
}
if ( 0 != pStream->Read( 1 ) ) // Version = 0
{
Event_Message( EVT_ERROR, "Error: Only Version 0 handled in STSD box\n" );
return false;
}
if ( 0 != pStream->Read( 3 ) ) // Flags = 0
{
Event_Message( EVT_ERROR, "Error with flag in STSD box. Expected flag 0\n" );
return false;
}
int nEntryCount = pStream->Read( 4 );
if ( 0 == pTrack->nTrackType )
{
for ( int nIndex = 0; nIndex < nEntryCount; nIndex++ )
{
if ( !Mj2_ReadSMJ2( pTrack, pImage, pStream ) )
return false;
}
}
else if ( 1 == pTrack->nTrackType )
{
// TO DO: Ðåëèçîâàòü
int nSkipLen = pStream->Read( 4 );
pStream->Skip( nSkipLen - 4 );
}
else if ( 2 == pTrack->nTrackType )
{
// TO DO: Ðåàëèçîâàòü
int nSkipLen = pStream->Read( 4 );
pStream->Skip( nSkipLen - 4 );
}
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with STSD Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadSTBL (Mj2_TrackParams* pTrack, Image* pImage, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_STBL != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected STBL Marker\n" );
return false;
}
if ( !Mj2_ReadSTSD( pTrack, pImage, pStream ) )
return false;
if ( !Mj2_ReadSTTS( pTrack, pStream ) )
return false;
if ( !Mj2_ReadSTSC( pTrack, pStream ) )
return false;
if ( !Mj2_ReadSTSZ( pTrack, pStream ) )
return false;
if ( !Mj2_ReadSTCO( pTrack, pStream ) )
return false;
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with STBL Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadMINF (Mj2_TrackParams* pTrack, Image* pImage, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_MINF != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected MINF Marker\n" );
return false;
}
pStream->Skip(4 );
unsigned int unBoxType = pStream->Read( 4 );
pStream->Skip( -8 );
if ( MJ2_VMHD == unBoxType )
{
if ( !Mj2_ReadVMHD( pTrack, pStream ) )
return false;
}
else if ( MJ2_SMHD == unBoxType )
{
if ( !Mj2_ReadSMHD( pTrack, pStream ) )
return false;
}
else if ( MJ2_HMHD == unBoxType )
{
if ( !Mj2_ReadHMHD( pTrack, pStream ) )
return false;
}
else
{
Event_Message( EVT_ERROR, "Error in MINF box expected vmhd, smhd or hmhd\n" );
return false;
}
if ( !Mj2_ReadDINF( pTrack, pStream ) )
return false;
if ( !Mj2_ReadSTBL( pTrack, pImage, pStream ) )
return false;
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with MINF Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadMDIA (Mj2_TrackParams* pTrack, Image* pImage, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_MDIA != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected MDIA Marker\n" );
return false;
}
if ( !Mj2_ReadMDHD( pTrack, pStream ) )
return false;
if ( !Mj2_ReadHDLR( pTrack, pStream ) )
return false;
if ( !Mj2_ReadMINF( pTrack, pImage, pStream ) )
return false;
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with MDIA Box size\n" );
return false;
}
return true;
}
static bool Mj2_ReadTRAK (Mj2_TrackParams* pTrack, Image* pImage, CReader * pStream)
{
Mj2_Box oBox;
Mj2_ReadBoxHeader( &oBox, pStream );
if ( MJ2_TRAK != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected TRAK Marker\n" );
return false;
}
if ( !Mj2_ReadTKHD( pTrack, pStream ) )
return false;
if ( !Mj2_ReadMDIA( pTrack, pImage, pStream ) )
return false;
if ( pStream->Tell() - oBox.nInitPos != oBox.nLength )
{
Event_Message( EVT_ERROR, "Error with TRAK Box\n" );
return false;
}
return true;
}
static bool Mj2_ReadMOOV (Mj2_Movie* pMovie, CReader * pStream, Image* pImage, Mj2_Box oBox)
{
if ( MJ2_MOOV != oBox.nType )
{
Event_Message( EVT_ERROR, "Error: Expected FTYP Marker\n" );
return false;
}
if ( !Mj2_ReadMVHD( pMovie, pStream ) )
return false;
pMovie->pTrack = (Mj2_TrackParams*)Malloc(HEAP_ZERO_MEMORY, ( pMovie->nNextTrackId - 1 ) * sizeof(Mj2_TrackParams) );
Mj2_Box oBox2;
for ( unsigned int unIndex = 0; pStream->Tell() - oBox.nInitPos < oBox.nLength; unIndex++ )
{
Mj2_TrackParams* pTrack = &pMovie->pTrack[unIndex];
pTrack->pCodecInfo = pMovie->pCodecInfo;
Mj2_ReadBoxHeader( &oBox2, pStream );
if ( MJ2_TRAK == oBox2.nType )
{
pStream->Seek( oBox2.nInitPos );
if ( !Mj2_ReadTRAK( pTrack, pImage, pStream ) )
return false;
if ( 0 == pTrack->nTrackType )
pMovie->nNumVtk++;
else if ( 1 == pTrack->nTrackType )
pMovie->nNumStk++;
else if ( 2 == pTrack->nTrackType )
pMovie->nNumHtk++;
}
else if ( MJ2_MVEX == oBox2.nType )
{
pStream->Seek( oBox2.nInitPos );
pStream->Skip( oBox2.nLength );
unIndex--;
}
else
{
Event_Message( EVT_ERROR, "Error with MOOV Box: Expected TRAK or MVEX box\n" );
return false;
}
}
return true;
}
static bool Mj2_ReadStruct (Mj2_Movie* pMovie, CReader * pStream, Image **ppImage)
{
if ( !Mj2_ReadJP( pStream ) )
return false;
if ( !Mj2_ReadFTYP( pMovie, pStream ) )
return false;
Mj2_Box oBox;
oBox.nType = 0;
Mj2_ReadBoxHeader( &oBox, pStream );
while( MJ2_MOOV != oBox.nType )
{
switch( oBox.nType )
{
case MJ2_MDAT:
// TO DO: Ñâÿçàòü äàííûå â MDAT ñ äàííûìè MOOV
if ( !Mj2_ReadMDAT( pMovie, pStream, ppImage, oBox ) )
return false;
break;
case MJ2_MOOF:
case MJ2_FREE:
case MJ2_SKIP:
pStream->Skip( oBox.nLength );
if ( pStream->GetLeftSize() < 0 )
return false;
break;
default:
Event_Message( EVT_ERROR, "Unknown box in MJ2 stream\n" );
pStream->Skip( oBox.nLength );
if ( pStream->GetLeftSize() < 0 )
return false;
break;
}
if ( !Mj2_ReadBoxHeader( &oBox, pStream ) )
return false;
}
Image oImage;
if ( !Mj2_ReadMOOV( pMovie, pStream, &oImage, oBox ) )
return false;
return true;
}
//-------------------------------------------------------------------------------------------------------------------------------
// Äåêîäèðîâàíèå ïîòîêà Mj2
//-------------------------------------------------------------------------------------------------------------------------------
void Mj2_DestroyDecompress(Mj2_Movie* pMovie)
{
if( pMovie )
{
Mj2_TrackParams* pTrack = NULL;
if ( pMovie->pCodecInfo->pJ2k )
J2k_DestroyCompress( pMovie->pJ2k );
//if ( pMovie->nCompListLength != 0 )
RELEASEHEAP( pMovie->pCompList );
for ( int nIndex = 0; nIndex < pMovie->nNumVtk + pMovie->nNumStk + pMovie->nNumHtk; nIndex++ )
{
pTrack = &pMovie->pTrack[nIndex];
//if ( pTrack->nNameSize != 0 )
RELEASEHEAP( pTrack->sName );
if ( pTrack->nTrackType == 0 )
{
RELEASEHEAP( pTrack->oJp2.pComponents );
RELEASEHEAP( pTrack->oJp2.pCompList );
RELEASEHEAP( pTrack->pJp2xData );
}
//if ( pTrack->nNumUrl != 0 )
RELEASEHEAP( pTrack->pUrl );
//if ( pTrack->nNumUrn != 0 )
RELEASEHEAP( pTrack->pUrn );
//if ( pTrack->nNumBr != 0 )
RELEASEHEAP( pTrack->pBr );
//if ( pTrack->nNumTimeToSample != 0 )
RELEASEHEAP( pTrack->pTimeToSample );
//if ( pTrack->unNumChunks != 0 )
RELEASEHEAP( pTrack->pChunk );
//if ( pTrack->nNumSamplesToChunk != 0 )
RELEASEHEAP( pTrack->pSampleToChunk );
//if ( pTrack->unNumSamples != 0 )
RELEASEHEAP( pTrack->pSample );
RELEASEHEAP( pTrack );
}
RELEASEHEAP( pMovie );
}
}
Mj2_Movie* Mj2_CreateDecompress (PCommon pCodecInfo)
{
Mj2_Movie* pMj2 = (Mj2_Movie*)Malloc(HEAP_ZERO_MEMORY, sizeof(Mj2_Movie) );
if( pMj2 )
{
pMj2->pCodecInfo = (PCommon)pCodecInfo;
pMj2->pJ2k = J2k_CreateDecompress( pCodecInfo );
if ( NULL == pMj2->pJ2k )
{
pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
Mj2_DestroyDecompress( pMj2 );
return NULL;
}
}
else
{
pCodecInfo->nErrorCode = JP2_ERROR_NOT_ENOUGH_MEMORY;
}
return pMj2;
}
void Mj2_SetupDecoder (Mj2_Movie* pMovie, DecoderParams *pParameters)
{
pMovie->nNumVtk = 0;
pMovie->nNumStk = 0;
pMovie->nNumHtk = 0;
J2k_SetupDecoder( (J2kCodestream*)pMovie->pCodecInfo->pJ2k, pParameters);
}
Image* Mj2_Decode (Mj2_Movie* pMovie, CReader * pStream)
{
if( !pMovie || !pStream )
{
return NULL;
}
PCommon pCodecInfo = pMovie->pCodecInfo;
Image *pImage = NULL;
// Äåêîäèðóåì JP2
if( !Mj2_ReadStruct( pMovie, pStream, &pImage ) )
{
Event_Message( EVT_ERROR, "Failed to decode jp2 structure\n" );
return NULL;
}
return pImage;
}