1/*
2 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11
12/****************************************************************************
13*
14*   Module Title :     onyxdxv.c
15*
16*   Description  :     VP80 interface to DXV.
17*
18*****************************************************************************
19*/
20/****************************************************************************
21*  Header Files
22****************************************************************************/
23#include <math.h>   // For Abs()
24#include "pragmas.h"
25
26#include "vpxdxv.h"
27#include "vpxdxv_plugin.h"
28
29#include "onyxd_int.h"
30#include "onyx.h"
31#include "codec_common_interface.h"
32#include "vpx_scale/vpxscale.h"
33#include "vpx_mem/vpx_mem.h"
34#include "postproc.h"
35#include "vpxblit.h"
36#include "g_common.h"
37#include "vpx_scale/yv12extend.h"
38
39#include <limits.h>
40#include <stdio.h>
41#include "scale_mode.h"
42#include "onyx_pb_interface.h"
43
44/****************************************************************************
45*  Macros
46****************************************************************************/
47
48#define VP8_FOURCC DXL_MKFOURCC( 'V', 'P', '8', '0')
49
50extern void vp8_blit_text(const char *msg, unsigned char *address, const int pitch);
51
52
53/****************************************************************************
54*  Typedefs
55****************************************************************************/
56
57typedef struct  // YUV buffer configuration structure
58{
59    int   y_width;
60    int   y_height;
61    int   y_stride;
62
63    int   uv_width;
64    int   uv_height;
65    int   uv_stride;
66
67    char *y_buffer;
68    char *u_buffer;
69    char *v_buffer;
70
71    char *uv_start;
72    int   uv_dst_area;
73    int   uv_used_area;
74
75    unsigned char *y_ptr_scrn;
76    unsigned char *u_ptr_scrn;
77    unsigned char *v_ptr_scrn;
78
79
80} DXV_YUV_BUFFER_CONFIG;
81
82
83typedef void ((*vp8blit_func)(unsigned char *, int, YUV_BUFFER_CONFIG *));
84
85/* define an x_image structure based on the core x_image struct */
86typedef struct t_ximage_codec
87{
88    DXV_YUV_BUFFER_CONFIG frame_buffer;
89    VP8D_COMP *my_pbi;
90    VP8_COMMON *common;
91    int owned;
92    int decompressed_once;
93
94    int sizeof_pixel;
95    vp8blit_func blitter;
96
97    unsigned int ppl_tag;
98    unsigned int bd_tag;
99    unsigned int *supported_output_format_list;
100
101    int cpu_free;
102    int postproc;
103    int add_noise;
104    int deinterlace;
105
106    int post_proc2time;
107    int post_proc4time;
108
109    int hs;
110    int hr;
111    int vs;
112    int vr;
113    YV12_BUFFER_CONFIG this_buffer;
114    YV12_BUFFER_CONFIG scaled_buffer;
115    YV12_BUFFER_CONFIG *passed_in_buffer;
116
117    int avgq;
118    int ppcount;
119
120
121} VP8_XIMAGE, *VP8_XIMAGE_HANDLE;
122
123
124/****************************************************************************
125*  Modul Statics
126****************************************************************************/
127static unsigned int g_vp8_preferred_output_format_list[] =
128{
129    VPXDXV_YUY2,
130    VPXDXV_UYVY,
131    VPXDXV_RGB8888,
132    VPXDXV_RGB888,
133    VPXDXV_RGB555,
134    VPXDXV_RGB565,
135    VPXDXV_YV12,
136    VPXDXV_I420,
137
138//    VPXDXV_YV12,
139//    VPXDXV_YUY2,
140//    VPXDXV_RGB565,
141//    VPXDXV_UYVY,
142    0
143};
144
145/****************************************************************************
146*  Forward declarationss
147****************************************************************************/
148void onyx_set_parameter(XIMAGE_HANDLE src, int Command, unsigned int Parameter);
149
150static int onyx_get_output_format(XIMAGE_HANDLE src, unsigned int *bd_tag);
151static int onyx_set_output_format(XIMAGE_HANDLE src, unsigned int bd_tag);
152
153static int vpx_get_size_of_pixel(unsigned int bd);
154
155/****************************************************************************
156*  Imports
157****************************************************************************/
158
159#define __Clamp255(x)   (unsigned char) ( (x) < 0 ? 0 : ( (x) <= 255 ? (x) : 255 ) )
160
161/*
162//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
163//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
164*/
165/*
166//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
167//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
168*/
169void
170convert_yv12_buffer_types(YV12_BUFFER_CONFIG *source, DXV_YUV_BUFFER_CONFIG *dest)
171{
172    dest->y_buffer = (char *)source->y_buffer;
173    dest->u_buffer = (char *)source->u_buffer;
174    dest->v_buffer = (char *)source->v_buffer;
175    dest->y_width  = source->y_width;
176    dest->y_height = source->y_height;
177    dest->y_stride = source->y_stride;
178    dest->uv_width  = source->uv_width;
179    dest->uv_height = source->uv_height;
180    dest->uv_stride = source->uv_stride;
181}
182
183/*
184//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
185//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
186*/
187
188
189int onyx_blit
190(
191    XIMAGE_HANDLE src,
192    VSCREEN_HANDLE v_screen,
193    DXV_YUV_BUFFER_CONFIG *frame_buffer,
194    int x,
195    int y
196)
197{
198    VP8_XIMAGE_HANDLE tab = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
199    VP8D_COMP *pbi;
200    VP8_COMMON *common = tab->common;
201    pbi = tab->my_pbi;
202
203    if (v_screen) /* if there is a v_screen, blit to it */
204    {
205        unsigned char *ptr_scrn;
206        int this_pitch, vs_height, vs_width;
207        unsigned int start_tick, stop_tick;
208
209        vpxdxv_get_vscreen_attributes(v_screen, (void **)&ptr_scrn,  &vs_width, &vs_height, &this_pitch);
210
211        if (ptr_scrn)
212        {
213            int w, h;
214
215            int p_size;
216            int view_x, view_y, view_w;
217            int hs, hr, vs, vr;
218            int neww, newh;
219            int cw, ch;
220            int microseconds_available = (int)(1000000 / 30);
221
222            microseconds_available = microseconds_available * tab->cpu_free / 100;
223
224            if (pbi)
225            {
226                microseconds_available -= pbi->decode_microseconds;
227
228                if (tab->cpu_free == 0)
229                    microseconds_available = INT_MAX;
230
231                if (tab->post_proc2time == 0)
232                    tab->post_proc2time = pbi->decode_microseconds * 1 / 2;
233
234                if (tab->post_proc4time == 0)
235                    tab->post_proc4time = pbi->decode_microseconds;
236            }
237
238
239            if (tab->ppcount == 0)
240            {
241                tab->post_proc2time = 0;
242                tab->post_proc4time = 0;
243                tab->ppcount = 64;
244            }
245            else
246            {
247                tab->ppcount --;
248            }
249
250            vpxdxv_get_vscreen_view(v_screen, &view_x, &view_y, &view_w, NULL);
251
252            Scale2Ratio(common->horiz_scale, &hr, &hs);
253            Scale2Ratio(common->vert_scale, &vr, &vs);
254
255            if (tab->postproc && tab->passed_in_buffer == 0)
256            {
257                int show_text = 0;
258
259                unsigned char message[512];
260
261                int pp = tab->postproc;
262                int q = (tab->avgq + 4) / 8;
263                int noise = 0;
264
265                vp8_clear_system_state();
266
267                if (pp >= 1000)
268                {
269                    pp -= 1000;
270                    noise = pp / 100;
271                    pp = pp - noise * 100;
272                }
273
274                if (pp >= 300)
275                {
276                    pp -= 300;
277                    show_text = 3;
278                }
279                else if (pp >= 200)
280                {
281                    pp -= 200;
282                    show_text = 2;
283                }
284                else if (pp >= 100)
285                {
286                    pp -= 100;
287                    show_text = 1;
288                }
289
290                if (pbi && (pbi->mb.segmentation_enabled & SEGMENT_PF) && tab->deinterlace)
291                {
292                    de_interlace(common->frame_to_show->y_buffer, common->post_proc_buffer.y_buffer,
293                                 common->post_proc_buffer.y_width, common->post_proc_buffer.y_height,
294                                 common->post_proc_buffer.y_stride);
295
296                    de_interlace(common->frame_to_show->u_buffer, common->post_proc_buffer.u_buffer,
297                                 common->post_proc_buffer.uv_width, common->post_proc_buffer.uv_height,
298                                 common->post_proc_buffer.uv_stride);
299                    de_interlace(common->frame_to_show->v_buffer, common->post_proc_buffer.v_buffer,
300                                 common->post_proc_buffer.uv_width, common->post_proc_buffer.uv_height,
301                                 common->post_proc_buffer.uv_stride);
302                }
303                else
304                {
305                    if (pp >= 10 && pp <= 20)
306                    {
307                        q = q + (pp - 15) * 10;
308
309                        if (q < 0)
310                            q = 0;
311                    }
312
313                    start_tick = vp8_get_high_res_timer_tick();
314
315                    if (pp > 3 && tab->post_proc4time < microseconds_available)
316                    {
317                        vp8_deblock_and_de_macro_block(common->frame_to_show, &common->post_proc_buffer, q, 1, 0);
318
319                        stop_tick = vp8_get_high_res_timer_tick();
320
321                        if (pbi)
322                            tab->post_proc4time = vp8_get_time_in_micro_sec(start_tick, stop_tick);
323                    }
324
325                    else if (pp > 0 && tab->post_proc2time < microseconds_available)
326                    {
327                        vp8_deblock(common->frame_to_show, &common->post_proc_buffer, q , 1,  0);
328                        stop_tick = vp8_get_high_res_timer_tick();
329
330                        if (pbi)
331                            tab->post_proc2time = vp8_get_time_in_micro_sec(start_tick, stop_tick);
332                    }
333                    else
334                    {
335                        vp8_yv12_copy_frame(common->frame_to_show, &common->post_proc_buffer);
336                    }
337
338                }
339
340                vp8_clear_system_state();
341
342                if (tab->add_noise == 1)
343                {
344
345                    vp8_plane_add_noise(common->post_proc_buffer.y_buffer,
346                                        common->post_proc_buffer.y_width, common->post_proc_buffer.y_height,
347                                        common->post_proc_buffer.y_stride, 63 - q, noise);
348                }
349
350
351                if (show_text == 1)
352                {
353#ifdef PACKET_TESTING
354                    {
355                        VP8_HEADER *oh2 = (VP8_HEADER *) pbi->Source;
356                        sprintf(message, "%8d %d%d%d%d%d size:%d\n",
357                        oh2->frame_number ,
358                        oh2->update_gold  ,
359                        oh2->update_last  ,
360                        oh2->uses_gold    ,
361                        oh2->uses_last    ,
362                        oh2->type,
363                        vpxdxv_get_ximage_csize(src));
364                    }
365#else
366                    sprintf(message, "F:%1ldG:%1ldQ:%3ldF:%3ld,%3ldP:%d_s:%6ld,N:%d,",
367                            (common->frame_type == KEY_FRAME),
368                            common->refresh_golden_frame,
369                            common->base_qindex,
370                            common->filter_level,
371                            q,
372                            tab->postproc,
373                            vpxdxv_get_ximage_csize(src), noise);
374#endif
375
376                    vp8_blit_text(message, common->post_proc_buffer.y_buffer, common->post_proc_buffer.y_stride);
377
378                }
379                else if (show_text == 2)
380                {
381                    int i, j;
382                    unsigned char *y_ptr;
383                    YV12_BUFFER_CONFIG *post = &common->post_proc_buffer;
384                    int mb_rows = post->y_height >> 4;
385                    int mb_cols = post->y_width  >> 4;
386                    int mb_index = 0;
387                    MODE_INFO *mi = common->mi;
388
389                    y_ptr = post->y_buffer + 4 * post->y_stride + 4;
390
391                    // vp8_filter each macro block
392                    for (i = 0; i < mb_rows; i++)
393                    {
394                        for (j = 0; j < mb_cols; j++)
395                        {
396                            char zz[4];
397
398                            if (pp == 4)
399                                sprintf(zz, "%c", mi[mb_index].mbmi.mode + 'a');
400                            else
401                                sprintf(zz, "%c", mi[mb_index].mbmi.ref_frame + 'a');
402
403                            vp8_blit_text(zz, y_ptr, post->y_stride);
404                            mb_index ++;
405                            y_ptr += 16;
406                        }
407
408                        mb_index ++; //border
409                        y_ptr += post->y_stride  * 16 - post->y_width;
410
411                    }
412                }
413                else if (show_text == 3)
414                {
415                    int i, j;
416                    unsigned char *y_ptr;
417                    YV12_BUFFER_CONFIG *post = &common->post_proc_buffer;
418                    int mb_rows = post->y_height >> 4;
419                    int mb_cols = post->y_width  >> 4;
420                    int mb_index = 0;
421                    MODE_INFO *mi = common->mi;
422
423                    y_ptr = post->y_buffer + 4 * post->y_stride + 4;
424
425                    // vp8_filter each macro block
426                    for (i = 0; i < mb_rows; i++)
427                    {
428                        for (j = 0; j < mb_cols; j++)
429                        {
430                            char zz[4];
431
432                            if (j == 0)
433                                sprintf(zz, "%c", '0' + i % 10);
434                            else
435                                sprintf(zz, "%c", '0' + j % 10);
436
437                            vp8_blit_text(zz, y_ptr, post->y_stride);
438                            mb_index ++;
439                            y_ptr += 16;
440                        }
441
442                        y_ptr += post->y_stride  * 16 - post->y_width;
443
444                    }
445                }
446
447                vpx_memcpy(&tab->this_buffer, &common->post_proc_buffer, sizeof(YV12_BUFFER_CONFIG));
448            }
449            else
450            {
451                vpx_memcpy(&tab->this_buffer, common->frame_to_show, sizeof(YV12_BUFFER_CONFIG));
452            }
453
454
455            /* get a frame pointer to the scaled and postprocessed reconstructed buffer */
456            if (tab->passed_in_buffer == 0)
457            {
458                if (common->horiz_scale != NORMAL || common->vert_scale != NORMAL)
459                {
460                    neww = hs * tab->this_buffer.y_width / hr;
461                    newh = vs * tab->this_buffer.y_height / vr;
462
463                    neww += neww & 1;
464
465                    if (tab->hs != hs || tab->hr != hr || tab->vs != vs || tab->vr != vr)
466                    {
467                        vp8_yv12_alloc_frame_buffer(&tab->scaled_buffer, neww, newh , 8);
468                    }
469
470                    vp8_yv12_scale_or_center(&tab->this_buffer,
471                                             &tab->scaled_buffer,
472                                             neww, newh, SCALE_TO_FIT, hs, hr, vs, vr);
473
474                    convert_yv12_buffer_types(&tab->scaled_buffer, frame_buffer);
475
476                    cw = hs * common->Width / hr;
477                    ch = vs * common->Height / vr;
478
479                }
480                else
481                {
482                    convert_yv12_buffer_types(&tab->this_buffer, frame_buffer);
483
484                    cw = common->Width;
485                    ch = common->Height;
486                }
487            }
488            else
489            {
490                convert_yv12_buffer_types(tab->passed_in_buffer, frame_buffer);
491                cw = common->Width;
492                ch = common->Height;
493                tab->passed_in_buffer = 0;
494            }
495
496            frame_buffer->y_width = cw;
497            frame_buffer->y_height = ch;
498            frame_buffer->uv_width = cw / 2;
499            frame_buffer->uv_height = ch / 2;
500
501            p_size = vpx_get_size_of_pixel(tab->bd_tag);
502
503            /* remember to offset if requested */
504            y += view_y;
505            x += view_x ;
506
507            /* for planar destinations */
508            w = view_w;
509            h = vs_height;
510
511            if (w < frame_buffer->y_width)
512            {
513                frame_buffer->y_width = w;
514                frame_buffer->uv_width = (w + 1) / 2;
515            }
516
517            if (h < frame_buffer->y_height)
518            {
519                frame_buffer->y_height = h;
520                frame_buffer->uv_height = (h + 1) / 2;
521            }
522
523            if (frame_buffer->y_width < view_w)
524                x += (view_w - frame_buffer->y_width) / 2;
525
526            if (x & 1)
527                x -= 1;
528
529            if (frame_buffer->y_height < vs_height)
530                y += (vs_height - frame_buffer->y_height) / 2;
531
532
533            ptr_scrn += (x * p_size) + (y * this_pitch);
534
535            frame_buffer->y_stride *= -1;
536            frame_buffer->uv_stride *= -1;
537
538            if (tab->bd_tag == VPXDXV_YV12 || tab->bd_tag == VPXDXV_I420)
539            {
540                if (this_pitch < 0)
541                {
542                    frame_buffer->uv_start = (char *)(ptr_scrn + abs(this_pitch) + abs(this_pitch) * h / 4 + this_pitch / 2);
543                    frame_buffer->uv_dst_area = abs((this_pitch * h) / 4);
544                    frame_buffer->uv_used_area = 0;
545                }
546                else
547                {
548                    frame_buffer->uv_start = (char *)(ptr_scrn + (this_pitch * h));
549                    frame_buffer->uv_dst_area = (((this_pitch + 1) / 2) * ((h + 1) / 2));
550                    frame_buffer->uv_used_area = (((this_pitch + 1) / 2) * frame_buffer->uv_height);
551                }
552            }
553
554            if ((pbi->mb.segmentation_enabled & SEGMENT_PF) && (tab->bd_tag != VPXDXV_YV12 && tab->bd_tag != VPXDXV_I420))
555            {
556                int ypitch = frame_buffer->y_stride;
557                int uvpitch = frame_buffer->uv_stride;
558
559                frame_buffer->y_stride <<= 1;
560                frame_buffer->y_height >>= 1;
561                frame_buffer->uv_stride <<= 1;
562                frame_buffer->uv_height >>= 1;
563
564                ptr_scrn += this_pitch;
565                frame_buffer->y_buffer -= ypitch;
566                frame_buffer->u_buffer -= uvpitch;
567                frame_buffer->v_buffer -= uvpitch;
568                tab->blitter(ptr_scrn, 2 * this_pitch, (YUV_BUFFER_CONFIG *)(&tab->frame_buffer));
569
570                ptr_scrn -= this_pitch;
571                frame_buffer->y_buffer += ypitch;
572                frame_buffer->u_buffer += uvpitch;
573                frame_buffer->v_buffer += uvpitch;
574                tab->blitter(ptr_scrn, 2 * this_pitch, (YUV_BUFFER_CONFIG *)(&tab->frame_buffer));
575
576            }
577            else
578            {
579                /* blit the screen */
580                tab->blitter(ptr_scrn, this_pitch, (YUV_BUFFER_CONFIG *)(&tab->frame_buffer));
581                vpx_log("Decoder: Frame shown \n");
582            }
583
584        }
585        else
586            vpx_log("Decoder: Frame not shown scrn pointer 0\n");
587    }
588    else
589        vpx_log("Decoder: Frame not shown vscreen 0\n");
590
591    return DXV_OK;
592}
593/****************************************************************************
594 *
595 *  ROUTINE       :     onyx_decompress
596 *
597 *  INPUTS        :     None
598 *
599 *  OUTPUTS       :     None
600 *
601 *  RETURNS       :     None.
602 *
603 *  FUNCTION      :
604 *
605 *  SPECIAL NOTES :
606 *
607 ****************************************************************************/
608static
609int onyx_decompress(XIMAGE_HANDLE src, VSCREEN_HANDLE v_screen)
610{
611    VP8_XIMAGE_HANDLE this_algorithm_base = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
612    unsigned char *c_addr;
613    unsigned int c_size;
614    int w, h, x, y;
615    int vp8_rv;
616
617    c_addr = vpxdxv_get_ximage_cdata_addr(src);
618    c_size = vpxdxv_get_ximage_csize(src);
619    vpxdxv_get_ximage_xywh(src, &x, &y, &w, &h);
620
621    // if we have a compressed frame decompress it ( otherwise we'll just redo
622    // the scaling and postprocessing from the last frame )
623    if (c_addr)
624    {
625        if (c_size != 0)
626        {
627            int flags;
628            int ret_val;
629
630            int f;
631
632            // decode the frame
633            ret_val = vp8d_decompress_frame((VP8D_PTR) this_algorithm_base->my_pbi,
634                                            c_size,
635                                            (char *) c_addr,
636                                            &this_algorithm_base->this_buffer,
637                                            &flags);
638
639
640            f = this_algorithm_base->my_pbi->common.filter_level * 10 / 6;
641
642            if (this_algorithm_base->my_pbi->common.frame_type == KEY_FRAME)
643                this_algorithm_base->avgq = 8 * f;
644            else
645                this_algorithm_base->avgq = this_algorithm_base->avgq * 7 / 8 + f;
646
647
648
649            if (ret_val != 0)
650            {
651                if (ret_val == -1)
652                    return DXV_VERSION_CONFLICT;
653                else
654                    return DXV_BAD_DATA;
655            }
656
657        }
658    }
659
660
661    vp8_rv = onyx_blit(src, v_screen, &this_algorithm_base->frame_buffer, x, y);
662
663
664    return vp8_rv;
665}
666/*
667//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
668//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
669*/
670static
671int vp8_ximagedestroy(XIMAGE_HANDLE src)
672{
673    VP8_XIMAGE_HANDLE this_algorithm_base = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
674
675    if (this_algorithm_base)
676    {
677
678        vp8_yv12_de_alloc_frame_buffer(&this_algorithm_base->scaled_buffer);
679
680        /* safety check in case stopdecode was not called */
681        if (this_algorithm_base->owned)
682            vp8dx_remove_decompressor((VP8D_PTR)(this_algorithm_base->my_pbi));
683
684        duck_free(this_algorithm_base);
685    }
686
687    return DXV_OK;
688}
689/*
690//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
691//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
692*/
693static int
694onyx_get_post_proc(XIMAGE_HANDLE src, unsigned int *ppl)
695{
696    VP8_XIMAGE_HANDLE this_algorithm_base = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
697
698    if (this_algorithm_base)
699    {
700        *ppl = this_algorithm_base->ppl_tag;
701
702        return DXV_OK;
703    }
704
705    return DXV_NULL_BASE;
706}
707/*
708//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
709//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
710*/
711static int
712onyx_set_post_proc(XIMAGE_HANDLE src, unsigned int ppl)
713{
714    VP8_XIMAGE_HANDLE this_algorithm_base = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
715
716    if (this_algorithm_base)
717    {
718        this_algorithm_base->ppl_tag = ppl;
719
720        return DXV_OK;
721    }
722
723    return DXV_NULL_BASE;
724}
725/*
726//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
727//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
728*/
729static
730int vp8_ximagestop_decode(XIMAGE_HANDLE src)
731{
732    VP8_XIMAGE_HANDLE this_algorithm_base = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
733
734    if (this_algorithm_base)
735    {
736
737        vp8_yv12_de_alloc_frame_buffer(&this_algorithm_base->scaled_buffer);
738
739        if (this_algorithm_base->owned)
740            vp8dx_remove_decompressor((VP8D_PTR)(this_algorithm_base->my_pbi));
741
742        this_algorithm_base->owned = 0;
743    }
744
745    return DXV_OK;
746}
747
748
749/*
750//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
751//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
752*/
753static
754int vp8_ximagestart_decode
755(
756    XIMAGE_HANDLE src
757)
758{
759    VP8_XIMAGE_HANDLE this_algorithm_base = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
760    XIMAGE_INFO_PTR xinfo = vpxdxv_get_ximage_info(src);
761    VP8D_CONFIG ocf;
762
763    if (xinfo)
764    {
765        ocf.Width = xinfo->width;
766        ocf.Height = xinfo->height;
767    }
768
769    if (this_algorithm_base->common == 0)
770    {
771        this_algorithm_base->my_pbi = (VP8D_COMP *) vp8dx_create_decompressor(&ocf);
772        this_algorithm_base->owned = 1;
773        this_algorithm_base->common = &this_algorithm_base->my_pbi->common;
774        this_algorithm_base->avgq = 0;
775
776    }
777
778    this_algorithm_base->passed_in_buffer = 0;
779    this_algorithm_base->post_proc2time = 0;
780    this_algorithm_base->post_proc4time = 0;
781    this_algorithm_base->ppcount = 64;
782
783    return DXV_OK;
784}
785/*
786//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
787//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
788*/
789static
790DXV_HANDLE vp8_ximagecreate(XIMAGE_HANDLE src)
791{
792    VP8_XIMAGE_HANDLE this_algorithm_base;
793
794    /* create a new algorithm base container */
795    this_algorithm_base = (VP8_XIMAGE_HANDLE)duck_calloc(1, sizeof(VP8_XIMAGE), DMEM_GENERAL);
796
797    if (this_algorithm_base == NULL)
798        return NULL;
799
800    vp8_scale_machine_specific_config();
801
802    vpxdxv_register_ximage_start_decode(src, vp8_ximagestart_decode);
803
804    vpxdxv_register_ximage_stop_decode(src, vp8_ximagestop_decode);
805
806    vpxdxv_register_ximage_destroy(src, vp8_ximagedestroy);
807
808    vpxdxv_register_ximage_dx(src, onyx_decompress);
809
810    vpxdxv_register_ximage_set_parameter(src, onyx_set_parameter);
811
812    vpxdxv_register_ximage_output_format_func(src,
813            onyx_get_output_format,
814            onyx_set_output_format);
815
816    vpxdxv_register_ximage_post_proc_level_func(src,
817            onyx_get_post_proc,
818            onyx_set_post_proc);
819
820    return (DXV_HANDLE)this_algorithm_base;
821}
822
823/*
824//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
825//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
826*/
827
828static int store_output_list(unsigned int supported, int count,
829                             unsigned int *outlist)
830{
831    int i = 0, j = 0,
832        ret = DXV_OK;
833
834    while (i < count)
835    {
836        while (supported && !(supported & 0x01))
837        {
838            supported >>= 1;
839            ++j;
840        }
841
842        *(outlist + i) = g_vp8_preferred_output_format_list[j];
843        ++i;
844        ++j;
845        supported >>= 1;
846    }
847
848
849    return ret;
850}
851
852/*
853//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
854//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
855*/
856static int onyx_get_output_list(XIMAGE_INFO_PTR xinfo, unsigned int *outlist,
857                                unsigned int *size)
858{
859    int i,
860        ret = DXV_INVALID_REQUEST;
861    unsigned int supported = 0,
862                 count = 0;
863    (void)xinfo;
864
865    if (size)
866    {
867        for (i = 0; i < sizeof(g_vp8_preferred_output_format_list) / sizeof(unsigned int) && i < 32; ++i)
868        {
869            if (vpx_get_blitter(g_vp8_preferred_output_format_list[i]) != (void *)0xffffffff)
870            {
871                supported |= (1 << i);
872                ++count;
873            }
874        }
875
876        if (outlist)
877        {
878            if (count && ((count + 1) == (*size / sizeof(int))))
879                ret = store_output_list(supported, count, outlist);
880            else
881                *outlist = 0;
882        }
883        else
884        {
885            *size = (count + 1) * sizeof(int);
886            ret = DXV_OK;
887        }
888    }
889
890    return ret;
891}
892
893/*
894//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
895//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
896*/
897int onyx_init(void)
898{
899    int vp8_rv;
900
901    /* register VPX blitters based on cpu */
902    vpx_set_blit();
903
904    vp8_rv = vpxdxv_register_ximage(vp8_ximagecreate, onyx_get_output_list, VP8_FOURCC);
905    return vp8_rv;
906
907    return DXV_OK;
908}
909/*
910//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
911//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
912*/
913int onyx_exit(void)
914{
915
916    vpxdxv_un_register_ximage(VP8_FOURCC);
917
918    return DXV_OK;
919}
920/****************************************************************************
921 *
922 *  ROUTINE       :  onyx_set_parameter
923 *
924 *  INPUTS        :  XIMAGE_HANDLE src   :
925 *                   int Command             :
926 *                   unsigned long Parameter :
927 *
928 *  OUTPUTS       :  None.
929 *
930 *  RETURNS       :  void
931 *
932 *  FUNCTION      :
933 *
934 *
935 *  SPECIAL NOTES :  None.
936 *
937 ****************************************************************************/
938void onyx_set_parameter(XIMAGE_HANDLE src, int Command, unsigned int Parameter)
939{
940    VP8_XIMAGE_HANDLE this_algorithm_base = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
941
942    switch (Command)
943    {
944    case PBC_SET_CPUFREE:
945        this_algorithm_base->cpu_free  = Parameter;
946        break;
947    case PBC_SET_POSTPROC:
948        this_algorithm_base->postproc = Parameter;
949        break;
950
951    case PBC_SET_BLITBUFF:
952        this_algorithm_base->passed_in_buffer = (YV12_BUFFER_CONFIG *) Parameter;
953        break;
954
955    case PBC_SET_REFERENCEFRAME:
956    {
957        VP8_XIMAGE_HANDLE tab = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
958        VP8D_COMP *pbi;
959        pbi = tab->my_pbi;
960        vp8_yv12_copy_frame((YV12_BUFFER_CONFIG *) Parameter, &pbi->common.last_frame);
961    }
962    break;
963
964    case PBC_SET_COMMON:
965
966        if (Parameter)
967        {
968            this_algorithm_base->common = (VP8_COMMON *)Parameter;
969        }
970
971        break;
972    case PBC_SET_ADDNOISE:
973        this_algorithm_base->add_noise = Parameter;
974        break;
975    case PBC_SET_DEINTERLACEMODE:
976        this_algorithm_base->deinterlace = Parameter;
977        break;
978
979    }
980}
981/*
982//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
983//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
984*/
985static int
986onyx_get_output_format(XIMAGE_HANDLE src, unsigned int *format_tag)
987{
988    VP8_XIMAGE_HANDLE this_algorithm_base = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
989
990    if (this_algorithm_base)
991    {
992        *format_tag = this_algorithm_base->bd_tag;
993        return DXV_OK;
994    }
995
996    return DXV_NULL_BASE;
997}
998
999/*
1000//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1001//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1002*/
1003static int
1004onyx_set_output_format(XIMAGE_HANDLE src, unsigned int bd_tag)
1005{
1006    VP8_XIMAGE_HANDLE this_algorithm_base = (VP8_XIMAGE_HANDLE)vpxdxv_get_algorithm_base_ptr(src);
1007    int i;
1008    unsigned int bd_tag_found;
1009
1010    if (this_algorithm_base)
1011    {
1012        i = 0;
1013        bd_tag_found = 0;
1014
1015        while (g_vp8_preferred_output_format_list[i] != 0)
1016        {
1017            if (g_vp8_preferred_output_format_list[i] == bd_tag)
1018            {
1019                bd_tag_found = 1;
1020                break;
1021            }
1022
1023            i++;
1024        }
1025
1026        if (bd_tag_found)
1027        {
1028            this_algorithm_base->blitter = (vp8blit_func)vpx_get_blitter(bd_tag);
1029            this_algorithm_base->bd_tag = bd_tag;
1030            return DXV_OK;
1031        }
1032
1033        return DXV_INVALID_BLIT;
1034    }
1035
1036    return DXV_NULL_BASE;
1037}
1038
1039/*
1040//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1041//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1042*/
1043int
1044vpx_get_size_of_pixel(unsigned int bd)
1045{
1046    int vp8_rv;
1047
1048    switch (bd)
1049    {
1050    case VPXDXV_YV12:
1051    case VPXDXV_I420:
1052        vp8_rv = 1;
1053        break;
1054
1055#ifdef _ENABLE_SPLIT_PIXEL_
1056    case VPXDXV_SPLIT565:
1057#endif
1058    case VPXDXV_RGB555:
1059    case VPXDXV_RGB565:
1060    case VPXDXV_YUY2:
1061    case VPXDXV_UYVY:
1062    case VPXDXV_YVYU:
1063        vp8_rv = 2;
1064        break;
1065
1066    case VPXDXV_RGB888:
1067        vp8_rv = 3;
1068        break;
1069
1070    case VPXDXV_RGB8888:
1071        vp8_rv = 4;
1072        break;
1073
1074    default:
1075        vp8_rv = -1;
1076        break;
1077    }
1078
1079    return vp8_rv;
1080}
1081