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): Thomas Davies (Original Author),
25 * Anuradha Suraparaju,
29 * Alternatively, the contents of this file may be used under the terms of
30 * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
31 * Public License Version 2.1 (the "LGPL"), in which case the provisions of
32 * the GPL or the LGPL are applicable instead of those above. If you wish to
33 * allow use of your version of this file only under the terms of the either
34 * the GPL or LGPL and not to allow others to use your version of this file
35 * under the MPL, indicate your decision by deleting the provisions above
36 * and replace them with the notice and other provisions required by the GPL
37 * or LGPL. If you do not delete the provisions above, a recipient may use
38 * your version of this file under the terms of any one of the MPL, the GPL
40 * ***** END LICENSE BLOCK ***** */
43 //Decompression of pictures
44 /////////////////////////
46 #include <libdirac_common/dirac_assertions.h>
47 #include <libdirac_decoder/picture_decompress.h>
48 #include <libdirac_decoder/comp_decompress.h>
49 #include <libdirac_common/mot_comp.h>
50 #include <libdirac_common/mv_codec.h>
51 #include <libdirac_byteio/picture_byteio.h>
52 #include <libdirac_common/dirac_exception.h>
53 using namespace dirac
;
61 PictureDecompressor::PictureDecompressor(DecoderParams
& decp
, ChromaFormat cf
)
68 PictureDecompressor::~PictureDecompressor()
73 bool PictureDecompressor::Decompress(ParseUnitByteIO
& parseunit_byteio
,
74 PictureBuffer
& my_buffer
)
76 // get current byte position
77 //int start_pos = parseunit_byteio.GetReadBytePosition();
81 PictureByteIO
picture_byteio(m_pparams
,
84 picture_byteio
.Input();
88 if (m_pparams
.GetPictureType() == INTRA_PICTURE
)
93 if (m_pparams
.GetReferenceType() == REFERENCE_PICTURE
)
98 m_pparams
.SetPicSort(fs
);
100 if (m_pparams
.GetReferenceType() == REFERENCE_PICTURE
)
101 // Now clean the reference pictures from the buffer
102 CleanReferencePictures( my_buffer
);
104 // Check if the picture can be decoded
105 if (m_pparams
.PicSort().IsInter()){
106 const std::vector
<int>& refs
= m_pparams
.Refs();
108 for (unsigned int i
= 0; i
< refs
.size(); ++i
)
109 if ( !my_buffer
.IsPictureAvail(refs
[i
]) )
113 // decode the rest of the picture
115 if ( m_decparams
.Verbose() ){
116 std::cout
<<std::endl
<<"Decoding picture "<<m_pparams
.PictureNum()<<" in display order";
117 if ( m_pparams
.PicSort().IsInter() ){
118 std::cout
<<std::endl
<<"References: "<<m_pparams
.Refs()[0];
119 if ( m_pparams
.Refs().size()>1 )
120 std::cout
<<" and "<<m_pparams
.Refs()[1];
124 PictureSort psort
= m_pparams
.PicSort();
125 auto_ptr
<MvData
> mv_data
;
127 if ( psort
.IsInter() )
128 //do all the MV stuff
129 DecompressMVData( mv_data
, picture_byteio
);
131 // Read the transform header
132 TransformByteIO
transform_byteio(picture_byteio
, m_pparams
, m_decparams
);
133 transform_byteio
.Input();
135 if (m_pparams
.PicSort().IsIntra() && m_decparams
.ZeroTransform()){
136 DIRAC_THROW_EXCEPTION(
137 ERR_UNSUPPORTED_STREAM_DATA
,
138 "Intra pictures cannot have Zero-Residual",
139 SEVERITY_PICTURE_ERROR
);
142 // Add a picture to the buffer to decode into
143 PushPicture(my_buffer
);
145 //Reference to the picture being decoded
146 Picture
& my_picture
= my_buffer
.GetPicture(m_pparams
.PictureNum());
148 if (!m_decparams
.ZeroTransform()){
150 Picture
& pic
= my_buffer
.GetPicture( m_pparams
.PictureNum() );
152 CompDecompressor
my_compdecoder( m_decparams
, pic
.GetPparams() );
154 PicArray
* comp_data
[3];
155 CoeffArray
* coeff_data
[3];
157 const int depth( m_decparams
.TransformDepth() );
158 WaveletTransform
wtransform( depth
, m_decparams
.TransformFilter() );
160 pic
.InitWltData( depth
);
162 for (int c
=0; c
<3; ++c
){
163 ComponentByteIO
component_byteio((CompSort
) c
, transform_byteio
);
164 comp_data
[c
] = &pic
.Data((CompSort
) c
);
165 coeff_data
[c
] = &pic
.WltData((CompSort
) c
);
167 SubbandList
& bands
= coeff_data
[c
]->BandList();
169 bands
.Init(depth
, coeff_data
[c
]->LengthX() , coeff_data
[c
]->LengthY());
170 my_compdecoder
.Decompress(&component_byteio
, *(coeff_data
[c
]), bands
);
172 wtransform
.Transform(BACKWARD
,*(comp_data
[c
]), *(coeff_data
[c
]));
178 if ( psort
.IsInter() ){
179 Picture
* my_pic
= &my_buffer
.GetPicture( m_pparams
.PictureNum() );
181 const std::vector
<int>& refs
= m_pparams
.Refs();
182 Picture
* ref_pics
[2];
184 ref_pics
[0] = &my_buffer
.GetPicture( refs
[0] );
186 ref_pics
[1] = &my_buffer
.GetPicture( refs
[1] );
188 ref_pics
[1] = ref_pics
[0];
190 //motion compensate to add the data back in if we don't have an I picture
191 MotionCompensator::CompensatePicture( m_decparams
.GetPicPredParams() , ADD
, *(mv_data
.get()) ,
197 if (m_decparams
.Verbose())
198 std::cout
<<std::endl
;
205 catch (const DiracException
& e
) {
214 void PictureDecompressor::CleanReferencePictures( PictureBuffer
& my_buffer
)
216 if ( m_decparams
.Verbose() )
217 std::cout
<<std::endl
<<"Cleaning reference buffer: ";
218 // Do picture buffer cleaning
219 int retd_pnum
= m_pparams
.RetiredPictureNum();
221 if ( retd_pnum
>= 0 && my_buffer
.IsPictureAvail(retd_pnum
) && my_buffer
.GetPicture(retd_pnum
).GetPparams().PicSort().IsRef() )
223 my_buffer
.Remove(retd_pnum
);
224 if ( m_decparams
.Verbose() )
225 std::cout
<<retd_pnum
<<" ";
229 void PictureDecompressor::SetMVBlocks()
231 PicturePredParams
& predparams
= m_decparams
.GetPicPredParams();
232 OLBParams olb_params
= predparams
.LumaBParams(2);
233 predparams
.SetBlockSizes(olb_params
, m_cformat
);
235 // Calculate the number of macro blocks
236 int xnum_sb
= (m_decparams
.Xl()+predparams
.LumaBParams(0).Xbsep()-1)/
237 predparams
.LumaBParams(0).Xbsep();
238 int ynum_sb
= (m_decparams
.Yl()+predparams
.LumaBParams(0).Ybsep()-1)/
239 predparams
.LumaBParams(0).Ybsep();
241 predparams
.SetXNumSB(xnum_sb
);
242 predparams
.SetYNumSB(ynum_sb
);
244 // Set the number of blocks
245 predparams
.SetXNumBlocks(4*xnum_sb
);
246 predparams
.SetYNumBlocks(4*ynum_sb
);
248 // Note that we do not have an integral number of superblocks in a picture
249 // So it is possible that part of a superblock and some blocks can fall
250 // of the edge of the true picture. We need to take this into
251 // consideration while doing Motion Compensation
254 void PictureDecompressor::PushPicture(PictureBuffer
&my_buffer
)
256 m_pparams
.SetCFormat(m_cformat
);
258 m_pparams
.SetXl(m_decparams
.Xl());
259 m_pparams
.SetYl(m_decparams
.Yl());
261 m_pparams
.SetLumaDepth(m_decparams
.LumaDepth());
262 m_pparams
.SetChromaDepth(m_decparams
.ChromaDepth());
264 my_buffer
.PushPicture(m_pparams
);
267 void PictureDecompressor::DecompressMVData( std::auto_ptr
<MvData
>& mv_data
,
268 PictureByteIO
& picture_byteio
)
270 PicturePredParams
& predparams
= m_decparams
.GetPicPredParams();
271 MvDataByteIO
mvdata_byteio (picture_byteio
, m_pparams
, predparams
);
273 // Read in the picture prediction parameters
274 mvdata_byteio
.Input();
277 mv_data
.reset(new MvData( predparams
, m_pparams
.NumRefs() ));
280 if (m_decparams
.Verbose())
281 std::cout
<<std::endl
<<"Decoding motion data ...";
285 // Read in the split mode data header
286 mvdata_byteio
.SplitModeData()->Input();
287 // Read the mode data
288 num_bits
= mvdata_byteio
.SplitModeData()->DataBlockSize();
289 SplitModeCodec
smode_decoder( mvdata_byteio
.SplitModeData()->DataBlock(), TOTAL_MV_CTXS
);
290 smode_decoder
.Decompress( *(mv_data
.get()) , num_bits
);
292 // Read in the prediction mode data header
293 mvdata_byteio
.PredModeData()->Input();
294 // Read the mode data
295 num_bits
= mvdata_byteio
.PredModeData()->DataBlockSize();
296 PredModeCodec
pmode_decoder( mvdata_byteio
.PredModeData()->DataBlock(), TOTAL_MV_CTXS
, m_pparams
.NumRefs());
297 pmode_decoder
.Decompress( *(mv_data
.get()) , num_bits
);
299 // Read in the MV1 horizontal data header
300 mvdata_byteio
.MV1HorizData()->Input();
301 // Read the MV1 horizontal data
302 num_bits
= mvdata_byteio
.MV1HorizData()->DataBlockSize();
303 VectorElementCodec
vdecoder1h( mvdata_byteio
.MV1HorizData()->DataBlock(), 1,
304 HORIZONTAL
, TOTAL_MV_CTXS
);
305 vdecoder1h
.Decompress( *(mv_data
.get()) , num_bits
);
307 // Read in the MV1 vertical data header
308 mvdata_byteio
.MV1VertData()->Input();
310 num_bits
= mvdata_byteio
.MV1VertData()->DataBlockSize();
311 VectorElementCodec
vdecoder1v( mvdata_byteio
.MV1VertData()->DataBlock(), 1,
312 VERTICAL
, TOTAL_MV_CTXS
);
313 vdecoder1v
.Decompress( *(mv_data
.get()) , num_bits
);
315 if ( m_pparams
.NumRefs()>1 )
317 // Read in the MV2 horizontal data header
318 mvdata_byteio
.MV2HorizData()->Input();
319 // Read the MV2 horizontal data
320 num_bits
= mvdata_byteio
.MV2HorizData()->DataBlockSize();
321 VectorElementCodec
vdecoder2h( mvdata_byteio
.MV2HorizData()->DataBlock(), 2,
322 HORIZONTAL
, TOTAL_MV_CTXS
);
323 vdecoder2h
.Decompress( *(mv_data
.get()) , num_bits
);
325 // Read in the MV2 vertical data header
326 mvdata_byteio
.MV2VertData()->Input();
327 // Read the MV2 vertical data
328 num_bits
= mvdata_byteio
.MV2VertData()->DataBlockSize();
329 VectorElementCodec
vdecoder2v( mvdata_byteio
.MV2VertData()->DataBlock(), 2,
330 VERTICAL
, TOTAL_MV_CTXS
);
331 vdecoder2v
.Decompress( *(mv_data
.get()) , num_bits
);
334 // Read in the Y DC data header
335 mvdata_byteio
.YDCData()->Input();
336 // Read the Y DC data
337 num_bits
= mvdata_byteio
.YDCData()->DataBlockSize();
338 DCCodec
ydc_decoder( mvdata_byteio
.YDCData()->DataBlock(), Y_COMP
, TOTAL_MV_CTXS
);
339 ydc_decoder
.Decompress( *(mv_data
.get()) , num_bits
);
341 // Read in the U DC data header
342 mvdata_byteio
.UDCData()->Input();
343 // Read the U DC data
344 num_bits
= mvdata_byteio
.UDCData()->DataBlockSize();
345 DCCodec
udc_decoder( mvdata_byteio
.YDCData()->DataBlock(), U_COMP
, TOTAL_MV_CTXS
);
346 udc_decoder
.Decompress( *(mv_data
.get()) , num_bits
);
348 // Read in the Y DC data header
349 mvdata_byteio
.YDCData()->Input();
350 // Read the Y DC data
351 num_bits
= mvdata_byteio
.YDCData()->DataBlockSize();
352 DCCodec
vdc_decoder( mvdata_byteio
.VDCData()->DataBlock(), V_COMP
, TOTAL_MV_CTXS
);
353 vdc_decoder
.Decompress( *(mv_data
.get()) , num_bits
);
356 void PictureDecompressor::InitCoeffData( CoeffArray
& coeff_data
, const int xl
, const int yl
){
358 // First set the dimensions up //
362 // The pic dimensions must be a multiple of 2^(transform depth)
363 int tx_mul
= (1<<m_decparams
.TransformDepth());
365 if ( xpad_len
%tx_mul
!= 0 )
366 xpad_len
= ( (xpad_len
/tx_mul
)+1 ) *tx_mul
;
367 if ( ypad_len
%tx_mul
!= 0 )
368 ypad_len
= ( (ypad_len
/tx_mul
)+1 ) * tx_mul
;
370 coeff_data
.Resize( ypad_len
, xpad_len
);