1

我想在视频图像上查看当前的 CPU 负载(来源是/dev/video0),我认为textoverlayelement 非常适合这个。我已经构建了一个(看似)工作管道,除了textoverlay一直显示最初设置的值。

管道目前是这样的:

v4l2src > qtdemux > queue > ffmpegcolorspace > textoverlay > xvimagesink

代码看起来像这样(我已经删除了一堆 gtk 窗口、线程处理代码和其他一些信号处理,只留下了相关部分):

#!/usr/bin/env python

import sys, os, time, signal
import pygtk, gtk, gobject

import pygst
pygst.require("0.10")
import gst

# For cpu load stats
import psutil
from multiprocessing import Process, Value, Lock # For starting threads

class Video:
  def __init__(self):

    window = gtk.Window(gtk.WINDOW_TOPLEVEL)        
    vbox = gtk.VBox()
    window.add(vbox)
    self.movie_window = gtk.DrawingArea()
    vbox.add(self.movie_window)   
    window.show_all()

    # Set up the gstreamer pipeline
    self.pipeline = gst.Pipeline("pipeline")
    self.camera = gst.element_factory_make("v4l2src","camera")
    self.camera.set_property("device","""/dev/video0""")
    self.pipeline.add(self.camera)

    # Demuxer
    self.demuxer = gst.element_factory_make("qtdemux","demuxer")

    # Create a dynamic callback for the demuxer
    self.demuxer.connect("pad-added", self.demuxer_callback)

    self.pipeline.add(self.demuxer)  

    # Demuxer doesnt have static pads, but they are created at runtime, we will need a callback to link those
    self.videoqueue = gst.element_factory_make("queue","videoqueue")

    self.pipeline.add(self.videoqueue)

    self.videoconverter = gst.element_factory_make("ffmpegcolorspace","videoconverter")
    self.pipeline.add(self.videoconverter)

    ## Text overlay stuff
    self.textoverlay = gst.element_factory_make("textoverlay","textoverlay")

    self.overlay_text = "cpu load, initializing"
    self.textoverlay.set_property("text",self.overlay_text)
    self.textoverlay.set_property("halign", "left")
    self.textoverlay.set_property("valign", "top")
    self.textoverlay.set_property("shaded-background","true")
    self.pipeline.add(self.textoverlay)

    self.videosink = gst.element_factory_make("xvimagesink","videosink")
    self.pipeline.add(self.videosink)

    self.camera.link(self.videoqueue)
    gst.element_link_many(self.videoqueue,   self.videoconverter, self.textoverlay, self.videosink)


    bus = self.pipeline.get_bus()
    bus.add_signal_watch()
    bus.enable_sync_message_emission()

    # Start stream
    self.pipeline.set_state(gst.STATE_PLAYING)

    # CPU stats calculator thread    
    cpu_load_thread = Process(target=self.cpu_load_calculator, args=())
    cpu_load_thread.start()

  def demuxer_callback(self, dbin, pad):

    if pad.get_property("template").name_template == "video_%02d":
      print "Linking demuxer & videopad"
      qv_pad = self.videoqueue.get_pad("sink")
      pad.link(qv_pad)


  def cpu_load_calculator(self):

    cpu_num = len( psutil.cpu_percent(percpu=True))

    while True:
      load = psutil.cpu_percent(percpu=True)
      self.parsed_load = ""

      for i in range (0,cpu_num):
        self.parsed_load = self.parsed_load + "CPU%d: %s%% " % (i, load[i])

      print self.textoverlay.get_property("text") # Correctly prints previous cycle CPU load
      self.textoverlay.set_property("text",self.parsed_load)


      time.sleep(2)

c = Video()

gtk.threads_init()
gtk.main()

一直在cpu_load_calculator后台运行,在我设置新值之前,我使用该函数打印出之前的get_property()值,并且设置正确。但是在实际的视频输出窗口上,它保持初始值。如何使 textoverlay 也正确更新到视频窗口?

4

1 回答 1

2

问题是您正在尝试从不同的Process更新 textoverlay 。与线程不同的进程在单独的地址空间中运行。

您可以切换到线程:

from threading import Thread
...
# CPU stats calculator thread    
cpu_load_thread = Thread(target=self.cpu_load_calculator, args=())
cpu_load_thread.start()

或者您可以cpu_load_calculator从主线程运行循环。这将起作用,因为self.pipeline.set_state(gst.STATE_PLAYING)在后台启动它自己的线程。

所以这就足够了:

# Start stream
self.pipeline.set_state(gst.STATE_PLAYING)

# CPU stats calculator loop
self.cpu_load_calculator()
于 2014-03-23T06:51:12.883 回答