Skip to content

Commit 1d0ecce

Browse files
xaionaro@dx.centerxaionaro@dx.center
authored andcommitted
docs: update llms.txt and README.md to use idiomatic APIs
Remove all capi/ fallback patterns now that hwbuf.Allocate, buf.Lock, buf.Describe, hwbuf.RecvHandleFromUnixSocket, codec.DequeueInputBuffer, codec.DequeueOutputBuffer, and media.BufferInfo are in the idiomatic layer. Update the "Idiomatic vs capi" sections, buffer processing loop, allocate-lock-unlock lifecycle, and IPC sharing examples.
1 parent 14ddfda commit 1d0ecce

File tree

2 files changed

+56
-63
lines changed

2 files changed

+56
-63
lines changed

README.md

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,22 @@ All three libraries talk to the same Android system services, but through differ
7676

7777
Always import the **idiomatic top-level packages** (`github.com/AndroidGoLab/ndk/{module}`) in your application code. These provide Go-friendly types with proper lifecycle management (`Close()`, `defer`), typed error handling, and method receivers.
7878

79-
The `capi/` packages (`github.com/AndroidGoLab/ndk/capi/{module}`) are the raw CGo bindings generated in Stage 2 of the pipeline. They mirror the C API directly — C-style function names, `unsafe.Pointer` parameters, raw integer return codes. **They are intended for power users** who need access to NDK functions not yet wrapped by the idiomatic layer. A few functions (e.g., `AHardwareBuffer_allocate`, `AHardwareBuffer_lock`, `AMediaCodec_dequeueInputBuffer`) are not yet exposed idiomatically and require a `capi/` import as a temporary fallback.
80-
81-
When using `capi/` functions, wrap the resulting C pointers in idiomatic types as soon as possible:
79+
The `capi/` packages (`github.com/AndroidGoLab/ndk/capi/{module}`) are the raw CGo bindings generated in Stage 2 of the pipeline. They mirror the C API directly — C-style function names, `unsafe.Pointer` parameters, raw integer return codes. **They are intended for power users** who need access to NDK functions not yet wrapped by the idiomatic layer. All commonly used functions — including `hwbuf.Allocate`, `buf.Lock`, `codec.DequeueInputBuffer`, and `codec.DequeueOutputBuffer` — are available in the idiomatic layer.
8280

8381
```go
84-
import capihw "github.com/AndroidGoLab/ndk/capi/hardwarebuffer"
82+
import "github.com/AndroidGoLab/ndk/hwbuf"
8583

86-
// Advanced: allocate via capi, then wrap in idiomatic type
87-
var rawBuf *capihw.AHardwareBuffer
88-
capihw.AHardwareBuffer_allocate(&desc, &rawBuf)
89-
buf := hwbuf.NewBufferFromPointer(unsafe.Pointer(rawBuf))
90-
defer buf.Close() // use idiomatic lifecycle from here on
84+
// Allocate a hardware buffer using the idiomatic API
85+
desc := hwbuf.Desc{
86+
Width: 1920, Height: 1080, Layers: 1,
87+
Format: uint32(hwbuf.R8g8b8a8Unorm),
88+
Usage: uint64(hwbuf.CpuWriteOften | hwbuf.GpuSampledImage),
89+
}
90+
buf, err := hwbuf.Allocate(&desc)
91+
if err != nil {
92+
log.Fatal(err)
93+
}
94+
defer buf.Close()
9195
```
9296

9397
## Examples

llms.txt

Lines changed: 43 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
## Idiomatic vs capi Packages
66

