iter2 step2: GLib/GStreamer compat shim, build succeeds
Vendored gsth265parser + nalutils + gstbitreader + gstbytereader (the
Step 1 commit) compile cleanly against libc + libv4l2 only after
adding 1 compat translation unit + 5 stub headers, no edits to the
vendored .c/.h files themselves.
src/h265_parser/gst_compat.{h,c} — new files (MIT, original work):
- GLib type aliases (gboolean, gchar, gint*, guint*, gsize, gpointer)
- Memory helpers (g_malloc/g_free as #define free, g_memdup2 inline)
- Asserts as no-op + parser-return-code-propagation
- All GST_DEBUG/INFO/WARNING/ERROR/LOG/FIXME as no-ops (the parser
is heavy on debug logging; we compile it all out)
- GArray implementation (~100 LOC, just enough for gsth265parser.c's
24 call sites)
- GList full struct with .data/.next/.prev so callers compile;
list-manipulation functions abort() — dead code paths only
- Byte-order read/write macros (GST_READ_UINT8/16/24/32/64_LE/BE,
GST_WRITE_UINT8/16/24/32_BE) — aarch64 LE inlines
- g_once_init_enter/leave as simple gate
- G_MAXUINT*, G_MAXINT*, G_MINxxx, G_GNUC_* attribute macros, etc.
- Opaque GstBuffer/GstMemory/GstMapInfo + abort-stub functions for
the encoder-side SEI-insertion paths the libva backend never invokes
- gst_util_ceil_log2 real impl (used by slice-header parser; dead
for our SPS-only call path but cheaper to implement than stub)
src/h265_parser/gst/{gst.h,base/base-prelude.h,base/gstbitwriter.h,
codecparsers/codecparsers-prelude.h,glib-compat-private.h} — 5 new
stub headers (MIT). All include gst_compat.h. gstbitwriter.h adds
abort-stub functions for the bit-writer API (used by nalutils.c's NAL
emulation-prevention encoder path — dead code for the parse-only
libva backend).
src/meson.build — added the 5 new .c source files and 10 new .h
headers; added include_directories('h265_parser') to the include path
so the vendored files' '#include <gst/base/...>' style references
resolve to the stub headers + actual vendored files in the local
tree.
Build verified: ninja -C build produces v4l2_request_drv_video.so
(682 KB, up from 485 KB pre-vendor — the +200 KB is the vendored
parser code). nm shows gst_h265_parse_sps, gst_h265_parse_sps_ext,
gst_h265_parser_identify_nalu, and the other functions we need for
Step 4 are present in the binary.
Two #warning messages from gsth265parser.h about API stability are
upstream-intentional and harmless ('The H.265 parsing library is
unstable API and may change in future').
This commit completes Step 2 of ampere-kernel-decoders iter2 Phase 6.
Backend remains functionally identical to pre-iter2 — the new code
compiles + links but is not yet called from h265_set_controls (that's
Step 4). Existing 5 codecs continue to work as before.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* gst_compat.c — GArray implementation for the vendored GStreamer parser.
|
||||
*
|
||||
* Scope: minimal subset of GArray API exercised by gsth265parser.c
|
||||
* (g_array_new, g_array_sized_new, g_array_append_vals + the
|
||||
* g_array_append_val macro, g_array_index macro, g_array_set_size,
|
||||
* g_array_set_clear_func, g_array_free, g_array_unref).
|
||||
*
|
||||
* Non-thread-safe (matches GArray's documented semantics — GArray is
|
||||
* not thread-safe in upstream GLib either, callers must serialize).
|
||||
*
|
||||
* License: MIT (matches backend's COPYING.MIT).
|
||||
*/
|
||||
|
||||
#include "gst_compat.h"
|
||||
|
||||
/* ===== internal helpers ===== */
|
||||
|
||||
static gboolean
|
||||
garray_grow(GArray *array, guint new_capacity)
|
||||
{
|
||||
if (new_capacity <= array->capacity)
|
||||
return TRUE;
|
||||
|
||||
/* round up to next power of two for amortized O(1) growth */
|
||||
guint cap = array->capacity > 0 ? array->capacity : 4;
|
||||
while (cap < new_capacity)
|
||||
cap *= 2;
|
||||
|
||||
char *new_data = realloc(array->data, (size_t)cap * array->element_size);
|
||||
if (new_data == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (array->clear) {
|
||||
memset(new_data + (size_t)array->capacity * array->element_size, 0,
|
||||
(size_t)(cap - array->capacity) * array->element_size);
|
||||
}
|
||||
|
||||
array->data = new_data;
|
||||
array->capacity = cap;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* ===== public API ===== */
|
||||
|
||||
GArray *
|
||||
g_array_sized_new(gboolean zero_terminated, gboolean clear,
|
||||
guint element_size, guint reserved_size)
|
||||
{
|
||||
/* zero_terminated is GLib-specific (appends a zero-element sentinel
|
||||
* for trailing-NULL semantics). The vendored parser does not use it;
|
||||
* we ignore the flag. */
|
||||
(void)zero_terminated;
|
||||
|
||||
GArray *a = calloc(1, sizeof(GArray));
|
||||
if (a == NULL)
|
||||
return NULL;
|
||||
|
||||
a->element_size = element_size;
|
||||
a->clear = clear;
|
||||
|
||||
if (reserved_size > 0) {
|
||||
if (!garray_grow(a, reserved_size)) {
|
||||
free(a);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
GArray *
|
||||
g_array_new(gboolean zero_terminated, gboolean clear, guint element_size)
|
||||
{
|
||||
return g_array_sized_new(zero_terminated, clear, element_size, 0);
|
||||
}
|
||||
|
||||
GArray *
|
||||
g_array_set_size(GArray *array, guint length)
|
||||
{
|
||||
if (length > array->capacity) {
|
||||
if (!garray_grow(array, length))
|
||||
return array;
|
||||
}
|
||||
|
||||
if (array->clear_func != NULL && length < array->len) {
|
||||
for (guint i = length; i < array->len; i++)
|
||||
array->clear_func(array->data + (size_t)i * array->element_size);
|
||||
}
|
||||
if (array->clear && length > array->len) {
|
||||
memset(array->data + (size_t)array->len * array->element_size, 0,
|
||||
(size_t)(length - array->len) * array->element_size);
|
||||
}
|
||||
array->len = length;
|
||||
return array;
|
||||
}
|
||||
|
||||
GArray *
|
||||
g_array_append_vals(GArray *array, gconstpointer data, guint len)
|
||||
{
|
||||
if (len == 0)
|
||||
return array;
|
||||
|
||||
if (!garray_grow(array, array->len + len))
|
||||
return array;
|
||||
|
||||
memcpy(array->data + (size_t)array->len * array->element_size,
|
||||
data, (size_t)len * array->element_size);
|
||||
array->len += len;
|
||||
return array;
|
||||
}
|
||||
|
||||
void
|
||||
g_array_set_clear_func(GArray *array, void (*clear_func)(gpointer))
|
||||
{
|
||||
array->clear_func = clear_func;
|
||||
}
|
||||
|
||||
gchar *
|
||||
g_array_free(GArray *array, gboolean free_segment)
|
||||
{
|
||||
if (array == NULL)
|
||||
return NULL;
|
||||
|
||||
if (array->clear_func != NULL) {
|
||||
for (guint i = 0; i < array->len; i++)
|
||||
array->clear_func(array->data + (size_t)i * array->element_size);
|
||||
}
|
||||
|
||||
gchar *data = NULL;
|
||||
if (free_segment) {
|
||||
free(array->data);
|
||||
} else {
|
||||
data = array->data;
|
||||
}
|
||||
free(array);
|
||||
return data;
|
||||
}
|
||||
|
||||
GArray *
|
||||
g_array_unref(GArray *array)
|
||||
{
|
||||
/* simplified to free; the backend never sub-references shared GArrays */
|
||||
g_array_free(array, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
Reference in New Issue
Block a user