videoeditorengine/audioeditorengine/codecs/AAC/src/ProcAACFrameHandler.cpp
author Mikael Laine <mikael.laine@ixonos.com>
Fri, 29 Jan 2010 14:08:33 +0200
changeset 0 951a5db380a0
permissions -rw-r--r--
Committing the Video Editor package under the Eclipse Public License

/*
* Copyright (c) 2010 Ixonos Plc.
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - Initial contribution
*
* Contributors:
* Ixonos Plc
*
* Description: 
*
*/




#include "ProcAACFrameHandler.h"
#include "ProcFrameHandler.h"
#include "ProcTools.h"
#include "nok_bits.h"
#include "AACAPI.h"

#include <f32file.h>
#include <e32math.h>


TBool CProcAACFrameHandler::ManipulateGainL(const HBufC8* aFrameIn, HBufC8*& aFrameOut, TInt8 aGain) 
    {

    if (aFrameIn == 0)
        return EFalse;

    
    TInt numBlocks = 1;
    TInt headerBytes = CalculateNumberOfHeaderBytes(aFrameIn, numBlocks);
    
    // Unfortunately const casting is needed to avoid unecessary temporary arrays
    // and we don't have a separate bitstream class for const objects
    // Just have to make very sure not to modify const descriptors!!
    TUint8* buf = const_cast<TUint8*>(aFrameIn->Right(aFrameIn->Size()-headerBytes).Ptr());
    
    uint8* gains = new (ELeave) uint8[16];
    uint32* gainPos = new (ELeave) uint32[16];

    TInt bufLen = aFrameIn->Size()-headerBytes;

    TBitStream bs;
    TBitStream bs2;
    
    BsInit(&bs, buf, bufLen);
    BsInit(&bs2, buf, bufLen);
    
    for (TInt b = 0 ; b < numBlocks ; b++)
        {
        
        TInt b_i = bs.buf_index;
        iFrameStarts.Append(b_i+headerBytes);

        BsSaveBufState(&bs, &bs2);

        uint8 numberOfGains = GetAACGlobalGains(&bs, iDecHandle, 16, gains, gainPos);
        
        if (numberOfGains > 2)
            {
            // illegal frame??
            delete[] gainPos;
            delete[] gains;
            return KErrGeneral;

            }

        if (bs.buf_index > 0)
            iFrameLengths.Append(bs.buf_index - b_i);
        else
            iFrameLengths.Append(bs.buf_len - b_i);
        
        if (headerBytes > 7)
            {
            bs.buf_index += 2; // crc
            bs.slots_read += 2;
            bs.bits_read += 16;

            }
                
        TInt tmpGain = aGain*500;
        int16 newGain = static_cast<int16>(tmpGain/1500);
        
        
        for (TInt a = 0 ; a < numberOfGains ; a++)
        {
            if (gains[a] + newGain > 255)
            {
                gains[a] = 255;
            }
            else if (gains[a] + newGain < 0)
            {
                gains[a] = 0;
            }
            else
            {
                gains[a] = static_cast<TUint8>(gains[a]+newGain);
            }
        }
        
    
        if (iAACInfo.isSBR || iAACInfo.iIsParametricStereo)
            {

            uint8 *data = new (ELeave) uint8[1024];
            CleanupStack::PushL(data);
            TBitStream bsOut;

            BsInit(&bsOut, data, 1024);

            SetAACPlusGlobalGains(&bs2, &bsOut, iDecHandle, static_cast<int16>(-newGain), numberOfGains, gains, gainPos);
            
            TInt incBytes = (bsOut.bits_read >> 3) - bs2.buf_len;
            iFrameLengths[iFrameLengths.Count()-1] +=incBytes; 
            
            TInt newSize = aFrameIn->Size()+incBytes;
            aFrameOut = HBufC8::NewL(newSize);
            aFrameOut->Des().Append(aFrameIn->Left(headerBytes));
            aFrameOut->Des().Append(bsOut.bit_buffer, bsOut.bits_read >> 3);
            
            if (headerBytes != 0) UpdateHeaderL(aFrameOut);
                
            CleanupStack::Pop(data);
            delete[] data;
            data = 0;
            
                
            }
        else
            {
            SetAACGlobalGains(&bs2, numberOfGains, gains, gainPos);
            aFrameOut = HBufC8::NewL(aFrameIn->Size());
            aFrameOut->Des().Copy(aFrameIn->Ptr(), aFrameIn->Size());
        
            }
            

            
        //    }

        }
    delete[] gains;
    delete[] gainPos;
    
    
    return ETrue;
    }

