Skip to content

Add audio element removal support with binaural renderer lifecycle management - #32

Open
jingbo-marquis wants to merge 5 commits into
mainfrom
ISSUE-31
Open

Add audio element removal support with binaural renderer lifecycle management#32
jingbo-marquis wants to merge 5 commits into
mainfrom
ISSUE-31

Conversation

@jingbo-marquis

Copy link
Copy Markdown
Contributor
  • Implement oar_remove_audio_element with separate paths for binaural (multi-element) and single-element renderers; binaural renderer is retained after element removal, tied to audio group lifecycle
  • Add OBR LIFO-only element removal via obr_remove_last_audio_element and ck_attribute_remove_element attribute
  • Add remove_element callback to AudioRendererAPI and implement audio_elements_renderer_remove_element with index/offset rebasing
  • Add crash-isolated test framework (test_framework.c/h) with fork-based process isolation
  • Add 5 test scenarios covering single/multiple removal, re-add, and binaural non-LIFO failure cases

Comment thread src/renderer/audio_elements_renderer.c Outdated
/* Notify the underlying renderer library to release per-element DSP
* resources. If the library does not support removal (e.g., OBR only
* supports LIFO), abort the removal so that OAR and library state stay
* consistent. The element remains functional and rendering is unaffected. */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe document this behavior for the oar_remove_audio_element() function in oar.h? So that users know what to expect.

@jingbo-marquis jingbo-marquis Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thank you for the suggestion.
I have moved the relevant content to the comments for the oar_remove_audio_element function in oar.h. Please refer to: 64d7b4a

…nagement

- Implement oar_remove_audio_element with separate paths for binaural
  (multi-element) and single-element renderers; binaural renderer is
  retained after element removal, tied to audio group lifecycle
- Add OBR LIFO-only element removal via obr_remove_last_audio_element
  and ck_attribute_remove_element attribute
- Add remove_element callback to AudioRendererAPI and implement
  audio_elements_renderer_remove_element with index/offset rebasing
- Add crash-isolated test framework (test_framework.c/h) with fork-based
  process isolation
- Add 5 test scenarios covering single/multiple removal, re-add, and
  binaural non-LIFO failure cases

Signed-off-by: Jingbo Hou <jingbo.hou@samsung.com>
Signed-off-by: Jingbo Hou <jingbo.hou@samsung.com>
- Replace raw error numbers with ck_oar_error_* enum constants across all API functions
- Add binaural renderer LIFO removal behavior notes to oar_remove_audio_element

Signed-off-by: Jingbo Hou <jingbo.hou@samsung.com>
- Rename get_channels to get_channel_count and get_element_channels to get_element_channel_count across renderer API
- Add get_element_count interface to return actual element count instead of renderer count
- Free staging buffer on element removal to prevent stale data rendering
- Return ck_oar_error_notsup when remove_element is not implemented
- Update test to expect element count 0 after removing all elements

Signed-off-by: Jingbo Hou <jingbo.hou@samsung.com>
Signed-off-by: Jingbo Hou <jingbo.hou@samsung.com>

@trsonic trsonic left a comment

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.

Approving. I built the branch with CMake (Debug and ASan) and with Bazel, ran the five new test cases plus the five existing example tests, and checked the removal paths for leaks.

What I verified:

  • Issue #31 is fixed. leaks --atExit on each of the five cases (run one per process via the --child N mode) reports 0 leaks / 0 bytes, and the ASan build is clean.
  • Non-LIFO removal is rejected in obr.c before any OAR-side state changes, so a failed removal leaves nothing inconsistent.
  • hash_map_remove runs before vector_remove, which owns the free, so there is no double free of the element context.
  • The renames (get_channels to get_channel_count and the rest) leave no stale references in src/, include/ or tests/.
  • The new @return doc comments in include/oar.h match enum EOarStatus and the actual returns. I spot-checked oar_add_audio_group, oar_add_audio_element, oar_set_metadata_unit_to_process and oar_update_metadata.
  • bazelisk build //tests/examples:test_remove_audio_element succeeds.

Two non-blocking comments inline.

One behaviour I measured that I will file as a separate issue rather than ask for here. audio_elements_renderer_add_element calls lib->open() whenever ctx->index == 0. Before this PR that could only happen once per renderer; now that a binaural group can be drained to zero elements, adding the next element re-enters _open(), which does if (ctx->renderer) _close(ctx); and creates a fresh OBR handle. head_tracking_enabled is re-propagated explicitly, but the head rotation cached in oar->head_rotation is not. Rendering the same mono sine through a binaural group with head tracking on and a 90 degree yaw set:

A = yaw set, no removal
B = yaw set, then remove-all and re-add
C = no rotation ever set

sum of absolute differences over the 256-sample stereo frame:
|A - B| = 122.792226    |B - C| = 0.000000    |A - C| = 122.792226

B comes out bit-identical to C. A host that streams rotation every frame recovers on the next update, so the exposure is limited to a host that enables head tracking and then sets a single static orientation.

add_test(NAME test_object_based_rendering COMMAND test_object_based_rendering)
add_test(NAME test_metadata_unit_processing COMMAND test_metadata_unit_processing)

add_test(NAME test_remove_audio_element COMMAND test_remove_audio_element)

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 entry is inert as things stand. Nothing in the tree calls enable_testing(), so ctest -N in a configured build tree reports Total Tests: 0, and .github/workflows/ci-cmake.yml runs a hardcoded list of four binaries rather than ctest. test_remove_audio_element therefore never runs in the CMake CI job. The Bazel job does pick up the new cc_test, so the test is not entirely uncovered.

Either add the binary to the smoke-test list in ci-cmake.yml (test_metadata_unit_processing has the same gap already), or add enable_testing() at the root and switch that CI step to ctest.


/* Parent: wait for the child and interpret the exit status. */
int status = 0;
waitpid(pid, &status, 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.

The return value is discarded. If waitpid returns -1 (EINTR, or any other error) status stays 0, so WIFEXITED(0) is true and WEXITSTATUS(0) is 0, and the runner prints PASSED for a test it never reaped.

  int r;
  while ((r = waitpid(pid, &status, 0)) < 0 && errno == EINTR) {
  }
  if (r < 0) {
    perror("waitpid");
    return TEST_FAIL;
  }

errno.h is already included. Minor, in the same function: num_tests is unused on the POSIX path.

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.

Renderer not deleted when an audio element is removed

3 participants