Skip to main content
mthanh2602
Associate II
November 29, 2018
Solved

Problem with MJPEG output data (STM32F769)

  • November 29, 2018
  • 5 replies
  • 2457 views

Hello everyone.

I have a problem with my code. I'm trying to write a program to take picture from camera and save it as motion jpeg video (MJPEG) in to USB, using JPEG encoder. I build already the header and the structure of MJPEG file but it had problem when I try to run that video file. Also by the source code was provided by STM, I finished to create the JPEG file.

This link below simply show some information about MJPEG construction https://blog.goo.ne.jp/sirius506/e/442f430a1531c018a32471f1ecd4ae77

I had checked and found out that the output data of frames and the idx1 is written by f_write was incorrect. Sometime 2 bytes were written again. Has someone told me that problem maybe is "3 bytes were dropped".

The header data I wrote to the begin of file is always right, but the data that I wrote to frame place and idx1 place usually has problem.

Ex: I want to write data like this below

01 02 03 04 05

01 02 03 04 05

01 02 03 04 05

01 02 03 04 05

but the output was like this

01 02 03 04 05

*01 02 01 02* 03

04 05 01 02 03

04 05 01 02 03

I had tried to change many way like make it slow (fps = 1 or 2) or change the parameter of f_write function , but it still error.

This is f_write function

UINT frame_count = 0;
f_write (&JPEG_File, Frame, sizeof(Frame), &frame_count);
 
FRESULT f_write (
FIL* fp, /* Pointer to the file object */
const void* buff, /* Pointer to the data to be written */
UINT btw, /* Number of bytes to write */
UINT* bw /* Pointer to number of bytes written */
)

 Write frames code

