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