Correct work with UMC object Mpeg4FrameConstructor (memory leaks, ipp-samples.7.1.1.013)

Correct work with UMC object Mpeg4FrameConstructor (memory leaks, ipp-samples.7.1.1.013)

Hello all,

I use the UMC classes (xxxFrameConstructor, xxxVideoDecoder) to uncompress streaming video (MPEG4, H.264).
From network come the streaming video data of some size. I bring this data into the class Mpeg4FrameConstructor until the function UnLockInputBuffer does not returns a value UMC_OK. After that, I give the video frame to the decoder using function LockOutputBuffer. And sends the data to the decoder. And then the cycle until the data comes from the network. In this case, each new call of function UnLockInputBuffer of the class Mpeg4FrameConstructor the size of the returned buffer decreases (on the size of the previous frame)! And in the end he (buffer) ends (buffer size to be smaller than the size of the packet data)! How do I free up space in the buffer away from the frame that I've picked up into the decoder!?

void TVideoDecoder::OnData (PCVOID data,uint dataSize,uint64 timeMs,uint rtpTimestamp,struct timeval &presentationTime)

{
     UMC::MediaData buffer;
     UMC::Status status;

     buffer.SetBufferPointer((Ipp8u *)1,dataSize);
     buffer.SetDataSize(dataSize);
     if((status = UmcFC->LockInputBuffer(&buffer)) != UMC::UMC_OK){
          LogError("...");
          return;
     }
     memcpy((PBYTE)buffer.GetDataPointer(),data,dataSize);     
     buffer.SetDataSize(dataSize);
     status = UmcFC->UnLockInputBuffer(&buffer);
     switch(status){
          case UMC::UMC_OK:
               frameComplete();
               break;

          case UMC::UMC_ERR_NOT_ENOUGH_DATA:
               break;

          default:
               return;
     }
}
//---------------------------------------------------------------------------
void TVideoDecoder::frameComplete (void)
{
     UMC::MediaData buffer;
     UMC::Status status;

     status = UmcFC->LockOutputBuffer(&buffer);
     switch(status){
          case UMC::UMC_OK:
               break;

          case UMC::UMC_ERR_NOT_ENOUGH_DATA:
               // ???
               return;

          default:
               LogError("...");
               return;
     }
     decodeFrame(&buffer);
     status = UmcFC->UnLockOutputBuffer(&buffer);
}
//---------------------------------------------------------------------------
void TVideoDecoder::decodeFrame (UMC::MediaData *dataIn)
{
     UMC::Status status;

     DstFrameBuffer = Handler->OnGetVideoFrame();
     DataOut.SetBufferPointer((Ipp8u *)DstFrameBuffer->GetAddress(),DstFrameBuffer->GetSize());
     try {
          status = UmcDecoder->GetFrame(dataIn,&DataOut);
     }
     catch(std::exception &ex){
          LogErrorF("Exception: '%s'. Fatal error",ex.what());
          return;
     }
     switch(status){
          case UMC::UMC_OK:
               setFrameReady(DstFrameBuffer.Detach());
               break;

          case UMC::UMC_ERR_NOT_ENOUGH_DATA:
               try {
                    status = UmcDecoder->GetFrame(NULL,&DataOut);
               }
               catch(std::exception &ex){
                    LogErrorF("Exception: '%s'. Fatal error",ex.what());
                    return;
               }
               switch(status){
                    case UMC::UMC_OK:
                    setFrameReady(DstFrameBuffer.Detach());
                    break;

               case UMC::UMC_ERR_NOT_ENOUGH_DATA:
                    setFrameNotReady(errOk);
                    break;

               default:
                    setFrameNotReady(errCommon);
                    status = UMC::UMC_OK;
               }
               break;

          default:
               setFrameNotReady(errCommon);
     }
     Handler->OnVideoFrame(&Result);
}

