cmisip
Posts: 94
Joined: Tue Aug 25, 2015 12:38 am

Getting lock memory failure on videocore with zero copy

Mon Aug 27, 2018 1:15 am

This is the error I am getting occasionally.

Code: Select all

[vc_sm_ioctl_lock]: failed to lock memory on videocore (status: 0, trans_id: 52232)
[vcsm_vma_fault]: failed to lock memory on videocore (status: 0)
[vc_sm_ioctl_lock]: failed to lock memory on videocore (status: 0, trans_id: 52499)
[vcsm_vma_fault]: failed to lock memory on videocore (status: 0)
I will try to remove the zero copy on component initialization to see if the error goes away. I don't recall seeing this before I updated the code to use zero copy. However, I also made a lot of other changes.

Any ideas on what might be the issue?

Thanks,
Chris

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

Re: Getting lock memory failure on videocore with zero copy

Mon Aug 27, 2018 7:53 am

Too little to go on.

Are you manually locking and unlocking buffers via vcsm? Or just using mmal zero copy?

When during your program do you get these errors? Allocation or buffer passing? My memory says that allocations are normally locked and mapped immediately after allocation due to a deadlock found if you try in the fault handler. If it is failing at allocation, then something very odd has gone on. Or have you managed to unmap it?
Software Engineer at Raspberry Pi Trading. Views expressed are still personal views.
Please don't send PMs asking for support - use the forum.
I'm not interested in doing contracts for bespoke functionality - please don't ask.

cmisip
Posts: 94
Joined: Tue Aug 25, 2015 12:38 am

Re: Getting lock memory failure on videocore with zero copy

Tue Aug 28, 2018 2:03 am

I'll post the mmal routines here. Maybe you can look it over to see if there are any obvious errors.


OpenMMalDecoder. Why does it need 20 input buffers?

Code: Select all

