source: 3DVCSoftware/trunk/source/App/TAppDecoder/TAppDecTop.cpp @ 1097

Last change on this file since 1097 was 1084, checked in by tech, 10 years ago

Merged branches/HTM-12.1-dev0@1083.

  • Property svn:eol-style set to native
File size: 36.1 KB
RevLine 
[5]1/* The copyright in this software is being made available under the BSD
2 * License, included below. This software may be subject to other third party
3 * and contributor rights, including patent rights, and no such rights are
[56]4 * granted under this license. 
[5]5 *
[872]6* Copyright (c) 2010-2014, ITU/ISO/IEC
[5]7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 *  * Redistributions of source code must retain the above copyright notice,
13 *    this list of conditions and the following disclaimer.
14 *  * Redistributions in binary form must reproduce the above copyright notice,
15 *    this list of conditions and the following disclaimer in the documentation
16 *    and/or other materials provided with the distribution.
[56]17 *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
[5]18 *    be used to endorse or promote products derived from this software without
19 *    specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
32 */
[2]33
34/** \file     TAppDecTop.cpp
35    \brief    Decoder application class
36*/
37
38#include <list>
[56]39#include <vector>
[2]40#include <stdio.h>
41#include <fcntl.h>
42#include <assert.h>
43
44#include "TAppDecTop.h"
[56]45#include "TLibDecoder/AnnexBread.h"
46#include "TLibDecoder/NALread.h"
[2]47
[56]48//! \ingroup TAppDecoder
49//! \{
[2]50
51// ====================================================================================================================
52// Constructor / destructor / initialization / destroy
53// ====================================================================================================================
54
55TAppDecTop::TAppDecTop()
[608]56#if !H_MV
57: m_iPOCLastDisplay(-MAX_INT)
58#else
59: m_numDecoders( 0 )
60#endif
[2]61{
[608]62#if H_MV
[738]63  for (Int i = 0; i < MAX_NUM_LAYER_IDS; i++) 
64  {
65    m_layerIdToDecIdx[i] = -1; 
66    m_layerInitilizedFlags[i] = false; 
67  }
[608]68#endif
69#if H_3D
70    m_pScaleOffsetFile  = 0;
71#endif
[964]72
[976]73#if H_MV
[964]74    m_markedForOutput = false; 
75#endif
76
[2]77}
78
79Void TAppDecTop::create()
80{
81}
82
83Void TAppDecTop::destroy()
84{
[608]85  if (m_pchBitstreamFile)
86  {
87    free (m_pchBitstreamFile);
88    m_pchBitstreamFile = NULL;
89  }
90#if H_MV
91  for (Int decIdx = 0; decIdx < m_numDecoders; decIdx++)
92  {
93    if (m_pchReconFiles[decIdx])
94    {
95      free (m_pchReconFiles[decIdx]);
96      m_pchReconFiles[decIdx] = NULL;
97    }
98  }
99#endif
100  if (m_pchReconFile)
101  {
102    free (m_pchReconFile);
103    m_pchReconFile = NULL;
104  }
105#if H_3D
106  if (m_pchScaleOffsetFile)
107  {
108    free (m_pchScaleOffsetFile);
109    m_pchScaleOffsetFile = NULL; 
110  }
111#endif
[2]112}
113
114// ====================================================================================================================
115// Public member functions
116// ====================================================================================================================
117
118/**
119 - create internal class
120 - initialize internal class
121 - until the end of the bitstream, call decoding function in TDecTop class
122 - delete allocated buffers
123 - destroy internal class
124 .
125 */
126Void TAppDecTop::decode()
127{
[608]128  Int                 poc;
129#if H_MV
130  poc = -1; 
[77]131#endif
[608]132  TComList<TComPic*>* pcListPic = NULL;
[210]133
[56]134  ifstream bitstreamFile(m_pchBitstreamFile, ifstream::in | ifstream::binary);
135  if (!bitstreamFile)
136  {
137    fprintf(stderr, "\nfailed to open bitstream file `%s' for reading\n", m_pchBitstreamFile);
138    exit(EXIT_FAILURE);
139  }
[2]140
[608]141#if H_3D
[56]142  if( m_pchScaleOffsetFile ) 
143  { 
144    m_pScaleOffsetFile = ::fopen( m_pchScaleOffsetFile, "wt" ); 
145    AOF( m_pScaleOffsetFile ); 
146  }
[608]147#endif
[56]148  InputByteStream bytestream(bitstreamFile);
149
[608]150  // create & initialize internal classes
151  xCreateDecLib();
152  xInitDecLib  ();
153#if !H_MV
154  m_iPOCLastDisplay += m_iSkipFrame;      // set the last displayed POC correctly for skip forward.
155
156  // main decoder loop
[655]157  Bool openedReconFile = false; // reconstruction file not yet opened. (must be performed after SPS is seen)
[608]158#else
[964]159
[608]160  Int  pocCurrPic        = -MAX_INT;     
161  Int  pocLastPic        = -MAX_INT;   
[964]162
163  Int  layerIdLastPic    = -MAX_INT; 
[608]164  Int  layerIdCurrPic    = 0; 
165
166  Int  decIdxLastPic     = 0; 
167  Int  decIdxCurrPic     = 0; 
168
169  Bool firstSlice        = true; 
170#endif
[872]171  Bool loopFiltered      = false;
172
[56]173  while (!!bitstreamFile)
[2]174  {
[56]175    /* location serves to work around a design fault in the decoder, whereby
176     * the process of reading a new slice that is the first slice of a new frame
177     * requires the TDecTop::decode() method to be called again with the same
178     * nal unit. */
179    streampos location = bitstreamFile.tellg();
[608]180#if H_MV
181#if ENC_DEC_TRACE
182    Int64 symCount = g_nSymbolCounter;
183#endif
184#endif
[56]185    AnnexBStats stats = AnnexBStats();
186    vector<uint8_t> nalUnit;
187    InputNALUnit nalu;
188    byteStreamNALUnit(bytestream, nalUnit, stats);
189
190    // call actual decoding function
[608]191    Bool bNewPicture = false;
192#if H_MV
193    Bool newSliceDiffPoc   = false;
194    Bool newSliceDiffLayer = false;
[964]195    Bool sliceSkippedFlag  = false; 
[608]196    Bool allLayersDecoded  = false;     
197#endif
[56]198    if (nalUnit.empty())
[2]199    {
[56]200      /* this can happen if the following occur:
201       *  - empty input file
202       *  - two back-to-back start_code_prefixes
203       *  - start_code_prefix immediately followed by EOF
204       */
205      fprintf(stderr, "Warning: Attempt to decode an empty NAL unit\n");
[2]206    }
207    else
208    {
[56]209      read(nalu, nalUnit);
[608]210#if H_MV     
[872]211      if( (m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) 
212          || !isNaluWithinTargetDecLayerIdSet(&nalu)
213          || nalu.m_layerId > MAX_NUM_LAYER_IDS-1
214          || (nalu.m_nalUnitType == NAL_UNIT_VPS && nalu.m_layerId > 0)           
[964]215          || (nalu.m_nalUnitType == NAL_UNIT_EOB && nalu.m_layerId > 0)   
216          || (nalu.m_nalUnitType == NAL_UNIT_EOS && nalu.m_layerId > 0)   
[872]217         ) 
[77]218      {
[608]219        bNewPicture = false;
[738]220        if ( !bitstreamFile )
221        {
222          decIdxLastPic     = decIdxCurrPic; 
223        }
[77]224      }
[210]225      else
[608]226      { 
[738]227        Int decIdx     = xGetDecoderIdx( nalu.m_layerId , true );     
[608]228        newSliceDiffLayer = nalu.isSlice() && ( nalu.m_layerId != layerIdCurrPic ) && !firstSlice;
[738]229        newSliceDiffPoc   = m_tDecTop[decIdx]->decode(nalu, m_iSkipFrame, m_pocLastDisplay[decIdx], newSliceDiffLayer, sliceSkippedFlag );
[608]230        // decode function only returns true when all of the following conditions are true
231        // - poc in particular layer changes
232        // - nalu does not belong to first slice in layer
233        // - nalu.isSlice() == true     
234
[964]235        if ( nalu.m_nalUnitType == NAL_UNIT_VPS )
236        {
237          m_vps = m_tDecTop[decIdx]->getPrefetchedVPS(); 
238          if ( m_targetDecLayerIdSetFileEmpty )
239          {
240            TComVPS* vps = m_vps; 
[1066]241            if ( m_targetOptLayerSetIdx == -1 )
242            {
243              // Not normative! Corresponds to specification by "External Means". (Should be set equal to 0, when no external means available. )
244              m_targetOptLayerSetIdx = vps->getVpsNumLayerSetsMinus1(); 
245            }
[976]246
[1066]247            for (Int dI = 0; dI < m_numDecoders; dI++ )
248            {
249              m_tDecTop[decIdx]->setTargetOptLayerSetIdx( m_targetOptLayerSetIdx ); 
250            }
251
252            if ( m_targetOptLayerSetIdx < 0 || m_targetOptLayerSetIdx >= vps->getNumOutputLayerSets() )
253            {
254              fprintf(stderr, "\ntarget output layer set index must be in the range of 0 to %d, inclusive \n", vps->getNumOutputLayerSets() - 1 );           
255              exit(EXIT_FAILURE);
256            }
257            m_targetDecLayerIdSet = vps->getTargetDecLayerIdList( m_targetOptLayerSetIdx ); 
[964]258          }
[1066]259          if (m_outputVpsInfo )
[872]260          {
[1066]261            m_vps->printScalabilityId();
262            m_vps->printLayerDependencies();
263            m_vps->printLayerSets();
264            m_vps->printPTL(); 
[872]265          }
[738]266        }
[872]267#if H_3D
268        if (nalu.m_nalUnitType == NAL_UNIT_VPS )
[884]269        {                 
[872]270          m_cCamParsCollector.init( m_pScaleOffsetFile, m_tDecTop[decIdx]->getPrefetchedVPS() );
271        }       
272#endif
[738]273        bNewPicture       = ( newSliceDiffLayer || newSliceDiffPoc ) && !sliceSkippedFlag; 
274        if ( nalu.isSlice() && firstSlice && !sliceSkippedFlag )       
[210]275        {
[608]276          layerIdCurrPic = nalu.m_layerId; 
277          pocCurrPic     = m_tDecTop[decIdx]->getCurrPoc(); 
278          decIdxCurrPic  = decIdx; 
279          firstSlice     = false; 
[210]280        }
[608]281
282        if ( bNewPicture || !bitstreamFile )
283        { 
[964]284          layerIdLastPic    = layerIdCurrPic; 
[608]285          layerIdCurrPic    = nalu.m_layerId; 
286          pocLastPic        = pocCurrPic; 
287          pocCurrPic        = m_tDecTop[decIdx]->getCurrPoc(); 
288          decIdxLastPic     = decIdxCurrPic; 
289          decIdxCurrPic     = decIdx; 
290          allLayersDecoded = ( pocCurrPic != pocLastPic );
[210]291        }
292#else
[608]293      if( (m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) || !isNaluWithinTargetDecLayerIdSet(&nalu)  )
[210]294      {
[655]295        bNewPicture = false;
[210]296      }
[608]297      else
[2]298      {
[608]299        bNewPicture = m_cTDecTop.decode(nalu, m_iSkipFrame, m_iPOCLastDisplay);
[56]300#endif
[608]301        if (bNewPicture)
[42]302        {
[56]303          bitstreamFile.clear();
304          /* location points to the current nalunit payload[1] due to the
305           * need for the annexB parser to read three extra bytes.
306           * [1] except for the first NAL unit in the file
307           *     (but bNewPicture doesn't happen then) */
308          bitstreamFile.seekg(location-streamoff(3));
309          bytestream.reset();
[872]310#if H_MV_ENC_DEC_TRAC
[608]311#if ENC_DEC_TRACE
312          const Bool resetCounter = false; 
313          if ( resetCounter )
314          {
315            g_nSymbolCounter  = symCount; // Only reset counter SH becomes traced twice
[210]316          }
[608]317          else
318          {
[872]319            g_disableHLSTrace = true;     // Tracing of second parsing of SH is not carried out
320          }     
[210]321#endif
[608]322#endif
[42]323        }
324      }
[56]325    }
[872]326    if (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS )
[56]327    {
[872]328      if (!loopFiltered || bitstreamFile)
329      {
[608]330#if H_MV
[872]331        assert( decIdxLastPic != -1 ); 
332        m_tDecTop[decIdxLastPic]->endPicDecoding(poc, pcListPic, m_targetDecLayerIdSet );
[964]333        xMarkForOutput( allLayersDecoded, poc, layerIdLastPic ); 
[608]334#else
[872]335        m_cTDecTop.executeLoopFilters(poc, pcListPic);
[608]336#endif
[872]337      }
338      loopFiltered = (nalu.m_nalUnitType == NAL_UNIT_EOS);
[56]339    }
[964]340#if !FIX_WRITING_OUTPUT
341#if SETTING_NO_OUT_PIC_PRIOR
342    if (bNewPicture && m_cTDecTop.getIsNoOutputPriorPics())
343    {
344      m_cTDecTop.checkNoOutputPriorPics( pcListPic );
345    }
346#endif
347#endif
[608]348#if H_3D
349    if ( allLayersDecoded || !bitstreamFile )
[56]350    {
[608]351      for( Int dI = 0; dI < m_numDecoders; dI++ )
352      {
353        TComPic* picLastCoded = m_ivPicLists.getPic( m_tDecTop[dI]->getLayerId(), pocLastPic );
354        assert( picLastCoded != NULL );       
355        picLastCoded->compressMotion(1);
356      }
357    }
358#endif
359
360    if( pcListPic )
361    {
362#if H_MV
363      if ( m_pchReconFiles[decIdxLastPic] && !m_reconOpen[decIdxLastPic] )
364#else
[655]365      if ( m_pchReconFile && !openedReconFile  )
[608]366#endif
[2]367      {
[608]368        if (!m_outputBitDepthY) { m_outputBitDepthY = g_bitDepthY; }
369        if (!m_outputBitDepthC) { m_outputBitDepthC = g_bitDepthC; }
370
371#if H_MV
372        m_tVideoIOYuvReconFile[decIdxLastPic]->open( m_pchReconFiles[decIdxLastPic], true, m_outputBitDepthY, m_outputBitDepthC, g_bitDepthY, g_bitDepthC ); // write mode
373        m_reconOpen[decIdxLastPic] = true;
[2]374      }
[964]375#if FIX_WRITING_OUTPUT
376      // write reconstruction to file
377      if( bNewPicture )
378      {
379        // Bumping after picture has been decoded
380#if ENC_DEC_TRACE
381        g_bJustDoIt = true; 
382        writeToTraceFile( "Bumping after decoding \n", g_decTracePicOutput  );         
383        g_bJustDoIt = false; 
384#endif
385        xWriteOutput( pcListPic, decIdxLastPic, nalu.m_temporalId );
386      }
387#if SETTING_NO_OUT_PIC_PRIOR
388      if ( (bNewPicture || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_CRA) && m_tDecTop[decIdxLastPic]->getNoOutputPriorPicsFlag() )
389      {
390        m_tDecTop[decIdxLastPic]->checkNoOutputPriorPics( pcListPic );
391        m_tDecTop[decIdxLastPic]->setNoOutputPriorPicsFlag (false);
392      }
393#endif
394#endif
[608]395      if ( bNewPicture && newSliceDiffPoc && 
396#else
397        m_cTVideoIOYuvReconFile.open( m_pchReconFile, true, m_outputBitDepthY, m_outputBitDepthC, g_bitDepthY, g_bitDepthC ); // write mode
[655]398        openedReconFile  = true;
[608]399      }
[964]400#if FIX_WRITING_OUTPUT
401      // write reconstruction to file
402      if( bNewPicture )
403      {
404        xWriteOutput( pcListPic, nalu.m_temporalId );
405      }
406#if SETTING_NO_OUT_PIC_PRIOR
407      if ( (bNewPicture || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_CRA) && m_cTDecTop.getNoOutputPriorPicsFlag() )
408      {
409        m_cTDecTop.checkNoOutputPriorPics( pcListPic );
410        m_cTDecTop.setNoOutputPriorPicsFlag (false);
411      }
412#endif
413#endif
[608]414      if ( bNewPicture && 
415#endif
416           (   nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL
417            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP
418            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_N_LP
419            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_RADL
420            || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_LP ) )
421      {
422#if H_MV
423        xFlushOutput( pcListPic, decIdxLastPic );
424#else
425        xFlushOutput( pcListPic );
426#endif
427      }
[872]428      if (nalu.m_nalUnitType == NAL_UNIT_EOS)
429      {
430#if H_MV
[964]431#if FIX_OUTPUT_EOS
432        xWriteOutput( pcListPic, decIdxLastPic, nalu.m_temporalId );
433#else
[872]434        xFlushOutput( pcListPic, decIdxLastPic );
[964]435#endif
[872]436#else
[964]437#if FIX_OUTPUT_EOS
438        xWriteOutput( pcListPic, nalu.m_temporalId );
439#else
[872]440        xFlushOutput( pcListPic );
441#endif
[964]442
443#endif
[872]444      }
[964]445      // write reconstruction to file -- for additional bumping as defined in C.5.2.3
446#if H_MV
447      // Above comment seems to be wrong
448#endif
449#if FIX_WRITING_OUTPUT
450      if(!bNewPicture && nalu.m_nalUnitType >= NAL_UNIT_CODED_SLICE_TRAIL_N && nalu.m_nalUnitType <= NAL_UNIT_RESERVED_VCL31)
451#else
[608]452      if(bNewPicture)
[964]453#endif
[2]454      {
[964]455#if H_MV       
456        // Bumping after reference picture set has been applied (here after first vcl nalu.
457#if ENC_DEC_TRACE
458        g_bJustDoIt = true; 
459        writeToTraceFile( "Bumping after reference picture set has been applied \n", g_decTracePicOutput  );         
460        g_bJustDoIt = false; 
461#endif
462
463        xWriteOutput( m_tDecTop[decIdxCurrPic]->getListPic(), decIdxCurrPic, nalu.m_temporalId );
464#else
465        xWriteOutput( pcListPic, nalu.m_temporalId );
466#endif
[2]467      }
468    }
[608]469  }
[964]470#if H_MV
[608]471#if H_3D
[57]472  if( m_cCamParsCollector.isInitialized() )
473  {
474    m_cCamParsCollector.setSlice( 0 );
475  }
[608]476#endif
477  for(UInt decIdx = 0; decIdx < m_numDecoders; decIdx++)
[2]478  {
[608]479    xFlushOutput( m_tDecTop[decIdx]->getListPic(), decIdx );
480  }
[964]481#else 
[608]482  xFlushOutput( pcListPic );
483  // delete buffers
484  m_cTDecTop.deletePicBuffer();
485#endif
486     
487  // destroy internal classes
[2]488  xDestroyDecLib();
489}
490
491// ====================================================================================================================
492// Protected member functions
493// ====================================================================================================================
494
[608]495Void TAppDecTop::xCreateDecLib()
496{
497#if H_MV
498  // initialize global variables
499  initROM(); 
500#if H_3D_DIM_DMM
501  initWedgeLists();
502#endif
503#else
504  // create decoder class
505  m_cTDecTop.create();
506#endif
507}
508
[2]509Void TAppDecTop::xDestroyDecLib()
510{
[608]511#if H_MV
512  // destroy ROM
513  destroyROM();
[2]514
[608]515  for(Int decIdx = 0; decIdx < m_numDecoders ; decIdx++)
[2]516  {
[608]517    if( m_tVideoIOYuvReconFile[decIdx] )
[56]518    {
[608]519      m_tVideoIOYuvReconFile[decIdx]->close();
520      delete m_tVideoIOYuvReconFile[decIdx]; 
521      m_tVideoIOYuvReconFile[decIdx] = NULL ;
[56]522    }
[2]523
[608]524    if( m_tDecTop[decIdx] )
[56]525    {
[608]526      m_tDecTop[decIdx]->deletePicBuffer();
527      m_tDecTop[decIdx]->destroy() ;
[56]528    }
[608]529    delete m_tDecTop[decIdx] ; 
530    m_tDecTop[decIdx] = NULL ;
[2]531  }
[608]532#else
533  if ( m_pchReconFile )
534  {
535    m_cTVideoIOYuvReconFile. close();
536  }
537 
538  // destroy decoder class
539  m_cTDecTop.destroy();
540#endif
541#if H_3D
[57]542  m_cCamParsCollector.uninit();
543  if( m_pScaleOffsetFile ) 
544  { 
545    ::fclose( m_pScaleOffsetFile ); 
546  }
[608]547#endif
[56]548}
[2]549
[608]550Void TAppDecTop::xInitDecLib()
[56]551{
[608]552#if !H_MV
553  // initialize decoder class
554  m_cTDecTop.init();
555  m_cTDecTop.setDecodedPictureHashSEIEnabled(m_decodedPictureHashSEIEnabled);
556#endif
557}
558
559/** \param pcListPic list of pictures to be written to file
560    \todo            DYN_REF_FREE should be revised
561 */
562#if H_MV
563Void TAppDecTop::xWriteOutput( TComList<TComPic*>* pcListPic, Int decIdx, Int tId )
564#else
565Void TAppDecTop::xWriteOutput( TComList<TComPic*>* pcListPic, UInt tId )
566#endif
567{
[872]568
569  if (pcListPic->empty())
570  {
571    return;
572  }
573
[56]574  TComList<TComPic*>::iterator iterPic   = pcListPic->begin();
[655]575  Int numPicsNotYetDisplayed = 0;
[964]576  Int dpbFullness = 0;
577#if H_MV
[1066]578  TComSPS* activeSPS = m_tDecTop[ decIdx ]->getActiveSPS();
579#else
[964]580  TComSPS* activeSPS = m_cTDecTop.getActiveSPS();
581#endif
582  UInt numReorderPicsHighestTid;
583  UInt maxDecPicBufferingHighestTid;
584  UInt maxNrSublayers = activeSPS->getMaxTLayers();
585
586  if(m_iMaxTemporalLayer == -1 || m_iMaxTemporalLayer >= maxNrSublayers)
587  {
588    numReorderPicsHighestTid = activeSPS->getNumReorderPics(maxNrSublayers-1);
589    maxDecPicBufferingHighestTid =  activeSPS->getMaxDecPicBuffering(maxNrSublayers-1); 
590  }
591  else
592  {
593    numReorderPicsHighestTid = activeSPS->getNumReorderPics(m_iMaxTemporalLayer);
594    maxDecPicBufferingHighestTid = activeSPS->getMaxDecPicBuffering(m_iMaxTemporalLayer); 
595  }
[655]596 
[56]597  while (iterPic != pcListPic->end())
[2]598  {
[56]599    TComPic* pcPic = *(iterPic);
[608]600#if H_MV
601    if(pcPic->getOutputMark() && pcPic->getPOC() > m_pocLastDisplay[decIdx])
602#else
603    if(pcPic->getOutputMark() && pcPic->getPOC() > m_iPOCLastDisplay)
604#endif
[56]605    {
[655]606      numPicsNotYetDisplayed++;
[964]607      dpbFullness++;
[56]608    }
[964]609    else if(pcPic->getSlice( 0 )->isReferenced())
610    {
611      dpbFullness++;
612    }
[56]613    iterPic++;
[2]614  }
[56]615  iterPic   = pcListPic->begin();
[655]616  if (numPicsNotYetDisplayed>2)
617  {
618    iterPic++;
619  }
[56]620 
[655]621  TComPic* pcPic = *(iterPic);
622  if (numPicsNotYetDisplayed>2 && pcPic->isField()) //Field Decoding
[2]623  {
[655]624    TComList<TComPic*>::iterator endPic   = pcListPic->end();
625    endPic--;
626    iterPic   = pcListPic->begin();
627    while (iterPic != endPic)
628    {
629      TComPic* pcPicTop = *(iterPic);
630      iterPic++;
631      TComPic* pcPicBottom = *(iterPic);
632     
[608]633#if H_MV
[655]634      if ( pcPicTop->getOutputMark() && (numPicsNotYetDisplayed >  pcPicTop->getNumReorderPics(tId) && !(pcPicTop->getPOC()%2) && pcPicBottom->getPOC() == pcPicTop->getPOC()+1)
635          && pcPicBottom->getOutputMark() && (numPicsNotYetDisplayed >  pcPicBottom->getNumReorderPics(tId) && (pcPicTop->getPOC() == m_pocLastDisplay[decIdx]+1 || m_pocLastDisplay[decIdx]<0)))
[608]636#else
[964]637      if ( pcPicTop->getOutputMark() && pcPicBottom->getOutputMark() &&
638          (numPicsNotYetDisplayed >  numReorderPicsHighestTid || dpbFullness > maxDecPicBufferingHighestTid) &&
639          (!(pcPicTop->getPOC()%2) && pcPicBottom->getPOC() == pcPicTop->getPOC()+1) &&
640          (pcPicTop->getPOC() == m_iPOCLastDisplay+1 || m_iPOCLastDisplay < 0))
[608]641#endif
[655]642      {
643        // write to file
644        numPicsNotYetDisplayed = numPicsNotYetDisplayed-2;
[608]645#if H_MV
646      if ( m_pchReconFiles[decIdx] )
647#else
[655]648        if ( m_pchReconFile )
[608]649#endif
[655]650        {
651          const Window &conf = pcPicTop->getConformanceWindow();
652          const Window &defDisp = m_respectDefDispWindow ? pcPicTop->getDefDisplayWindow() : Window();
653
654          const Bool isTff = pcPicTop->isTopField();
[608]655#if H_MV
[622]656        assert( conf   .getScaledFlag() );
657        assert( defDisp.getScaledFlag() );
[976]658#if ENC_DEC_TRACE
[964]659        g_bJustDoIt = true; 
660        writeToTraceFile( "OutputPic Poc"   , pcPic->getPOC    (), g_decTracePicOutput  ); 
661        writeToTraceFile( "OutputPic LayerId", pcPic->getLayerId(), g_decTracePicOutput );         
662        g_bJustDoIt = false; 
663#endif
[655]664        m_tVideoIOYuvReconFile[decIdx]->write( pcPicTop->getPicYuvRec(), pcPicBottom->getPicYuvRec(),
665#else
666          m_cTVideoIOYuvReconFile.write( pcPicTop->getPicYuvRec(), pcPicBottom->getPicYuvRec(),
[622]667#endif
[655]668                                        conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(),
669                                        conf.getWindowRightOffset() + defDisp.getWindowRightOffset(),
670                                        conf.getWindowTopOffset() + defDisp.getWindowTopOffset(),
671                                        conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(), isTff );
672        }
673       
674        // update POC of display order
675#if H_MV
676        m_pocLastDisplay[decIdx] = pcPic->getPOC();
[608]677#else
[655]678        m_iPOCLastDisplay = pcPicBottom->getPOC();
[608]679#endif
[655]680       
681        // erase non-referenced picture in the reference picture list after display
682        if ( !pcPicTop->getSlice(0)->isReferenced() && pcPicTop->getReconMark() == true )
683        {
684#if !DYN_REF_FREE
685          pcPicTop->setReconMark(false);
686         
687          // mark it should be extended later
688          pcPicTop->getPicYuvRec()->setBorderExtension( false );
689         
690#else
691          pcPicTop->destroy();
692          pcListPic->erase( iterPic );
693          iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised!
694          continue;
695#endif
696        }
697        if ( !pcPicBottom->getSlice(0)->isReferenced() && pcPicBottom->getReconMark() == true )
698        {
699#if !DYN_REF_FREE
700          pcPicBottom->setReconMark(false);
701         
702          // mark it should be extended later
703          pcPicBottom->getPicYuvRec()->setBorderExtension( false );
704         
705#else
706          pcPicBottom->destroy();
707          pcListPic->erase( iterPic );
708          iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised!
709          continue;
710#endif
711        }
712        pcPicTop->setOutputMark(false);
713        pcPicBottom->setOutputMark(false);
[56]714      }
[655]715    }
716  }
717  else if (!pcPic->isField()) //Frame Decoding
718  {
719    iterPic = pcListPic->begin();
720    while (iterPic != pcListPic->end())
721    {
722      pcPic = *(iterPic);
723
[608]724#if H_MV
[964]725      if(pcPic->getOutputMark() && pcPic->getPOC() > m_pocLastDisplay[decIdx] &&
726        (numPicsNotYetDisplayed >  numReorderPicsHighestTid || dpbFullness > maxDecPicBufferingHighestTid))
[655]727#else     
[964]728      if(pcPic->getOutputMark() && pcPic->getPOC() > m_iPOCLastDisplay &&
729        (numPicsNotYetDisplayed >  numReorderPicsHighestTid || dpbFullness > maxDecPicBufferingHighestTid))
[655]730#endif
731      {
732        // write to file
733        numPicsNotYetDisplayed--;
[964]734        if(pcPic->getSlice(0)->isReferenced() == false)
735        {
736          dpbFullness--;
737        }
[655]738#if H_MV
739      if ( m_pchReconFiles[decIdx] )
[608]740#else
[655]741        if ( m_pchReconFile )
[608]742#endif
[655]743        {
744          const Window &conf = pcPic->getConformanceWindow();
745          const Window &defDisp = m_respectDefDispWindow ? pcPic->getDefDisplayWindow() : Window();
746#if H_MV
747        assert( conf   .getScaledFlag() );
748        assert( defDisp.getScaledFlag() );
[964]749#if ENC_DEC_TRACE
750        g_bJustDoIt = true; 
751        writeToTraceFile( "OutputPic Poc"   , pcPic->getPOC    (), g_decTracePicOutput  ); 
752        writeToTraceFile( "OutputPic LayerId", pcPic->getLayerId(), g_decTracePicOutput );         
753        g_bJustDoIt = false; 
754#endif
[655]755        m_tVideoIOYuvReconFile[decIdx]->write( pcPic->getPicYuvRec(),
756#else
757          m_cTVideoIOYuvReconFile.write( pcPic->getPicYuvRec(),
758#endif
759                                        conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(),
760                                        conf.getWindowRightOffset() + defDisp.getWindowRightOffset(),
761                                        conf.getWindowTopOffset() + defDisp.getWindowTopOffset(),
762                                        conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset() );
763        }
[56]764       
[655]765        // update POC of display order
766#if H_MV
767        m_pocLastDisplay[decIdx] = pcPic->getPOC();
768#else
769        m_iPOCLastDisplay = pcPic->getPOC();
770#endif
[56]771       
[655]772        // erase non-referenced picture in the reference picture list after display
773        if ( !pcPic->getSlice(0)->isReferenced() && pcPic->getReconMark() == true )
774        {
775#if !DYN_REF_FREE
776          pcPic->setReconMark(false);
777         
778          // mark it should be extended later
779          pcPic->getPicYuvRec()->setBorderExtension( false );
780         
[56]781#else
[655]782          pcPic->destroy();
783          pcListPic->erase( iterPic );
784          iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised!
785          continue;
[56]786#endif
[655]787        }
788        pcPic->setOutputMark(false);
[976]789#if H_MV
[964]790        pcPic->setPicOutputFlag(false);
791#endif
[56]792      }
[655]793     
794      iterPic++;
[56]795    }
[2]796  }
797}
798/** \param pcListPic list of pictures to be written to file
799    \todo            DYN_REF_FREE should be revised
800 */
[608]801#if H_MV
802Void TAppDecTop::xFlushOutput( TComList<TComPic*>* pcListPic, Int decIdx )
803#else
804Void TAppDecTop::xFlushOutput( TComList<TComPic*>* pcListPic )
805#endif
[2]806{
[872]807  if(!pcListPic || pcListPic->empty())
[56]808  {
809    return;
[655]810  }
[2]811  TComList<TComPic*>::iterator iterPic   = pcListPic->begin();
[655]812 
[56]813  iterPic   = pcListPic->begin();
[655]814  TComPic* pcPic = *(iterPic);
[56]815 
[655]816  if (pcPic->isField()) //Field Decoding
[2]817  {
[655]818    TComList<TComPic*>::iterator endPic   = pcListPic->end();
819    endPic--;
820    TComPic *pcPicTop, *pcPicBottom = NULL;
821    while (iterPic != endPic)
[2]822    {
[655]823      pcPicTop = *(iterPic);
824      iterPic++;
825      pcPicBottom = *(iterPic);
826     
827      if ( pcPicTop->getOutputMark() && pcPicBottom->getOutputMark() && !(pcPicTop->getPOC()%2) && (pcPicBottom->getPOC() == pcPicTop->getPOC()+1) )
828      {
829        // write to file
[608]830#if H_MV
831      if ( m_pchReconFiles[decIdx] )
832#else
[655]833        if ( m_pchReconFile )
[608]834#endif
[655]835        {
836          const Window &conf = pcPicTop->getConformanceWindow();
837          const Window &defDisp = m_respectDefDispWindow ? pcPicTop->getDefDisplayWindow() : Window();
838          const Bool isTff = pcPicTop->isTopField();
[608]839#if H_MV
[622]840        assert( conf   .getScaledFlag() );
841        assert( defDisp.getScaledFlag() );
[964]842#if ENC_DEC_TRACE
843        g_bJustDoIt = true; 
844        writeToTraceFile( "OutputPic Poc"   , pcPic->getPOC    (), g_decTracePicOutput  ); 
845        writeToTraceFile( "OutputPic LayerId", pcPic->getLayerId(), g_decTracePicOutput );         
846        g_bJustDoIt = false; 
847#endif
[655]848        m_tVideoIOYuvReconFile[decIdx]->write( pcPicTop->getPicYuvRec(), pcPicBottom->getPicYuvRec(),
849#else
850          m_cTVideoIOYuvReconFile.write( pcPicTop->getPicYuvRec(), pcPicBottom->getPicYuvRec(),
[622]851#endif
[655]852                                        conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(),
853                                        conf.getWindowRightOffset() + defDisp.getWindowRightOffset(),
854                                        conf.getWindowTopOffset() + defDisp.getWindowTopOffset(),
855                                        conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(), isTff );
856        }
857       
858        // update POC of display order
859#if H_MV
860      m_pocLastDisplay[decIdx] = pcPic->getPOC();
[608]861#else
[655]862      m_iPOCLastDisplay = pcPicBottom->getPOC();
863#endif       
864        // erase non-referenced picture in the reference picture list after display
865        if ( !pcPicTop->getSlice(0)->isReferenced() && pcPicTop->getReconMark() == true )
866        {
867#if !DYN_REF_FREE
868          pcPicTop->setReconMark(false);
869         
870          // mark it should be extended later
871          pcPicTop->getPicYuvRec()->setBorderExtension( false );
872         
873#else
874          pcPicTop->destroy();
875          pcListPic->erase( iterPic );
876          iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised!
877          continue;
[608]878#endif
[655]879        }
880        if ( !pcPicBottom->getSlice(0)->isReferenced() && pcPicBottom->getReconMark() == true )
881        {
882#if !DYN_REF_FREE
883          pcPicBottom->setReconMark(false);
884         
885          // mark it should be extended later
886          pcPicBottom->getPicYuvRec()->setBorderExtension( false );
887         
888#else
889          pcPicBottom->destroy();
890          pcListPic->erase( iterPic );
891          iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised!
892          continue;
893#endif
894        }
895        pcPicTop->setOutputMark(false);
896        pcPicBottom->setOutputMark(false);
897       
898#if !DYN_REF_FREE
899        if(pcPicTop)
900        {
901          pcPicTop->destroy();
902          delete pcPicTop;
903          pcPicTop = NULL;
904        }
905#endif
[2]906      }
[655]907    }
908    if(pcPicBottom)
909    {
910      pcPicBottom->destroy();
911      delete pcPicBottom;
912      pcPicBottom = NULL;
913    }
914  }
915  else //Frame decoding
916  {
917    while (iterPic != pcListPic->end())
918    {
919      pcPic = *(iterPic);
[56]920     
[655]921      if ( pcPic->getOutputMark() )
922      {
923        // write to file
[608]924#if H_MV
[655]925      if ( m_pchReconFiles[decIdx] )
926#else
927        if ( m_pchReconFile )
928#endif
929        {
930          const Window &conf = pcPic->getConformanceWindow();
931          const Window &defDisp = m_respectDefDispWindow ? pcPic->getDefDisplayWindow() : Window();
932#if H_MV
933        assert( conf   .getScaledFlag() );
934        assert( defDisp.getScaledFlag() );
[964]935#if ENC_DEC_TRACE
936        g_bJustDoIt = true; 
937        writeToTraceFile( "OutputPic Poc"   , pcPic->getPOC    (), g_decTracePicOutput  ); 
938        writeToTraceFile( "OutputPic LayerId", pcPic->getLayerId(), g_decTracePicOutput );         
939        g_bJustDoIt = false; 
940#endif
[655]941        m_tVideoIOYuvReconFile[decIdx]->write( pcPic->getPicYuvRec(),
942#else
943          m_cTVideoIOYuvReconFile.write( pcPic->getPicYuvRec(),
944#endif
945                                        conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(),
946                                        conf.getWindowRightOffset() + defDisp.getWindowRightOffset(),
947                                        conf.getWindowTopOffset() + defDisp.getWindowTopOffset(),
948                                        conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset() );
949        }
950       
951        // update POC of display order
952#if H_MV
[608]953      m_pocLastDisplay[decIdx] = pcPic->getPOC();
954#else
[655]955        m_iPOCLastDisplay = pcPic->getPOC();
[608]956#endif
[655]957       
958        // erase non-referenced picture in the reference picture list after display
959        if ( !pcPic->getSlice(0)->isReferenced() && pcPic->getReconMark() == true )
960        {
[56]961#if !DYN_REF_FREE
[655]962          pcPic->setReconMark(false);
963         
964          // mark it should be extended later
965          pcPic->getPicYuvRec()->setBorderExtension( false );
966         
[56]967#else
[655]968          pcPic->destroy();
969          pcListPic->erase( iterPic );
970          iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised!
971          continue;
[56]972#endif
[655]973        }
974        pcPic->setOutputMark(false);
[976]975#if H_MV
[964]976        pcPic->setPicOutputFlag(false);
977#endif
[2]978      }
[608]979#if !H_MV
980#if !DYN_REF_FREE
[655]981      if(pcPic)
982      {
983        pcPic->destroy();
984        delete pcPic;
985        pcPic = NULL;
986      }
987#endif   
988#endif
989      iterPic++;
[608]990    }
[2]991  }
[608]992#if H_MV
993  m_pocLastDisplay[decIdx] = -MAX_INT;
994#else
[56]995  pcListPic->clear();
[608]996  m_iPOCLastDisplay = -MAX_INT;
997#endif
[2]998}
[608]999
1000/** \param nalu Input nalu to check whether its LayerId is within targetDecLayerIdSet
1001 */
1002Bool TAppDecTop::isNaluWithinTargetDecLayerIdSet( InputNALUnit* nalu )
[2]1003{
[608]1004  if ( m_targetDecLayerIdSet.size() == 0 ) // By default, the set is empty, meaning all LayerIds are allowed
[2]1005  {
[608]1006    return true;
[2]1007  }
[608]1008  for (std::vector<Int>::iterator it = m_targetDecLayerIdSet.begin(); it != m_targetDecLayerIdSet.end(); it++)
1009  {
1010#if H_MV
1011    if ( nalu->m_layerId == (*it) )
[81]1012#else
[608]1013    if ( nalu->m_reservedZero6Bits == (*it) )
[81]1014#endif
[56]1015    {
[608]1016      return true;
[56]1017    }
1018  }
[608]1019  return false;
[2]1020}
1021
[608]1022#if H_MV
1023Int TAppDecTop::xGetDecoderIdx( Int layerId, Bool createFlag /*= false */ )
1024{
1025  Int decIdx = -1; 
[738]1026
1027  if ( layerId > MAX_NUM_LAYER_IDS-1 ) 
1028  {
1029    return decIdx; 
1030  }
1031
[608]1032  if ( m_layerIdToDecIdx[ layerId ] != -1 ) 
1033  {     
1034    decIdx = m_layerIdToDecIdx[ layerId ]; 
[210]1035  }
1036  else
[608]1037  {     
1038    assert ( createFlag ); 
1039    assert( m_numDecoders < MAX_NUM_LAYERS ); 
[210]1040
[608]1041    decIdx = m_numDecoders; 
1042
1043    // Init decoder
1044    m_tDecTop[ decIdx ] =  new TDecTop;
1045    m_tDecTop[ decIdx ]->create();
1046    m_tDecTop[ decIdx ]->init( );
1047    m_tDecTop[ decIdx ]->setLayerId( layerId );
1048    m_tDecTop[ decIdx ]->setDecodedPictureHashSEIEnabled(m_decodedPictureHashSEIEnabled);
1049    m_tDecTop[ decIdx ]->setIvPicLists( &m_ivPicLists ); 
[738]1050    m_tDecTop[ decIdx ]->setLayerInitilizedFlags( m_layerInitilizedFlags );
[964]1051    m_tDecTop[ decIdx ]->setTargetOptLayerSetIdx( m_targetOptLayerSetIdx );   
[738]1052
[608]1053#if H_3D
1054   m_tDecTop[ decIdx ]->setCamParsCollector( &m_cCamParsCollector );
[210]1055#endif
[2]1056
[608]1057    // append pic list of new decoder to PicLists
1058    assert( m_ivPicLists.size() == m_numDecoders );
1059    m_ivPicLists.push_back( m_tDecTop[ decIdx ]->getListPic() );
[2]1060
[608]1061    // create recon file related stuff     
1062    Char* pchTempFilename = NULL;
1063    if ( m_pchReconFile )
1064    {     
1065      Char buffer[4];     
1066      sprintf(buffer,"_%i", layerId );
1067      assert ( m_pchReconFile ); 
1068      xAppendToFileNameEnd( m_pchReconFile , buffer, pchTempFilename );
1069      assert( m_pchReconFiles.size() == m_numDecoders );
[2]1070    }
[210]1071
[608]1072    m_pchReconFiles.push_back( pchTempFilename );   
[296]1073
[608]1074    m_tVideoIOYuvReconFile[ decIdx ] = new TVideoIOYuv;
1075    m_reconOpen           [ decIdx ] = false;
[443]1076
[608]1077    // set others
1078    m_pocLastDisplay      [ decIdx ] = -MAX_INT;
1079    m_layerIdToDecIdx     [ layerId ] = decIdx; 
[296]1080
[608]1081    m_numDecoders++; 
1082  };
1083  return decIdx;
[964]1084
[296]1085}
[964]1086
1087Void TAppDecTop::xMarkForOutput( Bool allLayersDecoded, Int pocLastPic, Int layerIdLastPic )
1088{ 
1089  vector<Int> targetOptLayerIdList = m_vps->getTargetOptLayerIdList( m_targetOptLayerSetIdx );
1090
1091  if (m_vps->getAltOutputLayerFlagVar( m_targetOptLayerSetIdx ) )
1092  {
1093    assert( targetOptLayerIdList.size() == 1 ); 
1094    Int targetLayerId = targetOptLayerIdList[0];     
1095
1096    TComPic* curPic = m_ivPicLists.getPic( layerIdLastPic, pocLastPic );
1097    assert( curPic != NULL );
1098
1099    if ( layerIdLastPic == targetLayerId )
1100    {
1101      if ( curPic->getPicOutputFlag() )
1102      {
1103        curPic->setOutputMark( true );
1104      }
1105      else
1106      {       
1107        xMarkAltOutPic( targetLayerId, pocLastPic ); 
1108      }
1109      m_markedForOutput = true; 
1110    }
1111    else if ( ( layerIdLastPic > targetLayerId || allLayersDecoded ) && !m_markedForOutput )
1112    {
1113      xMarkAltOutPic( targetLayerId, pocLastPic );
1114    }
1115
1116    if ( allLayersDecoded )
1117    {
1118      m_markedForOutput = false; 
1119    }
1120  }
1121  else
1122  { 
1123    for( Int dI = 0; dI < m_numDecoders; dI++ )
1124    {     
1125      Int layerId = m_tDecTop[dI]->getLayerId(); 
1126      TComPic* curPic = m_ivPicLists.getPic( layerId, pocLastPic );
1127      if ( curPic != NULL )
1128      {
1129        if ( curPic->getReconMark() )
1130        {
1131          Bool isTargetOptLayer = std::find(targetOptLayerIdList.begin(), targetOptLayerIdList.end(), layerId) != targetOptLayerIdList.end();
1132          curPic->setOutputMark( isTargetOptLayer ? curPic->getPicOutputFlag() : false ); 
1133        }
1134      }
1135    }
1136  }
1137}
[976]1138
1139Void TAppDecTop::xMarkAltOutPic( Int targetOutputLayer, Int pocLastPic )
1140{
1141  Int optLayerIdxInVps = m_vps->getLayerIdInNuh( targetOutputLayer ); 
1142  Int highestNuhLayerId = -1; 
1143  TComPic* picWithHighestNuhLayerId = NULL; 
1144  for (Int dIdx = 0; dIdx < m_numDecoders; dIdx++)
1145  {
1146    Int curLayerId = m_tDecTop[dIdx]->getLayerId();
1147    Int curLayerIdxInVps = m_vps->getLayerIdInNuh( curLayerId  ); 
[1066]1148    if ( m_vps->getDependencyFlag(optLayerIdxInVps, curLayerIdxInVps ) )
[976]1149    {
1150      TComPic* curPic = m_ivPicLists.getPic( curLayerId, pocLastPic ); 
1151      if (curPic != NULL)
1152      {
1153        if (curPic->getReconMark() && curPic->getPicOutputFlag() )
1154        {
1155          curPic->setOutputMark   ( false ); 
1156          curPic->setPicOutputFlag( false ); 
1157          if ( curLayerId > highestNuhLayerId)
1158          {
1159            highestNuhLayerId = curLayerId ; 
1160            picWithHighestNuhLayerId = curPic; 
1161          }           
1162        }
1163      }
1164    }
1165  }
1166  if ( picWithHighestNuhLayerId != NULL )
1167  {
1168    picWithHighestNuhLayerId->setPicOutputFlag(true); 
1169    picWithHighestNuhLayerId->setOutputMark   (true); 
1170  }
1171}
1172
[296]1173#endif
[56]1174//! \}
Note: See TracBrowser for help on using the repository browser.