1 /*-------------------------------------------------------------------------- 2 Copyright (c) 2010-2011, 2013, The Linux Foundation. All rights reserved. 3 4 Redistribution and use in source and binary forms, with or without 5 modification, are permitted provided that the following conditions are met: 6 * Redistributions of source code must retain the above copyright 7 notice, this list of conditions and the following disclaimer. 8 * Redistributions in binary form must reproduce the above copyright 9 notice, this list of conditions and the following disclaimer in the 10 documentation and/or other materials provided with the distribution. 11 * Neither the name of The Linux Foundation nor 12 the names of its contributors may be used to endorse or promote 13 products derived from this software without specific prior written 14 permission. 15 16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 --------------------------------------------------------------------------*/ 28 #include "video_encoder_test.h" 29 30 #define DEBUG_PRINT printf 31 /************************************************************************/ 32 /* #DEFINES */ 33 /************************************************************************/ 34 35 #define VOP_START_CODE 0x000001B6 36 #define SHORT_HEADER_START_CODE 0x00008000 37 #define H264_START_CODE 0x00000001 38 39 /************************************************************************/ 40 /* STATIC VARIABLES */ 41 /************************************************************************/ 42 43 static int Code_type; 44 static int total_frames = 0; 45 static unsigned int header_code = 0; 46 static pthread_mutex_t read_lock; 47 48 static unsigned int read_frame ( unsigned char *dataptr,unsigned int length, 49 FILE * inputBufferFile 50 ); 51 static unsigned clp2(unsigned x) 52 { 53 x = x - 1; 54 x = x | (x >> 1); 55 x = x | (x >> 2); 56 x = x | (x >> 4); 57 x = x | (x >> 8); 58 x = x | (x >>16); 59 return x + 1; 60 } 61 62 63 static void* video_thread (void *); 64 static void* async_thread (void *); 65 66 67 68 int main (int argc, char **argv) 69 { 70 struct video_encoder_context *encoder_context = NULL; 71 char *file_name = NULL; 72 FILE *file_ptr = NULL; 73 int temp1 =0,temp2 =0; 74 int error = 1; 75 unsigned int i = 0; 76 77 file_name = argv [1]; 78 file_ptr = fopen (file_name,"rb"); 79 80 if (file_ptr == NULL) { 81 DEBUG_PRINT("\n File is not located "); 82 return -1; 83 } 84 85 86 encoder_context = (struct video_encoder_context *) \ 87 calloc (sizeof (struct video_encoder_context),1); 88 89 if (encoder_context == NULL) { 90 return -1; 91 } 92 93 encoder_context->outputBufferFile = NULL; 94 encoder_context->inputBufferFile = NULL; 95 encoder_context->video_driver_fd = -1; 96 encoder_context->inputBufferFile = file_ptr; 97 encoder_context->input_width = 176; 98 encoder_context->input_height = 144; 99 encoder_context->codectype = VEN_CODEC_MPEG4; 100 encoder_context->fps_num = 60; 101 encoder_context->fps_den = 2; 102 encoder_context->inputformat = VEN_INPUTFMT_NV12; 103 encoder_context->targetbitrate = 128000; 104 105 file_ptr = fopen ("/data/output.m4v","wb"); 106 107 if (file_ptr == NULL) { 108 DEBUG_PRINT("\n File can't be created"); 109 free (encoder_context); 110 return -1; 111 } 112 113 encoder_context->outputBufferFile = file_ptr; 114 115 switch (atoi(argv[2])) { 116 case 0: 117 DEBUG_PRINT("\n MPEG4 codec selected"); 118 encoder_context->codectype = VEN_CODEC_MPEG4; 119 Code_type = 0; 120 break; 121 case 1: 122 DEBUG_PRINT("\n H.263"); 123 encoder_context->codectype = VEN_CODEC_H263; 124 Code_type = 0; 125 break; 126 case 2: 127 DEBUG_PRINT("\n H.264"); 128 encoder_context->codectype = VEN_CODEC_H264; 129 Code_type = 1; 130 break; 131 default: 132 DEBUG_PRINT("\n Wrong codec type"); 133 error = -1; 134 break; 135 } 136 137 if (error != -1) { 138 temp1 = atoi(argv[3]); 139 temp2 = atoi(argv[4]); 140 141 if (((temp1%16) != 0) || ((temp2%16) != 0)) { 142 error = -1; 143 } else { 144 encoder_context->input_width = temp1; 145 encoder_context->input_height = temp2; 146 } 147 } 148 149 switch (atoi(argv[5])) { 150 case 0: 151 DEBUG_PRINT("\n No Sink"); 152 encoder_context->outputBufferFile = NULL; 153 break; 154 } 155 156 if (error != -1) { 157 encoder_context->targetbitrate = atoi (argv[6]); 158 } 159 160 if ( error != -1 && (init_encoder (encoder_context) == -1 )) { 161 DEBUG_PRINT("\n Init decoder fails "); 162 error = -1; 163 } 164 165 DEBUG_PRINT("\n Decoder open successfull"); 166 167 168 /*Allocate input and output buffers*/ 169 if (error != -1 && (allocate_buffer (0,encoder_context)== -1)) { 170 DEBUG_PRINT("\n Error in input Buffer allocation"); 171 error = -1; 172 } 173 174 if (error != -1 && (allocate_buffer (1,encoder_context)== -1)) { 175 DEBUG_PRINT("\n Error in output Buffer allocation"); 176 error = -1; 177 } 178 179 180 if (error != -1 && (start_encoding (encoder_context) == -1)) { 181 DEBUG_PRINT("\n Error in start decoding call"); 182 error = -1; 183 } 184 185 if (error != -1 && (stop_encoding (encoder_context) == -1)) { 186 DEBUG_PRINT("\n Error in stop decoding call"); 187 error = -1; 188 } 189 190 DEBUG_PRINT("\n De-init the decoder"); 191 192 if ((deinit_encoder (encoder_context) == -1)) { 193 error = -1; 194 } 195 196 197 (void)free_buffer (INPUT_BUFFER,encoder_context); 198 (void)free_buffer (OUTPUT_BUFFER,encoder_context); 199 200 if (encoder_context->inputBufferFile != NULL) { 201 fclose (encoder_context->inputBufferFile); 202 } 203 204 if (encoder_context->outputBufferFile != NULL) { 205 fclose (encoder_context->outputBufferFile); 206 } 207 208 DEBUG_PRINT ("\n Total Number of frames decoded %d",total_frames); 209 DEBUG_PRINT("\n closing the driver"); 210 free (encoder_context); 211 212 return error; 213 } 214 215 int init_encoder ( struct video_encoder_context *init_decode ) 216 { 217 struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; 218 struct venc_basecfg basecfg; 219 struct video_queue_context *queue_ptr = NULL; 220 struct venc_ratectrlcfg ratecrl; 221 pthread_mutexattr_t init_values; 222 struct venc_profile profile; 223 struct ven_profilelevel profilelevel; 224 225 DEBUG_PRINT("\n Before calling the open"); 226 227 init_decode->video_driver_fd = open ("/dev/msm_vidc_enc", \ 228 O_RDWR | O_NONBLOCK); 229 230 231 232 if (init_decode->video_driver_fd < 0) { 233 DEBUG_PRINT("\n Open failed"); 234 return -1; 235 } 236 237 basecfg.codectype = init_decode->codectype; 238 basecfg.dvs_height = 0; 239 basecfg.dvs_width = 0; 240 basecfg.fps_den = init_decode->fps_den; 241 basecfg.fps_num = init_decode->fps_num; 242 basecfg.input_height = init_decode->input_height; 243 basecfg.input_width = init_decode->input_width; 244 basecfg.inputformat = init_decode->inputformat; 245 basecfg.targetbitrate = init_decode->targetbitrate; 246 247 /*Initialize Decoder with codec type and resolution*/ 248 ioctl_msg.in = &basecfg; 249 ioctl_msg.out = NULL; 250 251 if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_BASE_CFG, 252 (void*)&ioctl_msg) < 0) { 253 DEBUG_PRINT("\n Set base config type failed"); 254 return -1; 255 } 256 257 /*Initialize Decoder with codec type and resolution*/ 258 DEBUG_PRINT ("\n Switch off rate control"); 259 ioctl_msg.in = &ratecrl; 260 ioctl_msg.out = NULL; 261 ratecrl.rcmode = VEN_RC_OFF; 262 263 if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_RATE_CTRL_CFG, 264 (void*)&ioctl_msg) < 0) { 265 DEBUG_PRINT("\n Set rate control failed"); 266 return -1; 267 } 268 269 if (basecfg.codectype == VEN_CODEC_H264) { 270 DEBUG_PRINT ("\n Set the VEN_IOCTL_SET_CODEC_PROFILE High"); 271 ioctl_msg.in = &profile; 272 ioctl_msg.out = NULL; 273 profile.profile = VEN_PROFILE_H264_BASELINE; 274 275 if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_CODEC_PROFILE, 276 (void*)&ioctl_msg) < 0) { 277 DEBUG_PRINT("\n Set VEN_IOCTL_SET_CODEC_PROFILE failed"); 278 return -1; 279 } 280 281 DEBUG_PRINT ("\n Set the VEN_IOCTL_SET_CODEC_PROFILE High"); 282 ioctl_msg.in = &profilelevel; 283 ioctl_msg.out = NULL; 284 profilelevel.level = VEN_LEVEL_H264_1p1; 285 286 if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_PROFILE_LEVEL, 287 (void*)&ioctl_msg) < 0) { 288 DEBUG_PRINT("\n Set VEN_IOCTL_SET_CODEC_PROFILE failed"); 289 return -1; 290 } 291 292 if (basecfg.input_width > 720) { 293 DEBUG_PRINT ("\n Set the VEN_IOCTL_SET_CODEC_PROFILE High"); 294 ioctl_msg.in = &profile; 295 ioctl_msg.out = NULL; 296 profile.profile = VEN_PROFILE_H264_HIGH; 297 298 if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_CODEC_PROFILE, 299 (void*)&ioctl_msg) < 0) { 300 DEBUG_PRINT("\n Set VEN_IOCTL_SET_CODEC_PROFILE failed"); 301 return -1; 302 } 303 304 DEBUG_PRINT ("\n Set the VEN_IOCTL_SET_CODEC_PROFILE High"); 305 ioctl_msg.in = &profilelevel; 306 ioctl_msg.out = NULL; 307 profilelevel.level = VEN_LEVEL_H264_3p1; 308 309 if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_PROFILE_LEVEL, 310 (void*)&ioctl_msg) < 0) { 311 DEBUG_PRINT("\n Set VEN_IOCTL_SET_CODEC_PROFILE failed"); 312 return -1; 313 } 314 } 315 } 316 317 DEBUG_PRINT("\n Query Input bufffer requirements"); 318 /*Get the Buffer requirements for input and output ports*/ 319 320 321 322 ioctl_msg.in = NULL; 323 ioctl_msg.out = &init_decode->input_buffer; 324 325 if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_GET_INPUT_BUFFER_REQ, 326 (void*)&ioctl_msg) < 0) { 327 DEBUG_PRINT("\n Requesting for input buffer requirements failed"); 328 return -1; 329 } 330 331 DEBUG_PRINT("\n input Size=%d min count =%d actual count = %d", \ 332 (int)init_decode->input_buffer.datasize,\ 333 (int)init_decode->input_buffer.mincount,\ 334 (int)init_decode->input_buffer.actualcount); 335 336 337 ioctl_msg.in = &init_decode->input_buffer; 338 ioctl_msg.out = NULL; 339 init_decode->input_buffer.actualcount = init_decode->input_buffer.mincount + 2; 340 341 if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_SET_INPUT_BUFFER_REQ, 342 (void*)&ioctl_msg) < 0) { 343 DEBUG_PRINT("\n Set Buffer Requirements Failed"); 344 return -1; 345 } 346 347 348 DEBUG_PRINT("\n Query output bufffer requirements"); 349 ioctl_msg.in = NULL; 350 ioctl_msg.out = &init_decode->output_buffer; 351 352 if (ioctl (init_decode->video_driver_fd,VEN_IOCTL_GET_OUTPUT_BUFFER_REQ, 353 (void*)&ioctl_msg) < 0) { 354 DEBUG_PRINT("\n Requesting for output buffer requirements failed"); 355 return -1; 356 } 357 358 DEBUG_PRINT("\n output Size=%d min count =%d actual count = %d", \ 359 (int)init_decode->output_buffer.datasize,\ 360 (int)init_decode->output_buffer.mincount,\ 361 (int)init_decode->output_buffer.actualcount); 362 363 /*Create Queue related data structures*/ 364 queue_ptr = &init_decode->queue_context; 365 queue_ptr->commandq_size = 50; 366 queue_ptr->dataq_size = 50; 367 368 sem_init(&queue_ptr->sem_message,0, 0); 369 sem_init(&init_decode->sem_synchronize,0, 0); 370 371 pthread_mutexattr_init (&init_values); 372 pthread_mutex_init (&queue_ptr->mutex,&init_values); 373 pthread_mutex_init (&read_lock,&init_values); 374 DEBUG_PRINT("\n create Queues"); 375 queue_ptr->ptr_cmdq = (struct video_msgq*) \ 376 calloc (sizeof (struct video_msgq), 377 queue_ptr->commandq_size); 378 queue_ptr->ptr_dataq = (struct video_msgq*) \ 379 calloc (sizeof (struct video_msgq), 380 queue_ptr->dataq_size 381 ); 382 383 if ( queue_ptr->ptr_cmdq == NULL || 384 queue_ptr->ptr_dataq == NULL 385 ) { 386 return -1; 387 } 388 389 DEBUG_PRINT("\n create Threads"); 390 391 /*Create two threads*/ 392 if ( (pthread_create (&init_decode->videothread_id,NULL,video_thread, 393 init_decode) < 0) || 394 (pthread_create (&init_decode->asyncthread_id,NULL,async_thread, 395 init_decode) < 0) 396 ) { 397 return -1; 398 } 399 400 return 1; 401 } 402 403 404 405 int free_buffer ( unsigned int buffer_dir, 406 struct video_encoder_context *encoder_context 407 ) 408 { 409 unsigned int buffercount = 0,i=0; 410 struct venc_bufferpayload **ptemp = NULL; 411 412 if (encoder_context == NULL) { 413 return -1; 414 } 415 416 if (buffer_dir == INPUT_BUFFER && encoder_context->ptr_inputbuffer) { 417 buffercount = encoder_context->input_buffer.actualcount; 418 ptemp = encoder_context->ptr_inputbuffer; 419 420 for (i=0; i<buffercount; i++) { 421 if (ptemp [i]) { 422 if (ptemp [i]->fd != -1) { 423 munmap ( ptemp [i]->pbuffer,ptemp [i]->maped_size); 424 ptemp [i]->pbuffer = NULL; 425 close (ptemp [i]->fd); 426 } 427 428 free (ptemp [i]); 429 ptemp [i] = NULL; 430 } 431 } 432 433 free (encoder_context->ptr_inputbuffer); 434 encoder_context->ptr_inputbuffer = NULL; 435 } else if ( buffer_dir == OUTPUT_BUFFER && encoder_context->ptr_outputbuffer ) { 436 buffercount = encoder_context->output_buffer.actualcount; 437 ptemp = encoder_context->ptr_outputbuffer; 438 439 if (ptemp) { 440 for (i=0; i<buffercount; i++) { 441 if (ptemp [i]) { 442 if (ptemp [i]->fd != -1) { 443 munmap ( ptemp [i]->pbuffer,ptemp [i]->maped_size); 444 ptemp [i]->pbuffer = NULL; 445 close (ptemp [i]->fd); 446 } 447 448 free (ptemp [i]); 449 ptemp [i] = NULL; 450 } 451 } 452 453 free (ptemp); 454 encoder_context->ptr_outputbuffer = NULL; 455 } 456 } 457 458 return 1; 459 } 460 461 int allocate_buffer ( unsigned int buffer_dir, 462 struct video_encoder_context *encoder_context 463 ) 464 { 465 struct venc_bufferpayload **ptemp = NULL; 466 struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; 467 unsigned int buffercount = 0,i=0,alignedsize=0; 468 unsigned int buffersize = 0; 469 470 if ( encoder_context == NULL) { 471 DEBUG_PRINT ("\nallocate_buffer: context is NULL"); 472 return -1; 473 } 474 475 if ( buffer_dir == INPUT_BUFFER ) { 476 /*Check if buffers are allocated*/ 477 if (encoder_context->ptr_inputbuffer != NULL) { 478 DEBUG_PRINT ("\nallocate_buffer: encoder_context->ptr_inputbuffer is set"); 479 return -1; 480 } 481 482 buffercount = encoder_context->input_buffer.actualcount; 483 alignedsize = encoder_context->input_buffer.alignment; 484 buffersize = encoder_context->input_buffer.datasize; 485 buffersize = (buffersize + alignedsize) & (~alignedsize); 486 } else if (buffer_dir == OUTPUT_BUFFER) { 487 /*Check if buffers are allocated*/ 488 if (encoder_context->ptr_outputbuffer != NULL) { 489 DEBUG_PRINT ("\nallocate_buffer: Double allcoate output"); 490 return -1; 491 } 492 493 buffercount = encoder_context->output_buffer.actualcount; 494 alignedsize = encoder_context->output_buffer.alignment; 495 buffersize = encoder_context->output_buffer.datasize; 496 buffersize = (buffersize + alignedsize) & (~alignedsize); 497 498 } else { 499 DEBUG_PRINT ("\nallocate_buffer: Wrong buffer directions"); 500 return -1; 501 } 502 503 ptemp = (struct venc_bufferpayload **)\ 504 calloc (sizeof (struct venc_bufferpayload *),buffercount); 505 506 if (ptemp == NULL) { 507 DEBUG_PRINT ("\nallocate_buffer: venc_bufferpayload failure"); 508 return -1; 509 } 510 511 512 if (buffer_dir == OUTPUT_BUFFER) { 513 DEBUG_PRINT ("\nallocate_buffer: OUT"); 514 encoder_context->ptr_outputbuffer = ptemp; 515 } else { 516 DEBUG_PRINT ("\nallocate_buffer: IN"); 517 encoder_context->ptr_inputbuffer = ptemp; 518 } 519 520 /*Allocate buffer headers*/ 521 for (i=0; i< buffercount; i++) { 522 ptemp [i] = (struct venc_bufferpayload*)\ 523 calloc (sizeof (struct venc_bufferpayload),1); 524 525 if (ptemp [i] == NULL) { 526 DEBUG_PRINT ("\nallocate_buffer: ptemp [i] calloc failure"); 527 return -1; 528 } 529 530 ptemp [i]->fd = -1; 531 } 532 533 for (i=0; i< buffercount; i++) { 534 ptemp [i]->fd = open ("/dev/pmem_adsp",O_RDWR); 535 536 if (ptemp [i]->fd < 0) { 537 DEBUG_PRINT ("\nallocate_buffer: open pmem_adsp failed"); 538 return -1; 539 } 540 541 ptemp [i]->pbuffer = mmap(NULL,clp2(buffersize),PROT_READ|PROT_WRITE, 542 MAP_SHARED,ptemp [i]->fd,0); 543 DEBUG_PRINT ("\n pmem fd = %d virt addr = %p",ptemp [i]->fd,\ 544 ptemp [i]->pbuffer); 545 546 if (ptemp [i]->pbuffer == MAP_FAILED) { 547 ptemp [i]->pbuffer = NULL; 548 DEBUG_PRINT ("\nallocate_buffer: MMAP failed"); 549 return -1; 550 } 551 552 ptemp [i]->sz = buffersize; 553 ptemp [i]->maped_size = clp2 (buffersize); 554 555 ioctl_msg.in = ptemp [i]; 556 ioctl_msg.out = NULL; 557 558 if (buffer_dir == OUTPUT_BUFFER) { 559 if (ioctl (encoder_context->video_driver_fd,VEN_IOCTL_SET_OUTPUT_BUFFER, 560 &ioctl_msg) < 0) { 561 DEBUG_PRINT ("\nallocate_buffer: Set Output Buffer IOCTL failed"); 562 return -1; 563 } 564 } else { 565 if (ioctl (encoder_context->video_driver_fd,VEN_IOCTL_SET_INPUT_BUFFER, 566 &ioctl_msg) < 0) { 567 DEBUG_PRINT ("\nallocate_buffer: Set input Buffer IOCTL failed"); 568 return -1; 569 } 570 } 571 572 } 573 574 DEBUG_PRINT ("\nallocate_buffer: Success"); 575 return 1; 576 } 577 578 579 580 int start_encoding (struct video_encoder_context *encoder_context) 581 { 582 struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; 583 struct venc_buffer enc_buffer; 584 unsigned int i = 0; 585 unsigned int data_len =0; 586 587 588 if (encoder_context == NULL) { 589 return -1; 590 } 591 592 if (ioctl (encoder_context->video_driver_fd,VEN_IOCTL_CMD_START, 593 NULL) < 0) { 594 DEBUG_PRINT("\n Start failed"); 595 return -1; 596 } 597 598 DEBUG_PRINT("\n Start Issued successfully waiting for Start Done"); 599 /*Wait for Start command response*/ 600 sem_wait (&encoder_context->sem_synchronize); 601 602 /*Push output Buffers*/ 603 i = 0; 604 605 while (i < encoder_context->output_buffer.actualcount) { 606 enc_buffer.clientdata = (void *)encoder_context->ptr_outputbuffer [i]; 607 enc_buffer.flags = 0; 608 enc_buffer.sz = encoder_context->ptr_outputbuffer [i]->sz; 609 enc_buffer.len = 0; 610 enc_buffer.ptrbuffer = encoder_context->ptr_outputbuffer [i]->pbuffer; 611 enc_buffer.offset = 0; 612 enc_buffer.timestamp = 0; 613 614 DEBUG_PRINT ("\n Client Data on output = %p",(void *)enc_buffer.clientdata); 615 ioctl_msg.in = &enc_buffer; 616 ioctl_msg.out = NULL; 617 618 if (ioctl (encoder_context->video_driver_fd, 619 VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER,&ioctl_msg) < 0) { 620 DEBUG_PRINT("\n fill output frame failed"); 621 return -1; 622 } 623 624 i++; 625 } 626 627 628 /*push input buffers*/ 629 i = 0; 630 631 while (i < encoder_context->input_buffer.actualcount) { 632 DEBUG_PRINT("\n Read Frame from File"); 633 634 enc_buffer.clientdata = (void *)encoder_context->ptr_inputbuffer [i]; 635 enc_buffer.flags = 0; 636 enc_buffer.sz = encoder_context->ptr_inputbuffer [i]->sz; 637 enc_buffer.len = 0; 638 enc_buffer.ptrbuffer = encoder_context->ptr_inputbuffer [i]->pbuffer; 639 enc_buffer.offset = 0; 640 enc_buffer.timestamp = total_frames * 641 ((encoder_context->fps_den * 1000000)/encoder_context->fps_num); 642 enc_buffer.len = (encoder_context->input_height * 643 encoder_context->input_width *3)/2; 644 data_len = read_frame ( enc_buffer.ptrbuffer, 645 enc_buffer.len, 646 encoder_context->inputBufferFile); 647 648 if (data_len == 0) { 649 DEBUG_PRINT("\n Length is zero error"); 650 return -1; 651 } 652 653 enc_buffer.len = data_len; 654 DEBUG_PRINT("\n Read Frame from File szie = %d",(int)data_len); 655 656 DEBUG_PRINT ("\n Client Data on output = %p",(void *)enc_buffer.clientdata); 657 ioctl_msg.in = &enc_buffer; 658 ioctl_msg.out = NULL; 659 660 if (ioctl (encoder_context->video_driver_fd, 661 VEN_IOCTL_CMD_ENCODE_FRAME,&ioctl_msg) < 0) { 662 DEBUG_PRINT("\n Encode input frame failed"); 663 return -1; 664 } 665 666 total_frames++; 667 i++; 668 } 669 670 DEBUG_PRINT ("\n Wait for EOS"); 671 /*Wait for EOS or Error condition*/ 672 sem_wait (&encoder_context->sem_synchronize); 673 DEBUG_PRINT ("\n Reached EOS"); 674 675 return 1; 676 } 677 678 int stop_encoding (struct video_encoder_context *encoder_context) 679 { 680 struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; 681 struct venc_bufferflush buffer_flush; 682 683 if (encoder_context == NULL) { 684 return -1; 685 } 686 687 buffer_flush.flush_mode = VEN_FLUSH_INPUT; 688 ioctl_msg.in = &buffer_flush; 689 ioctl_msg.out = NULL; 690 691 if (ioctl(encoder_context->video_driver_fd,VEN_IOCTL_CMD_FLUSH, 692 &ioctl_msg) < 0) { 693 DEBUG_PRINT("\n Flush input failed"); 694 } else { 695 sem_wait (&encoder_context->sem_synchronize); 696 } 697 698 buffer_flush.flush_mode = VEN_FLUSH_OUTPUT; 699 ioctl_msg.in = &buffer_flush; 700 ioctl_msg.out = NULL; 701 702 if (ioctl(encoder_context->video_driver_fd,VEN_IOCTL_CMD_FLUSH, 703 &ioctl_msg) < 0) { 704 DEBUG_PRINT("\n Flush output failed"); 705 } else { 706 sem_wait (&encoder_context->sem_synchronize); 707 } 708 709 DEBUG_PRINT("\n Stop VEN_IOCTL_CMD_STOP"); 710 711 if (ioctl(encoder_context->video_driver_fd,VEN_IOCTL_CMD_STOP,NULL) < 0) { 712 DEBUG_PRINT("\n Stop failed"); 713 } else { 714 sem_wait (&encoder_context->sem_synchronize); 715 } 716 717 return 1; 718 } 719 720 int deinit_encoder (struct video_encoder_context *init_decode) 721 { 722 if (init_decode == NULL) { 723 return -1; 724 } 725 726 /*Close the driver*/ 727 if (init_decode->video_driver_fd != -1) { 728 close (init_decode->video_driver_fd); 729 } 730 731 if (init_decode->queue_context.ptr_cmdq) { 732 free (init_decode->queue_context.ptr_cmdq); 733 init_decode->queue_context.ptr_cmdq = NULL; 734 } 735 736 if (init_decode->queue_context.ptr_dataq) { 737 free (init_decode->queue_context.ptr_dataq); 738 init_decode->queue_context.ptr_dataq = NULL; 739 } 740 741 sem_destroy (&init_decode->queue_context.sem_message); 742 sem_destroy (&init_decode->sem_synchronize); 743 744 pthread_mutex_destroy(&init_decode->queue_context.mutex); 745 pthread_mutex_destroy (&read_lock); 746 747 return 1; 748 } 749 750 static void* video_thread (void *context) 751 { 752 struct video_encoder_context *encoder_context = NULL; 753 struct video_msgq *queueitem = NULL; 754 struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; 755 struct venc_bufferpayload *tempbuffer = NULL; 756 struct venc_buffer enc_buffer; 757 unsigned int data_len =0; 758 759 760 if (context == NULL) { 761 DEBUG_PRINT("\n video thread recieved NULL context"); 762 return NULL; 763 } 764 765 encoder_context = (struct video_encoder_context *) context; 766 767 /* Thread function which will accept commands from async thread 768 * or main thread 769 */ 770 while (1) { 771 queueitem = queue_get_cmd (&encoder_context ->queue_context); 772 773 if (queueitem != NULL) { 774 switch (queueitem->cmd) { 775 case VEN_MSG_START: 776 DEBUG_PRINT("\n recived start done command"); 777 sem_post (&encoder_context->sem_synchronize); 778 break; 779 780 case VEN_MSG_STOP: 781 DEBUG_PRINT("\n recieved stop done"); 782 sem_post (&encoder_context->sem_synchronize); 783 break; 784 785 case VEN_MSG_INPUT_BUFFER_DONE: 786 787 tempbuffer = (struct venc_bufferpayload *)queueitem->clientdata; 788 789 if (tempbuffer == NULL) { 790 DEBUG_PRINT("\n FATAL ERROR input buffer address is bad"); 791 sem_post (&encoder_context->sem_synchronize); 792 break; 793 } 794 795 tempbuffer->filled_len = (encoder_context->input_height * 796 encoder_context->input_width *3)/2; 797 798 data_len = read_frame ( tempbuffer->pbuffer, 799 tempbuffer->filled_len, 800 encoder_context->inputBufferFile); 801 802 if (data_len == 0) { 803 DEBUG_PRINT ("\n End of stream reached"); 804 sem_post (&encoder_context->sem_synchronize); 805 break; 806 } 807 808 enc_buffer.clientdata = (void *)tempbuffer; 809 enc_buffer.flags = 0; 810 enc_buffer.ptrbuffer = tempbuffer->pbuffer; 811 enc_buffer.sz = tempbuffer->sz; 812 enc_buffer.len = tempbuffer->filled_len; 813 enc_buffer.offset = 0; 814 enc_buffer.timestamp = total_frames * 815 ((encoder_context->fps_den * 1000000)/encoder_context->fps_num); 816 817 /*TODO: Time stamp needs to be updated*/ 818 ioctl_msg.in = &enc_buffer; 819 ioctl_msg.out = NULL; 820 total_frames++; 821 822 if (ioctl(encoder_context->video_driver_fd,VEN_IOCTL_CMD_ENCODE_FRAME, 823 &ioctl_msg) < 0) { 824 DEBUG_PRINT("\n Decoder frame failed"); 825 sem_post (&encoder_context->sem_synchronize); 826 } 827 828 DEBUG_PRINT("\n Input buffer done send next buffer current value = %d",\ 829 total_frames); 830 break; 831 832 case VEN_MSG_OUTPUT_BUFFER_DONE: 833 834 tempbuffer = (struct venc_bufferpayload *)queueitem->clientdata; 835 836 if (tempbuffer == NULL) { 837 DEBUG_PRINT("\n FATAL ERROR input buffer address is bad"); 838 sem_post (&encoder_context->sem_synchronize); 839 break; 840 } 841 842 if (encoder_context->outputBufferFile != NULL) { 843 fwrite (tempbuffer->pbuffer,1,tempbuffer->filled_len, 844 encoder_context->outputBufferFile); 845 } 846 847 848 DEBUG_PRINT("\n recieved output buffer consume outbuffer"); 849 DEBUG_PRINT("\nValues outputbuffer->bufferaddr = %p",\ 850 tempbuffer->pbuffer); 851 enc_buffer.clientdata = (void *)tempbuffer; 852 enc_buffer.flags = 0; 853 enc_buffer.sz = tempbuffer->sz; 854 enc_buffer.len = 0; 855 enc_buffer.ptrbuffer = tempbuffer->pbuffer; 856 enc_buffer.offset = 0; 857 enc_buffer.timestamp = 0; 858 859 ioctl_msg.in = &enc_buffer; 860 ioctl_msg.out = NULL; 861 862 if (ioctl (encoder_context->video_driver_fd, 863 VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER,&ioctl_msg) < 0) { 864 DEBUG_PRINT("\n Decoder frame failed"); 865 return NULL; 866 } 867 868 break; 869 870 case VEN_MSG_FLUSH_INPUT_DONE: 871 DEBUG_PRINT("\n Flush input complete"); 872 sem_post (&encoder_context->sem_synchronize); 873 break; 874 875 case VEN_MSG_FLUSH_OUPUT_DONE: 876 DEBUG_PRINT("\n Flush output complete"); 877 sem_post (&encoder_context->sem_synchronize); 878 break; 879 } 880 881 if (queueitem->cmd == VEN_MSG_STOP) { 882 DEBUG_PRINT("\n Playback has ended thread will exit"); 883 return NULL; 884 } 885 } else { 886 DEBUG_PRINT("\n Error condition recieved NULL from Queue"); 887 } 888 889 } 890 } 891 892 static void* async_thread (void *context) 893 { 894 struct video_encoder_context *encoder_context = NULL; 895 struct video_msgq queueitem ; 896 struct venc_msg venc_msg; 897 struct venc_bufferpayload *tempbuffer = NULL; 898 struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; 899 int result = -1; 900 901 if (context == NULL) { 902 DEBUG_PRINT("\n aynsc thread recieved NULL context"); 903 return NULL; 904 } 905 906 encoder_context = (struct video_encoder_context *) context; 907 DEBUG_PRINT("\n Entering the async thread"); 908 909 while (1) { 910 ioctl_msg.in = NULL; 911 ioctl_msg.out = (void*)&venc_msg; 912 DEBUG_PRINT ("\n Sizeof venc_msginfo = %d ",sizeof (venc_msg)); 913 DEBUG_PRINT("\n Address of Venc msg in async thread %p",\ 914 ioctl_msg.out); 915 916 if (ioctl (encoder_context->video_driver_fd,VEN_IOCTL_CMD_READ_NEXT_MSG,\ 917 (void*)&ioctl_msg) < 0) { 918 DEBUG_PRINT("\n Error in ioctl read next msg"); 919 } else { 920 switch (venc_msg.msgcode) { 921 case VEN_MSG_START: 922 case VEN_MSG_STOP: 923 case VEN_MSG_INDICATION: 924 DEBUG_PRINT("\nSTOP/START Indiacation"); 925 queueitem.cmd = venc_msg.msgcode; 926 queueitem.status = venc_msg.statuscode; 927 queueitem.clientdata = NULL; 928 break; 929 930 case VEN_MSG_INPUT_BUFFER_DONE: 931 DEBUG_PRINT("\nINPUT buffer done Indiacation"); 932 queueitem.cmd = venc_msg.msgcode; 933 queueitem.status = venc_msg.statuscode; 934 queueitem.clientdata = (void *)venc_msg.buf.clientdata; 935 DEBUG_PRINT("\nInput Client data pointer is %p",queueitem.clientdata); 936 tempbuffer = (struct venc_bufferpayload *) queueitem.clientdata; 937 DEBUG_PRINT ("\n Input Address of tempbuffer %p",tempbuffer); 938 tempbuffer->filled_len = venc_msg.buf.len; 939 DEBUG_PRINT ("\n Input value of tempbuffer tempbuffer->filled_len %d",(int)tempbuffer->filled_len); 940 break; 941 case VEN_MSG_OUTPUT_BUFFER_DONE: 942 DEBUG_PRINT("\nOUPUT buffer done Indiacation"); 943 queueitem.cmd = venc_msg.msgcode; 944 queueitem.status = venc_msg.statuscode; 945 queueitem.clientdata = (void *)venc_msg.buf.clientdata; 946 DEBUG_PRINT("\nOutput Client data pointer is %p",queueitem.clientdata); 947 tempbuffer = (struct venc_bufferpayload *) queueitem.clientdata; 948 DEBUG_PRINT ("\n Output Address of tempbuffer %p",tempbuffer); 949 tempbuffer->filled_len = venc_msg.buf.len; 950 DEBUG_PRINT ("\n Output value of tempbuffer tempbuffer->filled_len %d",(int)tempbuffer->filled_len); 951 break; 952 953 default: 954 DEBUG_PRINT("\nIn Default of get next message %d",(int)venc_msg.msgcode); 955 queueitem.cmd = venc_msg.msgcode; 956 queueitem.status = venc_msg.statuscode; 957 queueitem.clientdata = NULL; 958 break; 959 } 960 961 result = queue_post_cmdq (&encoder_context->queue_context,&queueitem); 962 963 while (result == 0) { 964 result = queue_post_cmdq (&encoder_context->queue_context,&queueitem); 965 } 966 967 if (result == -1) { 968 DEBUG_PRINT("\n FATAL ERROR WITH Queue"); 969 } 970 } 971 972 if (venc_msg.msgcode == VEN_MSG_STOP) { 973 /*Thread can exit at this point*/ 974 return NULL; 975 } 976 } 977 } 978 979 980 static unsigned int read_frame (unsigned char *dataptr, unsigned int length, 981 FILE * inputBufferFile) 982 { 983 984 unsigned int readOffset = 0; 985 int bytes_read = 0; 986 unsigned int code = 0; 987 int found = 0; 988 989 DEBUG_PRINT ("\n Inside the readframe"); 990 991 if (dataptr == NULL && length == 0) { 992 DEBUG_PRINT ("\n dataptr = %p length = %d",dataptr,(int)length); 993 return 0; 994 } 995 996 pthread_mutex_lock(&read_lock); 997 bytes_read = fread(&dataptr[readOffset],1,length,inputBufferFile); 998 pthread_mutex_unlock(&read_lock); 999 1000 return bytes_read; 1001 } 1002