int FfmpegCamera::OpenMmalDecoder(AVCodecContext *mVideoCodecContext){  
   

   // Create the decoder component.
   if ( mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &decoder)  != MMAL_SUCCESS) {
      Fatal("failed to create mmal decoder");
   }   
   
   // CONTROL PORT SETTINGS
   decoder->control->userdata = (MMAL_PORT_USERDATA_T *)&context;
   if ( mmal_port_enable(decoder->control, control_callback) != MMAL_SUCCESS ) {
     Fatal("failed to enable mmal decoder control port");
   }  
   
   
   /* Get statistics on the input port */
   MMAL_PARAMETER_CORE_STATISTICS_T stats = {{0}};
   stats.hdr.id = MMAL_PARAMETER_CORE_STATISTICS;
   stats.hdr.size = sizeof(MMAL_PARAMETER_CORE_STATISTICS_T);
   if (mmal_port_parameter_get(decoder->input[0], &stats.hdr) != MMAL_SUCCESS) {
     Info("failed to get decoder port statistics");
   }
   else {
     Info("Decoder stats: %i, %i", stats.stats.buffer_count, stats.stats.max_delay);
   }
   /* Set the zero-copy parameter on the input port */
   MMAL_PARAMETER_BOOLEAN_T zc = {{MMAL_PARAMETER_ZERO_COPY, sizeof(zc)}, MMAL_TRUE};
   if (mmal_port_parameter_set(decoder->input[0], &zc.hdr) != MMAL_SUCCESS)
     Info("Failed to set zero copy on decoder input");

   /* Set the zero-copy parameter on the output port */
   if (mmal_port_parameter_set_boolean(decoder->output[0], MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE) != MMAL_SUCCESS)
     Info("Failed to set zero copy on decoder output");

   /* Set format of video decoder input port */
   MMAL_ES_FORMAT_T *format_in = decoder->input[0]->format;
   format_in->type = MMAL_ES_TYPE_VIDEO;
   format_in->encoding = MMAL_ENCODING_H264;
   
   format_in->es->video.width = VCOS_ALIGN_UP(width, 32);
   format_in->es->video.height = VCOS_ALIGN_UP(height,16);
   format_in->es->video.crop.width = mVideoCodecContext->width;
   format_in->es->video.crop.height = mVideoCodecContext->height;
   
   format_in->es->video.frame_rate.num = 24000;
   format_in->es->video.frame_rate.den = 1001;
   format_in->es->video.par.num = mVideoCodecContext->sample_aspect_ratio.num;
   format_in->es->video.par.den = mVideoCodecContext->sample_aspect_ratio.den;
   format_in->flags = MMAL_ES_FORMAT_FLAG_FRAMED;
 

   
   if ( mmal_port_format_commit(decoder->input[0]) != MMAL_SUCCESS ) {
      Fatal("failed to commit mmal decoder input format");
   }   

   MMAL_ES_FORMAT_T *format_out = decoder->output[0]->format;
   format_out->type = MMAL_ES_TYPE_VIDEO;
   format_out->encoding = MMAL_ENCODING_I420;
  
   
   //ALLOCATE Extradata, copying from avcodec context
   if (mmal_format_extradata_alloc(format_in, mVideoCodecContext->extradata_size) != MMAL_SUCCESS)
     Fatal("failed to allocate extradata ");
     
   Info("Decoder extradata size %d\n", mVideoCodecContext->extradata_size);
   format_in->extradata_size = mVideoCodecContext->extradata_size;
   if (format_in->extradata_size)
      memcpy(format_in->extradata, mVideoCodecContext->extradata, mVideoCodecContext->extradata_size);
   
   
   if ( mmal_port_format_commit(decoder->output[0]) != MMAL_SUCCESS ) {
     Fatal("failed to commit decoder output format");
   }
   


   /* The format of both ports is now set so we can get their buffer requirements and create
    * our buffer headers. We use the buffer pool API to create these. */
   decoder->input[0]->buffer_num = decoder->input[0]->buffer_num_recommended;
   decoder->input[0]->buffer_size = decoder->input[0]->buffer_size_recommended;
   decoder->output[0]->buffer_num = decoder->output[0]->buffer_num_recommended;
   decoder->output[0]->buffer_size = decoder->output[0]->buffer_size_recommended;
   pool_ind = mmal_port_pool_create(decoder->input[0],decoder->input[0]->buffer_num,
                              decoder->input[0]->buffer_size);
   pool_outd = mmal_port_pool_create(decoder->output[0],decoder->output[0]->buffer_num,
                               decoder->output[0]->buffer_size);
                               
                               
   /* Display the input port format */
   display_format(&decoder->input[0],&format_in);
   
   display_format(&decoder->output[0],&format_out);
                               

   /* Create a queue to store our decoded video frames. The callback we will get when
    * a frame has been decoded will put the frame into this queue. */
   context.dqueue = mmal_queue_create();

   /* Store a reference to our context in each port (will be used during callbacks) */
   decoder->input[0]->userdata = (MMAL_PORT_USERDATA_T *)&context;
   decoder->output[0]->userdata = (MMAL_PORT_USERDATA_T *)&context;
   
   // Enable all the input port and the output port.
   if ( mmal_port_enable(decoder->input[0], input_callback) != MMAL_SUCCESS ) {
     Fatal("failed to enable mmal decoder input port");
   }  
   
   if ( mmal_port_enable(decoder->output[0], output_callbackd) != MMAL_SUCCESS ) {
     Fatal("failed to enable mmal decoder output port");
   }
   
   /* Component won't start processing data until it is enabled. */
   if ( mmal_component_enable(decoder) != MMAL_SUCCESS ) {
     Fatal("failed to enable mmal decoder component");
   }  

   return 0;

}
OpenMMalEncoder. Only used for getting motion vectors.

Code: Select all

