2.2.18. Video Outputs

Incoming and outgoing video feeds can optionally output video to a local window, as an RTP stream over UDP, to an inter pipe for other feeds to access, to a V4L2 loopback device (virtual camera) or to a shared memory area for another process to read.

This is specified during construction of the video feed type, by passing a VideoOutputFeedComponent object.

For example, to display an outgoing Media Server video feed in a local window:

    PxMedia::VideoOutputFeedAuto localOut;
    auto                         outgoingFeed =
        PxMedia::MediaServerOutgoingVideoFeed::create(mediaSession, props, input, localOut);

To display an outgoing Media Server video feed via RTP/UDP:

    PxMedia::VideoOutputFeedUdp udpOutput;
    udpOutput.host("localhost");
    udpOutput.port(5006);
    PxMedia::X264EncoderFeedComponent encoder;
    encoder.bitrate(5000_kbps);
    udpOutput.encoder(encoder);
    auto outgoingFeed =
        PxMedia::MediaServerOutgoingVideoFeed::create(mediaSession, props, inputVideo, udpOutput);

To output a local video feed to a V4L2 loopback device (Linux only):

    PxMedia::VideoOutputFeedV4Linux2 v4l2Output;
    v4l2Output.device("/dev/video2");

    PxMedia::UtilityVideoLocalFeed::FeedProperties utilProps{"v4l2-output"};
    auto                                           result =
        PxMedia::UtilityVideoLocalFeed::create(context, utilProps, inputVideo, v4l2Output);

Note

V4L2 loopback output requires the v4l2loopback kernel module to be loaded. The specified device (e.g., /dev/video2) must exist and be a valid V4L2 loopback device. Add loopback devices with specific settings using modprobe, for example:

sudo modprobe v4l2loopback exclusive_caps=1,1,1,1 max_buffers=2 devices=4

To disable local output of an outgoing Media Server video feed:

    PxMedia::VideoOutputComponentNull nullOutput;
    auto                              outgoingFeed =
        PxMedia::MediaServerOutgoingVideoFeed::create(mediaSession, props, inputVideo, nullOutput);

Note that the output encoder properties can be set using encoderProperties(). For a list of available encoder properties, see X264EncoderFeedComponent.

To use a hardware encoder like VAAPI (Intel/AMD GPUs) instead of the default X264 software encoder, use encoder():

    // Create a VAAPI hardware encoder for Intel/AMD GPUs
    PxMedia::H264VaapiEncoderComponent vaapiEncoder;
    vaapiEncoder.bitrate(5000_kbps);

    PxMedia::VideoOutputFeedUdp udpOutput;
    udpOutput.host("localhost");
    udpOutput.port(5006);
    udpOutput.encoder(vaapiEncoder);
    auto outgoingFeed =
        PxMedia::MediaServerOutgoingVideoFeed::create(mediaSession, props, inputVideo, udpOutput);

For a list of available VAAPI encoder properties, see H264VaapiEncoderComponent.

To display an incoming Peer video feed in a local window:

    PxMedia::PeerFeed::FeedProperties feedProperties;
    feedProperties.channel = "webcam";
    feedProperties.label   = "peer-auto";
    PxMedia::VideoOutputFeedAuto localOut;
    auto                         remotePeerFeed =
        PxMedia::PeerRemoteVideoFeed::create(peerSession, feedProperties, localOut);

To display an incoming Peer video feed via RTP/UDP:

    PxMedia::PeerFeed::FeedProperties feedProperties;
    feedProperties.channel = "webcam";
    feedProperties.label   = "peer-udp";
    PxMedia::VideoOutputFeedUdp udpOutput;
    udpOutput.host("localhost");
    udpOutput.port(5006);
    PxMedia::X264EncoderFeedComponent encoder;
    encoder.bitrate(5000_kbps);
    udpOutput.encoder(encoder);
    auto remotePeerFeed =
        PxMedia::PeerRemoteVideoFeed::create(peerSession, feedProperties, udpOutput);

2.2.18.1. Inter Pipe Output

To allow another feed to read an outgoing Media Server video feed via an inter pipe:

    PxMedia::VideoOutputFeedInter outputVideo;
    auto                          outgoingFeed =
        PxMedia::MediaServerOutgoingVideoFeed::create(mediaSession, props, input, outputVideo);

