Skip to content

File video_encoder.cpp

File List > device_tx > video_encoder.cpp

Go to the documentation of this file

#include "video_encoder.hpp"

#include "illixr/error_util.hpp"

#include 
#include 
#include 

namespace ILLIXR {

void vio_video_encoder::enqueue(cv::Mat& img0, cv::Mat& img1) {
    auto data_size      = img0.cols * img0.rows * img0.channels();
    int  size           = floor(data_size + ceil(img0.cols / 2.0) * ceil(img0.rows / 2.0) * 2);
    auto fill_zero_size = size - data_size;

    auto buffer_img0 = gst_buffer_new_and_alloc(size);
    auto buffer_img1 = gst_buffer_new_and_alloc(size);

    gst_buffer_fill(buffer_img0, 0, img0.data, data_size);
    gst_buffer_fill(buffer_img1, 0, img1.data, data_size);

    gst_buffer_memset(buffer_img0, data_size, 128, fill_zero_size);
    gst_buffer_memset(buffer_img1, data_size, 0, fill_zero_size);

    GST_BUFFER_OFFSET(buffer_img0) = num_samples_;
    GST_BUFFER_OFFSET(buffer_img1) = num_samples_;

    num_samples_++;

    auto ret_img0 = gst_app_src_push_buffer(reinterpret_cast<GstAppSrc*>(appsrc_img0_), buffer_img0);
    auto ret_img1 = gst_app_src_push_buffer(reinterpret_cast<GstAppSrc*>(appsrc_img1_), buffer_img1);
    if (ret_img0 != GST_FLOW_OK || ret_img1 != GST_FLOW_OK) {
        abort("Failed to push buffer");
    }
}

GstFlowReturn vio_video_encoder::cb_appsink(GstElement* sink) {
    GstSample* sample;
    g_signal_emit_by_name(sink, "pull-sample", &sample);
    if (sample) {
        GstBuffer* buffer = gst_sample_get_buffer(sample);

        std::unique_lock<std::mutex> lock(pipeline_sync_mutex_); // lock acquired
        if (sink == appsink_img0_) {
            gst_buffer_map(buffer, &img0_map_, GST_MAP_READ);
            img0_ready_ = true;
        } else {
            gst_buffer_map(buffer, &img1_map_, GST_MAP_READ);
            img1_ready_ = true;
        }

        if (img0_ready_ && img1_ready_) {
            callback_(img0_map_, img1_map_);
            img0_ready_ = false;
            img1_ready_ = false;
            lock.unlock(); // unlock and notify the waiting thread to clean up
            pipeline_sync_.notify_one();
        } else {
            pipeline_sync_.wait(lock, [&]() {
                return !img0_ready_ && !img1_ready_;
            });            // wait unlocks the mutex if condition is not met
            lock.unlock(); // wait has acquired the lock. unlock it and start cleaning up
        }

        if (sink == appsink_img0_) {
            gst_buffer_unmap(buffer, &img0_map_);
        } else {
            gst_buffer_unmap(buffer, &img1_map_);
        }
        gst_sample_unref(sample);
        return GST_FLOW_OK;
    }
    return GST_FLOW_ERROR;
}

} // namespace ILLIXR