int FfmpegCamera::OpenMmalEncoder(AVCodecContext *mVideoCodecContext){  
   

   // Create the encoder component.
   if ( mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER, &encoder)  != MMAL_SUCCESS) {
      Fatal("failed to create mmal encoder");
   }   
   
   // CONTROL PORT SETTINGS
   encoder->control->userdata = (MMAL_PORT_USERDATA_T *)&context;
   if ( mmal_port_enable(encoder->control, control_callback) != MMAL_SUCCESS ) {
     Fatal("failed to enable mmal encoder control port");
   }  
   
   /* Get statistics on the input port */
   MMAL_PARAMETER_CORE_STATISTICS_T stats = {{0}};
   stats.hdr.id = MMAL_PARAMETER_CORE_STATISTICS;
   stats.hdr.size = sizeof(MMAL_PARAMETER_CORE_STATISTICS_T);
   if (mmal_port_parameter_get(encoder->input[0], &stats.hdr) != MMAL_SUCCESS) {
     Info("failed to get encoder port statistics");
   }
   else {
     Info("Encoder stats: %i, %i", stats.stats.buffer_count, stats.stats.max_delay);
   }
   /* Set the zero-copy parameter on the input port */
   MMAL_PARAMETER_BOOLEAN_T zc = {{MMAL_PARAMETER_ZERO_COPY, sizeof(zc)}, MMAL_TRUE};
   if (mmal_port_parameter_set(encoder->input[0], &zc.hdr) != MMAL_SUCCESS)
     Info("Failed to set zero copy on encoder input");

   /* Set the zero-copy parameter on the output port */
   if (mmal_port_parameter_set_boolean(encoder->output[0], MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE) != MMAL_SUCCESS)
     Info("Failed to set zero copy on encoder output");

   /* Set format of video encoder input port */
   MMAL_ES_FORMAT_T *format_in = encoder->input[0]->format;
   format_in->type = MMAL_ES_TYPE_VIDEO;
   format_in->encoding = MMAL_ENCODING_I420;
   
   format_in->es->video.width = VCOS_ALIGN_UP(width, 32);
   format_in->es->video.height = VCOS_ALIGN_UP(height,16);
   format_in->es->video.crop.width = mVideoCodecContext->width;
   format_in->es->video.crop.height = mVideoCodecContext->height;
   
   format_in->es->video.frame_rate.num = 24000;
   format_in->es->video.frame_rate.den = 1001;
   format_in->es->video.par.num = mVideoCodecContext->sample_aspect_ratio.num;
   format_in->es->video.par.den = mVideoCodecContext->sample_aspect_ratio.den;
   format_in->flags = MMAL_ES_FORMAT_FLAG_FRAMED;
 

   
   if ( mmal_port_format_commit(encoder->input[0]) != MMAL_SUCCESS ) {
      Fatal("failed to commit mmal encoder input format");
   }   

   MMAL_ES_FORMAT_T *format_out = encoder->output[0]->format;
   format_out->type = MMAL_ES_TYPE_VIDEO;
   format_out->encoding = MMAL_ENCODING_H264;
   
   format_out->es->video.width = VCOS_ALIGN_UP(width, 32);
   format_out->es->video.height = VCOS_ALIGN_UP(height,16);
   format_out->es->video.crop.width = mVideoCodecContext->width;
   format_out->es->video.crop.height = mVideoCodecContext->height;
   
   
   if ( mmal_port_format_commit(encoder->output[0]) != MMAL_SUCCESS ) {
     Fatal("failed to commit encoder output format");
   }
   
   if (mmal_port_parameter_set_boolean(encoder->output[0], MMAL_PARAMETER_VIDEO_ENCODE_INLINE_VECTORS, 1) != MMAL_SUCCESS) {
      Fatal("failed to request inline motion vectors from mmal encoder");
   }   

   /* Display the input port format */
   display_format(&encoder->input[0],&format_in);
   
   display_format(&encoder->output[0],&format_out);
   

   /* The format of both ports is now set so we can get their buffer requirements and create
    * our buffer headers. We use the buffer pool API to create these. */
   encoder->input[0]->buffer_num = encoder->input[0]->buffer_num_min;
   encoder->input[0]->buffer_size = encoder->input[0]->buffer_size_min;
   encoder->output[0]->buffer_num = encoder->output[0]->buffer_num_min;
   encoder->output[0]->buffer_size = encoder->output[0]->buffer_size_min;
   pool_ine = mmal_port_pool_create(encoder->input[0],encoder->input[0]->buffer_num,
                              encoder->input[0]->buffer_size);
   pool_oute = mmal_port_pool_create(encoder->output[0],encoder->output[0]->buffer_num,
                               encoder->output[0]->buffer_size);

   /* Create a queue to store our decoded video frames. The callback we will get when
    * a frame has been decoded will put the frame into this queue. */
   context.equeue = mmal_queue_create();

   /* Store a reference to our context in each port (will be used during callbacks) */
   encoder->input[0]->userdata = (MMAL_PORT_USERDATA_T *)&context;
   encoder->output[0]->userdata = (MMAL_PORT_USERDATA_T *)&context;
   
   // Enable all the input port and the output port.
   if ( mmal_port_enable(encoder->input[0], input_callback) != MMAL_SUCCESS ) {
     Fatal("failed to enable mmal encoder input port");
   }  
   
   if ( mmal_port_enable(encoder->output[0], output_callbacke) != MMAL_SUCCESS ) {
     Fatal("failed to enable mmal encoder output port");
   }
   
   /* Component won't start processing data until it is enabled. */
   if ( mmal_component_enable(encoder) != MMAL_SUCCESS ) {
     Fatal("failed to enable mmal encoder component");
   }  

   return 0;

}
OpenMMalResizer. This is only being used for format conversion right now. This creates the RGB buffers which are sent to the analyse process and eventually converted to JPEG there. I think the software jpeg conversion is the slowest part in the analyse process and probably why the analyze process lags the capture process.

