summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorprasanth kamuju <prasanth.kamuju@linaro.org>2014-07-02 15:40:04 +0530
committerprasanth kamuju <prasanth.kamuju@linaro.org>2014-07-02 15:40:04 +0530
commitcd8b9a06d8019752b0784fdb7037a8a518a132b1 (patch)
treec5949ef9a4a560543773ad8053ec0a8e540ae470
parent46a430b4d2003ca6cc746437d9ee3c4cb8d348af (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-xdecodertest/decoder_driver_test.c351
-rwxr-xr-xdecodertest/decoder_driver_test.h13
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;