source: 3DVCSoftware/branches/0.3-poznan-univ/source/App/TAppRenderer/TAppRendererTop.cpp @ 461

Last change on this file since 461 was 48, checked in by poznan-univ, 13 years ago

some bug fix on high level syntax
fixed some compiler warning issues under windows and linux

  • Property svn:eol-style set to native
File size: 35.2 KB
Line 
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
4 * granted under this license.
5 *
6 * Copyright (c) 2010-2011, ISO/IEC
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.
17 *  * Neither the name of the ISO/IEC nor the names of its contributors may
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 */
33
34
35
36#include <list>
37#include <stdio.h>
38#include <fcntl.h>
39#include <assert.h>
40#include <math.h>
41
42#include "TAppRendererTop.h"
43
44// ====================================================================================================================
45// Constructor / destructor / initialization / destroy
46// ====================================================================================================================
47
48TAppRendererTop::TAppRendererTop()
49{
50
51}
52
53TAppRendererTop::~TAppRendererTop()
54{
55
56}
57
58
59Void TAppRendererTop::xCreateLib()
60{
61  Int iInteralBitDepth = g_uiBitDepth + g_uiBitIncrement;
62  Int iFileBitDepth    = 8;
63  m_pcRenTop = new TRenTop();
64
65  for(Int iViewIdx=0; iViewIdx<m_iNumberOfInputViews; iViewIdx++)
66  {
67    TVideoIOYuv* pcVideoInput = new TVideoIOYuv;
68    TVideoIOYuv* pcDepthInput = new TVideoIOYuv;
69
70    pcVideoInput->open( m_pchVideoInputFileList[iViewIdx], false, iFileBitDepth, iInteralBitDepth );  // read mode
71    pcDepthInput->open( m_pchDepthInputFileList[iViewIdx], false, iFileBitDepth, iInteralBitDepth );  // read mode
72
73    m_apcTVideoIOYuvVideoInput.push_back( pcVideoInput );
74    m_apcTVideoIOYuvDepthInput.push_back( pcDepthInput );
75  }
76
77  for(Int iViewIdx=0; iViewIdx<m_iNumberOfOutputViews; iViewIdx++)
78  {
79    TVideoIOYuv* pcSynthOutput = new TVideoIOYuv;
80    pcSynthOutput->open( m_pchSynthOutputFileList[iViewIdx], true, iFileBitDepth, iInteralBitDepth );  // write mode
81    m_apcTVideoIOYuvSynthOutput.push_back( pcSynthOutput );
82  }
83}
84
85
86Void TAppRendererTop::xDestroyLib()
87{
88  delete m_pcRenTop;
89
90  for ( Int iViewIdx = 0; iViewIdx < m_iNumberOfInputViews; iViewIdx++ )
91  {
92    m_apcTVideoIOYuvVideoInput[iViewIdx]->close();
93    m_apcTVideoIOYuvDepthInput[iViewIdx]->close();
94
95    delete m_apcTVideoIOYuvDepthInput[iViewIdx];
96    delete m_apcTVideoIOYuvVideoInput[iViewIdx];
97  };
98
99  for ( Int iViewIdx = 0; iViewIdx < m_iNumberOfOutputViews; iViewIdx++ )
100  {
101    m_apcTVideoIOYuvSynthOutput[iViewIdx]->close();
102    delete m_apcTVideoIOYuvSynthOutput[iViewIdx];
103  };
104}
105
106Void TAppRendererTop::xInitLib()
107{
108    m_pcRenTop->init(
109    m_iSourceWidth,
110    m_iSourceHeight,
111    (m_iRenderDirection != 0),
112    m_iLog2SamplingFactor,
113    m_iLog2SamplingFactor+m_iShiftPrecision,
114    m_bUVUp,
115    m_iPreProcMode,
116    m_iPreFilterSize,
117    m_iBlendMode,
118    m_iBlendZThresPerc,
119    m_bBlendUseDistWeight,
120    m_iBlendHoleMargin,
121    m_iInterpolationMode,
122    m_iHoleFillingMode,
123    m_iPostProcMode,
124    m_iUsedPelMapMarExt
125    );
126}
127
128// ====================================================================================================================
129// Public member functions
130// ====================================================================================================================
131
132
133
134Void TAppRendererTop::render()
135{
136  xCreateLib();
137  xInitLib();
138
139  // Create Buffers Input Views;
140  std::vector<TComPicYuv*> apcPicYuvBaseVideo;
141  std::vector<TComPicYuv*> apcPicYuvBaseDepth;
142
143  // TemporalImprovement Filter
144  std::vector<TComPicYuv*> apcPicYuvLastBaseVideo;
145  std::vector<TComPicYuv*> apcPicYuvLastBaseDepth;
146
147  Int aiPad[2] = { 0, 0 };
148
149  for ( UInt uiBaseView = 0; uiBaseView < m_iNumberOfInputViews; uiBaseView++ )
150  {
151    TComPicYuv* pcNewVideoPic = new TComPicYuv;
152    TComPicYuv* pcNewDepthPic = new TComPicYuv;
153
154    pcNewVideoPic->create( m_iSourceWidth, m_iSourceHeight, 1, 1, 1 );
155    apcPicYuvBaseVideo.push_back(pcNewVideoPic);
156
157    pcNewDepthPic->create( m_iSourceWidth, m_iSourceHeight, 1, 1, 1 );
158    apcPicYuvBaseDepth.push_back(pcNewDepthPic);
159
160    //Temporal improvement Filter
161    if ( m_bTempDepthFilter )
162    {
163      pcNewVideoPic = new TComPicYuv;
164      pcNewDepthPic = new TComPicYuv;
165
166      pcNewVideoPic->create( m_iSourceWidth, m_iSourceHeight, 1, 1, 1 );
167      apcPicYuvLastBaseVideo.push_back(pcNewVideoPic);
168
169      pcNewDepthPic->create( m_iSourceWidth, m_iSourceHeight, 1, 1, 1 );
170      apcPicYuvLastBaseDepth.push_back(pcNewDepthPic);
171    }
172  }
173
174  // Create Buffer for synthesized View
175  TComPicYuv* pcPicYuvSynthOut = new TComPicYuv;
176  pcPicYuvSynthOut->create( m_iSourceWidth, m_iSourceHeight, 1, 1, 1 );
177
178  Bool bAnyEOS = false;
179
180  Int iNumOfRenderedFrames = 0;
181  Int iFrame = 0;
182
183  while ( ( ( iNumOfRenderedFrames < m_iFramesToBeRendered ) || ( m_iFramesToBeRendered == 0 ) ) && !bAnyEOS )
184  {
185
186    // read in depth and video
187    for(Int iBaseViewIdx=0; iBaseViewIdx < m_iNumberOfInputViews; iBaseViewIdx++ )
188    {
189      m_apcTVideoIOYuvVideoInput[iBaseViewIdx]->read( apcPicYuvBaseVideo[iBaseViewIdx], aiPad  ) ;
190      apcPicYuvBaseVideo[iBaseViewIdx]->extendPicBorder();
191      bAnyEOS |= m_apcTVideoIOYuvVideoInput[iBaseViewIdx]->isEof();
192
193      m_apcTVideoIOYuvDepthInput[iBaseViewIdx]->read( apcPicYuvBaseDepth[iBaseViewIdx], aiPad  ) ;
194      apcPicYuvBaseDepth[iBaseViewIdx]->extendPicBorder();
195      bAnyEOS |= m_apcTVideoIOYuvDepthInput[iBaseViewIdx]->isEof();
196
197      if ( m_bTempDepthFilter && (iFrame >= m_iFrameSkip) )
198      {
199        m_pcRenTop->temporalFilterVSRS( apcPicYuvBaseVideo[iBaseViewIdx], apcPicYuvBaseDepth[iBaseViewIdx], apcPicYuvLastBaseVideo[iBaseViewIdx], apcPicYuvLastBaseDepth[iBaseViewIdx], ( iFrame == m_iFrameSkip) );
200      }
201    }
202
203    if ( iFrame < m_iFrameSkip ) // Skip Frames
204    {
205      std::cout << "Skipping Frame " << iFrame << std::endl;
206
207      iFrame++;
208      continue;
209    }
210
211    m_cCameraData.update( (UInt)iFrame );
212
213    for(Int iSynthViewIdx=0; iSynthViewIdx < m_iNumberOfOutputViews; iSynthViewIdx++ )
214    {
215      Int  iLeftBaseViewIdx  = -1;
216      Int  iRightBaseViewIdx = -1;
217
218      Bool bIsBaseView = false;
219
220      Int iRelDistToLeft;
221      Bool bHasLRView = m_cCameraData.getLeftRightBaseView( iSynthViewIdx, iLeftBaseViewIdx, iRightBaseViewIdx, iRelDistToLeft, bIsBaseView );
222      Bool bHasLView = ( iLeftBaseViewIdx != -1 );
223      Bool bHasRView = ( iRightBaseViewIdx != -1 );
224      Bool bRender   = true;
225
226      Int  iBlendMode = m_iBlendMode;
227      Int  iSimEnhBaseView = 0;
228
229      switch( m_iRenderDirection )
230      {
231      /// INTERPOLATION
232      case 0:
233        AOF( bHasLRView || bIsBaseView );
234
235        if ( !bHasLRView && bIsBaseView && m_iBlendMode == 0 )
236        {
237          bRender = false;
238        }
239        else
240        {
241          if ( bIsBaseView )
242          {
243            AOF( iLeftBaseViewIdx == iRightBaseViewIdx );
244            Int iSortedBaseViewIdx = m_cCameraData.getBaseId2SortedId() [iLeftBaseViewIdx];
245
246            if ( m_iBlendMode == 1 )
247            {
248              if ( iSortedBaseViewIdx - 1 >= 0 )
249              {
250                iLeftBaseViewIdx = m_cCameraData.getBaseSortedId2Id()[ iSortedBaseViewIdx - 1];
251                bRender = true;
252              }
253              else
254              {
255                bRender = false;
256              }
257            }
258            else if ( m_iBlendMode == 2 )
259            {
260              if ( iSortedBaseViewIdx + 1 < m_iNumberOfInputViews )
261              {
262                iRightBaseViewIdx = m_cCameraData.getBaseSortedId2Id()[ iSortedBaseViewIdx + 1];
263                bRender = true;
264              }
265              else
266              {
267                bRender = false;
268              }
269            }
270          }
271
272          if ( m_iBlendMode == 3 )
273          {
274            if ( bIsBaseView && (iLeftBaseViewIdx == 0) )
275            {
276              bRender = false;
277            }
278            else
279            {
280              Int iDistLeft  = abs( m_cCameraData.getBaseId2SortedId()[0] - m_cCameraData.getBaseId2SortedId() [iLeftBaseViewIdx ]  );
281              Int iDistRight = abs( m_cCameraData.getBaseId2SortedId()[0] - m_cCameraData.getBaseId2SortedId() [iRightBaseViewIdx]  );
282
283              Int iFillViewIdx = iDistLeft > iDistRight ? iLeftBaseViewIdx : iRightBaseViewIdx;
284
285              if( m_cCameraData.getBaseId2SortedId()[0] < m_cCameraData.getBaseId2SortedId() [iFillViewIdx] )
286              {
287                iBlendMode        = 1;
288                iLeftBaseViewIdx  = 0;
289                iRightBaseViewIdx = iFillViewIdx;
290               
291              }
292              else
293              {
294                iBlendMode        = 2;
295                iLeftBaseViewIdx  = iFillViewIdx;
296                iRightBaseViewIdx = 0;
297              }
298
299            }
300          }
301#if POZNAN_ENCODE_ONLY_DISOCCLUDED_CU
302          else if ( m_iBlendMode == 4 )
303          {
304            if ( bIsBaseView && (iLeftBaseViewIdx == 0) )
305            {
306              bRender = false;
307            }
308            else
309            {
310              //Int iDistLeft  = abs( m_cCameraData.getBaseId2SortedId()[0] - m_cCameraData.getBaseId2SortedId() [iLeftBaseViewIdx ]  );
311              //Int iDistRight = abs( m_cCameraData.getBaseId2SortedId()[0] - m_cCameraData.getBaseId2SortedId() [iRightBaseViewIdx]  );
312
313              Int iFillViewIdx = (0!=iLeftBaseViewIdx)? iLeftBaseViewIdx: iRightBaseViewIdx;
314
315              if( m_cCameraData.getBaseId2SortedId()[0] < m_cCameraData.getBaseId2SortedId() [iFillViewIdx] )
316              {
317                iBlendMode        = 0;
318                iLeftBaseViewIdx  = 0;
319                iRightBaseViewIdx = iFillViewIdx;
320                std::cout << "iBlen: " << iBlendMode << "iLeft: " << iLeftBaseViewIdx << "iRight: " << iRightBaseViewIdx <<std::endl;
321              }
322              else
323              {
324                iBlendMode        = 0;
325                iLeftBaseViewIdx  = iFillViewIdx;
326                iRightBaseViewIdx = 0;
327                std::cout << "iBlen: " << iBlendMode << "iLeft: " << iLeftBaseViewIdx << "iRight: " << iRightBaseViewIdx <<std::endl;
328              }
329
330            }
331          }
332#endif
333          else
334          {
335            iBlendMode = m_iBlendMode;
336          }
337        }
338
339        if ( m_bSimEnhance )
340        {
341          if ( m_iNumberOfInputViews == 3 && m_cCameraData.getRelSynthViewNumbers()[ iSynthViewIdx ] < VIEW_NUM_PREC  )
342          {
343            iSimEnhBaseView = 2; // Take middle view
344          }
345          else
346          {
347            iSimEnhBaseView = 1; // Take left view
348          }
349        }
350
351          if ( bRender )
352          {
353          std::cout << "Rendering Frame "    << iFrame
354                    << " of View "           << (Double) m_cCameraData.getSynthViewNumbers()[iSynthViewIdx    ] / VIEW_NUM_PREC
355                    << "   Left BaseView: "  << (Double) m_cCameraData.getBaseViewNumbers() [iLeftBaseViewIdx ] / VIEW_NUM_PREC
356                    << "   Right BaseView: " << (Double) m_cCameraData.getBaseViewNumbers() [iRightBaseViewIdx] / VIEW_NUM_PREC
357                    << "   BlendMode: "      << iBlendMode
358                    << std::endl;
359
360          m_pcRenTop->setShiftLUTs(
361            m_cCameraData.getSynthViewShiftLUTD()[iLeftBaseViewIdx ][iSynthViewIdx],
362            m_cCameraData.getSynthViewShiftLUTI()[iLeftBaseViewIdx ][iSynthViewIdx],
363            m_cCameraData.getBaseViewShiftLUTI ()[iLeftBaseViewIdx ][iRightBaseViewIdx],
364            m_cCameraData.getSynthViewShiftLUTD()[iRightBaseViewIdx][iSynthViewIdx],
365            m_cCameraData.getSynthViewShiftLUTI()[iRightBaseViewIdx][iSynthViewIdx],
366            m_cCameraData.getBaseViewShiftLUTI ()[iRightBaseViewIdx][iLeftBaseViewIdx ],
367
368            iRelDistToLeft
369          );
370
371          m_pcRenTop->interpolateView(
372            apcPicYuvBaseVideo[iLeftBaseViewIdx ],
373            apcPicYuvBaseDepth[iLeftBaseViewIdx ],
374            apcPicYuvBaseVideo[iRightBaseViewIdx],
375            apcPicYuvBaseDepth[iRightBaseViewIdx],
376            pcPicYuvSynthOut,
377            iBlendMode,
378            iSimEnhBaseView
379            );
380        }
381        else
382        {
383          AOT(iLeftBaseViewIdx != iRightBaseViewIdx );
384          apcPicYuvBaseVideo[iLeftBaseViewIdx]->copyToPic( pcPicYuvSynthOut );
385          std::cout << "Copied    Frame " << iFrame
386                    << " of View "        << (Double) m_cCameraData.getSynthViewNumbers()[iSynthViewIdx] / VIEW_NUM_PREC
387                    << "   (BaseView)  "    << std::endl;
388        }
389
390        break;
391      /// EXTRAPOLATION FROM LEFT
392      case 1:
393        if ( !bHasLView ) // View to render is BaseView
394        {
395          bRender = false;
396        }
397
398          if (  bIsBaseView )
399          {
400          AOF( iLeftBaseViewIdx == iRightBaseViewIdx );
401          Int iSortedBaseViewIdx = m_cCameraData.getBaseId2SortedId() [iLeftBaseViewIdx];
402          if ( iSortedBaseViewIdx - 1 >= 0 )
403          {
404            iLeftBaseViewIdx = m_cCameraData.getBaseSortedId2Id()[ iSortedBaseViewIdx - 1];
405          }
406          else
407          {
408            std::cout << "Copied    Frame " << iFrame << " of BaseView " << (Double) m_cCameraData.getSynthViewNumbers()[iSynthViewIdx] / VIEW_NUM_PREC  << std::endl;
409            apcPicYuvBaseVideo[iLeftBaseViewIdx]->copyToPic( pcPicYuvSynthOut ); // Copy Original
410            bRender = false;
411          }
412        }
413
414
415        if (bRender)
416        {
417          std::cout << "Rendering Frame " << iFrame << " of View " << (Double) m_cCameraData.getSynthViewNumbers()[iSynthViewIdx] / VIEW_NUM_PREC  << std::endl;
418          m_pcRenTop->setShiftLUTs( m_cCameraData.getSynthViewShiftLUTD()[iLeftBaseViewIdx ][iSynthViewIdx],
419            m_cCameraData.getSynthViewShiftLUTI()[iLeftBaseViewIdx ][iSynthViewIdx], NULL, NULL, NULL, NULL, -1 );
420          m_pcRenTop->extrapolateView( apcPicYuvBaseVideo[iLeftBaseViewIdx ], apcPicYuvBaseDepth[iLeftBaseViewIdx ], pcPicYuvSynthOut, true );
421        }
422        break;
423      /// EXTRAPOLATION FROM RIGHT
424      case 2:            // extrapolation from right
425        if ( !bHasRView ) // View to render is BaseView
426        {
427          bRender = false;
428        }
429
430          if (  bIsBaseView )
431          {
432
433          AOF( iLeftBaseViewIdx == iRightBaseViewIdx );
434          Int iSortedBaseViewIdx = m_cCameraData.getBaseId2SortedId() [iLeftBaseViewIdx];
435          if ( iSortedBaseViewIdx + 1 < m_iNumberOfInputViews )
436          {
437            iRightBaseViewIdx = m_cCameraData.getBaseSortedId2Id()[ iSortedBaseViewIdx + 1];
438          }
439          else
440          {
441            std::cout << "Copied    Frame " << iFrame << " of BaseView " << (Double) m_cCameraData.getSynthViewNumbers()[iSynthViewIdx] / VIEW_NUM_PREC  << std::endl;
442            apcPicYuvBaseVideo[iLeftBaseViewIdx]->copyToPic( pcPicYuvSynthOut ); // Copy Original
443            bRender = false;
444          }
445        }
446
447        if ( bRender )
448        {
449          std::cout << "Rendering Frame " << iFrame << " of View " << (Double) m_cCameraData.getSynthViewNumbers()[iSynthViewIdx] / VIEW_NUM_PREC  << std::endl;
450          m_pcRenTop->setShiftLUTs( NULL, NULL,NULL, m_cCameraData.getSynthViewShiftLUTD()[iRightBaseViewIdx ][iSynthViewIdx],
451            m_cCameraData.getSynthViewShiftLUTI()[iRightBaseViewIdx ][iSynthViewIdx],NULL, iRelDistToLeft);
452          m_pcRenTop->extrapolateView( apcPicYuvBaseVideo[iRightBaseViewIdx ], apcPicYuvBaseDepth[iRightBaseViewIdx ], pcPicYuvSynthOut, false);
453        }
454        break;
455      }
456
457      // Write Output
458      m_apcTVideoIOYuvSynthOutput[m_bSweep ? 0 : iSynthViewIdx]->write( pcPicYuvSynthOut, aiPad );
459    }
460    iFrame++;
461    iNumOfRenderedFrames++;
462  }
463
464  // Delete Buffers
465  for ( UInt uiBaseView = 0; uiBaseView < m_iNumberOfInputViews; uiBaseView++ )
466  {
467    apcPicYuvBaseVideo[uiBaseView]->destroy();
468    delete apcPicYuvBaseVideo[uiBaseView];
469
470    apcPicYuvBaseDepth[uiBaseView]->destroy();
471    delete apcPicYuvBaseDepth[uiBaseView];
472
473    // Temporal Filter
474    if ( m_bTempDepthFilter )
475    {
476      apcPicYuvLastBaseVideo[uiBaseView]->destroy();
477      delete apcPicYuvLastBaseVideo[uiBaseView];
478
479      apcPicYuvLastBaseDepth[uiBaseView]->destroy();
480      delete apcPicYuvLastBaseDepth[uiBaseView];
481    }
482  }
483
484  pcPicYuvSynthOut->destroy();
485  delete pcPicYuvSynthOut;
486
487  xDestroyLib();
488
489}
490
491Void TAppRendererTop::go()
492{
493  switch ( m_iRenderMode )
494  {
495  case 0:
496    render();
497    break;
498  case 1:
499    renderModel();
500    break;
501  case 10:
502    renderUsedPelsMap( );
503      break;
504
505  default:
506    AOT(true);
507  }
508}
509
510Void TAppRendererTop::renderModel()
511{
512  if ( m_bUseSetupString )
513  {
514    xRenderModelFromString();
515  }
516  else
517  {
518    xRenderModelFromNums();
519  }
520}
521
522Void TAppRendererTop::xRenderModelFromString()
523{
524
525    xCreateLib();
526    xInitLib();
527
528    // Create Buffers Input Views;
529    std::vector<TComPicYuv*> apcPicYuvBaseVideo;
530    std::vector<TComPicYuv*> apcPicYuvBaseDepth;
531
532
533    for ( UInt uiBaseView = 0; uiBaseView < m_iNumberOfInputViews; uiBaseView++ )
534    {
535      TComPicYuv* pcNewVideoPic = new TComPicYuv;
536      TComPicYuv* pcNewDepthPic = new TComPicYuv;
537
538      pcNewVideoPic->create( m_iSourceWidth, m_iSourceHeight, 1, 1, 1 );
539      apcPicYuvBaseVideo.push_back(pcNewVideoPic);
540
541      pcNewDepthPic->create( m_iSourceWidth, m_iSourceHeight, 1, 1, 1 );
542      apcPicYuvBaseDepth.push_back(pcNewDepthPic);
543    }
544
545    Int aiPad[2] = { 0, 0 };
546
547    // Init Model
548    TRenModel cCurModel;
549
550    AOT( m_iLog2SamplingFactor != 0 );
551    cCurModel.create( m_cRenModStrParser.getNumOfBaseViews(), m_cRenModStrParser.getNumOfModels(), m_iSourceWidth, m_iSourceHeight, m_iShiftPrecision, m_iBlendHoleMargin );
552
553    for ( Int iViewIdx = 0; iViewIdx < m_iNumberOfInputViews; iViewIdx++ )
554    {
555      Int iNumOfModels   = m_cRenModStrParser.getNumOfModelsForView(iViewIdx, 1);
556
557      for (Int iCurModel = 0; iCurModel < iNumOfModels; iCurModel++ )
558      {
559        Int iModelNum; Int iLeftViewNum; Int iRightViewNum; Int iDump; Int iOrgRefNum; Int iBlendMode;
560        m_cRenModStrParser.getSingleModelData  ( iViewIdx, 1, iCurModel, iModelNum, iBlendMode, iLeftViewNum, iRightViewNum, iOrgRefNum, iDump ) ;
561        cCurModel         .createSingleModel   ( iViewIdx, 1, iModelNum, iLeftViewNum, iRightViewNum, false, iBlendMode );
562
563      }
564    }
565
566    // Create Buffer for synthesized View
567    TComPicYuv* pcPicYuvSynthOut = new TComPicYuv;
568    pcPicYuvSynthOut->create( m_iSourceWidth, m_iSourceHeight, 1, 1, 1 );
569
570    Bool bAnyEOS = false;
571
572    Int iNumOfRenderedFrames = 0;
573    Int iFrame = 0;
574
575    while ( ( ( iNumOfRenderedFrames < m_iFramesToBeRendered ) || ( m_iFramesToBeRendered == 0 ) ) && !bAnyEOS )
576    {
577      // read in depth and video
578      for(Int iBaseViewIdx=0; iBaseViewIdx < m_iNumberOfInputViews; iBaseViewIdx++ )
579      {
580        m_apcTVideoIOYuvVideoInput[iBaseViewIdx]->read( apcPicYuvBaseVideo[iBaseViewIdx], aiPad  ) ;
581        bAnyEOS |= m_apcTVideoIOYuvVideoInput[iBaseViewIdx]->isEof();
582
583        m_apcTVideoIOYuvDepthInput[iBaseViewIdx]->read( apcPicYuvBaseDepth[iBaseViewIdx], aiPad  ) ;
584        bAnyEOS |= m_apcTVideoIOYuvDepthInput[iBaseViewIdx]->isEof();
585      }
586
587      if ( iFrame < m_iFrameSkip )
588      {
589        continue;
590      }
591
592
593      for(Int iBaseViewIdx=0; iBaseViewIdx < m_iNumberOfInputViews; iBaseViewIdx++ )
594      {
595        TComPicYuv* pcPicYuvVideo = apcPicYuvBaseVideo[iBaseViewIdx];
596        TComPicYuv* pcPicYuvDepth = apcPicYuvBaseDepth[iBaseViewIdx];
597        Int iBaseViewSIdx = m_cCameraData.getBaseId2SortedId()[iBaseViewIdx ];
598        cCurModel.setBaseView( iBaseViewSIdx, pcPicYuvVideo, pcPicYuvDepth, NULL, NULL );
599      }
600
601      for(Int iBaseViewIdx=0; iBaseViewIdx < m_iNumberOfInputViews; iBaseViewIdx++ )
602      {
603        m_cCameraData.update( (UInt)iFrame );
604
605        // setup virtual views
606        Int iBaseViewSIdx = m_cCameraData.getBaseId2SortedId()[iBaseViewIdx];
607
608        cCurModel.setErrorMode( iBaseViewSIdx, 1, 0 );
609        Int iNumOfSV  = m_cRenModStrParser.getNumOfModelsForView( iBaseViewSIdx, 1);
610        for (Int iCurView = 0; iCurView < iNumOfSV; iCurView++ )
611        {
612          Int iOrgRefBaseViewSIdx;
613          Int iLeftBaseViewSIdx;
614          Int iRightBaseViewSIdx;
615          Int iSynthViewRelNum;
616          Int iModelNum;
617          Int iBlendMode;
618
619          m_cRenModStrParser.getSingleModelData(iBaseViewSIdx, 1, iCurView, iModelNum, iBlendMode, iLeftBaseViewSIdx, iRightBaseViewSIdx, iOrgRefBaseViewSIdx, iSynthViewRelNum );
620
621          Int iLeftBaseViewIdx    = -1;
622          Int iRightBaseViewIdx   = -1;
623
624          TComPicYuv* pcPicYuvOrgRef  = NULL;
625          Int**      ppiShiftLUTLeft  = NULL;
626          Int**      ppiShiftLUTRight = NULL;
627          Int**      ppiBaseShiftLUTLeft  = NULL;
628          Int**      ppiBaseShiftLUTRight = NULL;
629
630
631          Int        iDistToLeft      = -1;
632
633          Int iSynthViewIdx = m_cCameraData.synthRelNum2Idx( iSynthViewRelNum );
634
635          if ( iLeftBaseViewSIdx != -1 )
636          {
637            iLeftBaseViewIdx   = m_cCameraData.getBaseSortedId2Id()   [ iLeftBaseViewSIdx ];
638            ppiShiftLUTLeft    = m_cCameraData.getSynthViewShiftLUTI()[ iLeftBaseViewIdx  ][ iSynthViewIdx  ];
639          }
640
641          if ( iRightBaseViewSIdx != -1 )
642          {
643            iRightBaseViewIdx  = m_cCameraData.getBaseSortedId2Id()   [iRightBaseViewSIdx ];
644            ppiShiftLUTRight   = m_cCameraData.getSynthViewShiftLUTI()[ iRightBaseViewIdx ][ iSynthViewIdx ];
645          }
646
647          if ( iRightBaseViewSIdx != -1 && iLeftBaseViewSIdx != -1 )
648          {
649
650            ppiBaseShiftLUTLeft  = m_cCameraData.getBaseViewShiftLUTI() [ iLeftBaseViewIdx  ][ iRightBaseViewIdx ];
651            ppiBaseShiftLUTRight = m_cCameraData.getBaseViewShiftLUTI() [ iRightBaseViewIdx ][ iLeftBaseViewIdx  ];
652            iDistToLeft    = m_cCameraData.getRelDistLeft(  iSynthViewIdx , iLeftBaseViewIdx, iRightBaseViewIdx);
653          }
654
655          std::cout << "Rendering Frame " << iFrame << " of View " << (Double) m_cCameraData.getSynthViewNumbers()[iSynthViewIdx] / VIEW_NUM_PREC  << std::endl;
656
657          cCurModel.setSingleModel( iModelNum, ppiShiftLUTLeft, ppiBaseShiftLUTLeft, ppiShiftLUTRight, ppiBaseShiftLUTRight, iDistToLeft, pcPicYuvOrgRef );
658
659          Int iViewPos;
660          if (iLeftBaseViewSIdx != -1 && iRightBaseViewSIdx != -1)
661          {
662            iViewPos = VIEWPOS_MERGED;
663          }
664          else if ( iLeftBaseViewSIdx != -1 )
665          {
666            iViewPos = VIEWPOS_LEFT;
667          }
668          else if ( iRightBaseViewSIdx != -1 )
669          {
670            iViewPos = VIEWPOS_RIGHT;
671          }
672          else
673          {
674            AOT(true);
675          }
676
677          cCurModel.getSynthVideo ( iModelNum, iViewPos, pcPicYuvSynthOut );
678
679          // Write Output
680          m_apcTVideoIOYuvSynthOutput[m_bSweep ? 0 : iModelNum]->write( pcPicYuvSynthOut, aiPad );
681        }
682      }
683      iFrame++;
684      iNumOfRenderedFrames++;
685  }
686
687    // Delete Buffers
688    for ( UInt uiBaseView = 0; uiBaseView < m_iNumberOfInputViews; uiBaseView++ )
689    {
690      apcPicYuvBaseVideo[uiBaseView]->destroy();
691      delete apcPicYuvBaseVideo[uiBaseView];
692
693      apcPicYuvBaseDepth[uiBaseView]->destroy();
694      delete apcPicYuvBaseDepth[uiBaseView];
695}
696    pcPicYuvSynthOut->destroy();
697    delete pcPicYuvSynthOut;
698
699    xDestroyLib();
700}
701
702Void TAppRendererTop::xRenderModelFromNums()
703{
704  xCreateLib();
705  xInitLib();
706
707  // Create Buffers Input Views;
708  std::vector<TComPicYuv*> apcPicYuvBaseVideo;
709  std::vector<TComPicYuv*> apcPicYuvBaseDepth;
710
711
712  Int aiPad[2] = { 0, 0 };
713
714  // Init Model
715  TRenModel cCurModel;
716
717  AOT( m_iLog2SamplingFactor != 0 );
718  cCurModel.create( m_iNumberOfInputViews, m_iNumberOfOutputViews, m_iSourceWidth, m_iSourceHeight, m_iShiftPrecision, m_iBlendHoleMargin );
719
720  for ( UInt uiBaseView = 0; uiBaseView < m_iNumberOfInputViews; uiBaseView++ )
721  {
722    TComPicYuv* pcNewVideoPic = new TComPicYuv;
723    TComPicYuv* pcNewDepthPic = new TComPicYuv;
724
725    pcNewVideoPic->create( m_iSourceWidth, m_iSourceHeight, 1, 1, 1 );
726    apcPicYuvBaseVideo.push_back(pcNewVideoPic);
727
728    pcNewDepthPic->create( m_iSourceWidth, m_iSourceHeight, 1, 1, 1 );
729    apcPicYuvBaseDepth.push_back(pcNewDepthPic);
730  }
731
732  for(Int iSynthViewIdx=0; iSynthViewIdx < m_iNumberOfOutputViews; iSynthViewIdx++ )
733  {
734    Int  iLeftBaseViewIdx  = -1;
735    Int  iRightBaseViewIdx = -1;
736    Bool bIsBaseView = false;
737
738    Int iRelDistToLeft;
739    m_cCameraData.getLeftRightBaseView( iSynthViewIdx, iLeftBaseViewIdx, iRightBaseViewIdx, iRelDistToLeft,  bIsBaseView );
740
741    if (m_iRenderDirection == 1 )
742    {
743      iRightBaseViewIdx = -1;
744      AOT( iLeftBaseViewIdx == -1);
745    }
746
747    if (m_iRenderDirection == 2 )
748    {
749      iLeftBaseViewIdx = -1;
750      AOT( iRightBaseViewIdx == -1);
751    }
752
753    Int iLeftBaseViewSIdx  = -1;
754    Int iRightBaseViewSIdx = -1;
755
756    if (iLeftBaseViewIdx != -1 )
757    {
758      iLeftBaseViewSIdx = m_cCameraData.getBaseId2SortedId()[iLeftBaseViewIdx];
759    }
760
761    if (iRightBaseViewIdx != -1 )
762    {
763      iRightBaseViewSIdx = m_cCameraData.getBaseId2SortedId()[iRightBaseViewIdx];
764    }
765    cCurModel.createSingleModel(-1, -1, iSynthViewIdx, iLeftBaseViewSIdx, iRightBaseViewSIdx, false, m_iBlendMode );
766  }
767
768  // Create Buffer for synthesized View
769  TComPicYuv* pcPicYuvSynthOut = new TComPicYuv;
770  pcPicYuvSynthOut->create( m_iSourceWidth, m_iSourceHeight, 1, 1, 1 );
771
772  Bool bAnyEOS = false;
773
774  Int iNumOfRenderedFrames = 0;
775  Int iFrame = 0;
776
777  while ( ( ( iNumOfRenderedFrames < m_iFramesToBeRendered ) || ( m_iFramesToBeRendered == 0 ) ) && !bAnyEOS )
778  {
779    // read in depth and video
780    for(Int iBaseViewIdx=0; iBaseViewIdx < m_iNumberOfInputViews; iBaseViewIdx++ )
781    {
782      m_apcTVideoIOYuvVideoInput[iBaseViewIdx]->read( apcPicYuvBaseVideo[iBaseViewIdx], aiPad  ) ;
783      bAnyEOS |= m_apcTVideoIOYuvVideoInput[iBaseViewIdx]->isEof();
784
785      m_apcTVideoIOYuvDepthInput[iBaseViewIdx]->read( apcPicYuvBaseDepth[iBaseViewIdx], aiPad  ) ;
786      bAnyEOS |= m_apcTVideoIOYuvDepthInput[iBaseViewIdx]->isEof();
787
788      if ( iFrame >= m_iFrameSkip )
789      {
790        Int iBaseViewSIdx = m_cCameraData.getBaseId2SortedId()[iBaseViewIdx];
791        cCurModel.setBaseView( iBaseViewSIdx, apcPicYuvBaseVideo[iBaseViewIdx], apcPicYuvBaseDepth[iBaseViewIdx], NULL, NULL );
792      }
793    }
794
795    if ( iFrame < m_iFrameSkip ) // Skip Frames
796    {
797      iFrame++;
798      continue;
799    }
800
801    m_cCameraData.update( (UInt)iFrame );
802
803    for(Int iSynthViewIdx=0; iSynthViewIdx < m_iNumberOfOutputViews; iSynthViewIdx++ )
804    {
805
806      Int  iLeftBaseViewIdx  = -1;
807      Int  iRightBaseViewIdx = -1;
808
809      Bool bIsBaseView = false;
810
811      Int iRelDistToLeft;
812      Bool bHasLRView = m_cCameraData.getLeftRightBaseView( iSynthViewIdx, iLeftBaseViewIdx, iRightBaseViewIdx, iRelDistToLeft, bIsBaseView );
813      Bool bHasLView = ( iLeftBaseViewIdx != -1 );
814      Bool bHasRView = ( iRightBaseViewIdx != -1 );
815
816      switch( m_iRenderDirection )
817      {
818        /// INTERPOLATION
819      case 0:
820        assert( bHasLRView || bIsBaseView );
821
822        if ( !bHasLRView && bIsBaseView ) // View to render is BaseView
823        {
824          std::cout << "Copied    Frame " << iFrame << " of BaseView " << (Double) m_cCameraData.getSynthViewNumbers()[iSynthViewIdx] / VIEW_NUM_PREC  << std::endl;
825          apcPicYuvBaseVideo[iLeftBaseViewIdx]->copyToPic( pcPicYuvSynthOut ); // Copy Original
826        }
827        else  // Render
828        {
829          std::cout << "Rendering Frame " << iFrame << " of View " << (Double) m_cCameraData.getSynthViewNumbers()[iSynthViewIdx] / VIEW_NUM_PREC  << std::endl;
830          cCurModel.setSingleModel( iSynthViewIdx,
831                                    m_cCameraData.getSynthViewShiftLUTI()[iLeftBaseViewIdx ][iSynthViewIdx]    ,
832                                    m_cCameraData.getBaseViewShiftLUTI ()[iLeftBaseViewIdx ][iRightBaseViewIdx],
833                                    m_cCameraData.getSynthViewShiftLUTI()[iRightBaseViewIdx][iSynthViewIdx]    ,
834                                    m_cCameraData.getBaseViewShiftLUTI ()[iRightBaseViewIdx][iLeftBaseViewIdx] ,
835                                    iRelDistToLeft,
836                                    NULL );
837          cCurModel.getSynthVideo ( iSynthViewIdx, VIEWPOS_MERGED, pcPicYuvSynthOut );
838        }
839        break;
840        /// EXTRAPOLATION FROM LEFT
841      case 1:
842
843        if ( !bHasLView ) // View to render is BaseView
844        {
845          std::cout << "Copied    Frame " << iFrame << " of BaseView " << (Double) m_cCameraData.getSynthViewNumbers()[iSynthViewIdx] / VIEW_NUM_PREC  << std::endl;
846          apcPicYuvBaseVideo[iLeftBaseViewIdx]->copyToPic( pcPicYuvSynthOut ); // Copy Original
847        }
848        else  // Render
849        {
850          std::cout << "Rendering Frame " << iFrame << " of View " << (Double) m_cCameraData.getSynthViewNumbers()[iSynthViewIdx] / VIEW_NUM_PREC  << std::endl;
851          cCurModel.setSingleModel( iSynthViewIdx, m_cCameraData.getSynthViewShiftLUTI()[iLeftBaseViewIdx ][iSynthViewIdx], NULL, NULL, NULL, -1,  NULL);
852          cCurModel.getSynthVideo ( iSynthViewIdx, VIEWPOS_LEFT, pcPicYuvSynthOut );
853        }
854        break;
855        /// EXTRAPOLATION FROM RIGHT
856      case 2:            // extrapolation from right
857        if ( !bHasRView ) // View to render is BaseView
858        {
859          std::cout << "Copied    Frame " << iFrame << " of BaseView " << (Double) m_cCameraData.getSynthViewNumbers()[iSynthViewIdx] / VIEW_NUM_PREC  << std::endl;
860          apcPicYuvBaseVideo[iRightBaseViewIdx]->copyToPic( pcPicYuvSynthOut ); // Copy Original
861        }
862        else  // Render
863        {
864          std::cout << "Rendering Frame " << iFrame << " of View " << (Double) m_cCameraData.getSynthViewNumbers()[iSynthViewIdx] / VIEW_NUM_PREC  << std::endl;
865          cCurModel.setSingleModel( iSynthViewIdx, NULL , NULL, m_cCameraData.getSynthViewShiftLUTI()[iRightBaseViewIdx ][iSynthViewIdx], NULL, -1, NULL);
866          cCurModel.getSynthVideo ( iSynthViewIdx, VIEWPOS_RIGHT, pcPicYuvSynthOut );
867        }
868        break;
869      }
870
871      // Write Output
872      m_apcTVideoIOYuvSynthOutput[m_bSweep ? 0 : iSynthViewIdx]->write( pcPicYuvSynthOut, aiPad );
873    }
874    iFrame++;
875    iNumOfRenderedFrames++;
876  }
877
878  // Delete Buffers
879  for ( UInt uiBaseView = 0; uiBaseView < m_iNumberOfInputViews; uiBaseView++ )
880  {
881    apcPicYuvBaseVideo[uiBaseView]->destroy();
882    delete apcPicYuvBaseVideo[uiBaseView];
883
884    apcPicYuvBaseDepth[uiBaseView]->destroy();
885    delete apcPicYuvBaseDepth[uiBaseView];
886  }
887  pcPicYuvSynthOut->destroy();
888  delete pcPicYuvSynthOut;
889
890  xDestroyLib();
891
892}
893
894Void TAppRendererTop::renderUsedPelsMap( )
895{
896  xCreateLib();
897  xInitLib();
898
899  // Create Buffers Input Views;
900  std::vector<TComPicYuv*> apcPicYuvBaseVideo;
901  std::vector<TComPicYuv*> apcPicYuvBaseDepth;
902
903  // TemporalImprovement Filter
904  std::vector<TComPicYuv*> apcPicYuvLastBaseVideo;
905  std::vector<TComPicYuv*> apcPicYuvLastBaseDepth;
906
907  Int aiPad[2] = { 0, 0 };
908
909  for ( UInt uiBaseView = 0; uiBaseView < m_iNumberOfInputViews; uiBaseView++ )
910  {
911    TComPicYuv* pcNewVideoPic = new TComPicYuv;
912    TComPicYuv* pcNewDepthPic = new TComPicYuv;
913
914    pcNewVideoPic->create( m_iSourceWidth, m_iSourceHeight, 1, 1, 1 );
915    apcPicYuvBaseVideo.push_back(pcNewVideoPic);
916
917    pcNewDepthPic->create( m_iSourceWidth, m_iSourceHeight, 1, 1, 1 );
918    apcPicYuvBaseDepth.push_back(pcNewDepthPic);
919
920    //Temporal improvement Filter
921    if ( m_bTempDepthFilter )
922    {
923      pcNewVideoPic = new TComPicYuv;
924      pcNewDepthPic = new TComPicYuv;
925
926      pcNewVideoPic->create( m_iSourceWidth, m_iSourceHeight, 1, 1, 1 );
927      apcPicYuvLastBaseVideo.push_back(pcNewVideoPic);
928
929      pcNewDepthPic->create( m_iSourceWidth, m_iSourceHeight, 1, 1, 1 );
930      apcPicYuvLastBaseDepth.push_back(pcNewDepthPic);
931    }
932  }
933
934  // Create Buffer for synthesized View
935  TComPicYuv* pcPicYuvSynthOut = new TComPicYuv;
936  pcPicYuvSynthOut->create( m_iSourceWidth, m_iSourceHeight, 1, 1, 1 );
937
938  Bool bAnyEOS = false;
939
940  Int iNumOfRenderedFrames = 0;
941  Int iFrame = 0;
942
943  while ( ( ( iNumOfRenderedFrames < m_iFramesToBeRendered ) || ( m_iFramesToBeRendered == 0 ) ) && !bAnyEOS )
944  {
945    // set shift LUT
946
947    // read in depth and video
948    for(Int iBaseViewIdx=0; iBaseViewIdx < m_iNumberOfInputViews; iBaseViewIdx++ )
949    {
950      m_apcTVideoIOYuvVideoInput[iBaseViewIdx]->read( apcPicYuvBaseVideo[iBaseViewIdx], aiPad  ) ;
951      apcPicYuvBaseVideo[iBaseViewIdx]->extendPicBorder();
952      bAnyEOS |= m_apcTVideoIOYuvVideoInput[iBaseViewIdx]->isEof();
953
954      m_apcTVideoIOYuvDepthInput[iBaseViewIdx]->read( apcPicYuvBaseDepth[iBaseViewIdx], aiPad  ) ;
955      apcPicYuvBaseDepth[iBaseViewIdx]->extendPicBorder();
956      bAnyEOS |= m_apcTVideoIOYuvDepthInput[iBaseViewIdx]->isEof();
957
958      if ( m_bTempDepthFilter && (iFrame >= m_iFrameSkip) )
959      {
960        m_pcRenTop->temporalFilterVSRS( apcPicYuvBaseVideo[iBaseViewIdx], apcPicYuvBaseDepth[iBaseViewIdx], apcPicYuvLastBaseVideo[iBaseViewIdx], apcPicYuvLastBaseDepth[iBaseViewIdx], ( iFrame == m_iFrameSkip) );
961      }
962    }
963
964    if ( iFrame < m_iFrameSkip ) // Skip Frames
965    {
966      std::cout << "Skipping Frame " << iFrame << std::endl;
967
968      iFrame++;
969      continue;
970    }
971
972    m_cCameraData.update( (UInt)iFrame );
973
974    for(Int iViewIdx=1; iViewIdx < m_iNumberOfInputViews; iViewIdx++ )
975    {
976      std::cout << "Rendering UsedPelsMap for Frame " << iFrame << " of View " << (Double) m_cCameraData.getBaseViewNumbers()[iViewIdx] << std::endl;
977
978      Int iViewSIdx      = m_cCameraData.getBaseId2SortedId()[iViewIdx];
979      Int iFirstViewSIdx = m_cCameraData.getBaseId2SortedId()[0];
980
981      AOT( iViewSIdx == iFirstViewSIdx );
982
983      Bool bFirstIsLeft = (iFirstViewSIdx < iViewSIdx);
984
985      m_pcRenTop->setShiftLUTs(
986        m_cCameraData.getBaseViewShiftLUTD()[0][iViewIdx],
987        m_cCameraData.getBaseViewShiftLUTI()[0][iViewIdx],
988        m_cCameraData.getBaseViewShiftLUTI()[0][iViewIdx],
989        m_cCameraData.getBaseViewShiftLUTD()[0][iViewIdx],
990        m_cCameraData.getBaseViewShiftLUTI()[0][iViewIdx],
991        m_cCameraData.getBaseViewShiftLUTI()[0][iViewIdx],
992        -1
993        );
994
995      m_pcRenTop->getUsedSamplesMap( apcPicYuvBaseDepth[0], pcPicYuvSynthOut, bFirstIsLeft );
996
997      // Write Output
998      m_apcTVideoIOYuvSynthOutput[iViewIdx-1]->write( pcPicYuvSynthOut, aiPad );
999
1000    }
1001    iFrame++;
1002    iNumOfRenderedFrames++;
1003  }
1004
1005  // Delete Buffers
1006  for ( UInt uiBaseView = 0; uiBaseView < m_iNumberOfInputViews; uiBaseView++ )
1007  {
1008    apcPicYuvBaseVideo[uiBaseView]->destroy();
1009    delete apcPicYuvBaseVideo[uiBaseView];
1010
1011    apcPicYuvBaseDepth[uiBaseView]->destroy();
1012    delete apcPicYuvBaseDepth[uiBaseView];
1013
1014    // Temporal Filter
1015    if ( m_bTempDepthFilter )
1016    {
1017      apcPicYuvLastBaseVideo[uiBaseView]->destroy();
1018      delete apcPicYuvLastBaseVideo[uiBaseView];
1019
1020      apcPicYuvLastBaseDepth[uiBaseView]->destroy();
1021      delete apcPicYuvLastBaseDepth[uiBaseView];
1022    }
1023  }
1024  pcPicYuvSynthOut->destroy();
1025  delete pcPicYuvSynthOut;
1026
1027  xDestroyLib();
1028
1029}
Note: See TracBrowser for help on using the repository browser.