Code: Select all

int FfmpegCamera::OpenMmalResizer(AVCodecContext *mVideoCodecContext){  
   

   // Create the Resizer component.
   if ( mmal_component_create("vc.ril.isp", &resizer)  != MMAL_SUCCESS) { 
      Fatal("failed to create mmal resizer");
   }   
   
   // CONTROL PORT SETTINGS
   resizer->control->userdata = (MMAL_PORT_USERDATA_T *)&context;
   if ( mmal_port_enable(resizer->control, control_callback) != MMAL_SUCCESS ) {
     Fatal("failed to enable mmal resizer control port");
   }  
   
   /* Get statistics on the input port */
   MMAL_PARAMETER_CORE_STATISTICS_T stats = {{0}};
   stats.hdr.id = MMAL_PARAMETER_CORE_STATISTICS;
   stats.hdr.size = sizeof(MMAL_PARAMETER_CORE_STATISTICS_T);
   if (mmal_port_parameter_get(resizer->input[0], &stats.hdr) != MMAL_SUCCESS) {
     Info("failed to get resizer port statistics");
   }
   else {
     Info("Resizer stats: %i, %i", stats.stats.buffer_count, stats.stats.max_delay);
   }
   /* Set the zero-copy parameter on the input port */
   MMAL_PARAMETER_BOOLEAN_T zc = {{MMAL_PARAMETER_ZERO_COPY, sizeof(zc)}, MMAL_TRUE};
   if (mmal_port_parameter_set(resizer->input[0], &zc.hdr) != MMAL_SUCCESS)
     Info("Failed to set zero copy on resizer input");

   /* Set the zero-copy parameter on the output port */
   if (mmal_port_parameter_set_boolean(resizer->output[0], MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE) != MMAL_SUCCESS)
     Info("Failed to set zero copy on resizer output");

   /* Set format of video resizer input port */
   MMAL_ES_FORMAT_T *format_in = resizer->input[0]->format;
   format_in->type = MMAL_ES_TYPE_VIDEO;
   format_in->encoding = MMAL_ENCODING_I420;
   format_in->encoding_variant = MMAL_ENCODING_I420;
   
   format_in->es->video.width = VCOS_ALIGN_UP(width, 32);
   format_in->es->video.height = VCOS_ALIGN_UP(height,16);
   format_in->es->video.crop.width = mVideoCodecContext->width;
   format_in->es->video.crop.height = mVideoCodecContext->height;
   
   format_in->es->video.frame_rate.num = 24000;
   format_in->es->video.frame_rate.den = 1001;
   format_in->es->video.par.num = mVideoCodecContext->sample_aspect_ratio.num;
   format_in->es->video.par.den = mVideoCodecContext->sample_aspect_ratio.den;
   format_in->flags = MMAL_ES_FORMAT_FLAG_FRAMED;
   
 

   
   if ( mmal_port_format_commit(resizer->input[0]) != MMAL_SUCCESS ) {
      Fatal("failed to commit mmal resizer input format");
   }   

   
   
   MMAL_ES_FORMAT_T *format_out = resizer->output[0]->format;
   
   format_out->es->video.width = VCOS_ALIGN_UP(width, 32);
   format_out->es->video.height = VCOS_ALIGN_UP(height,16);
   format_out->es->video.crop.width = mVideoCodecContext->width;
   format_out->es->video.crop.height = mVideoCodecContext->height;
   
  
   
   if ( colours == ZM_COLOUR_RGB32 ) {
       format_out->encoding = MMAL_ENCODING_RGBA;
   } else if ( colours == ZM_COLOUR_RGB24 ) {
       format_out->encoding = MMAL_ENCODING_RGB24;
   } else if(colours == ZM_COLOUR_GRAY8) { 
       format_out->encoding = MMAL_ENCODING_I420;
   }
   
   
   
   
   if ( mmal_port_format_commit(resizer->output[0]) != MMAL_SUCCESS ) {
     Fatal("failed to commit mmal resizer output format");
   }
   

   /* Display the input port format */
   display_format(&resizer->input[0],&format_in);
   
   display_format(&resizer->output[0],&format_out);
   

   /* The format of both ports is now set so we can get their buffer requirements and create
    * our buffer headers. We use the buffer pool API to create these. */
   resizer->input[0]->buffer_num = resizer->input[0]->buffer_num_min;
   resizer->input[0]->buffer_size = resizer->input[0]->buffer_size_min;
   resizer->output[0]->buffer_num = resizer->output[0]->buffer_num_min;
   resizer->output[0]->buffer_size = resizer->output[0]->buffer_size_min;
   pool_inr = mmal_port_pool_create(resizer->input[0],resizer->input[0]->buffer_num,
                              resizer->input[0]->buffer_size);
   pool_outr = mmal_port_pool_create(resizer->output[0],resizer->output[0]->buffer_num,
                               resizer->output[0]->buffer_size);

   /* Create a queue to store our decoded video frames. The callback we will get when
    * a frame has been decoded will put the frame into this queue. */
   context.rqueue = mmal_queue_create();

   /* Store a reference to our context in each port (will be used during callbacks) */
   resizer->input[0]->userdata = (MMAL_PORT_USERDATA_T *)&context;
   resizer->output[0]->userdata = (MMAL_PORT_USERDATA_T *)&context;
   
   // Enable all the input port and the output port.
   if ( mmal_port_enable(resizer->input[0], input_callback) != MMAL_SUCCESS ) {
     Fatal("failed to enable mmal resizer input port");
   }  
   
   if ( mmal_port_enable(resizer->output[0], output_callbackr) != MMAL_SUCCESS ) {
     Fatal("failed to enable mmal resizer output port");
   }
   
   /* Component won't start processing data until it is enabled. */
   if ( mmal_component_enable(resizer) != MMAL_SUCCESS ) {
     Fatal("failed to enable mmal resizer component");
   }  

   return 0;

}
Decode Routine creates an AVFrame.

