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