C# RTMP H.264 Video Streaming with FFmpeg.AutoGen
Here is an example C# code using FFmpeg.AutoGen for pushing H.264 video stream over RTMP:
using System;
using System.Runtime.InteropServices;
using FFmpeg.AutoGen;
namespace RTMPStreamPusher
{
class Program
{
private static AVFormatContext* _outputContext;
private static AVStream* _videoStream;
private static AVCodecContext* _codecContext;
private static AVFrame* _frame;
private static byte[] _buffer;
static void Main(string[] args)
{
// Initialize FFmpeg library
ffmpeg.av_register_all();
ffmpeg.avcodec_register_all();
ffmpeg.avformat_network_init();
// Open RTMP output stream
var rtmpUrl = 'rtmp://example.com/live/stream';
ffmpeg.avformat_alloc_output_context2(&_outputContext, null, 'flv', rtmpUrl);
if (_outputContext == null)
{
Console.WriteLine('Failed to allocate output context.');
return;
}
// Open video codec
var codec = ffmpeg.avcodec_find_encoder(AVCodecID.AV_CODEC_ID_H264);
if (codec == null)
{
Console.WriteLine('Failed to find H.264 encoder.');
return;
}
_videoStream = ffmpeg.avformat_new_stream(_outputContext, codec);
_codecContext = _videoStream->codec;
_codecContext->codec_id = AVCodecID.AV_CODEC_ID_H264;
_codecContext->width = 1920;
_codecContext->height = 1080;
_codecContext->time_base = new AVRational { num = 1, den = 25 };
_codecContext->pix_fmt = AVPixelFormat.AV_PIX_FMT_YUV420P;
_codecContext->bit_rate = 4000000;
_codecContext->gop_size = 10;
if ((_outputContext->oformat->flags & ffmpeg.AVFMT_GLOBALHEADER) != 0)
{
_codecContext->flags |= ffmpeg.CODEC_FLAG_GLOBAL_HEADER;
}
if (ffmpeg.avcodec_open2(_codecContext, codec, null) < 0)
{
Console.WriteLine('Failed to open H.264 encoder.');
return;
}
// Allocate frame and buffer
_frame = ffmpeg.av_frame_alloc();
_frame->format = (int)_codecContext->pix_fmt;
_frame->width = _codecContext->width;
_frame->height = _codecContext->height;
ffmpeg.av_frame_get_buffer(_frame, 32);
var bufferSize = ffmpeg.av_image_get_buffer_size(_codecContext->pix_fmt, _codecContext->width, _codecContext->height, 1);
_buffer = new byte[bufferSize];
// Open RTMP output stream
if ((_outputContext->oformat->flags & ffmpeg.AVFMT_NOFILE) == 0)
{
if (ffmpeg.avio_open(&_outputContext->pb, rtmpUrl, ffmpeg.AVIO_FLAG_WRITE) < 0)
{
Console.WriteLine('Failed to open RTMP output stream.');
return;
}
}
// Write header to output context
if (ffmpeg.avformat_write_header(_outputContext, null) < 0)
{
Console.WriteLine('Failed to write header to output context.');
return;
}
// Generate sample video data and push to output stream
var random = new Random();
var data = new byte[1920 * 1080 * 3 / 2];
while (true)
{
// Generate a frame of sample video data
for (int i = 0; i < data.Length; i++)
{
data[i] = (byte)random.Next(256);
}
// Convert sample video data to AVFrame
var ptr = Marshal.UnsafeAddrOfPinnedArrayElement(data, 0);
var srcData = new byte_ptrArray8();
srcData[0] = ptr;
srcData[1] = ptr + 1920 * 1080;
srcData[2] = ptr + 1920 * 1080 * 5 / 4;
ffmpeg.sws_scale(_codecContext->sws_ctx, srcData, _codecContext->width, _codecContext->height,
new int[] { 0, _codecContext->width, _codecContext->width * 5 / 4 }, _frame->data, _frame->linesize);
// Encode AVFrame to H.264 bitstream
var packet = new AVPacket();
ffmpeg.av_init_packet(&packet);
packet.data = null;
packet.size = 0;
ffmpeg.avcodec_send_frame(_codecContext, _frame);
while (true)
{
var ret = ffmpeg.avcodec_receive_packet(_codecContext, &packet);
if (ret == ffmpeg.AVERROR_EOF || ret == ffmpeg.AVERROR(EAGAIN))
{
break;
}
if (ret < 0)
{
Console.WriteLine('Failed to receive packet from encoder.');
return;
}
// Write H.264 bitstream to output stream
ffmpeg.av_interleaved_write_frame(_outputContext, &packet);
}
// Wait for 40ms (25fps)
System.Threading.Thread.Sleep(40);
}
}
}
}
Note that this code is just a simple example for demonstration purposes and has not been thoroughly tested. Also, you will need to add the necessary FFmpeg.AutoGen and FFmpeg libraries to your project.
原文地址: https://www.cveoy.top/t/topic/ndNF 著作权归作者所有。请勿转载和采集!