7-
Always import the idiomatic top-level packages (`github.com/AndroidGoLab/ndk/{module}`) — not the `capi/` packages. The `capi/` layer is a raw CGo binding with C-style names and unsafe types; it is intended only for power users who need NDK functions not yet wrapped by the idiomatic layer. A few functions (e.g., `AMediaCodec_dequeueInputBuffer`, `AHardwareBuffer_allocate`, `AHardwareBuffer_lock`) are not yet exposed idiomatically and require a `capi/` import as a temporary fallback. These cases are marked "**Advanced (capi)**" below.
7+
Always import the idiomatic top-level packages (`github.com/AndroidGoLab/ndk/{module}`) — not the `capi/` packages. The `capi/` layer is a raw CGo binding with C-style names and unsafe types; it is intended only for power users who need NDK functions not yet wrapped by the idiomatic layer. All commonly used functions — including `hwbuf.Allocate`, `buf.Lock`, `codec.DequeueInputBuffer`, `codec.DequeueOutputBuffer`, and `hwbuf.RecvHandleFromUnixSocket` — are available in the idiomatic layer.
88

99
## Resource Lifecycle and Memory Management
1010

@@ -624,23 +624,17 @@ Format keys are passed as strings to `SetInt32`/`SetString`/`SetFloat`/`SetInt64
624624

625625
### Buffer Processing Loop
626626

627-
The idiomatic `media` package provides `GetInputBuffer`, `QueueInputBuffer`, `GetOutputBuffer`, `ReleaseOutputBuffer`, and all constants (`media.AMEDIACODEC_INFO_*`, `media.AMEDIACODEC_BUFFER_FLAG_*`). The `DequeueInputBuffer` and `DequeueOutputBuffer` functions are not yet in the idiomatic layer and require a `capi/media` import (see **Advanced** note below).
628-
629-
The dequeue functions (`DequeueInputBuffer`, `DequeueOutputBuffer`) are not yet in the idiomatic layer and require a `capi/media` import. All other buffer operations use the idiomatic `media` package.
627+
The idiomatic `media` package provides all buffer processing functions: `DequeueInputBuffer`, `DequeueOutputBuffer`, `GetInputBuffer`, `QueueInputBuffer`, `GetOutputBuffer`, `ReleaseOutputBuffer`, and all constants (`media.AMEDIACODEC_INFO_*`, `media.AMEDIACODEC_BUFFER_FLAG_*`). The `media.BufferInfo` value struct is used with `DequeueOutputBuffer`.
630628

631629
```go
632630
import (
633631
"unsafe"
634632
"github.com/AndroidGoLab/ndk/media"
635-
capimedia "github.com/AndroidGoLab/ndk/capi/media" // needed for dequeue (not yet idiomatic)
636633
)
637634

