如何将OpenCV图像推入GStreamer Pipeline以通过TCPServer-Sink流式传输

时间:2013-11-26 14:10:55

标签: c++ opencv gstreamer

我正在尝试将OpenCV创建的图像推送到GStreamer-Pipeline,以便通过GStreamer-TCPServerSink流式传输视频。

我的GStreamer-Pipeline看起来如下: AppSrc - > FFMpegColorSpace - > VP8Enc - > WebMMux - > TCPServerSink 通过创建OpenCV-Images并通过 gst_app_src_push_buffer 将它们推送到Appsrc来提供AppSrc。

我写了一个名为“Sandbox”的测试程序,它显示了程序运行时GStreamer中出现的错误。

我的测试系统如下所示:

  • Gentoo的
  • 内核:3.10.0-rc3
  • OpenCV:2.4.5
  • GStreamer:0.10.36

我想了解为什么会出现这种错误,我做错了什么以及工作解决方案的外观如何?

我希望你能帮我解决问题。

我已经设置了一个Mini-CMake项目,其中包含产生错误的代码。它由两个文件组成,即CMakeLists.txt和Sandbox.cpp。 CMakeLists.txt是关于如何构建Sandbox.cpp中包含的沙盒程序的配置。 要构建它,只需创建一个目录,例如“构建”,更改为它并使用以下命令启动Out-of-Source构建:

cmake ../

现在,如果您安装了Dependencies,CMake会创建所有需要的文件,因此您只需输入:

make

构建程序。

####################################################################################################
# Projectinformations
####################################################################################################
project( Sandbox CXX )
cmake_minimum_required( VERSION 2.8 )

####################################################################################################
# G++ Options
####################################################################################################
set( CMAKE_C_COMPILER "gcc" )
set( CMAKE_CXX_COMPILER "g++" )

set( CMAKE_CXX_FLAGS "-g -O0 -std=c++11 -ggdb -Wall -W -Wunused-variable -Wunused-parameter -Wunused-function -Wunused -Woverloaded-virtual -Wwrite-strings --coverage" )
set( CMAKE_C_FLAGS ${CMAKE_CXX_FLAGS} )

####################################################################################################
# Resolve Dependencies
####################################################################################################
set( Boost_DEBUG 1 )
set( Boost_USE_MULTITHREADED 1 )
find_package( Boost 1.53 REQUIRED system thread timer )

find_package( PkgConfig )
pkg_check_modules( GSTREAMER_0_10 gstreamer-0.10 )
pkg_check_modules( GSTREAMER_0_10_APP gstreamer-app-0.10 )
include_directories( ${GSTREAMER_0_10_INCLUDE_DIRS} )
include_directories( ${GSTREAMER_0_10_APP_INCLUDE_DIRS} )

find_package( OpenCV REQUIRED )

####################################################################################################
# Project
####################################################################################################
add_executable( Sandbox Sandbox.cpp )

该计划本身如下:

// Standard C++ Libraries
#include <iostream>
#include <sstream>
#include <string>

// Boost Libraries
#include <boost/asio.hpp>
#include <boost/make_shared.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>

// GStreamer
#include <gstreamer-0.10/gst/gst.h>
#include <gstreamer-0.10/gst/gstelement.h>
#include <gstreamer-0.10/gst/gstpipeline.h>
#include <gstreamer-0.10/gst/gstutils.h>
#include <gstreamer-0.10/gst/app/gstappsrc.h>

// OpenCV
// #include "cv.h"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>


GMainLoop *glib_MainLoop;
unsigned int heartbeat_Intervall; ///< In Milliseconds
boost::shared_ptr<boost::asio::deadline_timer> heartbeat;

GstElement *source_OpenCV;
guint64 imagecounter;

void
GLib_MainLoop() {
    if( !g_main_loop_is_running( glib_MainLoop ) ) {
        std::cout << "Starting glib_MainLoop..." << std::endl;
        g_main_loop_run( glib_MainLoop );
        std::cout << "Starting glib_MainLoop stopped." << std::endl;
    }
};

