longo92
Posts: 41
Joined: Mon Sep 03, 2018 3:45 pm
Contact: Website Skype

jpeg encoding

Mon Sep 10, 2018 1:43 pm

Hi, i set the camera video port with encoding MMAL_ENCODING_OPAQUE and encoding_variant MMAL_ENCODING_I420, in the video port callback i want to send it to a JPEG ENCODER. The questions is: can i pass the opaque buffer to the encoder (after setting the input port of JPEG encoder to MMAL_ENCODING_OPAQUE and encoding variant to MMAL_ENCODING_I420)?
I try but the encoded image has size 0.

6by9
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 6645
Joined: Wed Dec 04, 2013 11:27 am
Location: ZZ9 Plural Z Alpha, aka just outside Cambridge.

Re: jpeg encoding

Mon Sep 10, 2018 1:54 pm

Yes, you should be able to.
Post your code (as long as it is a simple test case) someone sensible (eg github or pastebin) and I will have a look.
Software Engineer at Raspberry Pi Trading. Views expressed are still personal views.
I'm not interested in doing contracts for bespoke functionality - please don't ask.

longo92
Posts: 41
Joined: Mon Sep 03, 2018 3:45 pm
Contact: Website Skype

Re: jpeg encoding

Mon Sep 10, 2018 2:09 pm

