Untitled

mail@pastecode.io avatar
unknown
c_cpp
18 days ago
4.8 kB
0
Indexable
Never
extern "C" {
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libavutil/opt.h>
}

#include "vdo-map.h"
#include "vdo-stream.h"
#include "vdo-types.h"
#include "vdo-error.h"

#include <glib.h>
#include <string.h>
#include <syslog.h>

#include "imgprovider.h"

#define VDO_CLIENT_ERROR g_quark_from_static_string("vdo-client-error")

const char* RTSP_SERVER = "rtsp://192.168.1.253:8553/stream";

int main(int argc, char* argv[]) {
    openlog("acap_app", LOG_PID | LOG_CONS, LOG_USER);
    syslog(LOG_INFO, "Running test ACAP app");

    GError* error = nullptr;
    VdoMap* settings = vdo_map_new();

    // The desired width and height of the BGR frame
    unsigned int width  = 640; // 1024
    unsigned int height = 360; // 576

    // Set default arguments
    vdo_map_set_uint32(settings, "width", width);
    vdo_map_set_uint32(settings, "height", height);
    vdo_map_set_uint32(settings, "format", VDO_FORMAT_H264);

    // Create a new stream
    VdoStream* vdostream = vdo_stream_new(settings, NULL, &error);
    g_clear_object(&settings);
    if (!vdostream) {
        syslog(LOG_ERR, "Failed to create VDO stream.");
    }

    if (!vdo_stream_attach(vdostream, NULL, &error)) {
        syslog(LOG_ERR, "Failed to attach to VDO stream.");
        exit(1);
    }

    VdoMap* info = vdo_stream_get_info(vdostream, &error);
    if (!info) {
        syslog(LOG_ERR, "Failed to get VDO stream info.");
        exit(1);
    }

    syslog(LOG_INFO,
           "Starting stream: %s, %ux%u, %u fps\n",
           "h264",
           vdo_map_get_uint32(info, "width", 0),
           vdo_map_get_uint32(info, "height", 0),
           vdo_map_get_uint32(info, "framerate", 0));

    g_clear_object(&info);

    // Start the stream
    if (!vdo_stream_start(vdostream, &error)) {
        syslog(LOG_ERR, "Failed to start VDO stream.");
        exit(1);
    }

    avformat_network_init();

    AVFormatContext* ofmt_ctx = nullptr;
    AVStream *stream = nullptr;

    avformat_alloc_output_context2(&ofmt_ctx, nullptr, "rtsp", RTSP_SERVER);
    if (!ofmt_ctx) {
        fprintf(stderr, "Could not create output context.\n");
    } else {
        printf("Allocated output context.\n");
    }

    stream = avformat_new_stream(ofmt_ctx, nullptr);
    if (!stream) {
        fprintf(stderr, "Failed to create new livestream.\n");
        exit(1);
    } else {
        printf("New livestream created.\n");
    }

    AVCodecParameters *codec_params = stream->codecpar;
    // Set up codec parameters as per stream settings
    codec_params->codec_id = AV_CODEC_ID_H264;
    codec_params->codec_type = AVMEDIA_TYPE_VIDEO;
    codec_params->width = width;
    codec_params->height = height;

    // Open output URL
    if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE)) {
        if (avio_open(&ofmt_ctx->pb, ofmt_ctx->url, AVIO_FLAG_WRITE) < 0) {
            fprintf(stderr, "Could not open output URL.\n");
            exit(1);
        }
    }

    // Write header to output file
    if (avformat_write_header(ofmt_ctx, nullptr) < 0) {
        fprintf(stderr, "Error occurred when writing header.\n");
        exit(1);
    }

    AVPacket pkt;
    int frame_rate = 30;
    int64_t pts = 0;
    int64_t dts = 0;
    int64_t frame_duration = AV_TIME_BASE / frame_rate;

    av_init_packet(&pkt);
    pkt.data = nullptr;
    pkt.size = 0;
    pkt.dts = 0;

    while (true) {

        VdoBuffer* buffer = vdo_stream_get_buffer(vdostream, &error);
        VdoFrame* frame = vdo_buffer_get_frame(buffer);

        if (!frame) {
            syslog(LOG_INFO, "Failed to read frame.");
            break;
        }

        pkt.stream_index = stream->index;

        pkt.data = (uint8_t *)vdo_buffer_get_data(buffer);
        pkt.size = vdo_frame_get_size(frame);

        if (!pkt.data) {
            syslog(LOG_INFO, "Failed to get packet data.");
            av_packet_unref(&pkt);
            vdo_stream_buffer_unref(vdostream, &buffer, &error);
            break;
        }
        
        // Set DTS and PTS
        pkt.dts = dts;
        pkt.pts = pts;
        pkt.duration = frame_duration;

        if (av_interleaved_write_frame(ofmt_ctx, &pkt) < 0) {
            syslog(LOG_ERR, "Error writing frame to output context.");
            break;
        }

        // Update DTS and PTS
        dts += frame_duration;
        pts += frame_duration;

        // Release the buffer and allow the server to reuse it
        if (!vdo_stream_buffer_unref(vdostream, &buffer, &error)){
            syslog(LOG_ERR, "Failed to release buffer.");
            break;
        }

        av_packet_unref(&pkt);
    }

    av_write_trailer(ofmt_ctx);

    if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE))
        avio_closep(&ofmt_ctx->pb);

    printf("Program completed. Exiting...");
}
Leave a Comment