/// Creates an Image with a red filled Circle and the current Time displayed in it.
cv::Mat
Create_Image() {
    cv::Size size = cv::Size( 640, 480 );
    cv::Mat image = cv::Mat::zeros( size, CV_8UC3 );
    cv::Point center = cv::Point( size.width / 2, size.height / 2 );
    int thickness = -1;
    int lineType = 8;

    cv::circle( image, center, size.width / 4.0, cv::Scalar( 0, 0, 255 ), thickness, lineType );

    std::stringstream current_Time;
    boost::posix_time::time_facet *facet = new boost::posix_time::time_facet( "%Y.%m.%d %H:%M:%S.%f" );
    current_Time.imbue( std::locale( current_Time.getloc(), facet ) );
    current_Time << boost::posix_time::microsec_clock::universal_time();

    int font = cv::FONT_HERSHEY_SCRIPT_SIMPLEX;
    double fontsize = 1;
    int font_Thickness = 1;

    int baseline = 0;
    cv::Size textSize_01 = cv::getTextSize( current_Time.str(), font, fontsize, font_Thickness , &baseline );
    baseline += font_Thickness;

    cv::Point textOrg_01( ( image.cols - textSize_01.width ) / 2, ( image.rows + textSize_01.height * 2 ) / 2 );
    cv::Scalar textcolour = cv::Scalar( 0, 255, 0 );
    cv::putText( image, current_Time.str(), textOrg_01, font, fontsize, textcolour , font_Thickness , 1 );

    return image;
}

/// Creates a Graph of the created Pipeline including the contained Elements. The environment variable "GST_DEBUG_DUMP_DOT_DIR" must be set, e.g to /tmp/ to actually create the Graph.
/// Furthermore GST_DEBUG needs to be activated, e.g. with "GST_DEBUG=3".
/// So "GST_DEBUG=3 GST_DEBUG_DUMP_DOT_DIR=/tmp/" ./Sandbox would work.
/// The .dot file can be converted to a e.g. svg-Graphic with the following command (Package GraphViz): dot -Tsvg -oPipelineGraph.svg PipelineGraph.dot
void
Create_PipelineGraph( GstElement *pipeline ) {
    bool debug_active = gst_debug_is_active();
    gst_debug_set_active( 1 );
    GST_DEBUG_BIN_TO_DOT_FILE( GST_BIN( pipeline ), GST_DEBUG_GRAPH_SHOW_ALL, "PipelineGraph" );
    gst_debug_set_active( debug_active );
}