Code: Select all

...
frameComplete=mmal_decode(&packet);
...
Encoder Routine takes the AVFrame payload and puts it in the input buffer. Motion vectors are saved in a buffer and sent to analyse process via shared mem.

Code: Select all

...
mmal_encode(&mvect_buffer);
...
Resizer Routine takes the AVFrame payload and puts it in the input buffer. The RGB data is saved in a buffer and sent to analyse process via shared mem.

Code: Select all

mmal_resize(&directbuffer);
mmal_decode.

Code: Select all

int FfmpegCamera::mmal_decode(AVPacket *pkt) {   
	MMAL_BUFFER_HEADER_T *buffer;
	int got_frame=false;
	//Info("decode start");
	
	if ((buffer = mmal_queue_get(pool_ind->queue)) != NULL) {  
         
         memcpy(buffer->data,pkt->data,pkt->size);
         buffer->length=pkt->size;
         
         buffer->flags|=MMAL_BUFFER_HEADER_FLAG_FRAME_START;
         buffer->flags|=MMAL_BUFFER_HEADER_FLAG_FRAME_END;
         
         buffer->pts = pkt->pts == AV_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : pkt->pts;
         buffer->dts = pkt->dts == AV_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : pkt->dts;
         
         buffer->alloc_size = decoder->input[0]->buffer_size;
            
         if (mmal_port_send_buffer(decoder->input[0], buffer) != MMAL_SUCCESS) {
                 Warning("failed to send H264 buffer to decoder for frame %d\n", frameCount);
                  
         }
                 
         
      }

      
      while ((buffer = mmal_queue_get(context.dqueue)) != NULL)
      {
         //save it as AVFrame holding an I420 buffer
         av_image_fill_arrays(mRawFrame->data, mRawFrame->linesize, buffer->data, AV_PIX_FMT_YUV420P, mRawFrame->width, mRawFrame->height, 1);
         got_frame=true;
         
         mmal_buffer_header_release(buffer);
      }

      //if ((buffer = mmal_queue_get(pool_outd->queue)) != NULL) {
      while ((buffer = mmal_queue_get(pool_outd->queue)) != NULL){
		 if (mmal_port_send_buffer(decoder->output[0], buffer) != MMAL_SUCCESS) {
			   Warning("failed to send empty buffer to decoder output for frame %d\n", frameCount);
         } 
      }
      
     //Info("decode end");
     return (got_frame);    
}	
mmal_encode.

