diff -r 000000000000 -r 951a5db380a0 videoeditorengine/h263decoder/src/h263dntc.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/videoeditorengine/h263decoder/src/h263dntc.cpp Fri Jan 29 14:08:33 2010 +0200 @@ -0,0 +1,750 @@ +/* +* 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: +* Video decoder control interface. +* +*/ + + + +/* + * Includes + */ + +/* Include the definition header for the active build target */ +#include "h263dConfig.h" +/* Include the header for this file */ +#include "h263dntc.h" +/* All other inclusions */ +#include "biblin.h" +#include "h263dapi.h" +#include "vde.h" +#include "vdemain.h" +#include "vdeti.h" +#include "biblin.h" +/* MVE */ +//#include "InnerTranscoder.h" +#include "core.h" +#include "MPEG4Transcoder.h" + +/* + * Constants + */ +const TUint KH263StartCodeLength = 3; // H.263 picture start code length +const TUint KMPEG4StartCodeLength = 4; // MPEG4 picture start code length + +/* +* Global functions +*/ + +/* {{-output"h263dClose.txt"}} */ +/* +* h263dClose +* +* +* Parameters: +* hInstance instance handle +* +* Function: +* This function closes an H.263 decoder instance. +* +* Returns: +* Nothing +*/ + +void H263D_CC h263dClose(h263dHInstance_t hInstance) +/* {{-output"h263dClose.txt"}} */ +{ + if (hInstance) + vdeShutDown(hInstance); +} + + +/* {{-output"h263dDecodeFrame.txt"}} */ +/* +* h263dDecodeFrameL +* +* +* Parameters: +* hInstance instance data +* pStreamBuffer pointer to input data (>= 1 video frames) +* streamBufferSize size of pStreamBuffer +* fFirstFrame pointer to flag telling if the very first +* frame is being decoded +* frameSize If non-NULL, frameSize is used to return +* the number of bytes that were decoded +* to produce the reconstructed output frame. +* +* Function: +* This function decodes the bitstream until it gets at least one decoded +* frame. It also shows the resulting frames. +* In addition, the function handles the parameter updating synchronization. +* +* Returns: +* H263D_OK if the function was successful +* H263D_OK_EOS if the end of stream has been reached +* H263D_ERROR if a fatal error, from which the decoder +* cannot be restored, has occured +* H263D_ERROR_HALTED the instance is halted, it should be closed +*/ + +int H263D_CC h263dDecodeFrameL(h263dHInstance_t hInstance, + void *pStreamBuffer, + void *pOutStreamBuffer, + unsigned streamBufferSize, + u_char *fFirstFrame, + TInt *frameSize, + TInt *outframeSize, + vdeDecodeParamters_t *aDecoderInfo + ) + +/* {{-output"h263dDecodeFrame.txt"}} */ +{ + TInt colorEffect = aDecoderInfo->aColorEffect; + TInt colorToneU = aDecoderInfo->aColorToneU; + TInt colorToneV = aDecoderInfo->aColorToneV; + TInt frameOperation = aDecoderInfo->aFrameOperation; + TInt* trP = aDecoderInfo->aTrP; + TInt* trD = aDecoderInfo->aTrD; + TInt videoClipNumber = aDecoderInfo->aVideoClipNumber; + TInt smSpeed = aDecoderInfo->aSMSpeed; + TInt getDecodedFrame = aDecoderInfo->aGetDecodedFrame; + + bibBuffer_t + *buffer = 0; /* input buffer */ + + bibBuffer_t + *outbuffer = 0; /* output buffer */ + + bibBuffer_t + *tmpbuffer = 0; /* temporary buffer */ + + u_char* tmpbuf=0; + + bibBufferEdit_t + *bufEdit = 0; + + int StartByteIndex=0; + int StartBitIndex=7; + + int tr = 0; + int newtr = 0; + int efftr; + int numBitsGot; + int bitsErrorIndication; + int16 bibError; + + int retValue; /* return value for vde functions */ + + int leaveError = 0; + + int16 + errorCode = 0; /* return code for bib functions */ + + /* MVE */ + int startCodeLen = 0; + CMPEG4Transcoder *hTranscoder = NULL; + + TBool modifyMPEG4Afterwards = EFalse; + + vdeAssert(hInstance); + vdeAssert(pStreamBuffer); + vdeAssert(pOutStreamBuffer); + vdeAssert(streamBufferSize); + vdeAssert(fFirstFrame); + + vdeInstance_t *vdeinstance = (vdeInstance_t *) hInstance; + + /* Create bit buffer */ + buffer = bibCreate(pStreamBuffer, streamBufferSize, &errorCode); + if (!buffer || errorCode) + return H263D_ERROR; + + /* MVE */ + + if ((aDecoderInfo->streamMode==EVedVideoBitstreamModeMPEG4ShortHeader) || (aDecoderInfo->streamMode == EVedVideoBitstreamModeH263) ) + outbuffer = bibCreate(pOutStreamBuffer, streamBufferSize-3, &errorCode); + else + outbuffer = bibCreate(pOutStreamBuffer, streamBufferSize-4-3, &errorCode); + + if (!outbuffer || errorCode) + { + bibDelete(buffer, &errorCode); + return H263D_ERROR; + } + + bufEdit = bibBufferEditCreate(&errorCode); + if (!bufEdit || errorCode) + { + bibDelete(outbuffer, &errorCode); + bibDelete(buffer, &errorCode); + return H263D_ERROR; + } + + if(frameOperation==4 /*ENoDecodeNoWrite*/) + { + bufEdit->copyMode = CopyNone; + } + + if(colorEffect==1 || colorEffect==2) + { + outbuffer->numBytesRead=0; + outbuffer->size=0; + } + + /* Associate bit buffer with the VDE instance */ + retValue = vdeSetInputBuffer(hInstance, buffer); + if (retValue < 0) + goto freeBufferAndReturn; + + /* Associate output bit buffer with the VDE instance */ + retValue = vdeSetOutputBuffer(hInstance, outbuffer); + if (retValue < 0) + goto freeBufferAndReturn; + + retValue = vdeSetBufferEdit(hInstance, bufEdit); + if (retValue < 0) + goto freeBufferAndReturn; + + retValue = vdeSetVideoEditParams(hInstance, colorEffect, + getDecodedFrame, colorToneU, colorToneV); + if (retValue < 0) + goto freeBufferAndReturn; + + /* MVE */ + if (aDecoderInfo->streamMode == EVedVideoBitstreamModeH263 /*H.263*/) + { + /* read current TR */ + bibForwardBits(22,buffer); // streamBufferSize is in bytes + tr = bibGetBits(8,buffer,&numBitsGot, &bitsErrorIndication, &bibError); + bibRewindBits(30,buffer,&bibError); + } + + /* get first frame's QP */ + if (!(*fFirstFrame)) + { + vdeinstance->iRefQp = aDecoderInfo->aFirstFrameQp; + } + vdeinstance->iColorEffect = aDecoderInfo->aColorEffect; + vdeinstance->iColorToneU = aDecoderInfo->aColorToneU; + vdeinstance->iColorToneV = aDecoderInfo->aColorToneV; + + /* MVE */ + /* one frame is ready, initialize the transcoder */ + TRAP( leaveError, (hTranscoder = CMPEG4Transcoder::NewL(vdeinstance, vdeinstance->inBuffer, vdeinstance->outBuffer)) ); + if ( leaveError != 0 ) + { + retValue = leaveError; + goto freeBufferAndReturn; + } + + if (aDecoderInfo->aGetVideoMode) + { + /* we are to determine the bitstream mode */ + aDecoderInfo->aOutputVideoFormat = EVedVideoTypeNoVideo; + int dummy1, dummy2; // position of the error resillence bit,not used here + vdtGetVideoBitstreamInfo(buffer, aDecoderInfo, &dummy1, &dummy2); + } + + /* set transcoding information */ + retValue = hTranscoder->SetTranscoding(aDecoderInfo); + if ( retValue != TX_OK ) + { + goto freeBufferAndReturn; + } + + /* before the first frame is decoded, determine the stream type */ + if (*fFirstFrame) { + retValue = vdeDetermineStreamType(hInstance, hTranscoder); + if (retValue < 0) + goto freeBufferAndReturn; + + /* MVE */ + /* for the first frame of the bitstream, we may need to construct a new VOS */ + hTranscoder->ConstructVOSHeader(vdeinstance->fMPEG4, aDecoderInfo); + + if (vdeinstance->fMPEG4 == 1 ) + { + StartByteIndex = buffer->getIndex; + StartBitIndex = buffer->bitIndex; + + /* for MPEG4 (not including shortheader) stuffing bits are inserted at the end of the VOS + but the index here indicates the position of the stuffing bits + */ + if (StartBitIndex != 7) + { + StartByteIndex += 1; + StartBitIndex = 7; + } + + // update the output stream size by removing VOS size + streamBufferSize -= StartByteIndex; + } + + else if (aDecoderInfo->streamMode == EVedVideoBitstreamModeMPEG4ShortHeader) + { + if (aDecoderInfo->aOutputVideoFormat == EVedVideoTypeH263Profile0Level10 || + aDecoderInfo->aOutputVideoFormat == EVedVideoTypeH263Profile0Level45) + { + // we don't need the VOS header + StartByteIndex = buffer->getIndex; + StartBitIndex = buffer->bitIndex; + // update the output stream size by removing VOS size + streamBufferSize -= StartByteIndex; + } + else if (aDecoderInfo->aOutputVideoFormat == EVedVideoTypeMPEG4SimpleProfile && + aDecoderInfo->fModeChanged == EFalse) + { + // update the output stream size by removing VOS size + // but we need the original MPEG4 shortheader VOS, which is not yet copied to the output buffer + streamBufferSize -= buffer->getIndex; + + } + } + + } + + /* This may produce multiple output frames, and that is why it is commented + out. However, it may be useful if the bitstream is corrupted and picture + start codes are lost + while (buffer->bitsLeft > 8) { */ + /* Decode frame */ + + /* MVE */ + /* The buffer size is changed in h263decoder.cpp + In the old version, it is fixed to 3, which may be incorrect + */ + startCodeLen = (aDecoderInfo->streamMode == EVedVideoBitstreamModeH263)? KH263StartCodeLength : KMPEG4StartCodeLength; + + + + if ( ((aDecoderInfo->aOutputVideoFormat == EVedVideoTypeMPEG4SimpleProfile) + && !(aDecoderInfo->streamMode == EVedVideoBitstreamModeMPEG4ShortHeader)) + || ((aDecoderInfo->streamMode == EVedVideoBitstreamModeMPEG4ShortHeader) && aDecoderInfo->fModeChanged) ) + { + modifyMPEG4Afterwards = ETrue; + } + + if (frameOperation==1/*EDecodeAndWrite*/ || frameOperation==2/*EDecodeNoWrite*/) + { + if ( vdeinstance->fMPEG4 == 1 ) + { + buffer->size -= startCodeLen; + buffer->bitsLeft -= ( startCodeLen << 3 ); + } + retValue = vdeDecodeFrame(hInstance, StartByteIndex, StartBitIndex, hTranscoder); + if ( retValue < VDE_OK ) + { + // negative means fatal error + goto freeBufferAndReturn; + } + // get first frame QP for possible color toning + if (*fFirstFrame) + { + aDecoderInfo->aFirstFrameQp = hTranscoder->GetRefQP(); + } + } + else if (frameOperation==3/*EWriteNoDecode*/) + { + /* first reset bit counter to beginning of buffer */ + /* copy input frame as it is */ + bibForwardBits((streamBufferSize-startCodeLen)<<3,buffer); // streamBufferSize is in bytes + + if (aDecoderInfo->streamMode == EVedVideoBitstreamModeMPEG4ShortHeader && + aDecoderInfo->aOutputVideoFormat == EVedVideoTypeMPEG4SimpleProfile && + !(aDecoderInfo->fModeChanged)) + { + bibRewindBits(32,buffer,&bibError); + } + + /* reset buffer edit to CopyWhole mode */ + bufEdit->copyMode = CopyWhole/*CopyWhole*/; + + if ( vdeinstance->fMPEG4 == 1 ) + { + if (*fFirstFrame) + { + buffer->getIndex = buffer->size - startCodeLen; + buffer->bitIndex = 7; + buffer->bitsLeft = 24; + buffer->numBytesRead = buffer->size - startCodeLen; + } + + if ( buffer->numBytesRead > 4 ) + { + buffer->numBytesRead -= 4; + buffer->getIndex = buffer->numBytesRead; + } + } + // Reassign pointers so that outbuffer actually has the pointer to (in)buffer's data, + // if we have MPEG4 output (not short header) and we need to change e.g. timestamps + // This eliminates 2 memory copies - otherwise we would copy from buffer to outbuffer to tmpbuffer to outbuffer; + // the content is modified when copying from tmpbuffer to outbuffer. + // tmpbuffer is needed since we can't modify the content directly in the outbuffer. + // Now we can copy directly from buffer to outbuffer. + // In this branch we don't call vdeDecodeFrame at all, but use either CopyEditVopL for MPEG-4 or + // CopyStream for H.263 + if ( modifyMPEG4Afterwards ) + { + tmpbuffer = buffer; + } + else + { + /* copy from buffer to outbuffer. This simulates vdeDecodeFrame with EDecodeAndWrite */ + CopyStream(buffer,outbuffer,bufEdit,StartByteIndex,StartBitIndex); + } + retValue=0; + } + + outbuffer->size = outbuffer->getIndex; + outbuffer->bitsLeft = 0; + + if ( !tmpbuffer ) + { + /* if tr values are changes, need another buffer */ + /* first create temp buffer in memory */ + tmpbuf = (u_char*) malloc(outbuffer->size + 4); + if (tmpbuf == NULL) + { + bibDelete(outbuffer, &errorCode); + bibDelete(buffer, &errorCode); + bibBufEditDelete(bufEdit, &errorCode); + return H263D_ERROR; + } + tmpbuffer = bibCreate((void*)tmpbuf, outbuffer->size + 4, &errorCode); + if (!tmpbuffer || errorCode) + { + free(tmpbuf); + bibDelete(outbuffer, &errorCode); + bibDelete(buffer, &errorCode); + bibBufEditDelete(bufEdit, &errorCode); + return H263D_ERROR; + } + } + + /* MVE */ + if (aDecoderInfo->aOutputVideoFormat != EVedVideoTypeNoVideo) + { + + if ( modifyMPEG4Afterwards ) + { + if ( tmpbuffer != buffer ) + { + // the bitstream was decoded too, need to copy it temporarily from outbuffer to tmpbuffer since it needs to be modified + bibRewindBits(bibNumberOfFlushedBits(tmpbuffer),tmpbuffer,&bibError); + bibRewindBits(bibNumberOfFlushedBits(outbuffer),outbuffer,&bibError); + bibForwardBits(((outbuffer->size)<<3),outbuffer); + outbuffer->bitsLeft = 0; + + StartByteIndex = 0; + StartBitIndex = 7; + + CopyStream(outbuffer,tmpbuffer,bufEdit,StartByteIndex,StartBitIndex); + tmpbuffer->baseAddr[tmpbuffer->getIndex] = 0x0; + tmpbuffer->baseAddr[tmpbuffer->getIndex+1] = 0x0; + tmpbuffer->baseAddr[tmpbuffer->getIndex+2] = 0x01; + tmpbuffer->baseAddr[tmpbuffer->getIndex+3] = 0xb6; + } + else + { + // the tmpbuffer was used as a shortcut to the buffer, no need to copy anything here. + tmpbuffer->bitsLeft = 32; + // the following ones are probably not needed + tmpbuffer->baseAddr[tmpbuffer->getIndex+4] = 0x0; + tmpbuffer->baseAddr[tmpbuffer->getIndex+5] = 0x0; + tmpbuffer->baseAddr[tmpbuffer->getIndex+6] = 0x01; + tmpbuffer->baseAddr[tmpbuffer->getIndex+7] = 0xb6; + } + + + bibForwardBits(32,tmpbuffer); + + // Copy bitstream part-by-part, possibly modifying it, from tmp to output. + // StartByteIndex may be > 0 if there is VOS header in tmpbuffer already. It is always byte-aligned so no need to have StartBitIndex + TInt skip = 0; + if ( StartByteIndex > 0 ) + { + // startByteIndex refers to input buffer. + // The skip however should refer to the output buffer. The output header size is in aDecoderInfo + skip = aDecoderInfo->vosHeaderSize; + } + int retVal= CopyEditVop(hInstance, skip, tmpbuffer, aDecoderInfo); + if(retVal<0) + { + retValue = retVal; //will be handled later + } + } + else + { + /* copy input frame while changing TR */ + if((videoClipNumber>0) || (smSpeed!=1000)) + { + if ((frameOperation==1) || ((frameOperation==2) && !getDecodedFrame)) + { + /* if the output buffer will not be use, leave it as it is! */ + } + else + { + + /* get new TR */ + StartByteIndex = 0; + StartBitIndex = 7; + outbuffer->bitsLeft = 0; + newtr = GetNewTrValue(tr, trP, trD, smSpeed); + /* change TR value in output bitstream */ + /* prepare editing position */ + if (!bufEdit->editParams) + { + bufEdit->editParams = (bibEditParams_t *) malloc(sizeof(bibEditParams_t)); + if (bufEdit->editParams == NULL) + { + retValue = H263D_ERROR; + goto freeBufferAndReturn; + } + + bufEdit->numChanges=1; + bufEdit->copyMode = CopyWithEdit; // CopyWithEdit + } + bufEdit->editParams->curNumBits = bufEdit->editParams->newNumBits = 8; + bufEdit->editParams->StartByteIndex=2; //2; // starting position for the TR marker + bufEdit->editParams->StartBitIndex=1; //1; // starting position for the TR marker + bufEdit->editParams->newValue=newtr; + /* copy the input buffer to the output buffer with TR changes */ + CopyStream(outbuffer,tmpbuffer,bufEdit,StartByteIndex,StartBitIndex); + bibRewindBits((streamBufferSize)<<3,buffer,&bibError); + /* copy the changed bitstream from tmpbuffer back to buffer */ + bufEdit->copyMode = CopyWhole; // CopyWhole + bibRewindBits(bibNumberOfFlushedBits(outbuffer),outbuffer,&bibError); + CopyStream(tmpbuffer,outbuffer,bufEdit,StartByteIndex,StartBitIndex); + bibRewindBits((streamBufferSize)<<3,buffer,&bibError); + } + } + /* update TR values */ + efftr = (videoClipNumber>0 || smSpeed!=1000) ? newtr : tr; + *trP = efftr; + *trD = tr; + } + } + + *fFirstFrame = 0; + + if (retValue < 0) + goto freeBufferAndReturn; + /* See the comment above. + else if (retValue == H263D_OK_EOS) + break; + } */ + + if (frameSize) + *frameSize = bibNumberOfFlushedBytes(buffer) + + ((bibNumberOfFlushedBits(buffer) % 8 > 0) ? 1 : 0); + + *outframeSize = outbuffer->numBytesRead; + + +freeBufferAndReturn: + + int bitError = buffer->error; + + if (hTranscoder) + { + delete hTranscoder; + hTranscoder = NULL; + } + + if ( tmpbuffer == buffer ) + { + // tmpbuffer was a shortcut to inbuffer, set it to NULL to avoid deleting it + tmpbuffer = NULL; + } + + int16 deleteError = 0; + /* Delete bit buffer */ + bibDelete(buffer, &errorCode); + if ( errorCode ) + { + deleteError = errorCode; + } + + /* Delete output bit buffer */ + bibDelete(outbuffer, &errorCode); + if ( errorCode ) + { + deleteError = errorCode; + } + + /* Delete tmp bit buffer, if it was used */ + if ( tmpbuffer ) + { + bibDelete(tmpbuffer, &errorCode); + if ( errorCode ) + { + deleteError = errorCode; + } + } + if(tmpbuf) + free(tmpbuf); + + /* Delete bufEdit */ + bibBufEditDelete(bufEdit, &errorCode); + if ( errorCode ) + { + deleteError = errorCode; + } + if (deleteError || errorCode) + return H263D_ERROR; + + if ( bitError ) + { + return H263D_OK_BUT_FRAME_USELESS; + } + + return retValue; +} + + +/* {{-output"h263dGetLatestFrame.txt"}} */ +/* +* h263dGetLatestFrame +* +* +* Parameters: +* hInstance instance data +* +* ppy, ppu, ppv used to return Y, U and V frame pointers +* +* pLumWidth, pLumHeight used to return luminance image width and height +* +* pFrameNum used to return frame number +* +* Function: +* This function returns the latest correctly decoded frame +* (and some side-information). +* +* Returns: +* H263D_OK if the function was successful +* H263D_ERROR if a fatal error, from which the decoder +* cannot be restored, has occured +* H263D_ERROR_HALTED the instance is halted, it should be closed +*/ + + +int H263D_CC h263dGetLatestFrame( + h263dHInstance_t hInstance, + u_char **ppy, u_char **ppu, u_char **ppv, + int *pLumWidth, int *pLumHeight, + int *pFrameNum) + /* {{-output"h263dGetLatestFrame.txt"}} */ +{ + vdeAssert(hInstance); + vdeAssert(ppy); + vdeAssert(ppu); + vdeAssert(ppv); + vdeAssert(pLumWidth); + vdeAssert(pLumHeight); + vdeAssert(pFrameNum); + + return vdeGetLatestFrame(hInstance, ppy, ppu, ppv, pLumWidth, pLumHeight, + pFrameNum); +} + + + +/* {{-output"h263dIsIntra.txt"}} */ +/* +* h263dIsIntra +* +* +* Parameters: +* hInstance handle of instance data +* frameStart pointer to memory chunk containing a frame +* frameLength number of bytes in frame +* +* Function: +* This function returns 1 if the passed frame is an INTRA frame. +* Otherwise the function returns 0. +* +* Returns: +* See above. +*/ + +int h263dIsIntra( + h263dHInstance_t hInstance, + void *frameStart, + unsigned frameLength) + /* {{-output"h263dIsIntra.txt"}} */ +{ + vdeAssert(hInstance); + vdeAssert(frameStart); + vdeAssert(frameLength); + + return vdeIsINTRA(hInstance, frameStart, frameLength); +} + +/* {{-output"h263dOpen.txt"}} */ +/* +* h263dOpen +* +* +* Parameters: +* openParam initialization parameters +* +* Function: +* This function creates and initializes a new H.263 decoder instance. +* +* Returns: +* an instance handle if the function was successful +* NULL if an error occured +*/ + +h263dHInstance_t H263D_CC h263dOpen(h263dOpen_t *openParam) +/* {{-output"h263dOpen.txt"}} */ +{ + vdeAssert(openParam); + + /* No extra space needs to be allocated after the VDE instance data + (of type vdeInstance_t) due to the fact that no thread specific + data is needed. */ + openParam->freeSpace = 0; + + return vdeInit(openParam); +} + + + +int GetNewTrValue(int aTrCurOrig, int* aTrPrevNew, int* aTrPrevOrig, int aSMSpeed) +{ + int trCurNew=0; + int trDiff=0; + TReal speedFactor = (TReal)aSMSpeed/1000.0; + + trDiff = aTrCurOrig - *aTrPrevOrig; + if(trDiff==0) // if corrupt TR values + trDiff=1; + else if(trDiff<0) // jump in TR values (change of clip or end of limit) + trDiff = 3; // arbitrary, for 10 fps default + // check for slow motion + vdeAssert(aSMSpeed); + if(aSMSpeed!=1000) + trDiff = (int)((TReal)trDiff/speedFactor + 0.5); + trCurNew = *aTrPrevNew + trDiff; + if(trCurNew>255) + trCurNew = trCurNew%256; + return trCurNew; +} + + + +// End of File