void
Push_new_Image( const boost::system::error_code &error ) {
    if( error != 0 ) {
        std::cout << "Error in Timer: " << error.message() << std::endl;
        return;
    }

    cv::Mat image = Create_Image();

    /// OpenCV handles image in BGR, so to get RGB, Channels R and B needs to be swapped.
    cv::cvtColor( image, image, CV_CVTIMG_SWAP_RB );

    {
        /// How do i get the actual bpp and depth out of the cv::Mat?
        GstCaps *caps = gst_caps_new_simple( "video/x-raw-rgb", "width", G_TYPE_INT, image.cols, "height", G_TYPE_INT, image.rows, "framerate", GST_TYPE_FRACTION, 0, 1, NULL );
        g_object_set( G_OBJECT( source_OpenCV ), "caps", caps, NULL );
        gst_caps_unref( caps );

        IplImage* img = new IplImage( image );
        uchar *IMG_data = ( uchar* ) img->imageData;

        GstBuffer *buffer;
        {
            int bufferlength = image.cols * image.rows * image.channels();
            buffer = gst_buffer_new_and_alloc( bufferlength );

            /// Copy Data from OpenCV to GStreamer
            memcpy( GST_BUFFER_DATA( buffer ), IMG_data, GST_BUFFER_SIZE( buffer ) );

            GST_BUFFER_DURATION( buffer ) = gst_util_uint64_scale( bufferlength, GST_SECOND, 1 );
        }

        /// Setting the Metadata for the image to be pushed.
        {
            GstCaps *caps_Source = NULL;

            std::stringstream video_caps_text;
            video_caps_text << "video/x-raw-rgb,width=(int)" << image.cols << ",height=(int)" << image.rows << ",framerate=(fraction)0/1";
            caps_Source = gst_caps_from_string( video_caps_text.str().c_str() );

            if( !GST_IS_CAPS( caps_Source ) ) {
                std::cout << "Error creating Caps for OpenCV-Source, exiting...";
                exit( 1 );
            }

            gst_app_src_set_caps( GST_APP_SRC( source_OpenCV ), caps_Source );
            gst_buffer_set_caps( buffer, caps_Source );
            gst_caps_unref( caps_Source );
        }

        /// Setting a continues timestamp
        GST_BUFFER_TIMESTAMP( buffer ) = gst_util_uint64_scale( imagecounter * 20, GST_MSECOND, 1 );
        imagecounter += 1;

        /// Push Buffer into GStreamer-Pipeline
        GstFlowReturn rw;
        rw = gst_app_src_push_buffer( GST_APP_SRC( source_OpenCV ), buffer );

        if( rw != GST_FLOW_OK ) {
            std::cout << "Error push buffer to GStreamer-Pipeline, exiting...";

            exit( 1 );
        } else {
            std::cout << "GST_FLOW_OK " << "imagecounter: " << imagecounter << std::endl;
        }

    }

    /// Renew the Heartbeat-Timer
    heartbeat->expires_from_now( boost::posix_time::milliseconds( heartbeat_Intervall ) );
    heartbeat->async_wait( Push_new_Image );
}

