### RTSP Server Implementation in C Source: https://context7.com/ireader/media-server/llms.txt Implements an RTSP server to handle client requests for media streaming. It defines handlers for RTSP methods like DESCRIBE, SETUP, PLAY, and TEARDOWN, and uses a provided socket for communication. Dependencies include 'rtsp-server.h'. ```c #include "rtsp-server.h" static int rtsp_send(void* param, const void* data, size_t bytes) { int socket = *(int*)param; return send(socket, data, bytes, 0); } static int on_describe(void* ptr, rtsp_server_t* rtsp, const char* uri) { printf("DESCRIBE: %s\n", uri); // Generate SDP const char* sdp = "v=0\r\n" "o=- 0 0 IN IP4 127.0.0.1\r\n" "s=Stream\r\n" "c=IN IP4 0.0.0.0\r\n" "t=0 0\r\n" "m=video 0 RTP/AVP 96\r\n" "a=rtpmap:96 H264/90000\r\n" "a=fmtp:96 profile-level-id=42E01E\r\n"; return rtsp_server_reply_describe(rtsp, 200, sdp); } static int on_setup(void* ptr, rtsp_server_t* rtsp, const char* uri, const char* session, const struct rtsp_header_transport_t transports[], size_t num) { printf("SETUP: %s\n", uri); char transport[256]; snprintf(transport, sizeof(transport), "RTP/AVP;unicast;client_port=%d-%d;server_port=%d-%d", transports[0].rtp.u.client_port1, transports[0].rtp.u.client_port2, 5000, 5001); return rtsp_server_reply_setup(rtsp, 200, "123456789", transport); } static int on_play(void* ptr, rtsp_server_t* rtsp, const char* uri, const char* session, const int64_t* npt, const double* scale) { printf("PLAY: %s\n", uri); int64_t npt_start = 0; const char* rtpinfo = "url=/track1;seq=1;rtptime=0"; return rtsp_server_reply_play(rtsp, 200, &npt_start, NULL, rtpinfo); } static int on_teardown(void* ptr, rtsp_server_t* rtsp, const char* uri, const char* session) { printf("TEARDOWN: %s\n", uri); return rtsp_server_reply(rtsp, 200); } int main() { int socket_fd = /* TCP socket from client */; struct rtsp_handler_t handler = { .send = rtsp_send, .ondescribe = on_describe, .onsetup = on_setup, .onplay = on_play, .onteardown = on_teardown }; rtsp_server_t* rtsp = rtsp_server_create("0.0.0.0", 554, &handler, NULL, &socket_fd); uint8_t buffer[4096]; while (1) { int n = recv(socket_fd, buffer, sizeof(buffer), 0); if (n <= 0) break; size_t consumed = n; rtsp_server_input(rtsp, buffer, &consumed); } rtsp_server_destroy(rtsp); return 0; } ``` -------------------------------- ### Implement RTSP Client for Media Streaming Source: https://context7.com/ireader/media-server/llms.txt This C code demonstrates an RTSP client for connecting to a streaming server, handling SDP negotiation, and receiving RTP streams. It defines callbacks for sending RTSP requests, allocating RTP ports, and handling different RTSP messages like DESCRIBE, SETUP, and PLAY. The `rtsp_client_input` function processes incoming RTSP responses. ```c #include "rtsp-client.h" #include static int rtsp_send(void* param, const char* uri, const void* req, size_t bytes) { int socket = *(int*)param; return send(socket, req, bytes, 0); } static int rtsp_rtpport(void* param, int media, const char* source, unsigned short port[2], char* ip, int len) { // Allocate RTP/RTCP port pair port[0] = 5000; // RTP port port[1] = 5001; // RTCP port strcpy(ip, "0.0.0.0"); return 0; } static int on_describe(void* param, const char* sdp, int len) { printf("Received SDP:\n%.*s\n", len, sdp); return 0; } static int on_setup(void* param, int timeout, int64_t duration) { printf("Session timeout: %d, duration: %lld\n", timeout, duration); return 0; } static int on_play(void* param, int media, const uint64_t* nptbegin, const uint64_t* nptend, const double* scale, const struct rtsp_rtp_info_t* rtpinfo, int count) { printf("Playing...\n"); return 0; } static void on_rtp(void* param, uint8_t channel, const void* data, uint16_t bytes) { printf("RTP data: channel=%d, size=%d\n", channel, bytes); // Process RTP packet } int main() { int socket_fd = /* TCP socket connected to RTSP server */; struct rtsp_client_handler_t handler = { .send = rtsp_send, .rtpport = rtsp_rtpport, .ondescribe = on_describe, .onsetup = on_setup, .onplay = on_play, .onrtp = on_rtp }; rtsp_client_t* rtsp = rtsp_client_create("rtsp://server/stream", NULL, NULL, &handler, &socket_fd); // Send DESCRIBE rtsp_client_describe(rtsp); // Receive RTSP response uint8_t buffer[4096]; int n = recv(socket_fd, buffer, sizeof(buffer), 0); rtsp_client_input(rtsp, buffer, n); // After receiving SDP, setup and play const char* sdp = "..."; // From on_describe callback rtsp_client_setup(rtsp, sdp, strlen(sdp)); // Continue receiving and processing responses while (1) { n = recv(socket_fd, buffer, sizeof(buffer), 0); if (n <= 0) break; rtsp_client_input(rtsp, buffer, n); } rtsp_client_teardown(rtsp); rtsp_client_destroy(rtsp); return 0; } ``` -------------------------------- ### RTMP Client: Publish Live Streams (C) Source: https://context7.com/ireader/media-server/llms.txt Publish live video and audio streams to an RTMP server using the RTMP client API. This involves creating an RTMP client instance, starting in publish mode, and then pushing video and audio frames in FLV format. It also includes handling incoming data from the server. ```c #include "rtmp-client.h" #include static int rtmp_send(void* param, const void* header, size_t len, const void* payload, size_t bytes) { int socket = *(int*)param; send(socket, header, len, 0); send(socket, payload, bytes, 0); return 0; } int main() { int socket_fd = /* TCP socket connected to RTMP server */; struct rtmp_client_handler_t handler = { .send = rtmp_send }; rtmp_client_t* rtmp = rtmp_client_create("live", "stream", "rtmp://server/live", &socket_fd, &handler); // Start publishing rtmp_client_start(rtmp, 0); // 0 = publish mode // Push video frames (FLV format) uint8_t video_packet[10000] = { /* FLV video tag data */ }; uint32_t video_pts = 0; rtmp_client_push_video(rtmp, video_packet, sizeof(video_packet), video_pts); // Push audio frames (FLV format) uint8_t audio_packet[512] = { /* FLV audio tag data */ }; uint32_t audio_pts = 0; rtmp_client_push_audio(rtmp, audio_packet, sizeof(audio_packet), audio_pts); // Receive data from socket and feed to client uint8_t recv_buffer[4096]; int recv_len = recv(socket_fd, recv_buffer, sizeof(recv_buffer), 0); rtmp_client_input(rtmp, recv_buffer, recv_len); rtmp_client_destroy(rtmp); return 0; } ``` -------------------------------- ### Convert H.264 Annex-B and MP4 Formats (C) Source: https://context7.com/ireader/media-server/llms.txt Converts H.264 bitstreams between Annex-B format (using start codes like 0x000001) and MP4 format (using length prefixes). It relies on the mpeg4-avc library. Input includes AVCDecoderConfigurationRecord (extradata) and the frame data in one format, outputting the converted frame data and parsing information. ```c #include "mpeg4-avc.h" #include int main() { // Parse AVCDecoderConfigurationRecord (extradata from MP4) uint8_t avc_extradata[100] = { /* SPS/PPS from MP4 */ }; struct mpeg4_avc_t avc; if (mpeg4_avc_decoder_configuration_record_load(avc_extradata, sizeof(avc_extradata), &avc) <= 0) { printf("Failed to parse AVC configuration\n"); return -1; } printf("Profile: %d, Level: %d, NALULength: %d\n", avc.profile, avc.level, avc.nalu); // Convert MP4 format (length-prefix) to Annex-B (start codes) uint8_t mp4_frame[10000] = { /* length prefix + NAL units */ }; uint8_t annexb_output[20000]; int annexb_size = h264_mp4toannexb(&avc, mp4_frame, sizeof(mp4_frame), annexb_output, sizeof(annexb_output)); printf("Converted to Annex-B: %d bytes\n", annexb_size); // Convert Annex-B (start codes) to MP4 format (length-prefix) uint8_t annexb_frame[10000] = { 0x00, 0x00, 0x00, 0x01, /* NAL units */ }; uint8_t mp4_output[20000]; int vcl = 0, update = 0; int mp4_size = h264_annexbtomp4(&avc, annexb_frame, sizeof(annexb_frame), mp4_output, sizeof(mp4_output), &vcl, &update); printf("Converted to MP4: %d bytes, VCL=%d, config_update=%d\n", mp4_size, vcl, update); return 0; } ``` -------------------------------- ### Write MP4 Files with Multiple Audio/Video Tracks (C) Source: https://context7.com/ireader/media-server/llms.txt This C code demonstrates how to create standard MP4 files. It utilizes the 'mov-writer' library to add video (H.264) and audio (AAC) tracks, write sample data with timestamps, and finalize the MP4 structure. Ensure 'mov-writer.h' and 'mov-format.h' are included. ```c #include "mov-writer.h" #include "mov-format.h" int main() { FILE* fp = fopen("output.mp4", "wb"); // Create writer with faststart flag mov_writer_t* mov = mov_writer_create(mov_file_buffer(), fp, MOV_FLAG_FASTSTART); if (!mov) { printf("Failed to create MP4 writer\n"); return -1; } // Add video track uint8_t h264_extradata[100] = { /* AVCDecoderConfigurationRecord */ }; int video_track = mov_writer_add_video(mov, MOV_OBJECT_H264, 1920, 1080, h264_extradata, sizeof(h264_extradata)); // Add audio track uint8_t aac_extradata[16] = { /* AudioSpecificConfig */ }; int audio_track = mov_writer_add_audio(mov, MOV_OBJECT_AAC, 2, 16, 44100, aac_extradata, sizeof(aac_extradata)); // Write video samples (MP4 format - length prefixes) uint8_t video_frame[10000] = { /* H.264 MP4 format data */ }; int64_t video_pts = 0, video_dts = 0; mov_writer_write(mov, video_track, video_frame, sizeof(video_frame), video_pts, video_dts, MOV_AV_FLAG_KEYFREAME); // Write audio samples (raw AAC) uint8_t audio_frame[512] = { /* raw AAC data */ }; int64_t audio_pts = 0; mov_writer_write(mov, audio_track, audio_frame, sizeof(audio_frame), audio_pts, audio_pts, 0); mov_writer_destroy(mov); fclose(fp); return 0; } ``` -------------------------------- ### Implement SIP User Agent Client (UAC) Source: https://context7.com/ireader/media-server/llms.txt This C code implements a SIP User Agent Client (UAC) for making calls and registering with a SIP server. It relies on custom SIP agent and UAC libraries. The `sip_send` function handles outgoing SIP messages, and callbacks `on_register_reply` and `on_invite_reply` process server responses. The `main` function sets up the SIP agent, performs registration and call initiation, and enters a receive loop to process incoming SIP messages. ```c #include "sip-agent.h" #include "sip-uac.h" static int sip_send(void* param, const struct cstring_t* protocol, const struct cstring_t* url, const struct cstring_t* received, int rport, const void* data, int bytes) { int socket = *(int*)param; printf("Sending SIP message: %d bytes\n", bytes); return send(socket, data, bytes, 0); } static int on_register_reply(void* param, const struct sip_message_t* reply, struct sip_uac_transaction_t* t, int code) { printf("REGISTER response: %d\n", code); if (code == 200) { printf("Registration successful\n"); } return 0; } static int on_invite_reply(void* param, const struct sip_message_t* reply, struct sip_uac_transaction_t* t, struct sip_dialog_t* dialog, const struct cstring_t* id, int code) { printf("INVITE response: %d\n", code); if (code == 200) { printf("Call established\n"); // Send ACK sip_uac_ack(sip_agent, dialog, NULL, NULL); } return 0; } int main() { int socket_fd = /* UDP socket */; struct sip_uas_handler_t handler = { .send = sip_send }; struct sip_agent_t* sip = sip_agent_create(&handler); // REGISTER with SIP server sip_uac_register(sip, "sip:user@domain.com", "sip:registrar.domain.com", 3600, on_register_reply, &socket_fd); // Make a call (INVITE) sip_uac_invite(sip, "sip:caller@domain.com", "sip:callee@domain.com", on_invite_reply, &socket_fd); // Receive loop uint8_t buffer[4096]; while (1) { int n = recv(socket_fd, buffer, sizeof(buffer), 0); if (n <= 0) break; struct sip_message_t* msg = sip_message_parse(buffer, n); sip_agent_input(sip, msg, &socket_fd); sip_message_destroy(msg); } sip_agent_destroy(sip); return 0; } ``` -------------------------------- ### Write FLV Files with Audio/Video Packets using C Source: https://context7.com/ireader/media-server/llms.txt Creates FLV files by writing audio and video packets along with their timestamps. It utilizes 'flv-writer.h' and 'flv-proto.h'. The 'flv_writer_input' function is used to append packets, requiring the packet type, data, size, and presentation timestamp (PTS). ```c #include "flv-writer.h" #include "flv-proto.h" int main() { // Create FLV writer void* writer = flv_writer_create("output.flv"); if (!writer) { printf("Failed to create FLV file\n"); return -1; } // Write video packet (H.264) uint8_t video_data[1024] = { /* H.264 data */ }; int video_size = 1024; uint32_t video_pts = 0; if (flv_writer_input(writer, FLV_TYPE_VIDEO, video_data, video_size, video_pts) != 0) { printf("Failed to write video\n"); } // Write audio packet (AAC) uint8_t audio_data[512] = { /* AAC data */ }; int audio_size = 512; uint32_t audio_pts = 0; if (flv_writer_input(writer, FLV_TYPE_AUDIO, audio_data, audio_size, audio_pts) != 0) { printf("Failed to write audio\n"); } flv_writer_destroy(writer); return 0; } ``` -------------------------------- ### MP4 File Reader: Extract track info and read samples Source: https://context7.com/ireader/media-server/llms.txt This C code snippet shows how to read MP4 files using the 'mov-reader' library. It demonstrates extracting video and audio track information, including codec details and extradata, and processing individual samples with their timestamps and flags. Dependencies include 'mov-reader.h' and 'mov-format.h'. ```c #include "mov-reader.h" #include "mov-format.h" static void mov_video_info(void* param, uint32_t track, uint8_t object, int width, int height, const void* extra, size_t bytes) { printf("Video Track %d: codec=0x%02x, %dx%d, extradata=%zu bytes\n", track, object, width, height, bytes); } static void mov_audio_info(void* param, uint32_t track, uint8_t object, int channels, int bits, int sample_rate, const void* extra, size_t bytes) { printf("Audio Track %d: codec=0x%02x, %dch, %d-bit, %d Hz, extradata=%zu bytes\n", track, object, channels, bits, sample_rate, bytes); } static void mov_onread(void* param, uint32_t track, const void* buffer, size_t bytes, int64_t pts, int64_t dts, int flags) { printf("Track %d: pts=%lld, dts=%lld, size=%zu, keyframe=%d\n", track, pts, dts, bytes, flags & MOV_AV_FLAG_KEYFREAME); // Process sample data } int main() { FILE* fp = fopen("input.mp4", "rb"); mov_reader_t* mov = mov_reader_create(mov_file_buffer(), fp); if (!mov) { printf("Failed to open MP4 file\n"); return -1; } // Get track information struct mov_reader_trackinfo_t info = { .onvideo = mov_video_info, .onaudio = mov_audio_info }; mov_reader_getinfo(mov, &info, NULL); // Get duration uint64_t duration = mov_reader_getduration(mov); printf("Duration: %llu ms\n", duration); // Read samples uint8_t buffer[2 * 1024 * 1024]; while (mov_reader_read(mov, buffer, sizeof(buffer), mov_onread, NULL) > 0) { // Continue reading } // Seek to timestamp int64_t seek_time = 5000; // 5 seconds mov_reader_seek(mov, &seek_time); mov_reader_destroy(mov); fclose(fp); return 0; } ``` -------------------------------- ### Write MKV/WebM Files - C Source: https://context7.com/ireader/media-server/llms.txt Creates Matroska/WebM files with support for multiple audio and video tracks. It handles adding tracks with specific codecs and dimensions, and writing encoded frames with timestamps and flags. Dependencies include 'mkv-writer.h' and 'mkv-format.h'. Inputs are an output file path and frame data, with the output being a generated MKV file. ```c #include "mkv-writer.h" #include "mkv-format.h" int main() { FILE* fp = fopen("output.mkv", "wb"); mkv_writer_t* mkv = mkv_writer_create(mkv_file_buffer(), fp, 0); // Add video track uint8_t h264_extradata[100] = { /* SPS/PPS */ }; int video_track = mkv_writer_add_video(mkv, MKV_CODEC_VIDEO_H264, 1920, 1080, h264_extradata, sizeof(h264_extradata)); // Add audio track uint8_t aac_extradata[16] = { /* AudioSpecificConfig */ }; int audio_track = mkv_writer_add_audio(mkv, MKV_CODEC_AUDIO_AAC, 2, 16, 44100, aac_extradata, sizeof(aac_extradata)); // Write samples uint8_t video_frame[10000] = { /* H.264 data */ }; int64_t pts = 0, dts = 0; mkv_writer_write(mkv, video_track, video_frame, sizeof(video_frame), pts, dts, MKV_FLAGS_KEYFRAME); uint8_t audio_frame[512] = { /* AAC data */ }; mkv_writer_write(mkv, audio_track, audio_frame, sizeof(audio_frame), pts, pts, 0); mkv_writer_destroy(mkv); fclose(fp); return 0; } ``` -------------------------------- ### Read FLV Files Tag by Tag using C Source: https://context7.com/ireader/media-server/llms.txt Reads FLV files tag by tag to extract audio, video, and script data. It uses the 'flv-reader.h' and 'flv-proto.h' headers. The function 'flv_reader_read' returns tags sequentially, and the extracted data can be processed based on its type. ```c #include "flv-reader.h" #include "flv-proto.h" int main() { // Create FLV reader from file void* reader = flv_reader_create("input.flv"); if (!reader) { printf("Failed to open FLV file\n"); return -1; } // Read FLV tags int type; uint32_t timestamp; size_t taglen; uint8_t buffer[2 * 1024 * 1024]; while (1 == flv_reader_read(reader, &type, ×tamp, &taglen, buffer, sizeof(buffer))) { switch (type) { case FLV_TYPE_AUDIO: printf("Audio tag: timestamp=%u, size=%zu\n", timestamp, taglen); break; case FLV_TYPE_VIDEO: printf("Video tag: timestamp=%u, size=%zu\n", timestamp, taglen); break; case FLV_TYPE_SCRIPT: printf("Script tag: timestamp=%u, size=%zu\n", timestamp, taglen); break; } } flv_reader_destroy(reader); return 0; } ``` -------------------------------- ### Demux FLV to Elementary Streams (C) Source: https://context7.com/ireader/media-server/llms.txt Demultiplexes FLV tags into H.264 Annex-B video elementary streams and AAC ADTS audio elementary streams. It requires FLV demuxer and reader libraries. Input is an FLV file, and output is a raw H.264 file and console logs for audio information. Handles video keyframes and PTS/DTS timestamps. ```c #include "flv-demuxer.h" #include "flv-reader.h" static int flv_video_handler(void* param, int codec, const void* data, size_t bytes, uint32_t pts, uint32_t dts, int flags) { FILE* fp = (FILE*)param; // Write H.264 Annex-B stream fwrite(data, 1, bytes, fp); printf("Video: codec=%d, pts=%u, dts=%u, size=%zu, keyframe=%d\n", codec, pts, dts, bytes, flags & FLV_VIDEO_KEY_FRAME); return 0; } static int flv_audio_handler(void* param, int codec, const void* data, size_t bytes, uint32_t pts, uint32_t dts) { // Write AAC ADTS stream printf("Audio: codec=%d, pts=%u, size=%zu\n", codec, pts, bytes); return 0; } int main() { void* reader = flv_reader_create("input.flv"); FILE* h264_fp = fopen("output.h264", "wb"); struct flv_demuxer_handler_t handler = { .video = flv_video_handler, .audio = flv_audio_handler }; flv_demuxer_t* demuxer = flv_demuxer_create(&handler, h264_fp); int type; uint32_t timestamp; size_t taglen; uint8_t buffer[2 * 1024 * 1024]; while (1 == flv_reader_read(reader, &type, ×tamp, &taglen, buffer, sizeof(buffer))) { flv_demuxer_input(demuxer, type, buffer, taglen, timestamp); } flv_demuxer_destroy(demuxer); fclose(h264_fp); flv_reader_destroy(reader); return 0; } ``` -------------------------------- ### RTMP Client: Play Live Streams (C) Source: https://context7.com/ireader/media-server/llms.txt Play live streams from an RTMP server and receive video and audio data through callbacks. This involves setting up callbacks for video and audio, creating an RTMP client instance in play mode, and then feeding received data into the client for processing. ```c #include "rtmp-client.h" static int on_video(void* param, const void* data, size_t bytes, uint32_t timestamp) { printf("Received video: %zu bytes at %u ms\n", bytes, timestamp); // Process FLV video tag data return 0; } static int on_audio(void* param, const void* data, size_t bytes, uint32_t timestamp) { printf("Received audio: %zu bytes at %u ms\n", bytes, timestamp); // Process FLV audio tag data return 0; } static int rtmp_send(void* param, const void* header, size_t len, const void* payload, size_t bytes) { int socket = *(int*)param; send(socket, header, len, 0); send(socket, payload, bytes, 0); return 0; } int main() { int socket_fd = /* TCP socket connected to RTMP server */; struct rtmp_client_handler_t handler = { .send = rtmp_send, .onvideo = on_video, .onaudio = on_audio }; rtmp_client_t* rtmp = rtmp_client_create("live", "stream", "rtmp://server/live/stream", &socket_fd, &handler); // Start playing rtmp_client_start(rtmp, 1); // 1 = play mode // Receive loop uint8_t buffer[4096]; while (1) { int n = recv(socket_fd, buffer, sizeof(buffer), 0); if (n <= 0) break; rtmp_client_input(rtmp, buffer, n); } rtmp_client_destroy(rtmp); return 0; } ``` -------------------------------- ### Generate MPEG-DASH MPD and Segments Source: https://context7.com/ireader/media-server/llms.txt This C code generates MPEG-DASH manifests (MPD) and media segments for adaptive streaming. It requires custom libraries for DASH MPD creation and MOV format handling. The function `dash_segment_handler` processes segment data, and `main` orchestrates the creation of video and audio adaptation sets, feeds them with frame data, generates the MPD XML, and writes it to a file. ```c #include "dash-mpd.h" #include "mov-format.h" static int dash_segment_handler(void* param, int adaptation, const void* data, size_t bytes, int64_t pts, int64_t dts, int64_t duration, const char* name) { printf("DASH Segment: %s, adaptation=%d, duration=%lld ms, size=%zu\n", name, adaptation, duration, bytes); // Write segment to file FILE* fp = fopen(name, "wb"); fwrite(data, 1, bytes, fp); fclose(fp); return 0; } int main() { // Create DASH MPD (0 = static/VOD) dash_mpd_t* dash = dash_mpd_create(0, dash_segment_handler, NULL); // Add video adaptation set uint8_t h264_extradata[100] = { /* AVCDecoderConfigurationRecord */ }; int video_adaptation = dash_mpd_add_video_adaptation_set(dash, "video", MOV_OBJECT_H264, 1920, 1080, h264_extradata, sizeof(h264_extradata)); // Add audio adaptation set uint8_t aac_extradata[16] = { /* AudioSpecificConfig */ }; int audio_adaptation = dash_mpd_add_audio_adaptation_set(dash, "audio", MOV_OBJECT_AAC, 2, 16, 44100, aac_extradata, sizeof(aac_extradata)); // Feed video frames uint8_t video_frame[10000] = { /* H.264 MP4 format */ }; int64_t pts = 0, dts = 0; dash_mpd_input(dash, video_adaptation, video_frame, sizeof(video_frame), pts, dts, MOV_AV_FLAG_KEYFREAME); // Feed audio frames uint8_t audio_frame[512] = { /* raw AAC */ }; dash_mpd_input(dash, audio_adaptation, audio_frame, sizeof(audio_frame), pts, pts, 0); // Generate MPD manifest char mpd_xml[65536]; size_t mpd_size = dash_mpd_playlist(dash, mpd_xml, sizeof(mpd_xml)); FILE* fp = fopen("manifest.mpd", "wb"); fwrite(mpd_xml, 1, mpd_size, fp); fclose(fp); printf("MPD Manifest:\n%s\n", mpd_xml); dash_mpd_destroy(dash); return 0; } ``` -------------------------------- ### HLS fMP4 Segmenter: Create HLS segments from fragmented MP4 Source: https://context7.com/ireader/media-server/llms.txt This C code demonstrates how to create HLS segments in fragmented MP4 format. It initializes an HLS segmenter, adds video and audio tracks, generates an initialization segment, and feeds frames to produce segmented MP4 files and an M3U8 playlist. Dependencies include 'hls-fmp4.h', 'hls-m3u8.h', and 'mov-format.h'. ```c #include "hls-fmp4.h" #include "hls-m3u8.h" #include "mov-format.h" static int segment_counter = 0; static int fmp4_segment_handler(void* param, const void* data, size_t bytes, int64_t pts, int64_t dts, int64_t duration) { hls_m3u8_t* m3u = (hls_m3u8_t*)param; char filename[64]; snprintf(filename, sizeof(filename), "segment%d.m4s", segment_counter++); FILE* fp = fopen(filename, "wb"); fwrite(data, 1, bytes, fp); fclose(fp); printf("Segment: %s, duration=%lld ms\n", filename, duration); hls_m3u8_add(m3u, filename, pts, duration, 0); return 0; } int main() { // Create M3U8 playlist (VOD, version 7 for fMP4) hls_m3u8_t* m3u = hls_m3u8_create(0, 7); // Create fMP4 segmenter (10 second segments) hls_fmp4_t* hls = hls_fmp4_create(10000, fmp4_segment_handler, m3u); // Add video track uint8_t h264_extradata[100] = { /* AVC configuration */ }; int video_track = hls_fmp4_add_video(hls, MOV_OBJECT_H264, 1920, 1080, h264_extradata, sizeof(h264_extradata)); // Add audio track uint8_t aac_extradata[16] = { /* AudioSpecificConfig */ }; int audio_track = hls_fmp4_add_audio(hls, MOV_OBJECT_AAC, 2, 16, 44100, aac_extradata, sizeof(aac_extradata)); // Generate init segment uint8_t init_buffer[4096]; int init_size = hls_fmp4_init_segment(hls, init_buffer, sizeof(init_buffer)); FILE* init_fp = fopen("init.mp4", "wb"); fwrite(init_buffer, 1, init_size, init_fp); fclose(init_fp); hls_m3u8_set_x_map(m3u, "init.mp4"); // Feed frames uint8_t video_frame[10000] = { /* H.264 MP4 format */ }; int64_t pts = 0, dts = 0; hls_fmp4_input(hls, video_track, video_frame, sizeof(video_frame), pts, dts, MOV_AV_FLAG_KEYFREAME); // Generate playlist char playlist[4096]; hls_m3u8_playlist(m3u, 1, playlist, sizeof(playlist)); FILE* fp = fopen("index.m3u8", "wb"); fwrite(playlist, 1, strlen(playlist), fp); fclose(fp); hls_fmp4_destroy(hls); hls_m3u8_destroy(m3u); return 0; } ``` -------------------------------- ### Write Fragmented MP4 Files for Streaming (C) Source: https://context7.com/ireader/media-server/llms.txt This C code shows how to create fragmented MP4 files, ideal for adaptive bitrate streaming. It uses the 'fmp4-writer' library to generate init segments (ftyp, moov) and media fragments (moof, mdat). The code adds H.264 video and AAC audio tracks and writes sample data in a loop. ```c #include "fmp4-writer.h" #include "mov-format.h" int main() { FILE* fp = fopen("output.mp4", "wb"); // Create fragmented MP4 writer fmp4_writer_t* fmp4 = fmp4_writer_create(MOV_FLAG_SEGMENT, mov_file_buffer(), fp); // Add tracks uint8_t h264_extradata[100] = { /* AVCDecoderConfigurationRecord */ }; int video_track = fmp4_writer_add_video(fmp4, MOV_OBJECT_H264, 1920, 1080, h264_extradata, sizeof(h264_extradata)); uint8_t aac_extradata[16] = { /* AudioSpecificConfig */ }; int audio_track = fmp4_writer_add_audio(fmp4, MOV_OBJECT_AAC, 2, 16, 44100, aac_extradata, sizeof(aac_extradata)); // Write init segment (ftyp + moov) fmp4_writer_init_segment(fmp4); // Write media samples (moof + mdat fragments) uint8_t video_frame[10000] = { /* H.264 data */ }; int64_t pts = 0, dts = 0; for (int i = 0; i < 100; i++) { fmp4_writer_write(fmp4, video_track, video_frame, sizeof(video_frame), pts, dts, (i % 30 == 0) ? MOV_AV_FLAG_KEYFREAME : 0); pts += 33; dts += 33; } fmp4_writer_destroy(fmp4); fclose(fp); return 0; } ``` -------------------------------- ### RTMP Server: Distribute Live Streams (C) Source: https://context7.com/ireader/media-server/llms.txt Implement an RTMP server to accept publish and play requests from clients and distribute live streams. This involves setting up handlers for publish, play, video, and audio events. Received streams are then broadcast to all connected players. ```c #include "rtmp-server.h" static int rtmp_send(void* param, const void* header, size_t len, const void* payload, size_t bytes) { int socket = *(int*)param; send(socket, header, len, 0); send(socket, payload, bytes, 0); return 0; } static int on_publish(void* param, const char* app, const char* stream, const char* type) { printf("Client publishing: app=%s, stream=%s, type=%s\n", app, stream, type); return 0; // Accept publish } static int on_play(void* param, const char* app, const char* stream, double start, double duration, uint8_t reset) { printf("Client playing: app=%s, stream=%s\n", app, stream); return 0; // Accept play } static int on_video(void* param, const void* data, size_t bytes, uint32_t timestamp) { // Received video from publisher, broadcast to players rtmp_server_t* rtmp = (rtmp_server_t*)param; rtmp_server_send_video(rtmp, data, bytes, timestamp); return 0; } static int on_audio(void* param, const void* data, size_t bytes, uint32_t timestamp) { // Received audio from publisher, broadcast to players rtmp_server_t* rtmp = (rtmp_server_t*)param; rtmp_server_send_audio(rtmp, data, bytes, timestamp); return 0; } int main() { int socket_fd = /* TCP socket from client */; struct rtmp_server_handler_t handler = { .send = rtmp_send, .onpublish = on_publish, .onplay = on_play, .onvideo = on_video, .onaudio = on_audio }; rtmp_server_t* rtmp = rtmp_server_create(&socket_fd, &handler); // Receive loop uint8_t buffer[4096]; while (1) { int n = recv(socket_fd, buffer, sizeof(buffer), 0); if (n <= 0) break; rtmp_server_input(rtmp, buffer, n); } rtmp_server_destroy(rtmp); return 0; } ``` -------------------------------- ### Read MKV/WebM Files - C Source: https://context7.com/ireader/media-server/llms.txt Reads Matroska/WebM files to extract track information such as video dimensions and audio parameters. It utilizes a callback-based interface for handling video, audio, and general track data. Dependencies include 'mkv-reader.h' and 'mkv-format.h'. Inputs are an MKV file path, and outputs are printed track details and duration. ```c #include "mkv-reader.h" #include "mkv-format.h" static void mkv_video_info(void* param, uint32_t track, enum mkv_codec_t codec, int width, int height, const void* extra, size_t bytes) { printf("Video Track %d: codec=%d, %dx%d, extradata=%zu bytes\n", track, codec, width, height, bytes); } static void mkv_audio_info(void* param, uint32_t track, enum mkv_codec_t codec, int channels, int bits, int sample_rate, const void* extra, size_t bytes) { printf("Audio Track %d: codec=%d, %dch, %d-bit, %d Hz\n", track, codec, channels, bits, sample_rate); } static void mkv_onread(void* param, uint32_t track, const void* buffer, size_t bytes, int64_t pts, int64_t dts, int flags) { printf("Track %d: pts=%lld, dts=%lld, size=%zu, keyframe=%d\n", track, pts, dts, bytes, flags & MKV_FLAGS_KEYFRAME); } int main() { FILE* fp = fopen("input.mkv", "rb"); mkv_reader_t* mkv = mkv_reader_create(mkv_file_buffer(), fp); struct mkv_reader_trackinfo_t info = { .onvideo = mkv_video_info, .onaudio = mkv_audio_info }; mkv_reader_getinfo(mkv, &info, NULL); uint64_t duration = mkv_reader_getduration(mkv); printf("Duration: %llu ms\n", duration); uint8_t buffer[2 * 1024 * 1024]; while (mkv_reader_read(mkv, buffer, sizeof(buffer), mkv_onread, NULL) > 0) { // Process data } mkv_reader_destroy(mkv); fclose(fp); return 0; } ``` -------------------------------- ### HLS TS Segmenter in C Source: https://context7.com/ireader/media-server/llms.txt Creates HLS segments in MPEG-TS format from media streams. It generates '.ts' segment files and an '.m3u8' playlist. Dependencies include 'hls-media.h' and 'hls-m3u8.h'. Handles video (H264) and audio (AAC) streams. ```c #include "hls-media.h" #include "hls-m3u8.h" #include static int segment_counter = 0; static int hls_segment_handler(void* param, const void* data, size_t bytes, int64_t pts, int64_t dts, int64_t duration) { hls_m3u8_t* m3u = (hls_m3u8_t*)param; char filename[64]; snprintf(filename, sizeof(filename), "segment%d.ts", segment_counter++); FILE* fp = fopen(filename, "wb"); fwrite(data, 1, bytes, fp); fclose(fp); printf("Segment: %s, duration=%lld ms\n", filename, duration); hls_m3u8_add(m3u, filename, pts, duration, 0); return 0; } int main() { // Create M3U8 playlist (VOD, version 3 for TS) hls_m3u8_t* m3u = hls_m3u8_create(0, 3); // Create HLS segmenter (10 second segments) hls_media_t* hls = hls_media_create(10000, hls_segment_handler, m3u); // Add video stream uint8_t h264_extradata[100] = { /* SPS/PPS */ }; int video_track = hls_media_add_stream(hls, STREAM_VIDEO_H264, h264_extradata, sizeof(h264_extradata)); // Add audio stream uint8_t aac_extradata[16] = { /* AudioSpecificConfig */ }; int audio_track = hls_media_add_stream(hls, STREAM_AUDIO_AAC, aac_extradata, sizeof(aac_extradata)); // Feed frames uint8_t video_frame[10000] = { /* H.264 Annex-B */ }; int64_t pts = 0, dts = 0; hls_media_input(hls, STREAM_VIDEO_H264, video_frame, sizeof(video_frame), pts, dts, HLS_FLAGS_KEYFRAME); uint8_t audio_frame[512] = { /* raw AAC */ }; hls_media_input(hls, STREAM_AUDIO_AAC, audio_frame, sizeof(audio_frame), pts, pts, 0); // Generate playlist char playlist[4096]; hls_m3u8_playlist(m3u, 1, playlist, sizeof(playlist)); // 1 = EOF printf("Playlist:\n%s\n", playlist); FILE* fp = fopen("index.m3u8", "wb"); fwrite(playlist, 1, strlen(playlist), fp); fclose(fp); hls_media_destroy(hls); hls_m3u8_destroy(m3u); return 0; } ```