AutoGen.FFMpeg как получить видео по rtsp
Подскажите как получить цветное видео по протоколу rtsp. Ниже приведен код, но выводится только черно-белое. менял pFrame на rgbFrame, но от этого только хуже становится. Аналогичный код на С++ Qt работает, выдает цветное изображение
public partial class Form1 : Form
{
string RTSP_URL = "rtsp://192.168.1.119:554";
private int Width;
private int Height;
System.Threading.Thread myThread;
bool m_running;
public Form1()
{
InitializeComponent();
InitizlizeFFMpeg();
Width = pictureBox1.Width;
Height = pictureBox1.Height;
m_running = true;
}
unsafe private void InitizlizeFFMpeg()
{
ffmpeg.RootPath = "C:/ffmpeg-master-latest-win64-gpl-shared/ffmpeg-master-latest-win64-gpl-shared/bin";
ffmpeg.avformat_network_init();
}
unsafe private void StartVideoStream()
{
myThread = new System.Threading.Thread(() =>
{
AVDictionary* options = null;
ffmpeg.av_dict_set(&options, "rtsp_transport", "tcp", 0);
AVFormatContext* formatContext = ffmpeg.avformat_alloc_context();
if (formatContext == null)
{
MessageBox.Show("Не удалось создать formatContext");
return;
}
if (ffmpeg.avformat_open_input(&formatContext, RTSP_URL, null, &options) != 0)
{
MessageBox.Show("Не удалось открыть поток");
return;
}
if (ffmpeg.avformat_find_stream_info(formatContext, null) < 0)
{
MessageBox.Show("Не удалось найти информацию о потоке");
return;
}
int videoStreamIndex = -1;
for (int i = 0; i < formatContext->nb_streams; i++)
{
if (formatContext->streams[i]->codecpar->codec_type == AVMediaType.AVMEDIA_TYPE_VIDEO)
{
videoStreamIndex = i;
break;
}
}
if (videoStreamIndex == -1)
{
MessageBox.Show("Видеопоток не найден");
return;
}
var codecParameters = formatContext->streams[videoStreamIndex]->codecpar;
var codec = ffmpeg.avcodec_find_decoder(codecParameters->codec_id);
var codecContext = ffmpeg.avcodec_alloc_context3(codec);
ffmpeg.avcodec_parameters_to_context(codecContext, codecParameters);
ffmpeg.avcodec_open2(codecContext, codec, null);
var packet = ffmpeg.av_packet_alloc();
var frame = ffmpeg.av_frame_alloc();
var rgbFrame = ffmpeg.av_frame_alloc();
var bufferSize = ffmpeg.av_image_get_buffer_size(AVPixelFormat.AV_PIX_FMT_RGB24, Width, Height, 1);
var buffer = Marshal.AllocHGlobal(bufferSize);
rgbFrame->data[0] = (byte*)buffer;
rgbFrame->linesize[0] = Width * 3;
while (m_running && ffmpeg.av_read_frame(formatContext, packet) >= 0)
{
if (packet->stream_index == videoStreamIndex)
{
ffmpeg.avcodec_send_packet(codecContext, packet);
while (ffmpeg.avcodec_receive_frame(codecContext, frame) == 0)
{
var swsContext = ffmpeg.sws_getContext(
frame->width, frame->height, codecContext->pix_fmt, Width, Height,
AVPixelFormat.AV_PIX_FMT_RGB24, ffmpeg.SWS_BILINEAR | ffmpeg.SWS_ACCURATE_RND, null, null, null);
int result = ffmpeg.sws_scale(swsContext, frame->data, frame->linesize, 0, frame->height,
rgbFrame->data, rgbFrame->linesize);
ffmpeg.sws_freeContext(swsContext);
if (Width > 0 && Height > 0)
{
try
{
var bitmap = new Bitmap(Width, Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, Width, Height),
ImageLockMode.ReadOnly, bitmap.PixelFormat);
for (int y = 0; y < Height; y++)
{
byte* src = (byte*)frame->data[0] + y * frame->linesize[0];
byte* dst = (byte*)bitmapData.Scan0 + y * bitmapData.Stride;
for (int x = 0; x < Width; x++)
{
dst[x * 3 + 0] = src[x + 2];
dst[x * 3 + 1] = src[x + 1];
dst[x * 3 + 2] = src[x + 0];
}
}
bitmap.UnlockBits(bitmapData);
pictureBox1.Image?.Dispose();
pictureBox1.Image = bitmap;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + ' ' + ex.StackTrace);
m_running = false;
break;
}
}
}
}
ffmpeg.av_packet_unref(packet);
}
Marshal.FreeHGlobal(buffer);
ffmpeg.av_frame_free(&frame);
ffmpeg.av_frame_free(&rgbFrame);
ffmpeg.avcodec_free_context(&codecContext);
ffmpeg.avformat_close_input(&formatContext);
});
myThread.Start();
}
private void button1_Click(object sender, EventArgs e)
{
StartVideoStream();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
m_running = false;
myThread?.Join(1000);
}
}