638-
// Get the raw capi pointer for dequeue calls
639-
rawCodec := (*capimedia.AMediaCodec)(codec.Pointer())
640-
641635
for {
642-
// 1. Dequeue input buffer (capi — not yet in idiomatic layer)
643-
idx := capimedia.AMediaCodec_dequeueInputBuffer(rawCodec, timeoutUs)
636+
// 1. Dequeue input buffer
637+
idx := codec.DequeueInputBuffer(timeoutUs)
644638
if idx < 0 { continue } // no buffer available yet
645639

646640
// 2. Fill with data (NAL units for video, PCM for audio)
@@ -649,25 +643,25 @@ for {
649643
data := unsafe.Slice(buf, bufSize)
650644
n := copy(data, inputFrame)
651645

652-
// 3. Queue for processing (idiomatic)
646+
// 3. Queue for processing
653647
codec.QueueInputBuffer(uint64(idx), 0, uint64(n), presentationTimeUs, 0)
654648
// End of stream: pass uint32(media.AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM)
655649

656-
// 4. Dequeue output buffer (capi — not yet in idiomatic layer)
657-
var info capimedia.AMediaCodecBufferInfo
658-
outIdx := capimedia.AMediaCodec_dequeueOutputBuffer(rawCodec, &info, timeoutUs)
650+
// 4. Dequeue output buffer with BufferInfo
651+
var info media.BufferInfo
652+
outIdx := codec.DequeueOutputBuffer(&info, timeoutUs)
659653
if outIdx == int64(media.AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
660654
continue // output format changed, query new format
661655
}
662656
if outIdx < 0 { continue }
663657

664-
// 5. Consume output (idiomatic)
658+
// 5. Consume output — info.Offset, info.Size, info.PresentationTimeUs, info.Flags
665659
var outSize uint64
666660
outBuf := codec.GetOutputBuffer(uint64(outIdx), &outSize)
667661
outData := unsafe.Slice(outBuf, outSize)
668662
processOutput(outData)
669663

670-
// 6. Release back to codec (idiomatic; render=true to send to surface)
664+
// 6. Release back to codec (render=true to send to surface)
671665
codec.ReleaseOutputBuffer(uint64(outIdx), false)
672666
}
673667
```
@@ -1117,62 +1111,58 @@ Wraps the NDK `AHardwareBuffer` API for GPU/CPU-shared buffers. Lifecycle: Descr
11171111

11181112
### Idiomatic Buffer Usage
11191113

1120-
The idiomatic `hwbuf` package provides the `Buffer` type with `Acquire`, `Unlock`, `LockPlanes`, `SendHandleToUnixSocket`, `GetID`, and `Close` methods, plus all format and usage constants.
1114+
The idiomatic `hwbuf` package provides the full hardware buffer API: `Allocate`, `Lock`, `Describe`, `Acquire`, `Unlock`, `LockPlanes`, `SendHandleToUnixSocket`, `RecvHandleFromUnixSocket`, `IsSupported`, `GetID`, and `Close`, plus all format and usage constants. The `hwbuf.Desc` value struct has exported fields (Width, Height, Layers, Format, Usage, Stride, Rfu0, Rfu1) using raw uint32/uint64 types for layout compatibility.
11211115

11221116
```go
11231117
import "github.com/AndroidGoLab/ndk/hwbuf"
11241118

1125-
// Once you have a Buffer (from another API or via capi allocation below):
1126-
buf.Acquire() // increment ref count for sharing
1127-
buf.Unlock(nil) // release CPU mapping (nil = synchronous)
1119+
// Allocate and lifecycle
1120+
buf, err := hwbuf.Allocate(&desc) // allocate a new hardware buffer
1121+
buf.Describe() // get buffer description (*hwbuf.Desc)
1122+
buf.Lock(usage, fence, rect) // lock for CPU access (returns unsafe.Pointer)
1123+
buf.Acquire() // increment ref count for sharing
1124+
buf.Unlock(nil) // release CPU mapping (nil = synchronous)
11281125
buf.LockPlanes(usage, fence, rect, outPlanes) // multi-plane lock (YUV)
11291126
buf.SendHandleToUnixSocket(socketFd) // IPC sharing
1130-
buf.GetID(&id) // get unique buffer ID
1131-
buf.Close() // decrement ref count, free when zero
1127+
hwbuf.RecvHandleFromUnixSocket(socketFd) // IPC receive
1128+
hwbuf.IsSupported(&desc) // check if config is supported
1129+
buf.GetID(&id) // get unique buffer ID
1130+
buf.Close() // decrement ref count, free when zero
11321131
```
11331132

1134-
### Advanced (capi): Allocate-Lock-Unlock Lifecycle
1133+
### Allocate-Lock-Unlock Lifecycle
11351134

1136-
`AHardwareBuffer_allocate` and `AHardwareBuffer_lock` are not yet in the idiomatic layer and require the `capi/hardwarebuffer` package. Once allocated, wrap with `hwbuf.NewBufferFromPointer` for idiomatic usage.
1135+
The idiomatic `hwbuf` package provides `hwbuf.Desc` (a value struct with exported fields), `hwbuf.Allocate`, and `buf.Lock` for the full allocate-lock-unlock lifecycle. No `capi/` import is needed.
11371136

11381137
```go
11391138
import (
11401139
"unsafe"
11411140
"github.com/AndroidGoLab/ndk/hwbuf"
1142-
capihw "github.com/AndroidGoLab/ndk/capi/hardwarebuffer"
11431141
)
11441142

1145-
// 1. Describe: fill the buffer descriptor (capi struct)
1146-
desc := capihw.AHardwareBuffer_Desc{
1143+
// 1. Describe: fill the buffer descriptor (idiomatic value struct)
1144+
// Fields use raw uint32/uint64 for layout compatibility; cast enum constants.
1145+
desc := hwbuf.Desc{
11471146
Width: 1920,
11481147
Height: 1080,
11491148
Layers: 1,
1150-
Format: uint32(hwbuf.R8g8b8a8Unorm), // idiomatic constant
1151-
Usage: uint64(hwbuf.CpuWriteOften | hwbuf.GpuSampledImage), // idiomatic constants
1149+
Format: uint32(hwbuf.R8g8b8a8Unorm),
1150+
Usage: uint64(hwbuf.CpuWriteOften | hwbuf.GpuSampledImage),
11521151
}
11531152

1154-
// 2. Allocate (capi — wraps AHardwareBuffer_allocate)
1155-
var rawBuf *capihw.AHardwareBuffer
1156-
rc := capihw.AHardwareBuffer_allocate(&desc, &rawBuf)
1157-
if rc != 0 {
1158-
log.Fatalf("AHardwareBuffer_allocate failed: %d", rc)
1153+
// 2. Allocate — returns an idiomatic *hwbuf.Buffer directly
1154+
buf, err := hwbuf.Allocate(&desc)
1155+
if err != nil {
1156+
log.Fatalf("hwbuf.Allocate failed: %v", err)
11591157
}
1160-
// Wrap in idiomatic Buffer for lifecycle management
1161-
buf := hwbuf.NewBufferFromPointer(unsafe.Pointer(rawBuf))
11621158
defer buf.Close() // decrements ref count, frees when zero
11631159

1164-
// 3. Lock for CPU access (capi — wraps AHardwareBuffer_lock)
1160+
// 3. Lock for CPU access
11651161
// usage must be a subset of allocation usage flags.
11661162
// fence=-1 means no fence; rect=nil means full buffer.
1167-
var pixelPtr unsafe.Pointer
1168-
rc = capihw.AHardwareBuffer_lock(rawBuf,
1169-
uint64(hwbuf.CpuWriteOften), // CPU write access
1170-
-1, // fence fd (-1 = none)
1171-
nil, // rect (nil = full buffer)
1172-
&pixelPtr,
1173-
)
1174-
if rc != 0 {
1175-
log.Fatalf("AHardwareBuffer_lock failed: %d", rc)
1163+
pixelPtr, err := buf.Lock(uint64(hwbuf.CpuWriteOften), -1, nil)
1164+
if err != nil {
1165+
log.Fatalf("buf.Lock failed: %v", err)
11761166
}
11771167

11781168
// 4. Access: read/write pixel data via the mapped pointer
@@ -1188,7 +1178,7 @@ for y := 0; y < 1080; y++ {
11881178
}
11891179
}
11901180

1191-
// 5. Unlock via idiomatic method (nil fence = synchronous)
1181+
// 5. Unlock (nil fence = synchronous)
11921182
if err := buf.Unlock(nil); err != nil {
11931183
log.Fatalf("unlock: %v", err)
11941184
}
@@ -1234,15 +1224,14 @@ hwbuf.CpuWriteOften | hwbuf.VideoEncode
12341224
### IPC: Sharing Between Processes
12351225

12361226
```go
1237-
// Sender process (idiomatic):
1227+
// Sender process:
12381228
buf.SendHandleToUnixSocket(socketFd)
12391229

1240-
// Receiver process (capi — not yet in idiomatic layer):
1241-
import capihw "github.com/AndroidGoLab/ndk/capi/hardwarebuffer"
1242-
1243-
var recvBuf *capihw.AHardwareBuffer
1244-
capihw.AHardwareBuffer_recvHandleFromUnixSocket(socketFd, &recvBuf)
1245-
received := hwbuf.NewBufferFromPointer(unsafe.Pointer(recvBuf))
1230+
// Receiver process:
1231+
received, err := hwbuf.RecvHandleFromUnixSocket(socketFd)
1232+
if err != nil {
1233+
log.Fatalf("recv handle: %v", err)
1234+
}
12461235
defer received.Close()
12471236
```
12481237

0 commit comments

Comments
 (0)