libandroidplugin added
[mardrone] / mardrone / ARDrone_SDK_Version_1_8_20110726 / ARDroneLib / VLIB / P264 / p264_intra_pred.c
1 #include <VLIB/P264/p264_intra_pred.h>
2 #include <VP_Os/vp_os_malloc.h>
3 #include <VP_Os/vp_os_print.h>
4
5 C_RESULT p264_intra_4x4_luma (intra_4x4_mode_t mode, uint8_t *picture, uint32_t picture_width, uint32_t x, uint32_t y, uint32_t linesize)
6 // all mode partially validated (not all availability cases for each mode)
7 {
8 // A-M are the boundary pixels of the 4x4 block a-p
9 //
10 // M A B C D E F G H
11 // I a b c d
12 // J e f g h
13 // K i j k l
14 // L m n o p
15 //
16 // a-p = Pixel(x,y)
17   C_RESULT res = C_OK;
18         uint32_t A,B,C,D,E,F,G,H,I,J,K,L,M;
19         uint32_t IJKL;
20   uint32_t i;
21   uint32_t availability_flag=0;
22   uint8_t * picture_start;
23
24   // determine block availability
25   if (x==0)
26   {
27     // block 4x4 is located in the first column of the frame, A pixels are not available
28     availability_flag |= A_UNAVAILABLE;
29   }
30   if (y==0)
31   {
32     // block 4x4 is located in the first row of the frame, B and C  pixels are not available
33     availability_flag |= B_UNAVAILABLE | C_UNAVAILABLE;
34   }
35   if (x==picture_width-4)
36   {
37     // block 4x4 is located in the last column of the frame, C pixels are not available
38     availability_flag |= C_UNAVAILABLE;
39   }
40   if ((((x>>2)&0x01) == 1) &&  (((y>>2)&0x01) == 1))
41   {
42     // block 4x4 is located at the 'x' position in the following MB representation:
43     // - - - -
44     // - x - x
45     // - - - -
46     // - x - x
47     // therefore C is not available.
48     availability_flag |= C_UNAVAILABLE;
49   }
50   else if ((((x>>2)&0x03) == 3) &&  (((y>>2)&0x03) == 2))
51   {
52     // block 4x4 is located at the 'x' position in the following MB representation:
53     // - - - -
54     // - - - -
55     // - - - x
56     // - - - -
57     // therefore C is not available.
58     availability_flag |= C_UNAVAILABLE;
59   }
60
61   // check availability and mode
62   switch (mode)
63   {
64     case VERTICAL_4x4_MODE :
65     case DIAGONAL_DL_4x4_MODE :
66     case VERTICAL_LEFT_4x4_MODE :
67       if (availability_flag & B_UNAVAILABLE)
68       {
69         PRINT("%s : could no compute intra 4x4 mode_%d prediction on (%d,%d), B unavailable\n",__FUNCTION__,mode,x,y);
70         res = C_FAIL;
71       }
72       break;
73
74     case HORIZONTAL_4x4_MODE :
75     case HORIZONTAL_UP_4x4_MODE :
76       if (availability_flag & A_UNAVAILABLE)
77       {
78         PRINT("%s : could no compute intra 4x4 mode_%d prediction on (%d,%d) A unavailable\n",__FUNCTION__,mode,x,y);
79         res = C_FAIL;
80       }
81       break;
82
83     case DC_4x4_MODE :
84       // no restriction
85       break;
86
87     case DIAGONAL_DR_4x4_MODE :
88     case VERTICAL_RIGHT_4x4_MODE :
89     case HORIZONTAL_DOWN_4x4_MODE :
90       if (availability_flag & A_UNAVAILABLE)
91       {
92         PRINT("%s : could no compute intra 4x4 mode_%d prediction on (%d,%d) A unavailable\n",__FUNCTION__,mode,x,y);
93         res = C_FAIL;
94       }
95       if (availability_flag & B_UNAVAILABLE)
96       {
97         PRINT("%s : could no compute intra 4x4 mode_%d prediction on (%d,%d) B unavailable\n",__FUNCTION__,mode,x,y);
98         res = C_FAIL;
99       }
100       break;
101
102     default :
103       PRINT ("%s : mode_%d at block (%d,%d) is not a valid intra 4x4 prediction mode\n",__FUNCTION__,mode,x,y);
104       res = C_FAIL;
105   }
106
107   if (SUCCEED(res))
108   {
109     // make prediction
110     switch (mode)
111     {
112       case VERTICAL_4x4_MODE :
113         // jump to pixel A
114         picture += (linesize*(y-1)+x);
115         // load A-D pixel values
116         A = *picture++;
117         B = *picture++;
118         C = *picture++;
119         D = *picture++;
120         // extend ABCD line
121         for (i=0;i<4;i++)
122         {
123           // jump to next line
124           picture += (linesize-4);
125           // extend
126           *picture++ = A;
127           *picture++ = B;
128           *picture++ = C;
129           *picture++ = D;
130         }
131         break;
132
133       case HORIZONTAL_4x4_MODE :
134         // jump to pixel I
135         picture += (linesize*y+x-1);
136         for (i=0; i<4; i++)
137         {
138           // extend I-L pixels to a-d,e-h,i-l,m-p;
139           IJKL = *picture++;
140           *picture++ = IJKL;
141           *picture++ = IJKL;
142           *picture++ = IJKL;
143           *picture   = IJKL;
144           // jump to next row (pixel J,K,L)
145           picture += (linesize-4);
146         }
147         break;
148
149       case DC_4x4_MODE :
150         picture_start = picture;
151         uint32_t mean=0;
152         // compute mean over A-D and I-L pixels if available
153         if (!(availability_flag & B_UNAVAILABLE))
154         {
155           //jump to pixel A
156           picture += (linesize*(y-1)+x);
157           // sum pixel A-D
158           mean += *picture++;
159           mean += *picture++;
160           mean += *picture++;
161           mean += *picture;
162         }
163         if (!(availability_flag & A_UNAVAILABLE))
164         {
165           picture = picture_start;
166           //jump to pixel I
167           picture += (linesize*y+x-1);
168           for (i=0;i<4;i++)
169           {
170             mean += *picture;
171             //jump to next pixel
172             picture += linesize;
173           }
174         }
175
176         if (!(availability_flag & A_UNAVAILABLE) && !(availability_flag & B_UNAVAILABLE))
177           mean = (mean+4)>>3;
178         else if (!(availability_flag & A_UNAVAILABLE) || !(availability_flag & B_UNAVAILABLE))
179           mean = (mean+2)>>2;
180         else
181           mean=128;
182
183         // jump to pixel a and make prediction
184         picture = picture_start+linesize*y+x;
185         for (i=0;i<4;i++)
186         {
187           *picture++ = mean;
188           *picture++ = mean;
189           *picture++ = mean;
190           *picture++ = mean;
191           // jump to next line
192           picture = picture+linesize-4;
193         }
194         break;
195
196       case DIAGONAL_DL_4x4_MODE :
197         picture_start = picture;
198         // jump to pixel A
199         picture += (linesize*(y-1)+x);
200         // load A-D pixel values
201         A = *picture++;
202         B = *picture++;
203         C = *picture++;
204         D = *picture++;
205         // check block C availability
206         if (availability_flag & C_UNAVAILABLE)
207         {
208           // E,F,G,H not available, copy D value
209           E = F = G = H = D;
210         }
211         else
212         {
213           // load E-H pixel values
214           E = *picture++;
215           F = *picture++;
216           G = *picture++;
217           H = *picture++;
218         }
219
220         // jump to pixel a
221         picture = picture_start + linesize*y+x;
222
223          // make prediction
224         *picture++ = (A + C + 2*(B) + 2) >> 2; // a
225         *picture++ = (B + D + 2*(C) + 2) >> 2; // b
226         *picture++ = (C + E + 2*(D) + 2) >> 2; // c
227         *picture   = (D + F + 2*(E) + 2) >> 2; // d
228         picture += linesize-3;
229         *picture++ = (B + D + 2*(C) + 2) >> 2; // e
230         *picture++ = (C + E + 2*(D) + 2) >> 2; // f
231         *picture++ = (D + F + 2*(E) + 2) >> 2; // g
232         *picture   = (E + G + 2*(F) + 2) >> 2; // h
233         picture += linesize-3;
234         *picture++ = (C + E + 2*(D) + 2) >> 2; // i
235         *picture++ = (D + F + 2*(E) + 2) >> 2; // j
236         *picture++ = (E + G + 2*(F) + 2) >> 2; // k
237         *picture   = (F + H + 2*(G) + 2) >> 2; // l
238         picture += linesize-3;
239         *picture++ = (D + F + 2*(E) + 2) >> 2; // m
240         *picture++ = (E + G + 2*(F) + 2) >> 2; // n
241         *picture++ = (F + H + 2*(G) + 2) >> 2; // o
242         *picture   = (G + 3*(H) + 2) >> 2; // p
243         break;
244
245       case DIAGONAL_DR_4x4_MODE :
246         picture_start = picture;
247         // jump to pixel M
248         picture += (linesize*(y-1)+x-1);
249         // load M-D pixel values
250         M = *picture++;
251         A = *picture++;
252         B = *picture++;
253         C = *picture++;
254         D = *picture;
255         // jump to pixel I & load it
256         picture += linesize-4;
257         I = *picture;
258         // jump to pixel J & load it
259         picture += linesize;
260         J = *picture;
261         // jump to pixel K & load it
262         picture += linesize;
263         K = *picture;
264         // jump to pixel L & load it
265         picture += linesize;
266         L = *picture;
267         // jump to pixel a
268         picture = picture_start + linesize*y+x;
269         // make prediction
270         *picture++ = (I + 2*M + A + 2) >> 2; // a
271         *picture++ = (M + 2*A + B + 2) >> 2; // b
272         *picture++ = (A + 2*B + C + 2) >> 2; // c
273         *picture   = (B + 2*C + D + 2) >> 2; // d
274         picture += linesize-3;
275         *picture++ = (J + 2*I + M + 2) >> 2; // e
276         *picture++ = (I + 2*M + A + 2) >> 2; // f
277         *picture++ = (M + 2*A + B + 2) >> 2; // g
278         *picture   = (A + 2*B + C + 2) >> 2; // h
279         picture += linesize-3;
280         *picture++ = (K + 2*J + I + 2) >> 2; // i
281         *picture++ = (J + 2*I + M + 2) >> 2; // j
282         *picture++ = (I + 2*M + A + 2) >> 2; // k
283         *picture   = (M + 2*A + B + 2) >> 2; // l
284         picture += linesize-3;
285         *picture++ = (L + 2*K + J + 2) >> 2; // m
286         *picture++ = (K + 2*J + I + 2) >> 2; // n
287         *picture++ = (J + 2*I + M + 2) >> 2; // o
288         *picture   = (I + 2*M + A + 2) >> 2; // p
289         break;
290
291       case VERTICAL_RIGHT_4x4_MODE :
292         picture_start = picture;
293         // jump to pixel M
294         picture += (linesize*(y-1)+x-1);
295         // load M-D pixel values
296         M = *picture++;
297         A = *picture++;
298         B = *picture++;
299         C = *picture++;
300         D = *picture;
301         // jump to pixel I & load it
302         picture += linesize-4;
303         I = *picture;
304         // jump to pixel J & load it
305         picture += linesize;
306         J = *picture;
307         // jump to pixel K & load it
308         picture += linesize;
309         K = *picture;
310         // jump to pixel L & load it
311         picture += linesize;
312         L = *picture;
313         // jump to pixel a
314         picture = picture_start + linesize*y+x;
315         // make prediction
316         *picture++ = (M + A + 1) >> 1; // a
317         *picture++ = (A + B + 1) >> 1; // b
318         *picture++ = (B + C + 1) >> 1; // c
319         *picture   = (C + D + 1) >> 1; // d
320         picture += linesize-3;
321         *picture++ = (I + 2*M + A + 2) >> 2; // e
322         *picture++ = (M + 2*A + B + 2) >> 2; // f
323         *picture++ = (A + 2*B + C + 2) >> 2; // g
324         *picture   = (B + 2*C + D + 2) >> 2; // h
325         picture += linesize-3;
326         *picture++ = (M + 2*I + J + 2) >> 2; // i
327         *picture++ = (M + A + 1) >> 1; // j
328         *picture++ = (A + B + 1) >> 1; // k
329         *picture   = (B + C + 1) >> 1; // l
330         picture += linesize-3;
331         *picture++ = (I + 2*J + K + 2) >> 2; // m
332         *picture++ = (I + 2*M + A + 2) >> 2; // n
333         *picture++ = (M + 2*A + B + 2) >> 2; // o
334         *picture   = (A + 2*B + C + 2) >> 2; // p
335         break;
336
337       case HORIZONTAL_DOWN_4x4_MODE :
338         picture_start = picture;
339         // jump to pixel M
340         picture += (linesize*(y-1)+x-1);
341         // load M-D pixel values
342         M = *picture++;
343         A = *picture++;
344         B = *picture++;
345         C = *picture++;
346         D = *picture;
347         // jump to pixel I & load it
348         picture += linesize-4;
349         I = *picture;
350         // jump to pixel J & load it
351         picture += linesize;
352         J = *picture;
353         // jump to pixel K & load it
354         picture += linesize;
355         K = *picture;
356         // jump to pixel L & load it
357         picture += linesize;
358         L = *picture;
359         // jump to pixel a
360         picture = picture_start + linesize*y+x;
361         // make prediction
362         *picture++ = (M + I + 1) >> 1; // a
363         *picture++ = (I + 2*M + A + 2) >> 2; // b
364         *picture++ = (M + 2*A + B + 2) >> 2; // c
365         *picture   = (A + 2*B + C + 2) >> 2; // d
366         picture += linesize-3;
367         *picture++ = (I + J + 1) >> 1; // e
368         *picture++ = (M + 2*I + J + 2) >> 2; // f
369         *picture++ = (M + I + 1) >> 1; // g
370         *picture   = (I + 2*M + A + 2) >> 2; // h
371         picture += linesize-3;
372         *picture++ = (J + K + 1) >> 1; // i
373         *picture++ = (I + 2*J + K + 2) >> 2; // j
374         *picture++ = (I + J + 1) >> 1; // k
375         *picture   = (M + 2*I + J + 2) >> 2; // l
376         picture += linesize-3;
377         *picture++ = (K + L + 1) >> 1; // m
378         *picture++ = (J + 2*K + L + 2) >> 2; // n
379         *picture++ = (J + K + 1) >> 1; // o
380         *picture   = (I + 2*J + K + 2) >> 2; // p
381
382         break;
383
384       case VERTICAL_LEFT_4x4_MODE :
385         picture_start = picture;
386         // jump to pixel A
387         picture += (linesize*(y-1)+x);
388         // load A-D pixel values
389         A = *picture++;
390         B = *picture++;
391         C = *picture++;
392         D = *picture++;
393         // check block C availability
394         if (availability_flag & C_UNAVAILABLE)
395         {
396           // E,F,G,H not available, copy D value
397           E = F = G = H = D;
398         }
399         else
400         {
401           // load E-H pixel values
402           E = *picture++;
403           F = *picture++;
404           G = *picture++;
405           H = *picture;
406         }
407         // jump to pixel a
408         picture = picture_start + linesize*y+x;
409         // make prediction
410         *picture++ = (A + B + 1) >> 1; // a
411         *picture++ = (B + C + 1) >> 1; // b
412         *picture++ = (C + D + 1) >> 1; // c
413         *picture   = (D + E + 1) >> 1; // d
414         picture += linesize-3;
415         *picture++ = (A + 2*B + C + 2) >> 2; // e
416         *picture++ = (B + 2*C + D + 2) >> 2; // f
417         *picture++ = (C + 2*D + E + 2) >> 2; // g
418         *picture   = (D + 2*E + F + 2) >> 2; // h
419         picture += linesize-3;
420         *picture++ = (B + C + 1) >> 1; // i
421         *picture++ = (C + D + 1) >> 1; // j
422         *picture++ = (D + E + 1) >> 1; // k
423         *picture   = (E + F + 1) >> 1; // l
424         picture += linesize-3;
425         *picture++ = (B + 2*C + D + 2) >> 2; // m
426         *picture++ = (C + 2*D + E + 2) >> 2; // n
427         *picture++ = (D + 2*E + F + 2) >> 2; // o
428         *picture   = (E + 2*F + G + 2) >> 2; // p
429         break;
430
431       case HORIZONTAL_UP_4x4_MODE :
432         picture_start = picture;
433         // jump to pixel I & load it
434         picture += (linesize*y+x-1);
435         I = *picture;
436         // jump to pixel J & load it
437         picture += linesize;
438         J = *picture;
439         // jump to pixel K & load it
440         picture += linesize;
441         K = *picture;
442         // jump to pixel L & load it
443         picture += linesize;
444         L = *picture;
445         // jump to pixel a
446         picture = picture_start + linesize*y+x;
447         // make prediction
448         *picture++ = (I + J + 1) >> 1; // a
449         *picture++ = (I + 2*J + K + 2) >> 2; // b
450         *picture++ = (J + K + 1) >> 1; // c
451         *picture   = (J + 2*K + L + 2) >> 2; // d
452         picture += linesize-3;
453         *picture++ = (J + K + 1) >> 1; // e
454         *picture++ = (J + 2*K + L + 2) >> 2; // f
455         *picture++ = (K + L + 1) >> 1; // g
456         *picture   = (K + 2*L + L + 2) >> 2; // h
457         picture += linesize-3;
458         *picture++ = (K + L + 1) >> 1; // i
459         *picture++ = (K + 2*L + L + 2) >> 2; // j
460         *picture++ = L; // k
461         *picture   = L; // l
462         picture += linesize-3;
463         *picture++ = L; // m
464         *picture++ = L; // n
465         *picture++ = L; // o
466         *picture   = L; // p
467         break;
468
469       default :
470         PRINT ("%s : mode_%d at block (%d,%d) is not a valid intra 4x4 prediction mode\n",__FUNCTION__,mode,x,y);
471         res = C_FAIL;
472     }
473   }
474         return res;
475 }
476
477 C_RESULT p264_intra_16x16_luma (intra_16x16_luma_mode_t mode, uint8_t *picture, uint32_t x, uint32_t y, uint32_t linesize)
478 // Hori,Verti, Plane mode validated, DC missing
479 {
480 // Ai-Bi-M are the boundary pixels of the 16x16 block p(,)
481 //
482 //   M      B0     B1  ...    B15
483 //  A0  p(0,0) p(0,1)      p(0,15)
484 //  A1  p(1,0)
485 //
486 // ...             ...
487 //
488 // A15  p(15,0)            p(15,15)
489 //
490
491   C_RESULT res = C_OK;
492   uint32_t availability_flag=0;
493   uint8_t * picture_start;
494   uint32_t i,j;
495
496   // determine block availability
497   if (x==0)
498   {
499     // block 16x16 is located in the first column of the frame, A pixels are not available
500     availability_flag |= A_UNAVAILABLE;
501   }
502   if (y==0)
503   {
504     // block 16x16 is located in the first row of the frame, B pixels are not available
505     availability_flag |= B_UNAVAILABLE;
506   }
507
508   // check availability and mode
509   switch (mode)
510   {
511     case VERTICAL_16x16_LUMA_MODE :
512       if (availability_flag & B_UNAVAILABLE)
513       {
514         PRINT("%s : could no compute intra 16x16 mode_%d prediction on (%d,%d), B unavailable\n",__FUNCTION__,mode,x,y);
515         res = C_FAIL;
516       }
517       break;
518
519     case HORIZONTAL_16x16_LUMA_MODE :
520       if (availability_flag & A_UNAVAILABLE)
521       {
522         PRINT("%s : could no compute intra 16x16 mode_%d prediction on (%d,%d) A unavailable\n",__FUNCTION__,mode,x,y);
523         res = C_FAIL;
524       }
525       break;
526
527     case DC_16x16_LUMA_MODE :
528       // no restriction
529       break;
530
531     case PLANE_16x16_LUMA_MODE :
532      if (availability_flag & A_UNAVAILABLE)
533       {
534         PRINT("%s : could no compute intra 16x16 mode_%d prediction on (%d,%d) A unavailable\n",__FUNCTION__,mode,x,y);
535         res = C_FAIL;
536       }
537       if (availability_flag & B_UNAVAILABLE)
538       {
539         PRINT("%s : could no compute intra 16x16 mode_%d prediction on (%d,%d) B unavailable\n",__FUNCTION__,mode,x,y);
540         res = C_FAIL;
541       }
542       break;
543
544     default :
545       PRINT ("%s : mode_%d is not a valid intra 16x16 prediction mode\n",__FUNCTION__,mode);
546       res = C_FAIL;
547   }
548
549   if (SUCCEED(res))
550   {
551     // make prediction
552     switch (mode)
553     {
554       case  DC_16x16_LUMA_MODE :
555       {
556         picture_start = picture;
557         uint32_t mean=0;
558         // compute mean over Ai and Bi pixels if available
559         if (!(availability_flag & B_UNAVAILABLE))
560         {
561           //jump to pixel B0
562           picture += (linesize*(y-1)+x);
563           // sum pixel Bi
564           i=16;
565           while(i--)
566           {
567             mean += *picture++;
568           }
569         }
570
571         if (!(availability_flag & A_UNAVAILABLE))
572         {
573           picture = picture_start;
574           //jump to pixel A0
575           picture += (linesize*y+x-1);
576           // sum pixel Ai
577           i=16;
578           while(i--)
579           {
580             mean += *picture;
581             picture += linesize;
582           }
583         }
584
585         if (!(availability_flag & A_UNAVAILABLE) && !(availability_flag & B_UNAVAILABLE))
586           mean = (mean+16)>>5;
587         else if (!(availability_flag & A_UNAVAILABLE) || !(availability_flag & B_UNAVAILABLE))
588           mean = (mean+8)>>4;
589         else
590           mean=128;
591
592         // jump to pixel p(0,0) and make prediction
593         picture = picture_start+linesize*y+x;
594         j=16;
595         while(j--)
596         {
597           i=16;
598           while(i--)
599           {
600             *picture++ = mean;
601           }
602           picture += (linesize-16);
603         }
604       }
605         break;
606
607       case HORIZONTAL_16x16_LUMA_MODE :
608       {
609         //jump to pixel A0
610         picture += (linesize*y+x-1);
611         // extend pixel Ai horizontally
612         uint8_t pixel_buf;
613         j=16;
614         while(j--)
615         {
616           // load Ai
617           pixel_buf = *picture++;
618           // extend Ai
619           i=16;
620           while(i--)
621           {
622             *picture++ = pixel_buf;
623           }
624           // jump to Ai+1
625           picture += (linesize-17);
626         }
627       }
628         break;
629
630       case VERTICAL_16x16_LUMA_MODE :
631       {
632         // jump to pixel B0
633         picture += (linesize*(y-1)+x);
634         uint8_t line_buf[16];
635         // load Bi line
636         vp_os_memcpy(line_buf,picture,16*sizeof(uint8_t));
637         // extend Bi line vertically
638         i=16;
639         while(i--)
640         {
641           // jump to next line
642           picture += linesize;
643           // copy line
644           vp_os_memcpy(picture,line_buf,16*sizeof(uint8_t));
645         }
646       }
647         break;
648
649       case PLANE_16x16_LUMA_MODE :
650       {
651         int32_t A15,B15;
652         picture_start = picture;
653         // compute H :
654         // H' = 1* (B8 - B6) +
655         //      2* (B9 - B5) +
656         //      3*(B10 - B4) +
657         //      4*(B11 - B3) +
658         //      5*(B12 - B2) +
659         //      6*(B13 - B1) +
660         //      7*(B14 - B0) +
661         //      8*(B15 - M)
662         //  H = (5*H' + 32) / 64
663         // jump to M
664         picture += (linesize*(y-1)+x-1);
665         int32_t H=0;
666         for (i=8;i>=1;i--)
667         {
668           H -= i*(*picture++);
669         }
670         for (i=1;i<=8;i++)
671         {
672           H += i*(*++picture);
673         }
674         B15 = *(picture);
675         H = (5*H + 32)>>6;
676
677         // compute V :
678         // V' = 1* (A8 - A6) +
679         //      2* (A9 - A5) +
680         //      3*(A10 - A4) +
681         //      4*(A11 - A3) +
682         //      5*(A12 - A2) +
683         //      6*(A13 - A1) +
684         //      7*(A14 - A0) +
685         //      8*(A15 - M)
686         //  V = (5*V' + 32) / 64
687         int32_t V=0;
688         // jump to M
689         picture = picture_start + (linesize*(y-1)+x-1);
690         for (i=8;i>=1;i--)
691         {
692           V -= i*(*picture);
693           picture += linesize;
694         }
695         for (i=1;i<=8;i++)
696         {
697           picture += linesize;
698           V += i*(*picture);
699         }
700         A15 = *(picture);
701         V = (5*V + 32)>>6;
702
703         // fill pixel p(i,j) of the 16x16 block with the following rule :
704         // a = 16 * (A15 + B15 + 1) - 7*(V+H)
705         // b(i,j) = a + V * j + H * i
706         // p(i,j) = SATURATE_U8(b(i,j) / 32)
707         // SATURATE_U8() function indicates that the result of the operation should be bounded to an unsigned 8-bit range (0..255)
708
709         int32_t a = ((A15 + B15 + 1)<<4) - 7*(V+H);
710
711         // jump to p(0,0)
712         picture = picture_start + (linesize*y+x);
713         // make prediction
714         int32_t pixel_buf;
715         for (j=0;j<16;j++)
716         {
717           for (i=0;i<16;i++)
718           {
719             pixel_buf = (a + V*j + H*i)>>5;
720             // saturation
721             if (pixel_buf > 0xFF)
722               pixel_buf = 0xFF;
723             else if (pixel_buf < 0)
724               pixel_buf = 0;
725             *picture++ = pixel_buf;
726           }
727           // jump to next line
728           picture += linesize - 16;
729         }
730       }
731         break;
732
733       default :
734         PRINT ("%s : mode_%d is not a valid intra 16x16 prediction mode\n",__FUNCTION__,mode);
735         res = C_FAIL;
736     }
737   }
738   return res;
739 }
740
741
742 // DC_8x8_CHROMA_MODE is slightly different from DC_16x16_LUMA_MODE
743 // each 8x8 block is divided into 4 blocks
744 //  -------------------
745 // | all     | single1 |
746 //  --------- ---------
747 // | single2 | all     |
748 //  -------------------
749 //
750 // In "all" block, adjacent 4x4 blocks A and B are used to compute the DC value as in DC_16x16_LUMA_MODE.
751 //   If B is not available, A is used instead of B.
752 //   If A is not available, B is used instead of A.
753 //   If neither A nor B are available, DC is set to 128.
754 // In "single1" priority is given to B block to compute the DC value. If B is not available, A is used instead of B.
755 //   If neither A nor B are available, DC is set to 128.
756 // In "single2" priority is given to A block to compute the DC value. If A is not available, B is used instead of A.
757 //   If neither A nor B are available, DC is set to 128.
758 //
759 // Next scheme summarize the block used to compute the DC value in raster scan ordered image :
760 //          B blocks
761 //  A   -----------------
762 //     | x    x | A    A |
763 //  b  | x    x | A    A |
764 //  l   -------- --------  ...
765 //  o  | B    B | AB   B |
766 //  c  | B    B | A   AB |
767 //  k   -------- --------
768 //  s          ...
769
770 static uint8_t chroma_DC_all(uint8_t *picture, uint32_t x, uint32_t y, uint32_t linesize)
771 {
772   // this function assumes that (x,y) corresponds to a "all" DC block 4x4
773   uint32_t mean=0;
774   uint8_t *picture_start = picture;
775   if (x<=4 && y<=4)
776   {
777     // top left 8x8 chroma block, A&B are not available
778     mean = 128;
779   }
780   else
781   {
782     if (y>4)
783     {
784       // 8x8 chroma block is not located in the first row
785       // sum B
786       picture = picture_start + linesize*((y&0xFFF8)-1) + x;
787       mean += *picture++;
788       mean += *picture++;
789       mean += *picture++;
790       mean += *picture;
791     }
792     if (x>4)
793     {
794       // 8x8 chroma block is not located in the first column
795       // sum A
796       picture = picture_start + linesize*y + (x&0xFFF8)-1;
797       mean += *picture;
798       picture += linesize;
799       mean += *picture;
800       picture += linesize;
801       mean += *picture;
802       picture += linesize;
803       mean += *picture;
804     }
805     if (x<=4 || y<=4)
806     {
807       // only one adjacent block (A or B) is used to compute DC value
808       mean = mean>>2;
809     }
810     else
811     {
812       // both A and B blocks are used to compute DC value
813       mean = mean>>3;
814     }
815   }
816   return mean;
817 }
818
819 static uint8_t chroma_DC_single(uint8_t *picture, uint32_t x, uint32_t y, uint32_t linesize)
820 {
821   // this function assumes that (x,y) corresponds to a "single" DC block 4x4
822   uint32_t mean=0;
823   if (x<=4 && y<=4)
824   {
825     // top left 8x8 chroma block, A&B are not available
826     mean = 128;
827   }
828   else
829   {
830     if ((x<=4) ||  ((y>4) && ((y&0x07) == 0)))
831     {
832       // block 4x4 is located either on the first chroma 8x8 column or at the top right of a 8x8 chroma
833       // sum B
834       picture += linesize*((y&0xFFF8)-1) + x;
835       mean += *picture++;
836       mean += *picture++;
837       mean += *picture++;
838       mean += *picture;
839       mean = mean>>2;
840     }
841     else
842     {
843       // sum A
844       picture += linesize*y + (x&0xFFF8) - 1;
845       mean += *picture;
846       picture += linesize;
847       mean += *picture;
848       picture += linesize;
849       mean += *picture;
850       picture += linesize;
851       mean += *picture;
852       mean = mean>>2;
853     }
854   }
855   return mean;
856 }
857
858 static void fill_4x4_DC(uint8_t* picture, uint32_t x, uint32_t y, uint32_t linesize, uint8_t value)
859 {
860   picture += linesize*y+x;
861   uint32_t i;
862   for (i=0;i<4;i++)
863   {
864     *picture++ = value;
865     *picture++ = value;
866     *picture++ = value;
867     *picture++ = value;
868     // jump to next line
869     picture += linesize-4;
870   }
871 }
872
873 C_RESULT p264_intra_8x8_chroma (intra_8x8_chroma_mode_t mode, uint8_t *picture, uint32_t x, uint32_t y, uint32_t linesize)
874 // CHROMA DC mode validated on one MB
875 {
876 // Ai-Bi-M are the boundary pixels of the 16x16 block p(y,x)
877 //
878 //   M      B0     B1  ...    B7
879 //  A0  p(0,0) p(0,1)      p(0,7)
880 //  A1  p(1,0)
881 //
882 // ...             ...
883 //
884 // A7  p(7,0)            p(7,7)
885 //
886
887   C_RESULT res = C_OK;
888   uint32_t availability_flag=0;
889   uint8_t * picture_start;
890   int32_t i,j;
891
892   // determine block availability
893   if (x==0)
894   {
895     // block 8x8 is located in the first column of the frame, A pixels are not available
896     availability_flag |= A_UNAVAILABLE;
897   }
898   if (y==0)
899   {
900     // block 8x8 is located in the first row of the frame, B pixels are not available
901     availability_flag |= B_UNAVAILABLE;
902   }
903
904   // check availability and mode
905   switch (mode)
906   {
907     case VERTICAL_8x8_CHROMA_MODE :
908       if (availability_flag & B_UNAVAILABLE)
909       {
910         PRINT("%s : could no compute chroma intra 8x8 mode_%d prediction on (%d,%d), B unavailable\n",__FUNCTION__,mode,x,y);
911         res = C_FAIL;
912       }
913       break;
914
915     case HORIZONTAL_8x8_CHROMA_MODE :
916       if (availability_flag & A_UNAVAILABLE)
917       {
918         PRINT("%s : could no compute chroma intra 8x8 mode_%d prediction on (%d,%d) A unavailable\n",__FUNCTION__,mode,x,y);
919         res = C_FAIL;
920       }
921       break;
922
923     case DC_8x8_CHROMA_MODE :
924       // no restriction
925       break;
926
927     case PLANE_8x8_CHROMA_MODE :
928      if (availability_flag & A_UNAVAILABLE)
929       {
930         PRINT("%s : could no compute chroma intra 8x8 mode_%d prediction on (%d,%d) A unavailable\n",__FUNCTION__,mode,x,y);
931         res = C_FAIL;
932       }
933       if (availability_flag & B_UNAVAILABLE)
934       {
935         PRINT("%s : could no compute chroma intra 8x8 mode_%d prediction on (%d,%d) B unavailable\n",__FUNCTION__,mode,x,y);
936         res = C_FAIL;
937       }
938       break;
939
940     default :
941       PRINT ("%s : mode_%d is not a valid chroma intra 8x8 prediction mode\n",__FUNCTION__,mode);
942       res = C_FAIL;
943   }
944
945   if (SUCCEED(res))
946   {
947     // make prediction
948     switch (mode)
949     {
950       case  DC_8x8_CHROMA_MODE :
951       {
952         // DC_8x8_CHROMA_MODE is slightly different from DC_16x16_LUMA_MODE
953         // each 8x8 block is divided into 4 blocks
954         //  -------------------
955         // | all     | single1 |
956         //  --------- ---------
957         // | single2 | all     |
958         //  -------------------
959         //
960         // In "all" block, adjacent 4x4 blocks A and B are used to compute the DC value as in DC_16x16_LUMA_MODE.
961         //   If B is not available, A is used instead of B.
962         //   If A is not available, B is used instead of A.
963         //   If neither A nor B are available, DC is set to 128.
964         // In "single1" priority is given to B block to compute the DC value. If B is not available, A is used instead of B.
965         //   If neither A nor B are available, DC is set to 128.
966         // In "single2" priority is given to A block to compute the DC value. If A is not available, B is used instead of A.
967         //   If neither A nor B are available, DC is set to 128.
968         //
969         // Next scheme summarize the block used to compute the DC value in raster scan ordered image :
970         //          B blocks
971         //  A   -----------------
972         //     | x    x | A    A |
973         //  b  | x    x | A    A |
974         //  l   -------- --------  ...
975         //  o  | B    B | AB   B |
976         //  c  | B    B | A   AB |
977         //  k   -------- --------
978         //  s          ...
979
980         uint32_t mean;
981
982         // compute DC value of block_4x4(0,0)
983         mean = chroma_DC_all(picture,x,y,linesize);
984         // fill the block with DC
985         fill_4x4_DC(picture,x,y,linesize,mean);
986
987         // compute DC value of block_4x4(4,0)
988         mean = chroma_DC_single(picture,x+4,y,linesize);
989         // fill the block with DC
990         fill_4x4_DC(picture,x+4,y,linesize,mean);
991
992         // compute DC value of block_4x4(0,4)
993         mean = chroma_DC_single(picture,x,y+4,linesize);
994         // fill the block with DC
995         fill_4x4_DC(picture,x,y+4,linesize,mean);
996
997         // compute DC value of block_4x4(4,4)
998         mean = chroma_DC_all(picture,x+4,y+4,linesize);
999         // fill the block with DC
1000         fill_4x4_DC(picture,x+4,y+4,linesize,mean);
1001       }
1002         break;
1003
1004       case HORIZONTAL_8x8_CHROMA_MODE :
1005       {
1006         //jump to pixel A0
1007         picture += (linesize*y+x-1);
1008         // extend pixel Ai horizontally
1009         uint8_t pixel_buf;
1010         j=8;
1011         while(j--)
1012         {
1013           // load Ai
1014           pixel_buf = *picture++;
1015           // extend Ai
1016           i=8;
1017           while(i--)
1018           {
1019             *picture++ = pixel_buf;
1020           }
1021           // jump to Ai+1
1022           picture += (linesize-9);
1023         }
1024       }
1025         break;
1026
1027       case VERTICAL_8x8_CHROMA_MODE :
1028       {
1029         // jump to pixel B0
1030         picture += (linesize*(y-1)+x);
1031         uint8_t line_buf[8];
1032         // load Bi line
1033         vp_os_memcpy(line_buf,picture,8*sizeof(uint8_t));
1034         // extend Bi line vertically
1035         i=8;
1036         while(i--)
1037         {
1038           // jump to next line
1039           picture += linesize;
1040           // copy line
1041           vp_os_memcpy(picture,line_buf,8*sizeof(uint8_t));
1042         }
1043       }
1044         break;
1045
1046       case PLANE_8x8_CHROMA_MODE :
1047       {
1048         int32_t A7,B7;
1049         picture_start = picture;
1050         // compute H :
1051         // H' = 1* (B4 - B2) +
1052         //      2* (B5 - B1) +
1053         //      3* (B6 - B0) +
1054         //      4* (B7 -  M)
1055         //  H = (34*H' + 32) / 64
1056         // jump to M
1057         picture += (linesize*(y-1)+x-1);
1058         int32_t H=0;
1059         for (i=4;i>=1;i--)
1060         {
1061           H -= i*(*picture++);
1062         }
1063         for (i=1;i<=4;i++)
1064         {
1065           H += i*(*++picture);
1066         }
1067         B7 = *(picture);
1068         H = (34*H + 32)>>6;
1069
1070         // compute V :
1071         // V' = 1* (A4 - A2) +
1072         //      2* (A5 - A1) +
1073         //      3* (A6 - A0) +
1074         //      4* (A7 -  M)
1075          //  V = (34*V' + 32) / 64
1076         int32_t V=0;
1077         // jump to M
1078         picture = picture_start + (linesize*(y-1)+x-1);
1079         for (i=4;i>=1;i--)
1080         {
1081           V -= i*(*picture);
1082           picture += linesize;
1083         }
1084         for (i=1;i<=4;i++)
1085         {
1086           picture += linesize;
1087           V += i*(*picture);
1088         }
1089         A7 = *(picture);
1090         V = (34*V + 32)>>6;
1091
1092         // fill pixel p(i,j) of the 16x16 block with the following rule :
1093         // a = 16 * (A7 + B7 + 1) - 3*(V+H)
1094         // b(i,j) = a + V * j + H * i
1095         // p(i,j) = SATURATE_U8(b(i,j) / 32)
1096         // SATURATE_U8() function indicates that the result of the operation should be bounded to an unsigned 8-bit range (0..255)
1097
1098         int32_t a = ((A7 + B7 + 1)<<4) - 3*(V+H);
1099
1100         // jump to p(0,0)
1101         picture = picture_start + (linesize*y+x);
1102         // make prediction
1103         int32_t pixel_buf;
1104         for (j=0;j<8;j++)
1105         {
1106           for (i=0;i<8;i++)
1107           {
1108             pixel_buf = (a + V*j + H*i)>>5;
1109             // saturation
1110             if (pixel_buf > 0xFF)
1111               pixel_buf = 0xFF;
1112             else if (pixel_buf < 0)
1113               pixel_buf = 0;
1114             *picture++ = pixel_buf;
1115           }
1116           // jump to next line
1117           picture += linesize - 8;
1118         }
1119       }
1120         break;
1121
1122       default :
1123         PRINT ("%s : mode_%d is not a valid chrome intra 8x8 prediction mode\n",__FUNCTION__,mode);
1124         res = C_FAIL;
1125     }
1126   }
1127   return res;
1128 }