wip: real coeffs extraction
This commit is contained in:
@@ -195,6 +195,23 @@ if(DAEDALUS_BUILD_TOOLS)
|
|||||||
${DAEDALUS_FFMPEG_PREFIX}/lib/libswresample.a
|
${DAEDALUS_FFMPEG_PREFIX}/lib/libswresample.a
|
||||||
m z pthread)
|
m z pthread)
|
||||||
set(FFMPEG_CFLAGS_OTHER "-DDAEDALUS_HAVE_H264_MB_INSPECT_CB=1")
|
set(FFMPEG_CFLAGS_OTHER "-DDAEDALUS_HAVE_H264_MB_INSPECT_CB=1")
|
||||||
|
|
||||||
|
# PR-A3+ optional: also point at the patched FFmpeg SOURCE TREE
|
||||||
|
# so the CLI can include libavcodec/h264dec.h directly and
|
||||||
|
# dereference H264Context fields (the side-buffer mb_inspect_coeffs
|
||||||
|
# added in marfrit-packages patch 0017, the cur_pic.f for
|
||||||
|
# pre-deblock pixel access, etc.). When set, the internal-header
|
||||||
|
# include codepath is compiled in.
|
||||||
|
set(DAEDALUS_FFMPEG_SRC "" CACHE PATH
|
||||||
|
"Path to patched FFmpeg source tree (= path to FFmpeg/ checkout where build was run; contains config.h + libavcodec/h264dec.h). Empty = h264dec.h includes are disabled.")
|
||||||
|
if(DAEDALUS_FFMPEG_SRC)
|
||||||
|
message(STATUS "daedalus_decode_h264: FFmpeg source at ${DAEDALUS_FFMPEG_SRC}")
|
||||||
|
list(APPEND FFMPEG_INCLUDE_DIRS ${DAEDALUS_FFMPEG_SRC})
|
||||||
|
set(FFMPEG_CFLAGS_OTHER
|
||||||
|
"${FFMPEG_CFLAGS_OTHER} -DDAEDALUS_HAVE_H264_MB_INSPECT_COEFFS=1 -DHAVE_AV_CONFIG_H")
|
||||||
|
# Convert space-separated string to list (CMake idiom for compile flags).
|
||||||
|
separate_arguments(FFMPEG_CFLAGS_OTHER UNIX_COMMAND "${FFMPEG_CFLAGS_OTHER}")
|
||||||
|
endif()
|
||||||
else()
|
else()
|
||||||
pkg_check_modules(FFMPEG REQUIRED libavcodec libavformat libavutil)
|
pkg_check_modules(FFMPEG REQUIRED libavcodec libavformat libavutil)
|
||||||
message(STATUS "daedalus_decode_h264: system FFmpeg (no inspection callback)")
|
message(STATUS "daedalus_decode_h264: system FFmpeg (no inspection callback)")
|
||||||
|
|||||||
+225
-19
@@ -51,14 +51,32 @@
|
|||||||
#include <libavutil/imgutils.h>
|
#include <libavutil/imgutils.h>
|
||||||
|
|
||||||
/* Per-MB inspection callback API — provided by the patched FFmpeg
|
/* Per-MB inspection callback API — provided by the patched FFmpeg
|
||||||
* fork via marfrit-packages 0016. The H264Context struct itself
|
* fork via marfrit-packages patches 0016 + 0017.
|
||||||
* remains internal (declared in libavcodec/h264dec.h which isn't
|
*
|
||||||
* installed), so we only forward-declare it here and use it
|
* When DAEDALUS_HAVE_H264_MB_INSPECT_COEFFS is defined (CMake sets it
|
||||||
* opaquely through the callback signature. Real per-MB state
|
* alongside DAEDALUS_FFMPEG_SRC), we include libavcodec's INTERNAL
|
||||||
* extraction (sl->mb coefficients, mb_type, etc.) will land in
|
* h264dec.h header to dereference H264Context fields — specifically
|
||||||
* PR-A3 alongside an internal-header include path. */
|
* h->mb_inspect_coeffs (the 0017 side buffer holding pre-IDCT-
|
||||||
#ifdef DAEDALUS_HAVE_H264_MB_INSPECT_CB
|
* destruction sl->mb), h->cur_pic.f (pre-deblock reconstructed pixels),
|
||||||
|
* and h->cur_pic.mb_type[mb_xy] for the mb-type gate. The same
|
||||||
|
* configure-time config.h that built the static libavcodec.a is
|
||||||
|
* picked up via -DHAVE_AV_CONFIG_H + -I path; ABI match is automatic.
|
||||||
|
*
|
||||||
|
* When only DAEDALUS_HAVE_H264_MB_INSPECT_CB is defined (no source
|
||||||
|
* tree available — e.g. building against a distro-shipped patched
|
||||||
|
* libavcodec), the H264Context stays opaque and we fall back to
|
||||||
|
* identity-passthrough across all MBs.
|
||||||
|
*
|
||||||
|
* When neither is defined: stock libavcodec, no callback, identity-
|
||||||
|
* passthrough only (PR-A1b behaviour). */
|
||||||
|
#ifdef DAEDALUS_HAVE_H264_MB_INSPECT_COEFFS
|
||||||
|
# include "libavcodec/h264dec.h"
|
||||||
|
# include "libavcodec/h264.h" /* IS_INTRA4x4 / IS_8x8DCT / IS_INTRA_PCM */
|
||||||
|
#elif defined(DAEDALUS_HAVE_H264_MB_INSPECT_CB)
|
||||||
struct H264Context;
|
struct H264Context;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(DAEDALUS_HAVE_H264_MB_INSPECT_CB) || defined(DAEDALUS_HAVE_H264_MB_INSPECT_COEFFS)
|
||||||
typedef void (*ff_h264_mb_inspect_cb)(void *opaque,
|
typedef void (*ff_h264_mb_inspect_cb)(void *opaque,
|
||||||
const struct H264Context *h,
|
const struct H264Context *h,
|
||||||
int mb_x, int mb_y);
|
int mb_x, int mb_y);
|
||||||
@@ -76,35 +94,170 @@ static const char *substrate_str = "auto";
|
|||||||
static int max_frames = -1;
|
static int max_frames = -1;
|
||||||
|
|
||||||
/* Inspection-callback state: per-frame counter + "each MB seen exactly
|
/* Inspection-callback state: per-frame counter + "each MB seen exactly
|
||||||
* once" check. We use a bitmap rather than a raster-order assertion
|
* once" check. Bitmap, not raster-order — libavcodec's MB threading +
|
||||||
* because libavcodec's MB-level threading + multi-slice frames mean
|
* multi-slice frames mean MBs reach the callback out of strict order;
|
||||||
* MBs reach the callback in non-strictly-raster order; the contract
|
* contract is "every MB fires the callback exactly once per frame".
|
||||||
* is "every MB fires the callback exactly once per frame", not "in
|
*
|
||||||
* raster order". Reset at end of each frame. */
|
* When real-coeff extraction is compiled in (PR-A3+), we ALSO maintain
|
||||||
|
* a per-MB capture buffer (real-coeffs path) so the main loop can
|
||||||
|
* drive daedalus_decoder_append_mb with REAL pre-residual P + real
|
||||||
|
* coefficients for MBs that satisfy the gate (Intra_4x4, no 8x8 DCT,
|
||||||
|
* no PCM). Other MBs stay on identity-passthrough. */
|
||||||
#ifdef DAEDALUS_HAVE_H264_MB_INSPECT_CB
|
#ifdef DAEDALUS_HAVE_H264_MB_INSPECT_CB
|
||||||
|
struct mb_capture {
|
||||||
|
int valid; /* 1 = real-coeffs path, 0 = identity passthrough */
|
||||||
|
int16_t coeffs[256]; /* luma, column-major within 4x4, raster block order */
|
||||||
|
uint8_t predicted[256]; /* luma P recovered = pre_deblock - clipped IDCT(C) */
|
||||||
|
};
|
||||||
|
|
||||||
struct inspect_state {
|
struct inspect_state {
|
||||||
int n_cbs_this_frame;
|
int n_cbs_this_frame;
|
||||||
int mb_w, mb_h;
|
int mb_w, mb_h;
|
||||||
uint8_t *seen; /* mb_w * mb_h bitmap */
|
uint8_t *seen; /* mb_w * mb_h bitmap */
|
||||||
int duplicate_mbs; /* same (mb_x, mb_y) seen twice this frame */
|
int duplicate_mbs;
|
||||||
int out_of_bounds; /* (mb_x, mb_y) outside the coded grid */
|
int out_of_bounds;
|
||||||
|
#ifdef DAEDALUS_HAVE_H264_MB_INSPECT_COEFFS
|
||||||
|
struct mb_capture *captures; /* mb_w * mb_h entries */
|
||||||
|
int real_coeffs_mbs; /* count of MBs in real-coeffs path this frame */
|
||||||
|
int skipped_intra16x16;
|
||||||
|
int skipped_8x8dct;
|
||||||
|
int skipped_other;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef DAEDALUS_HAVE_H264_MB_INSPECT_COEFFS
|
||||||
|
/* Zig-zag scan position → column-major-within-4x4 idx.
|
||||||
|
* daedalus convention: block[c*4 + r] = coeff at (row=r, col=c).
|
||||||
|
* H.264 §6.4.3 / fig 6-12 4x4 luma zig-zag scan order. */
|
||||||
|
static const uint8_t zigzag_to_colmajor[16] = {
|
||||||
|
0, 4, 1, 2, 5, 8, 12, 9, 6, 3, 7, 10, 13, 14, 11, 15
|
||||||
|
};
|
||||||
|
|
||||||
|
/* H.264 §6.4.3 4x4 luma block scan within MB (z-scan).
|
||||||
|
* Maps raster-block-idx (sb_y*4+sb_x) → libavcodec sl->mb's z-scan idx.
|
||||||
|
* Z-scan happens to be its own inverse (symmetric mapping). */
|
||||||
|
static const uint8_t raster_to_zscan[16] = {
|
||||||
|
0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15
|
||||||
|
};
|
||||||
|
|
||||||
|
/* H.264 4x4 IDCT — transcribed from daedalus-fourier
|
||||||
|
* tests/test_idct_bitexact.c (which itself mirrors h264_idct4_ref.c).
|
||||||
|
* Outputs row-major 16-element residual; clip + shift happens in
|
||||||
|
* the consumer. */
|
||||||
|
static void h264_idct4_butterfly(const int d[4], int out[4]) {
|
||||||
|
int e = d[0] + d[2];
|
||||||
|
int f = d[0] - d[2];
|
||||||
|
int g = (d[1] >> 1) - d[3];
|
||||||
|
int h = d[1] + (d[3] >> 1);
|
||||||
|
out[0] = e + h;
|
||||||
|
out[1] = f + g;
|
||||||
|
out[2] = f - g;
|
||||||
|
out[3] = e - h;
|
||||||
|
}
|
||||||
|
static void ref_idct4_compute(const int16_t block[16], int out[16]) {
|
||||||
|
/* block COLUMN-MAJOR: block[c*4+r] = coef at (row=r, col=c). */
|
||||||
|
int tmp[4][4];
|
||||||
|
for (int r = 0; r < 4; r++) {
|
||||||
|
int d[4] = { block[0*4+r], block[1*4+r], block[2*4+r], block[3*4+r] };
|
||||||
|
int o[4];
|
||||||
|
h264_idct4_butterfly(d, o);
|
||||||
|
for (int c = 0; c < 4; c++) tmp[r][c] = o[c];
|
||||||
|
}
|
||||||
|
for (int c = 0; c < 4; c++) {
|
||||||
|
int d[4] = { tmp[0][c], tmp[1][c], tmp[2][c], tmp[3][c] };
|
||||||
|
int o[4];
|
||||||
|
h264_idct4_butterfly(d, o);
|
||||||
|
for (int r = 0; r < 4; r++) out[r*4+c] = o[r];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* DAEDALUS_HAVE_H264_MB_INSPECT_COEFFS */
|
||||||
|
|
||||||
static void inspect_cb(void *opaque,
|
static void inspect_cb(void *opaque,
|
||||||
const struct H264Context *h,
|
const struct H264Context *h,
|
||||||
int mb_x, int mb_y)
|
int mb_x, int mb_y)
|
||||||
{
|
{
|
||||||
(void) h;
|
|
||||||
struct inspect_state *st = opaque;
|
struct inspect_state *st = opaque;
|
||||||
|
#ifndef DAEDALUS_HAVE_H264_MB_INSPECT_COEFFS
|
||||||
|
(void) h;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (mb_x < 0 || mb_x >= st->mb_w || mb_y < 0 || mb_y >= st->mb_h) {
|
if (mb_x < 0 || mb_x >= st->mb_w || mb_y < 0 || mb_y >= st->mb_h) {
|
||||||
st->out_of_bounds++;
|
st->out_of_bounds++;
|
||||||
} else {
|
st->n_cbs_this_frame++;
|
||||||
const size_t idx = (size_t) mb_y * st->mb_w + (size_t) mb_x;
|
return;
|
||||||
if (st->seen[idx]) st->duplicate_mbs++;
|
|
||||||
st->seen[idx] = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const size_t idx = (size_t) mb_y * st->mb_w + (size_t) mb_x;
|
||||||
|
if (st->seen[idx]) st->duplicate_mbs++;
|
||||||
|
st->seen[idx] = 1;
|
||||||
st->n_cbs_this_frame++;
|
st->n_cbs_this_frame++;
|
||||||
|
|
||||||
|
#ifdef DAEDALUS_HAVE_H264_MB_INSPECT_COEFFS
|
||||||
|
/* Real-coeffs path: extract per-MB state for daedalus-decoder
|
||||||
|
* IDCT validation on this MB. Gate: only Intra_4x4 + 4x4 transform
|
||||||
|
* + non-PCM is supported in PR-A3b — other MB flavours fall back
|
||||||
|
* to identity-passthrough in the main loop. */
|
||||||
|
struct mb_capture *cap = &st->captures[idx];
|
||||||
|
cap->valid = 0; /* default to passthrough */
|
||||||
|
|
||||||
|
const int mb_xy = mb_y * h->mb_stride + mb_x;
|
||||||
|
const uint32_t mb_type = h->cur_pic.mb_type[mb_xy];
|
||||||
|
|
||||||
|
if (!IS_INTRA4x4(mb_type)) {
|
||||||
|
if (IS_INTRA16x16(mb_type)) st->skipped_intra16x16++;
|
||||||
|
else st->skipped_other++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (IS_8x8DCT(mb_type)) { st->skipped_8x8dct++; return; }
|
||||||
|
if (IS_INTRA_PCM(mb_type)) { st->skipped_other++; return; }
|
||||||
|
|
||||||
|
/* Snapshot luma pre-deblock pixels from cur_pic. */
|
||||||
|
const uint8_t *luma_plane = h->cur_pic.f->data[0];
|
||||||
|
const int luma_stride = h->cur_pic.f->linesize[0];
|
||||||
|
const uint8_t *mb_pixels = luma_plane + (ptrdiff_t) mb_y * 16 * luma_stride
|
||||||
|
+ mb_x * 16;
|
||||||
|
|
||||||
|
/* Coefficients are in sl->mb at end of entropy decode but zeroed by
|
||||||
|
* the time the callback fires (IDCT-add consumed them). Patch 0017
|
||||||
|
* preserves them in h->mb_inspect_coeffs[16 * 48] BEFORE IDCT runs,
|
||||||
|
* so we read from there. */
|
||||||
|
const int16_t *zz_mb = h->mb_inspect_coeffs; /* layout matches sl->mb 8-bit half */
|
||||||
|
|
||||||
|
for (int r_block = 0; r_block < 16; r_block++) {
|
||||||
|
const int z_block = raster_to_zscan[r_block];
|
||||||
|
const int16_t *zz_block = &zz_mb[z_block * 16];
|
||||||
|
|
||||||
|
/* Inverse zig-zag scan → column-major-within-block. */
|
||||||
|
int16_t col[16] = {0};
|
||||||
|
for (int p = 0; p < 16; p++)
|
||||||
|
col[zigzag_to_colmajor[p]] = zz_block[p];
|
||||||
|
|
||||||
|
memcpy(&cap->coeffs[r_block * 16], col, 16 * sizeof(int16_t));
|
||||||
|
|
||||||
|
/* IDCT → row-major 16-int residual. */
|
||||||
|
int idct_row[16];
|
||||||
|
ref_idct4_compute(col, idct_row);
|
||||||
|
|
||||||
|
/* P = clip(pre_deblock - ((IDCT + 32) >> 6)) for each pixel.
|
||||||
|
* Symmetric: daedalus IDCT-add will undo the subtract, including
|
||||||
|
* for saturating cases (where the same shift puts the value back
|
||||||
|
* at the same clip boundary). */
|
||||||
|
const int sb_y = r_block >> 2;
|
||||||
|
const int sb_x = r_block & 3;
|
||||||
|
for (int r = 0; r < 4; r++) {
|
||||||
|
for (int c = 0; c < 4; c++) {
|
||||||
|
const int pre_db = mb_pixels[(sb_y * 4 + r) * luma_stride + sb_x * 4 + c];
|
||||||
|
const int shift = (idct_row[r * 4 + c] + 32) >> 6;
|
||||||
|
int p = pre_db - shift;
|
||||||
|
if (p < 0) p = 0;
|
||||||
|
if (p > 255) p = 255;
|
||||||
|
cap->predicted[(sb_y * 4 + r) * 16 + (sb_x * 4 + c)] = (uint8_t) p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cap->valid = 1;
|
||||||
|
st->real_coeffs_mbs++;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -247,6 +400,17 @@ int main(int argc, char **argv)
|
|||||||
const AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_H264);
|
const AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_H264);
|
||||||
AVCodecContext *avctx = avcodec_alloc_context3(codec);
|
AVCodecContext *avctx = avcodec_alloc_context3(codec);
|
||||||
avcodec_parameters_to_context(avctx, fmt->streams[vstream]->codecpar);
|
avcodec_parameters_to_context(avctx, fmt->streams[vstream]->codecpar);
|
||||||
|
|
||||||
|
#ifdef DAEDALUS_HAVE_H264_MB_INSPECT_COEFFS
|
||||||
|
/* Patch 0017's coefficient side buffer lives in H264Context (single
|
||||||
|
* per-stream); multi-threaded slice decode would race on it. Force
|
||||||
|
* single-thread. Also disable libavcodec's deblock so AVFrame is
|
||||||
|
* pre-deblock and the P-recovery math is exact. */
|
||||||
|
avctx->thread_count = 1;
|
||||||
|
avctx->thread_type = 0;
|
||||||
|
avctx->skip_loop_filter = AVDISCARD_ALL;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (avcodec_open2(avctx, codec, NULL) < 0) {
|
if (avcodec_open2(avctx, codec, NULL) < 0) {
|
||||||
fprintf(stderr, "avcodec_open2 failed\n");
|
fprintf(stderr, "avcodec_open2 failed\n");
|
||||||
avformat_close_input(&fmt); return 2;
|
avformat_close_input(&fmt); return 2;
|
||||||
@@ -280,6 +444,11 @@ int main(int argc, char **argv)
|
|||||||
inspect_st.mb_h = H_round / 16;
|
inspect_st.mb_h = H_round / 16;
|
||||||
inspect_st.seen = calloc(1, (size_t) inspect_st.mb_w * inspect_st.mb_h);
|
inspect_st.seen = calloc(1, (size_t) inspect_st.mb_w * inspect_st.mb_h);
|
||||||
if (!inspect_st.seen) { rc = 1; goto cleanup; }
|
if (!inspect_st.seen) { rc = 1; goto cleanup; }
|
||||||
|
#ifdef DAEDALUS_HAVE_H264_MB_INSPECT_COEFFS
|
||||||
|
inspect_st.captures = calloc((size_t) inspect_st.mb_w * inspect_st.mb_h,
|
||||||
|
sizeof(*inspect_st.captures));
|
||||||
|
if (!inspect_st.captures) { rc = 1; goto cleanup; }
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
ff_h264_set_mb_inspect_cb(avctx, inspect_cb, &inspect_st);
|
ff_h264_set_mb_inspect_cb(avctx, inspect_cb, &inspect_st);
|
||||||
int inspect_total_cbs = 0;
|
int inspect_total_cbs = 0;
|
||||||
@@ -363,7 +532,26 @@ int main(int argc, char **argv)
|
|||||||
struct daedalus_decoder_mb_input mb = {0};
|
struct daedalus_decoder_mb_input mb = {0};
|
||||||
for (int my = 0; my < mb_h; my++) {
|
for (int my = 0; my < mb_h; my++) {
|
||||||
for (int mx = 0; mx < mb_w; mx++) {
|
for (int mx = 0; mx < mb_w; mx++) {
|
||||||
|
/* Default: identity-passthrough — luma from AVFrame,
|
||||||
|
* chroma from AVFrame, coeffs all zero. */
|
||||||
pack_mb_predicted(fr, mx, my, mb_pred);
|
pack_mb_predicted(fr, mx, my, mb_pred);
|
||||||
|
memset(mb_coeffs, 0, sizeof(mb_coeffs));
|
||||||
|
|
||||||
|
#ifdef DAEDALUS_HAVE_H264_MB_INSPECT_COEFFS
|
||||||
|
/* Real-coeffs path: if the callback captured this MB
|
||||||
|
* as Intra_4x4 / 4x4-DCT, override luma predicted
|
||||||
|
* with the recovered P and use the real luma coeffs.
|
||||||
|
* Chroma stays identity-passthrough (PR-A3b scope —
|
||||||
|
* chroma DC Hadamard + 8x8 transform follow-ups). */
|
||||||
|
const int mb_idx = my * mb_w + mx;
|
||||||
|
const struct mb_capture *cap = &inspect_st.captures[mb_idx];
|
||||||
|
if (cap->valid) {
|
||||||
|
memcpy(mb_pred, cap->predicted, 256);
|
||||||
|
for (int i = 0; i < 256; i++)
|
||||||
|
mb_coeffs[i] = cap->coeffs[i];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
mb.mb_x = (uint16_t) mx;
|
mb.mb_x = (uint16_t) mx;
|
||||||
mb.mb_y = (uint16_t) my;
|
mb.mb_y = (uint16_t) my;
|
||||||
mb.transform_8x8 = 0;
|
mb.transform_8x8 = 0;
|
||||||
@@ -424,6 +612,21 @@ int main(int argc, char **argv)
|
|||||||
inspect_st.duplicate_mbs = 0;
|
inspect_st.duplicate_mbs = 0;
|
||||||
inspect_st.out_of_bounds = 0;
|
inspect_st.out_of_bounds = 0;
|
||||||
memset(inspect_st.seen, 0, (size_t) expected);
|
memset(inspect_st.seen, 0, (size_t) expected);
|
||||||
|
|
||||||
|
#ifdef DAEDALUS_HAVE_H264_MB_INSPECT_COEFFS
|
||||||
|
printf(" frame %d: real-coeffs path %d MBs, "
|
||||||
|
"skipped intra16x16=%d 8x8dct=%d other=%d\n",
|
||||||
|
n_frames, inspect_st.real_coeffs_mbs,
|
||||||
|
inspect_st.skipped_intra16x16,
|
||||||
|
inspect_st.skipped_8x8dct,
|
||||||
|
inspect_st.skipped_other);
|
||||||
|
inspect_st.real_coeffs_mbs = 0;
|
||||||
|
inspect_st.skipped_intra16x16 = 0;
|
||||||
|
inspect_st.skipped_8x8dct = 0;
|
||||||
|
inspect_st.skipped_other = 0;
|
||||||
|
memset(inspect_st.captures, 0,
|
||||||
|
(size_t) expected * sizeof(*inspect_st.captures));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
printf(" frame %d: Y diff %zu/%zu UV diff %zu/%zu%s\n",
|
printf(" frame %d: Y diff %zu/%zu UV diff %zu/%zu%s\n",
|
||||||
@@ -478,6 +681,9 @@ cleanup:
|
|||||||
free(out_uv_dadec);free(out_y_dadec);
|
free(out_uv_dadec);free(out_y_dadec);
|
||||||
#ifdef DAEDALUS_HAVE_H264_MB_INSPECT_CB
|
#ifdef DAEDALUS_HAVE_H264_MB_INSPECT_CB
|
||||||
free(inspect_st.seen);
|
free(inspect_st.seen);
|
||||||
|
# ifdef DAEDALUS_HAVE_H264_MB_INSPECT_COEFFS
|
||||||
|
free(inspect_st.captures);
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
if (dec) daedalus_decoder_destroy(dec);
|
if (dec) daedalus_decoder_destroy(dec);
|
||||||
av_frame_free(&fr);
|
av_frame_free(&fr);
|
||||||
|
|||||||
Reference in New Issue
Block a user