diff options
author | prasanth kamuju <prasanth.kamuju@linaro.org> | 2014-07-02 15:40:04 +0530 |
---|---|---|
committer | prasanth kamuju <prasanth.kamuju@linaro.org> | 2014-07-02 15:40:04 +0530 |
commit | cd8b9a06d8019752b0784fdb7037a8a518a132b1 (patch) | |
tree | c5949ef9a4a560543773ad8053ec0a8e540ae470 | |
parent | 46a430b4d2003ca6cc746437d9ee3c4cb8d348af (diff) |
Support for H264 decoding
H264 decoding functionality added, it will take the H264
bit-stream as input and generate yuv format output file.
-rwxr-xr-x | decodertest/decoder_driver_test.c | 351 | ||||
-rwxr-xr-x | decodertest/decoder_driver_test.h | 13 |
2 files changed, 344 insertions, 20 deletions
diff --git a/decodertest/decoder_driver_test.c b/decodertest/decoder_driver_test.c index 935a9ab..74ebfaf 100755 --- a/decodertest/decoder_driver_test.c +++ b/decodertest/decoder_driver_test.c @@ -45,7 +45,7 @@ static int Code_type; static int total_frames = 0; static unsigned int header_code = 0; static pthread_mutex_t read_lock; - +int reconfig =0; static unsigned int read_frame ( unsigned char *dataptr,unsigned int length, FILE * inputBufferFile ); @@ -75,8 +75,10 @@ int main (int argc, char **argv) FILE *file_ptr = NULL; int temp1 =0,temp2 =0; int error = 1; - unsigned int i = 0; + unsigned int i = 0,type=0; + reconfig = 0; + memset(&h264_mv_buff,0,sizeof(struct h264_mv_buffer)); /* Allocate memory for the decode context */ decoder_context = (struct video_decoder_context *) \ calloc (sizeof (struct video_decoder_context),1); @@ -117,10 +119,22 @@ int main (int argc, char **argv) } /*As of now decoder type,frame_height and frame_width are hardcoded */ - decoder_context->decoder_format = VDEC_CODECTYPE_MPEG4; - Code_type = 0; - decoder_context->video_resoultion.frame_height = 480; - decoder_context->video_resoultion.frame_width = 640; + type = atoi(argv [2]); + if(type == 1) + { + decoder_context->decoder_format = VDEC_CODECTYPE_MPEG4; + DEBUG_PRINT("\n codec format VDEC_CODECTYPE_MPEG4"); + Code_type = VDEC_CODECTYPE_MPEG4; + } + else if(type == 2) + { + DEBUG_PRINT("\n codec format VDEC_CODECTYPE_H264 "); + decoder_context->decoder_format = VDEC_CODECTYPE_H264; + Code_type = VDEC_CODECTYPE_H264; + } + // Code_type = atoi(argv [3]); + decoder_context->video_resoultion.frame_height = atoi(argv [3]); + decoder_context->video_resoultion.frame_width = atoi(argv [4]); /* All the inputs are all right now, start the decode */ @@ -233,12 +247,7 @@ int init_decoder ( struct video_decoder_context *init_decode ) return -1; } - if(ioctl(init_decode->video_driver_fd,VDEC_IOCTL_SET_CONT_ON_RECONFIG) < 0) - { - DEBUG_PRINT("\n ========== VDEC_IOCTL_SET_CONT_ON_RECONFIG FAILED...."); - } - - /*Set the output format*/ + /*Set the output format*/ ioctl_msg.in = &output_format; ioctl_msg.out = NULL; @@ -317,6 +326,15 @@ int init_decoder ( struct video_decoder_context *init_decode ) init_decode->output_buffer.buf_poolid,\ init_decode->output_buffer.meta_buffer_size); +/* init_decode->disable_dmx = 0; + ioctl_msg.in = NULL; + ioctl_msg.out = &init_decode->disable_dmx; + if (ioctl(init_decode->video_driver_fd, VDEC_IOCTL_GET_DISABLE_DMX_SUPPORT, &ioctl_msg)) + { + DEBUG_PRINT("Error VDEC_IOCTL_GET_DISABLE_DMX_SUPPORT"); + return -1; + } +*/ /*Create Queue related data structures*/ queue_ptr = &init_decode->queue_context; queue_ptr->commandq_size = 50; @@ -365,6 +383,8 @@ int free_buffer ( enum vdec_buffer buffer_dir, { unsigned int buffercount = 0,i=0; struct vdec_bufferpayload *ptemp = NULL; + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + struct vdec_setbuffer_cmd setbuffers; if (decode_context == NULL) { @@ -393,11 +413,51 @@ int free_buffer ( enum vdec_buffer buffer_dir, buffercount = decode_context->output_buffer.actualcount; ptemp = decode_context->ptr_outputbuffer; + /* free mv buffers */ + if(h264_mv_buff.pmem_fd > 0) + { + if(ioctl(decode_context->video_driver_fd, VDEC_IOCTL_FREE_H264_MV_BUFFER,NULL) < 0) + DEBUG_PRINT("VDEC_IOCTL_FREE_H264_MV_BUFFER failed"); + munmap(h264_mv_buff.buffer, h264_mv_buff.size); + + if (close(decode_context->h264_mv.fd_ion_data.fd)) { + DEBUG_PRINT("\n ION: close(%d) failed", + decode_context->h264_mv.fd_ion_data.fd); + } + if(ioctl(decode_context->h264_mv.ion_device_fd,ION_IOC_FREE, + &decode_context->h264_mv.ion_alloc_data.handle)) { + DEBUG_PRINT("\n ION: free failed, dev_fd = %d, handle = 0x%p", + decode_context->h264_mv.ion_device_fd, decode_context->h264_mv.ion_alloc_data.handle); + } + decode_context->h264_mv.ion_device_fd = -1; + decode_context->h264_mv.ion_alloc_data.handle = NULL; + decode_context->h264_mv.fd_ion_data.fd = -1; + + DEBUG_PRINT("Cleaning H264_MV buffer of size %d",h264_mv_buff.size); + h264_mv_buff.pmem_fd = -1; + h264_mv_buff.offset = 0; + h264_mv_buff.size = 0; + h264_mv_buff.count = 0; + h264_mv_buff.buffer = NULL; + } + /* free output buffers */ + ioctl_msg.in = &decode_context->output_buffer; + ioctl_msg.out = NULL; for (i=0;i<buffercount;i++) { if (ptemp [i].pmem_fd != -1) { + setbuffers.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; + memcpy (&setbuffers.buffer,&decode_context->ptr_outputbuffer[i],sizeof (struct vdec_bufferpayload)); + ioctl_msg.in = &setbuffers; + ioctl_msg.out = NULL; + + if (ioctl (decode_context->video_driver_fd, VDEC_IOCTL_FREE_BUFFER, + &ioctl_msg) < 0) + { + DEBUG_PRINT("\n Release output buffer failed in VCD"); + } munmap ( ptemp [i].bufferaddr,ptemp [i].mmaped_size); ptemp [i].bufferaddr = NULL; close (ptemp [i].pmem_fd); @@ -795,7 +855,172 @@ int deinit_decoder (struct video_decoder_context *init_decode) DEBUG_PRINT("\n all threads are closed"); return 1; } +int test_vdec_alloc_h264_mv(void *context) +{ + int pmem_fd = -1,fd=-1,rc=-1; + int width, height, size, alignment; + void *buf_addr = NULL; + struct vdec_ioctl_msg ioctl_msg; + // struct pmem_allocation allocation; + struct vdec_h264_mv h264_mv; + struct vdec_mv_buff_size mv_buff_size; + struct video_decoder_context *decode_context = NULL; + + decode_context = (struct video_decoder_context *) context; + + decode_context->video_resoultion.stride = decode_context->video_resoultion.frame_width; + decode_context->video_resoultion.scan_lines = decode_context->video_resoultion.frame_height; + + mv_buff_size.width = decode_context->video_resoultion.stride; + mv_buff_size.height = decode_context->video_resoultion.scan_lines>>2; + + ioctl_msg.in = NULL; + ioctl_msg.out = (void*)&mv_buff_size; + + if (ioctl (decode_context->video_driver_fd,VDEC_IOCTL_GET_MV_BUFFER_SIZE, (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT("\n GET_MV_BUFFER_SIZE Failed for width: %d, Height %d" , + mv_buff_size.width, mv_buff_size.height); + return -1; + } + + DEBUG_PRINT("\nGET_MV_BUFFER_SIZE returned: Size: %d and alignment: %d", + mv_buff_size.size, mv_buff_size.alignment); + + size = mv_buff_size.size * decode_context->output_buffer.actualcount; + alignment = mv_buff_size.alignment; + + DEBUG_PRINT("\nEntered vdec_alloc_h264_mv act_width: %d, act_height: %d, size: %d, alignment %d", + decode_context->video_resoultion.frame_width, decode_context->video_resoultion.frame_height,size,alignment); + + struct ion_allocation_data *alloc_data = &decode_context->h264_mv.ion_alloc_data; + struct ion_fd_data *fd_data = &decode_context->h264_mv.fd_ion_data; + fd = m_vdec_ion_devicefd; + alloc_data->len = size; + alloc_data->flags = 0x1; + alloc_data->align = 8196; + alloc_data->heap_mask = 0x2000000; + rc = ioctl(fd,ION_IOC_ALLOC,alloc_data); + if (rc || !alloc_data->handle) { + DEBUG_PRINT("\n ION ALLOC failed, fd = %d, rc = %d, handle = 0x%p, " + "errno ", fd, rc, alloc_data->handle); + alloc_data->handle = NULL; + return -1; + } + fd_data->handle = alloc_data->handle; + rc = ioctl(fd,ION_IOC_MAP,fd_data); + if (rc) { + DEBUG_PRINT("\n ION MAP failed, fd = %d, handle = 0x%p, errno =", + fd, fd_data->handle); + fd_data->fd = -1; + return -1; + } + decode_context->h264_mv.ion_device_fd = fd; + pmem_fd = decode_context->h264_mv.fd_ion_data.fd; + + buf_addr = mmap(NULL, size, + PROT_READ | PROT_WRITE, + MAP_SHARED, pmem_fd, 0); + + if (buf_addr == (void*) MAP_FAILED) + { + pmem_fd = -1; + DEBUG_PRINT("Error returned in allocating recon buffers buf_addr: %p\n",buf_addr); + return -1; + } + DEBUG_PRINT("Allocated virt:%p, FD: %d of size %d count: %d", buf_addr, + pmem_fd, size, decode_context->output_buffer.actualcount); + + h264_mv.size = size; + h264_mv.count = decode_context->output_buffer.actualcount; + h264_mv.pmem_fd = pmem_fd; + h264_mv.offset = 0; + + ioctl_msg.in = (void*)&h264_mv; + ioctl_msg.out = NULL; + + if (ioctl (decode_context->video_driver_fd,VDEC_IOCTL_SET_H264_MV_BUFFER, (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT("Failed to set the H264_mv_buffers\n"); + return -1; + } + + h264_mv_buff.buffer = (unsigned char *) buf_addr; + h264_mv_buff.size = size; + h264_mv_buff.count = decode_context->output_buffer.actualcount; + h264_mv_buff.offset = 0; + h264_mv_buff.pmem_fd = pmem_fd; + DEBUG_PRINT("Saving virt:%p, FD: %d of size %d count: %d", h264_mv_buff.buffer, + h264_mv_buff.pmem_fd, h264_mv_buff.size, decode_context->output_buffer.actualcount); + return 1; +} + +int allocate_reconfig_buff(void *context) +{ + struct vdec_ioctl_msg ioctl_msg = {NULL,NULL}; + struct video_decoder_context *decode_context = NULL; + struct vdec_input_frameinfo frameinfo; + struct vdec_fillbuffer_cmd fillbuffer; + unsigned int i = 0; + unsigned int data_len =0; + + memset ((unsigned char*)&frameinfo,0,sizeof (struct vdec_input_frameinfo)); + memset ((unsigned char*)&fillbuffer,0,sizeof (struct vdec_fillbuffer_cmd)); + + decode_context = (struct video_decoder_context *) context; + decode_context->output_buffer.buffer_type = VDEC_BUFFER_TYPE_OUTPUT; + ioctl_msg.in = NULL; + ioctl_msg.out = &decode_context->output_buffer; + + if (ioctl (decode_context->video_driver_fd,VDEC_IOCTL_GET_BUFFER_REQ, + (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT("\n 2nd time Requesting for output buffer requirements failed"); + return -1; + } + + DEBUG_PRINT("\n 2nd time output_buffer Size=%d min count =%d actual count = %d, maxcount = %d,alignment = %d,buf_poolid= %ld,meta_buffer_size=%d\n\n",\ + decode_context->output_buffer.buffer_size,\ + decode_context->output_buffer.mincount,\ + decode_context->output_buffer.actualcount,\ + decode_context->output_buffer.maxcount,\ + decode_context->output_buffer.alignment,\ + decode_context->output_buffer.buf_poolid,\ + decode_context->output_buffer.meta_buffer_size); + test_vdec_alloc_h264_mv(decode_context); + if ((ion_allocate_buffer(VDEC_BUFFER_TYPE_OUTPUT, + decode_context)== -1)) + { + DEBUG_PRINT("\n Error in output Buffer allocation"); + } + i = 0; + while (i < decode_context->output_buffer.mincount) + { + fillbuffer.buffer.buffer_len = + decode_context->ptr_outputbuffer [i].buffer_len; + fillbuffer.buffer.bufferaddr = + decode_context->ptr_outputbuffer [i].bufferaddr; + fillbuffer.buffer.offset = + decode_context->ptr_outputbuffer [i].offset; + fillbuffer.buffer.pmem_fd = + decode_context->ptr_outputbuffer [i].pmem_fd; + fillbuffer.client_data = (void *)&decode_context->ptr_respbuffer[i]; + DEBUG_PRINT ("\n Client Data on output = %p and bufferaddr = %p",fillbuffer.client_data,decode_context->ptr_outputbuffer [i].bufferaddr); + ioctl_msg.in = &fillbuffer; + ioctl_msg.out = NULL; + + if (ioctl (decode_context->video_driver_fd, + VDEC_IOCTL_FILL_OUTPUT_BUFFER,&ioctl_msg) < 0) + { + DEBUG_PRINT("\n Decoder frame failed"); + return -1; + } + i++; + } + + return 1; +} static void* video_thread (void *context) { struct video_decoder_context *decode_context = NULL; @@ -829,10 +1054,10 @@ static void* video_thread (void *context) DEBUG_PRINT("\n FATAL ERROR "); break; case VDEC_MSG_RESP_INPUT_FLUSHED: - DEBUG_PRINT("\n Input Buffer Flushed"); +// DEBUG_PRINT("\n Input Buffer Flushed"); break; case VDEC_MSG_RESP_OUTPUT_FLUSHED: - DEBUG_PRINT("\n Output buffer Flushed"); +// DEBUG_PRINT("\n Output buffer Flushed"); break; case VDEC_MSG_RESP_START_DONE: DEBUG_PRINT("\n recived start done command"); @@ -887,7 +1112,19 @@ static void* video_thread (void *context) DEBUG_PRINT("\n Input buffer done send next buffer current value = %d",\ total_frames); break; -// case VDEC_MSG_EVT_CONFIG_CHANGED: + + case VDEC_MSG_EVT_CONFIG_CHANGED: + reconfig =1; + + ioctl_msg.in = &decode_context->output_buffer; + ioctl_msg.out = NULL; + if (ioctl(decode_context->video_driver_fd, VDEC_IOCTL_CMD_FLUSH, &ioctl_msg) < 0) + { + DEBUG_PRINT("\n >>>>>>>>>>> Flush Port (%d) Failed "); + } + (void)free_buffer(VDEC_BUFFER_TYPE_OUTPUT,decode_context); + break; + case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE: outputbuffer = (struct vdec_output_frameinfo *)\ queueitem->clientdata; @@ -950,8 +1187,15 @@ static void* video_thread (void *context) break; case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE: - DEBUG_PRINT("\n Flush output complete"); - sem_post (&decode_context->sem_synchronize); + DEBUG_PRINT("\n ---------- Flush output complete -----------------"); + if(reconfig == 1) + { + allocate_reconfig_buff(decode_context); + DEBUG_PRINT("\n ---------- reconfig set to 0 -----------------"); + reconfig = 0; + } + else + sem_post (&decode_context->sem_synchronize); break; default : DEBUG_PRINT("\n Video thread default case:: \n"); @@ -1087,7 +1331,7 @@ static unsigned int read_frame (unsigned char *dataptr, unsigned int length, return 0; } - if (!Code_type) + if (Code_type == VDEC_CODECTYPE_MPEG4) { /* Start of Critical Section*/ pthread_mutex_lock(&read_lock); @@ -1102,7 +1346,6 @@ static unsigned int read_frame (unsigned char *dataptr, unsigned int length, } code <<= 8; code |= (0x000000FF & dataptr[readOffset]); - //VOP start code comparision if (readOffset>3) { @@ -1110,11 +1353,11 @@ static unsigned int read_frame (unsigned char *dataptr, unsigned int length, { if( VOP_START_CODE == code) { + DEBUG_PRINT ("\n Found VOP Code"); header_code = VOP_START_CODE; } else if ( (0xFFFFFC00 & code) == SHORT_HEADER_START_CODE ) { - DEBUG_PRINT ("\n prasanth Found SHORT_HEADER_START_CODE"); header_code = SHORT_HEADER_START_CODE; } } @@ -1143,6 +1386,74 @@ static unsigned int read_frame (unsigned char *dataptr, unsigned int length, /* End of Critical Section*/ if (found == 1) { + //DEBUG_PRINT ("Found a Frame"); + return (readOffset+1); + } + else + { + //DEBUG_PRINT ("No Frames detected"); + return 0; + } + } + else if (Code_type == VDEC_CODECTYPE_H264) + { + /* Start of Critical Section*/ + pthread_mutex_lock(&read_lock); + do + { + //Start codes are always byte aligned. + bytes_read = fread(&dataptr[readOffset],1, 1,inputBufferFile); + if( !bytes_read) + { + DEBUG_PRINT("\n Bytes read Zero \n"); + break; + } + code <<= 8; + code |= (0x000000FF & dataptr[readOffset]); + + //VOP start code comparision + if (readOffset>3) + { + if(!header_code ) + { + if( H264_START_CODE == code) + { + header_code = H264_START_CODE; + } + else if ( (0xFFFFFC00 & code) == SHORT_HEADER_START_CODE ) + { + DEBUG_PRINT ("\n prasanth Found SHORT_HEADER_START_CODE"); + header_code = SHORT_HEADER_START_CODE; + } + } + //DEBUG_PRINT ("\n prasanth code : 0x%x",code); + if ((header_code == H264_START_CODE) && (code == H264_START_CODE)) + { + //Seek backwards by 4 + fseek(inputBufferFile, -4, SEEK_CUR); + readOffset-=4; + found = 1; + DEBUG_PRINT ("\n ---------- prasanth code detected : 0x%x",code); + break; + + } + /* else if (( header_code == SHORT_HEADER_START_CODE ) && + ( SHORT_HEADER_START_CODE == (code & 0xFFFFFC00))) + { + //Seek backwards by 4 + fseek(inputBufferFile, -4, SEEK_CUR); + readOffset-=4; + found = 1; + break; + }*/ + + } + readOffset++; + }while (readOffset < length); + pthread_mutex_unlock(&read_lock); + /* End of Critical Section*/ + if (found == 1) + { DEBUG_PRINT ("\nread_frame Found a Frame adn length : %d, code : 0x%x",readOffset,code); return (readOffset+1); } diff --git a/decodertest/decoder_driver_test.h b/decodertest/decoder_driver_test.h index cbdddaf..9296b47 100755 --- a/decodertest/decoder_driver_test.h +++ b/decodertest/decoder_driver_test.h @@ -45,6 +45,15 @@ struct vdec_ion struct ion_allocation_data ion_alloc_data; }; +struct h264_mv_buffer{ + unsigned char* buffer; + int size; + int count; + int pmem_fd; + int offset; + }; +struct h264_mv_buffer h264_mv_buff; + struct video_decoder_context { enum vdec_codec decoder_format; @@ -61,9 +70,13 @@ struct video_decoder_context struct vdec_ion *ip_buf_ion_info; struct vdec_ion *op_buf_ion_info; + struct vdec_ion h264_mv; + FILE * inputBufferFile; FILE * outputBufferFile; + unsigned disable_dmx; + pthread_t videothread_id; pthread_t asyncthread_id; sem_t sem_synchronize; |