blob: 1e281043407be34601b85373e9b09e9e816d0cca [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.
* -------------------------------------------------------------------
*/
///////////////////////////////////////////////////////////////////////////////
//
// RFC3640_payload_parser.cpp
//
// Implementation of payload parser for RFC3640 RTP format.
//
///////////////////////////////////////////////////////////////////////////////
#include "oscl_mem.h"
#include "rfc3640_payload_parser.h"
#include "bitstreamparser.h"
#include "oscl_byte_order.h"
#include "rfc3640_media_info.h"
//Until the fileformat node and decoder are re-worked to handle multiple-fragments
//per media message, we'll need to use this switch to control the output of the
//payload parser
#define RFC3640_ONE_FRAGMENT_PER_MEDIA_MSG 1
//Default Values
#define AAC_HBR_SIZELENGTH_DEFAULT_VALUE 13
#define AAC_HBR_INDEXLENGTH_DEFAULT_VALUE 3
#define AAC_HBR_INDEXDELTALENGTH_DEFAULT_VALUE 3
#define AAC_HBR_CTSDELTALENGTH_DEFAULT_VALUE 0
#define AAC_HBR_DTSDELTALENGTH_DEFAULT_VALUE 0
#define AAC_HBR_HEADERSLENGTH_DEFAULT_VALUE 16
#define AAC_HBR_AUXDATASIZELENGTH_DEFAULT_VALUE 0
///////////////////////////////////////////////////////////////////////////////
//
// Constructor/Destructor
//
///////////////////////////////////////////////////////////////////////////////
OSCL_EXPORT_REF RFC3640PayloadParser::RFC3640PayloadParser()
{
//Default to no headers at all.
//This is just in case Init() is never called.
headersPresent = false;
headersLength = 0;
sizeLength = 0;
indexLength = 0;
indexDeltaLength = 0;
CTSDeltaLength = 0;
DTSDeltaLength = 0;
randomAccessIndication = false;
auxDataSizeLength = 0;
}
OSCL_EXPORT_REF RFC3640PayloadParser::~RFC3640PayloadParser()
{
}
///////////////////////////////////////////////////////////////////////////////
//
// Initialization
//
///////////////////////////////////////////////////////////////////////////////
OSCL_EXPORT_REF bool RFC3640PayloadParser::Init(mediaInfo* config)
{
Oscl_Vector<PayloadSpecificInfoTypeBase*, OsclMemAllocator> payloadInfo;
payloadInfo = config->getPayloadSpecificInfoVector();
PayloadSpecificInfoTypeBase* payloadInfoBase = payloadInfo[0]; // is this "0" assumption okay???
RFC3640PayloadSpecificInfoType* r3640PayloadInfo =
OSCL_STATIC_CAST(RFC3640PayloadSpecificInfoType*, payloadInfoBase);
rfc3640_mediaInfo *r3640m = OSCL_STATIC_CAST(rfc3640_mediaInfo *, config);
bool retVal = false;
//TODO: Implement other modes (such as CELP-cbr, CELP-vbr, AAC-lbr, etc...).
sizeLength = r3640PayloadInfo->getSizeLength();
indexLength = r3640PayloadInfo->getIndexLength();
indexDeltaLength = r3640PayloadInfo->getIndexDeltaLength();
CTSDeltaLength = r3640PayloadInfo->getCTSDeltaLength();
DTSDeltaLength = r3640PayloadInfo->getDTSDeltaLength();
randomAccessIndication = false;
//We support AAC-hbr mode only.
if (!oscl_strncmp(r3640m->getMode(), "AAC-hbr", oscl_strlen("AAC-hbr")))
{
headersPresent = true;
headersLength = AAC_HBR_HEADERSLENGTH_DEFAULT_VALUE;
auxDataSizeLength = AAC_HBR_AUXDATASIZELENGTH_DEFAULT_VALUE;
//do sanity check on values. Only supporting AAC_HBR default fixed values.
if ((sizeLength != AAC_HBR_SIZELENGTH_DEFAULT_VALUE) ||
(indexLength != AAC_HBR_INDEXLENGTH_DEFAULT_VALUE) ||
(indexDeltaLength != AAC_HBR_INDEXDELTALENGTH_DEFAULT_VALUE))
{
retVal = true;
}
}
else
{
retVal = true;
}
return retVal;
}
///////////////////////////////////////////////////////////////////////////////
//
// Payload parsing
//
///////////////////////////////////////////////////////////////////////////////
OSCL_EXPORT_REF PayloadParserStatus
RFC3640PayloadParser::Parse(const Payload& inputPacket,
Oscl_Vector<Payload, OsclMemAllocator>& vParsedPayloads)
{
// Many of OsclRefCounterMemFrag's member functions
//should be const functions so this casting away constness is not necessary.
Payload& input = const_cast<Payload&>(inputPacket);
//@TODO: Implement AU de-interleaving
Payload out;
out.stream = inputPacket.stream;
out.marker = inputPacket.marker;
out.randAccessPt = inputPacket.randAccessPt;
out.sequence = inputPacket.sequence + 1;
out.timestamp = inputPacket.timestamp;
//Creating a boolean for checking whether RFC3640_ONE_FRAGMENT_PER_MEDIA_MSG is defined or not
bool rfc3640_one_fragement_per_media = false;
#ifndef RFC3640_ONE_FRAGMENT_PER_MEDIA_MSG
rfc3640_one_fragement_per_media = true;
#endif
// Many functions calls inside this for loop may Leave because of an
// overflow.
int32 err;
OSCL_TRY(err,
//Loop through all of the packets.
for (uint32 fragmentNumber = 0; fragmentNumber < inputPacket.vfragments.size(); fragmentNumber++)
{
//
// Strip RFC 3640 header section and auxiliary section.
//
//Establish a pointer to the payload fragment for iterating past the
//header and aux section.
BitStreamParser fragment((uint8*)input.vfragments[fragmentNumber].getMemFragPtr(),
input.vfragments[fragmentNumber].getMemFragSize());
//In some cases, such as with fixed-length AUs, the header is not present.
//Only process the header if it is present.
uint16 headersLength = 0;
if (headersPresent)
{
//Read the header length from the first 2 octets.
//Include the size of this headersLength field in the total length.
headersLength = fragment.ReadUInt16() + BITS_PER_UINT16;
}
uint8 accessUnits = 0; //controls index field interpretation (index or delta)
uint32 size = 0; //size of the AU
uint32 index = 0; //used for interleaving
uint32 indexDelta = 0; //used for interleaving
int CTSFlag = 0; //composition time stamp
uint32 CTSDelta = 0; //composition time stamp
int DTSFlag = 0; //decoding time stamp
uint32 DTSDelta = 0; //decoding time stamp
int RAPFlag = 0; //random access point - used to mark a key frame
uint32 auxDataSize = 0;
//Loop through all of the access units in the packet.
while (fragment.BitsRead() < headersLength)
{
//If the header is present, parse it.
if (headersLength)
{
if (0 != sizeLength)
{
//Read the AU Size field.
size = fragment.ReadBits(sizeLength);
}
//If the index field is present...
if (0 != indexLength)
{
//If this is the first access unit header...
if (0 == accessUnits)
{
//The AU index only occurs in the first header.
index = fragment.ReadBits(indexLength);
}
else
{
indexDelta = fragment.ReadBits(indexDeltaLength);
}
}
//From RFC3640: "The CTS-flag field MUST be present in each AU-header
// if the length of the CTS-delta field is signaled to
// be larger than zero."
if (0 != CTSDeltaLength)
{
CTSFlag = fragment.ReadBits(1);
if (CTSFlag)
{
CTSDelta = fragment.ReadBits(CTSDeltaLength);
}
}
if (0 != DTSDeltaLength)
{
DTSFlag = fragment.ReadBits(1);
if (DTSFlag)
{
DTSDelta = fragment.ReadBits(DTSDeltaLength);
}
}
if (randomAccessIndication)
{
RAPFlag = fragment.ReadBits(1);
}
}
if (rfc3640_one_fragement_per_media == true)
{
// At this time the decoder cannot handle multiple fragments.
OsclMemoryFragment memfrag;
//memfrag.ptr = NULL; //Unknown at this time.
memfrag.len = size;
input.vfragments[fragmentNumber].getRefCounter()->addRef();
OsclRefCounterMemFrag refCntMemFrag(memfrag,
input.vfragments[fragmentNumber].getRefCounter(),
memfrag.len);
out.vfragments.push_back(refCntMemFrag);
}
else
{
// Instead of creating multiple fragments, point to the first fragment, but
// increment the size field to span all access units. The decoder is still
// getting multiple frames in memory, but the data structure makes it appear as just one.
// This only works for non-interleaved access units & can only be a temporary solution
if (accessUnits == 0)
{
OsclMemoryFragment memfrag;
memfrag.ptr = (uint8*)(input.vfragments[fragmentNumber].getMemFragPtr()) + (headersLength / 8);
memfrag.len = input.vfragments[fragmentNumber].getMemFragSize() - (headersLength / 8);
input.vfragments[fragmentNumber].getRefCounter()->addRef();
OsclRefCounterMemFrag refCntMemFrag(memfrag,
input.vfragments[fragmentNumber].getRefCounter(),
memfrag.len);
out.vfragments.push_back(refCntMemFrag);
}
}
accessUnits++;
}
//Processed the header. Skip past any padding.
if (fragment.GetBitPos() != MOST_SIG_BIT)
{
fragment.NextBits(fragment.GetBitPos() + 1);
}
//Now skip over the aux data region.
if (auxDataSizeLength)
{
auxDataSize = fragment.ReadBits(auxDataSizeLength);
if (auxDataSize)
{
//Skip over the aux data region.
fragment.NextBits(auxDataSize);
//Skip past any padding.
if (fragment.GetBitPos() != MOST_SIG_BIT)
{
fragment.NextBits(fragment.GetBitPos() + 1);
}
}
}
if (rfc3640_one_fragement_per_media == true)
{
//Update the fragment pointers with real values now that we have
//parsed the headers.
//The output vector may contain fragments from previous runs, so
//start with the last fragments that we pushed on the back of the vector.
for (uint32 i = (out.vfragments.size() - accessUnits); i < out.vfragments.size(); i++)
{
out.vfragments[i].getMemFrag().ptr = fragment.GetBytePos();
fragment.NextBits(out.vfragments[i].getMemFrag().len * BITS_PER_BYTE);
}
}
}
); // End of OSCL_TRY
if (err != OsclErrNone)
{
return PayloadParserStatus_Failure;
}
vParsedPayloads.push_back(out);
return PayloadParserStatus_Success;
}
///////////////////////////////////////////////////////////////////////////////
//
// Repositioning related
//
///////////////////////////////////////////////////////////////////////////////
OSCL_EXPORT_REF void RFC3640PayloadParser::Reposition(const bool adjustSequence, const uint32 stream, const uint32 seqnum)
{
OSCL_UNUSED_ARG(adjustSequence);
OSCL_UNUSED_ARG(stream);
OSCL_UNUSED_ARG(seqnum);
}
OSCL_EXPORT_REF uint32 RFC3640PayloadParser::GetMinCurrTimestamp()
{
return 0;
}