@@ -87,12 +87,34 @@ void isoc_transfer_callback(usb_transfer_t *transfer)
8787
8888 // Check for start of new frame
8989 const uvc_payload_header_t * payload_header = (const uvc_payload_header_t * )payload ;
90+ // Derive payload data pointer/length once and reuse below
91+ const uint8_t * payload_data = payload + payload_header -> bHeaderLength ;
92+ const size_t payload_data_len = isoc_desc -> actual_num_bytes - payload_header -> bHeaderLength ;
93+
94+ if (payload_data_len == 0 ) {
95+ goto next_isoc_packet ;
96+ }
97+
98+ // Check for error flag
99+ if (payload_header -> bmHeaderInfo .error ) {
100+ ESP_LOGW (TAG , "frame error" );
101+ uvc_stream -> single_thread .skip_current_frame = true;
102+ }
103+
90104 const bool start_of_frame = (uvc_stream -> single_thread .current_frame_id != payload_header -> bmHeaderInfo .frame_id );
91105 if (start_of_frame ) {
92106 // We detected start of new frame. Update Frame ID and start fetching this frame
93107 uvc_stream -> single_thread .current_frame_id = payload_header -> bmHeaderInfo .frame_id ;
94108 uvc_stream -> single_thread .skip_current_frame = payload_header -> bmHeaderInfo .error ;
95109
110+ // Check mjpeg frame start
111+ if (uvc_stream -> dynamic .vs_format .format == UVC_VS_FORMAT_MJPEG &&
112+ payload_data [0 ] != 0xff && payload_data [1 ] != 0xd8 ) {
113+ // We received frame with invalid frame, skip this frame
114+ uvc_stream -> single_thread .skip_current_frame = true;
115+ ESP_LOGW (TAG , "invalid MJPEG SOI" );
116+ }
117+
96118 // Get free frame buffer for this new frame
97119 UVC_ENTER_CRITICAL ();
98120 const bool need_new_frame = (uvc_stream -> dynamic .streaming && !uvc_stream -> dynamic .current_frame );
@@ -115,20 +137,15 @@ void isoc_transfer_callback(usb_transfer_t *transfer)
115137 }
116138 } else {
117139 // We received SoF but current_frame is not NULL: We missed EoF - reset the frame buffer
140+ ESP_EARLY_LOGW (TAG , "missed EoF" );
141+ uvc_stream -> single_thread .skip_current_frame = true;
118142 uvc_frame_reset (uvc_stream -> dynamic .current_frame );
119143 UVC_EXIT_CRITICAL ();
120144 }
121145 }
122146
123- // Check for error flag
124- if (payload_header -> bmHeaderInfo .error ) {
125- uvc_stream -> single_thread .skip_current_frame = true;
126- }
127-
128147 // Add received data to frame buffer
129148 if (!uvc_stream -> single_thread .skip_current_frame ) {
130- const uint8_t * payload_data = payload + payload_header -> bHeaderLength ;
131- const size_t payload_data_len = isoc_desc -> actual_num_bytes - payload_header -> bHeaderLength ;
132149 uvc_host_frame_t * current_frame = UVC_ATOMIC_LOAD (uvc_stream -> dynamic .current_frame );
133150
134151 esp_err_t ret = uvc_frame_add_data (current_frame , payload_data , payload_data_len );
@@ -157,6 +174,11 @@ void isoc_transfer_callback(usb_transfer_t *transfer)
157174 uvc_host_frame_t * this_frame = uvc_stream -> dynamic .current_frame ;
158175 uvc_stream -> dynamic .current_frame = NULL ; // Stop writing more data to this frame
159176
177+ if (this_frame && this_frame -> data_len <= 2 ) {
178+ // We received too small frame, skip this frame
179+ uvc_stream -> single_thread .skip_current_frame = true;
180+ }
181+
160182 // Determine if we should invoke the frame callback:
161183 // Only invoke the callback if streaming is active, a frame callback exists,
162184 // and we have a valid frame to pass to the user.
0 commit comments