When using VideoOutputFeedInter, all calls to makeInput() must be made before the output is used to create the feed. Inputs obtained after the feed has been created will not be connected to the pipeline.

Each VideoInputFeedInter obtained from makeInput() can only be used in a single feed. Likewise, each VideoOutputFeedInter can only be used in a single feed. Violating either constraint is detected and surfaces as a PipelineElementBadProps error when the affected feed is created.

2.2.18.2. Shared Memory Output

VideoOutputFeedSharedMemory publishes raw video to a shared memory area (via GStreamer’s shmsink) for another process to read with a matching VideoInputFeedSharedMemory (see Video Inputs). The two endpoints are paired by a shared control socket path. No encoding is performed; the raw video data is transferred directly, enabling efficient, zero-copy video sharing between processes on the same machine.

    PxMedia::VideoOutputFeedSharedMemory shmOutput;
    shmOutput.socketPath("/tmp/px-shm-video");
    // Pin the pixel format published to shared memory so the reading endpoint, which cannot
    // negotiate caps over the transport, interprets the bytes correctly. This matters in
    // particular when video processing stages are applied to the source.
    shmOutput.videoCapabilities().mediaType(PxMedia::VideoCapabilities::MediaType::VIDEO_XRAW_I420);

    PxMedia::UtilityVideoLocalFeed::FeedProperties utilProps{"shared-memory-writer"};
    auto result = PxMedia::UtilityVideoLocalFeed::create(context, utilProps, inputVideo, shmOutput);

Warning

The shared memory transport carries raw bytes with no caps negotiation. The reading endpoint must be configured with capabilities matching the format produced by this output, otherwise the video will be interpreted incorrectly. An empty socket path surfaces as a PipelineElementBadProps error when the feed is created.

Use videoCapabilities() to pin the capabilities published to shared memory. The pixel format, and optionally the resolution (width/height) and frame rate, can each be pinned; only the properties you set are enforced, so pinning just the pixel format leaves the resolution and frame rate free. Pinning the pixel format is recommended whenever video processing stages are applied, since a stage may otherwise leave the published pixel format or buffer memory layout unspecified, which the reading endpoint cannot interpret. The reading endpoint must be configured with capabilities matching whatever is pinned here.

2.2.18.3. Monitor Output (Encoded Video Preview)

Outgoing video feeds can optionally provide a monitor output that displays the encoded video after the encoder stage. This is useful for previewing what is being transmitted over the network.

The monitor output:

  • Available for Media Server (WebRTC) and Peer (SRT) outgoing video feeds

  • Supports H.264 and VP8 for Media Server (WebRTC) outgoing video feeds

  • Supports H.264 only for Peer (SRT) outgoing video feeds

  • Decodes the video before sending to output component

  • Can output to window, UDP, V4L2, or any other video output component

Warning

Monitor outputs that re-encode the video (e.g., VideoOutputFeedUdp) will produce a transcoded stream (decode → re-encode) rather than the original encoded stream. This may introduce quality loss and increased CPU usage.

To monitor encoded video from a Media Server video feed in a window:

    PxMedia::VideoOutputFeedAuto localOut;    // Pre-encoder output
    PxMedia::VideoOutputFeedAuto monitorOut;  // Post-encoder output (encoded video)

    auto outgoingFeed =
        PxMedia::MediaServerOutgoingVideoFeed::Builder(mediaSession, props, inputVideo)
            .localOutput(localOut)
            .monitorOutput(monitorOut)
            .create();

To monitor encoded video from a Peer video feed in a window:

    PxMedia::PeerFeed::FeedProperties props;
    props.channel = "webcam";
    props.label   = "monitor-peer";
    PxMedia::VideoInputFeedTestPattern inputVideo;
    PxMedia::VideoOutputFeedAuto       localOut;    // Pre-encoder output
    PxMedia::VideoOutputFeedAuto       monitorOut;  // Post-encoder output (encoded video)
    PxMedia::X264EncoderFeedComponent  encoder;

    auto outgoingFeed = PxMedia::PeerLocalVideoFeed::Builder(peerSession, props, inputVideo)
                            .localOutput(localOut)
                            .monitorOutput(monitorOut)
                            .encoder(encoder)
                            .create();