Code: Select all

int FfmpegCamera::mmal_encode(uint8_t **mv_buffer) {  //uses mRawFrame data 
	MMAL_BUFFER_HEADER_T *buffer;
	//Info("encode start");
	uint16_t numblocks=((encoder->output[0]->format->es->video.width * encoder->output[0]->format->es->video.height)/256);
               
	if ((buffer = mmal_queue_get(pool_ine->queue)) != NULL) {  
         
         av_image_copy_to_buffer(buffer->data, bufsize, (const uint8_t **)mRawFrame->data, mRawFrame->linesize,
                                 AV_PIX_FMT_YUV420P, mRawFrame->width, mRawFrame->height, 1);
         buffer->length=bufsize;
         
         buffer->pts = buffer->dts = MMAL_TIME_UNKNOWN;
         
         buffer->alloc_size = encoder->input[0]->buffer_size;
          
         if (mmal_port_send_buffer(encoder->input[0], buffer) != MMAL_SUCCESS) {
                 Warning("failed to send I420 buffer to encoder for frame %d\n", frameCount);
                  
         }   
         
         
      }

      
      while ((buffer = mmal_queue_get(context.equeue)) != NULL) {
         
         
         if(buffer->flags & MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO) {
			     uint16_t t_offset=0; 
                      
                        uint32_t registers;
                  
                        mmal_motion_vector *mvarray=(mmal_motion_vector *)buffer->data;
                        
                        registers=0;
                        uint16_t count=0;
                        uint16_t wcount=0;
                        for (int i=0;i < numblocks ; i++) {
                            
                            if ((abs(mvarray[i].x_vector) + abs(mvarray[i].y_vector)) > 8) 
                               registers =registers | (1 << count);
                            
                            count++;
                            
                            if ( count == 32) {
                               memcpy((*mv_buffer)+t_offset , &registers, 4 ) ;  
                               count=0;
                               wcount+=1;
                               t_offset+=4;
      
                               registers=0;

                             }
                            
                        } 
         
	     }
	     
	     
         
         mmal_buffer_header_release(buffer);
      }

      //if ((buffer = mmal_queue_get(pool_out->queue)) != NULL) {
      while ((buffer = mmal_queue_get(pool_oute->queue)) != NULL) {
                   if (mmal_port_send_buffer(encoder->output[0], buffer) != MMAL_SUCCESS) {
                      Warning("failed to send buffer to encoder output for frame %d\n", frameCount);
                   }
		  
      }
     //Info("encode end");
     return (0);    
}	
mmal_resize.