TBool CProcAACFrameHandler::GetGainL(const HBufC8* aFrame, RArray<TInt>& aGains, TInt& aMaxGain) const
    {

    
    TInt numBlocks = 1;
    TInt headerBytes = CalculateNumberOfHeaderBytes(aFrame, numBlocks);
    
    //TBitStream bs;
    TUint8* buf = const_cast<TUint8*>(aFrame->Right(aFrame->Size()-headerBytes).Ptr());
    //BsInit(&bs, buf, aFrame->Size()-headerBytes);

    uint8* gains = new (ELeave) uint8[16];
    CleanupStack::PushL(gains);
    uint32* gainPos = new (ELeave) uint32[16];
    CleanupStack::PushL(gainPos);

    //TPtr8 frameWithoutHeader = aFrame->Right(aFrame->Size()-headerBytes));
    TInt bufLen = aFrame->Size()-headerBytes;

    TBitStream bs;

    
    BsInit(&bs, buf, bufLen);
    
    
    for (TInt b = 0 ; b < numBlocks ; b++)
    {
                
        uint8 numberOfGains = GetAACGlobalGains(&bs, iDecHandle, 16, gains, gainPos);

        for (TInt a = 0 ; a < numberOfGains ; a++)
        {
            aGains.Append(gains[a]);
        }

        if (headerBytes > 7)
            {
            bs.buf_index += 2; // crc
            bs.slots_read += 2;
            bs.bits_read += 16;

            }
                
    }
    CleanupStack::Pop(); //(gainPos)
    CleanupStack::Pop(); //(gains)
    delete[] gains;
    delete[] gainPos;

    aMaxGain = 255;
    return EFalse;



    }


TBool CProcAACFrameHandler::GetNormalizingMargin(const HBufC8* aFrame, TInt8& aMargin) const

    {
        
    TUint8* buf = const_cast<TUint8*>(aFrame->Ptr());
    TInt bufLen = aFrame->Size();

    uint8* gains = new uint8[16];

    uint32* gainPos = new uint32[16];
    
    
    TBitStream bs;
    
    BsInit(&bs, buf, bufLen);

    uint8 numberOfGains = GetAACGlobalGains(&bs, iDecHandle, 16, gains, gainPos);

    TUint8 maxGain = 0;

    for (TInt a = 0 ; a < numberOfGains ; a++)
        {
        if (gains[a] > maxGain)
            {
            maxGain = gains[a];
            }
        }
    delete[] gains;
    delete[] gainPos;

    TInt marginInt = (255-maxGain)*6;

    if (marginInt > 127)
        {
        aMargin = 127;
        }
    else if (marginInt < 0)
        {
        aMargin = 0;
        }
    else
        {
        aMargin = static_cast<TInt8>(marginInt);
        }

    return ETrue;


    }

CProcAACFrameHandler::~CProcAACFrameHandler()
    {

    iFrameStarts.Reset();
    iFrameLengths.Reset();
    if (iDecHandle != 0)
        {
        
        DeleteAACAudDec(iDecHandle);
        }


    }

CProcAACFrameHandler* CProcAACFrameHandler::NewL(TAACFrameHandlerInfo aAACInfo) 
    {

    
    CProcAACFrameHandler* self = NewLC(aAACInfo);
    CleanupStack::Pop(self);
    return self;

    }
CProcAACFrameHandler* CProcAACFrameHandler::NewLC(TAACFrameHandlerInfo aAACInfo) 
    {

    CProcAACFrameHandler* self = new (ELeave) CProcAACFrameHandler();
    CleanupStack::PushL(self);
    self->ConstructL(aAACInfo);
    return self;

    }

void CProcAACFrameHandler::ConstructL(TAACFrameHandlerInfo aAACInfo) 
    {
    
    CreateAACAudDecL(iDecHandle, static_cast<TInt16>(aAACInfo.iNumChannels), 
                                static_cast<TInt16>(aAACInfo.iNumCouplingChannels));
    
    InitAACAudDec(iDecHandle, static_cast<TInt16>(aAACInfo.iProfileID), 
                                static_cast<TInt16>(aAACInfo.iSampleRateID), 
                                static_cast<TUint8>(aAACInfo.iIs960));
    
    if(aAACInfo.isSBR)
        {
        uint8 isStereo;
        
        isStereo = (aAACInfo.iNumChannels > 1) ? 1 : 0;
        
        CreateAACPlusAudDecL(iDecHandle, static_cast<TInt16>(aAACInfo.iSampleRateID), isStereo, (uint8) 0);
        }
    iAACInfo = aAACInfo;
    
}

