manikmahajan
Posts: 2
Joined: Thu Aug 22, 2013 6:00 pm

getting YUV frames from .H264 , resizing and converting to J

Thu Aug 22, 2013 6:15 pm

I am a newbie trying to decode a h264 file into resized JPG images by modifying video.c example.I think two pipelines are possible.

1)H.264file->H.264decoder->(clock->scheduler)->resizer->write_still->JPG Image
2)H.264file->H.264decoder->(clock->scheduler)->resizer->image_encode->image_write->JPG Image

i tried the first one and code is as given below

Code: Select all

// Video deocode demo using OpenMAX IL though the ilcient helper library

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "bcm_host.h"
#include "ilclient.h"

static int video_decode_test(char *filename ,char* outfilename)
{
   OMX_VIDEO_PARAM_PORTFORMATTYPE format;
   OMX_TIME_CONFIG_CLOCKSTATETYPE cstate;
   COMPONENT_T *video_decode = NULL, *video_scheduler = NULL, *resize = NULL, *clock = NULL,*write_still;
   COMPONENT_T *list[6];
   TUNNEL_T tunnel[5];
   ILCLIENT_T *client;
   OMX_PARAM_CONTENTURITYPE*  write_still_uri = NULL;
   size_t uri_size = 0;
   size_t param_size =0 ;
   FILE *in;
   int status = 0;
   unsigned int data_len = 0;
   int packet_size = 80<<10;

   memset(list, 0, sizeof(list));
   memset(tunnel, 0, sizeof(tunnel));

   if((in = fopen(filename, "rb")) == NULL)
      return -2;

   if((client = ilclient_init()) == NULL)
   {
      fclose(in);
      return -3;
   }

   if(OMX_Init() != OMX_ErrorNone)
   {
      ilclient_destroy(client);
      fclose(in);
      return -4;
   }

   // create video_decode
   if(ilclient_create_component(client, &video_decode, "video_decode", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS) != 0)
      status = -14;
   list[0] = video_decode;

   // create resize
   if(status == 0 && ilclient_create_component(client, &resize, "resize", ILCLIENT_DISABLE_ALL_PORTS) != 0)
      status = -14;
   list[1] = resize;
   
   // create clock
   if(status == 0 && ilclient_create_component(client, &clock, "clock", ILCLIENT_DISABLE_ALL_PORTS) != 0)
      status = -14;
   list[2] = clock;

   memset(&cstate, 0, sizeof(cstate));
   cstate.nSize = sizeof(cstate);
   cstate.nVersion.nVersion = OMX_VERSION;
   cstate.eState = OMX_TIME_ClockStateWaitingForStartTime;
   cstate.nWaitMask = 1;
   if(clock != NULL && OMX_SetParameter(ILC_GET_HANDLE(clock), OMX_IndexConfigTimeClockState, &cstate) != OMX_ErrorNone)
      status = -13;

   // create video_scheduler
   if(status == 0 && ilclient_create_component(client, &video_scheduler, "video_scheduler", ILCLIENT_DISABLE_ALL_PORTS) != 0)
      status = -14;
   list[3] = video_scheduler;
   
      // create write_still
   if(status == 0 && ilclient_create_component(client, &write_still, "write_still", ILCLIENT_DISABLE_ALL_PORTS) != 0)
      status = -14;
   list[3] = write_still;

   set_tunnel(tunnel, video_decode, 131, video_scheduler, 10);
   set_tunnel(tunnel+1, video_scheduler, 11, resize, 60);
   set_tunnel(tunnel+2, clock, 80, video_scheduler, 12);
   set_tunnel(tunnel+3, resize, 61, write_still, 30);
   
   // setup clock tunnel first
   if(status == 0 && ilclient_setup_tunnel(tunnel+2, 0, 0) != 0)
      status = -15;
   else
      ilclient_change_component_state(clock, OMX_StateExecuting);

   if(status == 0)
      ilclient_change_component_state(video_decode, OMX_StateIdle);

   memset(&format, 0, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
   format.nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE);
   format.nVersion.nVersion = OMX_VERSION;
   format.nPortIndex = 130;
   format.eCompressionFormat = OMX_VIDEO_CodingAVC;

   if(status == 0 &&
      OMX_SetParameter(ILC_GET_HANDLE(video_decode), OMX_IndexParamVideoPortFormat, &format) == OMX_ErrorNone &&
      ilclient_enable_port_buffers(video_decode, 130, NULL, NULL, NULL) == 0)
   {
      OMX_BUFFERHEADERTYPE *buf;
      int port_settings_changed = 0;
      int first_packet = 1;

      ilclient_change_component_state(video_decode, OMX_StateExecuting);

      while((buf = ilclient_get_input_buffer(video_decode, 130, 1)) != NULL)
      {
         // feed data and wait until we get port settings changed
         unsigned char *dest = buf->pBuffer;

         data_len += fread(dest, 1, packet_size-data_len, in);

         if(port_settings_changed == 0 &&
            ((data_len > 0 && ilclient_remove_event(video_decode, OMX_EventPortSettingsChanged, 131, 0, 0, 1) == 0) ||
             (data_len == 0 && ilclient_wait_for_event(video_decode, OMX_EventPortSettingsChanged, 131, 0, 0, 1,
                                                       ILCLIENT_EVENT_ERROR | ILCLIENT_PARAMETER_CHANGED, 10000) == 0)))
         {
			unsigned int uWidth =0;
			unsigned int uHeight = 0;
			OMX_PARAM_PORTDEFINITIONTYPE portdef;
			
			port_settings_changed = 1;
			printf("PORT SETTING CHANGED\n");
			
			
			// need to setup the input for the resizer with the output of the decoder
			portdef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
			portdef.nVersion.nVersion = OMX_VERSION;
			portdef.nPortIndex = 131;
			OMX_GetParameter(ILC_GET_HANDLE(video_decode),OMX_IndexParamPortDefinition, &portdef);
			
			portdef.nPortIndex = 60;
			uWidth = (unsigned int) portdef.format.image.nFrameWidth;
            uHeight = (unsigned int) portdef.format.image.nFrameHeight;
			printf(" in decode width = %d , height =%d",uWidth,uHeight);
			   fflush(stdout);
			OMX_SetParameter(ILC_GET_HANDLE(resize),OMX_IndexParamPortDefinition , &portdef);
			
			portdef.nPortIndex = 61;
			OMX_SetParameter(ILC_GET_HANDLE(resize),OMX_IndexParamPortDefinition , &portdef);
			
            if(ilclient_setup_tunnel(tunnel, 0, 0) != 0)
            {
               status = -7;
               break;
            }

            ilclient_change_component_state(video_scheduler, OMX_StateExecuting);

            // now setup tunnel to resize
            if(ilclient_setup_tunnel(tunnel+1, 0, 1000) != 0)
            {
               status = -12;
               break;
            }
			
			ilclient_change_component_state(resize, OMX_StateIdle);
			// enable ports
		    OMX_SendCommand(ILC_GET_HANDLE(video_decode), OMX_CommandPortEnable, 131, NULL);
		    OMX_SendCommand(ILC_GET_HANDLE(resize),OMX_CommandPortEnable, 60, NULL);

            ilclient_change_component_state(resize, OMX_StateExecuting);
			
			if( (ilclient_remove_event(resize, OMX_EventPortSettingsChanged, 61, 0, 0, 1) == 0) ||
             (ilclient_wait_for_event(resize, OMX_EventPortSettingsChanged, 61, 0, 0, 1,ILCLIENT_EVENT_ERROR | ILCLIENT_PARAMETER_CHANGED, 10000) == 0))
			{
				OMX_PARAM_PORTDEFINITIONTYPE portdef;
				
				printf("\nGot port setting changed on resize");
				   fflush(stdout);
				
				portdef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
				portdef.nVersion.nVersion = OMX_VERSION;
				portdef.nPortIndex = 61;
				OMX_GetParameter(ILC_GET_HANDLE(resize),OMX_IndexParamPortDefinition, &portdef);
				
				portdef.nPortIndex = 30;
				uWidth = (unsigned int) portdef.format.image.nFrameWidth;
				uHeight = (unsigned int) portdef.format.image.nFrameHeight;
				printf("in resize width = %d , height =%d",uWidth,uHeight);
				   fflush(stdout);
				OMX_SetParameter(ILC_GET_HANDLE(write_still),OMX_IndexParamPortDefinition , &portdef);
				
				uri_size = strlen(outfilename) + 1;
				param_size = sizeof(OMX_PARAM_CONTENTURITYPE) + uri_size - 1;
				write_still_uri = malloc(param_size);
   
				write_still_uri->nSize = param_size;
				write_still_uri->nVersion.nVersion = OMX_VERSION;
				memcpy(write_still_uri->contentURI, outfilename, uri_size);
				OMX_SetParameter(ILC_GET_HANDLE(write_still),OMX_IndexParamContentURI , &write_still_uri );
				
				
				
				if(ilclient_setup_tunnel(tunnel+3, 0, 0) != 0)
				{
					status = -7;
					break;
				}
                                ilclient_change_component_state(write_still, OMX_StateIdle);
				OMX_SendCommand(ILC_GET_HANDLE(resize), OMX_CommandPortEnable, 61, NULL);
				OMX_SendCommand(ILC_GET_HANDLE(write_still),OMX_CommandPortEnable, 30, NULL);
				
				ilclient_change_component_state(write_still, OMX_StateExecuting);
			}
         }
		 
		 //nothing left to read
         if(!data_len)
            break;

         buf->nFilledLen = data_len;
         data_len = 0;

         buf->nOffset = 0;
         if(first_packet)
         {
            buf->nFlags = OMX_BUFFERFLAG_STARTTIME;
            first_packet = 0;
         }
         else
            buf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;

         if(OMX_EmptyThisBuffer(ILC_GET_HANDLE(video_decode), buf) != OMX_ErrorNone)
         {
            status = -6;
            break;
         }
      }

      buf->nFilledLen = 0;
      buf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN | OMX_BUFFERFLAG_EOS;

      if(OMX_EmptyThisBuffer(ILC_GET_HANDLE(video_decode), buf) != OMX_ErrorNone)
         status = -20;

      // wait for EOS from render
      ilclient_wait_for_event(resize, OMX_EventBufferFlag, 60, 0, OMX_BUFFERFLAG_EOS, 0,
                              ILCLIENT_BUFFER_FLAG_EOS, 10000);

      // need to flush the renderer to allow video_decode to disable its input port
      ilclient_flush_tunnels(tunnel, 0);

      ilclient_disable_port_buffers(video_decode, 130, NULL, NULL, NULL);
   }

   fclose(in);

   ilclient_disable_tunnel(tunnel);
   ilclient_disable_tunnel(tunnel+1);
   ilclient_disable_tunnel(tunnel+2);
   ilclient_teardown_tunnels(tunnel);

   ilclient_state_transition(list, OMX_StateIdle);
   ilclient_state_transition(list, OMX_StateLoaded);

   ilclient_cleanup_components(list);

   OMX_Deinit();

   ilclient_destroy(client);
   return status;
}

int main (int argc, char **argv)
{
   if (argc < 3) {
      printf("Usage: %s <filename> <output.jpg>\n", argv[0]);
      exit(1);
   }
   bcm_host_init();
   return video_decode_test(argv[1],argv[2]);
}
The program runs and prints width and height , but does not write the file . Can somebody please suggest what is wrong with the code . i suspectthere might be something fundamentally wrong with my approach as i am new to open max and have not seen any example of write_still.
Thanks

Return to “OpenMAX”