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