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