CProcAACFrameHandler::CProcAACFrameHandler() : iDecHandle(0)
{
    
}

TInt CProcAACFrameHandler::CalculateNumberOfHeaderBytes(const HBufC8* aFrame, TInt& aNumBlocksInFrame) const
    {

    if (aFrame->Size() < 7) return 0;
    TBuf8<7> possibleHeader(aFrame->Left(7));

    TUint8 byte2 = possibleHeader[1];
    TBuf8<8> byte2b;
    ProcTools::Dec2Bin(byte2, byte2b);
    TUint8 byte7 = possibleHeader[6];

    // lets confirm that we have found a legal AAC header
    if (possibleHeader[0] == 0xFF &&
        byte2b[0] == '1' &&
        byte2b[1] == '1' &&
        byte2b[2] == '1' &&
        byte2b[3] == '1' &&
        //    byte2b[4] == '1' &&
        byte2b[5] == '0' &&
        byte2b[6] == '0')
        {
        
        aNumBlocksInFrame = (byte7 & 0x3)+1;
        
        
        // protection_absent -> the last bit of the second byte
        if (byte2b[7] == '0')
            {
            return 9 + 2*(aNumBlocksInFrame-1);
            }
        else
            {
            return 7;
            }
        
        
        


        }
    else
        {
        // it seems like a raw data block
        return 0;



        }
    }



TBool CProcAACFrameHandler::ParseFramesL(HBufC8* aFrame, RArray<TInt>& aFrameStarts, RArray<TInt>& aFrameLengths)
{
    if (iFrameStarts.Count() > 0)
    {
        for (TInt a = 0 ; a < iFrameStarts.Count() ; a++)
        {
            aFrameStarts.Append(iFrameStarts[a]);
            aFrameLengths.Append(iFrameLengths[a]);
        }    
        iFrameStarts.Reset();
        iFrameLengths.Reset();
        return ETrue;
    }
    else
    {
        
        TInt numBlocks = 1;
        TInt headerBytes = CalculateNumberOfHeaderBytes(aFrame, numBlocks);
        if (headerBytes > 0)
        {
            //TBuf8<headerBytes> hB(aFrame->Left(headerBytes));
            
            
        }
        
        //TBitStream bs;
        TUint8* buf = const_cast<TUint8*>(aFrame->Right(aFrame->Size()-headerBytes).Ptr());
        //BsInit(&bs, buf, aFrame->Size()-headerBytes);
        
        uint8* gains = new (ELeave) uint8[16];
        CleanupStack::PushL(gains);
        uint32* gainPos = new (ELeave) uint32[16];
        CleanupStack::PushL(gainPos);
        
        //TPtr8 frameWithoutHeader = aFrame->Right(aFrame->Size()-headerBytes));
        TInt bufLen = aFrame->Size()-headerBytes;
        
        TBitStream bs;
    
        BsInit(&bs, buf, bufLen);
    
        for (TInt b = 0 ; b < numBlocks ; b++)
        {
            
            TInt b_i = bs.buf_index;
            iFrameStarts.Append(b_i+headerBytes);
            
            uint8 numberOfGains = GetAACGlobalGains(&bs, iDecHandle, 16, gains, gainPos);
            if (numberOfGains > 2) 
                {
                CleanupStack::Pop(); // gainPos
                CleanupStack::Pop(); // gains
                delete[] gains;
                delete[] gainPos;
                return EFalse;

                }
            
            if (bs.buf_index > 0)
                iFrameLengths.Append(bs.buf_index - b_i);
            else
                iFrameLengths.Append(bs.buf_len - b_i);
            
            if (headerBytes > 7)
            {
                bs.buf_index += 2; // crc
                bs.slots_read += 2;
                bs.bits_read += 16;
                
            }
                        
        }
        CleanupStack::Pop(); // gainPos
        CleanupStack::Pop(); // gains
        delete[] gains;
        delete[] gainPos;

        
        
        for (TInt c = 0 ; c < iFrameStarts.Count() ; c++)
            {
            aFrameStarts.Append(iFrameStarts[c]);
            aFrameLengths.Append(iFrameLengths[c]);
            }    
        iFrameStarts.Reset();
        iFrameLengths.Reset();
        return ETrue;    
        
    }
    
    
    
    
}



