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_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 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 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 * 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 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 * 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 */ 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 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 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 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 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 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 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 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 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 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 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