Untitled

 avatar
unknown
c_cpp
a year ago
3.5 kB
2
Indexable
#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