wip: callback wiring
This commit is contained in:
+25
-1
@@ -175,7 +175,31 @@ target_compile_options(bench_flush_frame PRIVATE -O2)
|
||||
# so the standard ctest build doesn't pull in FFmpeg as a hard dep.
|
||||
option(DAEDALUS_BUILD_TOOLS "Build daedalus-decoder CLI tools (requires libavcodec)" OFF)
|
||||
if(DAEDALUS_BUILD_TOOLS)
|
||||
pkg_check_modules(FFMPEG REQUIRED libavcodec libavformat libavutil)
|
||||
# Optional path to a private FFmpeg install carrying the per-MB
|
||||
# inspection callback (marfrit-packages patch 0016). When set,
|
||||
# the CLI links against it instead of the system FFmpeg and the
|
||||
# inspection-callback code path is compiled in.
|
||||
set(DAEDALUS_FFMPEG_PREFIX "" CACHE PATH
|
||||
"Path to a patched FFmpeg install (with 0016 mb-inspect-callback) for daedalus_decode_h264. Empty = use system pkg-config FFmpeg.")
|
||||
|
||||
if(DAEDALUS_FFMPEG_PREFIX)
|
||||
message(STATUS "daedalus_decode_h264: patched FFmpeg at ${DAEDALUS_FFMPEG_PREFIX}")
|
||||
set(FFMPEG_INCLUDE_DIRS ${DAEDALUS_FFMPEG_PREFIX}/include)
|
||||
set(FFMPEG_LIBRARY_DIRS ${DAEDALUS_FFMPEG_PREFIX}/lib)
|
||||
# Patched libavcodec is built static (no shared libs in the private prefix).
|
||||
# System pull-ins are still needed for libav* dependencies.
|
||||
set(FFMPEG_LIBRARIES
|
||||
${DAEDALUS_FFMPEG_PREFIX}/lib/libavformat.a
|
||||
${DAEDALUS_FFMPEG_PREFIX}/lib/libavcodec.a
|
||||
${DAEDALUS_FFMPEG_PREFIX}/lib/libavutil.a
|
||||
${DAEDALUS_FFMPEG_PREFIX}/lib/libswresample.a
|
||||
m z pthread)
|
||||
set(FFMPEG_CFLAGS_OTHER "-DDAEDALUS_HAVE_H264_MB_INSPECT_CB=1")
|
||||
else()
|
||||
pkg_check_modules(FFMPEG REQUIRED libavcodec libavformat libavutil)
|
||||
message(STATUS "daedalus_decode_h264: system FFmpeg (no inspection callback)")
|
||||
endif()
|
||||
|
||||
add_executable(daedalus_decode_h264 tools/daedalus_decode_h264.c)
|
||||
target_link_libraries(daedalus_decode_h264
|
||||
PRIVATE daedalus_decoder ${FFMPEG_LIBRARIES})
|
||||
|
||||
@@ -50,6 +50,22 @@
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavutil/imgutils.h>
|
||||
|
||||
/* Per-MB inspection callback API — provided by the patched FFmpeg
|
||||
* fork via marfrit-packages 0016. The H264Context struct itself
|
||||
* remains internal (declared in libavcodec/h264dec.h which isn't
|
||||
* installed), so we only forward-declare it here and use it
|
||||
* opaquely through the callback signature. Real per-MB state
|
||||
* extraction (sl->mb coefficients, mb_type, etc.) will land in
|
||||
* PR-A3 alongside an internal-header include path. */
|
||||
#ifdef DAEDALUS_HAVE_H264_MB_INSPECT_CB
|
||||
struct H264Context;
|
||||
typedef void (*ff_h264_mb_inspect_cb)(void *opaque,
|
||||
const struct H264Context *h,
|
||||
int mb_x, int mb_y);
|
||||
void ff_h264_set_mb_inspect_cb(AVCodecContext *avctx,
|
||||
ff_h264_mb_inspect_cb cb, void *opaque);
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -59,6 +75,37 @@
|
||||
static const char *substrate_str = "auto";
|
||||
static int max_frames = -1;
|
||||
|
||||
/* Inspection-callback state: per-frame counter + raster-order check.
|
||||
* Reset at end of each frame by the main loop. */
|
||||
#ifdef DAEDALUS_HAVE_H264_MB_INSPECT_CB
|
||||
struct inspect_state {
|
||||
int n_cbs_this_frame;
|
||||
int expected_mb_w;
|
||||
int raster_violations;
|
||||
int last_mb_x, last_mb_y; /* for raster-order detection */
|
||||
};
|
||||
|
||||
static void inspect_cb(void *opaque,
|
||||
const struct H264Context *h,
|
||||
int mb_x, int mb_y)
|
||||
{
|
||||
(void) h;
|
||||
struct inspect_state *st = opaque;
|
||||
|
||||
/* Raster order check: each subsequent (mb_x, mb_y) should be the
|
||||
* raster successor of the previous one within the frame. */
|
||||
if (st->n_cbs_this_frame > 0) {
|
||||
int expected_x = (st->last_mb_x + 1) % st->expected_mb_w;
|
||||
int expected_y = st->last_mb_y + (st->last_mb_x + 1 == st->expected_mb_w ? 1 : 0);
|
||||
if (mb_x != expected_x || mb_y != expected_y)
|
||||
st->raster_violations++;
|
||||
}
|
||||
st->last_mb_x = mb_x;
|
||||
st->last_mb_y = mb_y;
|
||||
st->n_cbs_this_frame++;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Extract one MB's predicted-samples block from a YUV420P AVFrame
|
||||
* (stock libavcodec) and pack it into the 384-byte mb_input.predicted
|
||||
* layout: 16x16 luma raster, then 8x8 Cb raster, then 8x8 Cr raster.
|
||||
@@ -206,6 +253,13 @@ int main(int argc, char **argv)
|
||||
AVPacket *pkt = av_packet_alloc();
|
||||
AVFrame *fr = av_frame_alloc();
|
||||
|
||||
#ifdef DAEDALUS_HAVE_H264_MB_INSPECT_CB
|
||||
struct inspect_state inspect_st = {0};
|
||||
ff_h264_set_mb_inspect_cb(avctx, inspect_cb, &inspect_st);
|
||||
int inspect_total_cbs = 0;
|
||||
int inspect_total_violations = 0;
|
||||
#endif
|
||||
|
||||
/* ---- Create daedalus_decoder. Coded width/height come from
|
||||
* the bitstream's SPS via libavcodec (after the first packet
|
||||
* is decoded — defer creation until then). ---- */
|
||||
@@ -269,6 +323,12 @@ int main(int argc, char **argv)
|
||||
}
|
||||
printf("daedalus_decode_h264: %dx%d, substrate=%s\n",
|
||||
W, H, substrate_str);
|
||||
#ifdef DAEDALUS_HAVE_H264_MB_INSPECT_CB
|
||||
inspect_st.expected_mb_w = W / 16;
|
||||
printf(" inspection callback: ACTIVE (patched libavcodec)\n");
|
||||
#else
|
||||
printf(" inspection callback: not built in (stock libavcodec)\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Pack each MB's predicted samples from the AVFrame.
|
||||
@@ -320,6 +380,24 @@ int main(int argc, char **argv)
|
||||
if (out_uv_dadec[i] != out_uv_ref[i]) uv_diffs++;
|
||||
total_y_diffs += y_diffs;
|
||||
total_uv_diffs += uv_diffs;
|
||||
#ifdef DAEDALUS_HAVE_H264_MB_INSPECT_CB
|
||||
{
|
||||
const int expected = mb_w * mb_h;
|
||||
if (inspect_st.n_cbs_this_frame != expected) {
|
||||
fprintf(stderr,
|
||||
" frame %d: callback fired %d times, expected %d (mb_w*mb_h)\n",
|
||||
n_frames, inspect_st.n_cbs_this_frame, expected);
|
||||
rc = 4; /* treat as bit-exact failure */
|
||||
}
|
||||
inspect_total_cbs += inspect_st.n_cbs_this_frame;
|
||||
inspect_total_violations += inspect_st.raster_violations;
|
||||
/* Reset for next frame. */
|
||||
inspect_st.n_cbs_this_frame = 0;
|
||||
inspect_st.raster_violations = 0;
|
||||
inspect_st.last_mb_x = 0;
|
||||
inspect_st.last_mb_y = 0;
|
||||
}
|
||||
#endif
|
||||
printf(" frame %d: Y diff %zu/%zu UV diff %zu/%zu%s\n",
|
||||
n_frames, y_diffs, y_size, uv_diffs, uv_size,
|
||||
(y_diffs || uv_diffs) ? " ***" : "");
|
||||
@@ -348,11 +426,20 @@ int main(int argc, char **argv)
|
||||
drained:
|
||||
printf("\n%d frames decoded; total Y diff %zu, UV diff %zu\n",
|
||||
n_frames, total_y_diffs, total_uv_diffs);
|
||||
if (total_y_diffs || total_uv_diffs) {
|
||||
#ifdef DAEDALUS_HAVE_H264_MB_INSPECT_CB
|
||||
printf("inspection callback: %d total invocations, %d raster-order violations\n",
|
||||
inspect_total_cbs, inspect_total_violations);
|
||||
if (inspect_total_violations) rc = 4;
|
||||
#endif
|
||||
if (rc == 0 && (total_y_diffs || total_uv_diffs)) {
|
||||
printf("FAIL: daedalus-decoder output does NOT match libavcodec reference byte-for-byte\n");
|
||||
rc = 4;
|
||||
} else {
|
||||
} else if (rc == 0) {
|
||||
printf("PASS: byte-exact identity-passthrough across %d frames\n", n_frames);
|
||||
} else {
|
||||
printf("FAIL: %s\n",
|
||||
(total_y_diffs || total_uv_diffs) ? "byte-exact comparison failed"
|
||||
: "inspection callback invariants violated");
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
Reference in New Issue
Block a user