为MJPEG流创建可被VLC播放的正确头部与流信息求助
Fixing MJPEG Stream for VLC Playback in C
Let's work through this step by step — I've dealt with exactly this issue when building MJPEG streams for media players like VLC. The core problem with your current code is that you're missing the critical initial HTTP response header, plus a few small but important buffer and flushing details.
Key Issues in Your Current Code
- No HTTP Response Header: VLC has no way to recognize your output as an MJPEG stream unless you first send a valid HTTP 200 OK response with the correct
Content-Typeheader. - Unsafe String Handling: Using
sprintfandstrcatcan lead to buffer overflows if your frame length is larger than expected. - Missing Output Flush: C's
stdoutis buffered by default — without flushing, your stream data might get stuck in the buffer instead of being sent to VLC immediately.
Corrected Implementation
Here's a revised version of your code that addresses all these issues:
1. Send the Initial HTTP Response Header
First, you need to tell VLC what kind of stream it's receiving. This only needs to be sent once at the start of the stream:
// Send HTTP response header (critical for VLC to recognize the stream) printf("HTTP/1.1 200 OK\r\n"); printf("Content-Type: multipart/x-mixed-replace; boundary=myboundary\r\n"); printf("Connection: close\r\n"); printf("\r\n"); fflush(stdout); // Force header to be sent immediately
2. Revised Frame Sending Loop
Now update your frame loop to use safer string handling and ensure data is flushed:
// Assume: // - jpg: pointer to your raw JPEG frame data (must include full SOI 0xFFD8 and EOI 0xFFD9 markers) // - frame_size: size of the JPEG frame in bytes (replace your 'ptr' variable with this clearer name) while (/* Your frame generation loop condition (e.g., while still capturing frames) */) { char boundary_buffer[256]; // Larger buffer to avoid overflow int boundary_len; // Safely build the boundary header with snprintf (avoids buffer overflow) boundary_len = snprintf(boundary_buffer, sizeof(boundary_buffer), "--myboundary\r\nContent-Type: image/jpeg\r\nContent-Length: %zu\r\n\r\n", frame_size); // Check for buffer overflow (shouldn't happen with 256-byte buffer, but safe to handle) if (boundary_len < 0 || boundary_len >= sizeof(boundary_buffer)) { fprintf(stderr, "Boundary buffer overflow!\n"); break; } // Send the boundary header fwrite(boundary_buffer, 1, boundary_len, stdout); // Send the JPEG frame data fwrite(jpg, 1, frame_size, stdout); // Flush immediately to ensure data reaches VLC without delay fflush(stdout); // Optional: Control frame rate (e.g., 30 FPS = ~33ms per frame) usleep(33000); }
Critical Notes to Ensure Playback
- Valid JPEG Frames: Double-check that each
jpgbuffer starts with0xFFD8(Start of Image) and ends with0xFFD9(End of Image) — even if the JPEG is "valid" otherwise, missing these markers will break playback in VLC. - Buffer Flushing: Never skip
fflush(stdout)— without it, your stream data will get trapped in the C standard library's buffer, and VLC will wait indefinitely for data. - Boundary Consistency: The boundary string in the HTTP header (
myboundary) must match the prefix in your frame headers (--myboundary). Don't add extra characters or change this mid-stream. - Socket Considerations: If you're sending this stream over a network socket instead of stdout, ensure you've disabled buffering for the socket (or use
fflushif wrapping it withfdopen).
内容的提问来源于stack exchange,提问作者John Smith
相关产品推荐
相关产品推荐