int
main( int argc, char **argv ) {
    std::cout << "Sandbox started." << std::endl;

    /// ####################
    /// Initialise Sandbox
    /// ####################
    boost::shared_ptr<boost::asio::io_service> io_service = boost::make_shared<boost::asio::io_service>();
    boost::shared_ptr<boost::asio::io_service::work> work = boost::make_shared<boost::asio::io_service::work>( *io_service );
    boost::shared_ptr<boost::thread_group> threadgroup = boost::make_shared<boost::thread_group>();

    /// io_service Callback for continuously feeding into the pipeline of GStreamer.
    /// I've using to push the Buffer into GStreamer as i come available instead of getting informed about an empty pipeline by GStreamer-Signals.
    heartbeat_Intervall = 1000; ///< In Milliseconds
    heartbeat = boost::make_shared<boost::asio::deadline_timer>( ( *( io_service.get() ) ) );

    std::cout << "Initialise GStreamer..." << std::endl;
    gst_init( &argc, &argv );

    glib_MainLoop = g_main_loop_new( NULL, 0 );

    std::cout << "Start GLib_MainLoop..." << std::endl;
    io_service->post( GLib_MainLoop );

    /// Create some Workerthreads
    for( std::size_t i = 0; i < 3; ++i )  {
        threadgroup->create_thread( boost::bind( &boost::asio::io_service::run, &( *io_service ) ) );
    }

    /// ####################
    /// Do the actual Work
    /// ####################
    GstElement *pipeline;
    GstElement *converter_FFMpegColorSpace;
    GstElement *converter_VP8_Encoder;
    GstElement *muxer_WebM;
    GstElement *sink_TCPServer;


    /// Create GStreamer Elements

    pipeline = gst_pipeline_new( "OpenCV_to_TCPServer" );

    if( !pipeline ) {
        std::cout << "Error creating Pipeline, exiting...";
        return 1;
    }

    {
        source_OpenCV = gst_element_factory_make( "appsrc", "Source_OpenCV" );

        if( !source_OpenCV ) {
            std::cout << "Error creating OpenCV-Source, exiting...";
            return 1;
        }

        gst_bin_add( GST_BIN( pipeline ), source_OpenCV );
    }

    {
        converter_FFMpegColorSpace = gst_element_factory_make( "ffmpegcolorspace", "Converter_FFMpegColorSpace" );

        if( !converter_FFMpegColorSpace ) {
            std::cout << "Error creating Converter_FFMpegColorSpace, exiting...";
            return 1;
        }

        gst_bin_add( GST_BIN( pipeline ), converter_FFMpegColorSpace );
    }

    {
        converter_VP8_Encoder = gst_element_factory_make( "vp8enc", "Converter_VP8_Encoder" );

        if( !converter_VP8_Encoder ) {
            std::cout << "Error creating Converter_VP8_Encoder, exiting...";
            return 1;
        }

        gst_bin_add( GST_BIN( pipeline ), converter_VP8_Encoder );
    }

    {
        muxer_WebM = gst_element_factory_make( "webmmux", "Muxer_WebM" );

        if( !muxer_WebM ) {
            std::cout << "Error creating Muxer_WebM, exiting...";
            return 1;
        }

        gst_bin_add( GST_BIN( pipeline ), muxer_WebM );
    }

    {
        sink_TCPServer = gst_element_factory_make( "tcpserversink", "Sink_TCPServer" );

        if( !sink_TCPServer ) {
            std::cout << "Error creating Sink_TCPServer, exiting...";
            return 1;
        }

        gst_bin_add( GST_BIN( pipeline ), sink_TCPServer );
    }


    /// Link GStreamer Elements

    if( !gst_element_link( source_OpenCV, converter_FFMpegColorSpace ) ) {
        std::cout << "Error linking creating source_OpenCV to converter_FFMpegColorSpace, exiting...";
        return 2;
    }

    if( !gst_element_link( converter_FFMpegColorSpace, converter_VP8_Encoder ) ) {
        std::cout << "Error linking creating converter_FFMpegColorSpace to converter_VP8_Encoder, exiting...";
        return 2;
    }

    if( !gst_element_link( converter_VP8_Encoder, muxer_WebM ) ) {
        std::cout << "Error linking creating converter_VP8_Encoder to muxer_WebM, exiting...";
        return 2;
    }

    if( !gst_element_link( muxer_WebM, sink_TCPServer ) ) {
        std::cout << "Error linking creating muxer_WebM to sink_TCPServer, exiting...";
        return 2;
    }


    /// Set State of the GStreamer Pipeline to Playing
    GstStateChangeReturn ret = gst_element_set_state( pipeline, GST_STATE_PLAYING );

    if( ret == GST_STATE_CHANGE_FAILURE ) {
        std::cout << "Error setting GStreamer-Pipeline to playing.";
        return 2;
    }

    Create_PipelineGraph( pipeline );


    /// Start the Heartbeat, that continously creates new Images
    heartbeat->expires_from_now( boost::posix_time::milliseconds( heartbeat_Intervall ) );
    heartbeat->async_wait( Push_new_Image );

    /// ####################
    /// Shutdown the Sandbox
    /// ####################
    std::cout << "Wait some Seconds before joining all Threads and shutdown the Sandbox..." << std::endl;
    boost::this_thread::sleep( boost::posix_time::seconds( 4 ) );

    std::cout << "Shutdown Sandbox..." << std::endl;
    g_main_loop_quit( glib_MainLoop );
    io_service->stop();

    while( !io_service->stopped() ) {
        boost::this_thread::sleep( boost::posix_time::seconds( 1 ) );
    }

    work.reset();
    threadgroup->join_all();

    g_main_loop_unref( glib_MainLoop );

    threadgroup.reset();
    work.reset();
    io_service.reset();

    std::cout << "Sandbox stopped" << std::endl;
}

target_link_libraries( Sandbox ${Boost_LIBRARIES} ${GSTREAMER_0_10_LIBRARIES} ${GSTREAMER_0_10_APP_LIBRARIES} ${OpenCV_LIBS} )

set_target_properties( Sandbox PROPERTIES LINKER_LANGUAGE CXX )

我正在按照以下方式启动Sandbox程序:

LC_ALL="C" GST_DEBUG=3 GST_DEBUG_DUMP_DOT_DIR=/tmp/ ./Sandbox

然后应在/ tmp /中创建当前管道的图表。此.dot文件可以转换为例如svg-Graphic with:

dot -Tsvg -oPipelineGraph.svg PipelineGraph.dot

错误发生后。这是通过GST_DEBUG = 3:

获得的短消息
...
0:00:00.141888460 28057      0x2245d90 INFO                 basesrc gstbasesrc.c:2562:gst_base_src_loop:<Source_OpenCV> pausing after gst_pad_push() = not-negotiated
0:00:00.141924274 28057      0x2245d90 WARN                 basesrc gstbasesrc.c:2625:gst_base_src_loop:<Source_OpenCV> error: Internal data flow error.
0:00:00.141937917 28057      0x2245d90 WARN                 basesrc gstbasesrc.c:2625:gst_base_src_loop:<Source_OpenCV> error: streaming task paused, reason not-negotiated (-4)
0:00:00.141965714 28057      0x2245d90 INFO        GST_ERROR_SYSTEM gstelement.c:1964:gst_element_message_full:<Source_OpenCV> posting message: Internal data flow error.
0:00:00.141998959 28057      0x2245d90 INFO        GST_ERROR_SYSTEM gstelement.c:1987:gst_element_message_full:<Source_OpenCV> posted error message: Internal data flow error.
0:00:00.142018539 28057      0x2245d90 ERROR                 vp8enc gstvp8enc.c:1028:gst_vp8_enc_finish:<Converter_VP8_Encoder> encode returned 1 error
0:00:00.142053733 28057      0x2245d90 INFO             matroskamux matroska-mux.c:2226:gst_matroska_mux_start:<ebmlwrite0> DocType: webm, Version: 2
0:00:00.142082043 28057      0x2245d90 INFO               ebmlwrite ebml-write.c:218:gst_ebml_writer_send_new_segment_event: seeking to 0
0:00:00.142093688 28057      0x2245d90 INFO               GST_EVENT gstevent.c:606:gst_event_new_new_segment_full: creating newsegment update 0, rate 1.000000, format bytes, start 0, stop -1, position 0
...

GST_DEBUG = 4,它看起来像:

