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
clp2(unsigned x)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
main(int argc,char ** argv)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
init_decoder(struct video_decoder_context * init_decode)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
free_buffer(enum vdec_buffer buffer_dir,struct video_decoder_context * decode_context)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
allocate_buffer(enum vdec_buffer buffer_dir,struct video_decoder_context * decode_context)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
start_decoding(struct video_decoder_context * decode_context)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
stop_decoding(struct video_decoder_context * decode_context)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
deinit_decoder(struct video_decoder_context * init_decode)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
video_thread(void * context)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
async_thread(void * context)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
read_frame(unsigned char * dataptr,unsigned int length,FILE * inputBufferFile)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
Read_Buffer_From_DAT_File(unsigned char * dataptr,unsigned int length,FILE * inputBufferFile)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 unsigned int 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 %ld",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