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_mpeg4.h"
15 #include "mixvideoconfigparamsenc_mpeg4.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_mpeg4_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_MPEG4, mix_videoformatenc_mpeg4, MIX_TYPE_VIDEOFORMATENC);
37 
mix_videoformatenc_mpeg4_init(MixVideoFormatEnc_MPEG4 * self)38 static void mix_videoformatenc_mpeg4_init(MixVideoFormatEnc_MPEG4 * 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_mpeg4_class_init(MixVideoFormatEnc_MPEG4Class * klass)58 static void mix_videoformatenc_mpeg4_class_init(
59         MixVideoFormatEnc_MPEG4Class * 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_mpeg4_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_mpeg4_getcaps;
77     video_formatenc_class->initialize = mix_videofmtenc_mpeg4_initialize;
78     video_formatenc_class->encode = mix_videofmtenc_mpeg4_encode;
79     video_formatenc_class->flush = mix_videofmtenc_mpeg4_flush;
80     video_formatenc_class->eos = mix_videofmtenc_mpeg4_eos;
81     video_formatenc_class->deinitialize = mix_videofmtenc_mpeg4_deinitialize;
82     video_formatenc_class->getmaxencodedbufsize = mix_videofmtenc_mpeg4_get_max_encoded_buf_size;
83 }
84 
85 MixVideoFormatEnc_MPEG4 *
mix_videoformatenc_mpeg4_new(void)86 mix_videoformatenc_mpeg4_new(void) {
87     MixVideoFormatEnc_MPEG4 *ret =
88         g_object_new(MIX_TYPE_VIDEOFORMATENC_MPEG4, NULL);
89 
90     return ret;
91 }
92 
mix_videoformatenc_mpeg4_finalize(GObject * obj)93 void mix_videoformatenc_mpeg4_finalize(GObject * obj) {
94     /* clean up here. */
95 
96     /*MixVideoFormatEnc_MPEG4 *mix = MIX_VIDEOFORMATENC_MPEG4(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_MPEG4 *
mix_videoformatenc_mpeg4_ref(MixVideoFormatEnc_MPEG4 * mix)108 mix_videoformatenc_mpeg4_ref(MixVideoFormatEnc_MPEG4 * mix) {
109     return (MixVideoFormatEnc_MPEG4 *) g_object_ref(G_OBJECT(mix));
110 }
111 
112 /*MPEG-4:2 vmethods implementation */
mix_videofmtenc_mpeg4_getcaps(MixVideoFormatEnc * mix,GString * msg)113 MIX_RESULT mix_videofmtenc_mpeg4_getcaps(MixVideoFormatEnc *mix, GString *msg) {
114 
115     /* TODO: add codes for MPEG-4:2 */
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_mpeg4_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_mpeg4_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_mpeg4_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     MixVideoConfigParamsEncMPEG4 * config_params_enc_mpeg4;
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_MPEG4(mix))
187     {
188         parent = MIX_VIDEOFORMATENC(&(mix->parent));
189         MixVideoFormatEnc_MPEG4 *self = MIX_VIDEOFORMATENC_MPEG4(mix);
190 
191         if (MIX_IS_VIDEOCONFIGPARAMSENC_MPEG4 (config_params_enc)) {
192             config_params_enc_mpeg4 =
193                 MIX_VIDEOCONFIGPARAMSENC_MPEG4 (config_params_enc);
194         } else {
195             LOG_V(
196                     "mix_videofmtenc_mpeg4_initialize:  no mpeg4 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 MPEG-4:2 params\n");
204 
205         /* get properties from MPEG4 params Object, which is special to MPEG4 format*/
206 
207         ret = mix_videoconfigparamsenc_mpeg4_get_profile_level (config_params_enc_mpeg4,
208                 &self->profile_and_level_indication);
209 
210         if (ret != MIX_RESULT_SUCCESS) {
211             //TODO cleanup
212             LOG_E(
213                     "Failed to mix_videoconfigparamsenc_mpeg4_get_profile_level\n");
214             g_mutex_unlock(parent->objectlock);
215             return MIX_RESULT_FAIL;
216         }
217 
218         ret = mix_videoconfigparamsenc_mpeg4_get_fixed_vti (config_params_enc_mpeg4,
219                 &(self->fixed_vop_time_increment));
220 
221         if (ret != MIX_RESULT_SUCCESS) {
222             //TODO cleanup
223             LOG_E(
224                     "Failed to mix_videoconfigparamsenc_mpeg4_get_fixed_vti\n");
225             g_mutex_unlock(parent->objectlock);
226             return MIX_RESULT_FAIL;
227         }
228 
229         ret = mix_videoconfigparamsenc_mpeg4_get_dlk (config_params_enc_mpeg4,
230                 &(self->disable_deblocking_filter_idc));
231 
232         if (ret != MIX_RESULT_SUCCESS) {
233             //TODO cleanup
234             LOG_E(
235                     "Failed to config_params_enc_mpeg4\n");
236             g_mutex_unlock(parent->objectlock);
237             return MIX_RESULT_FAIL;
238         }
239 
240 
241         LOG_V(
242                 "======MPEG4 Encode Object properities======:\n");
243 
244         LOG_I( "self->profile_and_level_indication = %d\n",
245                 self->profile_and_level_indication);
246         LOG_I( "self->fixed_vop_time_increment = %d\n\n",
247                 self->fixed_vop_time_increment);
248 
249         LOG_V(
250                 "Get properities from params done\n");
251 
252 
253     	//display = XOpenDisplay(NULL);
254      	//va_display = vaGetDisplay (videoencobj->display);
255 
256         parent->va_display = va_display;
257 
258         LOG_V( "Get Display\n");
259         LOG_I( "Display = 0x%08x\n",
260                 (guint)va_display);
261 
262         //va_status = vaInitialize(va_display, &va_major_ver, &va_minor_ver);
263         //g_print ("vaInitialize va_status = %d\n", va_status);
264 
265 
266 #if 0
267         /* query the vender information, can ignore*/
268         va_vendor = vaQueryVendorString (va_display);
269         LOG_I( "Vendor = %s\n",
270                 va_vendor);
271 #endif
272 
273         /*get the max number for profiles/entrypoints/attribs*/
274         va_max_num_profiles = vaMaxNumProfiles(va_display);
275         LOG_I( "va_max_num_profiles = %d\n",
276                 va_max_num_profiles);
277 
278         va_max_num_entrypoints = vaMaxNumEntrypoints(va_display);
279         LOG_I( "va_max_num_entrypoints = %d\n",
280                 va_max_num_entrypoints);
281 
282         va_max_num_attribs = vaMaxNumConfigAttributes(va_display);
283         LOG_I( "va_max_num_attribs = %d\n",
284                 va_max_num_attribs);
285 
286         va_profiles = g_malloc(sizeof(VAProfile)*va_max_num_profiles);
287         va_entrypoints = g_malloc(sizeof(VAEntrypoint)*va_max_num_entrypoints);
288 
289         if (va_profiles == NULL || va_entrypoints ==NULL)
290         {
291             LOG_E(
292                     "!va_profiles || !va_entrypoints\n");
293             g_mutex_unlock(parent->objectlock);
294             return MIX_RESULT_NO_MEMORY;
295         }
296 
297         LOG_I(
298                 "va_profiles = 0x%08x\n", (guint)va_profiles);
299 
300         LOG_V( "vaQueryConfigProfiles\n");
301 
302 
303         va_status = vaQueryConfigProfiles (va_display, va_profiles, &va_num_profiles);
304 
305         if (va_status != VA_STATUS_SUCCESS)
306         {
307             LOG_E(
308                     "Failed to call vaQueryConfigProfiles\n");
309             g_free(va_profiles);
310             g_free (va_entrypoints);
311             g_mutex_unlock(parent->objectlock);
312             return MIX_RESULT_FAIL;
313         }
314 
315         LOG_V( "vaQueryConfigProfiles Done\n");
316 
317 
318 
319         /*check whether profile is supported*/
320         for(index= 0; index < va_num_profiles; index++) {
321             if(parent->va_profile == va_profiles[index])
322                 break;
323         }
324 
325         if(index == va_num_profiles)
326         {
327             LOG_E( "Profile not supported\n");
328             g_free(va_profiles);
329             g_free (va_entrypoints);
330             g_mutex_unlock(parent->objectlock);
331             return MIX_RESULT_FAIL;  //Todo, add error handling here
332         }
333 
334         LOG_V( "vaQueryConfigEntrypoints\n");
335 
336 
337         /*Check entry point*/
338         va_status = vaQueryConfigEntrypoints(va_display,
339                 parent->va_profile,
340                 va_entrypoints, &va_num_entrypoints);
341 
342         if (va_status != VA_STATUS_SUCCESS)
343         {
344             LOG_E(
345                     "Failed to call vaQueryConfigEntrypoints\n");
346             g_free(va_profiles);
347             g_free (va_entrypoints);
348             g_mutex_unlock(parent->objectlock);
349             return MIX_RESULT_FAIL;
350         }
351 
352         for (index = 0; index < va_num_entrypoints; index ++) {
353             if (va_entrypoints[index] == VAEntrypointEncSlice) {
354                 break;
355             }
356         }
357 
358         if (index == va_num_entrypoints) {
359             LOG_E( "Entrypoint not found\n");
360             g_free(va_profiles);
361             g_free (va_entrypoints);
362             g_mutex_unlock(parent->objectlock);
363             return MIX_RESULT_FAIL;  //Todo, add error handling here
364         }
365 
366 
367         /*free profiles and entrypoints*/
368         g_free(va_profiles);
369         g_free (va_entrypoints);
370 
371         va_attrib[0].type = VAConfigAttribRTFormat;
372         va_attrib[1].type = VAConfigAttribRateControl;
373 
374         LOG_V( "vaGetConfigAttributes\n");
375 
376         va_status = vaGetConfigAttributes(va_display, parent->va_profile,
377                 parent->va_entrypoint,
378                 &va_attrib[0], 2);
379 
380         if (va_status != VA_STATUS_SUCCESS)
381         {
382             LOG_E(
383                     "Failed to call vaGetConfigAttributes\n");
384             g_mutex_unlock(parent->objectlock);
385             return MIX_RESULT_FAIL;
386         }
387 
388         if ((va_attrib[0].value & parent->va_format) == 0) {
389             LOG_E( "Matched format not found\n");
390             g_mutex_unlock(parent->objectlock);
391             return MIX_RESULT_FAIL;  //Todo, add error handling here
392         }
393 
394 
395         if ((va_attrib[1].value & parent->va_rcmode) == 0) {
396             LOG_E( "RC mode not found\n");
397             g_mutex_unlock(parent->objectlock);
398             return MIX_RESULT_FAIL;  //Todo, add error handling here
399         }
400 
401         va_attrib[0].value = parent->va_format; //VA_RT_FORMAT_YUV420;
402         va_attrib[1].value = parent->va_rcmode;
403 
404         LOG_V( "======VA Configuration======\n");
405 
406         LOG_I( "profile = %d\n",
407                 parent->va_profile);
408         LOG_I( "va_entrypoint = %d\n",
409                 parent->va_entrypoint);
410         LOG_I( "va_attrib[0].type = %d\n",
411                 va_attrib[0].type);
412         LOG_I( "va_attrib[1].type = %d\n",
413                 va_attrib[1].type);
414         LOG_I( "va_attrib[0].value (Format) = %d\n",
415                 va_attrib[0].value);
416         LOG_I( "va_attrib[1].value (RC mode) = %d\n",
417                 va_attrib[1].value);
418 
419         LOG_V( "vaCreateConfig\n");
420 
421         va_status = vaCreateConfig(va_display, parent->va_profile,
422                 parent->va_entrypoint,
423                 &va_attrib[0], 2, &(parent->va_config));
424 
425         if (va_status != VA_STATUS_SUCCESS)
426         {
427             LOG_E( "Failed vaCreateConfig\n");
428             g_mutex_unlock(parent->objectlock);
429             return MIX_RESULT_FAIL;
430         }
431 
432         /*TODO: compute the surface number*/
433         int numSurfaces;
434 
435         if (parent->share_buf_mode) {
436             numSurfaces = 2;
437         }
438         else {
439             numSurfaces = 8;
440             parent->ci_frame_num = 0;
441         }
442 
443         self->surface_num = numSurfaces + parent->ci_frame_num;
444 
445         surfaces = g_malloc(sizeof(VASurfaceID)*numSurfaces);
446 
447         if (surfaces == NULL)
448         {
449             LOG_E(
450                     "Failed allocate surface\n");
451             g_mutex_unlock(parent->objectlock);
452             return MIX_RESULT_NO_MEMORY;
453         }
454 
455         LOG_V( "vaCreateSurfaces\n");
456 
457         va_status = vaCreateSurfaces(va_display, parent->picture_width,
458                 parent->picture_height, parent->va_format,
459                 numSurfaces, surfaces);
460         //TODO check vret and return fail if needed
461 
462         if (va_status != VA_STATUS_SUCCESS)
463         {
464             LOG_E(
465                     "Failed vaCreateSurfaces\n");
466             g_mutex_unlock(parent->objectlock);
467             return MIX_RESULT_FAIL;
468         }
469 
470         if (parent->share_buf_mode) {
471 
472             LOG_V(
473                     "We are in share buffer mode!\n");
474             self->ci_shared_surfaces =
475                 g_malloc(sizeof(VASurfaceID) * parent->ci_frame_num);
476 
477             if (self->ci_shared_surfaces == NULL)
478             {
479                 LOG_E(
480                         "Failed allocate shared surface\n");
481                 g_mutex_unlock(parent->objectlock);
482                 return MIX_RESULT_NO_MEMORY;
483             }
484 
485             guint index;
486             for(index = 0; index < parent->ci_frame_num; index++) {
487 
488                 LOG_I( "ci_frame_id = %lu\n",
489                         parent->ci_frame_id[index]);
490 
491                 LOG_V(
492                         "vaCreateSurfaceFromCIFrame\n");
493 
494                 va_status = vaCreateSurfaceFromCIFrame(va_display,
495                         (gulong) (parent->ci_frame_id[index]),
496                         &self->ci_shared_surfaces[index]);
497                 if (va_status != VA_STATUS_SUCCESS)
498                 {
499                     LOG_E(
500                             "Failed to vaCreateSurfaceFromCIFrame\n");
501                     g_mutex_unlock(parent->objectlock);
502                     return MIX_RESULT_FAIL;
503                 }
504             }
505 
506             LOG_V(
507                     "vaCreateSurfaceFromCIFrame Done\n");
508 
509         }// if (parent->share_buf_mode)
510 
511         self->surfaces = g_malloc(sizeof(VASurfaceID) * self->surface_num);
512 
513         if (self->surfaces == NULL)
514         {
515             LOG_E(
516                     "Failed allocate private surface\n");
517             g_free (surfaces);
518             g_mutex_unlock(parent->objectlock);
519             return MIX_RESULT_NO_MEMORY;
520         }
521 
522         if (parent->share_buf_mode) {
523             /*shared surfaces should be put in pool first,
524              * because we will get it accoring to CI index*/
525             for(index = 0; index < parent->ci_frame_num; index++)
526                 self->surfaces[index] = self->ci_shared_surfaces[index];
527         }
528 
529         for(index = 0; index < numSurfaces; index++) {
530             self->surfaces[index + parent->ci_frame_num] = surfaces[index];
531         }
532 
533         LOG_V( "assign surface Done\n");
534         LOG_I( "Created %d libva surfaces\n",
535                 numSurfaces + parent->ci_frame_num);
536 
537 #if 0  //current put this in gst
538         images = g_malloc(sizeof(VAImage)*numSurfaces);
539         if (images == NULL)
540         {
541             g_mutex_unlock(parent->objectlock);
542             return MIX_RESULT_FAIL;
543         }
544 
545         for (index = 0; index < numSurfaces; index++) {
546             //Derive an VAImage from an existing surface.
547             //The image buffer can then be mapped/unmapped for CPU access
548             va_status = vaDeriveImage(va_display, surfaces[index],
549                     &images[index]);
550         }
551 #endif
552 
553         LOG_V( "mix_surfacepool_new\n");
554 
555         parent->surfacepool = mix_surfacepool_new();
556         if (surface_pool)
557             *surface_pool = parent->surfacepool;
558         //which is useful to check before encode
559 
560         if (parent->surfacepool == NULL)
561         {
562             LOG_E(
563                     "Failed to mix_surfacepool_new\n");
564             g_free (surfaces);
565             g_mutex_unlock(parent->objectlock);
566             return MIX_RESULT_FAIL;
567         }
568 
569         LOG_V(
570                 "mix_surfacepool_initialize\n");
571 
572         ret = mix_surfacepool_initialize(parent->surfacepool,
573                 self->surfaces, parent->ci_frame_num + numSurfaces);
574 
575         switch (ret)
576         {
577             case MIX_RESULT_SUCCESS:
578                 break;
579             case MIX_RESULT_ALREADY_INIT:
580                 //TODO cleanup and/or retry
581                 g_free (surfaces);
582                 g_mutex_unlock(parent->objectlock);
583                 return MIX_RESULT_FAIL;
584             default:
585                 break;
586         }
587 
588 
589         //Initialize and save the VA context ID
590         LOG_V( "vaCreateContext\n");
591 
592         va_status = vaCreateContext(va_display, parent->va_config,
593                 parent->picture_width, parent->picture_height,
594                 VA_PROGRESSIVE, self->surfaces, parent->ci_frame_num + numSurfaces,
595                 &(parent->va_context));
596 
597         LOG_I(
598                 "Created libva context width %d, height %d\n",
599                 parent->picture_width, parent->picture_height);
600 
601         if (va_status != VA_STATUS_SUCCESS)
602         {
603             LOG_E(
604                     "Failed to vaCreateContext\n");
605             LOG_I( "va_status = %d\n",
606                     (guint)va_status);
607             g_free (surfaces);
608             g_mutex_unlock(parent->objectlock);
609             return MIX_RESULT_FAIL;
610         }
611 
612 	 guint max_size = 0;
613         ret = mix_videofmtenc_mpeg4_get_max_encoded_buf_size (parent, &max_size);
614         if (ret != MIX_RESULT_SUCCESS)
615         {
616             LOG_E(
617                     "Failed to mix_videofmtenc_mpeg4_get_max_encoded_buf_size\n");
618             g_free (surfaces);
619             g_mutex_unlock(parent->objectlock);
620             return MIX_RESULT_FAIL;
621 
622         }
623 
624         /*Create coded buffer for output*/
625         va_status = vaCreateBuffer (va_display, parent->va_context,
626                 VAEncCodedBufferType,
627                 self->coded_buf_size,  //
628                 1, NULL,
629                 &self->coded_buf);
630 
631         if (va_status != VA_STATUS_SUCCESS)
632         {
633             LOG_E(
634                     "Failed to vaCreateBuffer: VAEncCodedBufferType\n");
635             g_free (surfaces);
636             g_mutex_unlock(parent->objectlock);
637             return MIX_RESULT_FAIL;
638         }
639 
640 #ifdef SHOW_SRC
641         Display * display = XOpenDisplay (NULL);
642 
643         LOG_I( "display = 0x%08x\n",
644                 (guint) display);
645         win = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0,
646                 parent->picture_width,  parent->picture_height, 0, 0,
647                 WhitePixel(display, 0));
648         XMapWindow(display, win);
649         XSelectInput(display, win, KeyPressMask | StructureNotifyMask);
650 
651         XSync(display, False);
652         LOG_I( "va_display = 0x%08x\n",
653                 (guint) va_display);
654 
655 #endif /* SHOW_SRC */
656 
657         parent->initialized = TRUE;
658 
659         g_mutex_unlock(parent->objectlock);
660         g_free (surfaces);
661 
662     }
663     else
664     {
665         LOG_E(
666                 "not MPEG4 video encode Object\n");
667         return MIX_RESULT_FAIL;
668 
669     }
670 
671     LOG_V( "end\n");
672 
673     return MIX_RESULT_SUCCESS;
674 }
675 
mix_videofmtenc_mpeg4_encode(MixVideoFormatEnc * mix,MixBuffer * bufin[],gint bufincnt,MixIOVec * iovout[],gint iovoutcnt,MixVideoEncodeParams * encode_params)676 MIX_RESULT mix_videofmtenc_mpeg4_encode(MixVideoFormatEnc *mix, MixBuffer * bufin[],
677         gint bufincnt, MixIOVec * iovout[], gint iovoutcnt,
678         MixVideoEncodeParams * encode_params) {
679 
680     MIX_RESULT ret = MIX_RESULT_SUCCESS;
681     MixVideoFormatEnc *parent = NULL;
682 
683     LOG_V( "Begin\n");
684 
685     /*currenly only support one input and output buffer*/
686     //TODO: params i
687 
688     if (bufincnt != 1 || iovoutcnt != 1) {
689         LOG_E(
690                 "buffer count not equel to 1\n");
691         LOG_E(
692                 "maybe some exception occurs\n");
693     }
694 
695     if (mix == NULL ||bufin[0] == NULL ||  iovout[0] == NULL) {
696         LOG_E(
697                 "!mix || !bufin[0] ||!iovout[0]\n");
698         return MIX_RESULT_NULL_PTR;
699     }
700 
701     //TODO: encode_params is reserved here for future usage.
702 
703     /* TODO: decide if we need to chainup parent method.
704      *      * * if we do, the following is the code:
705      * */
706 
707 #if 0
708     if (parent_class->encode) {
709         return parent_class->encode(mix, bufin, bufincnt, iovout,
710                 iovoutcnt, encode_params);
711     }
712 #endif
713 
714     if (MIX_IS_VIDEOFORMATENC_MPEG4(mix))
715     {
716 
717         parent = MIX_VIDEOFORMATENC(&(mix->parent));
718         MixVideoFormatEnc_MPEG4 *self = MIX_VIDEOFORMATENC_MPEG4 (mix);
719 
720         LOG_V( "Locking\n");
721         g_mutex_lock(parent->objectlock);
722 
723 
724         //TODO: also we could move some encode Preparation work to here
725 
726         LOG_V(
727                 "mix_videofmtenc_mpeg4_process_encode\n");
728 
729         ret = mix_videofmtenc_mpeg4_process_encode (self,
730                 bufin[0], iovout[0]);
731         if (ret != MIX_RESULT_SUCCESS)
732         {
733             LOG_E(
734                     "Failed mix_videofmtenc_mpeg4_process_encode\n");
735             return MIX_RESULT_FAIL;
736         }
737 
738 
739         LOG_V( "UnLocking\n");
740 
741         g_mutex_unlock(parent->objectlock);
742     }
743     else
744     {
745         LOG_E(
746                 "not MPEG4 video encode Object\n");
747         return MIX_RESULT_FAIL;
748     }
749 
750     LOG_V( "end\n");
751 
752     return MIX_RESULT_SUCCESS;
753 }
754 
mix_videofmtenc_mpeg4_flush(MixVideoFormatEnc * mix)755 MIX_RESULT mix_videofmtenc_mpeg4_flush(MixVideoFormatEnc *mix) {
756 
757     //MIX_RESULT ret = MIX_RESULT_SUCCESS;
758 
759     LOG_V( "Begin\n");
760 
761     if (mix == NULL) {
762         LOG_E( "mix == NULL\n");
763         return MIX_RESULT_NULL_PTR;
764     }
765 
766 
767     /*not chain to parent flush func*/
768 #if 0
769     if (parent_class->flush) {
770         return parent_class->flush(mix, msg);
771     }
772 #endif
773 
774     MixVideoFormatEnc_MPEG4 *self = MIX_VIDEOFORMATENC_MPEG4(mix);
775 
776     g_mutex_lock(mix->objectlock);
777 
778     /*unref the current source surface*/
779     if (self->cur_fame != NULL)
780     {
781         mix_videoframe_unref (self->cur_fame);
782         self->cur_fame = NULL;
783     }
784 
785     /*unref the reconstructed surface*/
786     if (self->rec_fame != NULL)
787     {
788         mix_videoframe_unref (self->rec_fame);
789         self->rec_fame = NULL;
790     }
791 
792     /*unref the reference surface*/
793     if (self->ref_fame != NULL)
794     {
795         mix_videoframe_unref (self->ref_fame);
796         self->ref_fame = NULL;
797     }
798 
799     /*reset the properities*/
800     self->encoded_frames = 0;
801     self->pic_skipped = FALSE;
802     self->is_intra = TRUE;
803 
804     g_mutex_unlock(mix->objectlock);
805 
806     LOG_V( "end\n");
807 
808     return MIX_RESULT_SUCCESS;
809 }
810 
mix_videofmtenc_mpeg4_eos(MixVideoFormatEnc * mix)811 MIX_RESULT mix_videofmtenc_mpeg4_eos(MixVideoFormatEnc *mix) {
812 
813     /* TODO: add codes for MPEG-4:2 */
814 
815     /* TODO: decide if we need to chainup parent method.
816      * if we do, the following is the code:
817      */
818 
819     LOG_V( "\n");
820 
821     if (mix == NULL) {
822         LOG_E( "mix == NULL\n");
823         return MIX_RESULT_NULL_PTR;
824     }
825 
826     if (parent_class->eos) {
827         return parent_class->eos(mix);
828     }
829     return MIX_RESULT_SUCCESS;
830 }
831 
mix_videofmtenc_mpeg4_deinitialize(MixVideoFormatEnc * mix)832 MIX_RESULT mix_videofmtenc_mpeg4_deinitialize(MixVideoFormatEnc *mix) {
833 
834     MixVideoFormatEnc *parent = NULL;
835     VAStatus va_status;
836 
837     LOG_V( "Begin\n");
838 
839     if (mix == NULL) {
840         LOG_E( "mix == NULL\n");
841         return MIX_RESULT_NULL_PTR;
842     }
843 
844     parent = MIX_VIDEOFORMATENC(&(mix->parent));
845     MixVideoFormatEnc_MPEG4 *self = MIX_VIDEOFORMATENC_MPEG4(mix);
846 
847     LOG_V( "Release frames\n");
848 
849     g_mutex_lock(parent->objectlock);
850 
851 #if 0
852     /*unref the current source surface*/
853     if (self->cur_fame != NULL)
854     {
855         mix_videoframe_unref (self->cur_fame);
856         self->cur_fame = NULL;
857     }
858 #endif
859 
860     /*unref the reconstructed surface*/
861     if (self->rec_fame != NULL)
862     {
863         mix_videoframe_unref (self->rec_fame);
864         self->rec_fame = NULL;
865     }
866 
867     /*unref the reference surface*/
868     if (self->ref_fame != NULL)
869     {
870         mix_videoframe_unref (self->ref_fame);
871         self->ref_fame = NULL;
872     }
873 
874     LOG_V( "Release surfaces\n");
875 
876     if (self->ci_shared_surfaces)
877     {
878         g_free (self->ci_shared_surfaces);
879         self->ci_shared_surfaces = NULL;
880     }
881 
882     if (self->surfaces)
883     {
884         g_free (self->surfaces);
885         self->surfaces = NULL;
886     }
887 
888     LOG_V( "vaDestroyContext\n");
889 
890     va_status = vaDestroyContext (parent->va_display, parent->va_context);
891     if (va_status != VA_STATUS_SUCCESS)
892     {
893         LOG_E(
894                 "Failed vaDestroyContext\n");
895         g_mutex_unlock(parent->objectlock);
896         return MIX_RESULT_FAIL;
897     }
898 
899     LOG_V( "vaDestroyConfig\n");
900 
901     va_status = vaDestroyConfig (parent->va_display, parent->va_config);
902     if (va_status != VA_STATUS_SUCCESS)
903     {
904         LOG_E(
905                 "Failed vaDestroyConfig\n");
906         g_mutex_unlock(parent->objectlock);
907         return MIX_RESULT_FAIL;
908     }
909 
910     parent->initialized = TRUE;
911 
912     g_mutex_unlock(parent->objectlock);
913 
914 #if 1
915     if (parent_class->deinitialize) {
916         return parent_class->deinitialize(mix);
917     }
918 #endif
919 
920     //Most stuff is cleaned up in parent_class->finalize()
921 
922     LOG_V( "end\n");
923 
924     return MIX_RESULT_SUCCESS;
925 }
926 
mix_videofmtenc_mpeg4_send_seq_params(MixVideoFormatEnc_MPEG4 * mix)927 MIX_RESULT mix_videofmtenc_mpeg4_send_seq_params (MixVideoFormatEnc_MPEG4 *mix)
928 {
929 
930     VAStatus va_status;
931     VAEncSequenceParameterBufferMPEG4 mpeg4_seq_param;
932     VABufferID				seq_para_buf_id;
933 
934 
935     MixVideoFormatEnc *parent = NULL;
936 
937     if (mix == NULL)
938         return MIX_RESULT_NULL_PTR;
939 
940     LOG_V( "Begin\n\n");
941 
942     if (MIX_IS_VIDEOFORMATENC_MPEG4(mix))
943     {
944         parent = MIX_VIDEOFORMATENC(&(mix->parent));
945 
946         /*set up the sequence params for HW*/
947         mpeg4_seq_param.profile_and_level_indication = mix->profile_and_level_indication;  //TODO, hard code now
948         mpeg4_seq_param.video_object_layer_width= parent->picture_width;
949         mpeg4_seq_param.video_object_layer_height= parent->picture_height;
950         mpeg4_seq_param.vop_time_increment_resolution =
951 			(unsigned int) (parent->frame_rate_num + parent->frame_rate_denom /2 ) / parent->frame_rate_denom;
952         mpeg4_seq_param.fixed_vop_time_increment= mix->fixed_vop_time_increment;
953         mpeg4_seq_param.bits_per_second= parent->bitrate;
954         mpeg4_seq_param.frame_rate =
955 			(unsigned int) (parent->frame_rate_num + parent->frame_rate_denom /2 ) / parent->frame_rate_denom;
956         mpeg4_seq_param.initial_qp = parent->initial_qp;
957         mpeg4_seq_param.min_qp = parent->min_qp;
958         mpeg4_seq_param.intra_period = parent->intra_period;
959 
960 
961         //mpeg4_seq_param.fixed_vop_rate = 30;
962 
963 
964 
965         LOG_V(
966                 "===mpeg4 sequence params===\n");
967 
968         LOG_I( "profile_and_level_indication = %d\n",
969                 (guint)mpeg4_seq_param.profile_and_level_indication);
970         LOG_I( "intra_period = %d\n",
971                 mpeg4_seq_param.intra_period);
972         LOG_I( "video_object_layer_width = %d\n",
973                 mpeg4_seq_param.video_object_layer_width);
974         LOG_I( "video_object_layer_height = %d\n",
975                 mpeg4_seq_param.video_object_layer_height);
976         LOG_I( "vop_time_increment_resolution = %d\n",
977                 mpeg4_seq_param.vop_time_increment_resolution);
978         LOG_I( "fixed_vop_rate = %d\n",
979                 mpeg4_seq_param.fixed_vop_rate);
980         LOG_I( "fixed_vop_time_increment = %d\n",
981                 mpeg4_seq_param.fixed_vop_time_increment);
982         LOG_I( "bitrate = %d\n",
983                 mpeg4_seq_param.bits_per_second);
984         LOG_I( "frame_rate = %d\n",
985                 mpeg4_seq_param.frame_rate);
986         LOG_I( "initial_qp = %d\n",
987                 mpeg4_seq_param.initial_qp);
988         LOG_I( "min_qp = %d\n",
989                 mpeg4_seq_param.min_qp);
990         LOG_I( "intra_period = %d\n\n",
991                 mpeg4_seq_param.intra_period);
992 
993         va_status = vaCreateBuffer(parent->va_display, parent->va_context,
994                 VAEncSequenceParameterBufferType,
995                 sizeof(mpeg4_seq_param),
996                 1, &mpeg4_seq_param,
997                 &seq_para_buf_id);
998         if (va_status != VA_STATUS_SUCCESS)
999         {
1000             LOG_E(
1001                     "Failed to vaCreateBuffer\n");
1002             return MIX_RESULT_FAIL;
1003         }
1004 
1005         va_status = vaRenderPicture(parent->va_display, parent->va_context,
1006                 &seq_para_buf_id, 1);
1007         if (va_status != VA_STATUS_SUCCESS)
1008         {
1009             LOG_E(
1010                     "Failed to vaRenderPicture\n");
1011             LOG_I( "va_status = %d\n", va_status);
1012             return MIX_RESULT_FAIL;
1013         }
1014     }
1015     else
1016     {
1017         LOG_E(
1018                 "not MPEG4 video encode Object\n");
1019         return MIX_RESULT_FAIL;
1020     }
1021 
1022     LOG_V( "end\n");
1023 
1024     return MIX_RESULT_SUCCESS;
1025 
1026 
1027 }
1028 
mix_videofmtenc_mpeg4_send_picture_parameter(MixVideoFormatEnc_MPEG4 * mix)1029 MIX_RESULT mix_videofmtenc_mpeg4_send_picture_parameter (MixVideoFormatEnc_MPEG4 *mix)
1030 {
1031     VAStatus va_status;
1032     VAEncPictureParameterBufferMPEG4 mpeg4_pic_param;
1033     MixVideoFormatEnc *parent = NULL;
1034 
1035     if (mix == NULL)
1036         return MIX_RESULT_NULL_PTR;
1037 
1038     LOG_V( "Begin\n\n");
1039 
1040 #if 0 //not needed currently
1041     MixVideoConfigParamsEncMPEG4 * params_mpeg4
1042         = MIX_VIDEOCONFIGPARAMSENC_MPEG4 (config_params_enc);
1043 #endif
1044 
1045     if (MIX_IS_VIDEOFORMATENC_MPEG4(mix)) {
1046 
1047         parent = MIX_VIDEOFORMATENC(&(mix->parent));
1048 
1049         /*set picture params for HW*/
1050         mpeg4_pic_param.reference_picture = mix->ref_fame->frame_id;
1051         mpeg4_pic_param.reconstructed_picture = mix->rec_fame->frame_id;
1052         mpeg4_pic_param.coded_buf = mix->coded_buf;
1053         mpeg4_pic_param.picture_width = parent->picture_width;
1054         mpeg4_pic_param.picture_height = parent->picture_height;
1055         mpeg4_pic_param.vop_time_increment= mix->encoded_frames;
1056         mpeg4_pic_param.picture_type = mix->is_intra ? VAEncPictureTypeIntra : VAEncPictureTypePredictive;
1057 
1058 
1059 
1060         LOG_V(
1061                 "======mpeg4 picture params======\n");
1062         LOG_I( "reference_picture = 0x%08x\n",
1063                 mpeg4_pic_param.reference_picture);
1064         LOG_I( "reconstructed_picture = 0x%08x\n",
1065                 mpeg4_pic_param.reconstructed_picture);
1066         LOG_I( "coded_buf = 0x%08x\n",
1067                 mpeg4_pic_param.coded_buf);
1068         LOG_I( "picture_width = %d\n",
1069                 mpeg4_pic_param.picture_width);
1070         LOG_I( "picture_height = %d\n",
1071                 mpeg4_pic_param.picture_height);
1072         LOG_I( "vop_time_increment = %d\n",
1073                 mpeg4_pic_param.vop_time_increment);
1074         LOG_I( "picture_type = %d\n\n",
1075                 mpeg4_pic_param.picture_type);
1076 
1077         va_status = vaCreateBuffer(parent->va_display, parent->va_context,
1078                 VAEncPictureParameterBufferType,
1079                 sizeof(mpeg4_pic_param),
1080                 1,&mpeg4_pic_param,
1081                 &mix->pic_param_buf);
1082 
1083         if (va_status != VA_STATUS_SUCCESS)
1084         {
1085             LOG_E(
1086                     "Failed to vaCreateBuffer\n");
1087             return MIX_RESULT_FAIL;
1088         }
1089 
1090 
1091         va_status = vaRenderPicture(parent->va_display, parent->va_context,
1092                 &mix->pic_param_buf, 1);
1093 
1094         if (va_status != VA_STATUS_SUCCESS)
1095         {
1096             LOG_E(
1097                     "Failed to vaRenderPicture\n");
1098             LOG_I( "va_status = %d\n", va_status);
1099             return MIX_RESULT_FAIL;
1100         }
1101     }
1102     else
1103     {
1104         LOG_E(
1105                 "not MPEG4 video encode Object\n");
1106         return MIX_RESULT_FAIL;
1107     }
1108 
1109     LOG_V( "end\n");
1110     return MIX_RESULT_SUCCESS;
1111 
1112 }
1113 
1114 
mix_videofmtenc_mpeg4_send_slice_parameter(MixVideoFormatEnc_MPEG4 * mix)1115 MIX_RESULT mix_videofmtenc_mpeg4_send_slice_parameter (MixVideoFormatEnc_MPEG4 *mix)
1116 {
1117     VAStatus va_status;
1118 
1119     guint slice_height;
1120     guint slice_index;
1121     guint slice_height_in_mb;
1122 
1123     if (mix == NULL)
1124         return MIX_RESULT_NULL_PTR;
1125 
1126     LOG_V( "Begin\n\n");
1127 
1128 
1129     MixVideoFormatEnc *parent = NULL;
1130 
1131     if (MIX_IS_VIDEOFORMATENC_MPEG4(mix))
1132     {
1133         parent = MIX_VIDEOFORMATENC(&(mix->parent));
1134 
1135         slice_height = parent->picture_height;
1136 
1137         slice_height += 15;
1138         slice_height &= (~15);
1139 
1140         VAEncSliceParameterBuffer slice_param;
1141         slice_index = 0;
1142         slice_height_in_mb = slice_height / 16;
1143         slice_param.start_row_number = 0;
1144         slice_param.slice_height = slice_height / 16;
1145         slice_param.slice_flags.bits.is_intra = mix->is_intra;
1146         slice_param.slice_flags.bits.disable_deblocking_filter_idc
1147             = mix->disable_deblocking_filter_idc;
1148 
1149             LOG_V(
1150                     "======mpeg4 slice params======\n");
1151 
1152             LOG_I( "start_row_number = %d\n",
1153                     (gint) slice_param.start_row_number);
1154             LOG_I( "slice_height_in_mb = %d\n",
1155                     (gint) slice_param.slice_height);
1156             LOG_I( "slice.is_intra = %d\n",
1157                     (gint) slice_param.slice_flags.bits.is_intra);
1158             LOG_I(
1159                     "disable_deblocking_filter_idc = %d\n\n",
1160                     (gint) mix->disable_deblocking_filter_idc);
1161 
1162         va_status = vaCreateBuffer (parent->va_display, parent->va_context,
1163                 VAEncSliceParameterBufferType,
1164                 sizeof(VAEncSliceParameterBuffer),
1165                 1, &slice_param,
1166                 &mix->slice_param_buf);
1167 
1168         if (va_status != VA_STATUS_SUCCESS)
1169         {
1170             LOG_E(
1171                     "Failed to vaCreateBuffer\n");
1172             return MIX_RESULT_FAIL;
1173         }
1174 
1175         va_status = vaRenderPicture(parent->va_display, parent->va_context,
1176                 &mix->slice_param_buf, 1);
1177 
1178         if (va_status != VA_STATUS_SUCCESS)
1179         {
1180             LOG_E(
1181                     "Failed to vaRenderPicture\n");
1182             return MIX_RESULT_FAIL;
1183         }
1184 
1185     }
1186     else
1187     {
1188         LOG_E(
1189                 "not MPEG4 video encode Object\n");
1190         return MIX_RESULT_FAIL;
1191     }
1192 
1193     LOG_V( "end\n");
1194 
1195     return MIX_RESULT_SUCCESS;
1196 }
1197 
mix_videofmtenc_mpeg4_process_encode(MixVideoFormatEnc_MPEG4 * mix,MixBuffer * bufin,MixIOVec * iovout)1198 MIX_RESULT mix_videofmtenc_mpeg4_process_encode (MixVideoFormatEnc_MPEG4 *mix,
1199         MixBuffer * bufin, MixIOVec * iovout)
1200 {
1201 
1202     MIX_RESULT ret = MIX_RESULT_SUCCESS;
1203     VAStatus va_status = VA_STATUS_SUCCESS;
1204     VADisplay va_display = NULL;
1205     VAContextID va_context;
1206     gulong surface = 0;
1207     guint16 width, height;
1208 
1209     MixVideoFrame *  tmp_fame;
1210     guint8 *buf;
1211 
1212     if ((mix == NULL) || (bufin == NULL) || (iovout == NULL)) {
1213         LOG_E(
1214                 "mix == NUL) || bufin == NULL || iovout == NULL\n");
1215         return MIX_RESULT_NULL_PTR;
1216     }
1217 
1218     LOG_V( "Begin\n");
1219 
1220     if (MIX_IS_VIDEOFORMATENC_MPEG4(mix))
1221     {
1222 
1223         MixVideoFormatEnc *parent = MIX_VIDEOFORMATENC(&(mix->parent));
1224 
1225         va_display = parent->va_display;
1226         va_context = parent->va_context;
1227         width = parent->picture_width;
1228         height = parent->picture_height;
1229 
1230 
1231         LOG_I( "encoded_frames = %d\n",
1232                 mix->encoded_frames);
1233         LOG_I( "is_intra = %d\n",
1234                 mix->is_intra);
1235         LOG_I( "ci_frame_id = 0x%08x\n",
1236                 (guint) parent->ci_frame_id);
1237 
1238         /* determine the picture type*/
1239         if ((mix->encoded_frames % parent->intra_period) == 0) {
1240             mix->is_intra = TRUE;
1241         } else {
1242             mix->is_intra = FALSE;
1243         }
1244 
1245         LOG_I( "is_intra_picture = %d\n",
1246                 mix->is_intra);
1247 
1248         LOG_V(
1249                 "Get Surface from the pool\n");
1250 
1251         /*current we use one surface for source data,
1252          * one for reference and one for reconstructed*/
1253         /*TODO, could be refine here*/
1254 
1255         if (!parent->share_buf_mode) {
1256             LOG_V(
1257                     "We are NOT in share buffer mode\n");
1258 
1259             if (mix->ref_fame == NULL)
1260             {
1261                 ret = mix_surfacepool_get(parent->surfacepool, &mix->ref_fame);
1262                 if (ret != MIX_RESULT_SUCCESS)  //#ifdef SLEEP_SURFACE not used
1263                 {
1264                     LOG_E(
1265                             "Failed to mix_surfacepool_get\n");
1266                     return MIX_RESULT_FAIL;
1267                 }
1268             }
1269 
1270             if (mix->rec_fame == NULL)
1271             {
1272                 ret = mix_surfacepool_get(parent->surfacepool, &mix->rec_fame);
1273                 if (ret != MIX_RESULT_SUCCESS)
1274                 {
1275                     LOG_E(
1276                             "Failed to mix_surfacepool_get\n");
1277                     return MIX_RESULT_FAIL;
1278                 }
1279             }
1280 
1281             if (parent->need_display) {
1282                 mix->cur_fame = NULL;
1283             }
1284 
1285             if (mix->cur_fame == NULL)
1286             {
1287                 ret = mix_surfacepool_get(parent->surfacepool, &mix->cur_fame);
1288                 if (ret != MIX_RESULT_SUCCESS)
1289                 {
1290                     LOG_E(
1291                             "Failed to mix_surfacepool_get\n");
1292                     return MIX_RESULT_FAIL;
1293                 }
1294             }
1295 
1296             LOG_V( "Get Surface Done\n");
1297 
1298 
1299             VAImage src_image;
1300             guint8 *pvbuf;
1301             guint8 *dst_y;
1302             guint8 *dst_uv;
1303             int i,j;
1304 
1305             LOG_V(
1306                     "map source data to surface\n");
1307 
1308             ret = mix_videoframe_get_frame_id(mix->cur_fame, &surface);
1309             if (ret != MIX_RESULT_SUCCESS)
1310             {
1311                 LOG_E(
1312                         "Failed to mix_videoframe_get_frame_id\n");
1313                 return MIX_RESULT_FAIL;
1314             }
1315 
1316 
1317             LOG_I(
1318                     "surface id = 0x%08x\n", (guint) surface);
1319 
1320             va_status = vaDeriveImage(va_display, surface, &src_image);
1321             //need to destroy
1322 
1323             if (va_status != VA_STATUS_SUCCESS)
1324             {
1325                 LOG_E(
1326                         "Failed to vaDeriveImage\n");
1327                 return MIX_RESULT_FAIL;
1328             }
1329 
1330             VAImage *image = &src_image;
1331 
1332             LOG_V( "vaDeriveImage Done\n");
1333 
1334 
1335             va_status = vaMapBuffer (va_display, image->buf, (void **)&pvbuf);
1336             if (va_status != VA_STATUS_SUCCESS)
1337             {
1338                 LOG_E( "Failed to vaMapBuffer\n");
1339                 return MIX_RESULT_FAIL;
1340             }
1341 
1342             LOG_V(
1343                     "vaImage information\n");
1344             LOG_I(
1345                     "image->pitches[0] = %d\n", image->pitches[0]);
1346             LOG_I(
1347                     "image->pitches[1] = %d\n", image->pitches[1]);
1348             LOG_I(
1349                     "image->offsets[0] = %d\n", image->offsets[0]);
1350             LOG_I(
1351                     "image->offsets[1] = %d\n", image->offsets[1]);
1352             LOG_I(
1353                     "image->num_planes = %d\n", image->num_planes);
1354             LOG_I(
1355                     "image->width = %d\n", image->width);
1356             LOG_I(
1357                     "image->height = %d\n", image->height);
1358 
1359             LOG_I(
1360                     "input buf size = %d\n", bufin->size);
1361 
1362             guint8 *inbuf = bufin->data;
1363 
1364             /*need to convert YUV420 to NV12*/
1365             dst_y = pvbuf +image->offsets[0];
1366 
1367             for (i = 0; i < height; i ++) {
1368                 memcpy (dst_y, inbuf + i * width, width);
1369                 dst_y += image->pitches[0];
1370             }
1371 
1372             dst_uv = pvbuf + image->offsets[1];
1373 
1374             for (i = 0; i < height / 2; i ++) {
1375                 for (j = 0; j < width; j+=2) {
1376                     dst_uv [j] = inbuf [width * height + i * width / 2 + j / 2];
1377                     dst_uv [j + 1] =
1378                         inbuf [width * height * 5 / 4 + i * width / 2 + j / 2];
1379                 }
1380                 dst_uv += image->pitches[1];
1381             }
1382 
1383             vaUnmapBuffer(va_display, image->buf);
1384             if (va_status != VA_STATUS_SUCCESS)
1385             {
1386                 LOG_E(
1387                         "Failed to vaUnmapBuffer\n");
1388                 return MIX_RESULT_FAIL;
1389             }
1390 
1391             va_status = vaDestroyImage(va_display, src_image.image_id);
1392             if (va_status != VA_STATUS_SUCCESS)
1393             {
1394                 LOG_E(
1395                         "Failed to vaDestroyImage\n");
1396                 return MIX_RESULT_FAIL;
1397             }
1398 
1399             LOG_V(
1400                     "Map source data to surface done\n");
1401 
1402         }
1403 
1404         else {//if (!parent->share_buf_mode)
1405 
1406             MixVideoFrame * frame = mix_videoframe_new();
1407 
1408             if (mix->ref_fame == NULL)
1409             {
1410                 ret = mix_videoframe_set_ci_frame_idx (frame, mix->surface_num - 1);
1411 
1412                 ret = mix_surfacepool_get_frame_with_ci_frameidx
1413                     (parent->surfacepool, &mix->ref_fame, frame);
1414                 if (ret != MIX_RESULT_SUCCESS)  //#ifdef SLEEP_SURFACE not used
1415                 {
1416                     LOG_E(
1417                             "get reference surface from pool failed\n");
1418                     return MIX_RESULT_FAIL;
1419                 }
1420             }
1421 
1422             if (mix->rec_fame == NULL)
1423             {
1424                 ret = mix_videoframe_set_ci_frame_idx (frame, mix->surface_num - 2);
1425 
1426                 ret = mix_surfacepool_get_frame_with_ci_frameidx
1427                     (parent->surfacepool, &mix->rec_fame, frame);
1428 
1429                 if (ret != MIX_RESULT_SUCCESS)
1430                 {
1431                     LOG_E(
1432                             "get recontructed surface from pool failed\n");
1433                     return MIX_RESULT_FAIL;
1434                 }
1435             }
1436 
1437             if (parent->need_display) {
1438                 mix->cur_fame = NULL;
1439             }
1440 
1441             if (mix->cur_fame == NULL)
1442             {
1443                 guint ci_idx;
1444                 memcpy (&ci_idx, bufin->data, bufin->size);
1445 
1446                 LOG_I(
1447                         "surface_num = %d\n", mix->surface_num);
1448                 LOG_I(
1449                         "ci_frame_idx = %d\n", ci_idx);
1450 
1451                 if (ci_idx > mix->surface_num - 2) {
1452                     LOG_E(
1453                             "the CI frame idx is too bigger than CI frame number\n");
1454                     return MIX_RESULT_FAIL;
1455                 }
1456 
1457 
1458                 ret = mix_videoframe_set_ci_frame_idx (frame, ci_idx);
1459 
1460                 ret = mix_surfacepool_get_frame_with_ci_frameidx
1461                     (parent->surfacepool, &mix->cur_fame, frame);
1462 
1463                 if (ret != MIX_RESULT_SUCCESS)
1464                 {
1465                     LOG_E(
1466                             "get current working surface from pool failed\n");
1467                     return MIX_RESULT_FAIL;
1468                 }
1469             }
1470 
1471             ret = mix_videoframe_get_frame_id(mix->cur_fame, &surface);
1472 
1473         }
1474 
1475         LOG_V( "vaBeginPicture\n");
1476         LOG_I( "va_context = 0x%08x\n",(guint)va_context);
1477         LOG_I( "surface = 0x%08x\n",(guint)surface);
1478         LOG_I( "va_display = 0x%08x\n",(guint)va_display);
1479 
1480         va_status = vaBeginPicture(va_display, va_context, surface);
1481         if (va_status != VA_STATUS_SUCCESS)
1482         {
1483             LOG_E( "Failed vaBeginPicture\n");
1484             return MIX_RESULT_FAIL;
1485         }
1486 
1487         LOG_V( "mix_videofmtenc_mpeg4_send_seq_params\n");
1488 
1489         if (mix->encoded_frames == 0) {
1490             mix_videofmtenc_mpeg4_send_seq_params (mix);
1491             if (ret != MIX_RESULT_SUCCESS)
1492             {
1493                 LOG_E(
1494                         "Failed mix_videofmtenc_mpeg4_send_seq_params\n");
1495                 return MIX_RESULT_FAIL;
1496             }
1497         }
1498 
1499         ret = mix_videofmtenc_mpeg4_send_picture_parameter (mix);
1500 
1501         if (ret != MIX_RESULT_SUCCESS)
1502         {
1503            LOG_E(
1504                    "Failed mix_videofmtenc_mpeg4_send_picture_parameter\n");
1505            return MIX_RESULT_FAIL;
1506         }
1507 
1508         ret = mix_videofmtenc_mpeg4_send_slice_parameter (mix);
1509         if (ret != MIX_RESULT_SUCCESS)
1510         {
1511             LOG_E(
1512                     "Failed mix_videofmtenc_mpeg4_send_slice_parameter\n");
1513             return MIX_RESULT_FAIL;
1514         }
1515 
1516         LOG_V( "before vaEndPicture\n");
1517 
1518         va_status = vaEndPicture (va_display, va_context);
1519         if (va_status != VA_STATUS_SUCCESS)
1520         {
1521             LOG_E( "Failed vaEndPicture\n");
1522             return MIX_RESULT_FAIL;
1523         }
1524 
1525 
1526         LOG_V( "vaSyncSurface\n");
1527 
1528         va_status = vaSyncSurface(va_display, surface);
1529         if (va_status != VA_STATUS_SUCCESS)
1530         {
1531             LOG_E( "Failed vaSyncSurface\n");
1532             return MIX_RESULT_FAIL;
1533         }
1534 
1535 
1536         LOG_V(
1537                 "Start to get encoded data\n");
1538 
1539         /*get encoded data from the VA buffer*/
1540         va_status = vaMapBuffer (va_display, mix->coded_buf, (void **)&buf);
1541         if (va_status != VA_STATUS_SUCCESS)
1542         {
1543             LOG_E( "Failed vaMapBuffer\n");
1544             return MIX_RESULT_FAIL;
1545         }
1546 
1547         // first 4 bytes is the size of the buffer
1548 		memcpy (&(iovout->data_size), (void*)buf, 4);
1549         //size = (guint*) buf;
1550 
1551         if (iovout->data == NULL) { //means app doesn't allocate the buffer, so _encode will allocate it.
1552 
1553             iovout->data = g_malloc (iovout->data_size);
1554             if (iovout->data == NULL) {
1555                 return MIX_RESULT_NO_MEMORY;
1556             }
1557         }
1558 
1559         memcpy (iovout->data, buf + 16, iovout->data_size);
1560 
1561         iovout->buffer_size = iovout->data_size;
1562 
1563         LOG_I(
1564                 "out size is = %d\n", iovout->data_size);
1565 
1566         va_status = vaUnmapBuffer (va_display, mix->coded_buf);
1567         if (va_status != VA_STATUS_SUCCESS)
1568         {
1569             LOG_E( "Failed vaUnmapBuffer\n");
1570             return MIX_RESULT_FAIL;
1571         }
1572 
1573         LOG_V( "get encoded data done\n");
1574 
1575 #if 0
1576         if (parent->drawable) {
1577             va_status = vaPutSurface(va_display, surface, (Drawable)parent->drawable,
1578                     0,0, width, height,
1579                     0,0, width, height,
1580                     NULL,0,0);
1581         }
1582 
1583 #ifdef SHOW_SRC
1584         else {
1585 
1586             va_status = vaPutSurface(va_display, surface, win,
1587                     0,0, width, height,
1588                     0,0, width, height,
1589                     NULL,0,0);
1590         }
1591 #endif //SHOW_SRC
1592 #endif
1593 
1594         VASurfaceStatus status;
1595 
1596         /*query the status of current surface*/
1597         va_status = vaQuerySurfaceStatus(va_display, surface,  &status);
1598         if (va_status != VA_STATUS_SUCCESS)
1599         {
1600             LOG_E(
1601                     "Failed vaQuerySurfaceStatus\n");
1602             return MIX_RESULT_FAIL;
1603         }
1604         mix->pic_skipped = status & VASurfaceSkipped;
1605 
1606 	//ret = mix_framemanager_enqueue(parent->framemgr, mix->rec_fame);
1607 
1608        if (parent->need_display) {
1609 	ret = mix_framemanager_enqueue(parent->framemgr, mix->cur_fame);
1610         if (ret != MIX_RESULT_SUCCESS)
1611         {
1612             LOG_E(
1613                     "Failed mix_framemanager_enqueue\n");
1614             return MIX_RESULT_FAIL;
1615         }
1616         }
1617 
1618 
1619         /*update the reference surface and reconstructed surface */
1620         if (!mix->pic_skipped) {
1621             tmp_fame = mix->rec_fame;
1622             mix->rec_fame= mix->ref_fame;
1623             mix->ref_fame = tmp_fame;
1624         }
1625 
1626 
1627 #if 0
1628         if (mix->ref_fame != NULL)
1629             mix_videoframe_unref (mix->ref_fame);
1630         mix->ref_fame = mix->rec_fame;
1631 
1632         mix_videoframe_unref (mix->cur_fame);
1633 #endif
1634 
1635         if (!(parent->need_display)) {
1636             mix_videoframe_unref (mix->cur_fame);
1637             mix->cur_fame = NULL;
1638         }
1639 
1640         mix->encoded_frames ++;
1641     }
1642     else
1643     {
1644         LOG_E(
1645                 "not MPEG4 video encode Object\n");
1646         return MIX_RESULT_FAIL;
1647     }
1648 
1649 
1650     LOG_V( "end\n");
1651 
1652     return MIX_RESULT_SUCCESS;
1653 }
1654 
mix_videofmtenc_mpeg4_get_max_encoded_buf_size(MixVideoFormatEnc * mix,guint * max_size)1655 MIX_RESULT mix_videofmtenc_mpeg4_get_max_encoded_buf_size (
1656         MixVideoFormatEnc *mix, guint * max_size)
1657 {
1658 
1659     MixVideoFormatEnc *parent = NULL;
1660 
1661     if (mix == NULL)
1662     {
1663         LOG_E(
1664                 "mix == NULL\n");
1665             return MIX_RESULT_NULL_PTR;
1666     }
1667 
1668     LOG_V( "Begin\n");
1669 
1670     parent = MIX_VIDEOFORMATENC(mix);
1671     MixVideoFormatEnc_MPEG4 *self = MIX_VIDEOFORMATENC_MPEG4 (mix);
1672 
1673     if (MIX_IS_VIDEOFORMATENC_MPEG4(self)) {
1674 
1675         if (self->coded_buf_size > 0) {
1676             *max_size = self->coded_buf_size;
1677             LOG_V ("Already calculate the max encoded size, get the value directly");
1678             return MIX_RESULT_SUCCESS;
1679         }
1680 
1681         /*base on the rate control mode to calculate the defaule encoded buffer size*/
1682         if (self->va_rcmode == VA_RC_NONE) {
1683             self->coded_buf_size =
1684                 (parent->picture_width* parent->picture_height * 400) / (16 * 16);
1685             // set to value according to QP
1686         }
1687         else {
1688             self->coded_buf_size = parent->bitrate/ 4;
1689         }
1690 
1691         self->coded_buf_size =
1692             max (self->coded_buf_size ,
1693                     (parent->picture_width* parent->picture_height * 400) / (16 * 16));
1694 
1695         /*in case got a very large user input bit rate value*/
1696         self->coded_buf_size =
1697             max(self->coded_buf_size,
1698                     (parent->picture_width * parent->picture_height * 1.5 * 8));
1699         self->coded_buf_size =  (self->coded_buf_size + 15) &(~15);
1700     }
1701     else
1702     {
1703         LOG_E(
1704                 "not MPEG4 video encode Object\n");
1705         return MIX_RESULT_FAIL;
1706     }
1707 
1708     *max_size = self->coded_buf_size;
1709 
1710     LOG_V( "end\n");
1711 
1712     return MIX_RESULT_SUCCESS;
1713 }
1714