2 posts / novo 0
Último post
Para obter mais informações sobre otimizações de compiladores, consulte Aviso sobre otimizações.

Hello,

Do you have to use FrameConstructor for some reason? It is much easier to use splitter ThreadedDemuxer to parse mpeg4 streams. FrameConstructor is used primarily as internal class for splitters and have quite vague interface.

Input buffer in FC clears up automatically after several samples. You need to have large enough buffer to store several samples and to process one frame at a time. Try to copy data in buffer in smaller portions, don't fill entire buffer at once. If you run out of space sooner than it frees up, try to initialize larger buffer in FC params.

Here is a decoding loop eaxample based on umc_video_dec_con:

    MediaData inBuff;
    Mpeg4FrameConstructor fc;
    FrameConstructorParams fcP;
    bool bEOF = false;
    size_t chunkSize   = 60000; // reading chunk
    fcP.m_lBufferSize  = 4194304; // should be several times larger than largest frame, ThreadedDemuxer initializes 4MB, probably for worst case scenario.
    fcP.m_bStopAtFrame = true;  // process one frame at a time
    fcP.m_bPureStream  = true;  // for pure streams
    fc.Init(&fcP);
    for(;;)
    {
        if(pDataIn && (pDataIn->GetDataSize() < 4 || status == UMC_ERR_NOT_ENOUGH_DATA))
        {
            status = fc.UnLockInputBuffer(NULL); // check buffer for frames
            if(status != UMC_OK)
            {
                if(bEOF)
                {
                    if(status == UMC_ERR_NOT_ENOUGH_DATA)
                        status = fc.UnLockInputBuffer(&inBuff, UMC_ERR_END_OF_STREAM); // get remaining data
                }
                else
                {
                    inBuff.SetBufferPointer((Ipp8u*)1, chunkSize);
                    inBuff.SetDataSize(chunkSize); // set data size to amount of data we want to read
                    status = fc.LockInputBuffer(&inBuff);
                    if(status != UMC_OK)
                        return 0; // not enough buffer to store chunks (try to enlarge m_lBufferSize in FrameConstructorParams)
                    // read chunk
                    size = chunkSize;
                    status = reader.GetData(inBuff.GetDataPointer(), size);
                    if(status == UMC_ERR_END_OF_STREAM)
                        bEOF = true;
                    else if(status != UMC_OK)
                        return 0;
                    inBuff.SetDataSize(size);
                    // parse chunk
                    status = fc.UnLockInputBuffer(&inBuff);
                    if(status == UMC_ERR_NOT_ENOUGH_DATA)
                    {
                        if(bEOF)
                            status = fc.UnLockInputBuffer(&inBuff, UMC_ERR_END_OF_STREAM); // get remaining data
                        else
                            continue; // chunk is too small, read another one
                    }
                }
            }
            // get parsed frame
            status = fc.LockOutputBuffer(pDataIn);
            if(bEOF && (status == UMC_ERR_NOT_ENOUGH_DATA || status == UMC_ERR_END_OF_STREAM))
                pDataIn = NULL; // end of FC parsing
        }
        status = decoder.GetFrame(pDataIn, &dataOut);
        // unlock output buffer
        if(pDataIn && (pDataIn->GetDataSize() < 4 || status == UMC_ERR_NOT_ENOUGH_DATA))
            status = fc.UnLockOutputBuffer(pDataIn);
        if (status == UMC_ERR_NOT_ENOUGH_DATA)
        {
            if(!pDataIn)
            {
                printf("decoding completed");
                return 0;
            }
            continue;
        }
        else if (status != UMC_OK)
        {
            printf("failed to decode frame");
            return 1;
        }
        // we have complete frame
        if(sOutputFile)
        {
            status = writeVideoFrame(&writer, &dataOut);
            if(status != UMC_OK)
            {
                printf("can not write to output file");
                return 1;
            }
        }
    }

Have a nice day.

Faça login para deixar um comentário.