Code: Select all

int  FfmpegCamera::mmal_resize(uint8_t** dbuffer) {   //uses mRawFrame data
	MMAL_BUFFER_HEADER_T *buffer;
	//Info("resize start");
	if ((buffer = mmal_queue_get(pool_inr->queue)) != NULL) { 
		 
         av_image_copy_to_buffer(buffer->data, bufsize, (const uint8_t **)mRawFrame->data, mRawFrame->linesize,
                                 AV_PIX_FMT_YUV420P, mRawFrame->width, mRawFrame->height, 1);
         buffer->length=bufsize;
         
         buffer->pts = buffer->dts = MMAL_TIME_UNKNOWN;
         //buffer->flags=packet->flags;
         
         buffer->alloc_size = resizer->input[0]->buffer_size;
            
         if (mmal_port_send_buffer(resizer->input[0], buffer) != MMAL_SUCCESS) {
                 Warning("failed to send I420 buffer to resizer for frame %d\n", frameCount);
                  
         }      
         
      }
      
      while ((buffer = mmal_queue_get(context.rqueue)) != NULL){
        
         memcpy((*dbuffer),buffer->data,width*height*colours);
         
         mmal_buffer_header_release(buffer);
      }

     
      //if ((buffer = mmal_queue_get(pool_outr->queue)) != NULL) {
      while ((buffer = mmal_queue_get(pool_outr->queue)) != NULL) {
                   if (mmal_port_send_buffer(resizer->output[0], buffer) != MMAL_SUCCESS) {
                      Warning("failed to send buffer to resizer output for frame %d\n", frameCount);
                   }
		  
      }
      //Info("resize end");
     return (0);    
}	


Mmal unload routine.

Code: Select all

int FfmpegCamera::CloseMmal(){
	
   mmal_port_disable(decoder->input[0]);
   mmal_port_disable(decoder->output[0]);
   mmal_port_disable(decoder->control); 
      
   mmal_port_flush(decoder->input[0]);
   mmal_port_flush(decoder->output[0]);
   mmal_port_flush(decoder->control); 
      
   mmal_port_disable(encoder->input[0]);   
   mmal_port_disable(encoder->output[0]);
   mmal_port_disable(encoder->control); 
      
   mmal_port_flush(encoder->input[0]);
   mmal_port_flush(encoder->output[0]);
   mmal_port_flush(encoder->control); 
   
   mmal_port_disable(resizer->input[0]);
   mmal_port_disable(resizer->output[0]);
   mmal_port_disable(resizer->control); 
      
   mmal_port_flush(resizer->input[0]);
   mmal_port_flush(resizer->output[0]);
   mmal_port_flush(resizer->control); 	
	
   if (decoder)
      mmal_component_destroy(decoder);
   if (resizer)
      mmal_component_destroy(resizer);
   if (encoder)
      mmal_component_destroy(encoder);
   if (pool_ind)
      mmal_pool_destroy(pool_ind);
   if (pool_outd)
      mmal_pool_destroy(pool_outd);
   if (pool_inr)
      mmal_pool_destroy(pool_inr);
   if (pool_outr)
      mmal_pool_destroy(pool_outr);
   if (pool_ine)
      mmal_pool_destroy(pool_ine);
   if (pool_oute)
      mmal_pool_destroy(pool_oute);
   if (context.equeue)
      mmal_queue_destroy(context.equeue);
   if (context.rqueue)
      mmal_queue_destroy(context.rqueue);
   if (context.dqueue)
      mmal_queue_destroy(context.dqueue);  
	 
   
   
   return 0;
}
Here is a link to the source code.

https://github.com/cmisip/ZoneMinder/bl ... camera.cpp

Thanks,
Chris

cmisip
Posts: 94
Joined: Tue Aug 25, 2015 12:38 am