uint8_t buf_4[4];
if(f_open(&JPEG_File, "video.avi", FA_CREATE_ALWAYS|FA_WRITE) == FR_OK) // 4
{
 
 //header
 UINT header_count = 0;
 f_write (&JPEG_File, Header , 5754, &header_count);
 
 //create avi with 50 frames
 for(int i_loop = 0; i_loop < num_frame_tam; i_loop++){
 /* Suspend the camera capture */
 BSP_CAMERA_Suspend();
 cameraState = CAMERA_STATE_SAVING_PICTURE;
 PicturePrepare1(); //prepare buffer for writer
 
 uint32_t before_avi_file = f_size(&JPEG_File); //get before size
 
 //8 connected bytes stand before each frame
 UINT frame_count = 2;
 uint8_t connect_frame[8] = {0x30, 0x30, 0x64, 0x63, 0x00, 0x00, 0x00, 0x00};
 f_write (&JPEG_File, connect_frame , 8, &frame_count);
 
 //write frame by Jpeg encoder
 /*
 uint32_t JpegEncodeProcessing_End = 0;
 JPEG_Encode_DMA(&JPEG_Handle, CONVERTED_FRAME_BUFFER,
 CameraResX * CameraResY * RGB888_BYTE_PER_PIXEL, &JPEG_File);
 
 do
 {
 JPEG_EncodeInputHandler(&JPEG_Handle);
 JpegEncodeProcessing_End = JPEG_EncodeOutputHandler(&JPEG_Handle);
 
 } while(JpegEncodeProcessing_End == 0);
 */
 
 //write the data was prepared before for test
 f_write (&JPEG_File, frame , sizeof(frame), &frame_count); //
 
 //calculate frame size and change last 4 bytes of connected 8bytes before each frame
 uint32_t newframe_size = f_size(&JPEG_File) - before_avi_file - 8; // size of frame
 
 num_to_array_4byte(newframe_size, buf_4);
 
 f_lseek(&JPEG_File, before_avi_file + 4);
 UINT bytesWritefile = 0;
 f_write (&JPEG_File, buf_4 , 4, &bytesWritefile);// ghi vao gia size of frame
 f_lseek(&JPEG_File, f_size(&JPEG_File));
 
 
 ////create dx1
 uint8_t idx1_combi[16] = {0x30, 0x30, 0x64, 0x63, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 change_aray_noptr(idx1_combi, 12, buf_4 , 4); //ghi real size vao byte 12
 
 num_to_array_4byte(idx1_next_size, buf_4);
 change_aray_noptr(idx1_combi, 8, buf_4 , 4); //ghi tong size vao byte 8
 
 //increase size of idx1 
 change_aray_noptr(idx1,idx1_size, idx1_combi, 16);
 idx1_size +=16;
 
 idx1_next_size = idx1_next_size + newframe_size + 8; // 8 bit dau moi frame
 
 
 BSP_CAMERA_Resume();
 
 }//for
 
 
 //Write idx1
 num_to_array_4byte(idx1_size-8, buf_4);
 change_aray_noptr(idx1, 4, buf_4 , 4);
 
 UINT after_write = 0;
 f_write (&JPEG_File, idx1, idx1_size, &after_write);
 
 //fill size of avi in the header
 f_lseek(&JPEG_File, 4);
 num_to_array_4byte(f_size(&JPEG_File) - 8, buf_4);
 f_write (&JPEG_File, buf_4 , 4, &after_write);
 
 //fill total frame size
 f_lseek(&JPEG_File, 5742+4);
 num_to_array_4byte(idx1_next_size, buf_4);
 f_write (&JPEG_File, buf_4 , 4, &after_write);
 
 //Close the JPEG file
 f_close(&JPEG_File);
} 

USB init

USBH_StatusTypeDef USBH_LL_Init(USBH_HandleTypeDef *phost)
{
#ifdef USE_USB_HS 
 /* Set the LL driver parameters */
 hhcd.Instance = USB_OTG_HS;
 hhcd.Init.Host_channels = 11; 
 hhcd.Init.dma_enable = 1;
 hhcd.Init.low_power_enable = 0;
#ifdef USE_USB_HS_IN_FS
 hhcd.Init.phy_itface = HCD_PHY_EMBEDDED; //This is not
#else 
 hhcd.Init.phy_itface = HCD_PHY_ULPI; //This ok
#endif 
 hhcd.Init.Sof_enable = 0;
 hhcd.Init.speed = HCD_SPEED_HIGH;
 hhcd.Init.use_external_vbus = 1; 
 /* Link the driver to the stack */
 hhcd.pData = phost;
 phost->pData = &hhcd;
 /* Initialize the LL driver */
 HAL_HCD_Init(&hhcd);
 
#endif /*USE_USB_HS*/ 
 USBH_LL_SetTimer(phost, HAL_HCD_GetCurrentFrame(&hhcd));
 
 return USBH_OK;
}

 Anybody have experience about this? I am very appreciate with any advise.

Sorry for my English. Thank so much.

I opened my MJPEG (avi) file by RIFF pad and it show me that the header was written into this output file is completely okay.

0690X000006CXhBQAW.png

This topic has been closed for replies.
Best answer by mthanh2602

Yes, I'm writing data to USB. 1 VGA frame around 1.5kbyte.

But good news is I had fixed my problem. The max define buffer of f_write is 512. It's okay when I increase this value to 1024 but not effective with 2048 and 4096. So I divided a big data i want to write to many smaller 512 byte packages and write it to USB. No problems happened and the AVI file run completely good. But the frame rate still slow and now I'm try to increase it.

Many thanks for your help.

5 replies

Tesla DeLorean
Guru
December 3, 2018

Can't open your other post, gets some error

Not sure how I'm supposed to debug the code as presented. You're going to need to instrument things, track how f_write() is being called, have a running total for bytes written, and running CRC, and compare that to the resultant file as you examine it.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
mthanh2602
Associate II
December 3, 2018

Hi Clive. Many thanks for your reply.

Maybe it was closed because I posted the same thing again. Have person told me that this mistake is "3 bytes were dropped", do you have any ideal about this?

I created one data with 5754 bytes and write it 50 times into USB. After the writing done, i had checked, compared and it show me the "2 bytes were written again" mistake like i described. What do you mean about CRC, i had thought CRC just used when we send or received data?

This is my writer code

for(int i_loop = 0; i_loop < num_frame_tam; i_loop++){
	/* Suspend the camera capture */
	BSP_CAMERA_Suspend();
	cameraState = CAMERA_STATE_SAVING_PICTURE;
	PicturePrepare1(); //Creater buffer for writer
 
	//the connect 8 bytes between each 2 frames
	UINT frame_count = 2;
	uint8_t connect_frame[8] = {0x30, 0x30, 0x64, 0x63, 0x00, 0x00, 0x00, 0x00};
	f_write (&JPEG_File, connect_frame , 8, &frame_count);
 
	f_write (&JPEG_File, frame, sizeof(frame), &frame_count);
 
	BSP_CAMERA_Resume();
}//for

Tesla DeLorean
Guru
December 3, 2018

Ok, but does f_write return an error, or a count indicating it didn't write what was requested?

I think the only way for you to know what is happening in your situation is for you to analyze it.. I presume the f_write is from FatFs, are you writing this to a MicroSD card or USB Stick?

How large is the "frame" here? Is is consistent from one conversion to another?

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
MSale.1
Senior
July 21, 2020

@mthanh2602​ 

Hey,

I am also trying to do video encoding. is it possible to share your AVI header because i am having problem in creating it?