Updating Contact email
[BrunelResearch-dirac.git] / libdirac_decoder / picture_decompress.cpp
blob6f69d0faf65efb504b7f128ca2f6aca8bc96495d
1 /* ***** BEGIN LICENSE BLOCK *****
3 * $Id$ $Name$
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
19 * Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 2004.
21 * All Rights Reserved.
23 * Contributor(s): Thomas Davies (Original Author),
24 * Scott R Ladd,
25 * Anuradha Suraparaju,
26 * Andrew Kennedy,
27 * Tim Borer
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
39 * or the LGPL.
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;
55 #include <iostream>
56 #include <memory>
58 using std::vector;
59 using std::auto_ptr;
61 PictureDecompressor::PictureDecompressor(DecoderParams& decp, ChromaFormat cf)
63 m_decparams(decp),
64 m_cformat(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();
78 try {
80 // read picture data
81 PictureByteIO picture_byteio(m_pparams,
82 parseunit_byteio);
84 picture_byteio.Input();
86 PictureSort fs;
88 if (m_pparams.GetPictureType() == INTRA_PICTURE)
89 fs.SetIntra();
90 else
91 fs.SetInter();
93 if (m_pparams.GetReferenceType() == REFERENCE_PICTURE)
94 fs.SetRef();
95 else
96 fs.SetNonRef();
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]) )
110 return false;
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()){
149 //decode components
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]));
175 else
176 my_picture.Fill(0);
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] );
185 if (refs.size()>1)
186 ref_pics[1] = &my_buffer.GetPicture( refs[1] );
187 else
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()) ,
192 my_pic, ref_pics );
195 my_picture.Clip();
197 if (m_decparams.Verbose())
198 std::cout<<std::endl;
201 //exit success
202 return true;
204 }// try
205 catch (const DiracException& e) {
206 // skip picture
207 throw e;
210 //exit failure
211 return false;
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();
276 SetMVBlocks();
277 mv_data.reset(new MvData( predparams, m_pparams.NumRefs() ));
279 // decode mv data
280 if (m_decparams.Verbose())
281 std::cout<<std::endl<<"Decoding motion data ...";
283 int num_bits;
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();
309 // Read the MV1 data
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 //
359 int xpad_len = xl;
360 int ypad_len = yl;
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 );