1/*--------------------------------------------------------------------------
2Copyright (c) 2010-2011, 2013, The Linux Foundation. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, 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
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26ADVISED 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
43static int Code_type;
44static int total_frames = 0;
45static unsigned int header_code = 0;
46static pthread_mutex_t read_lock;
47
48static unsigned int read_frame ( unsigned char *dataptr,unsigned int length,
49        FILE * inputBufferFile
50        );
51static int Read_Buffer_From_DAT_File( unsigned char *dataptr, unsigned int length,
52        FILE * inputBufferFile
53        );
54
55static 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
66static void* video_thread (void *);
67static void* async_thread (void *);
68
69int 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
207int 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
353int 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
421int 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
559int 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
656int 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
698int 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
728static 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
899static 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
1001static 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
1090static 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