videoeditorengine/h263decoder/src/vdeti.cpp
branchRCL_3
changeset 3 e0b5df5c0969
parent 0 951a5db380a0
child 5 4c409de21d23
equal deleted inserted replaced
0:951a5db380a0 3:e0b5df5c0969
     1 /*
       
     2 * Copyright (c) 2010 Ixonos Plc.
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - Initial contribution
       
    11 *
       
    12 * Contributors:
       
    13 * Ixonos Plc
       
    14 *
       
    15 * Description:  
       
    16 * Frame decoding function.
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 
       
    22 /*
       
    23  * Includes
       
    24  */
       
    25 
       
    26 #include "h263dconfig.h"
       
    27 #include "vdeti.h"
       
    28 #include "debug.h"
       
    29 #include "sync.h"
       
    30 #include "vde.h"
       
    31 #include "vdemain.h"
       
    32 #include "core.h"
       
    33 /* MVE */
       
    34 #include "MPEG4Transcoder.h"
       
    35 
       
    36 /*
       
    37  * Local function prototype
       
    38  */
       
    39 
       
    40 static int vdeSeekNextValidDecodingStartPosition(
       
    41    vdeInstance_t *instance, CMPEG4Transcoder *hTranscoder);
       
    42 
       
    43 
       
    44 /*
       
    45  * Functions visible outside this module
       
    46  */
       
    47 
       
    48 /* {{-output"vdeDecodeFrame.txt"}} */
       
    49 /*
       
    50  * vdeDecodeFrame
       
    51  *
       
    52  * Parameters:
       
    53  *    hInstance                  instance data
       
    54  *
       
    55  * Function:
       
    56  *    This function decodes the bitstream by using
       
    57  *    vdcDecodeFrame until it gets at least one decoded frame. It also shows 
       
    58  *    the resulting frames (by calling renDraw). 
       
    59  *    In addition, the function handles the parameter updating synchronization
       
    60  *    by calling the VDE Queue module.
       
    61  *
       
    62  *    This function is intended to be called from the thread main function.
       
    63  *    It won't return until it gets a new decoded frame. If the bitstream
       
    64  *    is totally corrupted, this feature might cause a considerable delay
       
    65  *    in the execution of the thread main function.
       
    66  *
       
    67  * Returns:
       
    68  *    VDE_OK                     if the function was successful
       
    69  *    VDE_OK_EOS                 if the end of stream has been reached
       
    70  *    VDE_OK_BUT_FRAME_USELESS   if the function behaved normally, but no 
       
    71  *                               decoding output was produced due to too
       
    72  *                               corrupted input frame
       
    73  *    VDE_ERROR                  if a fatal error, from which the decoder
       
    74  *                               cannot be restored, has occured
       
    75  *    VDE_ERROR_HALTED           the instance is halted, it should be closed
       
    76  *
       
    77  *    
       
    78  */
       
    79 
       
    80 
       
    81 int vdeDecodeFrame(vdeHInstance_t hInstance, int /*aStartByteIndex*/, int /*aStartBitIndex*/, CMPEG4Transcoder *hTranscoder)
       
    82 /* {{-output"vdeDecodeFrame.txt"}} */
       
    83 {
       
    84    int
       
    85       sncCode,                   /* sync code from which to start decoding */
       
    86       numOutputFrames,           /* number of output frames, 2 for PB-frames,
       
    87                                     1 otherwise */
       
    88       fOutputUseless,            /* 1 if frame(s) too corrupted to display,
       
    89                                     0 otherwise */
       
    90       i,                         /* loop variable */
       
    91       vdcStatus,                 /* return value of vdcDecodeFrame or 
       
    92                                     vdcDecodeMPEGVop */
       
    93       fFullPictureFreeze = 0;    /* set to 1 if full-picture freeze is
       
    94                                     going on as described in section L.4
       
    95                                     of the H.263 recommendation */
       
    96 
       
    97    vdeInstance_t 
       
    98       *instance = (vdeInstance_t *) hInstance;
       
    99                                  /* pointer to instance structure */
       
   100 
       
   101     /* MVE */
       
   102      int StartByteIndex ;
       
   103      int StartBitIndex ;
       
   104 
       
   105    instance->fPrevFrameDecoded = 0;
       
   106 
       
   107    /* If the instance is in the EOS state */
       
   108    if (instance->state == VDE_STATE_EOS) {
       
   109 
       
   110       /* If MPEG-4 stream, visual_object_sequence_end_code terminates
       
   111          a visual session, and therefore we return.
       
   112          If H.263 stream, EOS (End of Sequence) has no semantics, and
       
   113          therefore we return only if MoVi buffers wrapper indicates so. */
       
   114       if (instance->fMPEG4)
       
   115          /* Return an indication that the stream has ended */
       
   116          return VDE_OK_EOS;
       
   117    }
       
   118 
       
   119    /* If the instance is in the "Halted" state */
       
   120    if (instance->state == VDE_STATE_HALTED) {
       
   121 
       
   122       /* If the current frame is INTRA */
       
   123       if (vdcIsINTRA(instance->vdcHInstance, instance->inBuffer->baseAddr, 20)) {
       
   124          /* Reset the state and try to decode */
       
   125          instance->state = VDE_STATE_MIDDLE;
       
   126          deb("vdeDecodeFrame: Trying to recover from halted state.\n");
       
   127       }
       
   128 
       
   129       else {
       
   130          deb("vdeDecodeFrame: ERROR - already halted.\n");
       
   131          /* Return an indication that the stream cannot be decoded further */
       
   132          return VDE_ERROR_HALTED;
       
   133       }
       
   134    }
       
   135 
       
   136    /* If the instance state indicates that we should resynchronize to INTRA
       
   137       frame */
       
   138    if (instance->state == VDE_STATE_RESYNC) {
       
   139 
       
   140       /* If the current frame is INTRA */
       
   141       if (vdcIsINTRA(instance->vdcHInstance, instance->inBuffer->baseAddr, 20)) {
       
   142          /* Reset the state and continue decoding */
       
   143          instance->state = VDE_STATE_MIDDLE;
       
   144       }
       
   145 
       
   146       else
       
   147          return VDE_OK;
       
   148    }
       
   149 
       
   150    /* Read a synchronization code from the current position of the 
       
   151    bitstream or seek the next valid sync code to start decoding */
       
   152    sncCode = vdeSeekNextValidDecodingStartPosition(instance, hTranscoder);
       
   153 
       
   154    /* If error in seeking sync code */
       
   155    if (sncCode < 0)
       
   156       /* Return error */
       
   157       return sncCode;
       
   158 
       
   159    /* Else if sync code not found 
       
   160       Note: Can only happen in "one frame per one input bit buffer" case, 
       
   161       i.e. not in videophone */
       
   162    else if (sncCode == SNC_NO_SYNC)
       
   163       /* Note: One could send a INTRA picture request if such a service is
       
   164          available. However, it is assumed that the service is not available
       
   165          in this non-videophone application, and therefore no update is
       
   166          requested. */
       
   167 
       
   168       /* Return indication of useless (too corrupted) frame */
       
   169       return VDE_OK_BUT_FRAME_USELESS;
       
   170 
       
   171    /* Set the instance to the "Middle" state */
       
   172    instance->state = VDE_STATE_MIDDLE;
       
   173 
       
   174    /* If the synchronization code == EOS */
       
   175    if (sncCode == SNC_EOS) {
       
   176 
       
   177       /* Set the instance to the EOS state */
       
   178       instance->state = VDE_STATE_EOS;
       
   179 
       
   180       /* Return an indication that the stream ended */
       
   181       return VDE_OK_EOS;
       
   182    }
       
   183       
       
   184    /* MVE */
       
   185      StartByteIndex = instance->inBuffer->getIndex;
       
   186      StartBitIndex  = instance->inBuffer->bitIndex;
       
   187 
       
   188 
       
   189 
       
   190 
       
   191    /* Decode a frame */
       
   192 
       
   193    if (instance->fMPEG4) {
       
   194 
       
   195       vdcStatus = vdcDecodeMPEGVop(instance->vdcHInstance, instance->inBuffer,
       
   196           instance->outBuffer, instance->bufEdit, instance->iColorEffect, instance->iGetDecodedFrame,
       
   197           StartByteIndex, StartBitIndex, hTranscoder);
       
   198    } 
       
   199    else 
       
   200    {
       
   201 
       
   202 
       
   203        vdcStatus = vdcDecodeFrame(instance->vdcHInstance, instance->inBuffer, 
       
   204            instance->outBuffer, instance->bufEdit, instance->iColorEffect,instance->iGetDecodedFrame, hTranscoder);
       
   205 
       
   206    }
       
   207 
       
   208 
       
   209    if (vdcStatus < 0) {
       
   210       deb("vdeDecodeFrame: ERROR - vdcDecodeFrame failed.\n");
       
   211 
       
   212       instance->state = VDE_STATE_HALTED;
       
   213 
       
   214       if (vdcStatus == VDC_ERR_NO_INTRA)
       
   215           return VDE_ERROR_NO_INTRA;
       
   216       
       
   217       return VDE_ERROR_HALTED;
       
   218    }
       
   219 
       
   220    /* If EOS occured */
       
   221    if (vdcIsEOSReached(instance->vdcHInstance))
       
   222       instance->state = VDE_STATE_EOS;
       
   223 
       
   224    /* If the decoded frame is totally corrupted */
       
   225    if ((vdcStatus == VDC_OK_BUT_FRAME_USELESS) || (vdcStatus == VDC_OK_BUT_NOT_CODED)) {
       
   226 
       
   227       /* If continuous input buffer */
       
   228 
       
   229       fOutputUseless = 1;
       
   230    }
       
   231 
       
   232    else {
       
   233       fOutputUseless = 0;
       
   234       instance->fPrevFrameDecoded = 1;
       
   235    }
       
   236 
       
   237 
       
   238    /* If H.263 bitstream and decoding (partially) successful */
       
   239    if (!instance->fMPEG4 && !fOutputUseless) {
       
   240    }
       
   241 
       
   242    /*
       
   243     * Return decoded images to the image store and 
       
   244     * send them to Video Renderer if needed
       
   245     */
       
   246 
       
   247    numOutputFrames = vdcGetNumberOfOutputFrames(instance->vdcHInstance);
       
   248 
       
   249    /* Loop to handle each output frame separately */
       
   250    for (i = 0; i < numOutputFrames; i++) {
       
   251       vdeImsItem_t *imsItem;
       
   252 
       
   253       imsItem = vdcGetImsItem(instance->vdcHInstance, i);
       
   254 
       
   255       vdeAssert(imsItem);
       
   256 
       
   257       /* If the frame is useless */
       
   258       if (fOutputUseless) {
       
   259 
       
   260          /* Return the image buffer to the "Free" store */
       
   261          if (vdeImsPutFree(&instance->imageStore, imsItem) < 0) {
       
   262            deb("vdeDecodeFrame: ERROR - vdeImsPutFree failed.\n");
       
   263            instance->state = VDE_STATE_HALTED;
       
   264            return VDE_ERROR_HALTED;
       
   265          }
       
   266       }
       
   267 
       
   268       /* Else the frame is ok */
       
   269       else {
       
   270 
       
   271          vdeImb_t *imb;
       
   272 
       
   273          vdeImsStoreItemToImageBuffer(imsItem, &imb);
       
   274 
       
   275 
       
   276          /* If full-picture freeze requested */
       
   277          if (fFullPictureFreeze) {
       
   278 
       
   279             /* Return the image buffer to the image buffer store
       
   280                but don't send it to the renderer */
       
   281             if (vdeImsPut(&instance->imageStore, imsItem) < 0) {
       
   282                deb("vdeDecodeFrame: ERROR - vdeImsPut failed.\n");
       
   283                instance->state = VDE_STATE_HALTED;
       
   284                return VDE_ERROR_HALTED;
       
   285             }
       
   286          }
       
   287 
       
   288          /* Else normal displaying */
       
   289          else {
       
   290             h263dFrameType_t frameType;
       
   291             int renStatus;
       
   292             u_int32 renHandle;
       
   293 
       
   294             /* Get renderer for the output frame */
       
   295             frameType.scope = H263D_FTYPE_NDEF;
       
   296             frameType.width = renDriBitmapWidth(imb->drawItem);
       
   297             frameType.height = renDriBitmapHeight(imb->drawItem);
       
   298        
       
   299             renStatus = vdeFrtGetItem(&instance->renStore, &frameType, &renHandle);
       
   300 
       
   301             if (renStatus == VDE_OK_NOT_AVAILABLE)
       
   302                renHandle = 0;
       
   303 
       
   304 
       
   305             if (renStatus >= 0) {
       
   306                /* Return the image buffer to the image buffer store
       
   307                   and send it to the renderer (if possible) */
       
   308                if (vdeImsPut(&instance->imageStore, imsItem) < 0) {
       
   309                   deb("vdeDecodeFrame: ERROR - vdeImsPut failed.\n");
       
   310                   instance->state = VDE_STATE_HALTED;
       
   311                   return VDE_ERROR_HALTED;
       
   312                }
       
   313             }
       
   314 
       
   315             else {
       
   316                deb("vdeDecodeFrame: ERROR - vdeFrtGetItem failed.\n");
       
   317                instance->state = VDE_STATE_HALTED;
       
   318                return VDE_ERROR_HALTED;
       
   319             }
       
   320          }
       
   321 
       
   322       }
       
   323    }
       
   324    
       
   325    // fatal errors were returned already earlier
       
   326    switch ( vdcStatus )
       
   327     {
       
   328     case VDC_OK_BUT_FRAME_USELESS:
       
   329         {
       
   330         return VDE_OK_BUT_FRAME_USELESS;
       
   331         }
       
   332 //        break;
       
   333     case VDC_OK_BUT_NOT_CODED:
       
   334         {
       
   335         return VDE_OK_BUT_NOT_CODED;
       
   336         }
       
   337 //        break;
       
   338     default:
       
   339       {
       
   340         break;
       
   341 //      return VDE_OK;
       
   342       }
       
   343     }
       
   344     
       
   345 return VDE_OK;
       
   346 }
       
   347 
       
   348 
       
   349 /*
       
   350  * Local functions
       
   351  */
       
   352 
       
   353 /*
       
   354  * vdeSeekNextValidDecodingStartPosition
       
   355  *
       
   356  * Parameters:
       
   357  *    instance                   instance data
       
   358  *
       
   359  * Function:
       
   360  *    This function seeks the next synchronization position from the bitstream
       
   361  *    (starting from the current position) from which the decoder can start
       
   362  *    decoding.
       
   363  *
       
   364  * Returns:
       
   365  *    VDE_ERROR                  if a fatal error, from which the decoder
       
   366  *                               cannot be restored, has occured
       
   367  *
       
   368  *    SNC_NO_SYNC                if no suitable sync code was found
       
   369  *                               (can happen only in non-videophone case
       
   370  *                               where only one frame is in one bit input
       
   371  *                               buffer)
       
   372  *
       
   373  *    SNC_PSC                    H.263 Picture Start Code found
       
   374  *
       
   375  *    SNC_EOS                    H.263 End of Sequence found or
       
   376  *                               MPEG-4 EOB found
       
   377  *
       
   378  *    SNC_GBSC                   H.263 GBSC found
       
   379  *
       
   380  *    SNC_VOP                    MPEG-4 VOP
       
   381  *    SNC_GOV                    MPEG-4 GOV
       
   382  *
       
   383  *    
       
   384  */
       
   385 
       
   386 static int vdeSeekNextValidDecodingStartPosition(
       
   387    vdeInstance_t *instance, CMPEG4Transcoder *hTranscoder)
       
   388 {
       
   389    int
       
   390       sncCode = SNC_NO_SYNC;  /* sync code in current position */
       
   391    int16 
       
   392       error = 0;              /* error code returned from sync module */
       
   393 
       
   394    /* Note: For the first INTRA of the stream,
       
   395    do the H.263 vs. non-H.263 stream decision in a higher level,
       
   396    now assume that there has simply been a bit error in the header,
       
   397    and one should try from the next PSC */
       
   398 
       
   399    if (instance->fMPEG4) {
       
   400       vdcInstance_t* vdcinst = (vdcInstance_t *) instance->vdcHInstance;
       
   401       int fcode = vdcinst->pictureParam.fcode_forward;
       
   402 
       
   403       while (sncCode != SNC_VOP && 
       
   404              sncCode != SNC_GOV && 
       
   405              sncCode != SNC_EOB &&
       
   406              sncCode != SNC_VIDPACK) {
       
   407 
       
   408          sncCode = sncSeekMPEGStartCode(instance->inBuffer, (fcode ? fcode : 1), 1 /* VPs not relevant at this stage */, 0, &error);
       
   409          if (error == ERR_BIB_NOT_ENOUGH_DATA)
       
   410             return SNC_NO_SYNC;
       
   411          else if (error)
       
   412             return VDE_ERROR;
       
   413          else if (sncCode == SNC_VOS)
       
   414          {            
       
   415             /* Visual Object Sequence start code found, VOS + VO + VOL headers have to be parsed now.. */
       
   416             /* (The bitstream may contain multiple instances of VOS start codes before Visual
       
   417                 Object Sequence end code) */
       
   418             if (vdcDecodeMPEGVolHeader(vdcinst, instance->inBuffer, hTranscoder) != 0)
       
   419                return VDE_ERROR;
       
   420          }
       
   421       }
       
   422 
       
   423       if (sncCode == SNC_EOB)
       
   424          sncCode = SNC_EOS;
       
   425    }
       
   426    else 
       
   427    {
       
   428       while (
       
   429          sncCode != SNC_PSC && 
       
   430          sncCode != SNC_EOS &&
       
   431          sncCode != SNC_GBSC ) {
       
   432 
       
   433          sncCode = sncSeekSync(instance->inBuffer, &error);
       
   434          if (error == ERR_BIB_NOT_ENOUGH_DATA)
       
   435             return SNC_NO_SYNC;
       
   436          else if (error)
       
   437             return VDE_ERROR;
       
   438       }
       
   439    }
       
   440 
       
   441    return sncCode;
       
   442 }
       
   443 
       
   444 
       
   445 // End of file