Re: Getting lock memory failure on videocore with zero copy

Tue Aug 28, 2018 2:30 am

Here is a little more info. I get this in the logs every now and then:

Code: Select all

[ERROR: PORT: vc.ril.video_decode:ctr:0 Type: 7
This is followed by a BUS error.

I think this is coincident with these errors in dmesg:

Code: Select all

[  272.234787] [vc_sm_ioctl_lock]: failed to lock memory on videocore (status: 0, trans_id: 30374)
[  272.245142] [vcsm_vma_fault]: failed to lock memory on videocore (status: 0)
Thanks,
Chris

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

Re: Getting lock memory failure on videocore with zero copy

Tue Aug 28, 2018 10:40 am

cmisip wrote:
Tue Aug 28, 2018 2:03 am
OpenMMalDecoder. Why does it need 20 input buffers?
It doesn't. It defaults to 20 input buffers, but will run with >=1.

Nothing obviously wrong in the code, but it's only a small snippet and I haven't the time to look through your entire repo.

The one commit I recall is https://github.com/raspberrypi/userland ... dedca7f105 to make MMAL lock the buffer on request. Before that it was relying on the vma_fault to call across VCHI to lock the object on Videocore, and that had a deadlock condition.
At a guess you're trying to lock an invalid (eg already released) handle.
Software Engineer at Raspberry Pi Trading. Views expressed are still personal views.
Please don't send PMs asking for support - use the forum.
I'm not interested in doing contracts for bespoke functionality - please don't ask.

cmisip
Posts: 94
Joined: Tue Aug 25, 2015 12:38 am

Re: Getting lock memory failure on videocore with zero copy

Sat Sep 08, 2018 12:47 am

Could the problem with zero copy be related to some calloc errors I notice in dmesg. I followed the instructions in another thread and added the following in config.txt

Code: Select all

gpu_mem=256
gpu_mem_256=160
gpu_mem_512=416

cma_lwm=16
cma_hwm=32
And then in cmdline.txt

Code: Select all

coherent_pool=6M smsc95xx.turbo_mode=N
I turned on zero copy and I have been only running it for a day and I haven't seen the error yet.

Thanks,
Chris

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

Re: Getting lock memory failure on videocore with zero copy

Sat Sep 08, 2018 6:27 am

What calloc error in dmesg? Generally those are very bad, but I'm not going to guess where in the kernel it was.

Cma_lwm and cma_hwm do nothing. There was a module that tried to pass Gpu memory to the cma heap, but it never really worked and caused confusion.
You don't say which version of Pi you have, so I have no way of knowing which of those Gpu_mem settings is going to be active. They're just setting different values for platforms with 256 or 512 MB of ram.
Software Engineer at Raspberry Pi Trading. Views expressed are still personal views.
Please don't send PMs asking for support - use the forum.
I'm not interested in doing contracts for bespoke functionality - please don't ask.

cmisip
Posts: 94
Joined: Tue Aug 25, 2015 12:38 am

Re: Getting lock memory failure on videocore with zero copy

Sat Sep 15, 2018 4:46 pm

I am using a RPI 3B.

This is the output of uname a-

Code: Select all

Linux zoneminder 4.14.50-v7+ #1122 SMP Tue Jun 19 12:26:26 BST 2018 armv7l GNU/Linux
I have been running the program off and on because I am working on other aspects of the program at this time but during the time that I have run it, I haven't seen the vcore memory errors with zero copy turned on. I also haven't seen the calloc errors which is why I think they were related. If the config.txt change did not do anything, could the cmdline.txt change have resulted in the calloc errors disappearing?

Biggest problem right now is when the zoneminder supervisor process thinks the analyze process or the capture process is stuck because it has not communicated with it, it kills either the capture or the analyze process and restarts it. At this point, I may get an alignment trap. I can avoid this by avoiding the buffer overrun issue. It would be nice to get to the bottom of this issue at some point.

Thanks,
Chris

Return to “Advanced users”

Who is online

Users browsing this forum: Google [Bot] and 10 guests