Search code examples
videogstreamervideo-processingvideo-capturepython-gstreamer

Downscale h264 video only if video is more than 1080p


My overall objective is to ensure that i am not causing too much cpu usage unless necessary. I will be fetching h264 rtsp video from gstreamer and saving it. Wondering if i can save video in chunks (based on buffer size and duration) without re-encoding h264 if the resolution is less than 1080p (for less cpu utilization) and downscale the video only if it is more than 1080p.

Any idea or example gstreamer pipeline which can help me achieve what i wanted ?


Solution

  • You could decode one frame of the video stream check its resolution then launch the appropriate pipeline depending on the resolution.

    With C/C++ you could use a pad probe to get the pad caps on the src pad of the decoder then pause and link the appropriate file sink ore re-encode pipeline.

    GstCaps *caps = gst_pad_get_current_caps(decoder_src_pad);
    GstStructure *structure = gst_caps_get_structure(caps, 0);
    
    gint width, height;
    gst_structure_get_int(structure, "width", &width);
    gst_structure_get_int(structure, "height", &height);
    

    or

    Using just bash run gst-discover-1.0 to find the width and height and just parse the text

    user@computer:~$ gst-discoverer-1.0 -v rtsp://localhost:8554/test_stream
    Analyzing rtsp://localhost:8554/test_stream
    Done discovering rtsp://localhost:8554/test_stream
    
    Properties:
      Duration: 99:99:99.999999999
      Seekable: no
      Live: yes
      Tags: 
          video codec: H.264 (High Profile)
      unknown #0: application/x-rtp, media=(string)video, payload=(int)96, clock-rate=(int)90000, encoding-name=(string)H264, packetization-mode=(string)1, profile-level-id=(string)64001e, sprop-parameter-sets=(string)"Z2QAHqzZQKA9sBagICCoAAADAAgAAAMB5HixbLA\=\,aOvjyyLA", a-tool=(string)"vlc\ 3.0.16", a-recvonly=(string)"", a-type=(string)broadcast, a-charset=(string)UTF-8, ssrc=(uint)1465660118, clock-base=(uint)4212403521, seqnum-base=(uint)49262, npt-start=(guint64)415603480000, play-speed=(double)1, play-scale=(double)1, onvif-mode=(boolean)false
        video #1: video/x-h264, stream-format=(string)avc, alignment=(string)au, codec_data=(buffer)0164001effe1001d6764001eacd940a03db016a02020a8000003000800000301e478b16cb001000668ebe3cb22c0, level=(string)3, profile=(string)high, pixel-aspect-ratio=(fraction)1/1, width=(int)640, height=(int)480, framerate=(fraction)30/1, chroma-format=(string)4:2:0, bit-depth-luma=(uint)8, bit-depth-chroma=(uint)8, colorimetry=(string)2:4:5:1, parsed=(boolean)true
          Tags:
            video codec: H.264 (High Profile)
          
          Codec:
            video/x-h264, stream-format=(string)avc, alignment=(string)au, codec_data=(buffer)0164001effe1001d6764001eacd940a03db016a02020a8000003000800000301e478b16cb001000668ebe3cb22c0, level=(string)3, profile=(string)high, pixel-aspect-ratio=(fraction)1/1, width=(int)640, height=(int)480, framerate=(fraction)30/1, chroma-format=(string)4:2:0, bit-depth-luma=(uint)8, bit-depth-chroma=(uint)8, colorimetry=(string)2:4:5:1, parsed=(boolean)true
          Stream ID: 1b3bae77f33eae0e586433000678603a00eb5148824d7cb146fe50e009eb5bf7/video:0:0:RTP:AVP:96
          Width: 640
          Height: 480
          Depth: 24
          Frame rate: 30/1
          Pixel aspect ratio: 1/1
          Interlaced: false
          Bitrate: 0
          Max bitrate: 0