blob: 075668caaf75ccdb5c554bfa134a8066fb04635a [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
* -------------------------------------------------------------------
*/
#define IMPLEMENT_AVCSampleEntry
#include "avcsampleentry.h"
#include "atomutils.h"
#include "atomdefs.h"
AVCSampleEntry::AVCSampleEntry(MP4_FF_FILE *fp, uint32 size, uint32 type)
: Atom(fp, size, type)
{
_mp4ErrorCode = READ_AVC_SAMPLE_ENTRY_FAILED;
uint32 count = _size - DEFAULT_ATOM_SIZE;
_pAVCConfigurationBox = NULL;
_pMPEG4BitRateBox = NULL;
_decoderSpecificInfo = NULL;
_pPASPBox = NULL ; //PASP box
if (_success)
{
_success = false;
uint16 data16;
uint32 data32;
_pparent = NULL;
// Read reserved values
if (!AtomUtils::readByteData(fp, 6, _reserved))
{
return;
}
count -= 6;
if (!AtomUtils::read16(fp, _dataReferenceIndex))
{
return;
}
count -= 2;
if (!AtomUtils::read16(fp, data16))
{
return;
}
_preDefined1 = (int16)data16;
count -= 2;
if (!AtomUtils::read16(fp, data16))
{
return;
}
_reserved1 = (int16)data16;
count -= 2;
// Read in all reserved members
for (int32 i = 0; i < 3; i++)
{
if (!AtomUtils::read32(fp, data32))
{
return;
}
_predefined2[i] = (int32)data32;
count -= 4;
}
if (!AtomUtils::read16(fp, data16))
{
return;
}
_width = (int16)data16;
count -= 2;
if (!AtomUtils::read16(fp, data16))
{
return;
}
_height = (int16)data16;
count -= 2;
if (!AtomUtils::read32(fp, data32))
{
return;
}
_horizResolution = (int32)data32;
count -= 4;
if (!AtomUtils::read32(fp, data32))
{
return;
}
_vertResolution = (int32)data32;
count -= 4;
if (!AtomUtils::read32(fp, data32))
{
return;
}
_reserved2 = (int32)data32;
count -= 4;
if (!AtomUtils::read16(fp, data16))
{
return;
}
_preDefined2 = (int16)data16;
count -= 2;
if (!AtomUtils::readByteData(fp, 32, _compressorName))
{
return;
}
count -= 32;
if (!AtomUtils::read16(fp, data16))
{
return;
}
_depth = (int16)data16;
count -= 2;
if (!AtomUtils::read16(fp, data16))
{
return;
}
_predefined3 = (int16)data16;
count -= 2;
while (count > 0)
{
uint32 atomType = UNKNOWN_ATOM;
uint32 atomSize = 0;
AtomUtils::getNextAtomType(fp, atomSize, atomType);
if (atomType == AVC_CONFIGURATION_BOX)
{
PV_MP4_FF_NEW(fp->auditCB, AVCConfigurationBox, (fp, atomSize, atomType), _pAVCConfigurationBox);
if (!_pAVCConfigurationBox->MP4Success())
{
_mp4ErrorCode = READ_AVC_CONFIG_BOX_FAILED;
return;
}
count -= atomSize;
}
else if (atomType == MPEG4_BITRATE_BOX)
{
PV_MP4_FF_NEW(fp->auditCB, MPEG4BitRateBox, (fp, atomSize, atomType), _pMPEG4BitRateBox);
if (!_pMPEG4BitRateBox->MP4Success())
{
_mp4ErrorCode = READ_MPEG4_BITRATE_BOX_FAILED;
return;
}
count -= atomSize;
}
else if (atomType == PIXELASPECTRATIO_BOX) //PASP Box
{
PV_MP4_FF_NEW(fp->auditCB, PASPBox, (fp, atomSize, atomType), _pPASPBox);
if (!_pPASPBox->MP4Success())
{
_mp4ErrorCode = READ_PIXELASPECTRATIO_BOX_FAILED;
return;
}
count -= atomSize;
}
else
{
if (atomSize < DEFAULT_ATOM_SIZE)
{
_mp4ErrorCode = ZERO_OR_NEGATIVE_ATOM_SIZE;
return;
}
if (count < (uint32)atomSize)
{
_mp4ErrorCode = READ_FAILED;
break;
}
count -= atomSize;
atomSize -= DEFAULT_ATOM_SIZE;
AtomUtils::seekFromCurrPos(fp, atomSize);
}
}
if (createDecoderSpecificInfo(fp))
{
_success = true;
_mp4ErrorCode = EVERYTHING_FINE;
}
}
}
// Destructor
AVCSampleEntry::~AVCSampleEntry()
{
if (_pAVCConfigurationBox != NULL)
{
PV_MP4_FF_DELETE(NULL, AVCConfigurationBox, _pAVCConfigurationBox);
}
if (_pMPEG4BitRateBox != NULL)
{
PV_MP4_FF_DELETE(NULL, MPEG4BitRateBox, _pMPEG4BitRateBox);
}
if (_pPASPBox != NULL)
{
PV_MP4_FF_DELETE(NULL, PASPBox, _pPASPBox);
}
if (_decoderSpecificInfo != NULL)
{
PV_MP4_FF_DELETE(NULL, DecoderSpecificInfo, _decoderSpecificInfo);
}
}
bool
AVCSampleEntry::createDecoderSpecificInfo(MP4_FF_FILE *fp)
{
uint32 numSPS = getNumSequenceParamSets();
uint32 numPPS = getNumPictureParamSets();
uint32 totalSPSLen = getTotalSeqParameterSetLength();
uint32 totalPPSLen = getTotalPictureParameterSetLength();
uint32 len = (numSPS * 2) + (numPPS * 2) + totalSPSLen + totalPPSLen;
if ((int32)len > 0)
{
PV_MP4_FF_NEW(fp->auditCB, DecoderSpecificInfo, (fp, true), _decoderSpecificInfo);
uint8* info = (uint8*)(oscl_malloc(sizeof(uint8) * len));
if (!info)
return false; // malloc failed (unlikely)
uint8* destPtr = info;
if (numSPS > 0)
{
for (uint32 i = 0; i < numSPS; i++)
{
uint16 len = 0;
uint8* ptr = NULL;
if (getSequenceParamSet(i, len, ptr) == false)
{
OSCL_FREE(info);
return false;
}
oscl_memcpy(destPtr, &len, sizeof(uint16));
destPtr += sizeof(uint16);
oscl_memcpy(destPtr, ptr, len);
destPtr += len;
}
}
if (numPPS > 0)
{
for (uint32 i = 0; i < numPPS; i++)
{
uint16 len = 0;
uint8* ptr = NULL;
if (getPictureParamSet(i, len, ptr) == false)
{
OSCL_FREE(info);
return false;
}
oscl_memcpy(destPtr, &len, sizeof(uint16));
destPtr += sizeof(uint16);
oscl_memcpy(destPtr, ptr, len);
destPtr += len;
}
}
_decoderSpecificInfo->setInfoSize(len);
_decoderSpecificInfo->setInfo(info);
}
return true;
}