1 /* ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License
8 * Version 1.1 (the "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
14 * the specific language governing rights and limitations under the License.
16 * The Original Code is BBC Research and Development code.
18 * The Initial Developer of the Original Code is the British Broadcasting
20 * Portions created by the Initial Developer are Copyright (c) 2004.
21 * All Rights Reserved.
23 * Contributor(s): Anuradha Suraparaju (Original Author)
25 * Alternatively, the contents of this file may be used under the terms of
26 * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
27 * Public License Version 2.1 (the "LGPL"), in which case the provisions of
28 * the GPL or the LGPL are applicable instead of those above. If you wish to
29 * allow use of your version of this file only under the terms of the either
30 * the GPL or LGPL and not to allow others to use your version of this file
31 * under the MPL, indicate your decision by deleting the provisions above
32 * and replace them with the notice and other provisions required by the GPL
33 * or LGPL. If you do not delete the provisions above, a recipient may use
34 * your version of this file under the terms of any one of the MPL, the GPL
36 * ***** END LICENSE BLOCK ***** */
42 #include <libdirac_common/band_vlc.h>
43 #include <libdirac_byteio/subband_byteio.h>
44 #include <libdirac_common/dirac_exception.h>
46 using namespace dirac
;
48 // Constructor for encoding
49 BandVLC::BandVLC( SubbandByteIO
* subband_byteio
,
50 const SubbandList
& band_list
,
52 const bool is_intra
) :
55 m_node(band_list(band_num
)),
56 m_last_qf_idx(m_node
.QuantIndex()),
57 m_byteio(subband_byteio
)
62 int BandVLC::Compress(CoeffArray
&in_data
)
65 return m_byteio
->GetSize();
68 void BandVLC::DoWorkCode(CoeffArray
&in_data
)
70 const TwoDArray
<CodeBlock
>& block_list( m_node
.GetCodeBlocks() );
71 // coeff blocks can be skipped only if SpatialPartitioning is
72 // enabled i.e. more than one code-block per subband
73 bool code_skip
= (block_list
.LengthX() > 1 || block_list
.LengthY() > 1);
75 for (int j
=block_list
.FirstY() ; j
<=block_list
.LastY() ; ++j
)
77 CodeBlock
*block
= block_list
[j
];
78 for (int i
=block_list
.FirstX() ; i
<=block_list
.LastX() ; ++i
)
81 m_byteio
->WriteBit(block
[i
].Skipped()); // encode skip flag
82 if ( !block
[i
].Skipped() )
84 CodeCoeffBlock( block
[i
] , in_data
);
88 ClearBlock (block
[i
] , in_data
);
94 void BandVLC::CodeCoeffBlock(const CodeBlock
& code_block
, CoeffArray
& in_data
)
96 //main coding function, using binarisation
98 const int xbeg
= code_block
.Xstart();
99 const int ybeg
= code_block
.Ystart();
100 const int xend
= code_block
.Xend();
101 const int yend
= code_block
.Yend();
103 const int qf_idx
= code_block
.QuantIndex();
105 if ( m_node
.UsingMultiQuants() )
107 CodeQuantIndexOffset( qf_idx
- m_last_qf_idx
);
108 m_last_qf_idx
= qf_idx
;
111 m_qf
= dirac_quantiser_lists
.QuantFactor4( qf_idx
);
113 m_offset
= dirac_quantiser_lists
.IntraQuantOffset4( qf_idx
);
115 m_offset
= dirac_quantiser_lists
.InterQuantOffset4( qf_idx
);
117 for ( int ypos
=ybeg
; ypos
<yend
;++ypos
)
119 for ( int xpos
=xbeg
; xpos
<xend
;++xpos
)
121 CodeVal( in_data
, xpos
, ypos
, in_data
[ypos
][xpos
] );
127 void BandVLC::CodeQuantIndexOffset( const int offset
)
129 m_byteio
->WriteSint(offset
);
132 inline void BandVLC::CodeVal( CoeffArray
& in_data
,
135 const CoeffType val
)
137 int qval( std::abs(val
) );
140 in_data
[ypos
][xpos
] = static_cast<CoeffType
>( qval
);
142 // Code the quantised value into the bitstream
145 m_byteio
->WriteSint(qval
);
150 in_data
[ypos
][xpos
] *= m_qf
;
151 in_data
[ypos
][xpos
] += m_offset
+2;
152 in_data
[ypos
][xpos
] >>= 2;
154 in_data
[ypos
][xpos
] = -in_data
[ypos
][xpos
];
161 // decoding functions
162 void BandVLC::Decompress(CoeffArray
&out_data
, int num_bytes
)
164 m_byteio
->SetBitsLeft(num_bytes
* 8);
165 DoWorkDecode(out_data
);
166 m_byteio
->FlushInputB();
169 void BandVLC::DoWorkDecode(CoeffArray
& out_data
)
171 const TwoDArray
<CodeBlock
>& block_list( m_node
.GetCodeBlocks() );
173 // coeff blocks can be skipped only if SpatialPartitioning is
174 // enabled i.e. more than one code-block per subband
175 bool decode_skip
= (block_list
.LengthX() > 1 || block_list
.LengthY() > 1);
176 // Now loop over the blocks and decode
177 for (int j
=block_list
.FirstY() ; j
<=block_list
.LastY() ; ++j
)
179 CodeBlock
*block
= block_list
[j
];
180 for (int i
=block_list
.FirstX() ; i
<=block_list
.LastX() ; ++i
)
183 block
[i
].SetSkip( m_byteio
->ReadBoolB() );
184 if ( !block
[i
].Skipped() )
186 DecodeCoeffBlock( block
[i
] , out_data
);
190 ClearBlock (block
[i
] , out_data
);
197 void BandVLC::DecodeCoeffBlock(const CodeBlock
& code_block
, CoeffArray
& out_data
)
199 const int xbeg
= code_block
.Xstart();
200 const int ybeg
= code_block
.Ystart();
201 const int xend
= code_block
.Xend();
202 const int yend
= code_block
.Yend();
204 int qf_idx
= m_node
.QuantIndex();
206 if ( m_node
.UsingMultiQuants() )
208 qf_idx
= m_last_qf_idx
+DecodeQuantIndexOffset();
209 m_last_qf_idx
= qf_idx
;
212 if (qf_idx
> (int)dirac_quantiser_lists
.MaxQuantIndex())
214 std::ostringstream errstr
;
215 errstr
<< "Quantiser index out of range [0.."
216 << (int)dirac_quantiser_lists
.MaxQuantIndex() << "]";
217 DIRAC_THROW_EXCEPTION(
218 ERR_UNSUPPORTED_STREAM_DATA
,
220 SEVERITY_PICTURE_ERROR
);
223 m_qf
= dirac_quantiser_lists
.QuantFactor4( qf_idx
);
226 m_offset
= dirac_quantiser_lists
.IntraQuantOffset4( qf_idx
);
228 m_offset
= dirac_quantiser_lists
.InterQuantOffset4( qf_idx
);
232 for ( int ypos
=ybeg
; ypos
<yend
;++ypos
)
234 for ( int xpos
=xbeg
; xpos
<xend
;++xpos
)
236 DecodeVal( out_data
, xpos
, ypos
);
241 int BandVLC::DecodeQuantIndexOffset( )
243 return m_byteio
->ReadSintB();
246 inline void BandVLC::DecodeVal( CoeffArray
& out_data
, const int xpos
, const int ypos
)
248 // Read quantised coefs
249 int quant_coeff
= m_byteio
->ReadSintB();
250 CoeffType
& out_pixel
= out_data
[ypos
][xpos
];
253 out_pixel
= std::abs(quant_coeff
);
257 out_pixel
+= m_offset
+2;
260 if ( quant_coeff
< 0)
261 out_pixel
= -out_pixel
;
265 // general purpose functions
266 void BandVLC::ClearBlock( const CodeBlock
& code_block
, CoeffArray
& coeff_data
)
268 for (int j
=code_block
.Ystart() ; j
<code_block
.Yend() ; j
++)
270 CoeffType
*pic
= &coeff_data
[j
][code_block
.Xstart()];
271 memset (pic
, 0, (code_block
.Xend()-code_block
.Xstart())*sizeof(CoeffType
));
276 void BandVLC::SetToVal( const CodeBlock
& code_block
, CoeffArray
& pic_data
, const CoeffType val
)
278 for (int j
=code_block
.Ystart() ; j
<code_block
.Yend() ; j
++)
280 for (int i
=code_block
.Xstart() ; i
<code_block
.Xend() ; i
++)
282 pic_data
[j
][i
] = val
;
287 //////////////////////////////////////////////////////////////////////////////////
288 //Finally,special class incorporating prediction for the DC band of intra frames//
289 //////////////////////////////////////////////////////////////////////////////////
291 void IntraDCBandVLC::DoWorkCode(CoeffArray
& in_data
)
293 const TwoDArray
<CodeBlock
>& block_list( m_node
.GetCodeBlocks() );
295 // Now loop over the blocks and code. Note that DC blocks can't be skipped
296 for (int j
=block_list
.FirstY() ; j
<=block_list
.LastY() ; ++j
)
298 for (int i
=block_list
.FirstX() ; i
<=block_list
.LastX() ; ++i
)
300 CodeCoeffBlock( block_list
[j
][i
] , in_data
);
305 void IntraDCBandVLC::CodeCoeffBlock( const CodeBlock
& code_block
, CoeffArray
& in_data
)
307 // Main coding function, using binarisation
308 const int xbeg
= code_block
.Xstart();
309 const int ybeg
= code_block
.Ystart();
310 const int xend
= code_block
.Xend();
311 const int yend
= code_block
.Yend();
315 CoeffType prediction
;
317 const int qf_idx
= code_block
.QuantIndex();
319 if ( m_node
.UsingMultiQuants() )
321 CodeQuantIndexOffset( qf_idx
- m_last_qf_idx
);
322 m_last_qf_idx
= qf_idx
;
325 m_qf
= dirac_quantiser_lists
.QuantFactor4( qf_idx
);
327 m_offset
= dirac_quantiser_lists
.IntraQuantOffset4( qf_idx
);
329 for ( int ypos
=ybeg
; ypos
< yend
; ++ypos
)
331 for (int xpos
= xbeg
; xpos
< xend
; ++xpos
)
333 prediction
= GetPrediction( in_data
, xpos
, ypos
);
334 val
= in_data
[ypos
][xpos
] - prediction
;
335 CodeVal( in_data
, xpos
, ypos
, val
);
336 in_data
[ypos
][xpos
] += prediction
;
342 void IntraDCBandVLC::DoWorkDecode(CoeffArray
& out_data
)
344 const TwoDArray
<CodeBlock
>& block_list( m_node
.GetCodeBlocks() );
346 // coeff blocks can be skipped only if SpatialPartitioning is
347 // enabled i.e. more than one code-block per subband
348 bool decode_skip
= (block_list
.LengthX() > 1 || block_list
.LengthY() > 1);
350 // Now loop over the blocks and decode
351 for (int j
=block_list
.FirstY() ; j
<=block_list
.LastY() ; ++j
)
353 for (int i
=block_list
.FirstX() ; i
<=block_list
.LastX() ; ++i
)
356 block_list
[j
][i
].SetSkip( m_byteio
->ReadBoolB() );
358 if ( !block_list
[j
][i
].Skipped() )
359 DecodeCoeffBlock( block_list
[j
][i
] , out_data
);
361 ClearBlock( block_list
[j
][i
] , out_data
);
363 DCPrediction( block_list
[j
][i
], out_data
);
368 void IntraDCBandVLC::DecodeCoeffBlock( const CodeBlock
& code_block
, CoeffArray
& out_data
)
370 const int xbeg
= code_block
.Xstart();
371 const int ybeg
= code_block
.Ystart();
372 const int xend
= code_block
.Xend();
373 const int yend
= code_block
.Yend();
375 int qf_idx
= m_node
.QuantIndex();
377 if ( m_node
.UsingMultiQuants() )
379 qf_idx
= DecodeQuantIndexOffset()+m_last_qf_idx
;
380 m_last_qf_idx
= qf_idx
;
383 m_qf
= dirac_quantiser_lists
.QuantFactor4( qf_idx
);
385 m_offset
= dirac_quantiser_lists
.IntraQuantOffset4( qf_idx
);
389 for ( int ypos
=ybeg
; ypos
<yend
; ++ypos
)
391 for ( int xpos
=xbeg
; xpos
<xend
; ++xpos
)
393 DecodeVal( out_data
, xpos
, ypos
);
398 void IntraDCBandVLC::DCPrediction( const CodeBlock
& code_block
, CoeffArray
& out_data
)
400 const int xbeg
= code_block
.Xstart();
401 const int ybeg
= code_block
.Ystart();
402 const int xend
= code_block
.Xend();
403 const int yend
= code_block
.Yend();
405 for ( int ypos
=ybeg
; ypos
<yend
; ++ypos
)
407 for ( int xpos
=xbeg
; xpos
<xend
; ++xpos
)
409 out_data
[ypos
][xpos
] += GetPrediction( out_data
, xpos
, ypos
);
415 CoeffType
IntraDCBandVLC::GetPrediction( const CoeffArray
& data
, const int xpos
, const int ypos
) const
417 /* NB, 4.5.3 integer division
418 * numbers are rounded down towards -ve infinity, differing from
419 * C's convention that rounds towards 0
426 int sum
= data
[ypos
][xpos
-1] + data
[ypos
-1][xpos
-1] + data
[ypos
-1][xpos
] + 3/2;
433 return data
[ypos
- 1][0];
438 return data
[0][xpos
- 1];