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 "decoder_driver_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 int Read_Buffer_From_DAT_File( unsigned char *dataptr, unsigned int length, 52 FILE * inputBufferFile 53 ); 54 55 static unsigned clp2(unsigned x) 56 { 57 x = x - 1; 58 x = x | (x >> 1); 59 x = x | (x >> 2); 60 x = x | (x >> 4); 61 x = x | (x >> 8); 62 x = x | (x >>16); 63 return x + 1; 64 } 65 66 static void* video_thread (void *); 67 static void* async_thread (void *); 68 69 int main (int argc, char **argv) 70 { 71 struct video_decoder_context *decoder_context = NULL; 72 char *file_name = NULL; 73 FILE *file_ptr = NULL; 74 int temp1 =0,temp2 =0; 75 int error = 1; 76 unsigned int i = 0; 77 78 file_name = argv [1]; 79 file_ptr = fopen (file_name,"rb"); 80 81 if (file_ptr == NULL) { 82 DEBUG_PRINT("\n File is not located "); 83 return -1; 84 } 85 86 87 decoder_context = (struct video_decoder_context *) \ 88 calloc (sizeof (struct video_decoder_context),1); 89 90 if (decoder_context == NULL) { 91 return -1; 92 } 93 94 decoder_context->outputBufferFile = NULL; 95 decoder_context->inputBufferFile = NULL; 96 decoder_context->video_driver_fd = -1; 97 decoder_context->inputBufferFile = file_ptr; 98 99 file_ptr = fopen ("/data/output.yuv","wb"); 100 101 if (file_ptr == NULL) { 102 DEBUG_PRINT("\n File can't be created"); 103 free (decoder_context); 104 return -1; 105 } 106 107 decoder_context->outputBufferFile = file_ptr; 108 109 switch (atoi(argv[2])) { 110 case 0: 111 DEBUG_PRINT("\n MPEG4 codec selected"); 112 decoder_context->decoder_format = VDEC_CODECTYPE_MPEG4; 113 Code_type = 0; 114 break; 115 case 1: 116 DEBUG_PRINT("\n H.263"); 117 decoder_context->decoder_format = VDEC_CODECTYPE_H263; 118 Code_type = 0; 119 break; 120 case 2: 121 DEBUG_PRINT("\n H.264"); 122 decoder_context->decoder_format = VDEC_CODECTYPE_H264; 123 Code_type = 1; 124 break; 125 default: 126 DEBUG_PRINT("\n Wrong codec type"); 127 error = -1; 128 break; 129 } 130 131 if (error != -1) { 132 temp1 = atoi(argv[3]); 133 temp2 = atoi(argv[4]); 134 135 if (((temp1%16) != 0) || ((temp2%16) != 0)) { 136 error = -1; 137 } else { 138 decoder_context->video_resoultion.frame_height = temp1; 139 decoder_context->video_resoultion.frame_width = temp2; 140 } 141 } 142 143 switch (atoi(argv[5])) { 144 case 0: 145 DEBUG_PRINT("\n No Sink"); 146 decoder_context->outputBufferFile = NULL; 147 break; 148 } 149 150 if ( error != -1 && (init_decoder (decoder_context) == -1 )) { 151 DEBUG_PRINT("\n Init decoder fails "); 152 error = -1; 153 } 154 155 DEBUG_PRINT("\n Decoder open successfull"); 156 157 158 /*Allocate input and output buffers*/ 159 if (error != -1 && (allocate_buffer (VDEC_BUFFER_TYPE_INPUT, 160 decoder_context)== -1)) { 161 DEBUG_PRINT("\n Error in input Buffer allocation"); 162 error = -1; 163 } 164 165 if (error != -1 && (allocate_buffer (VDEC_BUFFER_TYPE_OUTPUT, 166 decoder_context)== -1)) { 167 DEBUG_PRINT("\n Error in output Buffer allocation"); 168 error = -1; 169 } 170 171 172 if (error != -1 && (start_decoding (decoder_context) == -1)) { 173 DEBUG_PRINT("\n Error in start decoding call"); 174 error = -1; 175 } 176 177 if (error != -1 && (stop_decoding (decoder_context) == -1)) { 178 DEBUG_PRINT("\n Error in stop decoding call"); 179 error = -1; 180 } 181 182 DEBUG_PRINT("\n De-init the decoder"); 183 184 if ((deinit_decoder (decoder_context) == -1)) { 185 error = -1; 186 } 187 188 189 (void)free_buffer (VDEC_BUFFER_TYPE_INPUT,decoder_context); 190 (void)free_buffer (VDEC_BUFFER_TYPE_OUTPUT,decoder_context); 191 192 if (decoder_context->inputBufferFile != NULL) { 193 fclose (decoder_context->inputBufferFile); 194 } 195 196 if (decoder_context->outputBufferFile != NULL) { 197 fclose (decoder_context->outputBufferFile); 198 } 199 200 DEBUG_PRINT ("\n Total Number of frames decoded %d",total_frames); 201 DEBUG_PRINT("\n closing the driver"); 202 free (decoder_context); 203 204 return error; 205 } 206 207 int init_decoder ( struct video_decoder_context *init_decode ) 208 { 209 struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; 210 struct video_queue_context *queue_ptr = NULL; 211 #ifdef MAX_RES_720P 212 enum vdec_output_fromat output_format = VDEC_YUV_FORMAT_NV12; 213 #endif 214 #ifdef MAX_RES_1080P 215 enum vdec_output_fromat output_format = VDEC_YUV_FORMAT_TILE_4x2; 216 #endif 217 218 pthread_mutexattr_t init_values; 219 220 DEBUG_PRINT("\n Before calling the open"); 221 222 init_decode->video_driver_fd = open ("/dev/msm_vidc_dec", \ 223 O_RDWR | O_NONBLOCK); 224 225 226 227 if (init_decode->video_driver_fd < 0) { 228 DEBUG_PRINT("\n Open failed"); 229 return -1; 230 } 231 232 233 /*Initialize Decoder with codec type and resolution*/ 234 ioctl_msg.in = &init_decode->decoder_format; 235 ioctl_msg.out = NULL; 236 237 if (ioctl (init_decode->video_driver_fd,VDEC_IOCTL_SET_CODEC, 238 (void*)&ioctl_msg) < 0) { 239 DEBUG_PRINT("\n Set codec type failed"); 240 return -1; 241 } 242 243 /*Set the output format*/ 244 ioctl_msg.in = &output_format; 245 ioctl_msg.out = NULL; 246 247 if (ioctl (init_decode->video_driver_fd,VDEC_IOCTL_SET_OUTPUT_FORMAT, 248 (void*)&ioctl_msg) < 0) { 249 DEBUG_PRINT("\n Set output format failed"); 250 return -1; 251 } 252 253 ioctl_msg.in = &init_decode->video_resoultion; 254 ioctl_msg.out = NULL; 255 256 if (ioctl (init_decode->video_driver_fd,VDEC_IOCTL_SET_PICRES, 257 (void*)&ioctl_msg) < 0) { 258 DEBUG_PRINT("\n Set Resolution failed"); 259 return -1; 260 } 261 262 DEBUG_PRINT("\n After Set Resolution"); 263 264 DEBUG_PRINT("\n Query Input bufffer requirements"); 265 /*Get the Buffer requirements for input and output ports*/ 266 267 init_decode->input_buffer.buffer_type = VDEC_BUFFER_TYPE_INPUT; 268 ioctl_msg.in = NULL; 269 ioctl_msg.out = &init_decode->input_buffer; 270 271 if (ioctl (init_decode->video_driver_fd,VDEC_IOCTL_GET_BUFFER_REQ, 272 (void*)&ioctl_msg) < 0) { 273 DEBUG_PRINT("\n Requesting for input buffer requirements failed"); 274 return -1; 275 } 276 277 DEBUG_PRINT("\n input Size=%d min count =%d actual count = %d", \ 278 init_decode->input_buffer.buffer_size,\ 279 init_decode->input_buffer.mincount,\ 280 init_decode->input_buffer.actualcount); 281 282 283 init_decode->input_buffer.buffer_type = VDEC_BUFFER_TYPE_INPUT; 284 ioctl_msg.in = &init_decode->input_buffer; 285 ioctl_msg.out = NULL; 286 init_decode->input_buffer.actualcount = init_decode->input_buffer.mincount + 2; 287 288 if (ioctl (init_decode->video_driver_fd,VDEC_IOCTL_SET_BUFFER_REQ, 289 (void*)&ioctl_msg) < 0) { 290 DEBUG_PRINT("\n Set Buffer Requirements Failed"); 291 return -1; 292 } 293 294 295 DEBUG_PRINT("\n Query output bufffer requirements"); 296 init_decode->output_buffer.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; 297 ioctl_msg.in = NULL; 298 ioctl_msg.out = &init_decode->output_buffer; 299 300 if (ioctl (init_decode->video_driver_fd,VDEC_IOCTL_GET_BUFFER_REQ, 301 (void*)&ioctl_msg) < 0) { 302 DEBUG_PRINT("\n Requesting for output buffer requirements failed"); 303 return -1; 304 } 305 306 DEBUG_PRINT("\n output Size=%d min count =%d actual count = %d", \ 307 init_decode->output_buffer.buffer_size,\ 308 init_decode->output_buffer.mincount,\ 309 init_decode->output_buffer.actualcount); 310 311 /*Create Queue related data structures*/ 312 queue_ptr = &init_decode->queue_context; 313 queue_ptr->commandq_size = 50; 314 queue_ptr->dataq_size = 50; 315 316 sem_init(&queue_ptr->sem_message,0, 0); 317 sem_init(&init_decode->sem_synchronize,0, 0); 318 319 pthread_mutexattr_init (&init_values); 320 pthread_mutex_init (&queue_ptr->mutex,&init_values); 321 pthread_mutex_init (&read_lock,&init_values); 322 DEBUG_PRINT("\n create Queues"); 323 queue_ptr->ptr_cmdq = (struct video_msgq*) \ 324 calloc (sizeof (struct video_msgq), 325 queue_ptr->commandq_size); 326 queue_ptr->ptr_dataq = (struct video_msgq*) \ 327 calloc (sizeof (struct video_msgq), 328 queue_ptr->dataq_size 329 ); 330 331 if ( queue_ptr->ptr_cmdq == NULL || 332 queue_ptr->ptr_dataq == NULL 333 ) { 334 return -1; 335 } 336 337 DEBUG_PRINT("\n create Threads"); 338 339 /*Create two threads*/ 340 if ( (pthread_create (&init_decode->videothread_id,NULL,video_thread, 341 init_decode) < 0) || 342 (pthread_create (&init_decode->asyncthread_id,NULL,async_thread, 343 init_decode) < 0) 344 ) { 345 return -1; 346 } 347 348 return 1; 349 } 350 351 352 353 int free_buffer ( enum vdec_buffer buffer_dir, 354 struct video_decoder_context *decode_context 355 ) 356 { 357 unsigned int buffercount = 0,i=0; 358 struct vdec_bufferpayload **ptemp = NULL; 359 360 if (decode_context == NULL) { 361 return -1; 362 } 363 364 if (buffer_dir == VDEC_BUFFER_TYPE_INPUT && decode_context->ptr_inputbuffer) { 365 buffercount = decode_context->input_buffer.actualcount; 366 ptemp = decode_context->ptr_inputbuffer; 367 368 for (i=0; i<buffercount; i++) { 369 if (ptemp [i]) { 370 if (ptemp [i]->pmem_fd != -1) { 371 munmap ( ptemp [i]->bufferaddr,ptemp [i]->mmaped_size); 372 ptemp [i]->bufferaddr = NULL; 373 close (ptemp [i]->pmem_fd); 374 } 375 376 free (ptemp [i]); 377 ptemp [i] = NULL; 378 } 379 } 380 381 free (decode_context->ptr_inputbuffer); 382 decode_context->ptr_inputbuffer = NULL; 383 } else if ( buffer_dir == VDEC_BUFFER_TYPE_OUTPUT ) { 384 buffercount = decode_context->output_buffer.actualcount; 385 ptemp = decode_context->ptr_outputbuffer; 386 387 if (decode_context->ptr_respbuffer) { 388 for (i=0; i<buffercount; i++) { 389 if (decode_context->ptr_respbuffer [i]) { 390 free (decode_context->ptr_respbuffer[i]); 391 decode_context->ptr_respbuffer [i] = NULL; 392 } 393 } 394 395 free (decode_context->ptr_respbuffer); 396 decode_context->ptr_respbuffer = NULL; 397 } 398 399 if (ptemp) { 400 for (i=0; i<buffercount; i++) { 401 if (ptemp [i]) { 402 if (ptemp [i]->pmem_fd != -1) { 403 munmap ( ptemp [i]->bufferaddr,ptemp [i]->mmaped_size); 404 ptemp [i]->bufferaddr = NULL; 405 close (ptemp [i]->pmem_fd); 406 } 407 408 free (ptemp [i]); 409 ptemp [i] = NULL; 410 } 411 } 412 413 free (ptemp); 414 decode_context->ptr_outputbuffer = NULL; 415 } 416 } 417 418 return 1; 419 } 420 421 int allocate_buffer ( enum vdec_buffer buffer_dir, 422 struct video_decoder_context *decode_context 423 ) 424 { 425 struct vdec_setbuffer_cmd setbuffers; 426 struct vdec_bufferpayload **ptemp = NULL; 427 struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; 428 unsigned int buffercount = 0,i=0,alignedsize=0; 429 unsigned int buffersize = 0; 430 431 if ( decode_context == NULL) { 432 DEBUG_PRINT ("\nallocate_buffer: context is NULL"); 433 return -1; 434 } 435 436 if ( buffer_dir == VDEC_BUFFER_TYPE_INPUT ) { 437 /*Check if buffers are allocated*/ 438 if (decode_context->ptr_inputbuffer != NULL) { 439 DEBUG_PRINT ("\nallocate_buffer: decode_context->ptr_inputbuffer is set"); 440 return -1; 441 } 442 443 buffercount = decode_context->input_buffer.actualcount; 444 alignedsize = decode_context->input_buffer.alignment; 445 buffersize = decode_context->input_buffer.buffer_size; 446 buffersize = (buffersize + alignedsize) & (~alignedsize); 447 } else if (buffer_dir == VDEC_BUFFER_TYPE_OUTPUT) { 448 /*Check if buffers are allocated*/ 449 if (decode_context->ptr_outputbuffer != NULL) { 450 DEBUG_PRINT ("\nallocate_buffer: Double allcoate output"); 451 return -1; 452 } 453 454 buffercount = decode_context->output_buffer.actualcount; 455 alignedsize = decode_context->output_buffer.alignment; 456 buffersize = decode_context->output_buffer.buffer_size; 457 buffersize = (buffersize + alignedsize) & (~alignedsize); 458 459 decode_context->ptr_respbuffer = (struct vdec_output_frameinfo **)\ 460 calloc (sizeof (struct vdec_output_frameinfo *),buffercount); 461 462 if (decode_context->ptr_respbuffer == NULL) { 463 DEBUG_PRINT ("\n Allocate failure ptr_respbuffer"); 464 return -1; 465 } 466 467 for (i=0; i< buffercount; i++) { 468 decode_context->ptr_respbuffer [i] = (struct vdec_output_frameinfo *)\ 469 calloc (sizeof (struct vdec_output_frameinfo),buffercount); 470 471 if (decode_context->ptr_respbuffer [i] == NULL) { 472 DEBUG_PRINT ("\nfailed to allocate vdec_output_frameinfo"); 473 return -1; 474 } 475 } 476 } else { 477 DEBUG_PRINT ("\nallocate_buffer: Wrong buffer directions"); 478 return -1; 479 } 480 481 ptemp = (struct vdec_bufferpayload **)\ 482 calloc (sizeof (struct vdec_bufferpayload *),buffercount); 483 484 if (ptemp == NULL) { 485 DEBUG_PRINT ("\nallocate_buffer: vdec_bufferpayload failure"); 486 return -1; 487 } 488 489 490 if (buffer_dir == VDEC_BUFFER_TYPE_OUTPUT) { 491 DEBUG_PRINT ("\nallocate_buffer: OUT"); 492 decode_context->ptr_outputbuffer = ptemp; 493 } else { 494 DEBUG_PRINT ("\nallocate_buffer: IN"); 495 decode_context->ptr_inputbuffer = ptemp; 496 } 497 498 /*Allocate buffer headers*/ 499 for (i=0; i< buffercount; i++) { 500 ptemp [i] = (struct vdec_bufferpayload*)\ 501 calloc (sizeof (struct vdec_bufferpayload),1); 502 503 if (ptemp [i] == NULL) { 504 DEBUG_PRINT ("\nallocate_buffer: ptemp [i] calloc failure"); 505 return -1; 506 } 507 508 if (buffer_dir == VDEC_BUFFER_TYPE_OUTPUT) { 509 decode_context->ptr_respbuffer [i]->client_data = \ 510 (void *) ptemp [i]; 511 } 512 513 ptemp [i]->pmem_fd = -1; 514 515 } 516 517 for (i=0; i< buffercount; i++) { 518 ptemp [i]->pmem_fd = open ("/dev/pmem_adsp",O_RDWR); 519 520 if (ptemp [i]->pmem_fd < 0) { 521 DEBUG_PRINT ("\nallocate_buffer: open pmem_adsp failed"); 522 return -1; 523 } 524 525 ptemp [i]->bufferaddr = mmap(NULL,clp2(buffersize),PROT_READ|PROT_WRITE, 526 MAP_SHARED,ptemp [i]->pmem_fd,0); 527 DEBUG_PRINT ("\n pmem fd = %d virt addr = %p",ptemp [i]->pmem_fd,\ 528 ptemp [i]->bufferaddr); 529 530 if (ptemp [i]->bufferaddr == MAP_FAILED) { 531 ptemp [i]->bufferaddr = NULL; 532 DEBUG_PRINT ("\nallocate_buffer: MMAP failed"); 533 return -1; 534 } 535 536 ptemp [i]->buffer_len = buffersize; 537 ptemp [i]->mmaped_size = clp2 (buffersize); 538 539 setbuffers.buffer_type = buffer_dir; 540 memcpy (&setbuffers.buffer,ptemp [i],sizeof (struct vdec_bufferpayload)); 541 542 ioctl_msg.in = &setbuffers; 543 ioctl_msg.out = NULL; 544 545 if (ioctl (decode_context->video_driver_fd,VDEC_IOCTL_SET_BUFFER, 546 &ioctl_msg) < 0) { 547 DEBUG_PRINT ("\nallocate_buffer: Set Buffer IOCTL failed"); 548 return -1; 549 } 550 551 } 552 553 DEBUG_PRINT ("\nallocate_buffer: Success"); 554 return 1; 555 } 556 557 558 559 int start_decoding (struct video_decoder_context *decode_context) 560 { 561 struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; 562 struct vdec_input_frameinfo frameinfo; 563 struct vdec_fillbuffer_cmd fillbuffer; 564 unsigned int i = 0; 565 unsigned int data_len =0; 566 567 memset ((unsigned char*)&frameinfo,0,sizeof (struct vdec_input_frameinfo)); 568 memset ((unsigned char*)&fillbuffer,0,sizeof (struct vdec_fillbuffer_cmd)); 569 570 if (decode_context == NULL) { 571 return -1; 572 } 573 574 if (ioctl (decode_context->video_driver_fd,VDEC_IOCTL_CMD_START, 575 NULL) < 0) { 576 DEBUG_PRINT("\n Start failed"); 577 return -1; 578 } 579 580 DEBUG_PRINT("\n Start Issued successfully waiting for Start Done"); 581 /*Wait for Start command response*/ 582 sem_wait (&decode_context->sem_synchronize); 583 584 /*Push output Buffers*/ 585 i = 0; 586 587 while (i < decode_context->output_buffer.mincount) { 588 fillbuffer.buffer.buffer_len = 589 decode_context->ptr_outputbuffer [i]->buffer_len; 590 fillbuffer.buffer.bufferaddr = 591 decode_context->ptr_outputbuffer [i]->bufferaddr; 592 fillbuffer.buffer.offset = 593 decode_context->ptr_outputbuffer [i]->offset; 594 fillbuffer.buffer.pmem_fd = 595 decode_context->ptr_outputbuffer [i]->pmem_fd; 596 fillbuffer.client_data = (void *)decode_context->ptr_respbuffer [i]; 597 DEBUG_PRINT ("\n Client Data on output = %p",fillbuffer.client_data); 598 ioctl_msg.in = &fillbuffer; 599 ioctl_msg.out = NULL; 600 601 if (ioctl (decode_context->video_driver_fd, 602 VDEC_IOCTL_FILL_OUTPUT_BUFFER,&ioctl_msg) < 0) { 603 DEBUG_PRINT("\n Decoder frame failed"); 604 return -1; 605 } 606 607 i++; 608 } 609 610 611 /*push input buffers*/ 612 i = 0; 613 614 while (i < decode_context->input_buffer.mincount) { 615 DEBUG_PRINT("\n Read Frame from File"); 616 data_len = read_frame ( decode_context->ptr_inputbuffer [i]->bufferaddr, 617 decode_context->ptr_inputbuffer [i]->buffer_len, 618 decode_context->inputBufferFile); 619 620 if (data_len == 0) { 621 DEBUG_PRINT("\n Length is zero error"); 622 return -1; 623 } 624 625 DEBUG_PRINT("\n Read Frame from File szie = %u",data_len); 626 frameinfo.bufferaddr = 627 decode_context->ptr_inputbuffer [i]->bufferaddr; 628 frameinfo.offset = 0; 629 frameinfo.pmem_fd = decode_context->ptr_inputbuffer [i]->pmem_fd; 630 frameinfo.pmem_offset = decode_context->ptr_inputbuffer [i]->offset; 631 frameinfo.datalen = data_len; 632 frameinfo.client_data = (struct vdec_bufferpayload *)\ 633 decode_context->ptr_inputbuffer [i]; 634 /*TODO: Time stamp needs to be updated*/ 635 ioctl_msg.in = &frameinfo; 636 ioctl_msg.out = NULL; 637 638 if (ioctl (decode_context->video_driver_fd,VDEC_IOCTL_DECODE_FRAME, 639 &ioctl_msg) < 0) { 640 DEBUG_PRINT("\n Decoder frame failed"); 641 return -1; 642 } 643 644 total_frames++; 645 i++; 646 } 647 648 DEBUG_PRINT ("\n Wait for EOS"); 649 /*Wait for EOS or Error condition*/ 650 sem_wait (&decode_context->sem_synchronize); 651 DEBUG_PRINT ("\n Reached EOS"); 652 653 return 1; 654 } 655 656 int stop_decoding (struct video_decoder_context *decode_context) 657 { 658 struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; 659 enum vdec_bufferflush flush_dir = VDEC_FLUSH_TYPE_INPUT; 660 661 if (decode_context == NULL) { 662 return -1; 663 } 664 665 ioctl_msg.in = &flush_dir; 666 ioctl_msg.out = NULL; 667 668 if (ioctl(decode_context->video_driver_fd,VDEC_IOCTL_CMD_FLUSH, 669 &ioctl_msg) < 0) { 670 DEBUG_PRINT("\n Flush input failed"); 671 } else { 672 sem_wait (&decode_context->sem_synchronize); 673 } 674 675 flush_dir = VDEC_FLUSH_TYPE_OUTPUT; 676 ioctl_msg.in = &flush_dir; 677 ioctl_msg.out = NULL; 678 679 if (ioctl(decode_context->video_driver_fd,VDEC_IOCTL_CMD_FLUSH, 680 &ioctl_msg) < 0) { 681 DEBUG_PRINT("\n Flush output failed"); 682 } else { 683 sem_wait (&decode_context->sem_synchronize); 684 } 685 686 DEBUG_PRINT("\n Stop VDEC_IOCTL_CMD_STOP"); 687 688 if (ioctl(decode_context->video_driver_fd,VDEC_IOCTL_CMD_STOP, 689 NULL) < 0) { 690 DEBUG_PRINT("\n Stop failed"); 691 } else { 692 sem_wait (&decode_context->sem_synchronize); 693 } 694 695 return 1; 696 } 697 698 int deinit_decoder (struct video_decoder_context *init_decode) 699 { 700 if (init_decode == NULL) { 701 return -1; 702 } 703 704 /*Close the driver*/ 705 if (init_decode->video_driver_fd != -1) { 706 close (init_decode->video_driver_fd); 707 } 708 709 if (init_decode->queue_context.ptr_cmdq) { 710 free (init_decode->queue_context.ptr_cmdq); 711 init_decode->queue_context.ptr_cmdq = NULL; 712 } 713 714 if (init_decode->queue_context.ptr_dataq) { 715 free (init_decode->queue_context.ptr_dataq); 716 init_decode->queue_context.ptr_dataq = NULL; 717 } 718 719 sem_destroy (&init_decode->queue_context.sem_message); 720 sem_destroy (&init_decode->sem_synchronize); 721 722 pthread_mutex_destroy(&init_decode->queue_context.mutex); 723 pthread_mutex_destroy (&read_lock); 724 725 return 1; 726 } 727 728 static void* video_thread (void *context) 729 { 730 struct video_decoder_context *decode_context = NULL; 731 struct video_msgq *queueitem = NULL; 732 struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; 733 struct vdec_input_frameinfo frameinfo; 734 struct vdec_fillbuffer_cmd fillbuffer; 735 struct vdec_output_frameinfo *outputbuffer = NULL; 736 struct vdec_bufferpayload *tempbuffer = NULL; 737 unsigned int data_len =0; 738 739 740 if (context == NULL) { 741 DEBUG_PRINT("\n video thread recieved NULL context"); 742 return NULL; 743 } 744 745 decode_context = (struct video_decoder_context *) context; 746 747 /* Thread function which will accept commands from async thread 748 * or main thread 749 */ 750 while (1) { 751 queueitem = queue_get_cmd (&decode_context ->queue_context); 752 753 if (queueitem != NULL) { 754 switch (queueitem->cmd) { 755 case VDEC_MSG_EVT_HW_ERROR: 756 DEBUG_PRINT("\n FATAL ERROR "); 757 break; 758 case VDEC_MSG_RESP_INPUT_FLUSHED: 759 DEBUG_PRINT("\n Input Buffer Flushed"); 760 break; 761 case VDEC_MSG_RESP_OUTPUT_FLUSHED: 762 DEBUG_PRINT("\n Output buffer Flushed"); 763 break; 764 case VDEC_MSG_RESP_START_DONE: 765 DEBUG_PRINT("\n recived start done command"); 766 sem_post (&decode_context->sem_synchronize); 767 break; 768 769 case VDEC_MSG_RESP_STOP_DONE: 770 DEBUG_PRINT("\n recieved stop done"); 771 sem_post (&decode_context->sem_synchronize); 772 break; 773 774 case VDEC_MSG_RESP_INPUT_BUFFER_DONE: 775 776 tempbuffer = (struct vdec_bufferpayload *)queueitem->clientdata; 777 778 if (tempbuffer == NULL) { 779 DEBUG_PRINT("\n FATAL ERROR input buffer address is bad"); 780 sem_post (&decode_context->sem_synchronize); 781 break; 782 } 783 784 data_len = read_frame ( tempbuffer->bufferaddr, 785 tempbuffer->buffer_len, 786 decode_context->inputBufferFile 787 ); 788 789 if (data_len == 0) { 790 DEBUG_PRINT ("\n End of stream reached"); 791 sem_post (&decode_context->sem_synchronize); 792 break; 793 } 794 795 frameinfo.bufferaddr = tempbuffer->bufferaddr; 796 frameinfo.offset = 0; 797 frameinfo.pmem_fd = tempbuffer->pmem_fd; 798 frameinfo.pmem_offset = tempbuffer->offset; 799 frameinfo.datalen = data_len; 800 frameinfo.client_data = (struct vdec_bufferpayload *)\ 801 tempbuffer; 802 /*TODO: Time stamp needs to be updated*/ 803 ioctl_msg.in = &frameinfo; 804 ioctl_msg.out = NULL; 805 total_frames++; 806 807 if (ioctl(decode_context->video_driver_fd,VDEC_IOCTL_DECODE_FRAME, 808 &ioctl_msg) < 0) { 809 DEBUG_PRINT("\n Decoder frame failed"); 810 sem_post (&decode_context->sem_synchronize); 811 } 812 813 DEBUG_PRINT("\n Input buffer done send next buffer current value = %d",\ 814 total_frames); 815 break; 816 817 case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE: 818 819 outputbuffer = (struct vdec_output_frameinfo *)\ 820 queueitem->clientdata; 821 DEBUG_PRINT("\n Value of client Data in VT %p",queueitem->clientdata); 822 823 if (outputbuffer == NULL || outputbuffer->bufferaddr == NULL || 824 outputbuffer->client_data == NULL 825 ) { 826 DEBUG_PRINT("\n FATAL ERROR output buffer is bad"); 827 DEBUG_PRINT("\nValues outputbuffer = %p",outputbuffer); 828 829 if (outputbuffer != NULL) { 830 DEBUG_PRINT("\nValues outputbuffer->bufferaddr = %p",\ 831 outputbuffer->bufferaddr); 832 DEBUG_PRINT("\nValues outputbuffer->client_data = %p",\ 833 outputbuffer->client_data); 834 } 835 836 sem_post (&decode_context->sem_synchronize); 837 break; 838 } 839 840 841 if (outputbuffer->len == 0) { 842 DEBUG_PRINT("\n Filled Length is zero Close decoding"); 843 sem_post (&decode_context->sem_synchronize); 844 break; 845 } 846 847 if (decode_context->outputBufferFile != NULL) { 848 fwrite (outputbuffer->bufferaddr,1,outputbuffer->len, 849 decode_context->outputBufferFile); 850 } 851 852 tempbuffer = (struct vdec_bufferpayload *)\ 853 outputbuffer->client_data; 854 855 DEBUG_PRINT("\n recieved output buffer consume outbuffer"); 856 DEBUG_PRINT("\nValues outputbuffer->bufferaddr = %p",\ 857 outputbuffer->bufferaddr); 858 DEBUG_PRINT ("\n Vir address of allocated buffer %p",\ 859 tempbuffer->bufferaddr); 860 fillbuffer.buffer.buffer_len = tempbuffer->buffer_len; 861 fillbuffer.buffer.bufferaddr = tempbuffer->bufferaddr; 862 fillbuffer.buffer.offset = tempbuffer->offset; 863 fillbuffer.buffer.pmem_fd = tempbuffer->pmem_fd; 864 fillbuffer.client_data = (void *)outputbuffer; 865 866 ioctl_msg.in = &fillbuffer; 867 ioctl_msg.out = NULL; 868 869 if (ioctl (decode_context->video_driver_fd, 870 VDEC_IOCTL_FILL_OUTPUT_BUFFER,&ioctl_msg) < 0) { 871 DEBUG_PRINT("\n Decoder frame failed"); 872 return NULL; 873 } 874 875 break; 876 877 case VDEC_MSG_RESP_FLUSH_INPUT_DONE: 878 DEBUG_PRINT("\n Flush input complete"); 879 sem_post (&decode_context->sem_synchronize); 880 break; 881 882 case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE: 883 DEBUG_PRINT("\n Flush output complete"); 884 sem_post (&decode_context->sem_synchronize); 885 break; 886 } 887 888 if (queueitem->cmd == VDEC_MSG_RESP_STOP_DONE) { 889 DEBUG_PRINT("\n Playback has ended thread will exit"); 890 return NULL; 891 } 892 } else { 893 DEBUG_PRINT("\n Error condition recieved NULL from Queue"); 894 } 895 896 } 897 } 898 899 static void* async_thread (void *context) 900 { 901 struct video_decoder_context *decode_context = NULL; 902 struct vdec_output_frameinfo *outputframe = NULL; 903 struct video_msgq queueitem ; 904 struct vdec_msginfo vdec_msg; 905 struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; 906 int result = -1; 907 908 if (context == NULL) { 909 DEBUG_PRINT("\n aynsc thread recieved NULL context"); 910 return NULL; 911 } 912 913 decode_context = (struct video_decoder_context *) context; 914 DEBUG_PRINT("\n Entering the async thread"); 915 916 while (1) { 917 ioctl_msg.in = NULL; 918 919 ioctl_msg.out = (void*)&vdec_msg; 920 DEBUG_PRINT ("\n Sizeof vdec_msginfo = %d ",sizeof (vdec_msg)); 921 DEBUG_PRINT("\n Address of Vdec msg in async thread %p",\ 922 ioctl_msg.out); 923 924 if (ioctl (decode_context->video_driver_fd,VDEC_IOCTL_GET_NEXT_MSG,\ 925 (void*)&ioctl_msg) < 0) { 926 DEBUG_PRINT("\n Error in ioctl read next msg"); 927 } else { 928 switch (vdec_msg.msgcode) { 929 case VDEC_MSG_RESP_FLUSH_INPUT_DONE: 930 case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE: 931 case VDEC_MSG_RESP_START_DONE: 932 case VDEC_MSG_RESP_STOP_DONE: 933 case VDEC_MSG_EVT_HW_ERROR: 934 DEBUG_PRINT("\nioctl read next msg"); 935 queueitem.cmd = vdec_msg.msgcode; 936 queueitem.status = vdec_msg.status_code; 937 queueitem.clientdata = NULL; 938 break; 939 940 case VDEC_MSG_RESP_INPUT_FLUSHED: 941 case VDEC_MSG_RESP_INPUT_BUFFER_DONE: 942 943 queueitem.cmd = vdec_msg.msgcode; 944 queueitem.status = vdec_msg.status_code; 945 queueitem.clientdata = (void *)\ 946 vdec_msg.msgdata.input_frame_clientdata; 947 break; 948 949 case VDEC_MSG_RESP_OUTPUT_FLUSHED: 950 case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE: 951 queueitem.cmd = vdec_msg.msgcode; 952 queueitem.status = vdec_msg.status_code; 953 outputframe = (struct vdec_output_frameinfo *)\ 954 vdec_msg.msgdata.output_frame.client_data; 955 DEBUG_PRINT ("\n Client Data value in %p", \ 956 vdec_msg.msgdata.output_frame.client_data); 957 outputframe->bufferaddr = vdec_msg.msgdata.output_frame.bufferaddr; 958 outputframe->framesize.bottom = \ 959 vdec_msg.msgdata.output_frame.framesize.bottom; 960 outputframe->framesize.left = \ 961 vdec_msg.msgdata.output_frame.framesize.left; 962 outputframe->framesize.right = \ 963 vdec_msg.msgdata.output_frame.framesize.right; 964 outputframe->framesize.top = \ 965 vdec_msg.msgdata.output_frame.framesize.top; 966 outputframe->framesize = vdec_msg.msgdata.output_frame.framesize; 967 outputframe->len = vdec_msg.msgdata.output_frame.len; 968 outputframe->time_stamp = vdec_msg.msgdata.output_frame.time_stamp; 969 queueitem.clientdata = (void *)outputframe; 970 DEBUG_PRINT ("\n Client Data value Copy %p",queueitem.clientdata); 971 break; 972 973 default: 974 DEBUG_PRINT("\nIn Default of get next message %d",vdec_msg.msgcode); 975 queueitem.cmd = vdec_msg.msgcode; 976 queueitem.status = vdec_msg.status_code; 977 queueitem.clientdata = NULL; 978 break; 979 } 980 981 result = queue_post_cmdq (&decode_context->queue_context,&queueitem); 982 983 while (result == 0) { 984 result = queue_post_cmdq (&decode_context->queue_context, 985 &queueitem); 986 } 987 988 if (result == -1) { 989 DEBUG_PRINT("\n FATAL ERROR WITH Queue"); 990 } 991 } 992 993 if (vdec_msg.msgcode == VDEC_MSG_RESP_STOP_DONE) { 994 /*Thread can exit at this point*/ 995 return NULL; 996 } 997 } 998 } 999 1000 1001 static unsigned int read_frame (unsigned char *dataptr, unsigned int length, 1002 FILE * inputBufferFile) 1003 { 1004 1005 unsigned int readOffset = 0; 1006 int bytes_read = 0; 1007 unsigned int code = 0; 1008 int found = 0; 1009 1010 DEBUG_PRINT ("\n Inside the readframe"); 1011 1012 if (dataptr == NULL || length == 0) { 1013 DEBUG_PRINT ("\n dataptr = %p length = %u",dataptr,length); 1014 return 0; 1015 } 1016 1017 if (!Code_type) { 1018 /* Start of Critical Section*/ 1019 pthread_mutex_lock(&read_lock); 1020 1021 do { 1022 //Start codes are always byte aligned. 1023 bytes_read = fread(&dataptr[readOffset],1, 1,inputBufferFile); 1024 1025 if ( !bytes_read) { 1026 DEBUG_PRINT("\n Bytes read Zero \n"); 1027 break; 1028 } 1029 1030 code <<= 8; 1031 code |= (0x000000FF & dataptr[readOffset]); 1032 1033 //VOP start code comparision 1034 if (readOffset>3) { 1035 if (!header_code ) { 1036 if ( VOP_START_CODE == code) { 1037 DEBUG_PRINT ("\n Found VOP Code"); 1038 header_code = VOP_START_CODE; 1039 } else if ( (0xFFFFFC00 & code) == SHORT_HEADER_START_CODE ) { 1040 header_code = SHORT_HEADER_START_CODE; 1041 } 1042 } 1043 1044 if ((header_code == VOP_START_CODE) && (code == VOP_START_CODE)) { 1045 //Seek backwards by 4 1046 fseek(inputBufferFile, -4, SEEK_CUR); 1047 readOffset-=4; 1048 found = 1; 1049 break; 1050 1051 } else if (( header_code == SHORT_HEADER_START_CODE ) && 1052 ( SHORT_HEADER_START_CODE == (code & 0xFFFFFC00))) { 1053 //Seek backwards by 4 1054 fseek(inputBufferFile, -4, SEEK_CUR); 1055 readOffset-=4; 1056 found = 1; 1057 break; 1058 } 1059 } 1060 1061 readOffset++; 1062 } while (readOffset < length); 1063 1064 pthread_mutex_unlock(&read_lock); 1065 1066 /* End of Critical Section*/ 1067 if (found == 1) { 1068 //DEBUG_PRINT ("Found a Frame"); 1069 return (readOffset+1); 1070 } else { 1071 //DEBUG_PRINT ("No Frames detected"); 1072 return 0; 1073 } 1074 } else { 1075 1076 readOffset = Read_Buffer_From_DAT_File(dataptr,length,inputBufferFile); 1077 1078 if (total_frames == 0) { 1079 bytes_read = Read_Buffer_From_DAT_File(&dataptr[readOffset], 1080 (length-readOffset), 1081 inputBufferFile); 1082 readOffset += bytes_read; 1083 } 1084 1085 return (readOffset); 1086 } 1087 1088 } 1089 1090 static int Read_Buffer_From_DAT_File(unsigned char *dataptr, unsigned int length, 1091 FILE * inputBufferFile) 1092 { 1093 1094 1095 long frameSize=0; 1096 char temp_buffer[10]; 1097 char temp_byte; 1098 int bytes_read=0; 1099 int i=0; 1100 unsigned char *read_buffer=NULL; 1101 char c = '1'; //initialize to anything except '\0'(0) 1102 char inputFrameSize[12]; 1103 int count =0; 1104 char cnt =0; 1105 memset(temp_buffer, 0, sizeof(temp_buffer)); 1106 1107 while (cnt < 10) 1108 /* Check the input file format, may result in infinite loop */ 1109 { 1110 count = fread(&inputFrameSize[cnt],1,1,inputBufferFile); 1111 1112 if (inputFrameSize[cnt] == '\0' ) 1113 break; 1114 1115 cnt++; 1116 } 1117 1118 inputFrameSize[cnt]='\0'; 1119 frameSize = atoi(inputFrameSize); 1120 //length = 0; 1121 DEBUG_PRINT ("\n Frame Size is %d",frameSize); 1122 1123 /* get the frame length */ 1124 fseek(inputBufferFile, -1, SEEK_CUR); 1125 bytes_read = fread(dataptr, 1, frameSize, inputBufferFile); 1126 1127 if (bytes_read == 0 || bytes_read < frameSize ) { 1128 return 0; 1129 } 1130 1131 return bytes_read; 1132 } 1133