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 Intels 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 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 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 * 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 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 * 107 mix_videoformatenc_preview_ref(MixVideoFormatEnc_Preview * mix) { 108 return (MixVideoFormatEnc_Preview *) g_object_ref(G_OBJECT(mix)); 109 } 110 111 /*Preview vmethods implementation */ 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 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 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 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 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 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 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