...
0:00:02.464122744 28483      0x24b8590 DEBUG               GST_CAPS gstpad.c:2925:gst_pad_get_allowed_caps:<Converter_VP8_Encoder:src> allowed caps video/x-vp8, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
0:00:02.464152446 28483      0x24b8590 DEBUG               GST_CAPS gstpad.c:2263:gst_pad_get_caps_unlocked:<Converter_VP8_Encoder:sink> pad getcaps returned video/x-raw-yuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ], format=(fourcc)I420
0:00:02.464174847 28483      0x24b8590 DEBUG               GST_PADS gstpad.c:2577:gst_pad_acceptcaps_default:<Converter_VP8_Encoder:sink> allowed caps video/x-raw-yuv, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ], format=(fourcc)I420
0:00:02.464198411 28483      0x24b8590 DEBUG               GST_PADS gstpad.c:2629:gst_pad_accept_caps:<Converter_VP8_Encoder:sink> acceptfunc returned 1
0:00:02.464210382 28483      0x24b8590 DEBUG          basetransform gstbasetransform.c:1082:gst_base_transform_find_transform:<Converter_FFMpegColorSpace> Input caps were video/x-raw-rgb, width=(int)640, height=(int)480, framerate=(fraction)0/1, and got final caps video/x-raw-yuv, width=(int)640, height=(int)480, framerate=(fraction)0/1, format=(fourcc)I420
0:00:02.464236195 28483      0x24b8590 DEBUG          basetransform gstbasetransform.c:810:gst_base_transform_configure_caps:<Converter_FFMpegColorSpace> in caps:  video/x-raw-rgb, width=(int)640, height=(int)480, framerate=(fraction)0/1
0:00:02.464252757 28483      0x24b8590 DEBUG          basetransform gstbasetransform.c:811:gst_base_transform_configure_caps:<Converter_FFMpegColorSpace> out caps: video/x-raw-yuv, width=(int)640, height=(int)480, framerate=(fraction)0/1, format=(fourcc)I420
0:00:02.464271709 28483      0x24b8590 DEBUG          basetransform gstbasetransform.c:819:gst_base_transform_configure_caps:<Converter_FFMpegColorSpace> have_same_caps: 0
0:00:02.464282177 28483      0x24b8590 DEBUG          basetransform gstbasetransform.c:2921:gst_base_transform_set_in_place:<Converter_FFMpegColorSpace> setting in_place FALSE
0:00:02.464292338 28483      0x24b8590 DEBUG          basetransform gstbasetransform.c:2860:gst_base_transform_set_passthrough:<Converter_FFMpegColorSpace> set passthrough 0
0:00:02.464302369 28483      0x24b8590 DEBUG          basetransform gstbasetransform.c:834:gst_base_transform_configure_caps:<Converter_FFMpegColorSpace> Calling set_caps method to setup caps
0:00:02.464318339 28483      0x24b8590 DEBUG       ffmpegcolorspace gstffmpegcolorspace.c:320:gst_ffmpegcsp_set_caps:<Converter_FFMpegColorSpace> could not configure context for input format
0:00:02.464329667 28483      0x24b8590 WARN           basetransform gstbasetransform.c:1311:gst_base_transform_setcaps:<Converter_FFMpegColorSpace> FAILED to configure caps <Converter_FFMpegColorSpace:src> to accept video/x-raw-yuv, width=(int)640, height=(int)480, framerate=(fraction)0/1, format=(fourcc)I420
0:00:02.464352143 28483      0x24b8590 DEBUG               GST_CAPS gstpad.c:2773:gst_pad_set_caps:<Converter_FFMpegColorSpace:sink> caps video/x-raw-rgb, width=(int)640, height=(int)480, framerate=(fraction)0/1 could not be set
0:00:02.464504648 28483      0x24b8590 INFO                 basesrc gstbasesrc.c:2562:gst_base_src_loop:<Source_OpenCV> pausing after gst_pad_push() = not-negotiated
0:00:02.464517617 28483      0x24b8590 DEBUG                basesrc gstbasesrc.c:2588:gst_base_src_loop:<Source_OpenCV> pausing task, reason not-negotiated
0:00:02.464531137 28483      0x24b8590 DEBUG               GST_PADS gstpad.c:5646:gst_pad_pause_task:<Source_OpenCV:src> pause task
0:00:02.464543705 28483      0x24b8590 DEBUG                   task gsttask.c:698:gst_task_set_state:<Source_OpenCV:src> Changing task 0x24c9000 to state 2
0:00:02.464585246 28483      0x24b8590 DEBUG              GST_EVENT gstevent.c:269:gst_event_new: creating new event 0x24b8940 eos 86
0:00:02.464618078 28483      0x24b8590 WARN                 basesrc gstbasesrc.c:2625:gst_base_src_loop:<Source_OpenCV> error: Internal data flow error.
0:00:02.464631538 28483      0x24b8590 WARN                 basesrc gstbasesrc.c:2625:gst_base_src_loop:<Source_OpenCV> error: streaming task paused, reason not-negotiated (-4)
0:00:02.464645609 28483      0x24b8590 DEBUG            GST_MESSAGE gstelement.c:1933:gst_element_message_full:<Source_OpenCV> start
0:00:02.464672918 28483      0x24b8590 INFO        GST_ERROR_SYSTEM gstelement.c:1964:gst_element_message_full:<Source_OpenCV> posting message: Internal data flow error.
0:00:02.464697059 28483      0x24b8590 DEBUG                GST_BUS gstbus.c:308:gst_bus_post:<bus0> [msg 0x2325680] posting on bus, type error, GstMessageError, gerror=(GError)NULL, debug=(string)"gstbasesrc.c\(2625\):\ gst_base_src_loop\ \(\):\ /GstPipeline:OpenCV_to_TCPServer/GstAppSrc:Source_OpenCV:\012streaming\ task\ paused\,\ reason\ not-negotiated\ \(-4\)"; from source <Source_OpenCV>
0:00:02.464727109 28483      0x24b8590 DEBUG                    bin gstbin.c:3164:gst_bin_handle_message_func:<OpenCV_to_TCPServer> [msg 0x2325680] handling child Source_OpenCV message of type error
0:00:02.464739521 28483      0x24b8590 DEBUG                    bin gstbin.c:3171:gst_bin_handle_message_func:<OpenCV_to_TCPServer> got ERROR message, unlocking state change
0:00:02.464750463 28483      0x24b8590 DEBUG                    bin gstbin.c:3441:gst_bin_handle_message_func:<OpenCV_to_TCPServer> posting message upward
0:00:02.464770307 28483      0x24b8590 DEBUG                GST_BUS gstbus.c:308:gst_bus_post:<bus1> [msg 0x2325680] posting on bus, type error, GstMessageError, gerror=(GError)NULL, debug=(string)"gstbasesrc.c\(2625\):\ gst_base_src_loop\ \(\):\ /GstPipeline:OpenCV_to_TCPServer/GstAppSrc:Source_OpenCV:\012streaming\ task\ paused\,\ reason\ not-negotiated\ \(-4\)"; from source <Source_OpenCV>
0:00:02.464792364 28483      0x24b8590 DEBUG                GST_BUS gstbus.c:338:gst_bus_post:<bus1> [msg 0x2325680] pushing on async queue
0:00:02.464804471 28483      0x24b8590 DEBUG                GST_BUS gstbus.c:343:gst_bus_post:<bus1> [msg 0x2325680] pushed on async queue
0:00:02.464824022 28483      0x24b8590 DEBUG                GST_BUS gstbus.c:334:gst_bus_post:<bus0> [msg 0x2325680] dropped
0:00:02.464835553 28483      0x24b8590 INFO        GST_ERROR_SYSTEM gstelement.c:1987:gst_element_message_full:<Source_OpenCV> posted error message: Internal data flow error.
...

