mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-20 03:55:47 +08:00
1541 lines
40 KiB
C
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;
|
|
}
|