Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
ab80baf
Initial plan
Copilot Dec 7, 2025
681e244
Add multi-branch latency tracking support to latency_tracer
Copilot Dec 7, 2025
cb2d7a8
Update documentation for multi-branch latency tracer support
Copilot Dec 7, 2025
f2c107a
Complete multi-branch latency tracer implementation
Copilot Dec 7, 2025
f443c5f
Add test examples script for multi-branch latency tracer
Copilot Dec 7, 2025
a7e5a9a
Add developer README for multi-branch latency tracer implementation
Copilot Dec 7, 2025
a6e3077
Remove CodeQL symlink and update gitignore
Copilot Dec 7, 2025
ed73c66
Merge pull request #1 from xwu2intel/copilot/extend-latency-tracer-mu…
xwu2intel Dec 7, 2025
e38817d
Initial plan
Copilot Dec 8, 2025
7a72b51
Initial plan
Copilot Dec 8, 2025
1674dd3
Add source_name and sink_name fields to latency tracer output
Copilot Dec 8, 2025
c977f1c
Fix code formatting with clang-format
Copilot Dec 8, 2025
c5fe793
Remove logging overhead in add_latency_meta function
Copilot Dec 8, 2025
ca1a9af
Improve comment explaining non-writable buffer behavior
Copilot Dec 8, 2025
71a2a09
Refine comment wording for clarity
Copilot Dec 8, 2025
cc5a995
Merge pull request #2 from xwu2intel/copilot/add-source-sink-names-to…
xwu2intel Dec 8, 2025
32b555b
Merge branch 'copilot/extend-latency-tracer-multiple-sources' into co…
xwu2intel Dec 8, 2025
1728215
Merge pull request #3 from xwu2intel/copilot/remove-logging-overhead
xwu2intel Dec 8, 2025
14bdecd
Merge pull request #4 from xwu2intel/copilot/extend-latency-tracer-mu…
xwu2intel Dec 8, 2025
e3de908
Initial plan
Copilot Dec 8, 2025
72907b3
Implement topology analysis for source element identification
Copilot Dec 8, 2025
14b3ee8
Update documentation to reflect topology-based source tracking
Copilot Dec 8, 2025
43bc971
Address code review feedback: improve iterator handling and remove un…
Copilot Dec 8, 2025
cd627d9
Add better logging for debugging: element names in errors and trace f…
Copilot Dec 8, 2025
7ff889b
Merge pull request #5 from xwu2intel/copilot/fix-source-element-ident…
xwu2intel Dec 8, 2025
4b9a7eb
Initial plan
Copilot Dec 8, 2025
0ee4acc
Remove duplicate backward-compatibility logging in do_push_buffer_pre
Copilot Dec 8, 2025
6e1709b
Update README to reflect per-branch frame counting and no duplicates
Copilot Dec 8, 2025
b94aa75
Merge pull request #6 from xwu2intel/copilot/fix-frame-count-and-logging
xwu2intel Dec 8, 2025
1cd990c
Initial plan
Copilot Dec 8, 2025
c7b011c
Remove backward compatibility code and dead fields from latency tracer
Copilot Dec 8, 2025
3199efb
Merge pull request #7 from xwu2intel/copilot/remove-backward-compatib…
xwu2intel Dec 8, 2025
75c709e
Initial plan
Copilot Dec 8, 2025
8811f6f
Implement is_sink_element helper to detect appsink
Copilot Dec 8, 2025
9c8b39d
Add NULL check for defensive programming
Copilot Dec 8, 2025
4a77fff
Add clarifying comments about GStreamer sink naming convention
Copilot Dec 8, 2025
5b3d947
Initial plan
Copilot Dec 8, 2025
c89cfb6
Merge pull request #8 from xwu2intel/copilot/fix-appsink-sink-detection
xwu2intel Dec 8, 2025
837b6d1
Add is_sink_element() and is_source_element() helper functions
Copilot Dec 8, 2025
573a74d
Use is_sink_element() in do_push_buffer_pre for consistency
Copilot Dec 8, 2025
b8393fd
Add null checks and proper iterator error handling to helper functions
Copilot Dec 8, 2025
d14d809
Improve iterator error handling in pad checks for both helper functions
Copilot Dec 8, 2025
6d7ed95
Initial plan
Copilot Dec 8, 2025
68ae7c4
Fix variable shadowing and memory leaks in iterator handling
Copilot Dec 8, 2025
be6e115
Remove factory name pattern checking from source/sink detection
Copilot Dec 8, 2025
b0c16a6
Merge branch 'latencytracermultibranches' into copilot/add-is-source-…
xwu2intel Dec 8, 2025
b3150bf
Merge pull request #9 from xwu2intel/copilot/add-is-source-element-he…
xwu2intel Dec 8, 2025
630a944
Fix iterator state handling in source/sink detection
Copilot Dec 8, 2025
bb2989e
Merge branch 'latencytracermultibranches' into copilot/remove-factory…
xwu2intel Dec 8, 2025
08b19d0
Merge pull request #10 from xwu2intel/copilot/remove-factory-name-pat…
xwu2intel Dec 8, 2025
26cac4d
remove duplicated functions
xwu2intel Dec 8, 2025
10b1352
Initial plan
Copilot Dec 8, 2025
12eda1c
Fix per-branch statistics initialization in BranchStats
Copilot Dec 8, 2025
eee903b
Fix ElementStats initialization and improve consistency
Copilot Dec 8, 2025
fab5bc5
Merge pull request #11 from xwu2intel/copilot/verify-branch-stats-cal…
xwu2intel Dec 8, 2025
3cb377b
Initial plan
Copilot Dec 8, 2025
60ad2b2
Implement core latency tracer optimizations
Copilot Dec 8, 2025
7a1037d
Fix topology cache and add defensive fallback for element type cache
Copilot Dec 8, 2025
a7b2902
Merge pull request #19 from xwu2intel/copilot/optimize-latency-tracer…
xwu2intel Dec 8, 2025
fa69a8a
fix build error
xwu2intel Dec 8, 2025
0bafeba
Initial plan
Copilot Dec 8, 2025
31a6e70
Apply performance optimizations A, C, D, E to latency_tracer
Copilot Dec 8, 2025
92e5732
Improve hash function for better distribution
Copilot Dec 8, 2025
66cdc75
Merge pull request #20 from xwu2intel/copilot/apply-final-performance…
xwu2intel Dec 8, 2025
eb1093f
Initial plan
Copilot Dec 8, 2025
f2b428e
Fix: Revert to std::map to fix compilation error in latency_tracer.cpp
Copilot Dec 8, 2025
f3a67c6
Fix: Remove reserve() call for std::map (not supported)
Copilot Dec 8, 2025
4df8cf9
Fix: Clarify comment about pointer-based key optimization
Copilot Dec 8, 2025
5895f3e
Merge pull request #22 from xwu2intel/copilot/fix-latencyfix2-compile…
xwu2intel Dec 8, 2025
8b52a4b
Initial plan
Copilot Dec 8, 2025
b154838
Fix BranchStats copy error by using try_emplace() for in-place constr…
Copilot Dec 8, 2025
c5a1a88
Merge pull request #23 from xwu2intel/copilot/fix-branchstats-copy-issue
xwu2intel Dec 8, 2025
39c908f
Initial plan
Copilot Dec 8, 2025
99d03c6
Remove unused variables and fix typos in latency_tracer.cpp
Copilot Dec 8, 2025
882ccd8
Merge pull request #24 from xwu2intel/copilot/remove-unused-variables
xwu2intel Dec 8, 2025
7860d15
Initial plan
Copilot Dec 8, 2025
7b921e2
Fix element type detection to use pad templates instead of actual pads
Copilot Dec 8, 2025
0549358
Apply clang-format to latency_tracer.cpp
Copilot Dec 8, 2025
4deb921
Fix misleading comment about element classification
Copilot Dec 8, 2025
00aa9eb
Add early exit optimization for element type detection
Copilot Dec 8, 2025
9488eb0
Fix early exit logic to be symmetric and correct
Copilot Dec 8, 2025
c358345
Remove unused variables from element type detection
Copilot Dec 8, 2025
efd1a3f
Merge pull request #26 from xwu2intel/copilot/fix-decodebin-sink-caching
xwu2intel Dec 8, 2025
8934dd2
Merge branch 'main' into latencyfix2
xwu2intel Dec 9, 2025
b7effa7
Initial plan
Copilot Dec 10, 2025
94990df
Implement multiple pipeline support in latency tracer
Copilot Dec 10, 2025
83aa10b
Add test scripts and documentation for multiple pipeline support
Copilot Dec 10, 2025
e2ae941
Address code review feedback: add null check and improve comments
Copilot Dec 10, 2025
da113be
Add detailed comments explaining compatibility constraints
Copilot Dec 10, 2025
d7af275
Refine comments and change warning to debug level
Copilot Dec 10, 2025
0c85975
Add comprehensive PR summary document
Copilot Dec 10, 2025
b5f09fd
Merge pull request #27 from xwu2intel/copilot/support-multiple-pipelines
xwu2intel Dec 10, 2025
e128219
print out pipeline name in the logs
xwu2intel Dec 10, 2025
2d5169d
Merge branch 'main' into latencyfix2
xwu2intel Dec 10, 2025
718d36d
map -> unordered_map
xwu2intel Dec 10, 2025
cc13679
remove deprecated
xwu2intel Dec 10, 2025
7c0fd50
Merge branch 'latencyfix2' of https://github.com/xwu2intel/edge-ai-li…
xwu2intel Dec 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
tools/visual-pipeline-and-platform-evaluation-tool/.venv/*
tools/visual-pipeline-and-platform-evaluation-tool/intel/*
tools/visual-pipeline-and-platform-evaluation-tool/models/*
_codeql_detected_source_root
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
# Multiple Pipeline Support Enhancement for Latency Tracer

## Overview

This enhancement enables the latency tracer to track **multiple GStreamer pipelines** (both sequential and concurrent), removing the previous single-pipeline limitation.

## Problem Statement

Previously, the latency tracer could only track one pipeline at a time:
- ❌ Only the first pipeline was tracked
- ❌ Subsequent pipelines triggered a warning
- ❌ Elements from other pipelines were ignored

## Changes Made

### 1. **BranchKey Enhancement** (Line ~138-160)
Changed from `pair<source, sink>` to `tuple<source, sink, pipeline>` to separate statistics per pipeline.

```cpp
// OLD: Only source and sink
using BranchKey = pair<GstElement*, GstElement*>;

// NEW: Include pipeline to separate stats
using BranchKey = tuple<GstElement*, GstElement*, GstElement*>;
```

Added `BranchKeyHash` struct for proper tuple hashing and updated `create_branch_key()` helper.

### 2. **Pipeline Detection** (Line ~495-530)
Replaced `is_parent_pipeline()` with `is_in_pipeline()` to check if element is in **any** pipeline.

```cpp
// OLD: Check if element is in specific pipeline (lt->pipeline)
static bool is_parent_pipeline(LatencyTracer *lt, GstElement *elem)

// NEW: Check if element is in any pipeline
static bool is_in_pipeline(LatencyTracer *lt, GstElement *elem)
```

Added `find_pipeline_for_element()` helper to identify which pipeline an element belongs to.

### 3. **Element Tracking** (Line ~760-815)
Updated `on_element_change_state_post()` to discover elements in **all** pipelines transitioning to PLAYING state.

```cpp
// OLD: Only track lt->pipeline
if (GST_STATE_TRANSITION_NEXT(change) == GST_STATE_PLAYING && elem == lt->pipeline)

// NEW: Track all pipelines
if (GST_STATE_TRANSITION_NEXT(change) == GST_STATE_PLAYING && GST_IS_PIPELINE(elem))
```

### 4. **Pipeline Registration** (Line ~815-824)
Removed single-pipeline restriction in `on_element_new()`.

```cpp
// OLD: Store first pipeline only, warn about subsequent ones
if (!lt->pipeline)
lt->pipeline = elem;
else
GST_WARNING_OBJECT(lt, "pipeline already exists...");

// NEW: Log all pipelines for tracking
GST_INFO("Latency tracer will track pipeline: %s", GST_ELEMENT_NAME(elem));
```

### 5. **Data Structure Optimization**
Changed from `map` to `unordered_map` with custom hash for better performance with tuple keys.

## Benefits

✅ **Sequential pipelines**: Each pipeline tracked separately
✅ **Concurrent pipelines**: Multiple pipelines running simultaneously
✅ **Per-pipeline stats**: Stats separated by pipeline using tuple key
✅ **Backward compatible**: Single pipeline case still works
✅ **No API changes**: Same `GST_TRACERS` environment variable

## Usage

### Sequential Pipelines (Python Example)

```python
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst
import os

os.environ['GST_TRACERS'] = 'latency_tracer(flags=pipeline)'
Gst.init(None)

# Pipeline 1
pipe1 = Gst.parse_launch("videotestsrc num-buffers=100 ! fakesink")
pipe1.set_state(Gst.State.PLAYING)
pipe1.get_state(Gst.CLOCK_TIME_NONE)
pipe1.set_state(Gst.State.NULL)

# Pipeline 2 - Now tracked! ✓
pipe2 = Gst.parse_launch("videotestsrc num-buffers=100 ! fakesink")
pipe2.set_state(Gst.State.PLAYING)
pipe2.get_state(Gst.CLOCK_TIME_NONE)
pipe2.set_state(Gst.State.NULL)
```

### Concurrent Pipelines (gst-launch Example)

```bash
# Terminal 1
GST_TRACERS="latency_tracer(flags=pipeline)" \
gst-launch-1.0 videotestsrc num-buffers=100 ! fakesink &

# Terminal 2
GST_TRACERS="latency_tracer(flags=pipeline)" \
gst-launch-1.0 videotestsrc num-buffers=100 ! fakesink &
```

## Expected Output

**With sequential pipelines**:
```
# Pipeline 1 running
source_name=videotestsrc0, sink_name=fakesink0, frame_num=100...

# Pipeline 2 running (now tracked!)
source_name=videotestsrc0, sink_name=fakesink0, frame_num=100...
```

**With concurrent pipelines**:
```
# Both tracked simultaneously
source_name=videotestsrc0, sink_name=fakesink0, frame_num=50... (pipeline1)
source_name=videotestsrc0, sink_name=fakesink0, frame_num=50... (pipeline2)
```

## Testing

Two test scripts are provided:

### 1. Sequential Pipeline Test
```bash
cd libraries/dl-streamer/docs/source/dev_guide
GST_TRACERS="latency_tracer(flags=pipeline)" \
GST_DEBUG="latency_tracer:5" \
python3 test_sequential_pipelines.py
```

### 2. Concurrent Pipeline Test
```bash
cd libraries/dl-streamer/docs/source/dev_guide
GST_TRACERS="latency_tracer(flags=pipeline)" \
GST_DEBUG="latency_tracer:5" \
python3 test_concurrent_pipelines.py
```

## Files Modified

- **latency_tracer.cpp**: All implementation changes
- **latency_tracer.h**: No changes (maintains binary compatibility)

## Technical Details

### BranchKey Hash Function
Uses boost::hash_combine pattern for efficient tuple hashing:
```cpp
h1 ^= h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2);
h1 ^= h3 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2);
```

### Pipeline Discovery
The new `find_pipeline_for_element()` walks up the element hierarchy to find the top-level pipeline:
```cpp
GstObject *parent = GST_OBJECT_CAST(elem);
while (parent) {
if (GST_IS_PIPELINE(parent)) {
return GST_ELEMENT_CAST(parent);
}
parent = GST_OBJECT_PARENT(parent);
}
```

## Backward Compatibility

- The `lt->pipeline` field is retained in the struct for binary compatibility
- Single pipeline tracking still works as before
- No changes to the public API or environment variables
- No changes to the header file

## Performance Considerations

- Uses `unordered_map` with custom hash for O(1) average lookup
- Pipeline pointer is cached with branch key to avoid repeated lookups
- Element type cache still provides O(1) type checking
- Topology cache still provides O(1) source lookup

## Future Enhancements

Possible future improvements:
- Add pipeline name to log output for better identification
- Add per-pipeline statistics summary on shutdown
- Add configuration option to limit tracked pipelines
169 changes: 169 additions & 0 deletions libraries/dl-streamer/docs/source/dev_guide/PR_SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
# Pull Request Summary: Multiple Pipeline Support for Latency Tracer

## Overview

This PR implements comprehensive support for tracking **multiple GStreamer pipelines** (both sequential and concurrent) in the DL Streamer latency tracer, removing the previous single-pipeline limitation.

## Problem Statement

Previously, the latency tracer could only track one pipeline at a time:
- ❌ Only the first pipeline was tracked
- ❌ Subsequent pipelines triggered warnings: "pipeline already exists, multiple pipelines may not give right result"
- ❌ Elements from other pipelines were ignored

This was particularly problematic for Python applications using `Gst.parse_launch()` to create multiple pipelines sequentially, and for applications running concurrent pipelines.

## Solution

### Core Changes (latency_tracer.cpp)

1. **Enhanced BranchKey Structure**
- Changed from `pair<source, sink>` to `tuple<source, sink, pipeline>`
- Enables proper statistics separation per pipeline
- Added custom hash function (`BranchKeyHash`) using golden ratio conjugate constant

2. **Pipeline Tracking Logic**
- Replaced `is_parent_pipeline()` with `is_in_pipeline()` - checks if element is in **any** pipeline
- Added `find_pipeline_for_element()` - identifies which pipeline an element belongs to
- Modified `on_element_new()` - removes single-pipeline restriction, tracks all pipelines
- Updated `on_element_change_state_post()` - discovers elements in all pipelines transitioning to PLAYING

3. **Data Structure Optimization**
- Changed from `map` to `unordered_map` for O(1) average lookup performance
- Custom hash function for efficient tuple hashing

4. **Safety Improvements**
- Added null check for pipeline pointer with debug logging
- Gracefully handles edge cases where elements aren't in pipelines

### Backward Compatibility

- ✅ No changes to `latency_tracer.h` - maintains binary interface
- ✅ Struct layout unchanged - preserves ABI stability
- ✅ `lt->pipeline` field retained (unused but kept for compatibility)
- ✅ GStreamer callback signatures maintained (unused params documented)
- ✅ Single pipeline case continues to work as before

## Testing

### Test Scripts Created

1. **test_sequential_pipelines.py**
- Tests sequential pipeline creation and tracking
- Validates that both pipe1 and pipe2 are tracked
- Ensures no warning messages about multiple pipelines

2. **test_concurrent_pipelines.py**
- Tests concurrent pipeline execution
- Uses threading to run pipelines simultaneously
- Validates separate statistics for each pipeline

### Usage

```bash
# Sequential test
GST_TRACERS="latency_tracer(flags=pipeline)" \
GST_DEBUG="latency_tracer:5" \
python3 test_sequential_pipelines.py

# Concurrent test
GST_TRACERS="latency_tracer(flags=pipeline)" \
GST_DEBUG="latency_tracer:5" \
python3 test_concurrent_pipelines.py
```

## Documentation

Created **MULTIPLE_PIPELINE_SUPPORT.md** with:
- Detailed explanation of all changes
- Usage examples (Python and gst-launch)
- Technical implementation details
- Expected output examples
- Performance considerations

## Code Quality

### Code Review
- ✅ 4 rounds of code review feedback addressed
- ✅ Added comprehensive comments explaining design decisions
- ✅ Documented GStreamer callback signature constraints
- ✅ Explained ABI/binary compatibility requirements

### Security
- ✅ Passed CodeQL security scan (0 alerts)
- ✅ Proper null pointer checks
- ✅ Safe error handling

## Benefits

1. **Functionality**
- ✅ Sequential pipelines tracked separately
- ✅ Concurrent pipelines supported
- ✅ Per-pipeline statistics properly isolated

2. **Compatibility**
- ✅ No API changes (same environment variables)
- ✅ ABI stable (shared library compatible)
- ✅ Single pipeline case unchanged

3. **Performance**
- ✅ O(1) average lookup with unordered_map
- ✅ Efficient tuple hashing
- ✅ No performance degradation for single pipeline

## Technical Highlights

### Hash Function
Uses boost::hash_combine pattern with golden ratio conjugate (φ⁻¹ * 2³²):
```cpp
h1 ^= h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2);
h1 ^= h3 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2);
```

### Pipeline Discovery
Walks up element hierarchy to find pipeline ancestor:
```cpp
GstObject *parent = GST_OBJECT_CAST(elem);
while (parent) {
if (GST_IS_PIPELINE(parent)) {
return GST_ELEMENT_CAST(parent);
}
parent = GST_OBJECT_PARENT(parent);
}
```

## Files Modified

| File | Lines Changed | Description |
|------|--------------|-------------|
| `latency_tracer.cpp` | +87 -21 | Core implementation |
| `test_sequential_pipelines.py` | +105 | Sequential test |
| `test_concurrent_pipelines.py` | +159 | Concurrent test |
| `MULTIPLE_PIPELINE_SUPPORT.md` | +199 | Documentation |
| **Total** | **+550 -21** | |

## Testing Recommendations

1. **Build and install** the updated latency tracer plugin
2. **Run provided test scripts** to validate basic functionality
3. **Test with real applications** that use multiple pipelines
4. **Verify backward compatibility** with existing single-pipeline applications

## Migration Notes

No migration required! The change is fully backward compatible:
- Existing code using single pipeline continues to work
- Same environment variables and configuration
- No code changes needed in applications

## Future Enhancements

Possible future improvements (out of scope for this PR):
- Add pipeline name to log output for better identification
- Add per-pipeline statistics summary on shutdown
- Add configuration option to limit number of tracked pipelines
- Add metrics for cross-pipeline comparisons

## Conclusion

This PR successfully implements comprehensive multiple pipeline support in the latency tracer while maintaining full backward compatibility, passing all code reviews and security scans, and providing thorough testing and documentation.
Loading
Loading