【问题标题】:Gstreamer wont play same video consecutivelyGstreamer 不会连续播放相同的视频
【发布时间】:2022-03-08 05:25:12
【问题描述】:

我正在使用在 Nvidia Jetson nano 上播放的 PyGST 和 Gst.parse_launch 编写 Gstreamer 管道。管道播放 4k 视频并在运行时淡入淡出视频。

我的问题是管道不会连续播放相同的视频。它会一个接一个地播放不同的视频。淡入淡出功能也运行良好。

这是问题的描述:

该管道第一次使用示例视频,例如 video_1.mp4。当我再次播放相同的视频时,它会卡在第一帧,停留在该帧并在几秒钟后退出该过程。

如果我播放 video_1.mp4,然后播放不同的视频,例如 video_2.mp4,那么管道将毫无问题地工作。如果在此之后我播放 video_1.mp4 那么它也会一直播放。

video_1.mp4 的持续时间为 10 秒。如果我在 5 秒处停止 video_1.mp4 并再次播放视频,将显示 video_1.mp4 的第一帧,它将在该帧等待 5 秒,然后在前一个管道停止的同一点继续解码视频.

我怀疑播放同一视频时缓冲区运行时间尚未重置为 0。我不确定为什么会发生这种情况,我将管道设置为 NULL,并尝试在视频完成后进行搜索位置 0 并刷新管道中的元素以将时钟时间重置回 0。也许是语法或我的方式我实施它是不正确的。

下面的这个线程创建管道

