Untitled
#include "rtsp_decoder.h" #include <iostream> extern "C" { #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libswscale/swscale.h> } struct RTSPDecoder { AVFormatContext* formatCtx = nullptr; AVStream* videoStream = nullptr; AVCodecContext* codecCtx = nullptr; AVFrame* frame = nullptr; }; extern "C" { void* CreateRTSPDecoder(const char* rtspUrl) { RTSPDecoder* decoder = new RTSPDecoder(); avformat_network_init(); if (avformat_open_input(&decoder->formatCtx, rtspUrl, NULL, NULL) != 0) { std::cerr << "Error opening RTSP stream" << std::endl; delete decoder; return nullptr; } for (unsigned int i = 0; i < decoder->formatCtx->nb_streams; ++i) { if (decoder->formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { decoder->videoStream = decoder->formatCtx->streams[i]; break; } } if (!decoder->videoStream) { std::cerr << "No video stream found" << std::endl; avformat_close_input(&decoder->formatCtx); delete decoder; return nullptr; } AVCodec* codec = avcodec_find_decoder(decoder->videoStream->codecpar->codec_id); decoder->codecCtx = avcodec_alloc_context3(codec); avcodec_parameters_to_context(decoder->codecCtx, decoder->videoStream->codecpar); avcodec_open2(decoder->codecCtx, codec, nullptr); decoder->frame = av_frame_alloc(); return decoder; } void DestroyRTSPDecoder(void* decoderPtr) { RTSPDecoder* decoder = static_cast<RTSPDecoder*>(decoderPtr); av_frame_free(&decoder->frame); avcodec_free_context(&decoder->codecCtx); avformat_close_input(&decoder->formatCtx); delete decoder; } bool GetDecodedFrame(void* decoderPtr, unsigned char** data, int* width, int* height) { RTSPDecoder* decoder = static_cast<RTSPDecoder*>(decoderPtr); AVPacket packet; int ret = av_read_frame(decoder->formatCtx, &packet); if (ret < 0) { return false; } if (packet.stream_index == decoder->videoStream->index) { ret = avcodec_send_packet(decoder->codecCtx, &packet); if (ret < 0) { std::cerr << "Error sending packet to decoder" << std::endl; av_packet_unref(&packet); return false; } while (ret >= 0) { ret = avcodec_receive_frame(decoder->codecCtx, decoder->frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { av_packet_unref(&packet); return false; } else if (ret < 0) { std::cerr << "Error receiving decoded frame" << std::endl; av_packet_unref(&packet); return false; } // Remplir les paramètres de sortie avec les données décodées *data = decoder->frame->data[0]; *width = decoder->frame->width; *height = decoder->frame->height; av_packet_unref(&packet); return true; } } av_packet_unref(&packet); return false; } }
Leave a Comment