1 /*
2  INTEL CONFIDENTIAL
3  Copyright 2009 Intel Corporation All Rights Reserved.
4  The source code contained or described herein and all documents related to the source code ("Material") are owned by Intel Corporation or its suppliers or licensors. Title to the Material remains with Intel Corporation or its suppliers and licensors. The Material contains trade secrets and proprietary and confidential information of Intel or its suppliers and licensors. The Material is protected by worldwide copyright and trade secret laws and treaty provisions. No part of the Material may be used, copied, reproduced, modified, published, uploaded, posted, transmitted, distributed, or disclosed in any way without Intel’s prior express written permission.
5 
6  No license under any patent, copyright, trade secret or other intellectual property right is granted to or conferred upon you by disclosure or delivery of the Materials, either expressly, by implication, inducement, estoppel or otherwise. Any license under such intellectual property rights must be express and approved by Intel in writing.
7  */
8 #include <glib.h>
9 #include <string.h>
10 #include <stdlib.h>
11 
12 #include "mixvideolog.h"
13 
14 #include "mixvideoformatenc_h264.h"
15 #include "mixvideoconfigparamsenc_h264.h"
16 
17 #define MDEBUG
18 #undef SHOW_SRC
19 
20 #ifdef SHOW_SRC
21 Window win = 0;
22 #endif /* SHOW_SRC */
23 
24 
25 /* The parent class. The pointer will be saved
26  * in this class's initialization. The pointer
27  * can be used for chaining method call if needed.
28  */
29 static MixVideoFormatEncClass *parent_class = NULL;
30 
31 static void mix_videoformatenc_h264_finalize(GObject * obj);
32 
33 /*
34  * Please note that the type we pass to G_DEFINE_TYPE is MIX_TYPE_VIDEOFORMATENC
35  */
36 G_DEFINE_TYPE (MixVideoFormatEnc_H264, mix_videoformatenc_h264, MIX_TYPE_VIDEOFORMATENC);
37 
mix_videoformatenc_h264_init(MixVideoFormatEnc_H264 * self)38 static void mix_videoformatenc_h264_init(MixVideoFormatEnc_H264 * self) {
39     MixVideoFormatEnc *parent = MIX_VIDEOFORMATENC(self);
40 
41     /* TODO: public member initialization */
42 
43     /* TODO: private member initialization */
44     self->encoded_frames = 0;
45     self->pic_skipped = FALSE;
46     self->is_intra = TRUE;
47     self->cur_fame = NULL;
48     self->ref_fame = NULL;
49     self->rec_fame = NULL;
50 
51     self->ci_shared_surfaces = NULL;
52     self->surfaces= NULL;
53     self->surface_num = 0;
54 
55     parent->initialized = FALSE;
56 }
57 
mix_videoformatenc_h264_class_init(MixVideoFormatEnc_H264Class * klass)58 static void mix_videoformatenc_h264_class_init(
59         MixVideoFormatEnc_H264Class * klass) {
60 
61     /* root class */
62     GObjectClass *gobject_class = (GObjectClass *) klass;
63 
64     /* direct parent class */
65     MixVideoFormatEncClass *video_formatenc_class =
66         MIX_VIDEOFORMATENC_CLASS(klass);
67 
68     /* parent class for later use */
69     parent_class = g_type_class_peek_parent(klass);
70 
71     /* setup finializer */
72     gobject_class->finalize = mix_videoformatenc_h264_finalize;
73 
74     /* setup vmethods with base implementation */
75     /* TODO: decide if we need to override the parent's methods */
76     video_formatenc_class->getcaps = mix_videofmtenc_h264_getcaps;
77     video_formatenc_class->initialize = mix_videofmtenc_h264_initialize;
78     video_formatenc_class->encode = mix_videofmtenc_h264_encode;
79     video_formatenc_class->flush = mix_videofmtenc_h264_flush;
80     video_formatenc_class->eos = mix_videofmtenc_h264_eos;
81     video_formatenc_class->deinitialize = mix_videofmtenc_h264_deinitialize;
82     video_formatenc_class->getmaxencodedbufsize = mix_videofmtenc_h264_get_max_encoded_buf_size;
83 }
84 
85 MixVideoFormatEnc_H264 *
mix_videoformatenc_h264_new(void)86 mix_videoformatenc_h264_new(void) {
87     MixVideoFormatEnc_H264 *ret =
88         g_object_new(MIX_TYPE_VIDEOFORMATENC_H264, NULL);
89 
90     return ret;
91 }
92 
mix_videoformatenc_h264_finalize(GObject * obj)93 void mix_videoformatenc_h264_finalize(GObject * obj) {
94     /* clean up here. */
95 
96     /*MixVideoFormatEnc_H264 *mix = MIX_VIDEOFORMATENC_H264(obj); */
97     GObjectClass *root_class = (GObjectClass *) parent_class;
98 
99     LOG_V( "\n");
100 
101     /* Chain up parent */
102     if (root_class->finalize) {
103         root_class->finalize(obj);
104     }
105 }
106 
107 MixVideoFormatEnc_H264 *
mix_videoformatenc_h264_ref(MixVideoFormatEnc_H264 * mix)108 mix_videoformatenc_h264_ref(MixVideoFormatEnc_H264 * mix) {
109     return (MixVideoFormatEnc_H264 *) g_object_ref(G_OBJECT(mix));
110 }
111 
112 /*H.264 vmethods implementation */
mix_videofmtenc_h264_getcaps(MixVideoFormatEnc * mix,GString * msg)113 MIX_RESULT mix_videofmtenc_h264_getcaps(MixVideoFormatEnc *mix, GString *msg) {
114 
115     /* TODO: add codes for H.264 */
116 
117     /* TODO: decide if we need to chainup parent method.
118      * if we do, the following is the code:
119      */
120 
121     LOG_V( "mix_videofmtenc_h264_getcaps\n");
122 
123     if (mix == NULL) {
124         LOG_E( "mix == NULL\n");
125         return MIX_RESULT_NULL_PTR;
126     }
127 
128 
129     if (parent_class->getcaps) {
130         return parent_class->getcaps(mix, msg);
131     }
132     return MIX_RESULT_SUCCESS;
133 }
134 
mix_videofmtenc_h264_initialize(MixVideoFormatEnc * mix,MixVideoConfigParamsEnc * config_params_enc,MixFrameManager * frame_mgr,MixBufferPool * input_buf_pool,MixSurfacePool ** surface_pool,VADisplay va_display)135 MIX_RESULT mix_videofmtenc_h264_initialize(MixVideoFormatEnc *mix,
136         MixVideoConfigParamsEnc * config_params_enc,
137         MixFrameManager * frame_mgr,
138         MixBufferPool * input_buf_pool,
139         MixSurfacePool ** surface_pool,
140         VADisplay va_display ) {
141 
142     MIX_RESULT ret = MIX_RESULT_SUCCESS;
143     MixVideoFormatEnc *parent = NULL;
144     MixVideoConfigParamsEncH264 * config_params_enc_h264;
145 
146     VAStatus va_status = VA_STATUS_SUCCESS;
147     VASurfaceID * surfaces;
148 
149     gint va_max_num_profiles, va_max_num_entrypoints, va_max_num_attribs;
150     gint va_num_profiles,  va_num_entrypoints;
151 
152     VAProfile *va_profiles = NULL;
153     VAEntrypoint *va_entrypoints = NULL;
154     VAConfigAttrib va_attrib[2];
155     guint index;
156 
157 
158     /*frame_mgr and input_buf_pool is reservered for future use*/
159 
160     if (mix == NULL || config_params_enc == NULL || va_display == NULL) {
161         LOG_E(
162                 "mix == NULL || config_params_enc == NULL || va_display == NULL\n");
163         return MIX_RESULT_NULL_PTR;
164     }
165 
166     LOG_V( "begin\n");
167 
168 
169     //TODO additional parameter checking
170 
171     /* Chainup parent method. */
172 #if 1
173     if (parent_class->initialize) {
174         ret = parent_class->initialize(mix, config_params_enc,
175                 frame_mgr, input_buf_pool, surface_pool,
176                 va_display);
177     }
178 
179     if (ret != MIX_RESULT_SUCCESS)
180     {
181         return ret;
182     }
183 
184 #endif //disable it currently
185 
186     if (MIX_IS_VIDEOFORMATENC_H264(mix))
187     {
188         parent = MIX_VIDEOFORMATENC(&(mix->parent));
189         MixVideoFormatEnc_H264 *self = MIX_VIDEOFORMATENC_H264(mix);
190 
191         if (MIX_IS_VIDEOCONFIGPARAMSENC_H264 (config_params_enc)) {
192             config_params_enc_h264 =
193                 MIX_VIDEOCONFIGPARAMSENC_H264 (config_params_enc);
194         } else {
195             LOG_V(
196                     "mix_videofmtenc_h264_initialize:  no h264 config params found\n");
197             return MIX_RESULT_FAIL;
198         }
199 
200         g_mutex_lock(parent->objectlock);
201 
202         LOG_V(
203                 "Start to get properities from h.264 params\n");
204 
205         /* get properties from H264 params Object, which is special to H264 format*/
206         ret = mix_videoconfigparamsenc_h264_get_bus (config_params_enc_h264,
207                 &self->basic_unit_size);
208 
209         if (ret != MIX_RESULT_SUCCESS) {
210             //TODO cleanup
211             LOG_E(
212                     "Failed to mix_videoconfigparamsenc_h264_get_bus\n");
213             g_mutex_unlock(parent->objectlock);
214             return MIX_RESULT_FAIL;
215         }
216 
217 
218         ret = mix_videoconfigparamsenc_h264_get_dlk (config_params_enc_h264,
219                 &self->disable_deblocking_filter_idc);
220 
221         if (ret != MIX_RESULT_SUCCESS) {
222             //TODO cleanup
223             LOG_E(
224                     "Failed to mix_videoconfigparamsenc_h264_get_dlk\n");
225             g_mutex_unlock(parent->objectlock);
226             return MIX_RESULT_FAIL;
227         }
228 
229 
230         ret = mix_videoconfigparamsenc_h264_get_slice_num (config_params_enc_h264,
231                 &self->slice_num);
232 
233         if (ret != MIX_RESULT_SUCCESS) {
234             //TODO cleanup
235             LOG_E(
236                     "Failed to mix_videoconfigparamsenc_h264_get_slice_num\n");
237             g_mutex_unlock(parent->objectlock);
238             return MIX_RESULT_FAIL;
239         }
240 
241         ret = mix_videoconfigparamsenc_h264_get_delimiter_type (config_params_enc_h264,
242                 &self->delimiter_type);
243 
244         if (ret != MIX_RESULT_SUCCESS) {
245             //TODO cleanup
246             LOG_E (
247                     "Failed to mix_videoconfigparamsenc_h264_get_delimiter_type\n");
248             g_mutex_unlock(parent->objectlock);
249             return MIX_RESULT_FAIL;
250         }
251 
252         LOG_V(
253                 "======H264 Encode Object properities======:\n");
254 
255         LOG_I( "self->basic_unit_size = %d\n",
256                 self->basic_unit_size);
257         LOG_I( "self->disable_deblocking_filter_idc = %d\n",
258                 self->disable_deblocking_filter_idc);
259         LOG_I( "self->slice_num = %d\n",
260                 self->slice_num);
261         LOG_I ("self->delimiter_type = %d\n",
262                 self->delimiter_type);
263 
264         LOG_V(
265                 "Get properities from params done\n");
266 
267 
268     	//display = XOpenDisplay(NULL);
269      	//va_display = vaGetDisplay (videoencobj->display);
270 
271         parent->va_display = va_display;
272 
273         LOG_V( "Get Display\n");
274         LOG_I( "Display = 0x%08x\n",
275                 (guint)va_display);
276 
277         //va_status = vaInitialize(va_display, &va_major_ver, &va_minor_ver);
278         //g_print ("vaInitialize va_status = %d\n", va_status);
279 
280 
281 #if 0
282         /* query the vender information, can ignore*/
283         va_vendor = vaQueryVendorString (va_display);
284         LOG_I( "Vendor = %s\n",
285                 va_vendor);
286 #endif
287 
288         /*get the max number for profiles/entrypoints/attribs*/
289         va_max_num_profiles = vaMaxNumProfiles(va_display);
290         LOG_I( "va_max_num_profiles = %d\n",
291                 va_max_num_profiles);
292 
293         va_max_num_entrypoints = vaMaxNumEntrypoints(va_display);
294         LOG_I( "va_max_num_entrypoints = %d\n",
295                 va_max_num_entrypoints);
296 
297         va_max_num_attribs = vaMaxNumConfigAttributes(va_display);
298         LOG_I( "va_max_num_attribs = %d\n",
299                 va_max_num_attribs);
300 
301         va_profiles = g_malloc(sizeof(VAProfile)*va_max_num_profiles);
302         va_entrypoints = g_malloc(sizeof(VAEntrypoint)*va_max_num_entrypoints);
303 
304         if (va_profiles == NULL || va_entrypoints ==NULL)
305         {
306             LOG_E(
307                     "!va_profiles || !va_entrypoints\n");
308             g_mutex_unlock(parent->objectlock);
309             return MIX_RESULT_NO_MEMORY;
310         }
311 
312         LOG_I(
313                 "va_profiles = 0x%08x\n", (guint)va_profiles);
314 
315         LOG_V( "vaQueryConfigProfiles\n");
316 
317 
318         va_status = vaQueryConfigProfiles (va_display, va_profiles, &va_num_profiles);
319 
320         if (va_status != VA_STATUS_SUCCESS)
321         {
322             LOG_E(
323                     "Failed to call vaQueryConfigProfiles\n");
324             g_free(va_profiles);
325             g_free (va_entrypoints);
326             g_mutex_unlock(parent->objectlock);
327             return MIX_RESULT_FAIL;
328         }
329 
330         LOG_V( "vaQueryConfigProfiles Done\n");
331 
332 
333 
334         /*check whether profile is supported*/
335         for(index= 0; index < va_num_profiles; index++) {
336             if(parent->va_profile == va_profiles[index])
337                 break;
338         }
339 
340         if(index == va_num_profiles)
341         {
342             LOG_E( "Profile not supported\n");
343             g_free(va_profiles);
344             g_free (va_entrypoints);
345             g_mutex_unlock(parent->objectlock);
346             return MIX_RESULT_FAIL;  //Todo, add error handling here
347         }
348 
349         LOG_V( "vaQueryConfigEntrypoints\n");
350 
351 
352         /*Check entry point*/
353         va_status = vaQueryConfigEntrypoints(va_display,
354                 parent->va_profile,
355                 va_entrypoints, &va_num_entrypoints);
356 
357         if (va_status != VA_STATUS_SUCCESS)
358         {
359             LOG_E(
360                     "Failed to call vaQueryConfigEntrypoints\n");
361             g_free(va_profiles);
362             g_free (va_entrypoints);
363             g_mutex_unlock(parent->objectlock);
364             return MIX_RESULT_FAIL;
365         }
366 
367         for (index = 0; index < va_num_entrypoints; index ++) {
368             if (va_entrypoints[index] == VAEntrypointEncSlice) {
369                 break;
370             }
371         }
372 
373         if (index == va_num_entrypoints) {
374             LOG_E( "Entrypoint not found\n");
375             g_free(va_profiles);
376             g_free (va_entrypoints);
377             g_mutex_unlock(parent->objectlock);
378             return MIX_RESULT_FAIL;  //Todo, add error handling here
379         }
380 
381 
382         /*free profiles and entrypoints*/
383         g_free(va_profiles);
384         g_free (va_entrypoints);
385 
386         va_attrib[0].type = VAConfigAttribRTFormat;
387         va_attrib[1].type = VAConfigAttribRateControl;
388 
389         LOG_V( "vaGetConfigAttributes\n");
390 
391         va_status = vaGetConfigAttributes(va_display, parent->va_profile,
392                 parent->va_entrypoint,
393                 &va_attrib[0], 2);
394 
395         if (va_status != VA_STATUS_SUCCESS)
396         {
397             LOG_E(
398                     "Failed to call vaGetConfigAttributes\n");
399             g_mutex_unlock(parent->objectlock);
400             return MIX_RESULT_FAIL;
401         }
402 
403         if ((va_attrib[0].value & parent->va_format) == 0) {
404             LOG_E( "Matched format not found\n");
405             g_mutex_unlock(parent->objectlock);
406             return MIX_RESULT_FAIL;  //Todo, add error handling here
407         }
408 
409 
410         if ((va_attrib[1].value & parent->va_rcmode) == 0) {
411             LOG_E( "RC mode not found\n");
412             g_mutex_unlock(parent->objectlock);
413             return MIX_RESULT_FAIL;  //Todo, add error handling here
414         }
415 
416         va_attrib[0].value = parent->va_format; //VA_RT_FORMAT_YUV420;
417         va_attrib[1].value = parent->va_rcmode;
418 
419         LOG_V( "======VA Configuration======\n");
420 
421         LOG_I( "profile = %d\n",
422                 parent->va_profile);
423         LOG_I( "va_entrypoint = %d\n",
424                 parent->va_entrypoint);
425         LOG_I( "va_attrib[0].type = %d\n",
426                 va_attrib[0].type);
427         LOG_I( "va_attrib[1].type = %d\n",
428                 va_attrib[1].type);
429         LOG_I( "va_attrib[0].value (Format) = %d\n",
430                 va_attrib[0].value);
431         LOG_I( "va_attrib[1].value (RC mode) = %d\n",
432                 va_attrib[1].value);
433 
434         LOG_V( "vaCreateConfig\n");
435 
436         va_status = vaCreateConfig(va_display, parent->va_profile,
437                 parent->va_entrypoint,
438                 &va_attrib[0], 2, &(parent->va_config));
439 
440         if (va_status != VA_STATUS_SUCCESS)
441         {
442             LOG_E( "Failed vaCreateConfig\n");
443             g_mutex_unlock(parent->objectlock);
444             return MIX_RESULT_FAIL;
445         }
446 
447         /*TODO: compute the surface number*/
448         int numSurfaces;
449 
450         if (parent->share_buf_mode) {
451             numSurfaces = 2;
452         }
453         else {
454             numSurfaces = 8;
455             parent->ci_frame_num = 0;
456         }
457 
458         self->surface_num = numSurfaces + parent->ci_frame_num;
459 
460         surfaces = g_malloc(sizeof(VASurfaceID)*numSurfaces);
461 
462         if (surfaces == NULL)
463         {
464             LOG_E(
465                     "Failed allocate surface\n");
466             g_mutex_unlock(parent->objectlock);
467             return MIX_RESULT_NO_MEMORY;
468         }
469 
470         LOG_V( "vaCreateSurfaces\n");
471 
472         va_status = vaCreateSurfaces(va_display, parent->picture_width,
473                 parent->picture_height, parent->va_format,
474                 numSurfaces, surfaces);
475         //TODO check vret and return fail if needed
476 
477         if (va_status != VA_STATUS_SUCCESS)
478         {
479             LOG_E(
480                     "Failed vaCreateSurfaces\n");
481             g_mutex_unlock(parent->objectlock);
482             return MIX_RESULT_FAIL;
483         }
484 
485         if (parent->share_buf_mode) {
486 
487             LOG_V(
488                     "We are in share buffer mode!\n");
489             self->ci_shared_surfaces =
490                 g_malloc(sizeof(VASurfaceID) * parent->ci_frame_num);
491 
492             if (self->ci_shared_surfaces == NULL)
493             {
494                 LOG_E(
495                         "Failed allocate shared surface\n");
496                 g_mutex_unlock(parent->objectlock);
497                 return MIX_RESULT_NO_MEMORY;
498             }
499 
500             guint index;
501             for(index = 0; index < parent->ci_frame_num; index++) {
502 
503                 LOG_I( "ci_frame_id = %lu\n",
504                         parent->ci_frame_id[index]);
505 
506                 LOG_V(
507                         "vaCreateSurfaceFromCIFrame\n");
508 
509                 va_status = vaCreateSurfaceFromCIFrame(va_display,
510                         (gulong) (parent->ci_frame_id[index]),
511                         &self->ci_shared_surfaces[index]);
512                 if (va_status != VA_STATUS_SUCCESS)
513                 {
514                     LOG_E(
515                             "Failed to vaCreateSurfaceFromCIFrame\n");
516                     g_mutex_unlock(parent->objectlock);
517                     return MIX_RESULT_FAIL;
518                 }
519             }
520 
521             LOG_V(
522                     "vaCreateSurfaceFromCIFrame Done\n");
523 
524         }// if (parent->share_buf_mode)
525 
526         self->surfaces = g_malloc(sizeof(VASurfaceID) * self->surface_num);
527 
528         if (self->surfaces == NULL)
529         {
530             LOG_E(
531                     "Failed allocate private surface\n");
532             g_free (surfaces);
533             g_mutex_unlock(parent->objectlock);
534             return MIX_RESULT_NO_MEMORY;
535         }
536 
537         if (parent->share_buf_mode) {
538             /*shared surfaces should be put in pool first,
539              * because we will get it accoring to CI index*/
540             for(index = 0; index < parent->ci_frame_num; index++)
541                 self->surfaces[index] = self->ci_shared_surfaces[index];
542         }
543 
544         for(index = 0; index < numSurfaces; index++) {
545             self->surfaces[index + parent->ci_frame_num] = surfaces[index];
546         }
547 
548         LOG_V( "assign surface Done\n");
549         LOG_I( "Created %d libva surfaces\n",
550                 numSurfaces + parent->ci_frame_num);
551 
552 #if 0  //current put this in gst
553         images = g_malloc(sizeof(VAImage)*numSurfaces);
554         if (images == NULL)
555         {
556             g_mutex_unlock(parent->objectlock);
557             return MIX_RESULT_FAIL;
558         }
559 
560         for (index = 0; index < numSurfaces; index++) {
561             //Derive an VAImage from an existing surface.
562             //The image buffer can then be mapped/unmapped for CPU access
563             va_status = vaDeriveImage(va_display, surfaces[index],
564                     &images[index]);
565         }
566 #endif
567 
568         LOG_V( "mix_surfacepool_new\n");
569 
570         parent->surfacepool = mix_surfacepool_new();
571         if (surface_pool)
572             *surface_pool = parent->surfacepool;
573         //which is useful to check before encode
574 
575         if (parent->surfacepool == NULL)
576         {
577             LOG_E(
578                     "Failed to mix_surfacepool_new\n");
579             g_free (surfaces);
580             g_mutex_unlock(parent->objectlock);
581             return MIX_RESULT_FAIL;
582         }
583 
584         LOG_V(
585                 "mix_surfacepool_initialize\n");
586 
587         ret = mix_surfacepool_initialize(parent->surfacepool,
588                 self->surfaces, parent->ci_frame_num + numSurfaces);
589 
590         switch (ret)
591         {
592             case MIX_RESULT_SUCCESS:
593                 break;
594             case MIX_RESULT_ALREADY_INIT:
595                 //TODO cleanup and/or retry
596                 g_free (surfaces);
597                 g_mutex_unlock(parent->objectlock);
598                 return MIX_RESULT_FAIL;
599             default:
600                 break;
601         }
602 
603 
604         //Initialize and save the VA context ID
605         LOG_V( "vaCreateContext\n");
606 
607         va_status = vaCreateContext(va_display, parent->va_config,
608                 parent->picture_width, parent->picture_height,
609                 0, self->surfaces, parent->ci_frame_num + numSurfaces,
610                 &(parent->va_context));
611 
612         LOG_I(
613                 "Created libva context width %d, height %d\n",
614                 parent->picture_width, parent->picture_height);
615 
616         if (va_status != VA_STATUS_SUCCESS)
617         {
618             LOG_E(
619                     "Failed to vaCreateContext\n");
620             LOG_I( "va_status = %d\n",
621                     (guint)va_status);
622             g_free (surfaces);
623             g_mutex_unlock(parent->objectlock);
624             return MIX_RESULT_FAIL;
625         }
626 
627         guint max_size = 0;
628         ret = mix_videofmtenc_h264_get_max_encoded_buf_size (parent, &max_size);
629         if (ret != MIX_RESULT_SUCCESS)
630         {
631             LOG_E(
632                     "Failed to mix_videofmtenc_h264_get_max_encoded_buf_size\n");
633             g_free (surfaces);
634             g_mutex_unlock(parent->objectlock);
635             return MIX_RESULT_FAIL;
636 
637         }
638 
639         /*Create coded buffer for output*/
640         va_status = vaCreateBuffer (va_display, parent->va_context,
641                 VAEncCodedBufferType,
642                 self->coded_buf_size,  //
643                 1, NULL,
644                 &self->coded_buf);
645 
646         if (va_status != VA_STATUS_SUCCESS)
647         {
648             LOG_E(
649                     "Failed to vaCreateBuffer: VAEncCodedBufferType\n");
650             g_free (surfaces);
651             g_mutex_unlock(parent->objectlock);
652             return MIX_RESULT_FAIL;
653         }
654 
655 #ifdef SHOW_SRC
656         Display * display = XOpenDisplay (NULL);
657 
658         LOG_I( "display = 0x%08x\n",
659                 (guint) display);
660         win = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0,
661                 parent->picture_width,  parent->picture_height, 0, 0,
662                 WhitePixel(display, 0));
663         XMapWindow(display, win);
664         XSelectInput(display, win, KeyPressMask | StructureNotifyMask);
665 
666         XSync(display, False);
667         LOG_I( "va_display = 0x%08x\n",
668                 (guint) va_display);
669 
670 #endif /* SHOW_SRC */
671 
672         parent->initialized = TRUE;
673 
674         g_mutex_unlock(parent->objectlock);
675         g_free (surfaces);
676 
677     }
678     else
679     {
680         LOG_E(
681                 "not H264 video encode Object\n");
682         return MIX_RESULT_FAIL;
683 
684     }
685 
686     LOG_V( "end\n");
687 
688     return MIX_RESULT_SUCCESS;
689 }
690 
mix_videofmtenc_h264_encode(MixVideoFormatEnc * mix,MixBuffer * bufin[],gint bufincnt,MixIOVec * iovout[],gint iovoutcnt,MixVideoEncodeParams * encode_params)691 MIX_RESULT mix_videofmtenc_h264_encode(MixVideoFormatEnc *mix, MixBuffer * bufin[],
692         gint bufincnt, MixIOVec * iovout[], gint iovoutcnt,
693         MixVideoEncodeParams * encode_params) {
694 
695     MIX_RESULT ret = MIX_RESULT_SUCCESS;
696     MixVideoFormatEnc *parent = NULL;
697 
698     LOG_V( "Begin\n");
699 
700     /*currenly only support one input and output buffer*/
701     //TODO: params i
702 
703     if (bufincnt != 1 || iovoutcnt != 1) {
704         LOG_E(
705                 "buffer count not equel to 1\n");
706         LOG_E(
707                 "maybe some exception occurs\n");
708     }
709 
710     if (mix == NULL ||bufin[0] == NULL ||  iovout[0] == NULL) {
711         LOG_E(
712                 "!mix || !bufin[0] ||!iovout[0]\n");
713         return MIX_RESULT_NULL_PTR;
714     }
715 
716     //TODO: encode_params is reserved here for future usage.
717 
718     /* TODO: decide if we need to chainup parent method.
719      *      * * if we do, the following is the code:
720      * */
721 
722 #if 0
723     if (parent_class->encode) {
724         return parent_class->encode(mix, bufin, bufincnt, iovout,
725                 iovoutcnt, encode_params);
726     }
727 #endif
728 
729     if (MIX_IS_VIDEOFORMATENC_H264(mix))
730     {
731 
732         parent = MIX_VIDEOFORMATENC(&(mix->parent));
733         MixVideoFormatEnc_H264 *self = MIX_VIDEOFORMATENC_H264 (mix);
734 
735         LOG_V( "Locking\n");
736         g_mutex_lock(parent->objectlock);
737 
738 
739         //TODO: also we could move some encode Preparation work to here
740 
741         LOG_V(
742                 "mix_videofmtenc_h264_process_encode\n");
743 
744         ret = mix_videofmtenc_h264_process_encode (self,
745                 bufin[0], iovout[0]);
746         if (ret != MIX_RESULT_SUCCESS)
747         {
748             LOG_E(
749                     "Failed mix_videofmtenc_h264_process_encode\n");
750             g_mutex_unlock(parent->objectlock);
751             return MIX_RESULT_FAIL;
752         }
753 
754 
755         LOG_V( "UnLocking\n");
756 
757         g_mutex_unlock(parent->objectlock);
758     }
759     else
760     {
761         LOG_E(
762                 "not H264 video encode Object\n");
763         return MIX_RESULT_FAIL;
764     }
765 
766     LOG_V( "end\n");
767 
768     return MIX_RESULT_SUCCESS;
769 }
770 
mix_videofmtenc_h264_flush(MixVideoFormatEnc * mix)771 MIX_RESULT mix_videofmtenc_h264_flush(MixVideoFormatEnc *mix) {
772 
773     //MIX_RESULT ret = MIX_RESULT_SUCCESS;
774 
775     LOG_V( "Begin\n");
776 
777     if (mix == NULL) {
778         LOG_E( "mix == NULL\n");
779         return MIX_RESULT_NULL_PTR;
780     }
781 
782 
783     /*not chain to parent flush func*/
784 #if 0
785     if (parent_class->flush) {
786         return parent_class->flush(mix, msg);
787     }
788 #endif
789 
790     MixVideoFormatEnc_H264 *self = MIX_VIDEOFORMATENC_H264(mix);
791 
792     g_mutex_lock(mix->objectlock);
793 
794 #if 0
795     /*unref the current source surface*/
796     if (self->cur_fame != NULL)
797     {
798         mix_videoframe_unref (self->cur_fame);
799         self->cur_fame = NULL;
800     }
801 #endif
802 
803     /*unref the reconstructed surface*/
804     if (self->rec_fame != NULL)
805     {
806         mix_videoframe_unref (self->rec_fame);
807         self->rec_fame = NULL;
808     }
809 
810     /*unref the reference surface*/
811     if (self->ref_fame != NULL)
812     {
813         mix_videoframe_unref (self->ref_fame);
814         self->ref_fame = NULL;
815     }
816 
817     /*reset the properities*/
818     self->encoded_frames = 0;
819     self->pic_skipped = FALSE;
820     self->is_intra = TRUE;
821 
822     g_mutex_unlock(mix->objectlock);
823 
824     LOG_V( "end\n");
825 
826     return MIX_RESULT_SUCCESS;
827 }
828 
mix_videofmtenc_h264_eos(MixVideoFormatEnc * mix)829 MIX_RESULT mix_videofmtenc_h264_eos(MixVideoFormatEnc *mix) {
830 
831     /* TODO: add codes for H.264 */
832 
833     /* TODO: decide if we need to chainup parent method.
834      * if we do, the following is the code:
835      */
836 
837     LOG_V( "\n");
838 
839     if (mix == NULL) {
840         LOG_E( "mix == NULL\n");
841         return MIX_RESULT_NULL_PTR;
842     }
843 
844     if (parent_class->eos) {
845         return parent_class->eos(mix);
846     }
847     return MIX_RESULT_SUCCESS;
848 }
849 
mix_videofmtenc_h264_deinitialize(MixVideoFormatEnc * mix)850 MIX_RESULT mix_videofmtenc_h264_deinitialize(MixVideoFormatEnc *mix) {
851 
852     MixVideoFormatEnc *parent = NULL;
853     VAStatus va_status;
854 
855     LOG_V( "Begin\n");
856 
857     if (mix == NULL) {
858         LOG_E( "mix == NULL\n");
859         return MIX_RESULT_NULL_PTR;
860     }
861 
862     parent = MIX_VIDEOFORMATENC(&(mix->parent));
863     MixVideoFormatEnc_H264 *self = MIX_VIDEOFORMATENC_H264(mix);
864 
865     LOG_V( "Release frames\n");
866 
867     g_mutex_lock(parent->objectlock);
868 
869 #if 0
870     /*unref the current source surface*/
871     if (self->cur_fame != NULL)
872     {
873         mix_videoframe_unref (self->cur_fame);
874         self->cur_fame = NULL;
875     }
876 #endif
877 
878     /*unref the reconstructed surface*/
879     if (self->rec_fame != NULL)
880     {
881         mix_videoframe_unref (self->rec_fame);
882         self->rec_fame = NULL;
883     }
884 
885     /*unref the reference surface*/
886     if (self->ref_fame != NULL)
887     {
888         mix_videoframe_unref (self->ref_fame);
889         self->ref_fame = NULL;
890     }
891 
892     LOG_V( "Release surfaces\n");
893 
894     if (self->ci_shared_surfaces)
895     {
896         g_free (self->ci_shared_surfaces);
897         self->ci_shared_surfaces = NULL;
898     }
899 
900     if (self->surfaces)
901     {
902         g_free (self->surfaces);
903         self->surfaces = NULL;
904     }
905 
906     LOG_V( "vaDestroyContext\n");
907 
908     va_status = vaDestroyContext (parent->va_display, parent->va_context);
909     if (va_status != VA_STATUS_SUCCESS)
910     {
911         LOG_E(
912                 "Failed vaDestroyContext\n");
913         g_mutex_unlock(parent->objectlock);
914         return MIX_RESULT_FAIL;
915     }
916 
917     LOG_V( "vaDestroyConfig\n");
918 
919     va_status = vaDestroyConfig (parent->va_display, parent->va_config);
920     if (va_status != VA_STATUS_SUCCESS)
921     {
922         LOG_E(
923                 "Failed vaDestroyConfig\n");
924         g_mutex_unlock(parent->objectlock);
925         return MIX_RESULT_FAIL;
926     }
927 
928     parent->initialized = TRUE;
929 
930     g_mutex_unlock(parent->objectlock);
931 
932 #if 1
933     if (parent_class->deinitialize) {
934         return parent_class->deinitialize(mix);
935     }
936 #endif
937 
938     //Most stuff is cleaned up in parent_class->finalize()
939 
940     LOG_V( "end\n");
941 
942     return MIX_RESULT_SUCCESS;
943 }
944 
mix_videofmtenc_h264_send_seq_params(MixVideoFormatEnc_H264 * mix)945 MIX_RESULT mix_videofmtenc_h264_send_seq_params (MixVideoFormatEnc_H264 *mix)
946 {
947 
948     VAStatus va_status;
949     VAEncSequenceParameterBufferH264 h264_seq_param;
950 
951     MixVideoFormatEnc *parent = NULL;
952 
953     if (mix == NULL)
954         return MIX_RESULT_NULL_PTR;
955 
956     LOG_V( "Begin\n\n");
957 
958     if (MIX_IS_VIDEOFORMATENC_H264(mix))
959     {
960         parent = MIX_VIDEOFORMATENC(&(mix->parent));
961 
962         /*set up the sequence params for HW*/
963         h264_seq_param.level_idc = 30;  //TODO, hard code now
964         h264_seq_param.intra_period = parent->intra_period;
965         h264_seq_param.picture_width_in_mbs = parent->picture_width / 16;
966         h264_seq_param.picture_height_in_mbs = parent->picture_height/ 16;
967         h264_seq_param.bits_per_second = parent->bitrate;
968         h264_seq_param.frame_rate =
969 			(unsigned int) (parent->frame_rate_num + parent->frame_rate_denom /2 ) / parent->frame_rate_denom;
970         h264_seq_param.initial_qp = parent->initial_qp;
971         h264_seq_param.min_qp = parent->min_qp;
972         h264_seq_param.basic_unit_size = mix->basic_unit_size; //for rate control usage
973         h264_seq_param.intra_period = parent->intra_period;
974         //h264_seq_param.vui_flag = 248;
975         //h264_seq_param.seq_parameter_set_id = 176;
976 
977         LOG_V(
978                 "===h264 sequence params===\n");
979 
980         LOG_I( "seq_parameter_set_id = %d\n",
981                 (guint)h264_seq_param.seq_parameter_set_id);
982         LOG_I( "level_idc = %d\n",
983                 (guint)h264_seq_param.level_idc);
984         LOG_I( "intra_period = %d\n",
985                 h264_seq_param.intra_period);
986         LOG_I( "picture_width_in_mbs = %d\n",
987                 h264_seq_param.picture_width_in_mbs);
988         LOG_I( "picture_height_in_mbs = %d\n",
989                 h264_seq_param.picture_height_in_mbs);
990         LOG_I( "bitrate = %d\n",
991                 h264_seq_param.bits_per_second);
992         LOG_I( "frame_rate = %d\n",
993                 h264_seq_param.frame_rate);
994         LOG_I( "initial_qp = %d\n",
995                 h264_seq_param.initial_qp);
996         LOG_I( "min_qp = %d\n",
997                 h264_seq_param.min_qp);
998         LOG_I( "basic_unit_size = %d\n",
999                 h264_seq_param.basic_unit_size);
1000         LOG_I( "vui_flag = %d\n\n",
1001                 h264_seq_param.vui_flag);
1002 
1003         va_status = vaCreateBuffer(parent->va_display, parent->va_context,
1004                 VAEncSequenceParameterBufferType,
1005                 sizeof(h264_seq_param),
1006                 1, &h264_seq_param,
1007                 &mix->seq_param_buf);
1008         if (va_status != VA_STATUS_SUCCESS)
1009         {
1010             LOG_E(
1011                     "Failed to vaCreateBuffer\n");
1012             return MIX_RESULT_FAIL;
1013         }
1014 
1015         va_status = vaRenderPicture(parent->va_display, parent->va_context,
1016                 &mix->seq_param_buf, 1);
1017         if (va_status != VA_STATUS_SUCCESS)
1018         {
1019             LOG_E(
1020                     "Failed to vaRenderPicture\n");
1021             return MIX_RESULT_FAIL;
1022         }
1023     }
1024     else
1025     {
1026         LOG_E(
1027                 "not H264 video encode Object\n");
1028         return MIX_RESULT_FAIL;
1029     }
1030 
1031     LOG_V( "end\n");
1032 
1033     return MIX_RESULT_SUCCESS;
1034 
1035 
1036 }
1037 
mix_videofmtenc_h264_send_picture_parameter(MixVideoFormatEnc_H264 * mix)1038 MIX_RESULT mix_videofmtenc_h264_send_picture_parameter (MixVideoFormatEnc_H264 *mix)
1039 {
1040     VAStatus va_status;
1041     VAEncPictureParameterBufferH264 h264_pic_param;
1042     MixVideoFormatEnc *parent = NULL;
1043 
1044     if (mix == NULL)
1045         return MIX_RESULT_NULL_PTR;
1046 
1047     LOG_V( "Begin\n\n");
1048 
1049 #if 0 //not needed currently
1050     MixVideoConfigParamsEncH264 * params_h264
1051         = MIX_VIDEOCONFIGPARAMSENC_H264 (config_params_enc);
1052 #endif
1053 
1054     if (MIX_IS_VIDEOFORMATENC_H264(mix)) {
1055 
1056         parent = MIX_VIDEOFORMATENC(&(mix->parent));
1057 
1058         /*set picture params for HW*/
1059         h264_pic_param.reference_picture = mix->ref_fame->frame_id;
1060         h264_pic_param.reconstructed_picture = mix->rec_fame->frame_id;
1061         h264_pic_param.coded_buf = mix->coded_buf;
1062         h264_pic_param.picture_width = parent->picture_width;
1063         h264_pic_param.picture_height = parent->picture_height;
1064         h264_pic_param.last_picture = 0;
1065 
1066 
1067         LOG_V(
1068                 "======h264 picture params======\n");
1069         LOG_I( "reference_picture = 0x%08x\n",
1070                 h264_pic_param.reference_picture);
1071         LOG_I( "reconstructed_picture = 0x%08x\n",
1072                 h264_pic_param.reconstructed_picture);
1073         LOG_I( "coded_buf = 0x%08x\n",
1074                 h264_pic_param.coded_buf);
1075         LOG_I( "picture_width = %d\n",
1076                 h264_pic_param.picture_width);
1077         LOG_I( "picture_height = %d\n\n",
1078                 h264_pic_param.picture_height);
1079 
1080         va_status = vaCreateBuffer(parent->va_display, parent->va_context,
1081                 VAEncPictureParameterBufferType,
1082                 sizeof(h264_pic_param),
1083                 1,&h264_pic_param,
1084                 &mix->pic_param_buf);
1085 
1086         if (va_status != VA_STATUS_SUCCESS)
1087         {
1088             LOG_E(
1089                     "Failed to vaCreateBuffer\n");
1090             return MIX_RESULT_FAIL;
1091         }
1092 
1093 
1094         va_status = vaRenderPicture(parent->va_display, parent->va_context,
1095                 &mix->pic_param_buf, 1);
1096 
1097         if (va_status != VA_STATUS_SUCCESS)
1098         {
1099             LOG_E(
1100                     "Failed to vaRenderPicture\n");
1101             return MIX_RESULT_FAIL;
1102         }
1103     }
1104     else
1105     {
1106         LOG_E(
1107                 "not H264 video encode Object\n");
1108         return MIX_RESULT_FAIL;
1109     }
1110 
1111     LOG_V( "end\n");
1112     return MIX_RESULT_SUCCESS;
1113 
1114 }
1115 
1116 
mix_videofmtenc_h264_send_slice_parameter(MixVideoFormatEnc_H264 * mix)1117 MIX_RESULT mix_videofmtenc_h264_send_slice_parameter (MixVideoFormatEnc_H264 *mix)
1118 {
1119     VAStatus va_status;
1120 
1121     guint slice_num;
1122     guint slice_height;
1123     guint slice_index;
1124     guint slice_height_in_mb;
1125 
1126     if (mix == NULL)
1127         return MIX_RESULT_NULL_PTR;
1128 
1129     LOG_V( "Begin\n\n");
1130 
1131 
1132     MixVideoFormatEnc *parent = NULL;
1133 
1134     if (MIX_IS_VIDEOFORMATENC_H264(mix))
1135     {
1136         parent = MIX_VIDEOFORMATENC(&(mix->parent));
1137 
1138         slice_num = mix->slice_num;
1139         slice_height = parent->picture_height / slice_num;
1140 
1141         slice_height += 15;
1142         slice_height &= (~15);
1143 
1144 #if 1
1145         va_status = vaCreateBuffer (parent->va_display, parent->va_context,
1146                 VAEncSliceParameterBufferType,
1147                 sizeof(VAEncSliceParameterBuffer),
1148                 slice_num, NULL,
1149                 &mix->slice_param_buf);
1150 
1151         if (va_status != VA_STATUS_SUCCESS)
1152         {
1153             LOG_E(
1154                     "Failed to vaCreateBuffer\n");
1155             return MIX_RESULT_FAIL;
1156         }
1157 
1158         VAEncSliceParameterBuffer *slice_param, *current_slice;
1159 
1160         va_status = vaMapBuffer(parent->va_display,
1161                 mix->slice_param_buf,
1162                 (void **)&slice_param);
1163 
1164         if (va_status != VA_STATUS_SUCCESS)
1165         {
1166             LOG_E(
1167                     "Failed to vaMapBuffer\n");
1168             return MIX_RESULT_FAIL;
1169         }
1170 
1171         current_slice = slice_param;
1172 
1173 
1174         for (slice_index = 0; slice_index < slice_num; slice_index++) {
1175             current_slice = slice_param + slice_index;
1176             slice_height_in_mb =
1177                 min (slice_height, parent->picture_height
1178                         - slice_index * slice_height) / 16;
1179 
1180             // starting MB row number for this slice
1181             current_slice->start_row_number = slice_index * slice_height / 16;
1182             // slice height measured in MB
1183             current_slice->slice_height = slice_height_in_mb;
1184             current_slice->slice_flags.bits.is_intra = mix->is_intra;
1185             current_slice->slice_flags.bits.disable_deblocking_filter_idc
1186                 = mix->disable_deblocking_filter_idc;
1187 
1188             LOG_V(
1189                     "======h264 slice params======\n");
1190 
1191             LOG_I( "slice_index = %d\n",
1192                     (gint) slice_index);
1193             LOG_I( "start_row_number = %d\n",
1194                     (gint) current_slice->start_row_number);
1195             LOG_I( "slice_height_in_mb = %d\n",
1196                     (gint) current_slice->slice_height);
1197             LOG_I( "slice.is_intra = %d\n",
1198                     (gint) current_slice->slice_flags.bits.is_intra);
1199             LOG_I(
1200                     "disable_deblocking_filter_idc = %d\n\n",
1201                     (gint) mix->disable_deblocking_filter_idc);
1202 
1203         }
1204 
1205         va_status = vaUnmapBuffer(parent->va_display, mix->slice_param_buf);
1206 
1207         if (va_status != VA_STATUS_SUCCESS)
1208         {
1209             LOG_E(
1210                     "Failed to vaUnmapBuffer\n");
1211             return MIX_RESULT_FAIL;
1212         }
1213 #endif
1214 
1215 #if 0
1216             VAEncSliceParameterBuffer slice_param;
1217             slice_index = 0;
1218             slice_height_in_mb = slice_height / 16;
1219             slice_param.start_row_number = 0;
1220             slice_param.slice_height = slice_height / 16;
1221             slice_param.slice_flags.bits.is_intra = mix->is_intra;
1222             slice_param.slice_flags.bits.disable_deblocking_filter_idc
1223                 = mix->disable_deblocking_filter_idc;
1224 
1225             va_status = vaCreateBuffer (parent->va_display, parent->va_context,
1226                     VAEncSliceParameterBufferType,
1227                     sizeof(slice_param),
1228                     slice_num, &slice_param,
1229                     &mix->slice_param_buf);
1230 
1231             if (va_status != VA_STATUS_SUCCESS)
1232             {
1233                 LOG_E(
1234                         "Failed to vaCreateBuffer\n");
1235                 return MIX_RESULT_FAIL;
1236             }
1237 #endif
1238 
1239         va_status = vaRenderPicture(parent->va_display, parent->va_context,
1240                 &mix->slice_param_buf, 1);
1241 
1242         if (va_status != VA_STATUS_SUCCESS)
1243         {
1244             LOG_E(
1245                     "Failed to vaRenderPicture\n");
1246             return MIX_RESULT_FAIL;
1247         }
1248 
1249     }
1250     else
1251     {
1252         LOG_E(
1253                 "not H264 video encode Object\n");
1254         return MIX_RESULT_FAIL;
1255     }
1256 
1257     LOG_V( "end\n");
1258 
1259     return MIX_RESULT_SUCCESS;
1260 }
1261 
mix_videofmtenc_h264_process_encode(MixVideoFormatEnc_H264 * mix,MixBuffer * bufin,MixIOVec * iovout)1262 MIX_RESULT mix_videofmtenc_h264_process_encode (MixVideoFormatEnc_H264 *mix,
1263         MixBuffer * bufin, MixIOVec * iovout)
1264 {
1265 
1266     MIX_RESULT ret = MIX_RESULT_SUCCESS;
1267     VAStatus va_status = VA_STATUS_SUCCESS;
1268     VADisplay va_display = NULL;
1269     VAContextID va_context;
1270     gulong surface = 0;
1271     guint16 width, height;
1272 
1273     MixVideoFrame *  tmp_fame;
1274     guint8 *buf;
1275 
1276     if ((mix == NULL) || (bufin == NULL) || (iovout == NULL)) {
1277         LOG_E(
1278                 "mix == NUL) || bufin == NULL || iovout == NULL\n");
1279         return MIX_RESULT_NULL_PTR;
1280     }
1281 
1282     LOG_V( "Begin\n");
1283 
1284     if (MIX_IS_VIDEOFORMATENC_H264(mix))
1285     {
1286 
1287         MixVideoFormatEnc *parent = MIX_VIDEOFORMATENC(&(mix->parent));
1288 
1289         va_display = parent->va_display;
1290         va_context = parent->va_context;
1291         width = parent->picture_width;
1292         height = parent->picture_height;
1293 
1294 
1295         LOG_I( "encoded_frames = %d\n",
1296                 mix->encoded_frames);
1297         LOG_I( "is_intra = %d\n",
1298                 mix->is_intra);
1299         LOG_I( "ci_frame_id = 0x%08x\n",
1300                 (guint) parent->ci_frame_id);
1301 
1302         /* determine the picture type*/
1303         if ((mix->encoded_frames % parent->intra_period) == 0) {
1304             mix->is_intra = TRUE;
1305         } else {
1306             mix->is_intra = FALSE;
1307         }
1308 
1309         LOG_I( "is_intra_picture = %d\n",
1310                 mix->is_intra);
1311 
1312         LOG_V(
1313                 "Get Surface from the pool\n");
1314 
1315         /*current we use one surface for source data,
1316          * one for reference and one for reconstructed*/
1317         /*TODO, could be refine here*/
1318 
1319         if (!parent->share_buf_mode) {
1320             LOG_V(
1321                     "We are NOT in share buffer mode\n");
1322 
1323             if (mix->ref_fame == NULL)
1324             {
1325                 ret = mix_surfacepool_get(parent->surfacepool, &mix->ref_fame);
1326                 if (ret != MIX_RESULT_SUCCESS)  //#ifdef SLEEP_SURFACE not used
1327                 {
1328                     LOG_E(
1329                             "Failed to mix_surfacepool_get\n");
1330                     return MIX_RESULT_FAIL;
1331                 }
1332             }
1333 
1334             if (mix->rec_fame == NULL)
1335             {
1336                 ret = mix_surfacepool_get(parent->surfacepool, &mix->rec_fame);
1337                 if (ret != MIX_RESULT_SUCCESS)
1338                 {
1339                     LOG_E(
1340                             "Failed to mix_surfacepool_get\n");
1341                     return MIX_RESULT_FAIL;
1342                 }
1343             }
1344 
1345             if (parent->need_display) {
1346                 mix->cur_fame = NULL;
1347             }
1348 
1349             if (mix->cur_fame == NULL)
1350             {
1351                 ret = mix_surfacepool_get(parent->surfacepool, &mix->cur_fame);
1352                 if (ret != MIX_RESULT_SUCCESS)
1353                 {
1354                     LOG_E(
1355                             "Failed to mix_surfacepool_get\n");
1356                     return MIX_RESULT_FAIL;
1357                 }
1358             }
1359 
1360             LOG_V( "Get Surface Done\n");
1361 
1362 
1363             VAImage src_image;
1364             guint8 *pvbuf;
1365             guint8 *dst_y;
1366             guint8 *dst_uv;
1367             int i,j;
1368 
1369             LOG_V(
1370                     "map source data to surface\n");
1371 
1372             ret = mix_videoframe_get_frame_id(mix->cur_fame, &surface);
1373             if (ret != MIX_RESULT_SUCCESS)
1374             {
1375                 LOG_E(
1376                         "Failed to mix_videoframe_get_frame_id\n");
1377                 return MIX_RESULT_FAIL;
1378             }
1379 
1380 
1381             LOG_I(
1382                     "surface id = 0x%08x\n", (guint) surface);
1383 
1384             va_status = vaDeriveImage(va_display, surface, &src_image);
1385             //need to destroy
1386 
1387             if (va_status != VA_STATUS_SUCCESS)
1388             {
1389                 LOG_E(
1390                         "Failed to vaDeriveImage\n");
1391                 return MIX_RESULT_FAIL;
1392             }
1393 
1394             VAImage *image = &src_image;
1395 
1396             LOG_V( "vaDeriveImage Done\n");
1397 
1398 
1399             va_status = vaMapBuffer (va_display, image->buf, (void **)&pvbuf);
1400             if (va_status != VA_STATUS_SUCCESS)
1401             {
1402                 LOG_E( "Failed to vaMapBuffer\n");
1403                 return MIX_RESULT_FAIL;
1404             }
1405 
1406             LOG_V(
1407                     "vaImage information\n");
1408             LOG_I(
1409                     "image->pitches[0] = %d\n", image->pitches[0]);
1410             LOG_I(
1411                     "image->pitches[1] = %d\n", image->pitches[1]);
1412             LOG_I(
1413                     "image->offsets[0] = %d\n", image->offsets[0]);
1414             LOG_I(
1415                     "image->offsets[1] = %d\n", image->offsets[1]);
1416             LOG_I(
1417                     "image->num_planes = %d\n", image->num_planes);
1418             LOG_I(
1419                     "image->width = %d\n", image->width);
1420             LOG_I(
1421                     "image->height = %d\n", image->height);
1422 
1423             LOG_I(
1424                     "input buf size = %d\n", bufin->size);
1425 
1426             guint8 *inbuf = bufin->data;
1427 
1428             /*need to convert YUV420 to NV12*/
1429             dst_y = pvbuf +image->offsets[0];
1430 
1431             for (i = 0; i < height; i ++) {
1432                 memcpy (dst_y, inbuf + i * width, width);
1433                 dst_y += image->pitches[0];
1434             }
1435 
1436             dst_uv = pvbuf + image->offsets[1];
1437 
1438             for (i = 0; i < height / 2; i ++) {
1439                 for (j = 0; j < width; j+=2) {
1440                     dst_uv [j] = inbuf [width * height + i * width / 2 + j / 2];
1441                     dst_uv [j + 1] =
1442                         inbuf [width * height * 5 / 4 + i * width / 2 + j / 2];
1443                 }
1444                 dst_uv += image->pitches[1];
1445             }
1446 
1447             vaUnmapBuffer(va_display, image->buf);
1448             if (va_status != VA_STATUS_SUCCESS)
1449             {
1450                 LOG_E(
1451                         "Failed to vaUnmapBuffer\n");
1452                 return MIX_RESULT_FAIL;
1453             }
1454 
1455             va_status = vaDestroyImage(va_display, src_image.image_id);
1456             if (va_status != VA_STATUS_SUCCESS)
1457             {
1458                 LOG_E(
1459                         "Failed to vaDestroyImage\n");
1460                 return MIX_RESULT_FAIL;
1461             }
1462 
1463             LOG_V(
1464                     "Map source data to surface done\n");
1465 
1466         }
1467 
1468         else {//if (!parent->share_buf_mode)
1469 
1470             MixVideoFrame * frame = mix_videoframe_new();
1471 
1472             if (mix->ref_fame == NULL)
1473             {
1474                 ret = mix_videoframe_set_ci_frame_idx (frame, mix->surface_num - 1);
1475 
1476                 ret = mix_surfacepool_get_frame_with_ci_frameidx
1477                     (parent->surfacepool, &mix->ref_fame, frame);
1478                 if (ret != MIX_RESULT_SUCCESS)  //#ifdef SLEEP_SURFACE not used
1479                 {
1480                     LOG_E(
1481                             "get reference surface from pool failed\n");
1482                     return MIX_RESULT_FAIL;
1483                 }
1484             }
1485 
1486             if (mix->rec_fame == NULL)
1487             {
1488                 ret = mix_videoframe_set_ci_frame_idx (frame, mix->surface_num - 2);
1489 
1490                 ret = mix_surfacepool_get_frame_with_ci_frameidx
1491                     (parent->surfacepool, &mix->rec_fame, frame);
1492 
1493                 if (ret != MIX_RESULT_SUCCESS)
1494                 {
1495                     LOG_E(
1496                             "get recontructed surface from pool failed\n");
1497                     return MIX_RESULT_FAIL;
1498                 }
1499             }
1500 
1501             //mix_videoframe_unref (mix->cur_fame);
1502 
1503             if (parent->need_display) {
1504                 mix->cur_fame = NULL;
1505             }
1506 
1507             if (mix->cur_fame == NULL)
1508             {
1509                 guint ci_idx;
1510                 memcpy (&ci_idx, bufin->data, bufin->size);
1511 
1512                 LOG_I(
1513                         "surface_num = %d\n", mix->surface_num);
1514                 LOG_I(
1515                         "ci_frame_idx = %d\n", ci_idx);
1516 
1517                 if (ci_idx > mix->surface_num - 2) {
1518                     LOG_E(
1519                             "the CI frame idx is too bigger than CI frame number\n");
1520                     return MIX_RESULT_FAIL;
1521                 }
1522 
1523 
1524                 ret = mix_videoframe_set_ci_frame_idx (frame, ci_idx);
1525 
1526                 ret = mix_surfacepool_get_frame_with_ci_frameidx
1527                     (parent->surfacepool, &mix->cur_fame, frame);
1528 
1529                 if (ret != MIX_RESULT_SUCCESS)
1530                 {
1531                     LOG_E(
1532                             "get current working surface from pool failed\n");
1533                     return MIX_RESULT_FAIL;
1534                 }
1535             }
1536 
1537             ret = mix_videoframe_get_frame_id(mix->cur_fame, &surface);
1538 
1539         }
1540 
1541         LOG_V( "vaBeginPicture\n");
1542         LOG_I( "va_context = 0x%08x\n",(guint)va_context);
1543         LOG_I( "surface = 0x%08x\n",(guint)surface);
1544         LOG_I( "va_display = 0x%08x\n",(guint)va_display);
1545 
1546         va_status = vaBeginPicture(va_display, va_context, surface);
1547         if (va_status != VA_STATUS_SUCCESS)
1548         {
1549             LOG_E( "Failed vaBeginPicture\n");
1550             return MIX_RESULT_FAIL;
1551         }
1552 
1553         LOG_V( "mix_videofmtenc_h264_send_seq_params\n");
1554 
1555         if (mix->encoded_frames == 0) {
1556             mix_videofmtenc_h264_send_seq_params (mix);
1557             if (ret != MIX_RESULT_SUCCESS)
1558             {
1559                 LOG_E(
1560                         "Failed mix_videofmtenc_h264_send_seq_params\n");
1561                 return MIX_RESULT_FAIL;
1562             }
1563         }
1564 
1565         ret = mix_videofmtenc_h264_send_picture_parameter (mix);
1566 
1567         if (ret != MIX_RESULT_SUCCESS)
1568         {
1569            LOG_E(
1570                    "Failed mix_videofmtenc_h264_send_picture_parameter\n");
1571            return MIX_RESULT_FAIL;
1572         }
1573 
1574         ret = mix_videofmtenc_h264_send_slice_parameter (mix);
1575         if (ret != MIX_RESULT_SUCCESS)
1576         {
1577             LOG_E(
1578                     "Failed mix_videofmtenc_h264_send_slice_parameter\n");
1579             return MIX_RESULT_FAIL;
1580         }
1581 
1582         LOG_V( "before vaEndPicture\n");
1583 
1584         va_status = vaEndPicture (va_display, va_context);
1585         if (va_status != VA_STATUS_SUCCESS)
1586         {
1587             LOG_E( "Failed vaEndPicture\n");
1588             return MIX_RESULT_FAIL;
1589         }
1590 
1591 
1592         LOG_V( "vaSyncSurface\n");
1593 
1594         va_status = vaSyncSurface(va_display, surface);
1595         if (va_status != VA_STATUS_SUCCESS)
1596         {
1597             LOG_E( "Failed vaSyncSurface\n");
1598             return MIX_RESULT_FAIL;
1599         }
1600 
1601 
1602         LOG_V(
1603                 "Start to get encoded data\n");
1604 
1605         /*get encoded data from the VA buffer*/
1606         va_status = vaMapBuffer (va_display, mix->coded_buf, (void **)&buf);
1607         if (va_status != VA_STATUS_SUCCESS)
1608         {
1609             LOG_E( "Failed vaMapBuffer\n");
1610             return MIX_RESULT_FAIL;
1611         }
1612 
1613         // first 4 bytes is the size of the buffer
1614         memcpy (&(iovout->data_size), (void*)buf, 4);
1615         //size = (guint*) buf;
1616 
1617         guint size = iovout->data_size + 100;
1618 
1619         iovout->buffer_size = size;
1620 
1621         //We will support two buffer mode, one is application allocates the buffer and passes to encode,
1622         //the other is encode allocate memory
1623 
1624         if (iovout->data == NULL) { //means  app doesn't allocate the buffer, so _encode will allocate it.
1625             iovout->data = g_malloc (size);  // In case we have lots of 0x000001 start code, and we replace them with 4 bytes length prefixed
1626             if (iovout->data == NULL) {
1627                 return MIX_RESULT_NO_MEMORY;
1628             }
1629         }
1630 
1631         if (mix->delimiter_type == MIX_DELIMITER_ANNEXB) {
1632             memcpy (iovout->data, buf + 16, iovout->data_size); //parload is started from 17th byte
1633             size = iovout->data_size;
1634         } else {
1635 
1636             guint pos = 0;
1637             guint zero_byte_count = 0;
1638             guint prefix_length = 0;
1639             guint8 nal_unit_type = 0;
1640 	     guint8 * payload = buf + 16;
1641 
1642             while ((payload[pos++] == 0x00)) {
1643                 zero_byte_count ++;
1644                 if (pos >= iovout->data_size)  //to make sure the buffer to be accessed is valid
1645                     break;
1646             }
1647 
1648 	     nal_unit_type = (guint8)(payload[pos] & 0x1f);
1649             prefix_length = zero_byte_count + 1;
1650 
1651             LOG_I ("nal_unit_type = %d\n", nal_unit_type);
1652             LOG_I ("zero_byte_count = %d\n", zero_byte_count);
1653 
1654             if ((payload [pos - 1] & 0x01) && mix->slice_num == 1 && nal_unit_type == 1) {
1655                 size =  iovout->data_size;
1656                 iovout->data[0] = ((size - prefix_length) >> 24) & 0xff;
1657                 iovout->data[1] = ((size - prefix_length) >> 16) & 0xff;
1658                 iovout->data[2] = ((size - prefix_length) >> 8)  & 0xff;
1659                 iovout->data[3] = (size - prefix_length)   & 0xff;
1660                 // use 4 bytes to indicate the NALU length
1661                 memcpy (iovout->data + 4, buf + 16 + prefix_length, size - prefix_length);
1662                 LOG_V ("We only have one start code, copy directly\n");
1663             }
1664             else {
1665                 ret = mix_videofmtenc_h264_AnnexB_to_length_prefixed (buf + 16, iovout->data_size, iovout->data, &size);
1666                 if (ret != MIX_RESULT_SUCCESS)
1667                 {
1668                     LOG_E (
1669                             "Failed mix_videofmtenc_h264_AnnexB_to_length_prefixed\n");
1670                     return MIX_RESULT_FAIL;
1671                 }
1672             }
1673         }
1674 
1675         iovout->data_size = size;
1676         LOG_I(
1677                 "out size is = %d\n", iovout->data_size);
1678 
1679         va_status = vaUnmapBuffer (va_display, mix->coded_buf);
1680         if (va_status != VA_STATUS_SUCCESS)
1681         {
1682             LOG_E( "Failed vaUnmapBuffer\n");
1683             return MIX_RESULT_FAIL;
1684         }
1685 
1686         LOG_V( "get encoded data done\n");
1687 #if 0
1688         if (parent->drawable) {
1689             va_status = vaPutSurface(va_display, surface, (Drawable)parent->drawable,
1690                     0,0, width, height,
1691                     0,0, width, height,
1692                     NULL,0,0);
1693         }
1694 
1695 #ifdef SHOW_SRC
1696         else {
1697 
1698             va_status = vaPutSurface(va_display, surface, win,
1699                     0,0, width, height,
1700                     0,0, width, height,
1701                     NULL,0,0);
1702         }
1703 #endif //SHOW_SRC
1704 #endif
1705 
1706         VASurfaceStatus status;
1707 
1708         /*query the status of current surface*/
1709         va_status = vaQuerySurfaceStatus(va_display, surface,  &status);
1710         if (va_status != VA_STATUS_SUCCESS)
1711         {
1712             LOG_E(
1713                     "Failed vaQuerySurfaceStatus\n");
1714             return MIX_RESULT_FAIL;
1715         }
1716         mix->pic_skipped = status & VASurfaceSkipped;
1717 
1718         if (parent->need_display) {
1719             ret = mix_framemanager_enqueue(parent->framemgr, mix->cur_fame);
1720             if (ret != MIX_RESULT_SUCCESS)
1721             {
1722                 LOG_E(
1723                         "Failed mix_framemanager_enqueue\n");
1724                 return MIX_RESULT_FAIL;
1725             }
1726         }
1727 
1728 
1729         /*update the reference surface and reconstructed surface */
1730         if (!mix->pic_skipped) {
1731             tmp_fame = mix->rec_fame;
1732             mix->rec_fame= mix->ref_fame;
1733             mix->ref_fame = tmp_fame;
1734         }
1735 
1736 #if 0
1737         if (mix->ref_fame != NULL)
1738             mix_videoframe_unref (mix->ref_fame);
1739         mix->ref_fame = mix->rec_fame;
1740 
1741         mix_videoframe_unref (mix->cur_fame);
1742 #endif
1743 
1744         if (!(parent->need_display)) {
1745             mix_videoframe_unref (mix->cur_fame);
1746             mix->cur_fame = NULL;
1747         }
1748 
1749         mix->encoded_frames ++;
1750     }
1751     else
1752     {
1753         LOG_E(
1754                 "not H264 video encode Object\n");
1755         return MIX_RESULT_FAIL;
1756     }
1757 
1758 
1759     LOG_V( "end\n");
1760 
1761     return MIX_RESULT_SUCCESS;
1762 }
1763 
mix_videofmtenc_h264_get_max_encoded_buf_size(MixVideoFormatEnc * mix,guint * max_size)1764 MIX_RESULT mix_videofmtenc_h264_get_max_encoded_buf_size (
1765         MixVideoFormatEnc *mix, guint *max_size)
1766 {
1767 
1768     MixVideoFormatEnc *parent = NULL;
1769 
1770     if (mix == NULL || max_size == NULL)
1771     {
1772         LOG_E(
1773                 "mix == NULL || max_size == NULL\n");
1774             return MIX_RESULT_NULL_PTR;
1775     }
1776 
1777     parent = MIX_VIDEOFORMATENC(mix);
1778     MixVideoFormatEnc_H264 *self = MIX_VIDEOFORMATENC_H264(mix);
1779 
1780     LOG_V( "Begin\n");
1781 
1782     if (MIX_IS_VIDEOFORMATENC_H264(self)) {
1783 
1784         if (self->coded_buf_size > 0) {
1785             *max_size = self->coded_buf_size;
1786             LOG_V ("Already calculate the max encoded size, get the value directly");
1787             return MIX_RESULT_SUCCESS;
1788         }
1789 
1790         /*base on the rate control mode to calculate the defaule encoded buffer size*/
1791         if (self->va_rcmode == VA_RC_NONE) {
1792             self->coded_buf_size =
1793                 (parent->picture_width* parent->picture_height * 400) / (16 * 16);
1794             // set to value according to QP
1795         }
1796         else {
1797             self->coded_buf_size = parent->bitrate/ 4;
1798         }
1799 
1800         self->coded_buf_size =
1801             max (self->coded_buf_size ,
1802                     (parent->picture_width* parent->picture_height * 400) / (16 * 16));
1803 
1804         /*in case got a very large user input bit rate value*/
1805         self->coded_buf_size =
1806             min(self->coded_buf_size,
1807                     (parent->picture_width * parent->picture_height * 1.5 * 8));
1808         self->coded_buf_size =  (self->coded_buf_size + 15) &(~15);
1809     }
1810     else
1811     {
1812         LOG_E(
1813                 "not H264 video encode Object\n");
1814         return MIX_RESULT_FAIL;
1815     }
1816 
1817     *max_size = self->coded_buf_size;
1818 
1819     return MIX_RESULT_SUCCESS;
1820 }
1821 
mix_videofmtenc_h264_AnnexB_to_length_prefixed(guint8 * bufin,guint bufin_len,guint8 * bufout,guint * bufout_len)1822 MIX_RESULT mix_videofmtenc_h264_AnnexB_to_length_prefixed (
1823         guint8 * bufin, guint bufin_len, guint8* bufout, guint * bufout_len)
1824 {
1825 
1826     guint pos = 0;
1827     guint last_pos = 0;
1828 
1829     guint zero_byte_count = 0;
1830     guint nal_size = 0;
1831     guint prefix_length = 0;
1832     guint size_copied = 0;
1833     guint leading_zero_count = 0;
1834 
1835     if (bufin == NULL || bufout == NULL || bufout_len == NULL) {
1836 
1837         LOG_E(
1838                 "bufin == NULL || bufout == NULL || bufout_len = NULL\n");
1839         return MIX_RESULT_NULL_PTR;
1840     }
1841 
1842     if (bufin_len <= 0 || *bufout_len <= 0) {
1843         LOG_E(
1844                 "bufin_len <= 0 || *bufout_len <= 0\n");
1845         return MIX_RESULT_FAIL;
1846     }
1847 
1848     LOG_V ("Begin\n");
1849 
1850     while ((bufin[pos++] == 0x00)) {
1851         zero_byte_count ++;
1852         if (pos >= bufin_len)  //to make sure the buffer to be accessed is valid
1853             break;
1854     }
1855 
1856     if (bufin[pos - 1] != 0x01 || zero_byte_count < 2)
1857     {
1858         LOG_E("The stream is not AnnexB format \n");
1859         return MIX_RESULT_FAIL;	;  //not AnnexB, we won't process it
1860     }
1861 
1862     zero_byte_count = 0;
1863     last_pos = pos;
1864 
1865     while (pos < bufin_len) {
1866 
1867         while (bufin[pos++] == 0) {
1868             zero_byte_count ++;
1869             if (pos >= bufin_len) //to make sure the buffer to be accessed is valid
1870                 break;
1871         }
1872 
1873         if (bufin[pos - 1] == 0x01 && zero_byte_count >= 2) {
1874             if (zero_byte_count == 2) {
1875                 prefix_length = 3;
1876             }
1877             else {
1878                 prefix_length = 4;
1879                 leading_zero_count = zero_byte_count - 3;
1880             }
1881 
1882             LOG_I("leading_zero_count = %d\n", leading_zero_count);
1883 
1884             nal_size = pos - last_pos - prefix_length - leading_zero_count;
1885             if (nal_size < 0) {
1886                 LOG_E ("something wrong in the stream\n");
1887                 return MIX_RESULT_FAIL;	  //not AnnexB, we won't process it
1888             }
1889 
1890             if (*bufout_len < (size_copied + nal_size + 4)) {
1891                 LOG_E ("The length of destination buffer is too small\n");
1892                 return MIX_RESULT_FAIL;
1893             }
1894 
1895             LOG_I ("nal_size = %d\n", nal_size);
1896 
1897             /*We use 4 bytes length prefix*/
1898             bufout [size_copied] = nal_size >> 24 & 0xff;
1899             bufout [size_copied + 1] = nal_size >> 16 & 0xff;
1900             bufout [size_copied + 2] = nal_size >> 8 & 0xff;
1901             bufout [size_copied + 3] = nal_size  & 0xff;
1902 
1903             size_copied += 4;	//4 bytes length prefix
1904             memcpy (bufout + size_copied, bufin + last_pos, nal_size);
1905             size_copied += nal_size;
1906 
1907             LOG_I ("size_copied = %d\n", size_copied);
1908 
1909             zero_byte_count = 0;
1910             leading_zero_count = 0;
1911             last_pos = pos;
1912         }
1913 
1914         else if (pos == bufin_len) {
1915 
1916             LOG_V ("Last NALU in this frame\n");
1917 
1918             nal_size = pos - last_pos;
1919 
1920             if (*bufout_len < (size_copied + nal_size + 4)) {
1921                 LOG_E ("The length of destination buffer is too small\n");
1922                 return MIX_RESULT_FAIL;
1923             }
1924 
1925             /*We use 4 bytes length prefix*/
1926             bufout [size_copied] = nal_size >> 24 & 0xff;
1927             bufout [size_copied + 1] = nal_size >> 16 & 0xff;
1928             bufout [size_copied + 2] = nal_size >> 8 & 0xff;
1929             bufout [size_copied + 3] = nal_size  & 0xff;
1930 
1931             size_copied += 4;	//4 bytes length prefix
1932             memcpy (bufout + size_copied, bufin + last_pos, nal_size);
1933             size_copied += nal_size;
1934 
1935             LOG_I ("size_copied = %d\n", size_copied);
1936         }
1937 
1938         else {
1939             zero_byte_count = 0;
1940             leading_zero_count = 0;
1941         }
1942 
1943     }
1944 
1945     if (size_copied != *bufout_len) {
1946         *bufout_len = size_copied;
1947     }
1948 
1949     LOG_V ("End\n");
1950 
1951     return MIX_RESULT_SUCCESS;
1952 
1953 }
1954 
1955