1 /* ***** BEGIN LICENSE BLOCK *****
2 *
3 * $Id: picture.cpp,v 1.4 2008/08/14 00:51:08 asuraparaju Exp $ $Name: Dirac_1_0_2 $
4 *
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 *
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/
11 *
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.
15 *
16 * The Original Code is BBC Research and Development code.
17 *
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.
22 *
23 * Contributor(s): Thomas Davies (Original Author)
24 *
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
35 * or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
37 
38 //Implementation of picture classes in picture.h
39 
40 #include <libdirac_common/picture.h>
41 #include <libdirac_common/upconvert.h>
42 using namespace dirac;
43 
44 #include <iostream>
45 #if defined(HAVE_MMX)
46 #include <mmintrin.h>
47 #endif
48 
49 ///////////////
50 //---Picture---//
51 ///////////////
52 
Picture(const PictureParams & pp)53 Picture::Picture(const PictureParams& pp):
54     m_pparams(pp)
55 {
56     for (int c=0;c<3;++c){
57         m_pic_data[c] = NULL;
58 	m_up_pic_data[c] = NULL;
59     }
60 
61     Init();
62 }
63 
Picture(const Picture & cpy)64 Picture::Picture( const Picture& cpy ):
65     m_pparams(cpy.m_pparams)
66 {
67 
68     //delete data to be overwritten
69     for (int c=0;c<3;++c){
70         m_pic_data[c] = NULL;
71 	m_up_pic_data[c] = NULL;
72     }
73 
74     //now copy the data across
75     for (int c=0; c<3; ++c ){
76         m_pic_data[c] = new PicArray( *(cpy.m_pic_data[c]) );
77         if (cpy.m_up_pic_data[c] != NULL)
78             m_up_pic_data[c] = new PicArray( *(cpy.m_up_pic_data[c]) );
79     }
80 
81 }
82 
83 
~Picture()84 Picture::~Picture()
85 {
86     ClearData();
87 }
88 
operator =(const Picture & rhs)89 Picture& Picture::operator=(const Picture& rhs)
90 {
91     if ( &rhs != this)
92     {
93         m_pparams=rhs.m_pparams;
94 
95         // Delete current data
96         ClearData();
97 
98         // Copy the data across
99 	for (int c=0; c<3; ++c ){
100 	    m_pic_data[c] = new PicArray( *(rhs.m_pic_data[c]) );
101 
102             if (rhs.m_up_pic_data[c] != NULL)
103                 m_up_pic_data[c] = new PicArray( *(rhs.m_up_pic_data[c]) );
104 	}
105     }
106 
107     return *this;
108 
109 }
110 
Fill(ValueType val)111 void Picture::Fill(ValueType val)
112 {
113     for (int c=0; c<3; ++c ){
114         m_pic_data[c]->Fill(val);
115 	if (m_up_pic_data[c] != NULL )
116 	    delete m_up_pic_data[c];
117     }
118 }
119 
120 //Other functions
121 
Init()122 void Picture::Init()
123 {
124     //const ChromaFormat cformat=m_pparams.CFormat();
125 
126     //first delete data if we need to
127     ClearData();
128 
129     m_pic_data[0]=new PicArray( m_pparams.Yl() , m_pparams.Xl());
130     m_pic_data[0]->SetCSort( Y_COMP );
131 
132     m_pic_data[1] = new PicArray( m_pparams.ChromaYl() ,
133                               m_pparams.ChromaXl() );
134     m_pic_data[1]->SetCSort( U_COMP );
135 
136     m_pic_data[2] = new PicArray( m_pparams.ChromaYl() ,
137                               m_pparams.ChromaXl() );
138     m_pic_data[2]->SetCSort( V_COMP );
139 }
140 
UpData(CompSort cs)141 PicArray& Picture::UpData(CompSort cs)
142 {
143     const int c = (int) cs;
144 
145     if (m_up_pic_data[c] != NULL )
146         return *(m_up_pic_data[c]);
147     else
148     {//we have to do the upconversion
149 
150         m_up_pic_data[c] = new PicArray( 2*m_pic_data[c]->LengthY(),
151                                          2*m_pic_data[c]->LengthX() );
152         UpConverter* myupconv;
153 	if (c>0)
154             myupconv = new UpConverter(-(1 << (m_pparams.ChromaDepth()-1)),
155                                       (1 << (m_pparams.ChromaDepth()-1))-1,
156                                       m_pparams.ChromaXl(), m_pparams.ChromaYl());
157         else
158             myupconv = new UpConverter(-(1 << (m_pparams.LumaDepth()-1)),
159                                       (1 << (m_pparams.LumaDepth()-1))-1,
160                                       m_pparams.Xl(), m_pparams.Yl());
161 
162         myupconv->DoUpConverter( *(m_pic_data[c]) , *(m_up_pic_data[c]) );
163 
164 	delete myupconv;
165 
166         return *(m_up_pic_data[c]);
167 
168     }
169 }
170 
UpData(CompSort cs) const171 const PicArray& Picture::UpData(CompSort cs) const
172 {
173     const int c = (int) cs;
174 
175     if (m_up_pic_data[c] != NULL)
176         return *(m_up_pic_data[c]);
177     else
178     {//we have to do the upconversion
179 
180         m_up_pic_data[c] = new PicArray( 2*m_pic_data[c]->LengthY(),
181                                          2*m_pic_data[c]->LengthX() );
182         UpConverter* myupconv;
183 	if (c>0)
184             myupconv = new UpConverter(-(1 << (m_pparams.ChromaDepth()-1)),
185                                       (1 << (m_pparams.ChromaDepth()-1))-1,
186                                       m_pparams.ChromaXl(), m_pparams.ChromaYl());
187         else
188             myupconv = new UpConverter(-(1 << (m_pparams.LumaDepth()-1)),
189                                       (1 << (m_pparams.LumaDepth()-1))-1,
190                                       m_pparams.Xl(), m_pparams.Yl());
191 
192         myupconv->DoUpConverter( *(m_pic_data[c]) , *(m_up_pic_data[c]) );
193 
194 	delete myupconv;
195 
196         return *(m_up_pic_data[c]);
197 
198     }
199 }
200 
InitWltData(const int transform_depth)201 void Picture::InitWltData( const int transform_depth )
202 {
203 
204     int xpad_len, ypad_len;
205     int tx_mul = 1<<transform_depth;
206 
207     for (int c=0; c<3; ++c){
208         xpad_len = m_pic_data[c]->LengthX();
209         ypad_len = m_pic_data[c]->LengthY();
210 
211         if ( xpad_len%tx_mul != 0 )
212             xpad_len = ( (xpad_len/tx_mul)+1 ) *tx_mul;
213         if ( ypad_len%tx_mul != 0 )
214              ypad_len = ( (ypad_len/tx_mul)+1 ) * tx_mul;
215 
216         m_wlt_data[c].Resize( ypad_len, xpad_len );
217     }
218 
219 }
220 
ClipComponent(PicArray & pic_data,CompSort cs) const221 void Picture::ClipComponent(PicArray& pic_data, CompSort cs) const
222 {
223     ValueType *pic = &(pic_data[pic_data.FirstY()][pic_data.FirstX()]);
224     int count = pic_data.LengthY() * pic_data.LengthX();
225 
226     ValueType min_val;
227     ValueType max_val;
228 
229     min_val = (cs == Y_COMP) ?
230               -(1 << (m_pparams.LumaDepth()-1) ) :
231               -(1 << (m_pparams.ChromaDepth()-1) );
232 
233     max_val = (cs == Y_COMP) ?
234               (1 << (m_pparams.LumaDepth()-1) )-1 :
235               (1 << (m_pparams.ChromaDepth()-1) )-1;
236 
237 #if defined (HAVE_MMX)
238     {
239         int qcount = count >> 2;
240         count = count & 3;
241 
242         //__m64 pack_usmax = _mm_set_pi16 (0xffff, 0xffff, 0xffff, 0xffff);
243         //__m64 pack_smin = _mm_set_pi16 (0x8000, 0x8000, 0x8000, 0x8000);
244         __m64 pack_usmax = _mm_set_pi16 (-1, -1, -1, -1);
245         __m64 pack_smin = _mm_set_pi16 (-32768, -32768, -32768, -32768);
246         __m64 high_val = _mm_set_pi16 (max_val, max_val, max_val, max_val);
247         __m64 lo_val = _mm_set_pi16 (min_val, min_val, min_val, min_val);
248 
249         __m64 clip_max = _mm_add_pi16 (pack_smin, high_val);
250         __m64 clip_min = _mm_add_pi16 (pack_smin, lo_val);
251 
252         __m64 tmp1 =  _mm_subs_pu16 ( pack_usmax, clip_max);
253         __m64 tmp2 =  _mm_adds_pu16 ( clip_min, tmp1 );
254 
255         while (qcount--)
256         {
257             ValueType *p1 = pic;
258             *(__m64 *)p1 = _mm_add_pi16 (pack_smin, *(__m64 *)p1);
259             *(__m64 *)p1 = _mm_adds_pu16 (*(__m64 *)p1,  tmp1);
260             *(__m64 *)p1 = _mm_subs_pu16 (*(__m64 *)p1,  tmp2);
261             *(__m64 *)p1 = _mm_add_pi16 (lo_val, *(__m64 *)p1);
262             pic += 4;
263         }
264         //Mop up remaining pixels
265             while( count-- )
266         {
267             *pic = std::max( min_val, std::min( max_val , *pic )
268                     );
269             pic++;
270         }
271 
272         _mm_empty();
273         return;
274     }
275 #endif
276 
277     // NOTE: depending on a contigous chunk of memory being allocated
278     while (count--)
279     {
280         *pic = std::max( min_val, std::min( max_val, *pic ));
281         pic++;
282     }
283 }
284 
Clip()285 void Picture::Clip()
286 {
287     //just clips the straight picture data, not the upconverted data
288 
289     for (int c=0; c<3; ++c)
290         ClipComponent( *(m_pic_data[c]), (CompSort) c);
291 }
292 
ClipUpData()293 void Picture::ClipUpData()
294 {
295     //just clips the upconverted data
296 
297     for (int c=0; c<3; ++c){
298         if (m_up_pic_data[c])
299             ClipComponent( *(m_up_pic_data[c]), (CompSort) c );
300     }
301 
302 }
303 
ClearData()304 void Picture::ClearData()
305 {
306     for (int c=0;c<3;++c){
307         if (m_pic_data[c] != NULL){
308             delete m_pic_data[c];
309             m_pic_data[c] = NULL;
310         }
311 
312         if (m_up_pic_data[c] != NULL){
313             delete m_up_pic_data[c];
314             m_up_pic_data[c] = NULL;
315         }
316     }
317 
318 }
319 
ReconfigPicture(const PictureParams & pp)320 void Picture::ReconfigPicture(const PictureParams &pp )
321 {
322 
323     PictureParams old_pp = m_pparams;
324     m_pparams = pp;
325 
326     // HAve picture dimensions  or Chroma format changed ?
327     if (m_pparams.Xl() == old_pp.Xl() &&
328         m_pparams.Yl() == old_pp.Yl() &&
329         m_pparams.CFormat() == old_pp.CFormat())
330         return;
331 
332     // Picture dimensions have changed. Re-initialise
333     Init();
334 }
335 
336 
337 
338