mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 19:51:51 +09:00
optimised motion search
This commit is contained in:
@@ -1,63 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Created by Claude on 2025-08-17.
|
||||
# Build script for TSVM Enhanced Video (TEV) encoder
|
||||
|
||||
set -e
|
||||
|
||||
echo "Building TSVM Enhanced Video (TEV) Encoder..."
|
||||
|
||||
# Check for required dependencies
|
||||
echo "Checking dependencies..."
|
||||
|
||||
# Check for zstd development library
|
||||
if ! pkg-config --exists libzstd; then
|
||||
echo "Error: libzstd development library not found"
|
||||
echo "Please install it with one of these commands:"
|
||||
echo " Ubuntu/Debian: sudo apt install libzstd-dev"
|
||||
echo " CentOS/RHEL: sudo yum install libzstd-devel"
|
||||
echo " openSUSE: sudo zypper install libzstd-devel"
|
||||
echo " macOS: brew install zstd"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for zlib development library
|
||||
if ! pkg-config --exists zlib; then
|
||||
echo "Error: zlib development library not found"
|
||||
echo "Please install it with one of these commands:"
|
||||
echo " Ubuntu/Debian: sudo apt install zlib1g-dev"
|
||||
echo " CentOS/RHEL: sudo yum install zlib-devel"
|
||||
echo " openSUSE: sudo zypper install zlib-devel"
|
||||
echo " macOS: brew install zlib"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for FFmpeg (required for video processing)
|
||||
if ! command -v ffmpeg &> /dev/null; then
|
||||
echo "Warning: FFmpeg not found. It's required for video input processing."
|
||||
echo "Please install FFmpeg:"
|
||||
echo " Ubuntu/Debian: sudo apt install ffmpeg"
|
||||
echo " CentOS/RHEL: sudo yum install ffmpeg"
|
||||
echo " openSUSE: sudo zypper install ffmpeg"
|
||||
echo " macOS: brew install ffmpeg"
|
||||
fi
|
||||
|
||||
echo "Dependencies OK."
|
||||
|
||||
# Build the encoder
|
||||
echo "Compiling encoder..."
|
||||
make clean
|
||||
make
|
||||
|
||||
if [ -f "encoder_tev" ]; then
|
||||
echo "✓ Build successful!"
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
echo " ./encoder_tev input.mp4 -o output.tev"
|
||||
echo " ./encoder_tev --help"
|
||||
echo ""
|
||||
echo "To install system-wide:"
|
||||
echo " sudo make install"
|
||||
else
|
||||
echo "✗ Build failed!"
|
||||
exit 1
|
||||
fi
|
||||
@@ -407,7 +407,7 @@ static void dct_8x8(float *input, float *output) {
|
||||
dct_table_8[v][y];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
output[u * 8 + v] = 0.25f * cu * cv * sum;
|
||||
}
|
||||
}
|
||||
@@ -502,43 +502,61 @@ static void estimate_motion(tev_encoder_t *enc, int block_x, int block_y,
|
||||
int start_x = block_x * 16;
|
||||
int start_y = block_y * 16;
|
||||
|
||||
// Search in range [-16, +16] pixels
|
||||
for (int mv_y = -MAX_MOTION_SEARCH; mv_y <= MAX_MOTION_SEARCH; mv_y++) {
|
||||
for (int mv_x = -MAX_MOTION_SEARCH; mv_x <= MAX_MOTION_SEARCH; mv_x++) {
|
||||
int ref_x = start_x - mv_x; // Motion estimation: where did current block come FROM?
|
||||
int ref_y = start_y - mv_y;
|
||||
|
||||
// Diamond search pattern (much faster than full search)
|
||||
static const int diamond_x[] = {0, -1, 1, 0, 0, -2, 2, 0, 0};
|
||||
static const int diamond_y[] = {0, 0, 0, -1, 1, 0, 0, -2, 2};
|
||||
|
||||
int center_x = 0, center_y = 0;
|
||||
int step_size = 4; // Start with larger steps
|
||||
|
||||
while (step_size >= 1) {
|
||||
int improved = 0;
|
||||
|
||||
for (int i = 0; i < 9; i++) {
|
||||
int mv_x = center_x + diamond_x[i] * step_size;
|
||||
int mv_y = center_y + diamond_y[i] * step_size;
|
||||
|
||||
// Check bounds
|
||||
if (ref_x < 0 || ref_y < 0 ||
|
||||
if (mv_x < -MAX_MOTION_SEARCH || mv_x > MAX_MOTION_SEARCH ||
|
||||
mv_y < -MAX_MOTION_SEARCH || mv_y > MAX_MOTION_SEARCH) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int ref_x = start_x - mv_x;
|
||||
int ref_y = start_y - mv_y;
|
||||
|
||||
if (ref_x < 0 || ref_y < 0 ||
|
||||
ref_x + 16 > enc->width || ref_y + 16 > enc->height) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calculate SAD for 16x16 block
|
||||
|
||||
// Fast SAD using integer luma approximation
|
||||
int sad = 0;
|
||||
for (int dy = 0; dy < 16; dy++) {
|
||||
for (int dx = 0; dx < 16; dx++) {
|
||||
int cur_offset = ((start_y + dy) * enc->width + (start_x + dx)) * 3;
|
||||
int ref_offset = ((ref_y + dy) * enc->width + (ref_x + dx)) * 3;
|
||||
|
||||
// Compare luminance using YCoCg-R luma equation
|
||||
int cur_luma = (enc->current_rgb[cur_offset] +
|
||||
2 * enc->current_rgb[cur_offset + 1] +
|
||||
enc->current_rgb[cur_offset + 2]) / 4;
|
||||
int ref_luma = (enc->previous_rgb[ref_offset] +
|
||||
2 * enc->previous_rgb[ref_offset + 1] +
|
||||
enc->previous_rgb[ref_offset + 2]) / 4;
|
||||
|
||||
for (int dy = 0; dy < 16; dy += 2) { // Sample every 2nd row for speed
|
||||
uint8_t *cur_row = &enc->current_rgb[((start_y + dy) * enc->width + start_x) * 3];
|
||||
uint8_t *ref_row = &enc->previous_rgb[((ref_y + dy) * enc->width + ref_x) * 3];
|
||||
|
||||
for (int dx = 0; dx < 16; dx += 2) { // Sample every 2nd pixel
|
||||
// Fast luma approximation: (R + 2*G + B) >> 2
|
||||
int cur_luma = (cur_row[dx*3] + (cur_row[dx*3+1] << 1) + cur_row[dx*3+2]) >> 2;
|
||||
int ref_luma = (ref_row[dx*3] + (ref_row[dx*3+1] << 1) + ref_row[dx*3+2]) >> 2;
|
||||
sad += abs(cur_luma - ref_luma);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (sad < best_sad) {
|
||||
best_sad = sad;
|
||||
*best_mv_x = mv_x;
|
||||
*best_mv_y = mv_y;
|
||||
center_x = mv_x;
|
||||
center_y = mv_y;
|
||||
improved = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!improved) {
|
||||
step_size >>= 1; // Reduce step size
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user