LCOV - code coverage report
Current view: directory - frmts/ecw - ecwasyncreader.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1 1 100.0 %
Date: 2012-04-28 Functions: 3 2 66.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: ecwdataset.cpp 21486 2011-01-13 17:38:17Z warmerdam $
       3                 :  *
       4                 :  * Project:  GDAL 
       5                 :  * Purpose:  ECWAsyncReader implementation
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2011, Frank Warmerdam <warmerdam@pobox.com>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "gdal_ecw.h"
      31                 : 
      32            4029 : CPL_CVSID("$Id: ecwdataset.cpp 21486 2011-01-13 17:38:17Z warmerdam $");
      33                 : 
      34                 : #if defined(FRMT_ecw) && (ECWSDK_VERSION >= 40)
      35                 : 
      36                 : /************************************************************************/
      37                 : /*                          BeginAsyncReader()                          */
      38                 : /************************************************************************/
      39                 : 
      40                 : GDALAsyncReader* 
      41                 : ECWDataset::BeginAsyncReader( int nXOff, int nYOff, int nXSize, int nYSize, 
      42                 :                               void *pBuf, int nBufXSize, int nBufYSize,
      43                 :                               GDALDataType eBufType,
      44                 :                               int nBandCount, int* panBandMap,
      45                 :                               int nPixelSpace, int nLineSpace, int nBandSpace,
      46                 :                               char **papszOptions)
      47                 : 
      48                 : {
      49                 : /* -------------------------------------------------------------------- */
      50                 : /*      Provide default packing if needed.                              */
      51                 : /* -------------------------------------------------------------------- */
      52                 :     if( nPixelSpace == 0 )
      53                 :         nPixelSpace = GDALGetDataTypeSize(eBufType) / 8;
      54                 :     if( nLineSpace == 0 )
      55                 :         nLineSpace = nPixelSpace * nBufXSize;
      56                 :     if( nBandSpace == 0 )
      57                 :         nBandSpace = nLineSpace * nBufYSize;
      58                 :     
      59                 : /* -------------------------------------------------------------------- */
      60                 : /*      We should do a bit of validation first - perhaps add later.     */
      61                 : /* -------------------------------------------------------------------- */
      62                 :     
      63                 : /* -------------------------------------------------------------------- */
      64                 : /*      Create the corresponding async reader.                          */
      65                 : /* -------------------------------------------------------------------- */
      66                 :     ECWAsyncReader *poReader = new ECWAsyncReader();
      67                 : 
      68                 :     poReader->poDS = this;
      69                 : 
      70                 :     poReader->nXOff = nXOff;
      71                 :     poReader->nYOff = nYOff;
      72                 :     poReader->nXSize = nXSize;
      73                 :     poReader->nYSize = nYSize;
      74                 : 
      75                 :     poReader->pBuf = pBuf;
      76                 :     poReader->nBufXSize = nBufXSize;
      77                 :     poReader->nBufYSize = nBufYSize;
      78                 :     poReader->eBufType = eBufType;
      79                 :     poReader->nBandCount = nBandCount;
      80                 :     poReader->panBandMap = (int *) CPLCalloc(sizeof(int),nBandCount);
      81                 :     memcpy( poReader->panBandMap, panBandMap, sizeof(int) * nBandCount );
      82                 : 
      83                 :     poReader->nPixelSpace = nPixelSpace;
      84                 :     poReader->nLineSpace = nLineSpace;
      85                 :     poReader->nBandSpace = nBandSpace;
      86                 : 
      87                 : /* -------------------------------------------------------------------- */
      88                 : /*      Create a new view for this request.                             */
      89                 : /* -------------------------------------------------------------------- */
      90                 :     poReader->poFileView = OpenFileView( GetDescription(), true, 
      91                 :                                          poReader->bUsingCustomStream );
      92                 : 
      93                 :     if( poReader->poFileView == NULL )
      94                 :     {
      95                 :         delete poReader;
      96                 :         return NULL;
      97                 :     }
      98                 : 
      99                 :     poReader->poFileView->SetClientData( poReader );
     100                 :     poReader->poFileView->SetRefreshCallback( ECWAsyncReader::RefreshCB );
     101                 : 
     102                 : /* -------------------------------------------------------------------- */
     103                 : /*      Issue a corresponding SetView command.                          */
     104                 : /* -------------------------------------------------------------------- */
     105                 :     std::vector<UINT32> anBandIndices;
     106                 :     int   i;
     107                 :     NCSError     eNCSErr;
     108                 :     CNCSError    oErr;
     109                 :     
     110                 :     for( i = 0; i < nBandCount; i++ )
     111                 :         anBandIndices.push_back( panBandMap[i] - 1 );
     112                 : 
     113                 :     oErr = poReader->poFileView->SetView( nBandCount, &(anBandIndices[0]),
     114                 :                                           nXOff, nYOff, 
     115                 :                                           nXOff + nXSize - 1, 
     116                 :                                           nYOff + nYSize - 1,
     117                 :                                           nBufXSize, nBufYSize );
     118                 :     eNCSErr = oErr.GetErrorNumber();
     119                 :     
     120                 :     if( eNCSErr != NCS_SUCCESS )
     121                 :     {
     122                 :         delete poReader;
     123                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     124                 :                   "%s", NCSGetErrorText(eNCSErr) );
     125                 :         
     126                 :         return NULL;
     127                 :     }
     128                 : 
     129                 :     return poReader;
     130                 : }
     131                 : 
     132                 : /************************************************************************/
     133                 : /*                           EndAsyncReader()                           */
     134                 : /************************************************************************/
     135                 : void ECWDataset::EndAsyncReader(GDALAsyncReader *poReader)
     136                 : 
     137                 : {
     138                 :     delete poReader;
     139                 : }
     140                 : 
     141                 : /************************************************************************/
     142                 : /*                           ECWAsyncReader()                           */
     143                 : /************************************************************************/
     144                 : 
     145                 : ECWAsyncReader::ECWAsyncReader()
     146                 : 
     147                 : {
     148                 :     hMutex = CPLCreateMutex();
     149                 :     CPLReleaseMutex( hMutex );
     150                 : 
     151                 :     poFileView = NULL;
     152                 :     bUpdateReady = FALSE;
     153                 :     bComplete = FALSE;
     154                 : }
     155                 : 
     156                 : /************************************************************************/
     157                 : /*                          ~ECWAsyncReader()                           */
     158                 : /************************************************************************/
     159                 : 
     160                 : ECWAsyncReader::~ECWAsyncReader()
     161                 : 
     162                 : {
     163                 :     {
     164                 :         CPLMutexHolderD( &hMutex );
     165                 : 
     166                 :         // cancel? 
     167                 : 
     168                 :         delete poFileView;
     169                 :         // we should also consider cleaning up the io stream if needed.
     170                 :     }
     171                 : 
     172                 :     CPLDestroyMutex( hMutex );
     173                 :     hMutex = NULL;
     174                 : }
     175                 : 
     176                 : /************************************************************************/
     177                 : /*                             RefreshCB()                              */
     178                 : /*                                                                      */
     179                 : /*      This static method is called by the ECW SDK to notify us        */
     180                 : /*      that there is new data ready to refresh from.  We just mark     */
     181                 : /*      the async reader as ready for an update.  We fetch the data     */
     182                 : /*      and push into into the buffer the application uses.  We lock    */
     183                 : /*      this async reader's mutex for this whole operation to avoid     */
     184                 : /*      a conflict with the main application.                           */
     185                 : /************************************************************************/
     186                 : 
     187                 : NCSEcwReadStatus ECWAsyncReader::RefreshCB( NCSFileView *pFileView )
     188                 : 
     189                 : {
     190                 :     NCSFileViewSetInfo *psVSI = NULL;
     191                 : 
     192                 :     NCScbmGetViewInfo( pFileView, &psVSI );
     193                 :     if( psVSI != NULL )
     194                 :     {
     195                 :         CPLDebug( "ECW", "RefreshCB(): BlockCounts=%d/%d/%d/%d", 
     196                 :                   psVSI->nBlocksAvailableAtSetView,
     197                 :                   psVSI->nBlocksAvailable,
     198                 :                   psVSI->nMissedBlocksDuringRead,
     199                 :                   psVSI->nBlocksInView );
     200                 :     }
     201                 : 
     202                 : /* -------------------------------------------------------------------- */
     203                 : /*      Identify the reader we are responding on behalf of.             */
     204                 : /* -------------------------------------------------------------------- */
     205                 :     CNCSJP2FileView *poFileView = (CNCSJP2FileView *) pFileView;
     206                 :     ECWAsyncReader *poReader = (ECWAsyncReader *)poFileView->GetClientData();
     207                 :     
     208                 : /* -------------------------------------------------------------------- */
     209                 : /*      Acquire the async reader mutex.  Currently we make no           */
     210                 : /*      arrangements for failure to acquire it.                         */
     211                 : /* -------------------------------------------------------------------- */
     212                 :     CPLMutexHolderD( &(poReader->hMutex) );
     213                 : 
     214                 : /* -------------------------------------------------------------------- */
     215                 : /*      Mark the buffer as updated unless we are already complete.      */
     216                 : /*      It seems the Update callback keeps getting called even when     */
     217                 : /*      no new data has arrived after completion so we don't want to    */
     218                 : /*      trigger new work elsewhere in that case.                        */
     219                 : /*                                                                      */
     220                 : /*      Also record whether we are now complete.                        */
     221                 : /* -------------------------------------------------------------------- */
     222                 :     if( !poReader->bComplete )
     223                 :         poReader->bUpdateReady = TRUE;
     224                 : 
     225                 :     if( psVSI->nBlocksAvailable == psVSI->nBlocksInView )
     226                 :         poReader->bComplete = TRUE;
     227                 : 
     228                 :     return NCSECW_READ_OK;
     229                 : }
     230                 : 
     231                 : /************************************************************************/
     232                 : /*                            ReadToBuffer()                            */
     233                 : /************************************************************************/
     234                 : NCSEcwReadStatus ECWAsyncReader::ReadToBuffer()
     235                 : {
     236                 : /* -------------------------------------------------------------------- */
     237                 : /*      Setup working scanline, and the pointers into it.               */
     238                 : /*                                                                      */
     239                 : /*      Should we try and optimize some cases that we could read        */
     240                 : /*      directly into the application buffer?  Perhaps in the           */
     241                 : /*      future.                                                         */
     242                 : /* -------------------------------------------------------------------- */
     243                 :     ECWDataset *poECWDS = (ECWDataset *) poDS;
     244                 :     int i;
     245                 :     int nDataTypeSize = (GDALGetDataTypeSize(poECWDS->eRasterDataType) / 8);
     246                 :     GByte *pabyBILScanline = (GByte *) 
     247                 :         CPLMalloc(nBufXSize * nDataTypeSize * nBandCount);
     248                 :     GByte **papabyBIL = (GByte**)CPLMalloc(nBandCount*sizeof(void*));
     249                 : 
     250                 :     for( i = 0; i < nBandCount; i++ )
     251                 :         papabyBIL[i] = pabyBILScanline 
     252                 :             + i * nBufXSize * nDataTypeSize;
     253                 : 
     254                 : /* -------------------------------------------------------------------- */
     255                 : /*      Read back the imagery into the buffer.                          */
     256                 : /* -------------------------------------------------------------------- */ 
     257                 :     for( int iScanline = 0; iScanline < nBufYSize; iScanline++ )
     258                 :     {
     259                 :         NCSEcwReadStatus  eRStatus;
     260                 : 
     261                 :         eRStatus = 
     262                 :             poFileView->ReadLineBIL( poECWDS->eNCSRequestDataType, 
     263                 :                                                (UINT16) nBandCount,
     264                 :                                                (void **) papabyBIL );
     265                 :         if( eRStatus != NCSECW_READ_OK )
     266                 :         {
     267                 :             CPLFree( papabyBIL );
     268                 :             CPLFree( pabyBILScanline );
     269                 :             CPLError( CE_Failure, CPLE_AppDefined,
     270                 :                       "NCScbmReadViewLineBIL failed." );
     271                 :             return eRStatus;
     272                 :         }
     273                 : 
     274                 :         for( i = 0; i < nBandCount; i++ )
     275                 :         {
     276                 :             GDALCopyWords( 
     277                 :                 pabyBILScanline + i * nDataTypeSize * nBufXSize,
     278                 :                 poECWDS->eRasterDataType, nDataTypeSize, 
     279                 :                 ((GByte *) pBuf) 
     280                 :                 + nLineSpace * iScanline 
     281                 :                 + nBandSpace * i, 
     282                 :                 eBufType, 
     283                 :                 nPixelSpace, 
     284                 :                 nBufXSize );
     285                 :         }
     286                 :     }
     287                 : 
     288                 :     CPLFree( pabyBILScanline );
     289                 :     CPLFree( papabyBIL );
     290                 : 
     291                 :     return NCSECW_READ_OK;
     292                 : }
     293                 : 
     294                 : /************************************************************************/
     295                 : /*                        GetNextUpdatedRegion()                        */
     296                 : /************************************************************************/
     297                 : 
     298                 : GDALAsyncStatusType 
     299                 : ECWAsyncReader::GetNextUpdatedRegion( double dfTimeout,
     300                 :                                       int* pnXBufOff, int* pnYBufOff,
     301                 :                                       int* pnXBufSize, int* pnYBufSize )
     302                 : 
     303                 : {
     304                 :     CPLDebug( "ECW", "GetNextUpdatedRegion()" );
     305                 : 
     306                 : /* -------------------------------------------------------------------- */
     307                 : /*      We always mark the whole raster as updated since the ECW SDK    */
     308                 : /*      does not have a concept of partial update notifications.        */
     309                 : /* -------------------------------------------------------------------- */
     310                 :     *pnXBufOff = 0;
     311                 :     *pnYBufOff = 0;
     312                 :     *pnXBufSize = nBufXSize;
     313                 :     *pnYBufSize = nBufYSize;
     314                 : 
     315                 :     if( bComplete && !bUpdateReady )
     316                 :     {
     317                 :         CPLDebug( "ECW", "return GARIO_COMPLETE" );
     318                 :         return GARIO_COMPLETE;
     319                 :     }
     320                 :         
     321                 : /* -------------------------------------------------------------------- */
     322                 : /*      Wait till our timeout, or until we are notified there is        */
     323                 : /*      data ready.  We are trusting the CPLSleep() to be pretty        */
     324                 : /*      accurate instead of keeping track of time elapsed ourselves     */
     325                 : /*      - this is not necessarily a good approach.                      */
     326                 : /* -------------------------------------------------------------------- */
     327                 :     if( dfTimeout < 0.0 )
     328                 :         dfTimeout = 100000.0;
     329                 :     
     330                 :     while( !bUpdateReady && dfTimeout > 0.0 )
     331                 :     {
     332                 :         CPLSleep( MIN(0.1, dfTimeout) );
     333                 :         dfTimeout -= 0.1;
     334                 :         CPLDebug( "ECW", "wait..." );
     335                 :     }
     336                 : 
     337                 :     if( !bUpdateReady )
     338                 :     {
     339                 :         CPLDebug( "ECW", "return GARIO_PENDING" );
     340                 :         return GARIO_PENDING;
     341                 :     }
     342                 : 
     343                 :     bUpdateReady = FALSE;
     344                 : 
     345                 : /* -------------------------------------------------------------------- */
     346                 : /*      Acquire Mutex                                                   */
     347                 : /* -------------------------------------------------------------------- */
     348                 :     if( !CPLAcquireMutex( hMutex, dfTimeout ) )
     349                 :     {
     350                 :         CPLDebug( "ECW", "return GARIO_PENDING" );
     351                 :         return GARIO_PENDING;
     352                 :     }
     353                 : 
     354                 : /* -------------------------------------------------------------------- */
     355                 : /*      Actually decode the imagery into our buffer.                    */
     356                 : /* -------------------------------------------------------------------- */
     357                 :     NCSEcwReadStatus  eRStatus = ReadToBuffer();
     358                 : 
     359                 :     if( eRStatus != NCSECW_READ_OK )
     360                 :     {
     361                 :         CPLReleaseMutex( hMutex );
     362                 :         return GARIO_ERROR;
     363                 :     }
     364                 : 
     365                 : /* -------------------------------------------------------------------- */
     366                 : /*      Return indication of complete or just buffer updateded.         */
     367                 : /* -------------------------------------------------------------------- */
     368                 : 
     369                 :     if( bComplete && !bUpdateReady )
     370                 :     {
     371                 :         CPLReleaseMutex( hMutex );
     372                 :         CPLDebug( "ECW", "return GARIO_COMPLETE" );
     373                 :         return GARIO_COMPLETE;
     374                 :     }
     375                 :     else
     376                 :     {
     377                 :         CPLReleaseMutex( hMutex );
     378                 :         CPLDebug( "ECW", "return GARIO_UPDATE" );
     379                 :         return GARIO_UPDATE;
     380                 :     }
     381                 : }
     382                 : 
     383                 : #endif /* def FRMT_ecw */

Generated by: LCOV version 1.7