This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TDA4VH-Q1:GST_ELEMENT_SET_STATE 函数中的 GStreamer 应用阻止

Guru**** 2478765 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1388828/tda4vh-q1-gstreamer-application-blocking-in-gst_element_set_state-function

器件型号:TDA4VH-Q1
主题中讨论的其他器件:TDA4VH

工具与软件:

大家好、我正在使用 SDK0900处理 TDA4VH、我遇到了一个问题、在我多次调用 gst_element_set_state 函数时、gstreamer 应用程序会阻止。

附件是可以重现此问题的最小代码、当问题发生时、gdb 跟踪显示它卡在具有 VIDIOC_STREAMOFF 命令的 ioctl 函数中。

我注意到、每次将管道状态设置为 NULL 时、它都停留在60秒左右、因此我怀疑内核 v4l2驱动程序中可能有一个60秒的超时值。


我还注意到、这种最小应用程序的驻留内存不断增加、因此我怀疑其中也可能存在内存泄漏。


因此、我想知道为什么这个 ioctl 命令会卡住? 或者在代码中使用 gstreamer API 时是否有错误?

请帮助我找出这个问题的原因,非常感谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    上传代码文件时出现问题、因此我将其发布在此处:

    #include <stdio.h>
    #include <stdint.h>
    #include <gst/gst.h>
    
    struct gstChObj
    {
        GstElement *m_pipeline;
        uint32_t ch_idx;
        uint32_t started;
    }gapp[2];
    
    #define PRINT(msg, ...) \
        do { printf(" %lu [%s:%u] " msg, get_time_in_ms(), __FUNCTION__, __LINE__, ## __VA_ARGS__); } while (1 == 0)
    
    // static const char *gst_cmdline = "videotestsrc is-live=true do-timestamp=true num-buffers=300000 ! video/x-raw, width=1920, height=1080, framerate=30/1, format=NV12 ! v4l2h265enc ! fakesink";
    static const char *gst_cmdline = "videotestsrc ! v4l2h265enc ! fakesink";
    
    static const char *GstState_enum_to_string[] =
        {
            [GST_STATE_VOID_PENDING] = "GST_STATE_VOID_PENDING",
            [GST_STATE_NULL] = "GST_STATE_NULL",
            [GST_STATE_READY] = "GST_STATE_READY",
            [GST_STATE_PAUSED] = "GST_STATE_PAUSED",
            [GST_STATE_PLAYING] = "GST_STATE_PLAYING",
    };
    
    static const char *GstStateChangeReturn_enum_to_string[] =
        {
            [GST_STATE_CHANGE_FAILURE] = "GST_STATE_CHANGE_FAILURE",
            [GST_STATE_CHANGE_SUCCESS] = "GST_STATE_CHANGE_SUCCESS",
            [GST_STATE_CHANGE_ASYNC] = "GST_STATE_CHANGE_ASYNC",
            [GST_STATE_CHANGE_NO_PREROLL] = "GST_STATE_CHANGE_NO_PREROLL",
    };
    
    static uint64_t get_time_in_ms()
    {
        struct timeval ts;
        gettimeofday(&ts, NULL);
    
        return ts.tv_sec * 1000 + ts.tv_usec / 1000;
    }
    
    
    static int gst_start_playing(struct gstChObj *chobj)
    {
        GstState state, pend;
        GstStateChangeReturn ret;
    
        // if pipeline has set to playing but no frame has ever beem provided,
        // this api may hang
        PRINT("channel %d,  ... gst_element_get_state\n ... ", chobj->ch_idx);
        ret = gst_element_get_state(chobj->m_pipeline, &state, &pend, GST_CLOCK_TIME_NONE);
        PRINT("channel %d, ret %s, state: %s, pend: %s\n",
               chobj->ch_idx,
               GstStateChangeReturn_enum_to_string[ret],
               GstState_enum_to_string[state],
               GstState_enum_to_string[pend]);
        PRINT("ret %d, state: %d, pend: %d\n", ret, state, pend);
        if (state == GST_STATE_PLAYING)
        {
            PRINT("already in playing state!\n");
            chobj->started = 1;
            return 0;
        }
        else
        {
            PRINT("channel %d, gst set state to playing...\n", chobj->ch_idx);
            ret = gst_element_set_state(GST_ELEMENT(chobj->m_pipeline), GST_STATE_PLAYING);
            PRINT("channel %d, gst set state to playing... done. ret: %s\n", chobj->ch_idx, GstStateChangeReturn_enum_to_string[ret]);
            PRINT("gst_element_set_state ret is %d\n", ret);
            if (ret == GST_STATE_CHANGE_FAILURE)
            {
                PRINT("failed to set pipeline state to playing!");
                return 0;
            }
            chobj->started = 1;
        }
    
        return 0;
    }
    
    
    
    static int gst_stop_playing(struct gstChObj *chobj)
    {
        GstStateChangeReturn ret;
        GstFlowReturn t;
        GstState state, pend;
    
        // check current state
        PRINT("channel %d,  ... gst_element_get_state\n ... ", chobj->ch_idx);
        ret = gst_element_get_state(chobj->m_pipeline, &state, &pend, GST_CLOCK_TIME_NONE);
        PRINT("channel %d, ret %s, state: %s, pend: %s\n",
               chobj->ch_idx,
               GstStateChangeReturn_enum_to_string[ret],
               GstState_enum_to_string[state],
               GstState_enum_to_string[pend]);
        if (state != GST_STATE_PLAYING && pend != GST_STATE_PLAYING)
        {
            PRINT("already stopped!\n");
            chobj->started = 0;
            return 0;
        }
    
        // // enqueue EOS to stream
        // PRINT("enqueue EOS to stream...");
        // t = gst_app_src_end_of_stream(GST_APP_SRC(chobj->appsrc_elem));
        // if (t != GST_FLOW_OK)
        // {
        //     PRINT("gst_wrapper: Pushing EOS to AppSrc returned %d instead of GST_FLOW_OK:%d\n", t, GST_FLOW_OK);
        // }
    
        // setting pipeline to paused
        PRINT("channel %d, setting state to PAUSED...\n", chobj->ch_idx);
        ret = gst_element_set_state(GST_ELEMENT(chobj->m_pipeline), GST_STATE_PAUSED);
        PRINT("channel %d, setting state to PAUSED... done. ret: %s\n", chobj->ch_idx, GstStateChangeReturn_enum_to_string[ret]);
        if (ret == GST_STATE_CHANGE_FAILURE)
        {
            PRINT("failed to set pipeline state to playing!\n");
            return -1;
        }
    
        // stopping pipeline
        PRINT("channel %d, setting state to NULL...\n", chobj->ch_idx);
        ret = gst_element_set_state(GST_ELEMENT(chobj->m_pipeline), GST_STATE_NULL);
        PRINT("channel %d, setting state to NULL... done. ret: %s\n", chobj->ch_idx, GstStateChangeReturn_enum_to_string[ret]);
        if (ret == GST_STATE_CHANGE_FAILURE)
        {
            PRINT("failed to set pipeline state to playing!\n");
            return -1;
        }
        chobj->started = 0;
    
        return 0;
    }
    
    
    int main(int argc, char const *argv[])
    {
        GError *gerror = NULL;
    
        setenv("GST_DEBUG", "3,appsrc:4", 1);
        setenv("GST_DEBUG_DUMP_DOT_DIR", "/data/gst-test", 1);
        gst_init(NULL, NULL);
    
        gapp[0].m_pipeline = gst_parse_launch(gst_cmdline, &gerror);
        g_assert(gapp[0].m_pipeline);
        gapp[0].ch_idx = 0;
    
        gapp[1].m_pipeline = gst_parse_launch(gst_cmdline, &gerror);
        g_assert(gapp[1].m_pipeline);
        gapp[1].ch_idx = 1;
    
        uint64_t t1, t2, t3, t4;
        while (1)
        {
            t1 = get_time_in_ms();
            gst_start_playing(&gapp[0]);
            // gst_start_playing(&gapp[1]);
            t2 = get_time_in_ms();
            if (t2 - t1 > 5000UL){
                puts("error: gst_start_playing timeout!");
                exit(1);
            }
            sleep(2);
            t3 = get_time_in_ms();
            gst_stop_playing(&gapp[0]);
            // gst_stop_playing(&gapp[1]);
            t4 = get_time_in_ms();
            if (t4 - t3 > 5000UL){
                puts("error: gst_stop_playing timeout!");
                exit(1);
            }
        }
        
    }
    
    

    Concerto。mak:

    ifeq ($(TARGET_CPU),$(filter $(TARGET_CPU), A72))
    include $(PRELUDE)
    
    TARGET := gst-test
    CSOURCES := gst-test.c
    # CSOURCES := app_tmp.c
    TARGETTYPE := exe
    
    # IDIRS += $(VISION_APPS_KERNELS_IDIRS)
    # IDIRS += $(VISION_APPS_PATH)/kernels/fileio/include
    # IDIRS += $(PSDK_PATH)/imaging/kernels/include
    # IDIRS += $(PSDK_PATH)/imaging/sensor_drv/include
    # IDIRS += $(VISION_APPS_PATH)/kernels/img_proc/include/
    # IDIRS += $(VISION_APPS_PATH)/kernels/hirain_utils/include/
    # IDIRS += ${VISION_APPS_PATH}/utils/hirain_tiovx_modules//include
    # IDIRS += $(VISION_APPS_PATH)/kernels/img_proc/include/
    IDIRS += $(LINUX_FS_PATH)/usr/include/gstreamer-1.0/
    IDIRS += $(LINUX_FS_PATH)/usr/include/glib-2.0/
    IDIRS += $(LINUX_FS_PATH)/usr/lib/glib-2.0/include/
    
    CFLAGS += -Wno-unused-function -g
    
    SYS_SHARED_LIBS += gstreamer-1.0 gstapp-1.0 gstbase-1.0 gobject-2.0 glib-2.0 gmodule-2.0
    
    include $(FINALE)
    
    endif
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    我目前不在办公室。 返回后、我会查看您的问题。

    谢谢!

    Fabiana

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    您似乎在要求调试我们不支持的自定义代码。

    谢谢!

    Fabiana

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Nonono,事实是,我在其他平台上运行相同的代码,它运行良好,这就是为什么我怀疑它是一个与平台相关的问题。

    您可以尝试重现此问题、并且代码似乎卡在 gstbufferpool 正在等待编解码器硬件使用的缓冲区的某个位置。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您能否分享您当前正在使用的 SDK +任何软件包以及此代码在哪个平台上运行良好?

    谢谢!

    Fabiana

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    很抱歉耽误你的时间。

    我可以很好地在 I 上运行我的代码 MX8平台。

    您当前使用的 SDK 和任何软件包

    对不起,我没有得到你,我正在使用 sdk0900,你说"包"是什么意思?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您使用的是 Linux 还是 RTOS SDK? 请在此处参阅适用于此器件的可用 SDK 列表: https://www.ti.com/product/TDA4VH-Q1#software-development

    谢谢!

    Fabiana

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Linux 实际上不依赖于 RTOS。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的确认。 您是否可以尝试使用最新的 SDK 版本、并告知我问题是否仍然存在?

    谢谢!

    Fabiana

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    最新的 SDK 中是否有任何与此相关的更改?

    我们在产品中使用 SDD0900、更改 SDK 版本很困难。

    您可以尝试使用我的代码重现此问题、非常简单、只需编译它并运行即可、无需任何输入。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好吧,我将尝试在我的最后

    谢谢!

    Fabiana

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    大家好、在这方面有什么进展吗?  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    嗨、haijun:

    这对您来说仍然是一个未决问题吗?

    谢谢!

    Fabiana

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是、

    我想知道您能否在最后重现此问题

    谢谢。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好

    我们负责处理此线程的专家 Fabiana 在9月25日之前不在办公室。 请预计回复将延迟。

    谢谢。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    正在解锁该线程。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    正在解锁该线程。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你(们)好  

    这个问题仍然困扰着你吗?

    此致、

    Adam