mpeg2: initial support for mpeg2 (WIP)
[crystalhd-video:crystalhd-video.git] / src / crystalhd_drv_video.c
1 /*
2  * Copyright (c) 2010 iWorldcom Co., Ltd. All Rights Reserved.
3  *
4  *    - Victor Tseng <palatis@iworldcom.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <assert.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <stdarg.h>
35 #include <string.h>
36
37 #define _GNU_SOURCE
38 #define __USE_GNU
39 #include <dlfcn.h>
40
41 #include "crystalhd_drv_video.h"
42 #include "crystalhd_video_mpeg2.h"
43 #include "crystalhd_video_h264.h"
44
45 #include "debug.h"
46
47 #define CONFIG_ID_OFFSET                0x01000000
48 #define CONTEXT_ID_OFFSET               0x02000000
49 #define SURFACE_ID_OFFSET               0x04000000
50 #define BUFFER_ID_OFFSET                0x08000000
51 #define IMAGE_ID_OFFSET                 0x10000000
52
53 enum {
54         CRYSTALHD_SURFACETYPE_RGBA = 1,
55         CRYSTALHD_SURFACETYPE_YUV,
56         CRYSTALHD_SURFACETYPE_INDEXED,
57 };
58
59 typedef struct {
60         unsigned int type;
61         VAImageFormat va_format;
62 } crystalhd_image_format_map_t;
63
64 static const crystalhd_image_format_map_t
65 crystalhd_image_formats_map[CRYSTALHD_MAX_IMAGE_FORMATS] = {
66 #if 0
67         /* TODO: support these image formats... and maybe more */
68         { CRYSTALHD_SURFACETYPE_YUV,
69           { VA_FOURCC('Y','V','1','2'), VA_LSB_FIRST, 12, } },
70         { CRYSTALHD_SURFACETYPE_YUV,
71           { VA_FOURCC('I','4','2','0'), VA_LSB_FIRST, 12, } },
72 #endif
73         { CRYSTALHD_SURFACETYPE_YUV,
74           { VA_FOURCC('N','V','1','2'), VA_LSB_FIRST, 12, } },
75 };
76
77 /* Helper functions */
78 static VAStatus crystalhd__update_attribute(object_config_p obj_config, VAConfigAttrib *attrib)
79 {
80         int i;
81         /* Check existing attrbiutes */
82         for(i = 0; obj_config->attrib_count < i; i++)
83         {
84                 if (obj_config->attrib_list[i].type == attrib->type)
85                 {
86                         /* Update existing attribute */
87                         obj_config->attrib_list[i].value = attrib->value;
88                         return VA_STATUS_SUCCESS;
89                 }
90         }
91         if (obj_config->attrib_count < CRYSTALHD_MAX_CONFIG_ATTRIBUTES)
92         {
93                 i = obj_config->attrib_count;
94                 obj_config->attrib_list[i].type = attrib->type;
95                 obj_config->attrib_list[i].value = attrib->value;
96                 obj_config->attrib_count++;
97                 return VA_STATUS_SUCCESS;
98         }
99         return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
100 }
101
102 static VAStatus crystalhd__allocate_buffer(object_buffer_p obj_buffer, int size)
103 {
104         obj_buffer->buffer_data = realloc(obj_buffer->buffer_data, size);
105         if (NULL == obj_buffer->buffer_data)
106                 return VA_STATUS_ERROR_ALLOCATION_FAILED;
107         return VA_STATUS_SUCCESS;
108 }
109
110 static void crystalhd__destroy_buffer(struct crystalhd_driver_data *driver_data, object_buffer_p obj_buffer)
111 {
112         free(obj_buffer->buffer_data);
113         object_heap_free( &driver_data->buffer_heap, (object_base_p) obj_buffer);
114 }
115
116 /* VA Backend APIs */
117 VAStatus crystalhd_QueryConfigProfiles(
118                 VADriverContextP ctx,
119                 VAProfile *profile_list,        /* out */
120                 int *num_profiles               /* out */
121         )
122 {
123         INIT_DRIVER_DATA;
124         int i = 0;
125
126         profile_list[i++] = VAProfileMPEG2Simple;
127         profile_list[i++] = VAProfileMPEG2Main;
128         //profile_list[i++] = VAProfileMPEG4Simple;
129         //profile_list[i++] = VAProfileMPEG4AdvancedSimple;
130         //profile_list[i++] = VAProfileMPEG4Main;
131         profile_list[i++] = VAProfileH264Baseline;
132         profile_list[i++] = VAProfileH264Main;
133         profile_list[i++] = VAProfileH264High;
134         //profile_list[i++] = VAProfileVC1Simple;
135         //profile_list[i++] = VAProfileVC1Main;
136         //rofile_list[i++] = VAProfileVC1Advanced;
137         //profile_list[i++] = VAProfileH263Baseline;
138         //profile_list[i++] = VAProfileJPEGBaseline;
139
140         /* If the assert fails then CRYSTALHD_MAX_PROFILES needs to be bigger */
141         assert(i <= CRYSTALHD_MAX_PROFILES);
142         *num_profiles = i;
143
144         return VA_STATUS_SUCCESS;
145 }
146
147 VAStatus crystalhd_QueryConfigEntrypoints(
148                 VADriverContextP ctx,
149                 VAProfile profile,
150                 VAEntrypoint  *entrypoint_list, /* out */
151                 int *num_entrypoints            /* out */
152         )
153 {
154         INIT_DRIVER_DATA;
155
156         switch (profile) {
157                 case VAProfileMPEG2Simple:
158                 case VAProfileMPEG2Main:
159                                 *num_entrypoints = 2;
160                                 entrypoint_list[0] = VAEntrypointVLD;
161                                 entrypoint_list[1] = VAEntrypointMoComp;
162                                 break;
163
164 #if 0
165                 case VAProfileMPEG4Simple:
166                 case VAProfileMPEG4AdvancedSimple:
167                 case VAProfileMPEG4Main:
168                                 *num_entrypoints = 1;
169                                 entrypoint_list[0] = VAEntrypointVLD;
170                                 break;
171 #endif
172                 case VAProfileH264Baseline:
173                 case VAProfileH264Main:
174                 case VAProfileH264High:
175                                 *num_entrypoints = 1;
176                                 entrypoint_list[0] = VAEntrypointVLD;
177                                 break;
178
179 #if 0
180                 case VAProfileVC1Simple:
181                 case VAProfileVC1Main:
182                 case VAProfileVC1Advanced:
183                                 *num_entrypoints = 1;
184                                 entrypoint_list[0] = VAEntrypointVLD;
185                                 break;
186
187                 case VAProfileH263Baseline:
188                                 *num_entrypoints = 1;
189                                 entrypoint_list[0] = VAEntrypointVLD;
190                                 break;
191
192                 case VAProfileJPEGBaseline:
193                                 *num_entrypoints = 1;
194                                 entrypoint_list[0] = VAEntrypointVLD;
195                                 break;
196 #endif
197
198                 default:
199                                 *num_entrypoints = 0;
200                                 break;
201         }
202
203         /* If the assert fails then CRYSTALHD_MAX_ENTRYPOINTS needs to be bigger */
204         assert(*num_entrypoints <= CRYSTALHD_MAX_ENTRYPOINTS);
205
206         return VA_STATUS_SUCCESS;
207 }
208
209 VAStatus crystalhd_GetConfigAttributes(
210                 VADriverContextP ctx,
211                 VAProfile profile,
212                 VAEntrypoint entrypoint,
213                 VAConfigAttrib *attrib_list,    /* in/out */
214                 int num_attribs
215         )
216 {
217         INIT_DRIVER_DATA;
218
219         int i;
220
221         /* Other attributes don't seem to be defined */
222         /* What to do if we don't know the attribute? */
223         for (i = 0; i < num_attribs; i++)
224         {
225                 switch (attrib_list[i].type)
226                 {
227                   case VAConfigAttribRTFormat:
228                           attrib_list[i].value = VA_RT_FORMAT_YUV420;
229                           break;
230
231                   default:
232                           /* Do nothing */
233                           attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
234                           break;
235                 }
236         }
237
238         return VA_STATUS_SUCCESS;
239 }
240
241 VAStatus crystalhd_CreateConfig(
242                 VADriverContextP ctx,
243                 VAProfile profile,
244                 VAEntrypoint entrypoint,
245                 VAConfigAttrib *attrib_list,
246                 int num_attribs,
247                 VAConfigID *config_id           /* out */
248         )
249 {
250         INIT_DRIVER_DATA;
251         VAStatus vaStatus;
252         int configID;
253         object_config_p obj_config;
254         int i;
255
256         /* Validate profile & entrypoint */
257         switch (profile) {
258         case VAProfileMPEG2Simple:
259         case VAProfileMPEG2Main:
260                 if ((VAEntrypointVLD == entrypoint) ||
261                         (VAEntrypointMoComp == entrypoint))
262                 {
263                         vaStatus = VA_STATUS_SUCCESS;
264                 }
265                 else
266                 {
267                         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
268                 }
269                 break;
270
271 #if 0
272         case VAProfileMPEG4Simple:
273         case VAProfileMPEG4AdvancedSimple:
274         case VAProfileMPEG4Main:
275                 if (VAEntrypointVLD == entrypoint)
276                 {
277                         vaStatus = VA_STATUS_SUCCESS;
278                 }
279                 else
280                 {
281                         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
282                 }
283                 break;
284 #endif
285         case VAProfileH264Baseline:
286         case VAProfileH264Main:
287         case VAProfileH264High:
288                 if (VAEntrypointVLD == entrypoint)
289                 {
290                         vaStatus = VA_STATUS_SUCCESS;
291                 }
292                 else
293                 {
294                         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
295                 }
296                 break;
297
298 #if 0
299         case VAProfileVC1Simple:
300         case VAProfileVC1Main:
301         case VAProfileVC1Advanced:
302                 if (VAEntrypointVLD == entrypoint)
303                 {
304                         vaStatus = VA_STATUS_SUCCESS;
305                 }
306                 else
307                 {
308                         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
309                 }
310                 break;
311
312         default:
313                 vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
314                 break;
315 #endif
316         }
317
318         if (VA_STATUS_SUCCESS != vaStatus)
319         {
320                 return vaStatus;
321         }
322
323         configID = object_heap_allocate( &driver_data->config_heap );
324         obj_config = CONFIG(configID);
325         if (NULL == obj_config)
326         {
327                 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
328                 return vaStatus;
329         }
330
331         obj_config->profile = profile;
332         obj_config->entrypoint = entrypoint;
333         obj_config->attrib_list[0].type = VAConfigAttribRTFormat;
334         obj_config->attrib_list[0].value = VA_RT_FORMAT_YUV420;
335         obj_config->attrib_count = 1;
336
337         for(i = 0; i < num_attribs; i++)
338         {
339                 vaStatus = crystalhd__update_attribute(obj_config, &(attrib_list[i]));
340                 if (VA_STATUS_SUCCESS != vaStatus)
341                 {
342                         break;
343                 }
344         }
345
346         /* Error recovery */
347         if (VA_STATUS_SUCCESS != vaStatus)
348         {
349                 object_heap_free( &driver_data->config_heap, (object_base_p) obj_config);
350         }
351         else
352         {
353                 *config_id = configID;
354         }
355
356         return vaStatus;
357 }
358
359 VAStatus crystalhd_DestroyConfig(
360                 VADriverContextP ctx,
361                 VAConfigID config_id
362         )
363 {
364         INIT_DRIVER_DATA;
365
366         VAStatus vaStatus;
367         object_config_p obj_config;
368
369         obj_config = CONFIG(config_id);
370         if (NULL == obj_config)
371         {
372                 vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
373                 return vaStatus;
374         }
375
376         object_heap_free( &driver_data->config_heap, (object_base_p) obj_config);
377         return VA_STATUS_SUCCESS;
378 }
379
380 VAStatus crystalhd_QueryConfigAttributes(
381                 VADriverContextP ctx,
382                 VAConfigID config_id,
383                 VAProfile *profile,             /* out */
384                 VAEntrypoint *entrypoint,       /* out */
385                 VAConfigAttrib *attrib_list,    /* out */
386                 int *num_attribs                /* out */
387         )
388 {
389         INIT_DRIVER_DATA;
390
391         VAStatus vaStatus = VA_STATUS_SUCCESS;
392         object_config_p obj_config;
393         int i;
394
395         obj_config = CONFIG(config_id);
396         assert(obj_config);
397
398         *profile = obj_config->profile;
399         *entrypoint = obj_config->entrypoint;
400         *num_attribs =  obj_config->attrib_count;
401         for(i = 0; i < obj_config->attrib_count; i++)
402         {
403                 attrib_list[i] = obj_config->attrib_list[i];
404         }
405
406         return vaStatus;
407 }
408
409 VAStatus crystalhd_CreateSurfaces(
410                 VADriverContextP ctx,
411                 int width,
412                 int height,
413                 int format,
414                 int num_surfaces,
415                 VASurfaceID *surfaces           /* out */
416         )
417 {
418         INIT_DRIVER_DATA;
419
420         VAStatus vaStatus = VA_STATUS_SUCCESS;
421         int i;
422
423         /* We only support one format */
424         if (VA_RT_FORMAT_YUV420 != format)
425         {
426                 return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
427         }
428
429         for (i = 0; i < num_surfaces; i++)
430         {
431                 int surfaceID = object_heap_allocate( &driver_data->surface_heap );
432                 object_surface_p obj_surface = SURFACE(surfaceID);
433                 if (NULL == obj_surface)
434                 {
435                         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
436                         break;
437                 }
438                 obj_surface->surface_id = surfaceID;
439                 obj_surface->metadata = NULL;
440                 obj_surface->data = NULL;
441                 surfaces[i] = surfaceID;
442         }
443
444         /* Error recovery */
445         if (VA_STATUS_SUCCESS != vaStatus)
446         {
447                 /* surfaces[i-1] was the last successful allocation */
448                 for(; i--; )
449                 {
450                         object_surface_p obj_surface = SURFACE(surfaces[i]);
451                         surfaces[i] = VA_INVALID_SURFACE;
452                         assert(obj_surface);
453                         object_heap_free( &driver_data->surface_heap, (object_base_p) obj_surface);
454                 }
455         }
456
457         return vaStatus;
458 }
459
460 VAStatus crystalhd_DestroySurfaces(
461                 VADriverContextP ctx,
462                 VASurfaceID *surface_list,
463                 int num_surfaces
464         )
465 {
466         INIT_DRIVER_DATA;
467
468         int i;
469         for(i = num_surfaces; i--; )
470         {
471                 object_surface_p obj_surface = SURFACE(surface_list[i]);
472                 if (!obj_surface)
473                         continue;
474
475                 if (obj_surface->metadata)
476                         free(obj_surface->metadata);
477                 if (obj_surface->data)
478                         free(obj_surface->data);
479
480                 object_heap_free( &driver_data->surface_heap, (object_base_p) obj_surface);
481         }
482         return VA_STATUS_SUCCESS;
483 }
484
485 VAStatus crystalhd_QueryImageFormats(
486         VADriverContextP ctx,
487         VAImageFormat *format_list,     /* out */
488         int *num_formats                /* out */
489 )
490 {
491         INIT_DRIVER_DATA;
492         
493         int n;
494         for (n = 0; crystalhd_image_formats_map[n].va_format.fourcc != 0; ++n) {
495                 const crystalhd_image_format_map_t * const m = &crystalhd_image_formats_map[n];
496                 if (format_list)
497                         format_list[n] = m->va_format;
498         }
499
500         if (num_formats)
501                 *num_formats = n;
502
503         return VA_STATUS_SUCCESS;
504 }
505
506 VAStatus crystalhd_CreateImage(
507         VADriverContextP ctx,
508         VAImageFormat *format,
509         int width,
510         int height,
511         VAImage *out_image              /* out */
512 )
513 {
514         INIT_DRIVER_DATA;
515
516         object_image_p obj_image;
517         VAImageID image_id;
518         unsigned int width2, height2, size2, size;
519         
520         out_image->image_id = VA_INVALID_ID;
521         out_image->buf = VA_INVALID_ID;
522
523         image_id = object_heap_allocate(&driver_data->image_heap);
524         if (image_id == VA_INVALID_ID)
525                 return VA_STATUS_ERROR_ALLOCATION_FAILED;
526
527         obj_image = IMAGE(image_id);
528         if (!obj_image)
529                 return VA_STATUS_ERROR_ALLOCATION_FAILED;
530         obj_image->palette = NULL;
531
532         VAImage * const image = &obj_image->image;
533         image->image_id = image_id;
534         image->buf = VA_INVALID_ID;
535
536         size = width * height;
537         width2 = (width + 1) / 2;
538         height2 = (height + 1) / 2;
539         size2 = width2 * height2;
540
541         image->num_palette_entries = 0;
542         image->entry_bytes = 0;
543         memset(image->component_order, 0, sizeof(image->component_order));
544
545         switch (format->fourcc) {
546 #if 0
547                 case VA_FOURCC('I','A','4','4'):
548                 case VA_FOURCC('A','I','4','4'):
549                         image->num_planes = 1;
550                         image->pitches[0] = width;
551                         image->offsets[0] = 0;
552                         image->data_size = image->offsets[0] + image->pitches[0] * height;
553                         image->num_palette_entries = 16;
554                         image->entry_bytes = 3;
555                         image->component_order[0] = 'R';
556                         image->component_order[1] = 'G';
557                         image->component_order[2] = 'B';
558                         break;
559                 case VA_FOURCC('A','R','G','B'):
560                 case VA_FOURCC('A','B','G','R'):
561                 case VA_FOURCC('B','G','R','A'):
562                 case VA_FOURCC('R','G','B','A'):
563                         image->num_planes = 1;
564                         image->pitches[0] = width * 4;
565                         image->offsets[0] = 0;
566                         image->data_size = image->offsets[0] + image->pitches[0] * height;
567                         break;
568                 case VA_FOURCC('Y','V','1','2'):
569                         image->num_planes = 3;
570                         image->pitches[0] = width;
571                         image->offsets[0] = 0;
572                         image->pitches[1] = width2;
573                         image->offsets[1] = size + size2;
574                         image->pitches[2] = width2;
575                         image->offsets[2] = size;
576                         image->data_size = size + 2 * size2;
577                         break;
578                 case VA_FOURCC('I','4','2','0'):
579                         image->num_planes = 3;
580                         image->pitches[0] = width;
581                         image->offsets[0] = 0;
582                         image->pitches[1] = width2;
583                         image->offsets[1] = size;
584                         image->pitches[2] = width2;
585                         image->offsets[2] = size + size2;
586                         image->data_size = size + 2 * size2;
587                         break;
588 #endif
589                 case VA_FOURCC('N','V','1','2'):
590                         image->num_planes = 2;
591                         image->pitches[0] = width;
592                         image->offsets[0] = 0;
593                         image->pitches[1] = width;
594                         image->offsets[1] = size;
595                         image->data_size = size + 2 * size2;
596                         break;
597                 default:
598                         goto error;
599         };
600
601         if (crystalhd_CreateBuffer(ctx, 0, VAImageBufferType,
602                 image->data_size, 1, NULL, &image->buf) != VA_STATUS_SUCCESS)
603                 goto error;
604
605         if (image->num_palette_entries > 0 && image->entry_bytes > 0) {
606                 obj_image->palette = malloc(image->num_palette_entries * sizeof(obj_image->palette));
607                 if (!obj_image->palette)
608                         goto error;
609         }
610
611         image->image_id = image_id;
612         image->format = *format;
613         image->width = width;
614         image->height = height;
615
616         *out_image = *image;
617
618         return VA_STATUS_SUCCESS;
619
620 error:
621         crystalhd_DestroyImage(ctx, image_id);
622
623         return VA_STATUS_ERROR_OPERATION_FAILED;
624 }
625
626 VAStatus crystalhd_DeriveImage(
627         VADriverContextP ctx,
628         VASurfaceID surface,
629         VAImage *image                  /* out */
630 )
631 {
632         INIT_DRIVER_DATA;
633         
634         /* TODO */
635
636         return VA_STATUS_ERROR_UNIMPLEMENTED;
637 }
638
639 VAStatus crystalhd_DestroyImage(
640         VADriverContextP ctx,
641         VAImageID image
642 )
643 {
644         INIT_DRIVER_DATA;
645
646         object_image_p obj_image = IMAGE(image);
647         if (obj_image)
648         {
649                 if (obj_image->image.buf != VA_INVALID_ID)
650                         crystalhd_DestroyBuffer(ctx, obj_image->image.buf);
651
652                 if (obj_image->palette)
653                         free(obj_image->palette);
654
655                 object_heap_free(&driver_data->image_heap, (object_base_p)obj_image);
656         }
657
658         return VA_STATUS_SUCCESS;
659 }
660
661 VAStatus crystalhd_SetImagePalette(
662         VADriverContextP ctx,
663         VAImageID image,
664         unsigned char *palette
665 )
666 {
667         INIT_DRIVER_DATA;
668         
669         /* TODO */
670
671         return VA_STATUS_ERROR_UNIMPLEMENTED;
672 }
673
674 VAStatus crystalhd_GetImage(
675         VADriverContextP ctx,
676         VASurfaceID surface,
677         int x,                  /* coordinates of the upper left source pixel */
678         int y,
679         unsigned int width,     /* width and height of the region */
680         unsigned int height,
681         VAImageID image
682 )
683 {
684         INIT_DRIVER_DATA;
685
686         object_surface_p obj_surface = SURFACE(surface);
687         if (NULL == obj_surface)
688         {
689                 return VA_STATUS_ERROR_INVALID_SURFACE;
690         }
691
692         object_image_p obj_output_image = IMAGE(obj_surface->output_image_id);
693         if (NULL == obj_output_image)
694         {
695                 return VA_STATUS_ERROR_INVALID_IMAGE;
696         }
697
698         object_image_p obj_image = IMAGE(image);
699         if (NULL == obj_image)
700         {
701                 return VA_STATUS_ERROR_INVALID_IMAGE;
702         }
703
704         obj_image->image.format = obj_output_image->image.format;
705         obj_image->image.width = obj_output_image->image.width;
706         obj_image->image.height = obj_output_image->image.height;
707         obj_image->image.num_planes = obj_output_image->image.num_planes;
708         obj_image->image.entry_bytes = obj_output_image->image.entry_bytes;
709         obj_image->image.pitches[0] = obj_output_image->image.pitches[0];
710         obj_image->image.pitches[1] = obj_output_image->image.pitches[1];
711         obj_image->image.pitches[2] = obj_output_image->image.pitches[2];
712         obj_image->image.offsets[0] = obj_output_image->image.offsets[0];
713         obj_image->image.offsets[1] = obj_output_image->image.offsets[1];
714         obj_image->image.offsets[2] = obj_output_image->image.offsets[2];
715         obj_image->image.component_order[0] = obj_output_image->image.component_order[0];
716         obj_image->image.component_order[1] = obj_output_image->image.component_order[1];
717         obj_image->image.component_order[2] = obj_output_image->image.component_order[2];
718         obj_image->image.component_order[3] = obj_output_image->image.component_order[3];
719
720         object_buffer_p buf = BUFFER(obj_image->image.buf),
721                         obuf = BUFFER(obj_output_image->image.buf);
722         crystalhd__information_message("0x%08x\n", obj_image->image.buf);
723         crystalhd__information_message("0x%08x\n", obj_output_image->image.buf);
724         
725         memcpy( buf->buffer_data, obuf->buffer_data,
726                 CRYSTALHD_MIN(obj_image->image.data_size, obj_output_image->image.data_size));
727         crystalhd__information_message("0x%08x 0x%08x\n", obj_image->image.data_size, obj_output_image->image.data_size);
728         
729         return VA_STATUS_SUCCESS;
730 }
731
732 VAStatus crystalhd_PutImage(
733         VADriverContextP ctx,
734         VASurfaceID surface,
735         VAImageID image,
736         int src_x,
737         int src_y,
738         unsigned int src_width,
739         unsigned int src_height,
740         int dest_x,
741         int dest_y,
742         unsigned int dest_width,
743         unsigned int dest_height
744 )
745 {
746         INIT_DRIVER_DATA;
747         
748         /* TODO */
749
750         return VA_STATUS_ERROR_UNIMPLEMENTED;
751 }
752
753 VAStatus crystalhd_QuerySubpictureFormats(
754         VADriverContextP ctx,
755         VAImageFormat *format_list,     /* out */
756         unsigned int *flags,            /* out */
757         unsigned int *num_formats       /* out */
758 )
759 {
760         INIT_DRIVER_DATA;
761         
762         /* TODO */
763
764         return VA_STATUS_ERROR_UNIMPLEMENTED;
765 }
766
767 VAStatus crystalhd_CreateSubpicture(
768         VADriverContextP ctx,
769         VAImageID image,
770         VASubpictureID *subpicture      /* out */
771 )
772 {
773         INIT_DRIVER_DATA;
774         
775         /* TODO */
776
777         return VA_STATUS_ERROR_UNIMPLEMENTED;
778 }
779
780 VAStatus crystalhd_DestroySubpicture(
781         VADriverContextP ctx,
782         VASubpictureID subpicture
783 )
784 {
785         INIT_DRIVER_DATA;
786         
787         /* TODO */
788
789         return VA_STATUS_ERROR_UNIMPLEMENTED;
790 }
791
792 VAStatus crystalhd_SetSubpictureImage(
793                 VADriverContextP ctx,
794                 VASubpictureID subpicture,
795                 VAImageID image
796 )
797 {
798         INIT_DRIVER_DATA;
799         
800         /* TODO */
801
802         return VA_STATUS_ERROR_UNIMPLEMENTED;
803 }
804
805 VAStatus crystalhd_SetSubpicturePalette(
806         VADriverContextP ctx,
807         VASubpictureID subpicture,
808         /*
809          * pointer to an array holding the palette data.  The size of the array is
810          * num_palette_entries * entry_bytes in size.  The order of the components
811          * in the palette is described by the component_order in VASubpicture struct
812          */
813         unsigned char *palette
814 )
815 {
816         INIT_DRIVER_DATA;
817         
818         /* TODO */
819
820         return VA_STATUS_ERROR_UNIMPLEMENTED;
821 }
822
823 VAStatus crystalhd_SetSubpictureChromakey(
824         VADriverContextP ctx,
825         VASubpictureID subpicture,
826         unsigned int chromakey_min,
827         unsigned int chromakey_max,
828         unsigned int chromakey_mask
829 )
830 {
831         INIT_DRIVER_DATA;
832         
833         /* TODO */
834
835         return VA_STATUS_ERROR_UNIMPLEMENTED;
836 }
837
838 VAStatus crystalhd_SetSubpictureGlobalAlpha(
839         VADriverContextP ctx,
840         VASubpictureID subpicture,
841         float global_alpha 
842 )
843 {
844         INIT_DRIVER_DATA;
845         
846         /* TODO */
847
848         return VA_STATUS_ERROR_UNIMPLEMENTED;
849 }
850
851
852 VAStatus crystalhd_AssociateSubpicture(
853         VADriverContextP ctx,
854         VASubpictureID subpicture,
855         VASurfaceID *target_surfaces,
856         int num_surfaces,
857         short src_x, /* upper left offset in subpicture */
858         short src_y,
859         unsigned short src_width,
860         unsigned short src_height,
861         short dest_x, /* upper left offset in surface */
862         short dest_y,
863         unsigned short dest_width,
864         unsigned short dest_height,
865         /*
866          * whether to enable chroma-keying or global-alpha
867          * see VA_SUBPICTURE_XXX values
868          */
869         unsigned int flags
870 )
871 {
872         INIT_DRIVER_DATA;
873         
874         /* TODO */
875
876         return VA_STATUS_ERROR_UNIMPLEMENTED;
877 }
878
879 VAStatus crystalhd_DeassociateSubpicture(
880         VADriverContextP ctx,
881         VASubpictureID subpicture,
882         VASurfaceID *target_surfaces,
883         int num_surfaces
884 )
885 {
886         INIT_DRIVER_DATA;
887         
888         /* TODO */
889
890         return VA_STATUS_ERROR_UNIMPLEMENTED;
891 }
892
893 VAStatus crystalhd_CreateContext(
894         VADriverContextP ctx,
895         VAConfigID config_id,
896         int picture_width,
897         int picture_height,
898         int flag,
899         VASurfaceID *render_targets,
900         int num_render_targets,
901         VAContextID *context            /* out */
902 )
903 {
904         INIT_DRIVER_DATA;
905
906         VAStatus vaStatus = VA_STATUS_SUCCESS;
907         object_config_p obj_config;
908         int i;
909
910         obj_config = CONFIG(config_id);
911         if (NULL == obj_config)
912         {
913                 vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
914                 goto error_CleanUp;
915         }
916
917         int contextID = object_heap_allocate( &driver_data->context_heap );
918         object_context_p obj_context = CONTEXT(contextID);
919         if (NULL == obj_context)
920         {
921                 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
922                 goto error_CleanUp;
923         }
924
925         obj_context->context_id  = contextID;
926         *context = contextID;
927         obj_context->current_render_target = -1;
928         obj_context->config_id = config_id;
929         obj_context->picture_width = picture_width;
930         obj_context->picture_height = picture_height;
931         obj_context->num_render_targets = num_render_targets;
932         obj_context->last_iqmatrix_buffer_id = 0;
933         obj_context->last_slice_param_buffer_id = 0;
934         obj_context->last_picture_param_buffer_id = 0;
935         obj_context->last_h264_sps_id = 0;
936         obj_context->last_h264_pps_id = 0;
937         obj_context->metadata = NULL;
938         obj_context->metadata_size = 0;
939
940         obj_context->render_targets = (VASurfaceID *) malloc(num_render_targets * sizeof(VASurfaceID));
941         if (obj_context->render_targets == NULL)
942         {
943                 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
944                 goto error_FreeHeap;
945         }
946         
947         for(i = 0; i < num_render_targets; i++)
948         {
949                 if (NULL == SURFACE(render_targets[i]))
950                 {
951                         vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
952                         goto error_FreeRenderTargets;
953                 }
954                 obj_context->render_targets[i] = render_targets[i];
955         }
956         obj_context->flags = flag;
957
958         switch (obj_config->profile) {
959                 case VAProfileMPEG2Simple:
960                 case VAProfileMPEG2Main:
961                         vaStatus = crystalhd_prepare_decoder_mpeg2(ctx, obj_context);
962                         break;
963
964                 case VAProfileH264Baseline:
965                 case VAProfileH264Main:
966                 case VAProfileH264High:
967                         vaStatus = crystalhd_prepare_decoder_h264(ctx, obj_context);
968                         break;
969 #if 0
970                 case VAProfileVC1Simple:
971                 case VAProfileVC1Main:
972                 case VAProfileVC1Advanced:
973                         vaStatus = crystalhd_prepare_decoder_vc1(ctx, obj_context);
974                         break;
975 #endif
976
977 #if 0
978                 // no DIVX support for VA-API
979                 case VAProfileDivx???:
980                 // no MPEG4 support for Crystal HD
981                 case VAProfileMPEG4Simple:
982                 case VAProfileMPEG4AdvancedSimple:
983                 case VAProfileMPEG4Main:
984                 // no H263 support for Crystal HD
985                 case VAProfileH263Baseline:
986                 // no JPEG support for Crystal HD
987                 case VAProfileJPEGBaseline:
988                         breka;
989 #endif
990                 default:
991                         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
992         }
993         if ( VA_STATUS_SUCCESS != vaStatus )
994                 goto error_FreeRenderTargets;
995
996         return vaStatus;
997
998 error_FreeRenderTargets:
999         free(obj_context->render_targets);
1000
1001 error_FreeHeap:
1002         object_heap_free( &driver_data->context_heap, (object_base_p) obj_context);
1003
1004 error_CleanUp:
1005         obj_context->context_id = -1;
1006         obj_context->config_id = -1;
1007         obj_context->render_targets = NULL;
1008         obj_context->num_render_targets = 0;
1009         obj_context->flags = 0;
1010
1011         return vaStatus;
1012 }
1013
1014 VAStatus crystalhd_DestroyContext(
1015                 VADriverContextP ctx,
1016                 VAContextID context
1017         )
1018 {
1019         INIT_DRIVER_DATA;
1020
1021         object_context_p obj_context = CONTEXT(context);
1022         assert(obj_context);
1023
1024         obj_context->context_id = -1;
1025         obj_context->config_id = -1;
1026         obj_context->picture_width = 0;
1027         obj_context->picture_height = 0;
1028         if (obj_context->render_targets)
1029         {
1030                 free(obj_context->render_targets);
1031         }
1032         obj_context->render_targets = NULL;
1033         obj_context->num_render_targets = 0;
1034         obj_context->flags = 0;
1035
1036         obj_context->current_render_target = -1;
1037
1038         /* CrystalHD specific */
1039         DtsStopDecoder(driver_data->hdev);
1040         DtsCloseDecoder(driver_data->hdev);
1041
1042         object_heap_free( &driver_data->context_heap, (object_base_p) obj_context);
1043
1044         return VA_STATUS_SUCCESS;
1045 }
1046
1047 VAStatus crystalhd_CreateBuffer(
1048                 VADriverContextP ctx,
1049                 VAContextID context,            /* in */
1050                 VABufferType type,              /* in */
1051                 unsigned int size,              /* in */
1052                 unsigned int num_elements,      /* in */
1053                 void *data,                     /* in */
1054                 VABufferID *buf_id              /* out */
1055         )
1056 {
1057         INIT_DRIVER_DATA;
1058
1059         VAStatus vaStatus = VA_STATUS_SUCCESS;
1060         int bufferID;
1061         object_buffer_p obj_buffer;
1062
1063         /* Validate type */
1064         switch (type)
1065         {
1066                 case VAPictureParameterBufferType:
1067                 case VAIQMatrixBufferType:
1068                 case VABitPlaneBufferType:
1069                 case VASliceGroupMapBufferType:
1070                 case VASliceParameterBufferType:
1071                 case VASliceDataBufferType:
1072                 case VAMacroblockParameterBufferType:
1073                 case VAResidualDataBufferType:
1074                 case VADeblockingParameterBufferType:
1075                 case VAImageBufferType:
1076                         /* Ok */
1077                         break;
1078                 default:
1079                         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
1080                         return vaStatus;
1081         }
1082
1083         bufferID = object_heap_allocate( &driver_data->buffer_heap );
1084         obj_buffer = BUFFER(bufferID);
1085         crystalhd__information_message("buffer_id = 0x%08x, obj_buffer = %p, obj_buffer->base.id = 0x%08x, BufferType: %s, size: %d * %d = %d\n",
1086                         bufferID, obj_buffer, obj_buffer->base.id, string_of_VABufferType(type), size, num_elements, size * num_elements);
1087         if (NULL == obj_buffer)
1088         {
1089                 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1090                 return vaStatus;
1091         }
1092
1093         obj_buffer->type = type;
1094         obj_buffer->buffer_data = NULL;
1095
1096         vaStatus = crystalhd__allocate_buffer(obj_buffer, size * num_elements);
1097         if (VA_STATUS_SUCCESS == vaStatus)
1098         {
1099                 obj_buffer->element_size = size;
1100                 obj_buffer->num_elements = num_elements;
1101                 obj_buffer->max_num_elements = num_elements;
1102                 if (data)
1103                 {
1104                         memcpy(obj_buffer->buffer_data, data, size * num_elements);
1105                 }
1106                 *buf_id = bufferID;
1107         }
1108
1109         return vaStatus;
1110 }
1111
1112 VAStatus crystalhd_BufferSetNumElements(
1113                 VADriverContextP ctx,
1114                 VABufferID buf_id,              /* in */
1115                 unsigned int num_elements       /* in */
1116         )
1117 {
1118         INIT_DRIVER_DATA;
1119
1120         VAStatus vaStatus = VA_STATUS_SUCCESS;
1121         object_buffer_p obj_buffer = BUFFER(buf_id);
1122         assert(obj_buffer);
1123
1124         if ((num_elements < 0) || (num_elements > obj_buffer->max_num_elements))
1125         {
1126                 vaStatus = VA_STATUS_ERROR_UNKNOWN;
1127         }
1128         if (VA_STATUS_SUCCESS == vaStatus)
1129         {
1130                 obj_buffer->num_elements = num_elements;
1131         }
1132
1133         return vaStatus;
1134 }
1135
1136 VAStatus crystalhd_MapBuffer(
1137                 VADriverContextP ctx,
1138                 VABufferID buffer_id,   /* in */
1139                 void **pbuf             /* out */
1140         )
1141 {
1142         INIT_DRIVER_DATA;
1143
1144         object_buffer_p obj_buffer = BUFFER(buffer_id);
1145
1146         if (NULL == obj_buffer)
1147         {
1148                 return VA_STATUS_ERROR_INVALID_BUFFER;
1149         }
1150
1151         if (NULL != obj_buffer->buffer_data)
1152         {
1153                 *pbuf = obj_buffer->buffer_data;
1154         }
1155
1156         return VA_STATUS_SUCCESS;
1157 }
1158
1159 VAStatus crystalhd_UnmapBuffer(
1160                 VADriverContextP ctx,
1161                 VABufferID buf_id       /* in */
1162         )
1163 {
1164         /* Do nothing */
1165         return VA_STATUS_SUCCESS;
1166 }
1167
1168 VAStatus crystalhd_DestroyBuffer(
1169                 VADriverContextP ctx,
1170                 VABufferID buffer_id
1171         )
1172 {
1173         INIT_DRIVER_DATA;
1174         object_buffer_p obj_buffer = BUFFER(buffer_id);
1175         if (NULL == obj_buffer)
1176                 return VA_STATUS_SUCCESS;
1177
1178         crystalhd__destroy_buffer(driver_data, obj_buffer);
1179
1180         return VA_STATUS_SUCCESS;
1181 }
1182
1183 VAStatus crystalhd_BeginPicture(
1184                 VADriverContextP ctx,
1185                 VAContextID context,
1186                 VASurfaceID render_target
1187         )
1188 {
1189         INIT_DRIVER_DATA;
1190
1191         VAStatus vaStatus = VA_STATUS_SUCCESS;
1192
1193         object_context_p obj_context = CONTEXT(context);
1194         if ( NULL == obj_context )
1195         {
1196                 vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
1197                 goto error;
1198         }
1199
1200         object_surface_p obj_surface = SURFACE(render_target);
1201         if ( NULL == obj_surface )
1202         {
1203                 vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
1204                 goto error;
1205         }
1206
1207         object_config_p obj_config = CONFIG(obj_context->config_id);
1208         if ( NULL == obj_config )
1209         {
1210                 vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
1211                 goto error;
1212         }
1213
1214         obj_context->current_render_target = obj_surface->base.id;
1215
1216         switch (obj_config->profile) {
1217                 case VAProfileMPEG2Simple:
1218                 case VAProfileMPEG2Main:
1219                         vaStatus = crystalhd_begin_picture_mpeg2(ctx, context, render_target);
1220                         break;
1221
1222                 case VAProfileH264Baseline:
1223                 case VAProfileH264Main:
1224                 case VAProfileH264High:
1225                         vaStatus = crystalhd_begin_picture_h264(ctx, context, render_target);
1226                         break;
1227 #if 0
1228                 case VAProfileVC1Simple:
1229                         vaStatus = crystalhd_begin_picture_vc1(ctx, context, render_target);
1230                         break;
1231
1232                 case VAProfileDivx???:
1233                         vaStatus = crystalhd_begin_picture_divx(ctx, context, render_target);
1234                         break;
1235
1236                 case VAProfileVC1Main:
1237                 case VAProfileVC1Advanced:
1238                         vaStatus = crystalhd_begin_picture_vc1mp(ctx, context, render_target);
1239                         break;
1240 #endif
1241                 default:
1242                         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
1243         }
1244
1245 error:
1246         return vaStatus;
1247 }
1248
1249 #if 0
1250 VAStatus crystalhd_render_picture_parameter_buffer_mpeg2(
1251                 VADriverContextP ctx,
1252                 object_context_p obj_context,
1253                 object_buffer_p obj_buffer
1254         )
1255 {
1256         INIT_DRIVER_DATA;
1257
1258         VAStatus vaStatus = VA_STATUS_ERROR_UNIMPLEMENTED;
1259         /* TODO */
1260         return vaStatus;
1261 }
1262
1263 VAStatus crystalhd_render_picture_parameter_buffer_vc1(
1264                 VADriverContextP ctx,
1265                 object_context_p obj_context,
1266                 object_buffer_p obj_buffer
1267         )
1268 {
1269         INIT_DRIVER_DATA;
1270
1271         VAStatus vaStatus = VA_STATUS_ERROR_UNIMPLEMENTED;
1272         /* TODO */
1273         return vaStatus;
1274 }
1275
1276 VAStatus crystalhd_render_picture_parameter_buffer_vc1mp(
1277                 VADriverContextP ctx,
1278                 object_context_p obj_context,
1279                 object_buffer_p obj_buffer
1280         )
1281 {
1282         INIT_DRIVER_DATA;
1283
1284         VAStatus vaStatus = VA_STATUS_ERROR_UNIMPLEMENTED;
1285         /* TODO */
1286         return vaStatus;
1287 }
1288 #endif
1289
1290 VAStatus crystalhd_render_iqmatrix_buffer(
1291                 VADriverContextP ctx,
1292                 object_context_p obj_context,
1293                 object_buffer_p obj_buffer
1294         )
1295 {
1296         INIT_DRIVER_DATA;
1297
1298         VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
1299         object_config_p obj_config = CONFIG(obj_context->config_id);
1300
1301         switch (obj_config->profile) {
1302                 case VAProfileMPEG2Simple:
1303                 case VAProfileMPEG2Main:
1304                         vaStatus = crystalhd_render_iqmatrix_buffer_mpeg2(ctx, obj_context, obj_buffer);
1305                         break;
1306
1307                 case VAProfileH264Baseline:
1308                 case VAProfileH264Main:
1309                 case VAProfileH264High:
1310                         vaStatus = crystalhd_render_iqmatrix_buffer_h264(ctx, obj_context, obj_buffer);
1311                         break;
1312 #if 0
1313                 case VAProfileVC1Simple:
1314                 case VAProfileVC1Main:
1315                 case VAProfileVC1Advanced:
1316                         vaStatus = crystalhd_render_iqmatrix_buffer_vc1(ctx, obj_context, obj_buffer);
1317                         break;
1318 #endif
1319                 default:
1320                         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
1321         }
1322
1323         return vaStatus;
1324 }
1325
1326 VAStatus crystalhd_render_picture_parameter_buffer(
1327                 VADriverContextP ctx,
1328                 object_context_p obj_context,
1329                 object_buffer_p obj_buffer
1330         )
1331 {
1332         INIT_DRIVER_DATA;
1333
1334         VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
1335         object_config_p obj_config = CONFIG(obj_context->config_id);
1336
1337         switch (obj_config->profile) {
1338                 case VAProfileMPEG2Simple:
1339                 case VAProfileMPEG2Main:
1340                         vaStatus = crystalhd_render_picture_parameter_buffer_mpeg2(ctx, obj_context, obj_buffer);
1341                         break;
1342
1343                 case VAProfileH264Baseline:
1344                 case VAProfileH264Main:
1345                 case VAProfileH264High:
1346                         vaStatus = crystalhd_render_picture_parameter_buffer_h264(ctx, obj_context, obj_buffer);
1347                         break;
1348 #if 0
1349                 case VAProfileVC1Simple:
1350                 case VAProfileVC1Main:
1351                 case VAProfileVC1Advanced:
1352                         vaStatus = crystalhd_render_picture_parameter_buffer_vc1(ctx, obj_context, obj_buffer);
1353                         break;
1354 #endif
1355                 default:
1356                         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
1357         }
1358
1359         return vaStatus;
1360 }
1361
1362 VAStatus crystalhd_render_slice_parameter_buffer(
1363                 VADriverContextP ctx,
1364                 object_context_p obj_context,
1365                 object_buffer_p obj_buffer
1366         )
1367 {
1368         INIT_DRIVER_DATA;
1369         
1370         VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
1371         object_config_p obj_config = CONFIG(obj_context->config_id);
1372
1373         switch (obj_config->profile) {
1374                 case VAProfileMPEG2Simple:
1375                 case VAProfileMPEG2Main:
1376                         vaStatus = crystalhd_render_slice_parameter_buffer_mpeg2(ctx, obj_context, obj_buffer);
1377                         break;
1378
1379                 case VAProfileH264Baseline:
1380                 case VAProfileH264Main:
1381                 case VAProfileH264High:
1382                         vaStatus = crystalhd_render_slice_parameter_buffer_h264(ctx, obj_context, obj_buffer);
1383                         break;
1384 #if 0
1385                 case VAProfileVC1Simple:
1386                 case VAProfileVC1Main:
1387                 case VAProfileVC1Advanced:
1388                         vaStatus = crystalhd_render_slice_parameter_buffer_vc1(ctx, obj_context, obj_buffer);
1389                         break;
1390 #endif
1391
1392                 default:
1393                         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
1394         }
1395
1396         return vaStatus;
1397 }
1398
1399 VAStatus crystalhd_render_slice_data_buffer(
1400                 VADriverContextP ctx,
1401                 object_context_p obj_context,
1402                 object_buffer_p obj_buffer
1403         )
1404 {
1405         INIT_DRIVER_DATA;
1406
1407         VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
1408         object_config_p obj_config = CONFIG(obj_context->config_id);
1409
1410         switch (obj_config->profile) {
1411                 case VAProfileMPEG2Simple:
1412                 case VAProfileMPEG2Main:
1413                         vaStatus = crystalhd_render_slice_data_buffer_mpeg2(ctx, obj_context, obj_buffer);
1414                         break;
1415
1416                 case VAProfileH264Baseline:
1417                 case VAProfileH264Main:
1418                 case VAProfileH264High:
1419                         vaStatus = crystalhd_render_slice_data_buffer_h264(ctx, obj_context, obj_buffer);
1420                         break;
1421
1422 #if 0
1423                 case VAProfileVC1Simple:
1424                 case VAProfileVC1Main:
1425                 case VAProfileVC1Advanced:
1426                         vaStatus = crystalhd_render_slice_data_buffer_vc1(ctx, obj_context, obj_buffer);
1427                         break;
1428 #endif
1429
1430                 default:
1431                         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
1432         }
1433
1434         return vaStatus;
1435 }
1436
1437 VAStatus crystalhd_RenderPicture(
1438                 VADriverContextP ctx,
1439                 VAContextID context,
1440                 VABufferID *buffers,
1441                 int num_buffers
1442         )
1443 {
1444         INIT_DRIVER_DATA;
1445
1446         VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
1447         int i;
1448
1449         object_context_p obj_context = CONTEXT(context);
1450         assert(obj_context);
1451
1452         object_surface_p obj_surface = SURFACE(obj_context->current_render_target);
1453         assert(obj_surface);
1454
1455         /* verify that we got valid buffer references */
1456         crystalhd__information_message("%s: num_buffers = %d\n", __func__, num_buffers);
1457         for(i = 0; i < num_buffers; ++i)
1458         {
1459                 object_buffer_p obj_buffer = BUFFER(buffers[i]);
1460                 assert(obj_buffer);
1461                 if (NULL == obj_buffer)
1462                 {
1463                         return VA_STATUS_ERROR_INVALID_BUFFER;
1464                 }
1465                 crystalhd__information_message("%s:   buffer[%d] = %p, type = %s\n", __func__, i, obj_buffer, string_of_VABufferType(obj_buffer->type));
1466         }
1467
1468         for(i = 0;i < num_buffers; ++i)
1469         {
1470                 object_buffer_p obj_buffer = BUFFER(buffers[i]);
1471                 switch (obj_buffer->type)
1472                 {
1473                 case VAIQMatrixBufferType:
1474                         vaStatus = crystalhd_render_iqmatrix_buffer(ctx, obj_context, obj_buffer);
1475                         break;
1476
1477                 case VAPictureParameterBufferType:
1478                         vaStatus = crystalhd_render_picture_parameter_buffer(ctx, obj_context, obj_buffer);
1479                         break;
1480
1481                 case VASliceParameterBufferType:
1482                         vaStatus = crystalhd_render_slice_parameter_buffer(ctx, obj_context, obj_buffer);
1483                         break;
1484
1485                 case VASliceDataBufferType:
1486                         vaStatus = crystalhd_render_slice_data_buffer(ctx, obj_context, obj_buffer);
1487                         break;
1488
1489                 default:
1490                         crystalhd__information_message("%s: byffer type '%d' not handled.\n", __func__, obj_buffer->type);
1491                 }
1492         }
1493
1494         return vaStatus;
1495 }
1496
1497 VAStatus crystalhd_EndPicture(
1498                 VADriverContextP ctx,
1499                 VAContextID context
1500         )
1501 {
1502         INIT_DRIVER_DATA;
1503
1504         VAStatus vaStatus = VA_STATUS_SUCCESS;
1505
1506         object_context_p obj_context = CONTEXT(context);
1507         if ( NULL == obj_context )
1508         {
1509                 vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
1510                 goto error;
1511         }
1512
1513         object_config_p obj_config = CONFIG(obj_context->config_id);
1514         if ( NULL == obj_config )
1515         {
1516                 vaStatus = VA_STATUS_ERROR_INVALID_CONFIG;
1517                 goto error;
1518         }
1519
1520         object_surface_p obj_surface = SURFACE(obj_context->current_render_target);
1521         if ( NULL == obj_surface )
1522         {
1523                 vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
1524                 goto error;
1525         }
1526
1527         switch (obj_config->profile) {
1528                 case VAProfileMPEG2Simple:
1529                 case VAProfileMPEG2Main:
1530                         vaStatus = crystalhd_end_picture_mpeg2(ctx, obj_context, obj_surface);
1531                         break;
1532
1533                 case VAProfileH264Baseline:
1534                 case VAProfileH264Main:
1535                 case VAProfileH264High:
1536                         vaStatus = crystalhd_end_picture_h264(ctx, obj_context, obj_surface);
1537                         break;
1538 #if 0
1539                 case VAProfileVC1Simple:
1540                 case VAProfileVC1Main:
1541                 case VAProfileVC1Advanced:
1542                         vaStatus = crystalhd_end_picture_vc1(ctx, obj_context, obj_surface);
1543                         break;
1544 #endif
1545                 default:
1546                         vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
1547         }
1548         if ( VA_STATUS_SUCCESS != vaStatus )
1549                 goto error;
1550
1551         unsigned int width, height, width2, height2, flags;
1552         width = obj_context->picture_width;
1553         height = obj_context->picture_height;
1554 again:
1555         width2 = (width + 1) / 2;
1556         height2 = (height + 1) / 2;
1557
1558         VAImage image = { .image_id = VA_INVALID_ID };
1559         vaStatus = crystalhd_CreateImage(ctx, (VAImageFormat *) &(crystalhd_image_formats_map[0].va_format), width, height, &image);
1560         if ( VA_STATUS_SUCCESS != vaStatus )
1561                 goto error;
1562
1563         object_buffer_p obj_image_buf = BUFFER(image.buf);
1564
1565         BC_DTS_PROC_OUT output;
1566         memset(&output, 0, sizeof(output));
1567         output.PoutFlags        = BC_POUT_FLAGS_SIZE;
1568         output.PicInfo.width    = width;
1569         output.PicInfo.height   = height;
1570         output.Ybuff            = obj_image_buf->buffer_data;
1571         output.YbuffSz          = width * height;
1572         output.UVbuff           = obj_image_buf->buffer_data + output.YbuffSz;
1573         output.UVbuffSz         = 2 * width2 * height2;
1574
1575         BC_STATUS sts;
1576         sts = DtsProcOutput(driver_data->hdev, DTS_OUTPUT_TIMEOUT, &output);
1577         switch (sts) {
1578         case BC_STS_SUCCESS:
1579                 if (!(output.PoutFlags & BC_POUT_FLAGS_PIB_VALID))
1580                 {
1581                         crystalhd__information_message("%s: checking BC_POUT_FLAG_PIB_VALID failed. trying again.\n", __func__);
1582                         goto again;
1583                 }
1584                 break;
1585
1586         case BC_STS_FMT_CHANGE:
1587                 flags = BC_POUT_FLAGS_PIB_VALID | BC_POUT_FLAGS_FMT_CHANGE;
1588                 if ((output.PoutFlags & flags) == flags) {
1589                         width = output.PicInfo.width;
1590                         height = output.PicInfo.height;
1591                 }
1592                 goto again;
1593
1594         default:
1595                 if (sts != BC_STS_SUCCESS)
1596                 {
1597                         crystalhd__information_message("status = %d\n", sts);
1598                         return VA_STATUS_ERROR_OPERATION_FAILED;
1599                 }
1600         }
1601         obj_surface->output_image_id = image.image_id;
1602
1603         // For now, assume that we are done with rendering right away
1604         obj_context->current_render_target = -1;
1605
1606 error_DestroyImage:
1607         crystalhd_DestroyImage(ctx, image.image_id);
1608
1609 error:
1610         return vaStatus;
1611 }
1612
1613 VAStatus crystalhd_SyncSurface(
1614                 VADriverContextP ctx,
1615                 VASurfaceID render_target
1616         )
1617 {
1618         INIT_DRIVER_DATA;
1619
1620         VAStatus vaStatus = VA_STATUS_ERROR_UNIMPLEMENTED;
1621
1622         return vaStatus;
1623 }
1624
1625 VAStatus crystalhd_QuerySurfaceStatus(
1626                 VADriverContextP ctx,
1627                 VASurfaceID render_target,
1628                 VASurfaceStatus *status /* out */
1629         )
1630 {
1631         INIT_DRIVER_DATA;
1632
1633         VAStatus vaStatus = VA_STATUS_SUCCESS;
1634         object_surface_p obj_surface;
1635
1636         obj_surface = SURFACE(render_target);
1637         if ( NULL != obj_surface)
1638         {
1639                 vaStatus = VA_STATUS_ERROR_INVALID_SURFACE;
1640                 goto error;
1641         }
1642
1643         /* TODO: check for surface status */
1644         *status = VASurfaceReady;
1645
1646 error:
1647         return vaStatus;
1648 }
1649
1650 VAStatus crystalhd_PutSurface(
1651                 VADriverContextP ctx,
1652                 VASurfaceID surface,
1653                 void *draw, /* Drawable of window system */
1654                 short srcx,
1655                 short srcy,
1656                 unsigned short srcw,
1657                 unsigned short srch,
1658                 short destx,
1659                 short desty,
1660                 unsigned short destw,
1661                 unsigned short desth,
1662                 VARectangle *cliprects, /* client supplied clip list */
1663                 unsigned int number_cliprects, /* number of clip rects in the clip list */
1664                 unsigned int flags /* de-interlacing flags */
1665         )
1666 {
1667         INIT_DRIVER_DATA;
1668
1669 //      return VA_STATUS_ERROR_UNIMPLEMENTED;
1670         return VA_STATUS_SUCCESS;
1671 }
1672
1673 /* 
1674  * Query display attributes 
1675  * The caller must provide a "attr_list" array that can hold at
1676  * least vaMaxNumDisplayAttributes() entries. The actual number of attributes
1677  * returned in "attr_list" is returned in "num_attributes".
1678  */
1679 VAStatus crystalhd_QueryDisplayAttributes (
1680                 VADriverContextP ctx,
1681                 VADisplayAttribute *attr_list,  /* out */
1682                 int *num_attributes             /* out */
1683         )
1684 {
1685         INIT_DRIVER_DATA;
1686
1687         if (num_attributes)
1688                 *num_attributes = 0;
1689
1690         return VA_STATUS_SUCCESS;
1691 }
1692
1693 /* 
1694  * Get display attributes 
1695  * This function returns the current attribute values in "attr_list".
1696  * Only attributes returned with VA_DISPLAY_ATTRIB_GETTABLE set in the "flags" field
1697  * from vaQueryDisplayAttributes() can have their values retrieved.  
1698  */
1699 VAStatus crystalhd_GetDisplayAttributes (
1700                 VADriverContextP ctx,
1701                 VADisplayAttribute *attr_list,  /* in/out */
1702                 int num_attributes
1703         )
1704 {
1705         INIT_DRIVER_DATA;
1706
1707         /* TODO */
1708
1709         return VA_STATUS_ERROR_UNIMPLEMENTED;
1710 }
1711
1712 /* 
1713  * Set display attributes 
1714  * Only attributes returned with VA_DISPLAY_ATTRIB_SETTABLE set in the "flags" field
1715  * from vaQueryDisplayAttributes() can be set.  If the attribute is not settable or 
1716  * the value is out of range, the function returns VA_STATUS_ERROR_ATTR_NOT_SUPPORTED
1717  */
1718 VAStatus crystalhd_SetDisplayAttributes (
1719                 VADriverContextP ctx,
1720                 VADisplayAttribute *attr_list,
1721                 int num_attributes
1722         )
1723 {
1724         INIT_DRIVER_DATA;
1725
1726         /* TODO */
1727
1728         return VA_STATUS_ERROR_UNIMPLEMENTED;
1729 }
1730
1731
1732 VAStatus crystalhd_BufferInfo(
1733                 VADriverContextP ctx,
1734                 VAContextID context,            /* in */
1735                 VABufferID buffer_id,           /* in */
1736                 VABufferType *type,             /* out */
1737                 unsigned int *size,             /* out */
1738                 unsigned int *num_elements      /* out */
1739         )
1740 {
1741         INIT_DRIVER_DATA;
1742
1743         object_buffer_p obj_buffer = BUFFER(buffer_id);
1744         if (NULL == obj_buffer)
1745         {
1746                 return VA_STATUS_ERROR_INVALID_BUFFER;
1747         }
1748
1749         if (NULL != type)
1750                 *type = obj_buffer->type;
1751
1752         if (NULL != size)
1753                 *size = obj_buffer->element_size;
1754
1755         if (NULL != num_elements)
1756                 *num_elements = obj_buffer->num_elements;
1757
1758         return VA_STATUS_SUCCESS;
1759 }
1760
1761 VAStatus crystalhd_LockSurface(
1762                 VADriverContextP ctx,
1763                 VASurfaceID surface,
1764                 unsigned int *fourcc, /* following are output argument */
1765                 unsigned int *luma_stride,
1766                 unsigned int *chroma_u_stride,
1767                 unsigned int *chroma_v_stride,
1768                 unsigned int *luma_offset,
1769                 unsigned int *chroma_u_offset,
1770                 unsigned int *chroma_v_offset,
1771                 unsigned int *buffer_name,
1772                 void **buffer
1773         )
1774 {
1775         /* TODO */
1776         return VA_STATUS_ERROR_UNIMPLEMENTED;
1777 }
1778
1779 VAStatus crystalhd_UnlockSurface(
1780                 VADriverContextP ctx,
1781                 VASurfaceID surface
1782         )
1783 {
1784         /* TODO */
1785         return VA_STATUS_ERROR_UNIMPLEMENTED;
1786 }
1787
1788 VAStatus
1789 crystalhd_Terminate(
1790                 VADriverContextP ctx
1791         )
1792 {
1793         INIT_DRIVER_DATA;
1794
1795         object_buffer_p obj_buffer;
1796         object_config_p obj_config;
1797         object_image_p obj_image;
1798         object_heap_iterator iter;
1799
1800         /* close device */
1801         if (driver_data->hdev)
1802         {
1803                 DtsDeviceClose(driver_data->hdev);
1804         }
1805
1806         /* Clean up images */
1807         obj_image = (object_image_p) object_heap_first( &driver_data->image_heap, &iter);
1808         while (obj_image)
1809         {
1810                 object_heap_free( &driver_data->image_heap, (object_base_p) obj_image);
1811                 obj_image = (object_image_p) object_heap_next( &driver_data->image_heap, &iter);
1812         }
1813         object_heap_destroy( &driver_data->image_heap );
1814
1815         /* Clean up left over buffers */
1816         obj_buffer = (object_buffer_p) object_heap_first( &driver_data->buffer_heap, &iter);
1817         while (obj_buffer)
1818         {
1819                 crystalhd__information_message("vaTerminate: bufferID %08x still allocated, destroying\n", obj_buffer->base.id);
1820                 crystalhd__destroy_buffer(driver_data, obj_buffer);
1821                 obj_buffer = (object_buffer_p) object_heap_next( &driver_data->buffer_heap, &iter);
1822         }
1823         object_heap_destroy( &driver_data->buffer_heap );
1824
1825         /* Clean up configs */
1826         obj_config = (object_config_p) object_heap_first( &driver_data->config_heap, &iter);
1827         while (obj_config)
1828         {
1829                 object_heap_free( &driver_data->config_heap, (object_base_p) obj_config);
1830                 obj_config = (object_config_p) object_heap_next( &driver_data->config_heap, &iter);
1831         }
1832         object_heap_destroy( &driver_data->config_heap );
1833
1834         object_heap_destroy( &driver_data->surface_heap );
1835         object_heap_destroy( &driver_data->context_heap );
1836         free(ctx->pDriverData);
1837
1838         return VA_STATUS_SUCCESS;
1839 }
1840
1841 VAStatus
1842 __vaDriverInit_0_31(
1843                 VADriverContextP ctx
1844         )
1845 {
1846         object_heap_iterator iter;
1847         object_buffer_p obj_buffer;
1848         object_config_p obj_config;
1849
1850         VAStatus vaStatus = VA_STATUS_SUCCESS;
1851
1852         ctx->version_major = VA_MAJOR_VERSION;
1853         ctx->version_minor = VA_MINOR_VERSION;
1854         ctx->max_profiles = CRYSTALHD_MAX_PROFILES;
1855         ctx->max_entrypoints = CRYSTALHD_MAX_ENTRYPOINTS;
1856         ctx->max_attributes = CRYSTALHD_MAX_CONFIG_ATTRIBUTES;
1857         ctx->max_image_formats = CRYSTALHD_MAX_IMAGE_FORMATS;
1858         ctx->max_subpic_formats = CRYSTALHD_MAX_SUBPIC_FORMATS;
1859         ctx->max_display_attributes = CRYSTALHD_MAX_DISPLAY_ATTRIBUTES;
1860         ctx->str_vendor = CRYSTALHD_STR_VENDOR;
1861
1862         ctx->vtable.vaTerminate = crystalhd_Terminate;
1863         ctx->vtable.vaQueryConfigEntrypoints = crystalhd_QueryConfigEntrypoints;
1864         ctx->vtable.vaQueryConfigProfiles = crystalhd_QueryConfigProfiles;
1865         ctx->vtable.vaQueryConfigEntrypoints = crystalhd_QueryConfigEntrypoints;
1866         ctx->vtable.vaQueryConfigAttributes = crystalhd_QueryConfigAttributes;
1867         ctx->vtable.vaCreateConfig = crystalhd_CreateConfig;
1868         ctx->vtable.vaDestroyConfig = crystalhd_DestroyConfig;
1869         ctx->vtable.vaGetConfigAttributes = crystalhd_GetConfigAttributes;
1870         ctx->vtable.vaCreateSurfaces = crystalhd_CreateSurfaces;
1871         ctx->vtable.vaDestroySurfaces = crystalhd_DestroySurfaces;
1872         ctx->vtable.vaCreateContext = crystalhd_CreateContext;
1873         ctx->vtable.vaDestroyContext = crystalhd_DestroyContext;
1874         ctx->vtable.vaCreateBuffer = crystalhd_CreateBuffer;
1875         ctx->vtable.vaBufferSetNumElements = crystalhd_BufferSetNumElements;
1876         ctx->vtable.vaMapBuffer = crystalhd_MapBuffer;
1877         ctx->vtable.vaUnmapBuffer = crystalhd_UnmapBuffer;
1878         ctx->vtable.vaDestroyBuffer = crystalhd_DestroyBuffer;
1879         ctx->vtable.vaBeginPicture = crystalhd_BeginPicture;
1880         ctx->vtable.vaRenderPicture = crystalhd_RenderPicture;
1881         ctx->vtable.vaEndPicture = crystalhd_EndPicture;
1882         ctx->vtable.vaSyncSurface = crystalhd_SyncSurface;
1883         ctx->vtable.vaQuerySurfaceStatus = crystalhd_QuerySurfaceStatus;
1884         ctx->vtable.vaPutSurface = crystalhd_PutSurface;
1885         ctx->vtable.vaQueryImageFormats = crystalhd_QueryImageFormats;
1886         ctx->vtable.vaCreateImage = crystalhd_CreateImage;
1887         ctx->vtable.vaDeriveImage = crystalhd_DeriveImage;
1888         ctx->vtable.vaDestroyImage = crystalhd_DestroyImage;
1889         ctx->vtable.vaSetImagePalette = crystalhd_SetImagePalette;
1890         ctx->vtable.vaGetImage = crystalhd_GetImage;
1891         ctx->vtable.vaPutImage = crystalhd_PutImage;
1892         ctx->vtable.vaQuerySubpictureFormats = crystalhd_QuerySubpictureFormats;
1893         ctx->vtable.vaCreateSubpicture = crystalhd_CreateSubpicture;
1894         ctx->vtable.vaDestroySubpicture = crystalhd_DestroySubpicture;
1895         ctx->vtable.vaSetSubpictureImage = crystalhd_SetSubpictureImage;
1896         ctx->vtable.vaSetSubpictureChromakey = crystalhd_SetSubpictureChromakey;
1897         ctx->vtable.vaSetSubpictureGlobalAlpha = crystalhd_SetSubpictureGlobalAlpha;
1898         ctx->vtable.vaAssociateSubpicture = crystalhd_AssociateSubpicture;
1899         ctx->vtable.vaDeassociateSubpicture = crystalhd_DeassociateSubpicture;
1900         ctx->vtable.vaQueryDisplayAttributes = crystalhd_QueryDisplayAttributes;
1901         ctx->vtable.vaGetDisplayAttributes = crystalhd_GetDisplayAttributes;
1902         ctx->vtable.vaSetDisplayAttributes = crystalhd_SetDisplayAttributes;
1903         ctx->vtable.vaLockSurface = crystalhd_LockSurface;
1904         ctx->vtable.vaUnlockSurface = crystalhd_UnlockSurface;
1905         ctx->vtable.vaBufferInfo = crystalhd_BufferInfo;
1906
1907         struct crystalhd_driver_data *driver_data = (struct crystalhd_driver_data *) malloc( sizeof(*driver_data) );
1908         if ( NULL == driver_data )
1909         {
1910                 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1911                 goto error_DeviceClose;
1912         }
1913         ctx->pDriverData = (void *) driver_data;
1914
1915         BC_STATUS sts = DtsDeviceOpen(&(driver_data->hdev),
1916                         DTS_PLAYBACK_MODE | DTS_LOAD_FILE_PLAY_FW |
1917                         DTS_DFLT_RESOLUTION(vdecRESOLUTION_CUSTOM));
1918         if ( sts != BC_STS_SUCCESS )
1919         {
1920                 vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
1921                 goto error_free_DriverData;
1922         }
1923
1924         if ( 0 != object_heap_init( &driver_data->config_heap, sizeof(struct object_config), CONFIG_ID_OFFSET ) )
1925         {
1926                 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1927                 goto error_DeviceClose;
1928         }
1929
1930         if ( 0 != object_heap_init( &driver_data->context_heap, sizeof(struct object_context), CONTEXT_ID_OFFSET ) )
1931         {
1932                 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1933                 goto error_free_ConfigHeap;
1934         }
1935
1936         if ( 0 != object_heap_init( &driver_data->surface_heap, sizeof(struct object_surface), SURFACE_ID_OFFSET ) )
1937         {
1938                 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1939                 goto error_free_ContextHeap;
1940         }
1941
1942         if ( 0 != object_heap_init( &driver_data->buffer_heap, sizeof(struct object_buffer), BUFFER_ID_OFFSET ) )
1943         {
1944                 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1945                 goto error_free_SurfaceHeap;
1946         }
1947
1948         if ( 0 != object_heap_init( &driver_data->image_heap, sizeof(struct object_image), IMAGE_ID_OFFSET ) )
1949         {
1950                 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
1951                 goto error_free_BufferHeap;
1952         }
1953
1954         return vaStatus;
1955
1956 error_free_BufferHeap:
1957         obj_buffer = (object_buffer_p) object_heap_first( &driver_data->buffer_heap, &iter);
1958         while (obj_buffer)
1959         {
1960                 crystalhd__information_message("vaTerminate: bufferID %08x still allocated, destroying\n", obj_buffer->base.id);
1961                 crystalhd__destroy_buffer(driver_data, obj_buffer);
1962                 obj_buffer = (object_buffer_p) object_heap_next( &driver_data->buffer_heap, &iter);
1963         }
1964         object_heap_destroy( &driver_data->buffer_heap );
1965
1966 error_free_SurfaceHeap:
1967         object_heap_destroy( &driver_data->surface_heap );
1968
1969 error_free_ContextHeap:
1970         object_heap_destroy( &driver_data->context_heap );
1971
1972 error_free_ConfigHeap:
1973         obj_config = (object_config_p) object_heap_first( &driver_data->config_heap, &iter);
1974         while (obj_config)
1975         {
1976                 object_heap_free( &driver_data->config_heap, (object_base_p) obj_config);
1977                 obj_config = (object_config_p) object_heap_next( &driver_data->config_heap, &iter);
1978         }
1979         object_heap_destroy( &driver_data->config_heap );
1980
1981 error_DeviceClose:
1982         DtsDeviceClose( driver_data->hdev );
1983
1984 error_free_DriverData:
1985         free( ctx->pDriverData );
1986
1987         return vaStatus;
1988 }