TBool CProcAACFrameHandler::UpdateHeaderL(HBufC8* aFrame)
    {

    _LIT8(KZero, "0");

    TInt frameLength = aFrame->Size();

    HBufC8* lenBin;
    ProcTools::Dec2BinL(frameLength, lenBin);
    
    HBufC8* len13Bin = HBufC8::NewL(13);
    TInt zerosNeeded = 13-lenBin->Size();
    
    TPtr8 framePtr(aFrame->Des());
    for (TInt w = 0 ; w < zerosNeeded ; w++)
        {
        len13Bin->Des().Append(_L8("0"));
        }
    len13Bin->Des().Append(lenBin->Des());

    if (len13Bin->Mid(0,1).Compare(KZero) == 0)
        {
        framePtr[3] &= 0xFD; // 1111 1101
        }
    else
        {
        framePtr[3] |= 2;
        }

    if (len13Bin->Mid(1,1).Compare(KZero) == 0)
        {
        framePtr[3] &= 0xFE; // 1111 1110

        }
    else
        {
        framePtr[3] |= 1;
        }


    TUint byte5 = 0;
    ProcTools::Bin2Dec(len13Bin->Mid(2,8),byte5);
    framePtr[4] = static_cast<TUint8>(byte5);

    if (len13Bin->Mid(10,1).Compare(KZero) == 0)
        {
        framePtr[5] &= 0x7F;

        }
    else
        {
        framePtr[5] |= 0x80;
        }

    if (len13Bin->Mid(11,1).Compare(KZero) == 0)
        {
        framePtr[5] &= 0xBF;

        }
    else
        {
        framePtr[5] |= 0x40;
        }

    if (len13Bin->Mid(12,1).Compare(KZero) == 0)
        {
        framePtr[5] &= 0xDF;

        }
    else
        {
        framePtr[5] |= 0x20;
        }
    delete lenBin;
    delete len13Bin;
    return ETrue;
    }



void CProcAACFrameHandler::
GetEnhancedAACPlusParametersL(TUint8* buf, TInt bufLen, 
                              TAudFileProperties* aProperties, 
                              TAACFrameHandlerInfo *aAACInfo)
{
  TBitStream bs;
  uint8 sbrStatus;
  int16 bytesInFrame;
  CAACAudDec* decHandle = 0;

  //-- No SBR by default. --//
  aAACInfo->isSBR = 0;
  aAACInfo->iIsParametricStereo = 0;
  aProperties->iAudioTypeExtension = EAudExtensionTypeNoExtension;
  aProperties->iChannelModeExtension = EAudChannelModeNotRecognized;

  //-- Create AAC handle. --//
  CreateAACAudDecL(decHandle, 
                   static_cast<TInt16>(aAACInfo->iNumChannels), 
                   static_cast<TInt16>(aAACInfo->iNumCouplingChannels));
  CleanupStack::PushL(decHandle);

  //-- Initialize AAC handle. --/
  InitAACAudDec(decHandle, 
                static_cast<TInt16>(aAACInfo->iProfileID), 
                                static_cast<TInt16>(aAACInfo->iSampleRateID), 
                                static_cast<TUint8>(aAACInfo->iIs960));

  //-- Create SBR handle on top of the AAC handle. --
  sbrStatus = CreateAACPlusAudDecL(decHandle, static_cast<TInt16>(aAACInfo->iSampleRateID), 
                                   (uint8) ((aAACInfo->iNumChannels > 1) ? 1 : 0), 
                                   (uint8) 0);

  if(sbrStatus)
  {
    //-- Initialize bitstream. --
    BsInit(&bs, buf, bufLen);

    //-- Parse the AAC frame. --/
    CountAACChunkLength(&bs, decHandle, &bytesInFrame);

    //-- Were any SBR elements found? --
    if(IsAACSBREnabled(decHandle))
    {
      aAACInfo->isSBR = 1;
      aProperties->iAudioTypeExtension = EAudExtensionTypeEnhancedAACPlus;
      
      aAACInfo->iIsParametricStereo = IsAACParametricStereoEnabled(decHandle);

      if(aAACInfo->iIsParametricStereo)
      {
        aProperties->iChannelModeExtension = EAudParametricStereoChannel;
        aProperties->iAudioTypeExtension = EAudExtensionTypeEnhancedAACPlusParametricStereo;
      }
    }
  }


  //-- Delete resources. --/
  CleanupStack::Pop(decHandle);
  if(decHandle != 0)
      {
      DeleteAACAudDec(decHandle);    
      }
    
  decHandle = 0;
}