source: 3DVCSoftware/trunk/source/App/utils/BitrateTargeting/ExtractBitrates.cpp @ 1417

Last change on this file since 1417 was 1413, checked in by tech, 6 years ago

Merged HTM-16.2-dev@1412

File size: 6.7 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-2017, ITU/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 ITU/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#include "ExtractBitrates.h"
35#include <string>
36#include <sstream>
37#include <cassert>
38#include <limits>
39#include <map>
40
41namespace
42{
43  /// Maintains a sum and a sample-count for calculating averages
44  class Tally
45  {
46    public:
47
48      /// Contructs a new zeroed tally
49      Tally( ): m_sum( 0.0 ), m_numSlices( 0 ) { }
50
51      /// Adds to the sum and increments the sample-count
52      void add( double in ) { ++m_numSlices; m_sum += in; }
53
54      /// \return The calculated average
55      double average( ) const { return m_sum / ( double )m_numSlices; }
56
57    private:
58      double m_sum;
59      unsigned long m_numSlices;
60  };
61
62  /// Ignores all of the the characters up to and including a given character
63  /// \param line The line being read from
64  /// \param iLine The active input stream
65  /// \param character The character to ignore up to
66  /// \throw POCParseException if the stream goes bad before character is encountered or just after character is encountered
67  void ignoreUpTo( const std::string& line, std::istream& iLine, char character )
68  {
69    while( iLine.good( ) && character != iLine.get( ) )
70      ;
71    if( !iLine.good( ) )
72    {
73      throw POCParseException( line );
74    }
75  }
76
77  /// Extracts the average bitrates for each of the temporal layers from the given log
78  /// \param i The input stream that represents the log
79  /// \return A map that countains the average bitrates for each temporal layer.  Each pair contains the QP value in first and the average bitrate in second.
80  /// \throw POCParseException if an error occured while parsing a POC line
81  std::map< unsigned char, double > extractBitratesForQPs( std::istream& i )
82  {
83    std::map< unsigned char, Tally > tallyMap;
84
85    while( i.good( ) )
86    {
87      // Initialize variables for this line
88      std::string line;
89      std::getline( i, line );
90      std::istringstream iLine( line );
91      if( !iLine.good( ) )
92      {
93        continue;
94      }
95
96      // Ignore the "POC"
97      if( iLine.get( ) != 'P' )
98      {
99        continue;
100      }
101      if( !iLine.good( ) )
102      {
103        continue;
104      }
105      if( iLine.get( ) != 'O' )
106      {
107        continue;
108      }
109      if( !iLine.good( ) )
110      {
111        continue;
112      }
113      if( iLine.get( ) != 'C' )
114      {
115        continue;
116      }
117      if( !iLine.good( ) )
118      {
119        throw POCParseException( line );
120      }
121
122      ignoreUpTo( line, iLine, '(' );
123
124      if( iLine.get( ) != ' ' )
125      {
126        throw POCParseException( line );
127      }
128      if( !iLine.good( ) )
129      {
130        throw POCParseException( line );
131      }
132
133      if( 'I' == iLine.get( ) )
134      {
135        continue;
136      }
137      if( !iLine.good( ) )
138      {
139        throw POCParseException( line );
140      }
141
142      ignoreUpTo( line, iLine, ' ' );
143      ignoreUpTo( line, iLine, ' ' );
144
145      // Parse the qpIndex
146      long qpIndexLong;
147      iLine >> qpIndexLong;
148      if( ( long )std::numeric_limits< unsigned char >::max( ) < qpIndexLong )
149      {
150        throw POCParseException( line );
151      }
152      unsigned char qpIndex( ( unsigned char )qpIndexLong );
153      if( !iLine.good( ) )
154      {
155        throw POCParseException( line );
156      }
157
158      ignoreUpTo( line, iLine, ')' );
159      ignoreUpTo( line, iLine, ' ' );
160
161      // Parse the number of bits
162      unsigned long bitsULong;
163      iLine >> bitsULong;
164      if( !iLine.good( ) )
165      {
166        throw POCParseException( line );
167      }
168
169      // Find the tally that corresponds to our QP.  If there is no such tally yet, then add a new one to the map.
170      std::map< unsigned char, Tally >::iterator iter( tallyMap.find( qpIndex ) );
171      if( tallyMap.end( ) == iter )
172      {
173        tallyMap[ qpIndex ] = Tally( );
174        iter = tallyMap.find( qpIndex );
175      }
176      assert( iter != tallyMap.end( ) );
177
178      iter->second.add( ( double )bitsULong );
179    }
180
181    // Populate and return the result based on all of the tallies
182    std::map< unsigned char, double > result;
183    for( std::map< unsigned char, Tally >::const_iterator iter( tallyMap.begin( ) ); iter != tallyMap.end( ); ++iter )
184    {
185      result[ iter->first ] = iter->second.average( );
186    }
187    return result;
188  }
189}
190
191std::vector< double > extractBitratesForTemporalLayers( std::istream& i )
192{
193  std::vector< double > result;
194
195  std::map< unsigned char, double > bitratesForQPsMap( extractBitratesForQPs( i ) );
196  if( !bitratesForQPsMap.empty( ) )
197  {
198    unsigned char expectedNextQPIndex( bitratesForQPsMap.begin( )->first );
199
200    for( std::map< unsigned char, double >::const_iterator i( bitratesForQPsMap.begin( ) ); i != bitratesForQPsMap.end( ); ++i )
201    {
202      if( i->first != expectedNextQPIndex )
203      {
204        throw NonContiguousQPSetException( );
205      }
206      ++expectedNextQPIndex;
207      result.push_back( i->second );
208    }
209  }
210
211  return result;
212}
Note: See TracBrowser for help on using the repository browser.