GST_DEBUG = 5将超过此帖子的限制。 :)

我正在阅读Log in that Way将图像从Source_OpenCV传输到Converter_FFMpegColorSpace元素时出现问题?但是为什么converter_FFMpegColorSpace不能处理数据呢?我以为我向Converter_FFMpegColorSpace提供了x-raw-rgb,所以它可以将它转换为x-raw-yuv for Converter_VP8_Encoder。我是否以错误的方式指定了推送的图像?

如果我错过了一些信息,我很高兴获得提示,所以我可以添加它们。

提前致谢!

2 个答案:

答案 0 :(得分:4)

这里的问题是你将video / x-raw-rgb,width = 640,height = 480,framerate = 0/1设置为大写字母。这还不完整,如果是ARGB,你还需要提供红色,绿色和蓝色蒙版,字节序和alpha蒙版。检查例如以ffmpegcolorspace接收器模板为例,从中选择了正确的格式。

另外考虑使用GStreamer 1.x而不是旧的和未维护的0.10版本。在那里它也更容易指定大写,因为它只需要视频/ x-raw,格式= ARGB,宽度= 640,高度= 480,帧率= 0/1这种情况下(假设它是ARGB而不是BGRA或BGRx或无论)。

IIRC opencv使用RGB或RGBA。

答案 1 :(得分:1)

opencv输出格式为rgb,但vp8enc sink caps如下:

 SINK template: 'sink'
    Availability: Always
    Capabilities:
      video/x-raw-yuv
                 format: I420
                  width: [ 1, 2147483647 ]
                 height: [ 1, 2147483647 ]
              framerate: [ 0/1, 2147483647/1 ]

您需要转换rgb - &gt; yuv,我在opencv和gstreamer之间转换了yuv2rgb,如果你需要我可以和你分享我的代码。