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