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_preview.h"
15 #include "mixvideoconfigparamsenc_preview.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_preview_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_Preview, mix_videoformatenc_preview, MIX_TYPE_VIDEOFORMATENC);
37
mix_videoformatenc_preview_init(MixVideoFormatEnc_Preview * self)38 static void mix_videoformatenc_preview_init(MixVideoFormatEnc_Preview * 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_preview_class_init(MixVideoFormatEnc_PreviewClass * klass)58 static void mix_videoformatenc_preview_class_init(
59 MixVideoFormatEnc_PreviewClass * 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_preview_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_preview_getcaps;
77 video_formatenc_class->initialize = mix_videofmtenc_preview_initialize;
78 video_formatenc_class->encode = mix_videofmtenc_preview_encode;
79 video_formatenc_class->flush = mix_videofmtenc_preview_flush;
80 video_formatenc_class->eos = mix_videofmtenc_preview_eos;
81 video_formatenc_class->deinitialize = mix_videofmtenc_preview_deinitialize;
82 }
83
84 MixVideoFormatEnc_Preview *
mix_videoformatenc_preview_new(void)85 mix_videoformatenc_preview_new(void) {
86 MixVideoFormatEnc_Preview *ret =
87 g_object_new(MIX_TYPE_VIDEOFORMATENC_PREVIEW, NULL);
88
89 return ret;
90 }
91
mix_videoformatenc_preview_finalize(GObject * obj)92 void mix_videoformatenc_preview_finalize(GObject * obj) {
93 /* clean up here. */
94
95 /*MixVideoFormatEnc_Preview *mix = MIX_VIDEOFORMATENC_PREVIEW(obj); */
96 GObjectClass *root_class = (GObjectClass *) parent_class;
97
98 LOG_V( "\n");
99
100 /* Chain up parent */
101 if (root_class->finalize) {
102 root_class->finalize(obj);
103 }
104 }
105
106 MixVideoFormatEnc_Preview *
mix_videoformatenc_preview_ref(MixVideoFormatEnc_Preview * mix)107 mix_videoformatenc_preview_ref(MixVideoFormatEnc_Preview * mix) {
108 return (MixVideoFormatEnc_Preview *) g_object_ref(G_OBJECT(mix));
109 }
110
111 /*Preview vmethods implementation */
mix_videofmtenc_preview_getcaps(MixVideoFormatEnc * mix,GString * msg)112 MIX_RESULT mix_videofmtenc_preview_getcaps(MixVideoFormatEnc *mix, GString *msg) {
113
114 /* TODO: add codes for Preview format */
115
116 /* TODO: decide if we need to chainup parent method.
117 * if we do, the following is the code:
118 */
119
120 LOG_V( "mix_videofmtenc_preview_getcaps\n");
121
122 if (mix == NULL) {
123 LOG_E( "mix == NULL\n");
124 return MIX_RESULT_NULL_PTR;
125 }
126
127
128 if (parent_class->getcaps) {
129 return parent_class->getcaps(mix, msg);
130 }
131 return MIX_RESULT_SUCCESS;
132 }
133
mix_videofmtenc_preview_initialize(MixVideoFormatEnc * mix,MixVideoConfigParamsEnc * config_params_enc,MixFrameManager * frame_mgr,MixBufferPool * input_buf_pool,MixSurfacePool ** surface_pool,VADisplay va_display)134 MIX_RESULT mix_videofmtenc_preview_initialize(MixVideoFormatEnc *mix,
135 MixVideoConfigParamsEnc * config_params_enc,
136 MixFrameManager * frame_mgr,
137 MixBufferPool * input_buf_pool,
138 MixSurfacePool ** surface_pool,
139 VADisplay va_display ) {
140
141 MIX_RESULT ret = MIX_RESULT_SUCCESS;
142 MixVideoFormatEnc *parent = NULL;
143 MixVideoConfigParamsEncPreview * config_params_enc_preview;
144
145 VAStatus va_status = VA_STATUS_SUCCESS;
146 VASurfaceID * surfaces;
147
148 gint va_max_num_profiles, va_max_num_entrypoints, va_max_num_attribs;
149 gint va_num_profiles, va_num_entrypoints;
150
151 VAProfile *va_profiles = NULL;
152 VAEntrypoint *va_entrypoints = NULL;
153 VAConfigAttrib va_attrib[2];
154 guint index;
155
156
157 /*frame_mgr and input_buf_pool is reservered for future use*/
158
159 if (mix == NULL || config_params_enc == NULL || va_display == NULL) {
160 LOG_E(
161 "mix == NULL || config_params_enc == NULL || va_display == NULL\n");
162 return MIX_RESULT_NULL_PTR;
163 }
164
165 LOG_V( "begin\n");
166
167
168 //TODO additional parameter checking
169
170 /* Chainup parent method. */
171 #if 1
172 if (parent_class->initialize) {
173 ret = parent_class->initialize(mix, config_params_enc,
174 frame_mgr, input_buf_pool, surface_pool,
175 va_display);
176 }
177
178 if (ret != MIX_RESULT_SUCCESS)
179 {
180 return ret;
181 }
182
183 #endif //disable it currently
184
185 if (MIX_IS_VIDEOFORMATENC_PREVIEW(mix))
186 {
187 parent = MIX_VIDEOFORMATENC(&(mix->parent));
188 MixVideoFormatEnc_Preview *self = MIX_VIDEOFORMATENC_PREVIEW(mix);
189
190 if (MIX_IS_VIDEOCONFIGPARAMSENC_PREVIEW (config_params_enc)) {
191 config_params_enc_preview =
192 MIX_VIDEOCONFIGPARAMSENC_PREVIEW (config_params_enc);
193 } else {
194 LOG_V(
195 "mix_videofmtenc_preview_initialize: no preview config params found\n");
196 return MIX_RESULT_FAIL;
197 }
198
199 g_mutex_lock(parent->objectlock);
200
201
202 LOG_V(
203 "Get properities from params done\n");
204
205
206 //display = XOpenDisplay(NULL);
207 //va_display = vaGetDisplay (videoencobj->display);
208
209 parent->va_display = va_display;
210
211 LOG_V( "Get Display\n");
212 LOG_I( "Display = 0x%08x\n",
213 (guint)va_display);
214
215 //va_status = vaInitialize(va_display, &va_major_ver, &va_minor_ver);
216 //g_print ("vaInitialize va_status = %d\n", va_status);
217
218
219 #if 0
220 /* query the vender information, can ignore*/
221 va_vendor = vaQueryVendorString (va_display);
222 LOG_I( "Vendor = %s\n",
223 va_vendor);
224 #endif
225
226 /*get the max number for profiles/entrypoints/attribs*/
227 va_max_num_profiles = vaMaxNumProfiles(va_display);
228 LOG_I( "va_max_num_profiles = %d\n",
229 va_max_num_profiles);
230
231 va_max_num_entrypoints = vaMaxNumEntrypoints(va_display);
232 LOG_I( "va_max_num_entrypoints = %d\n",
233 va_max_num_entrypoints);
234
235 va_max_num_attribs = vaMaxNumConfigAttributes(va_display);
236 LOG_I( "va_max_num_attribs = %d\n",
237 va_max_num_attribs);
238
239 va_profiles = g_malloc(sizeof(VAProfile)*va_max_num_profiles);
240 va_entrypoints = g_malloc(sizeof(VAEntrypoint)*va_max_num_entrypoints);
241
242 if (va_profiles == NULL || va_entrypoints ==NULL)
243 {
244 LOG_E(
245 "!va_profiles || !va_entrypoints\n");
246 g_mutex_unlock(parent->objectlock);
247 return MIX_RESULT_NO_MEMORY;
248 }
249
250 LOG_I(
251 "va_profiles = 0x%08x\n", (guint)va_profiles);
252
253 LOG_V( "vaQueryConfigProfiles\n");
254
255
256 va_status = vaQueryConfigProfiles (va_display, va_profiles, &va_num_profiles);
257
258 if (va_status != VA_STATUS_SUCCESS)
259 {
260 LOG_E(
261 "Failed to call vaQueryConfigProfiles\n");
262 g_free(va_profiles);
263 g_free (va_entrypoints);
264 g_mutex_unlock(parent->objectlock);
265 return MIX_RESULT_FAIL;
266 }
267
268 LOG_V( "vaQueryConfigProfiles Done\n");
269
270
271
272 /*check whether profile is supported*/
273 for(index= 0; index < va_num_profiles; index++) {
274 if(parent->va_profile == va_profiles[index])
275 break;
276 }
277
278 if(index == va_num_profiles)
279 {
280 LOG_E( "Profile not supported\n");
281 g_free(va_profiles);
282 g_free (va_entrypoints);
283 g_mutex_unlock(parent->objectlock);
284 return MIX_RESULT_FAIL; //Todo, add error handling here
285 }
286
287 LOG_V( "vaQueryConfigEntrypoints\n");
288
289
290 /*Check entry point*/
291 va_status = vaQueryConfigEntrypoints(va_display,
292 parent->va_profile,
293 va_entrypoints, &va_num_entrypoints);
294
295 if (va_status != VA_STATUS_SUCCESS)
296 {
297 LOG_E(
298 "Failed to call vaQueryConfigEntrypoints\n");
299 g_free(va_profiles);
300 g_free (va_entrypoints);
301 g_mutex_unlock(parent->objectlock);
302 return MIX_RESULT_FAIL;
303 }
304
305 for (index = 0; index < va_num_entrypoints; index ++) {
306 if (va_entrypoints[index] == VAEntrypointEncSlice) {
307 break;
308 }
309 }
310
311 if (index == va_num_entrypoints) {
312 LOG_E( "Entrypoint not found\n");
313 g_free(va_profiles);
314 g_free (va_entrypoints);
315 g_mutex_unlock(parent->objectlock);
316 return MIX_RESULT_FAIL; //Todo, add error handling here
317 }
318
319
320 /*free profiles and entrypoints*/
321 g_free(va_profiles);
322 g_free (va_entrypoints);
323
324 va_attrib[0].type = VAConfigAttribRTFormat;
325 va_attrib[1].type = VAConfigAttribRateControl;
326
327 LOG_V( "vaGetConfigAttributes\n");
328
329 va_status = vaGetConfigAttributes(va_display, parent->va_profile,
330 parent->va_entrypoint,
331 &va_attrib[0], 2);
332
333 if (va_status != VA_STATUS_SUCCESS)
334 {
335 LOG_E(
336 "Failed to call vaGetConfigAttributes\n");
337 g_mutex_unlock(parent->objectlock);
338 return MIX_RESULT_FAIL;
339 }
340
341 if ((va_attrib[0].value & parent->va_format) == 0) {
342 LOG_E( "Matched format not found\n");
343 g_mutex_unlock(parent->objectlock);
344 return MIX_RESULT_FAIL; //Todo, add error handling here
345 }
346
347
348 if ((va_attrib[1].value & parent->va_rcmode) == 0) {
349 LOG_E( "RC mode not found\n");
350 g_mutex_unlock(parent->objectlock);
351 return MIX_RESULT_FAIL; //Todo, add error handling here
352 }
353
354 va_attrib[0].value = parent->va_format; //VA_RT_FORMAT_YUV420;
355 va_attrib[1].value = parent->va_rcmode;
356
357 LOG_V( "======VA Configuration======\n");
358
359 LOG_I( "profile = %d\n",
360 parent->va_profile);
361 LOG_I( "va_entrypoint = %d\n",
362 parent->va_entrypoint);
363 LOG_I( "va_attrib[0].type = %d\n",
364 va_attrib[0].type);
365 LOG_I( "va_attrib[1].type = %d\n",
366 va_attrib[1].type);
367 LOG_I( "va_attrib[0].value (Format) = %d\n",
368 va_attrib[0].value);
369 LOG_I( "va_attrib[1].value (RC mode) = %d\n",
370 va_attrib[1].value);
371
372 LOG_V( "vaCreateConfig\n");
373
374 va_status = vaCreateConfig(va_display, parent->va_profile,
375 parent->va_entrypoint,
376 &va_attrib[0], 2, &(parent->va_config));
377
378 if (va_status != VA_STATUS_SUCCESS)
379 {
380 LOG_E( "Failed vaCreateConfig\n");
381 g_mutex_unlock(parent->objectlock);
382 return MIX_RESULT_FAIL;
383 }
384
385 /*TODO: compute the surface number*/
386 int numSurfaces;
387
388 if (parent->share_buf_mode) {
389 numSurfaces = 2;
390 }
391 else {
392 numSurfaces = 8;
393 parent->ci_frame_num = 0;
394 }
395
396 self->surface_num = numSurfaces + parent->ci_frame_num;
397
398 surfaces = g_malloc(sizeof(VASurfaceID)*numSurfaces);
399
400 if (surfaces == NULL)
401 {
402 LOG_E(
403 "Failed allocate surface\n");
404 g_mutex_unlock(parent->objectlock);
405 return MIX_RESULT_NO_MEMORY;
406 }
407
408 LOG_V( "vaCreateSurfaces\n");
409
410 va_status = vaCreateSurfaces(va_display, parent->picture_width,
411 parent->picture_height, parent->va_format,
412 numSurfaces, surfaces);
413 //TODO check vret and return fail if needed
414
415 if (va_status != VA_STATUS_SUCCESS)
416 {
417 LOG_E(
418 "Failed vaCreateSurfaces\n");
419 g_mutex_unlock(parent->objectlock);
420 return MIX_RESULT_FAIL;
421 }
422
423 if (parent->share_buf_mode) {
424
425 LOG_V(
426 "We are in share buffer mode!\n");
427 self->ci_shared_surfaces =
428 g_malloc(sizeof(VASurfaceID) * parent->ci_frame_num);
429
430 if (self->ci_shared_surfaces == NULL)
431 {
432 LOG_E(
433 "Failed allocate shared surface\n");
434 g_mutex_unlock(parent->objectlock);
435 return MIX_RESULT_NO_MEMORY;
436 }
437
438 guint index;
439 for(index = 0; index < parent->ci_frame_num; index++) {
440
441 LOG_I( "ci_frame_id = %lu\n",
442 parent->ci_frame_id[index]);
443
444 LOG_V(
445 "vaCreateSurfaceFromCIFrame\n");
446
447 va_status = vaCreateSurfaceFromCIFrame(va_display,
448 (gulong) (parent->ci_frame_id[index]),
449 &self->ci_shared_surfaces[index]);
450 if (va_status != VA_STATUS_SUCCESS)
451 {
452 LOG_E(
453 "Failed to vaCreateSurfaceFromCIFrame\n");
454 g_mutex_unlock(parent->objectlock);
455 return MIX_RESULT_FAIL;
456 }
457 }
458
459 LOG_V(
460 "vaCreateSurfaceFromCIFrame Done\n");
461
462 }// if (parent->share_buf_mode)
463
464 self->surfaces = g_malloc(sizeof(VASurfaceID) * self->surface_num);
465
466 if (self->surfaces == NULL)
467 {
468 LOG_E(
469 "Failed allocate private surface\n");
470 g_free (surfaces);
471 g_mutex_unlock(parent->objectlock);
472 return MIX_RESULT_NO_MEMORY;
473 }
474
475 if (parent->share_buf_mode) {
476 /*shared surfaces should be put in pool first,
477 * because we will get it accoring to CI index*/
478 for(index = 0; index < parent->ci_frame_num; index++)
479 self->surfaces[index] = self->ci_shared_surfaces[index];
480 }
481
482 for(index = 0; index < numSurfaces; index++) {
483 self->surfaces[index + parent->ci_frame_num] = surfaces[index];
484 }
485
486 LOG_V( "assign surface Done\n");
487 LOG_I( "Created %d libva surfaces\n",
488 numSurfaces + parent->ci_frame_num);
489
490 #if 0 //current put this in gst
491 images = g_malloc(sizeof(VAImage)*numSurfaces);
492 if (images == NULL)
493 {
494 g_mutex_unlock(parent->objectlock);
495 return MIX_RESULT_FAIL;
496 }
497
498 for (index = 0; index < numSurfaces; index++) {
499 //Derive an VAImage from an existing surface.
500 //The image buffer can then be mapped/unmapped for CPU access
501 va_status = vaDeriveImage(va_display, surfaces[index],
502 &images[index]);
503 }
504 #endif
505
506 LOG_V( "mix_surfacepool_new\n");
507
508 parent->surfacepool = mix_surfacepool_new();
509 if (surface_pool)
510 *surface_pool = parent->surfacepool;
511 //which is useful to check before encode
512
513 if (parent->surfacepool == NULL)
514 {
515 LOG_E(
516 "Failed to mix_surfacepool_new\n");
517 g_free (surfaces);
518 g_mutex_unlock(parent->objectlock);
519 return MIX_RESULT_FAIL;
520 }
521
522 LOG_V(
523 "mix_surfacepool_initialize\n");
524
525 ret = mix_surfacepool_initialize(parent->surfacepool,
526 self->surfaces, parent->ci_frame_num + numSurfaces);
527
528 switch (ret)
529 {
530 case MIX_RESULT_SUCCESS:
531 break;
532 case MIX_RESULT_ALREADY_INIT:
533 //TODO cleanup and/or retry
534 g_free (surfaces);
535 g_mutex_unlock(parent->objectlock);
536 return MIX_RESULT_FAIL;
537 default:
538 break;
539 }
540
541
542 //Initialize and save the VA context ID
543 LOG_V( "vaCreateContext\n");
544
545 va_status = vaCreateContext(va_display, parent->va_config,
546 parent->picture_width, parent->picture_height,
547 0, self->surfaces, parent->ci_frame_num + numSurfaces,
548 &(parent->va_context));
549
550 LOG_I(
551 "Created libva context width %d, height %d\n",
552 parent->picture_width, parent->picture_height);
553
554 if (va_status != VA_STATUS_SUCCESS)
555 {
556 LOG_E(
557 "Failed to vaCreateContext\n");
558 LOG_I( "va_status = %d\n",
559 (guint)va_status);
560 g_free (surfaces);
561 g_mutex_unlock(parent->objectlock);
562 return MIX_RESULT_FAIL;
563 }
564
565 self->coded_buf_size = 4;
566
567 /*Create coded buffer for output*/
568 va_status = vaCreateBuffer (va_display, parent->va_context,
569 VAEncCodedBufferType,
570 self->coded_buf_size, //
571 1, NULL,
572 &self->coded_buf);
573
574 if (va_status != VA_STATUS_SUCCESS)
575 {
576 LOG_E(
577 "Failed to vaCreateBuffer: VAEncCodedBufferType\n");
578 g_free (surfaces);
579 g_mutex_unlock(parent->objectlock);
580 return MIX_RESULT_FAIL;
581 }
582
583 #ifdef SHOW_SRC
584 Display * display = XOpenDisplay (NULL);
585
586 LOG_I( "display = 0x%08x\n",
587 (guint) display);
588 win = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0,
589 parent->picture_width, parent->picture_height, 0, 0,
590 WhitePixel(display, 0));
591 XMapWindow(display, win);
592 XSelectInput(display, win, KeyPressMask | StructureNotifyMask);
593
594 XSync(display, False);
595 LOG_I( "va_display = 0x%08x\n",
596 (guint) va_display);
597
598 #endif /* SHOW_SRC */
599
600 parent->initialized = TRUE;
601
602 g_mutex_unlock(parent->objectlock);
603 g_free (surfaces);
604
605 }
606 else
607 {
608 LOG_E(
609 "not Preview video encode Object\n");
610 return MIX_RESULT_FAIL;
611
612 }
613
614 LOG_V( "end\n");
615
616 return MIX_RESULT_SUCCESS;
617 }
618
mix_videofmtenc_preview_encode(MixVideoFormatEnc * mix,MixBuffer * bufin[],gint bufincnt,MixIOVec * iovout[],gint iovoutcnt,MixVideoEncodeParams * encode_params)619 MIX_RESULT mix_videofmtenc_preview_encode(MixVideoFormatEnc *mix, MixBuffer * bufin[],
620 gint bufincnt, MixIOVec * iovout[], gint iovoutcnt,
621 MixVideoEncodeParams * encode_params) {
622
623 MIX_RESULT ret = MIX_RESULT_SUCCESS;
624 MixVideoFormatEnc *parent = NULL;
625
626 LOG_V( "Begin\n");
627
628 /*currenly only support one input and output buffer*/
629 //TODO: params i
630
631 if (bufincnt != 1 || iovoutcnt != 1) {
632 LOG_E(
633 "buffer count not equel to 1\n");
634 LOG_E(
635 "maybe some exception occurs\n");
636 }
637
638 if (mix == NULL ||bufin[0] == NULL || iovout[0] == NULL) {
639 LOG_E(
640 "!mix || !bufin[0] ||!iovout[0]\n");
641 return MIX_RESULT_NULL_PTR;
642 }
643
644 //TODO: encode_params is reserved here for future usage.
645
646 /* TODO: decide if we need to chainup parent method.
647 * * * if we do, the following is the code:
648 * */
649
650 #if 0
651 if (parent_class->encode) {
652 return parent_class->encode(mix, bufin, bufincnt, iovout,
653 iovoutcnt, encode_params);
654 }
655 #endif
656
657 if (MIX_IS_VIDEOFORMATENC_PREVIEW(mix))
658 {
659
660 parent = MIX_VIDEOFORMATENC(&(mix->parent));
661 MixVideoFormatEnc_Preview *self = MIX_VIDEOFORMATENC_PREVIEW (mix);
662
663 LOG_V( "Locking\n");
664 g_mutex_lock(parent->objectlock);
665
666
667 //TODO: also we could move some encode Preparation work to here
668
669 LOG_V(
670 "mix_videofmtenc_preview_process_encode\n");
671
672 ret = mix_videofmtenc_preview_process_encode (self,
673 bufin[0], iovout[0]);
674 if (ret != MIX_RESULT_SUCCESS)
675 {
676 LOG_E(
677 "Failed mix_videofmtenc_preview_process_encode\n");
678 return MIX_RESULT_FAIL;
679 }
680
681
682 LOG_V( "UnLocking\n");
683
684 g_mutex_unlock(parent->objectlock);
685 }
686 else
687 {
688 LOG_E(
689 "not Preview video encode Object\n");
690 return MIX_RESULT_FAIL;
691 }
692
693 LOG_V( "end\n");
694
695 return MIX_RESULT_SUCCESS;
696 }
697
mix_videofmtenc_preview_flush(MixVideoFormatEnc * mix)698 MIX_RESULT mix_videofmtenc_preview_flush(MixVideoFormatEnc *mix) {
699
700 //MIX_RESULT ret = MIX_RESULT_SUCCESS;
701
702 LOG_V( "Begin\n");
703
704 if (mix == NULL) {
705 LOG_E( "mix == NULL\n");
706 return MIX_RESULT_NULL_PTR;
707 }
708
709
710 /*not chain to parent flush func*/
711 #if 0
712 if (parent_class->flush) {
713 return parent_class->flush(mix, msg);
714 }
715 #endif
716
717 MixVideoFormatEnc_Preview *self = MIX_VIDEOFORMATENC_PREVIEW(mix);
718
719 g_mutex_lock(mix->objectlock);
720
721 #if 0
722 /*unref the current source surface*/
723 if (self->cur_fame != NULL)
724 {
725 mix_videoframe_unref (self->cur_fame);
726 self->cur_fame = NULL;
727 }
728 #endif
729
730 /*unref the reconstructed surface*/
731 if (self->rec_fame != NULL)
732 {
733 mix_videoframe_unref (self->rec_fame);
734 self->rec_fame = NULL;
735 }
736
737 /*unref the reference surface*/
738 if (self->ref_fame != NULL)
739 {
740 mix_videoframe_unref (self->ref_fame);
741 self->ref_fame = NULL;
742 }
743
744 /*reset the properities*/
745 self->encoded_frames = 0;
746 self->pic_skipped = FALSE;
747 self->is_intra = TRUE;
748
749 g_mutex_unlock(mix->objectlock);
750
751 LOG_V( "end\n");
752
753 return MIX_RESULT_SUCCESS;
754 }
755
mix_videofmtenc_preview_eos(MixVideoFormatEnc * mix)756 MIX_RESULT mix_videofmtenc_preview_eos(MixVideoFormatEnc *mix) {
757
758 /* TODO: add codes for preview */
759
760 /* TODO: decide if we need to chainup parent method.
761 * if we do, the following is the code:
762 */
763
764 LOG_V( "\n");
765
766 if (mix == NULL) {
767 LOG_E( "mix == NULL\n");
768 return MIX_RESULT_NULL_PTR;
769 }
770
771 if (parent_class->eos) {
772 return parent_class->eos(mix);
773 }
774 return MIX_RESULT_SUCCESS;
775 }
776
mix_videofmtenc_preview_deinitialize(MixVideoFormatEnc * mix)777 MIX_RESULT mix_videofmtenc_preview_deinitialize(MixVideoFormatEnc *mix) {
778
779 MixVideoFormatEnc *parent = NULL;
780 VAStatus va_status;
781
782 LOG_V( "Begin\n");
783
784 if (mix == NULL) {
785 LOG_E( "mix == NULL\n");
786 return MIX_RESULT_NULL_PTR;
787 }
788
789 parent = MIX_VIDEOFORMATENC(&(mix->parent));
790 MixVideoFormatEnc_Preview *self = MIX_VIDEOFORMATENC_PREVIEW(mix);
791
792 LOG_V( "Release frames\n");
793
794 g_mutex_lock(parent->objectlock);
795
796 #if 0
797 /*unref the current source surface*/
798 if (self->cur_fame != NULL)
799 {
800 mix_videoframe_unref (self->cur_fame);
801 self->cur_fame = NULL;
802 }
803 #endif
804
805 /*unref the reconstructed surface*/
806 if (self->rec_fame != NULL)
807 {
808 mix_videoframe_unref (self->rec_fame);
809 self->rec_fame = NULL;
810 }
811
812 /*unref the reference surface*/
813 if (self->ref_fame != NULL)
814 {
815 mix_videoframe_unref (self->ref_fame);
816 self->ref_fame = NULL;
817 }
818
819 LOG_V( "Release surfaces\n");
820
821 if (self->ci_shared_surfaces)
822 {
823 g_free (self->ci_shared_surfaces);
824 self->ci_shared_surfaces = NULL;
825 }
826
827 if (self->surfaces)
828 {
829 g_free (self->surfaces);
830 self->surfaces = NULL;
831 }
832
833 LOG_V( "vaDestroyContext\n");
834
835 va_status = vaDestroyContext (parent->va_display, parent->va_context);
836 if (va_status != VA_STATUS_SUCCESS)
837 {
838 LOG_E(
839 "Failed vaDestroyContext\n");
840 g_mutex_unlock(parent->objectlock);
841 return MIX_RESULT_FAIL;
842 }
843
844 LOG_V( "vaDestroyConfig\n");
845
846 va_status = vaDestroyConfig (parent->va_display, parent->va_config);
847 if (va_status != VA_STATUS_SUCCESS)
848 {
849 LOG_E(
850 "Failed vaDestroyConfig\n");
851 g_mutex_unlock(parent->objectlock);
852 return MIX_RESULT_FAIL;
853 }
854
855 parent->initialized = TRUE;
856
857 g_mutex_unlock(parent->objectlock);
858
859 #if 1
860 if (parent_class->deinitialize) {
861 return parent_class->deinitialize(mix);
862 }
863 #endif
864
865 //Most stuff is cleaned up in parent_class->finalize()
866
867 LOG_V( "end\n");
868
869 return MIX_RESULT_SUCCESS;
870 }
871
872
mix_videofmtenc_preview_process_encode(MixVideoFormatEnc_Preview * mix,MixBuffer * bufin,MixIOVec * iovout)873 MIX_RESULT mix_videofmtenc_preview_process_encode (MixVideoFormatEnc_Preview *mix,
874 MixBuffer * bufin, MixIOVec * iovout)
875 {
876
877 MIX_RESULT ret = MIX_RESULT_SUCCESS;
878 VAStatus va_status = VA_STATUS_SUCCESS;
879 VADisplay va_display = NULL;
880 VAContextID va_context;
881 gulong surface = 0;
882 guint16 width, height;
883
884 //MixVideoFrame * tmp_fame;
885 //guint8 *buf;
886
887 if ((mix == NULL) || (bufin == NULL) || (iovout == NULL)) {
888 LOG_E(
889 "mix == NUL) || bufin == NULL || iovout == NULL\n");
890 return MIX_RESULT_NULL_PTR;
891 }
892
893 LOG_V( "Begin\n");
894
895 if (MIX_IS_VIDEOFORMATENC_PREVIEW(mix))
896 {
897
898 MixVideoFormatEnc *parent = MIX_VIDEOFORMATENC(&(mix->parent));
899
900 va_display = parent->va_display;
901 va_context = parent->va_context;
902 width = parent->picture_width;
903 height = parent->picture_height;
904
905
906 LOG_I( "encoded_frames = %d\n",
907 mix->encoded_frames);
908 LOG_I( "is_intra = %d\n",
909 mix->is_intra);
910 LOG_I( "ci_frame_id = 0x%08x\n",
911 (guint) parent->ci_frame_id);
912
913 LOG_V(
914 "Get Surface from the pool\n");
915
916 /*current we use one surface for source data,
917 * one for reference and one for reconstructed*/
918 /*TODO, could be refine here*/
919
920 if (!parent->share_buf_mode) {
921 LOG_V(
922 "We are NOT in share buffer mode\n");
923
924 if (mix->ref_fame == NULL)
925 {
926 ret = mix_surfacepool_get(parent->surfacepool, &mix->ref_fame);
927 if (ret != MIX_RESULT_SUCCESS) //#ifdef SLEEP_SURFACE not used
928 {
929 LOG_E(
930 "Failed to mix_surfacepool_get\n");
931 return MIX_RESULT_FAIL;
932 }
933 }
934
935 if (mix->rec_fame == NULL)
936 {
937 ret = mix_surfacepool_get(parent->surfacepool, &mix->rec_fame);
938 if (ret != MIX_RESULT_SUCCESS)
939 {
940 LOG_E(
941 "Failed to mix_surfacepool_get\n");
942 return MIX_RESULT_FAIL;
943 }
944 }
945
946 if (parent->need_display) {
947 mix->cur_fame = NULL;
948 }
949
950 if (mix->cur_fame == NULL)
951 {
952 ret = mix_surfacepool_get(parent->surfacepool, &mix->cur_fame);
953 if (ret != MIX_RESULT_SUCCESS)
954 {
955 LOG_E(
956 "Failed to mix_surfacepool_get\n");
957 return MIX_RESULT_FAIL;
958 }
959 }
960
961 LOG_V( "Get Surface Done\n");
962
963
964 VAImage src_image;
965 guint8 *pvbuf;
966 guint8 *dst_y;
967 guint8 *dst_uv;
968 int i,j;
969
970 LOG_V(
971 "map source data to surface\n");
972
973 ret = mix_videoframe_get_frame_id(mix->cur_fame, &surface);
974 if (ret != MIX_RESULT_SUCCESS)
975 {
976 LOG_E(
977 "Failed to mix_videoframe_get_frame_id\n");
978 return MIX_RESULT_FAIL;
979 }
980
981
982 LOG_I(
983 "surface id = 0x%08x\n", (guint) surface);
984
985 va_status = vaDeriveImage(va_display, surface, &src_image);
986 //need to destroy
987
988 if (va_status != VA_STATUS_SUCCESS)
989 {
990 LOG_E(
991 "Failed to vaDeriveImage\n");
992 return MIX_RESULT_FAIL;
993 }
994
995 VAImage *image = &src_image;
996
997 LOG_V( "vaDeriveImage Done\n");
998
999
1000 va_status = vaMapBuffer (va_display, image->buf, (void **)&pvbuf);
1001 if (va_status != VA_STATUS_SUCCESS)
1002 {
1003 LOG_E( "Failed to vaMapBuffer\n");
1004 return MIX_RESULT_FAIL;
1005 }
1006
1007 LOG_V(
1008 "vaImage information\n");
1009 LOG_I(
1010 "image->pitches[0] = %d\n", image->pitches[0]);
1011 LOG_I(
1012 "image->pitches[1] = %d\n", image->pitches[1]);
1013 LOG_I(
1014 "image->offsets[0] = %d\n", image->offsets[0]);
1015 LOG_I(
1016 "image->offsets[1] = %d\n", image->offsets[1]);
1017 LOG_I(
1018 "image->num_planes = %d\n", image->num_planes);
1019 LOG_I(
1020 "image->width = %d\n", image->width);
1021 LOG_I(
1022 "image->height = %d\n", image->height);
1023
1024 LOG_I(
1025 "input buf size = %d\n", bufin->size);
1026
1027 guint8 *inbuf = bufin->data;
1028
1029 /*need to convert YUV420 to NV12*/
1030 dst_y = pvbuf +image->offsets[0];
1031
1032 for (i = 0; i < height; i ++) {
1033 memcpy (dst_y, inbuf + i * width, width);
1034 dst_y += image->pitches[0];
1035 }
1036
1037 dst_uv = pvbuf + image->offsets[1];
1038
1039 for (i = 0; i < height / 2; i ++) {
1040 for (j = 0; j < width; j+=2) {
1041 dst_uv [j] = inbuf [width * height + i * width / 2 + j / 2];
1042 dst_uv [j + 1] =
1043 inbuf [width * height * 5 / 4 + i * width / 2 + j / 2];
1044 }
1045 dst_uv += image->pitches[1];
1046 }
1047
1048 vaUnmapBuffer(va_display, image->buf);
1049 if (va_status != VA_STATUS_SUCCESS)
1050 {
1051 LOG_E(
1052 "Failed to vaUnmapBuffer\n");
1053 return MIX_RESULT_FAIL;
1054 }
1055
1056 va_status = vaDestroyImage(va_display, src_image.image_id);
1057 if (va_status != VA_STATUS_SUCCESS)
1058 {
1059 LOG_E(
1060 "Failed to vaDestroyImage\n");
1061 return MIX_RESULT_FAIL;
1062 }
1063
1064 LOG_V(
1065 "Map source data to surface done\n");
1066
1067 }
1068
1069 else {//if (!parent->share_buf_mode)
1070
1071 MixVideoFrame * frame = mix_videoframe_new();
1072
1073 if (mix->ref_fame == NULL)
1074 {
1075 ret = mix_videoframe_set_ci_frame_idx (frame, mix->surface_num - 1);
1076
1077 ret = mix_surfacepool_get_frame_with_ci_frameidx
1078 (parent->surfacepool, &mix->ref_fame, frame);
1079 if (ret != MIX_RESULT_SUCCESS) //#ifdef SLEEP_SURFACE not used
1080 {
1081 LOG_E(
1082 "get reference surface from pool failed\n");
1083 return MIX_RESULT_FAIL;
1084 }
1085 }
1086
1087 if (mix->rec_fame == NULL)
1088 {
1089 ret = mix_videoframe_set_ci_frame_idx (frame, mix->surface_num - 2);
1090
1091 ret = mix_surfacepool_get_frame_with_ci_frameidx
1092 (parent->surfacepool, &mix->rec_fame, frame);
1093
1094 if (ret != MIX_RESULT_SUCCESS)
1095 {
1096 LOG_E(
1097 "get recontructed surface from pool failed\n");
1098 return MIX_RESULT_FAIL;
1099 }
1100 }
1101
1102 //mix_videoframe_unref (mix->cur_fame);
1103
1104 if (parent->need_display) {
1105 mix->cur_fame = NULL;
1106 }
1107
1108 if (mix->cur_fame == NULL)
1109 {
1110 guint ci_idx;
1111 memcpy (&ci_idx, bufin->data, bufin->size);
1112
1113 LOG_I(
1114 "surface_num = %d\n", mix->surface_num);
1115 LOG_I(
1116 "ci_frame_idx = %d\n", ci_idx);
1117
1118 if (ci_idx > mix->surface_num - 2) {
1119 LOG_E(
1120 "the CI frame idx is too bigger than CI frame number\n");
1121 return MIX_RESULT_FAIL;
1122 }
1123
1124
1125 ret = mix_videoframe_set_ci_frame_idx (frame, ci_idx);
1126
1127 ret = mix_surfacepool_get_frame_with_ci_frameidx
1128 (parent->surfacepool, &mix->cur_fame, frame);
1129
1130 if (ret != MIX_RESULT_SUCCESS)
1131 {
1132 LOG_E(
1133 "get current working surface from pool failed\n");
1134 return MIX_RESULT_FAIL;
1135 }
1136 }
1137
1138 ret = mix_videoframe_get_frame_id(mix->cur_fame, &surface);
1139
1140 }
1141
1142 LOG_V( "vaBeginPicture\n");
1143 LOG_I( "va_context = 0x%08x\n",(guint)va_context);
1144 LOG_I( "surface = 0x%08x\n",(guint)surface);
1145 LOG_I( "va_display = 0x%08x\n",(guint)va_display);
1146
1147 iovout->data_size = 4;
1148 iovout->data = g_malloc (iovout->data_size);
1149 if (iovout->data == NULL) {
1150 return MIX_RESULT_NO_MEMORY;
1151 }
1152
1153 memset (iovout->data, 0, iovout->data_size);
1154
1155 iovout->buffer_size = iovout->data_size;
1156
1157
1158 if (parent->need_display) {
1159 ret = mix_framemanager_enqueue(parent->framemgr, mix->cur_fame);
1160 if (ret != MIX_RESULT_SUCCESS)
1161 {
1162 LOG_E(
1163 "Failed mix_framemanager_enqueue\n");
1164 return MIX_RESULT_FAIL;
1165 }
1166 }
1167
1168
1169 if (!(parent->need_display)) {
1170 mix_videoframe_unref (mix->cur_fame);
1171 mix->cur_fame = NULL;
1172 }
1173
1174 mix->encoded_frames ++;
1175 }
1176 else
1177 {
1178 LOG_E(
1179 "not Preview video encode Object\n");
1180 return MIX_RESULT_FAIL;
1181 }
1182
1183
1184 LOG_V( "end\n");
1185
1186 return MIX_RESULT_SUCCESS;
1187 }
1188