# Ogg Demo

## Overview

This sample demonstrates a real-time **Opus-based audio loopback** flow on K230, with **Ogg muxing and demuxing** inserted in the middle of the pipeline. The program captures audio from `AI`, encodes it with `AENC` as Opus, performs Ogg mux and demux entirely in memory, then sends the decoded stream to `ADEC` and finally plays it through `AO`.

- **Ogg muxing**: package Opus frames output by `AENC` into Ogg pages
- **Ogg demuxing**: extract Opus frames from Ogg pages
- **Real-time loopback**: `AI -> AENC -> Ogg mux -> Ogg demux -> ADEC -> AO`
- **Exit method**: the program keeps running until `Ctrl+C`, then triggers signal handling and resource cleanup

## Usage

### Code Location

Sample directory:

```bash
/src/rtsmart/examples/mpp/sample_ogg
```

The current entry file is `main.cpp`, and the built executable is `sample_ogg.elf`.

### Key Parameters

| Parameter | Description | Value |
| --- | --- | --- |
| `SAMPLE_RATE` | audio sample rate | `16000 Hz` |
| `AUDIO_PERSEC_DIV_NUM` | audio frames per second | `25` |
| `MAX_AUDIO_STREAM_SIZE` | intermediate Ogg/Opus buffer size | `1000 bytes` |
| codec format | payload type used by `AENC` and `ADEC` | `Opus` |
| codec channel count | encode and decode channels | `1` |
| sample precision | I2S bit width | `16 bit` |
| AI/AO device ID | default device used by the program | `0` |
| AI/AO/AENC/ADEC channel ID | default channel used by the program | `0` |

### Run Program

After startup, the program initializes `VB`, `AI`, `AO`, `AENC`, `ADEC`, the Ogg muxer, and the Ogg demuxer, then enters the real-time audio processing loop. Press `Ctrl+C` to exit.

```bash
./sample_ogg.elf
```

At startup, the program prints messages similar to:

```text
Starting Ogg audio sample program. Press Ctrl+C to exit.
vb_set_config succeeded
Ogg stream muxer initialized successfully.
```

### Code Flow Description

1. Initialize VB resources
   `audio_sample_vb_init()` calls `kd_mpi_vb_set_config()` and `kd_mpi_vb_init()` to initialize the VB system.
   `audio_data_vb_create_pool()` creates a private VB pool for the intermediate audio stream used as ADEC input.
   The sample uses `kd_mpi_vb_get_block()`, `kd_mpi_vb_handle_to_phyaddr()`, and `kd_mpi_sys_mmap()` to map the physical buffer into user space.
1. Initialize the Ogg components
   `init_ogg_muxer()` configures `kd_ogg_muxer_params` with `16 kHz`, mono, and streaming output mode.
   `init_ogg_demuxer()` creates the Ogg demuxer used to restore Ogg pages back into Opus frames.
1. Configure audio input, output, and codecs
   In `audio_sample_ogg()`, both `AI` and `AO` are configured in I2S mode with the built-in codec.
   `AI` and `AO` both use `16 bit`, `16 kHz`, and `AUDIO_PERSEC_DIV_NUM = 25`.
   The sample creates `AENC` and `ADEC` channels with payload type `K_PT_OPUS`.
1. Build the MPP binding relationships
   `kd_mpi_sys_bind()` binds the `AI` channel to `AENC`.
   `kd_mpi_sys_bind()` binds the `ADEC` channel to `AO`.
1. Perform Ogg muxing and demuxing in memory
   The main loop gets the encoded Opus stream through `kd_mpi_aenc_get_stream()`.
   `do_opus_stream()` first calls `kd_ogg_write_frame_ex()` to package the Opus frame into an Ogg page.
   It then calls `kd_ogg_demuxer_feed_page_ex()` to extract the Opus frame back from that page.
   The extracted Opus data is copied into the preallocated `g_audio_stream` buffer and sent to the decoder through `kd_mpi_adec_send_stream()`.
   After processing, the sample calls `kd_mpi_aenc_release_stream()` to release the encoded stream.
1. Exit on signal and clean up resources
   `main()` registers `SIGINT` and `SIGTERM`. Once a signal is received, `g_running` is set to `false`.
   After the loop exits, the program unbinds `AI/AENC` and `ADEC/AO`, then closes `AI`, `AO`, `AENC`, and `ADEC`.
   `cleanup_resources()` destroys the Ogg muxer and demuxer, releases the VB block, destroys the VB pool, and calls `kd_mpi_vb_exit()`.

### Notes

- This sample does **not** read or write `.ogg` files. All Ogg muxing and demuxing are performed in memory.
- The sample uses device ID `0` and channel ID `0` by default. If you port it to a different audio path, update the code accordingly.
- If audio-device initialization fails, the program prints an error and immediately enters the cleanup path.

```{admonition} Tip
For Ogg processing and audio codec related interfaces, read `sample_ogg/main.cpp` together with the corresponding audio API documentation.
```
