camcordermmfplugin/mediarecorder/Src/CCMRVideoCodecDataH263.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 00:20:52 +0200
changeset 2 c7e61a0077eb
parent 0 9b3e960ffc8a
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/*
* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "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:
*
* Description:  H.263 specific data
*
*/



// INCLUDE FILES
#include "CCMRVideoCodecDataH263.h"
#include "CCMRVideoSettings.h"
#include "CCMRMediaRecorder.h"

#include <mmf/devvideo/devvideorecord.h>
#include <mmf/devvideo/h263.h>

// Debug print macro
#ifdef _DEBUG
#include <e32svr.h>
#define PRINT(x) RDebug::Print x
#else
#define PRINT(x)
#endif

// CONSTANTS based on ITU-T H.263 specification (04/2005)
// Annex X, profiles and levels definition
// Table X.2/H.263 - Levels of operation:

// Max framerates (fps) based on codec levels
const TReal32 KCMRH263Level10Fps = 15.0; // or actually 14.985
const TReal32 KCMRH263Level20Fps = 15.0; // or actually 14.985
const TReal32 KCMRH263Level20FpsQCIF = 30.0; // or actually 29.97
const TReal32 KCMRH263Level3040Fps = 30.0; // or actually 29.97
const TReal32 KCMRH263Level45Fps = 15.0; // or actually 14.985
const TReal32 KCMRH263Level50Fps = 50.0;
const TReal32 KCMRH263Level50FpsSIF = 60.0; // or actually 59.94

// Max bitrates (bps) based on codec levels
const TInt KCMRH263Level10Bps = 64000;
const TInt KCMRH263Level20Bps = 128000;
const TInt KCMRH263Level30Bps = 384000;
const TInt KCMRH263Level40Bps = 2048000;
const TInt KCMRH263Level45Bps = 128000;
const TInt KCMRH263Level50Bps = 4096000;

// max coded picture size (bytes; per H.263 requirements).
const TUint KCMRMaxCodedPictureSizeQCIF = 16384; // QCIF and smaller
const TUint KCMRMaxCodedPictureSizeCIF = 65536; // CIF and smaller

// ---------------------------------------------------------
// CCMRVideoCodecDataH263::MaxBitRate
// Checks the maximum allowed bitrate for the selected codec
// (other items were commented in a header).
// ---------------------------------------------------------
//
TInt CCMRVideoCodecDataH263::MaxBitRate() const
    {
    switch ( iVideoCodecLevel )
        {
        case 20 :
            return KCMRH263Level20Bps;
        case 30 :
            return KCMRH263Level30Bps;
        case 40 :
            return KCMRH263Level40Bps;
        case 45 :
            return KCMRH263Level45Bps;
        case 50 :
            return KCMRH263Level50Bps;
        case 10 : // 10 is the default level
        default :
            return KCMRH263Level10Bps;
        }
    }

// ---------------------------------------------------------
// CCMRVideoCodecDataH263::MaxFrameRate
// Checks the maximum allowed frame rate for the selected codec
// (other items were commented in a header).
// ---------------------------------------------------------
//
TReal32 CCMRVideoCodecDataH263::MaxFrameRate(const TSize& aFrameSize) const
    {
    switch ( iVideoCodecLevel )
        {
        case 20 :
            if ( aFrameSize.iHeight > KCMRQCIFHeight || aFrameSize.iWidth > KCMRQCIFWidth )
                {
                return KCMRH263Level20Fps;
                }
            else
                {
                // smaller size (at most QCIF) => different max rate
                return KCMRH263Level20FpsQCIF;
                }
        case 30 :
        case 40 :
            return KCMRH263Level3040Fps;
        case 45 :
            return KCMRH263Level45Fps;
        case 50 :
            if ( aFrameSize.iHeight == KCMRCIFHeight )
                {
                return KCMRH263Level50Fps;
                }
            else
                {
                // smaller size (at most 352x240) => different max rate
                return KCMRH263Level50FpsSIF;
                }
        case 10 : // 10 is the default level
        default :
            return KCMRH263Level10Fps;
        }
    }

// ---------------------------------------------------------
// CCMRVideoCodecDataH263::MaxFrameSize
// Checks if the frame size for the selected codec is acceptable
// (other items were commented in a header).
// ---------------------------------------------------------
//
TBool CCMRVideoCodecDataH263::MaxFrameSize( const TSize& aSize ) const
    {
    TSize maxSize;
    TBool arbitrarySizeAllowed = ETrue;
    switch ( iVideoCodecLevel )
        {
        case 20 :
        case 30 :
        case 40 :
            arbitrarySizeAllowed = EFalse;
            maxSize.SetSize(KCMRCIFWidth,KCMRCIFHeight);
            break;
        case 50 :
            arbitrarySizeAllowed = ETrue;
            maxSize.SetSize(KCMRCIFWidth,KCMRCIFHeight);
            break;
        case 45 :
            arbitrarySizeAllowed = ETrue;
            maxSize.SetSize(KCMRQCIFWidth,KCMRQCIFHeight);
            break;
        case 10 : // 10 is the default level
        default: 
            arbitrarySizeAllowed = EFalse;
            maxSize.SetSize(KCMRQCIFWidth,KCMRQCIFHeight);
        }

    // subQCIF is always the smallest one we support. 
    // Max size depends on codec level and checked above
    if ( (aSize.iWidth < KCMRSubQCIFWidth) || (aSize.iHeight < KCMRSubQCIFHeight) 
        || (aSize.iWidth > maxSize.iWidth) || (aSize.iHeight > maxSize.iHeight) )
        {
        // size not ok
        return EFalse;
        }

    // next step, check if size is arbitrary
    if ( !arbitrarySizeAllowed )
        {
        // accept only subQCIF, QCIF or CIF
        if ( ((aSize.iWidth == KCMRSubQCIFWidth) && (aSize.iHeight == KCMRSubQCIFHeight)) ||
             ((aSize.iWidth == KCMRQCIFWidth) && (aSize.iHeight == KCMRQCIFHeight)) ||
             ((aSize.iWidth == KCMRCIFWidth) && (aSize.iHeight == KCMRCIFHeight)) 
            )
            {
            // size ok
            return ETrue;
            }
        else
            {
            // size not ok
            return EFalse;
            }
        }
    else
        {
        // size ok
        return ETrue;
        }
    }


