Xcode 9中FFMpeg报错:‘AVMediaType’类型定义冲突及RTSP直播推流问题求解
Hey there! Let's break down your two FFmpeg issues and get you sorted out.
1. Resolving 'AVMediaType' Definition Conflict
This error pops up because FFmpeg's AVMediaType typedef clashes with the one from Apple's AVFoundation framework (they share the exact same name). Here are three practical fixes, ordered by ease of implementation:
Option 1: Use Macro Wrappers to Isolate FFmpeg Headers
This is the quickest fix without modifying the FFmpeg library itself. Wrap your FFmpeg header includes with macros to temporarily disable the system's AVMediaType definition:
// Save the system's AVMediaType definition #pragma push_macro("AVMediaType") #undef AVMediaType // Include your FFmpeg headers here #include <libavutil/avutil.h> #include <libavformat/avformat.h> #include <libavcodec/avcodec.h> // Restore the system's AVMediaType definition #pragma pop_macro("AVMediaType")
This way, when compiling FFmpeg code, the system's AVMediaType is hidden, and vice versa for AVFoundation code.
Option 2: Compile FFmpeg with Namespace Support
If you're building FFmpeg from source, enable the --enable-namespace flag during configuration. This wraps all FFmpeg types in a FFmpeg:: namespace, so you'd reference it as FFmpeg::AVMediaType instead of just AVMediaType.
Option 3: Rename FFmpeg's AVMediaType (Last Resort)
If you're using a precompiled FFmpeg library, you can manually edit the avutil.h header:
- Find the line
typedef enum AVMediaType AVMediaType; - Rename it to something like
typedef enum AVMediaType FFAVMediaType; - Replace all references to
AVMediaTypein your FFmpeg-related code withFFAVMediaType.
Note: This is tedious and requires updating every instance, so only use it if the above options don't work.
2. Implementing RTSP Live Streaming with FFmpeg (Using avutil & Related Libraries)
Keep in mind: RTSP streaming requires more than just avutil.h—you'll need avformat, avcodec, and swscale libraries too. Here's a step-by-step guide with code snippets:
Step 1: Initialize FFmpeg & Network
First, set up FFmpeg's core components and network support:
// Register all formats and codecs av_register_all(); // Initialize network components (critical for RTSP) avformat_network_init();
Step 2: Configure Output Context & RTSP URL
Create an output format context for RTSP and set your stream URL:
AVFormatContext *outputCtx = NULL; const char *rtspUrl = "rtsp://your-stream-server-url:port/stream-name"; // Auto-detect output format from URL (should pick RTSP) int ret = avformat_alloc_output_context2(&outputCtx, NULL, "rtsp", rtspUrl); if (ret < 0) { // Handle error (use av_strerror to get readable message) char errBuf[1024]; av_strerror(ret, errBuf, sizeof(errBuf)); NSLog(@"Failed to create output context: %s", errBuf); return; } // Set RTSP transport options (TCP is more reliable for live streaming) AVDictionary *opts = NULL; av_dict_set(&opts, "rtsp_transport", "tcp", 0); av_dict_set(&opts, "stimeout", "5000000", 0); // 5-second timeout
Step 3: Add Output Stream & Configure Encoder
Assuming you're streaming H.264 video (common for RTSP), create a video stream and set up the encoder:
// Create a new stream in the output context AVStream *outStream = avformat_new_stream(outputCtx, NULL); if (!outStream) { NSLog(@"Failed to create output stream"); goto cleanup; } // Set stream parameters (match your input video's specs) AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_H264); AVCodecContext *codecCtx = avcodec_alloc_context3(codec); codecCtx->codec_id = AV_CODEC_ID_H264; codecCtx->codec_type = AVMEDIA_TYPE_VIDEO; codecCtx->pix_fmt = AV_PIX_FMT_YUV420P; // Required for H.264 codecCtx->width = 1280; // Your video width codecCtx->height = 720; // Your video height codecCtx->bit_rate = 2000000; // 2Mbps bitrate codecCtx->time_base = (AVRational){1, 30}; // 30fps codecCtx->framerate = (AVRational){30, 1}; // Copy codec params to output stream avcodec_parameters_from_context(outStream->codecpar, codecCtx); // Open the encoder ret = avcodec_open2(codecCtx, codec, &opts); if (ret < 0) { char errBuf[1024]; av_strerror(ret, errBuf, sizeof(errBuf)); NSLog(@"Failed to open encoder: %s", errBuf); goto cleanup; }
Step 4: Open Output IO & Write Header
Connect to the RTSP server and send the stream header:
// Open the RTSP output ret = avio_open2(&outputCtx->pb, rtspUrl, AVIO_FLAG_WRITE, NULL, &opts); if (ret < 0) { char errBuf[1024]; av_strerror(ret, errBuf, sizeof(errBuf)); NSLog(@"Failed to open RTSP output: %s", errBuf); goto cleanup; } // Write the stream header to the server ret = avformat_write_header(outputCtx, &opts); if (ret < 0) { char errBuf[1024]; av_strerror(ret, errBuf, sizeof(errBuf)); NSLog(@"Failed to write header: %s", errBuf); goto cleanup; }
Step 5: Encode & Send Frames
For each video frame you capture (e.g., from iOS camera), convert it to the encoder's pixel format, encode it, and send it to the server:
// Example: Convert a captured CMSampleBuffer to AVFrame (you'll need to implement this) AVFrame *frame = convertCMSampleBufferToAVFrame(sampleBuffer); // Send frame to encoder ret = avcodec_send_frame(codecCtx, frame); if (ret < 0) { // Handle send error continue; } // Receive encoded packets AVPacket pkt = {0}; av_init_packet(&pkt); while (ret >= 0) { ret = avcodec_receive_packet(codecCtx, &pkt); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { // Handle receive error break; } // Set packet stream index and time base pkt.stream_index = outStream->index; av_packet_rescale_ts(&pkt, codecCtx->time_base, outStream->time_base); // Write packet to RTSP stream ret = av_interleaved_write_frame(outputCtx, &pkt); av_packet_unref(&pkt); }
Step 6: Cleanup Resources
When you're done streaming, make sure to release all FFmpeg resources properly:
cleanup: // Write trailer av_write_trailer(outputCtx); // Close encoder avcodec_close(codecCtx); // Close output IO avio_close(outputCtx->pb); // Free context avformat_free_context(outputCtx); // Clean up network avformat_network_deinit();
内容的提问来源于stack exchange,提问作者Vineesh TP

