Skip to content

Access the raw frames#63

Merged
Sarah5567 merged 5 commits into
mainfrom
access_the_raw_frames
Oct 19, 2025
Merged

Access the raw frames#63
Sarah5567 merged 5 commits into
mainfrom
access_the_raw_frames

Conversation

@Sarah5567

Copy link
Copy Markdown
Collaborator

Description
This PR adds the ability to access and modify raw frames inside a DeepStream pipeline.
A pad probe is attached after the nvvideoconvert (RGBA conversion) element, allowing direct access to GPU buffers via pyds.get_nvds_buf_surface.

Key Features

  • Extracts raw frames from the pipeline (in RGBA format).
  • Demonstrates custom manipulation using NumPy.
  • Preserves GPU memory integrity using np.copyto to write back modified data.
  • Designed as a minimal DeepStream pipeline (no nvinfer or OSD).
  • Compatible with RTSP input and multifilesink output.

Files Added

  • src/access_raw_frames.py - main implementation.
  • env/arm/pyds-1.1.10-py3-none-linux_aarch64.whl - for installing the pyds library, which is required for the code.
  • docs/access_raw_frames.md - documentation describing mechanism and usage.

closes #57

Sarah5567 and others added 3 commits October 16, 2025 15:00
Co-authored-by: Sarah Gershuni <sarah556726@gmail.com>
Co-authored-by: Chani Orlinski <c9992946@gmail.com>
Co-authored-by: Sarah Gershuni <sarah556726@gmail.com>
Co-authored-by: Chani Orlinski <c9992946@gmail.com>
Co-authored-by: Sarah Gershuni <sarah556726@gmail.com>
Co-authored-by: Chani Orlinski <c9992946@gmail.com>
@Sarah5567 Sarah5567 force-pushed the access_the_raw_frames branch from a95ddda to 5db7977 Compare October 16, 2025 12:00
Comment thread src/access_raw_frames_pipeline.py Outdated
print("Pipeline stopped")

if __name__ == "__main__":
main() No newline at end of file

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a new line.

return Gst.PadProbeReturn.OK

# Retrieve NvBufSurface from GPU memory
surface = pyds.get_nvds_buf_surface(hash(buf), 0)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using hash(buf) to access the surface. It’s unreliable across DeepStream versions and may cause invalid memory access.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

surface = pyds.get_nvds_buf_surface(hash(buf), 0)

# Copy to CPU (RGBA format)
frame = np.array(surface, copy=True, order='C')

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may not return a valid NumPy array — the surface might be a pointer, not the raw frame data.

# frame = (frame * 0.7).astype(np.uint8)

# Copy back to GPU
np.copyto(np.array(surface, copy=False, order='C'), frame)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copying back to GPU may fail if the surface isn’t in matching format (RGBA).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how that works internally, but since we were able to see the output frames manipulated, I suppose that worked properly

elems["nvvideoconvert1"].link(elems["capsfilter"])
sinkpad = elems["streammux"].get_request_pad("sink_0")
srcpad = elems["capsfilter"].get_static_pad("src")
srcpad.link(sinkpad)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

streammux should receive raw video, not post-RGBA capsfilter. This link order may cause performance loss.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that in this case, RGBA conversion before nvstreammux is intentional, since the pad probe requires RGBA frames for CPU-side access and NumPy processing. The small performance cost is acceptable for this workflow.

def on_pad_added(src, new_pad):
sink_pad = elems["depay"].get_static_pad("sink")
if not sink_pad.is_linked():
new_pad.link(sink_pad)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing pad type check — if RTSP includes audio, it’ll try linking it too and fail.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, yes - but here we don't care about audio stream in video


def main():
Gst.init(None)
os.makedirs(OUTPUT_DIR, exist_ok=True)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create the output directory before building the pipeline, otherwise multifilesink may not find it.

Sarah5567 and others added 2 commits October 16, 2025 16:33
Co-authored-by: Sarah Gershuni <sarah556726@gmail.com>
Co-authored-by: Chani Orlinski <c9992946@gmail.com>
Co-authored-by: Sarah Gershuni <sarah556726@gmail.com>
Co-authored-by: Chani Orlinski <c9992946@gmail.com>
@Sarah5567 Sarah5567 merged commit ce8089f into main Oct 19, 2025
1 check failed
lyuzinmaxim added a commit that referenced this pull request Oct 19, 2025
lyuzinmaxim added a commit that referenced this pull request Oct 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Access the raw frames in a deepstream pipeline

3 participants