// -----------------------------------------------------------------------------
// CCMRVideoCodecDataH263::LevelForMMS
// Check if codec level indicates we are recording for MMS; then some tighter restrictions apply
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TBool CCMRVideoCodecDataH263::LevelForMMS() const
    {
    if ( iVideoCodecLevel == 10 )
        {
        // H.263 level 10 is the mandatory codec for MMS
        PRINT((_L("CCMRVideoCodecDataH263::LevelForMMS() using H.263 level 10, applying MMS restrictions")));
        return ETrue;
        }
    else
        {
        PRINT((_L("CCMRVideoCodecDataH263::LevelForMMS() using some non-MMS H.263 level")));
        return EFalse;
        }
    }


// -----------------------------------------------------------------------------
// CCMRVideoCodecDataH263::MaxBufferLength
// Returns the max used buffer length for this codec. Client can then e.g. allocate buffers based on it
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TInt CCMRVideoCodecDataH263::MaxBufferLength(const TSize& aFrameSize) const
    {

    if ( (aFrameSize.iHeight <= KCMRQCIFHeight) && (aFrameSize.iWidth <= KCMRQCIFWidth) )
        {
        // QCIF and smaller
        // H.263, only depends on picture size
        return KCMRMaxCodedPictureSizeQCIF;
        }
    else if ( (aFrameSize.iHeight <= KCMRCIFHeight) && (aFrameSize.iWidth <= KCMRCIFWidth) )
        {
        // QCIF+ to CIF
        return KCMRMaxCodedPictureSizeCIF;
        }
    else
        {
        // larger picture sizes not supported
        return 0;
        }
    }
    
// ---------------------------------------------------------
// CCMRVideoCodecDataH263::SetVideoCodingOptionsL
// Set misc video coding options
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoCodecDataH263::SetVideoCodingOptionsL(const TCCMRVideoCodingOptions& aOptions)
    {
    iSyncIntervalInPicture = aOptions.iSyncIntervalInPicture;
    
    if ( (aOptions.iExpectedBitErrorRate == 0.0) && (aOptions.iExpectedPacketLossRate > 0.0) )
        {
        // currently only BitErrorRate has an effect, map also PacketLossRate to BitErrorRate; a very strong simplification
        if ( aOptions.iExpectedPacketLossRate > KCMRBadPacketLossRate )
            {
            // bad packet loss rate
            iExpectedBitErrorRate = KCMRBadBitErrorRate;
            }
        else if ( aOptions.iExpectedPacketLossRate > KCMRNotNoticeablePacketLossRate )
            {
            // between bad and not noticeable
            iExpectedBitErrorRate = KCMRTolerableBitErrorRate;
            }
        else
            {
            // not noticeable
            iExpectedBitErrorRate = KCMRNotNoticeableBitErrorRate;
            }
        }
    else
        {
        iExpectedBitErrorRate = aOptions.iExpectedBitErrorRate;
        }
    }
    
    
// ---------------------------------------------------------
// CCMRVideoCodecDataH263::SetPreInitParamsL
// Set codec-specific video coding options to DevVideoRecord before initialize
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoCodecDataH263::SetPreInitParamsL(CMMFDevVideoRecord* aDevVideoRecord) const
    {
    if ( iSyncIntervalInPicture > 0 )
        {
        // Set Standard specific coding options
        TH263VideoMode h263Options;
        h263Options.iAllowedPictureTypes = EH263PictureTypeI | EH263PictureTypeP;
        h263Options.iForceRoundingTypeToZero = ETrue;
        h263Options.iPictureHeaderRepetition = 0;
        h263Options.iGOBHeaderInterval = iSyncIntervalInPicture;
        TPckgC<TH263VideoMode> h263pckg(h263Options);
        aDevVideoRecord->SetCodingStandardSpecificOptionsL( h263pckg );
        }
    }
    


// ---------------------------------------------------------
// CCMRVideoCodecDataH263::SetPostInitParamsL
// Set codec-specific video coding options to DevVideoRecord after initialize
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CCMRVideoCodecDataH263::SetPostInitParamsL(CMMFDevVideoRecord* aDevVideoRecord) const
    {
    if ( iExpectedBitErrorRate > 0.0 )
        {
        // set expected bit error rate to encoder
        aDevVideoRecord->SetChannelBitErrorRate( 0, iExpectedBitErrorRate, 0);
        }
    }