Ok, but i tell you the short story.
I try to do something more sophisticated, but it's long to write. For now i write it simple.
I have the video output port attached to a splitter and on one splitter's output i have the callback that pass the frame to the jpeg encoder .
  1. The video port is configured in the following manner:

    Code: Select all

    //setup video port format
    	MMAL_ES_FORMAT_T * format = video_port->format;
    	format->encoding = MMAL_ENCODING_OPAQUE;
    	format->encoding_variant = MMAL_ENCODING_I420;
    	format->es->video.width = 1280;
    	format->es->video.height = 960;
    	format->es->video.crop.x = 0;
    	format->es->video.crop.y = 0;
    	format->es->video.crop.width = 1280;
    	format->es->video.crop.height = 960;
    	format->es->video.frame_rate.num = 30;
    	format->es->video.frame_rate.den = 1;
    	status = mmal_port_format_commit(video_port);
    	if (status != MMAL_SUCCESS)
    	{
    		printf("Couldn't set video port format : error %d", status);
    		mmal_component_destroy(camera);
    		return NULL;
    	}
    	status = mmal_port_parameter_set_boolean(video_port,MMAL_PARAMETER_ZERO_COPY,MMAL_ZERO_ENABLED);
       	if (status != MMAL_SUCCESS)
       	{
    		printf("Couldn't setcamera video port  output  port ZERO COPY  : error %d", status);
    		mmal_component_destroy(camera);
    		return NULL;
    	}
  2. The splitter :

    Code: Select all

    	status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_SPLITTER, &splitter);
    	if (status != MMAL_SUCCESS)
    	{
    		printf("Failed to create splitter component\n");
    		goto error;
    	}
    
    	//check we have output ports
    	if (splitter->output_num != 4 || splitter->input_num != 1)
    	{
    		printf("Splitter doesn't have correct ports: %d, %d\n",splitter->input_num,splitter->output_num);
    		goto error;
    	}
    
    	//get the ports
    	input_port = splitter->input[0];
    	mmal_format_copy(input_port->format,video_port->format);
    	input_port->buffer_num = 3;
    	status = mmal_port_format_commit(input_port);
    	if (status != MMAL_SUCCESS)
    	{
    		printf("Couldn't set resizer input port format : error %d", status);
    		goto error;
    	}
    	//SET ZERO-COPY ON INPUT PORT SPLITTER
    	status = mmal_port_parameter_set_boolean(input_port,MMAL_PARAMETER_ZERO_COPY,MMAL_TRUE);
    	if (status != MMAL_SUCCESS)
    	{
    		printf("Couldn't set SPLITTER INPUT port ZERO COPY  : error %d", status);
    		goto error;
    	}
    
    
    	for(int i = 0; i < splitter->output_num; i++)
    	{
    		output_port = splitter->output[i];
    		output_port->buffer_num = 3;
    		mmal_format_copy(output_port->format,input_port->format);
    		output_port->format->encoding = MMAL_ENCODING_OPAQUE;
    		output_port->format->encoding_variant = MMAL_ENCODING_I420;
    		status = mmal_port_format_commit(output_port);
    		if (status != MMAL_SUCCESS)
    			{
    				printf("Couldn't set splitter  port format : error %d", status);
    				goto error;
    			}
    
    		//UN-SET ZERO-COPY IN SPLITTER OUTPUT PORT
    		status = mmal_port_parameter_set_boolean(output_port,MMAL_PARAMETER_ZERO_COPY,MMAL_FALSE);
    		if (status != MMAL_SUCCESS)
    		{
    			printf("Couldn't set SPLITTER output port ZERO COPY  : error %d", status);
    			goto error;
    		}
    
    	}
    
  3. The Encoder JPEG (i call the function passing as input port one of splitter's output);

    Code: Select all

    
    // This callback and the above semaphore is used when waiting for
    // data to be returned.
    static void mmalCallback(MMAL_WRAPPER_T* encoder)
    {
       vcos_semaphore_post(&sem);
    }
    
     
    void create_Encoder_JPEG(uint32_t m_quality, MMAL_PORT_T* input_port){
    MMAL_STATUS_T status;
    	bcm_host_init();
       if (vcos_semaphore_create(&sem, "encoder sem", 0) != VCOS_SUCCESS) {
          fprintf(stderr, "Failed to create semaphore\n");
          exit(1);
       }
    
       if (mmal_wrapper_create(&encoder, MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER)
           != MMAL_SUCCESS) {
          fprintf(stderr, "Failed to create mmal component\n");
          exit(1);
       }
    
      quality = m_quality;
      if(mmal_port_parameter_set_uint32(encoder->output[0],MMAL_PARAMETER_JPEG_Q_FACTOR,quality)!=MMAL_SUCCESS){
    	printf("ERRIR IN SETTING JPEQ QUALITY\n");
    	exit(1);
    }
    
      mmal_port_parameter_get_uint32(encoder->output[0],MMAL_PARAMETER_JPEG_Q_FACTOR,&quality);
      printf ("JPEG QUALITY: %lu\n",quality);
       encoder->callback = mmalCallback;
    
    mmal_format_copy(encoder->input[0]->format,input_port->format);
     
    
    
       if (mmal_port_format_commit(encoder->input[0]) != MMAL_SUCCESS) {
          fprintf(stderr, "Failed to commit input port format\n");
          exit(1);
       }
    
    
    }
    
    
  4. The function that i call inside the splitter' output callback for encoding the frame:

    Code: Select all

    //return the encoded jpeg
    MMAL_BUFFER_HEADER_T* mmal_encode_JPEG(MMAL_FOURCC_T encoding, // Encoding
                          void* frame_data, int frame_size, uint32_t quality) // File name
    {
    	void * mem_test;
       MMAL_PORT_T* portIn;
       MMAL_PORT_T* portOut;
       MMAL_BUFFER_HEADER_T* in;
       MMAL_BUFFER_HEADER_T* out;
       MMAL_STATUS_T status;
       int eos = 0;
       int sent = 0;
     int outputWritten = 0;
    int nw;
       
      unsigned int  ret;
    
     // Perform the encoding
    #ifdef DEBUG_JPG
       FILE* outFile = fopen("test.jpg", "w");
       if (!outFile) {
          fprintf(stderr, "Failed to open file test.jpg (%s)\n", strerror(errno));
          exit(1);
       }  
     #endif
    
    
       portIn = encoder->input[0];
       encoder->status = MMAL_SUCCESS;
    
       if (portIn->is_enabled) {
          if (mmal_wrapper_port_disable(portIn) != MMAL_SUCCESS) {
             fprintf(stderr, "Failed to disable input port\n");
             exit(1);
          }
       }
    
     
       if (mmal_wrapper_port_enable(portIn, MMAL_WRAPPER_FLAG_PAYLOAD_ALLOCATE)
           != MMAL_SUCCESS) {
          fprintf(stderr, "Failed to enable input port\n");
          exit(1);
       }
    
    
       // Configure output
      
       portOut = encoder->output[0];
    
       if (portOut->is_enabled) {
          if (mmal_wrapper_port_disable(portOut) != MMAL_SUCCESS) {
             fprintf(stderr, "Failed to disable output port\n");
             exit(1);
          }
       }
    
       portOut->format->encoding = encoding;
       if (mmal_port_format_commit(portOut) != MMAL_SUCCESS) {
          fprintf(stderr, "Failed to commit output port format\n");
          exit(1);
       }
    
       mmal_port_parameter_set_uint32(portOut, MMAL_PARAMETER_JPEG_Q_FACTOR, quality);
      
       portOut->buffer_size = portOut->buffer_size_recommended;
       portOut->buffer_num = portOut->buffer_num_recommended;
    
       if (mmal_wrapper_port_enable(portOut, MMAL_WRAPPER_FLAG_PAYLOAD_ALLOCATE)
           != MMAL_SUCCESS) {
          fprintf(stderr, "Failed to enable output port\n");
          exit(1);
       }
    
    
      
       // Perform the encoding
    
       
      
       while (!eos) {
        
          // Send output buffers to be filled with encoded image.
          while (mmal_wrapper_buffer_get_empty(portOut, &out, 0) == MMAL_SUCCESS) {
             if (mmal_port_send_buffer(portOut, out) != MMAL_SUCCESS) {
                fprintf(stderr, "Failed to send buffer\n");
                break;
             }
          }
    
          // Send image to be encoded.
          if (!sent && mmal_wrapper_buffer_get_empty(portIn, &in, 0) == MMAL_SUCCESS) {
             //printf("- sending %u bytes to encoder\n", in->alloc_size);
             in->data = frame_data;
             in->length =  frame_size;
             in->flags = MMAL_BUFFER_HEADER_FLAG_EOS;
             if (mmal_port_send_buffer(portIn, in) != MMAL_SUCCESS) {
                fprintf(stderr, "Failed to send buffer\n");
                break;
             }
             sent = 1;
          }
    
          // Get filled output buffers.
          status = mmal_wrapper_buffer_get_full(portOut, &out, 0);
          if (status == MMAL_EAGAIN) {
             // No buffer available, wait for callback and loop.
             vcos_semaphore_wait(&sem);
             continue;
          } else if (status != MMAL_SUCCESS) {
             fprintf(stderr, "Failed to get full buffer : %d\n",status);
            exit(1);
          }
    
          //printf("- received %i bytes\n", out->length);
          eos = out->flags & MMAL_BUFFER_HEADER_FLAG_EOS;
    #ifdef DEBUG_JPG
    	 nw = fwrite(out->data, 1, out->length, outFile);
          if (nw != out->length) {
             fprintf(stderr, "Failed to write complete buffer\n");
             exit(1);
          }
          outputWritten += nw;
    #endif
    
         
        
       }
    
       mmal_port_flush(portOut);
    #ifdef DEBUG_JPG
    fclose(outFile);
    #endif
       return out;
    }
  5. The splitter's output's callback:

    Code: Select all

    
    static void OnVideoBufferCallback_Encode_JPEG(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer){
    	MMAL_BUFFER_HEADER_T* frame_JPEG= NULL;
    	  mmal_buffer_header_mem_lock(buffer);
    	frame_JPEG = mmal_encode_JPEG(MMAL_ENCODING_JPEG,buffer->data,buffer->length,qualityJPEG);
    	handler_buffer(BufferPool,OutputQueue, port, buffer);
    	mmal_buffer_header_mem_unlock(buffer);
    	
    }
    
If can help the buffer->length of the output's splitter is 128 byte (but i think is right, i suppose is the standard size of opaque buffer).

Return to “Graphics programming”