import gi
import time
gi.require_version(\'Gst\', \'1.0\')
gi.require_version(\'GstPbutils\', \'1.0\')
gi.require_version(\'GstController\', \'1.0\')
from gi.repository import GObject, Gst, GstPbutils, GstController
from player_thread import PlayerThread
from threading import Timer
import logging
import time

class VideoPlayer(): 
    def __init__(self):
        Gst.init(None)
        GObject.threads_init()

        self.pipeline = Gst.parse_launch (\"\"\"
            nvcompositor name=comp sink_0::alpha=1 ! video/x-raw(memory:NVMM),format=RGBA ! 
            nvvidconv ! video/x-raw(memory:NVMM), format=NV12 ! autovideosink name=sinky uridecodebin name=vidsrc !
            nvvidconv name=pipeconv ! video/x-raw(memory:NVMM),format=RGBA,pixel-aspect-ratio=1/1 ! queue ! comp.sink_0
        \"\"\")

        self.loop = GObject.MainLoop()
        self.bus = self.pipeline.get_bus()
        self.bus.add_signal_watch()
        self.bus.connect(\"message::eos\", self.bus_call, self.loop)
        self.bus.connect(\"message::error\", self.bus_call, self.loop)
        self.sink  = self.pipeline.get_by_name(\'sinky\')
        self.convert = self.pipeline.get_by_name(\'pipeconv\')
        self.source = self.pipeline.get_by_name(\'vidsrc\')
        self.compositor = self.pipeline.get_by_name(\'comp\')
        self.source.connect(\"pad-added\", self.on_pad_added)
        self.running = False
        self.pipeline.set_state(Gst.State.NULL)
        self.loop.run()

    def get_alpha_controller(self, incoming_pad):
        self.pad = incoming_pad
        self.control_source = GstController.InterpolationControlSource()
        self.control_source.set_property(\'mode\', GstController.InterpolationMode.LINEAR)
        self.control_bind = GstController.DirectControlBinding.new(self.pad, \'alpha\', self.control_source)
        self.pad.add_control_binding(self.control_bind)
        return self.control_source

    def fade_video_in(self):
        self.compositor_sink_pad = self.compositor.get_static_pad(\'sink_0\')
        self.control_source = self.get_alpha_controller(self.compositor_sink_pad)
        self.control_source.set(0*Gst.SECOND, 0)
        self.control_source.set(2*Gst.SECOND, 1)

    def fade_video_out(self):
            self.pos = self.pipeline.query_position(Gst.Format.TIME).cur 
            self.control_source.set(self.pos, 1)
            self.control_source.set(self.pos + 1*Gst.SECOND, 0)

    def on_pad_added(self, src, new_pad):
        print(
            \"Received new pad \'{0:s}\' from \'{1:s}\'\".format(
                new_pad.get_name(),
                src.get_name()))
        
        new_pad_caps = new_pad.get_current_caps()
        new_pad_struct = new_pad_caps.get_structure(0)
        new_pad_type = new_pad_struct.get_name()

        if new_pad_type.startswith(\"video/x-raw\"):
            sink_pad = self.convert.get_static_pad(\"sink\")
        else:
            print(
                \"It has type \'{0:s}\' which is not raw audio/video. Ignoring.\".format(new_pad_type))
            return

        # if our converter is already linked, we have nothing to do here
        # if(sink_pad.is_linked()):
        #     print(\"We are already linked. Ignoring.\")
        #     return

        # attempt the link
        ret = new_pad.link(sink_pad)

        if not ret == Gst.PadLinkReturn.OK:
            print(\"Type is \'{0:s}}\' but link failed\".format(new_pad_type))
        else:
            print(\"Link succeeded (type \'{0:s}\')\".format(new_pad_type))

        return

    def play_video(self, video_url, scene_name):
        self.compositor.props.background = 1
        self.running = True
        self.scene_name = scene_name 
        self.video_url = video_url  
        print(self.video_url)
        self.source.props.uri = self.video_url
        self.sink.seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH, 0 * Gst.SECOND)
        self.pipeline.set_state(Gst.State.READY)
        self.pipeline.get_state(Gst.CLOCK_TIME_NONE)
        self.pipeline.set_state(Gst.State.PAUSED)
        self.pipeline.set_state(Gst.State.PLAYING)

    def stop_video(self):
        self.running = False
        self.pipeline.set_state(Gst.State.NULL)
        self.pipeline.set_state(Gst.State.READY)
        self.pipeline.seek_simple(Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT, 0.0 * Gst.SECOND )
        self.source.props.uri = \"\"
 

    def bus_call(self, bus, message, loop):
        t = message.type
        if t == Gst.MessageType.EOS:
            self.stop_video()

        elif t == Gst.MessageType.ERROR:
            print(message.parse_error())
        elif message.type == Gst.MessageType.SEGMENT_DONE:
            # self.fade_video_out()
            pass
        else:
                # should not get here
                print(\"ERROR: Unexpected message received\")
        return True

    def exit(self):
        self.loop.quit()

这些是发生错误时的 Gstreamer 调试日志

0:05:51.707439047  1756   0x7f7800e540 WARN              aggregator gstaggregator.c:1717:gst_aggregator_query_latency_unlocked:<comp> Latency query failed
0:05:51.709119977  1756   0x7f70007460 WARN                 basesrc gstbasesrc.c:3583:gst_base_src_start_complete:<source> pad not activated yet
0:05:51.709991980  1756   0x7f70007460 WARN                 basesrc gstbasesrc.c:3583:gst_base_src_start_complete:<source> pad not activated yet
sending message {\"action\": \"STATE_CHANGE\", \"body\": {\"videoActiveVideo\": \"test\"}}
0:05:51.714088392  1756     0x106e9630 WARN                 qtdemux qtdemux_types.c:233:qtdemux_type_get: unknown QuickTime node type pasp
0:05:51.714195686  1756     0x106e9630 WARN                 qtdemux qtdemux.c:3031:qtdemux_parse_trex:<qtdemux11> failed to find fragment defaults for stream 1
Opening in BLOCKING MODE 
0:05:51.759452369  1756     0x106fae80 WARN                    v4l2 gstv4l2object.c:4447:gst_v4l2_object_probe_caps:<nvv4l2decoder11:src> Failed to probe pixel aspect ratio with VIDIOC_CROPCAP: Unknown error -1
0:05:51.759527839  1756     0x106fae80 WARN                    v4l2 gstv4l2object.c:2388:gst_v4l2_object_add_interlace_mode:0x7f64022090 Failed to determine interlace mode
0:05:51.759581956  1756     0x106fae80 WARN                    v4l2 gstv4l2object.c:2388:gst_v4l2_object_add_interlace_mode:0x7f64022090 Failed to determine interlace mode
0:05:51.759638728  1756     0x106fae80 WARN                    v4l2 gstv4l2object.c:2388:gst_v4l2_object_add_interlace_mode:0x7f64022090 Failed to determine interlace mode
NvMMLiteOpen : Block : BlockType = 261 
NVMEDIA: Reading vendor.tegra.display-size : status: 6 
NvMMLiteBlockCreate : Block : BlockType = 261 
0:05:51.865431565  1756     0x106fae80 WARN                    v4l2 gstv4l2object.c:4447:gst_v4l2_object_probe_caps:<nvv4l2decoder11:src> Failed to probe pixel aspect ratio with VIDIOC_CROPCAP: Unknown error -1
0:05:51.865703395  1756     0x106fae80 WARN                    v4l2 gstv4l2object.c:2388:gst_v4l2_object_add_interlace_mode:0x7f64022090 Failed to determine interlace mode
0:05:51.865971579  1756     0x106fae80 WARN                    v4l2 gstv4l2object.c:2388:gst_v4l2_object_add_interlace_mode:0x7f64022090 Failed to determine interlace mode
0:05:51.866240232  1756     0x106fae80 WARN                    v4l2 gstv4l2object.c:2388:gst_v4l2_object_add_interlace_mode:0x7f64022090 Failed to determine interlace mode
Received new pad \'src_16\' from \'vidsrc\'
Link succeeded (type \'video/x-raw\')
0:05:51.876923175  1756     0x106fae80 WARN            v4l2videodec gstv4l2videodec.c:1673:gst_v4l2_video_dec_decide_allocation:<nvv4l2decoder11> Duration invalid, not setting latency
0:05:51.877534077  1756     0x106fae80 WARN          v4l2bufferpool gstv4l2bufferpool.c:1065:gst_v4l2_buffer_pool_start:<nvv4l2decoder11:pool:src> Uncertain or not enough buffers, enabling copy threshold
0:05:51.883864038  1756   0x7f5c007850 WARN          v4l2bufferpool gstv4l2bufferpool.c:1512:gst_v4l2_buffer_pool_dqbuf:<nvv4l2decoder11:pool:src> Driver should never set v4l2_buffer.field to ANY
0:05:51.891684769  1756   0x7f7800e540 FIXME               basesink gstbasesink.c:3145:gst_base_sink_default_event:<sinky-actual-sink-nvoverlay> stream-start event without group-id. Consider implementing group-id handling in the upstream elements
0:05:51.893670863  1756   0x7f7800e540 WARN            nvcompositor gstnvcompositor.c:980:gst_nvcompositor_negotiated_caps:<comp> Release old pool

这些是您播放不同视频并且管道重置后的日志(管道正常工作)

0:06:21.907924995  1756   0x7f580cc320 WARN              aggregator gstaggregator.c:1717:gst_aggregator_query_latency_unlocked:<comp> Latency query failed
0:06:21.909268156  1756   0x7f70007460 WARN                 basesrc gstbasesrc.c:3583:gst_base_src_start_complete:<source> pad not activated yet
0:06:21.910099324  1756   0x7f70007460 WARN                 basesrc gstbasesrc.c:3583:gst_base_src_start_complete:<source> pad not activated yet
sending message {\"action\": \"STATE_CHANGE\", \"body\": {\"videoActiveVideo\": \"test1\"}}
0:06:21.913367433  1756   0x7f7800e720 WARN                 qtdemux qtdemux_types.c:233:qtdemux_type_get: unknown QuickTime node type gsst
0:06:21.914455326  1756   0x7f7800e720 WARN                 qtdemux qtdemux_types.c:233:qtdemux_type_get: unknown QuickTime node type gstd
0:06:21.914529130  1756   0x7f7800e720 WARN                 qtdemux qtdemux.c:3031:qtdemux_parse_trex:<qtdemux12> failed to find fragment defaults for stream 1
0:06:21.914677884  1756   0x7f7800e720 WARN                 qtdemux qtdemux.c:3031:qtdemux_parse_trex:<qtdemux12> failed to find fragment defaults for stream 2
Opening in BLOCKING MODE 
0:06:21.964505314  1756     0x106ee320 WARN                    v4l2 gstv4l2object.c:4447:gst_v4l2_object_probe_caps:<nvv4l2decoder12:src> Failed to probe pixel aspect ratio with VIDIOC_CROPCAP: Unknown error -1
0:06:21.964574795  1756     0x106ee320 WARN                    v4l2 gstv4l2object.c:2388:gst_v4l2_object_add_interlace_mode:0x7f5802e8e0 Failed to determine interlace mode
0:06:21.964636619  1756     0x106ee320 WARN                    v4l2 gstv4l2object.c:2388:gst_v4l2_object_add_interlace_mode:0x7f5802e8e0 Failed to determine interlace mode
0:06:21.964687871  1756     0x106ee320 WARN                    v4l2 gstv4l2object.c:2388:gst_v4l2_object_add_interlace_mode:0x7f5802e8e0 Failed to determine interlace mode
NvMMLiteOpen : Block : BlockType = 261 
NVMEDIA: Reading vendor.tegra.display-size : status: 6 
NvMMLiteBlockCreate : Block : BlockType = 261 
0:06:22.070629669  1756     0x106ee320 WARN                    v4l2 gstv4l2object.c:4447:gst_v4l2_object_probe_caps:<nvv4l2decoder12:src> Failed to probe pixel aspect ratio with VIDIOC_CROPCAP: Unknown error -1
0:06:22.070809622  1756     0x106ee320 WARN                    v4l2 gstv4l2object.c:2388:gst_v4l2_object_add_interlace_mode:0x7f5802e8e0 Failed to determine interlace mode
0:06:22.071008898  1756     0x106ee320 WARN                    v4l2 gstv4l2object.c:2388:gst_v4l2_object_add_interlace_mode:0x7f5802e8e0 Failed to determine interlace mode
0:06:22.071295416  1756     0x106ee320 WARN                    v4l2 gstv4l2object.c:2388:gst_v4l2_object_add_interlace_mode:0x7f5802e8e0 Failed to determine interlace mode
Received new pad \'src_17\' from \'vidsrc\'
Link succeeded (type \'video/x-raw\')
Received new pad \'src_18\' from \'vidsrc\'
It has type \'audio/x-raw\' which is not raw audio/video. Ignoring.
0:06:22.080439932  1756     0x106ee320 WARN            v4l2videodec gstv4l2videodec.c:1673:gst_v4l2_video_dec_decide_allocation:<nvv4l2decoder12> Duration invalid, not setting latency
0:06:22.080866610  1756     0x106ee320 WARN          v4l2bufferpool gstv4l2bufferpool.c:1065:gst_v4l2_buffer_pool_start:<nvv4l2decoder12:pool:src> Uncertain or not enough buffers, enabling copy threshold
0:06:22.085282770  1756   0x7f5c0078f0 WARN          v4l2bufferpool gstv4l2bufferpool.c:1512:gst_v4l2_buffer_pool_dqbuf:<nvv4l2decoder12:pool:src> Driver should never set v4l2_buffer.field to ANY
0:06:22.091041154  1756   0x7f580cc320 FIXME               basesink gstbasesink.c:3145:gst_base_sink_default_event:<sinky-actual-sink-nvoverlay> stream-start event without group-id. Consider implementing group-id handling in the upstream elements
0:06:22.098388747  1756   0x7f580cc320 WARN            nvcompositor gstnvcompositor.c:980:gst_nvcompositor_negotiated_caps:<comp> Release old pool
0:06:22.108516102  1756   0x7f580cc320 ERROR                    omx gstomx.c:256:gst_omx_component_handle_messages:<sinky-actual-sink-nvoverlay> yuv420 port 0 was not flushing

标签: python gstreamer nvidia-jetson-nano pygst


【解决方案1】:

不确定您的情况,但由于 Jetson 上的 autovideosink 可能会选择 nvoverlaysink,您可以尝试 resetting its properties。

【讨论】:

  • @Isaac Sante,您可以尝试一下吗?一些反馈将受到欢迎。
猜你喜欢
  • 1970-01-01
  • 2023-02-15
  • 1970-01-01
  • 2012-10-12
  • 1970-01-01
  • 1970-01-01
  • 2020-09-07
  • 2011-01-16
  • 2015-04-23
相关资源
最近更新 更多