diff --git a/video_encoder/include/tav_encoder_lib.h b/video_encoder/include/tav_encoder_lib.h index bcb4a34..1ec11e9 100644 --- a/video_encoder/include/tav_encoder_lib.h +++ b/video_encoder/include/tav_encoder_lib.h @@ -75,7 +75,7 @@ typedef struct { // === Advanced Options === int verbose; // 1=enable debug output, 0=quiet (default) - int monoblock; // 1=single tile encoding (always 1 for current implementation) + int monoblock; // -1=auto (based on dimensions), 0=force tiled, 1=force monoblock } tav_encoder_params_t; @@ -296,6 +296,23 @@ void tav_encoder_get_stats(tav_encoder_context_t *ctx, tav_encoder_stats_t *stat #define TAV_PACKET_GOP_SYNC 0xFC // GOP sync (frame count marker) #define TAV_PACKET_TIMECODE 0xFD // Timecode metadata +// ============================================================================= +// Tile Settings (for multi-tile mode) +// ============================================================================= + +#define TAV_TILE_SIZE_X 640 // Base tile width +#define TAV_TILE_SIZE_Y 540 // Base tile height +#define TAV_DWT_FILTER_HALF_SUPPORT 4 // For 9/7 filter (filter lengths 9,7 → L=4) +#define TAV_TILE_MARGIN_LEVELS 3 // Use margin for 3 levels: 4 * (2^3) = 32px +#define TAV_TILE_MARGIN (TAV_DWT_FILTER_HALF_SUPPORT * (1 << TAV_TILE_MARGIN_LEVELS)) // 32px +#define TAV_PADDED_TILE_SIZE_X (TAV_TILE_SIZE_X + 2 * TAV_TILE_MARGIN) // 704 +#define TAV_PADDED_TILE_SIZE_Y (TAV_TILE_SIZE_Y + 2 * TAV_TILE_MARGIN) // 604 + +// Monoblock threshold: D1 PAL resolution (720x576) +// If width > 720 OR height > 576, automatically switch to tiled mode +#define TAV_MONOBLOCK_MAX_WIDTH 720 +#define TAV_MONOBLOCK_MAX_HEIGHT 576 + #ifdef __cplusplus } #endif diff --git a/video_encoder/lib/libtavenc/tav_encoder_lib.c b/video_encoder/lib/libtavenc/tav_encoder_lib.c index abcc6ff..521f477 100644 --- a/video_encoder/lib/libtavenc/tav_encoder_lib.c +++ b/video_encoder/lib/libtavenc/tav_encoder_lib.c @@ -206,6 +206,9 @@ struct tav_encoder_context { int verbose; int monoblock; + // Tile configuration (derived from monoblock and dimensions) + int tiles_x, tiles_y; // Number of tiles in x/y directions + // Derived quantizer values (QLUT indices) int quantiser_y, quantiser_co, quantiser_cg; @@ -304,7 +307,7 @@ void tav_encoder_params_init(tav_encoder_params_t *params, int width, int height // Advanced params->verbose = 0; - params->monoblock = 1; // Single tile (always 1 for current implementation) + params->monoblock = -1; // -1=auto (based on dimensions), 0=force tiled, 1=force monoblock } // ============================================================================= @@ -381,10 +384,60 @@ tav_encoder_context_t *tav_encoder_create(const tav_encoder_params_t *params) { // Force temporal level 2 ctx->temporal_levels = 2; + // Handle monoblock mode: + // -1 = auto (select based on dimensions), 0 = force tiled, 1 = force monoblock + if (ctx->monoblock == -1) { + // Auto mode: use monoblock for <= D1 PAL, tiled for larger + if (ctx->width > TAV_MONOBLOCK_MAX_WIDTH || ctx->height > TAV_MONOBLOCK_MAX_HEIGHT) { + ctx->monoblock = 0; + if (ctx->verbose) { + printf("Auto-selected Padded Tiling mode: %dx%d exceeds D1 PAL threshold (%dx%d)\n", + ctx->width, ctx->height, TAV_MONOBLOCK_MAX_WIDTH, TAV_MONOBLOCK_MAX_HEIGHT); + } + } else { + ctx->monoblock = 1; + if (ctx->verbose) { + printf("Auto-selected Monoblock mode: %dx%d within D1 PAL threshold\n", + ctx->width, ctx->height); + } + } + } else if (ctx->monoblock == 0) { + if (ctx->verbose) { + printf("Forced Padded Tiling mode (--tiled)\n"); + } + } else { + // monoblock == 1: force monoblock even for large dimensions + if (ctx->verbose) { + printf("Forced Monoblock mode (--monoblock)\n"); + } + } + + // Calculate tile dimensions based on monoblock setting + if (ctx->monoblock) { + // Monoblock mode: single tile covering entire frame + ctx->tiles_x = 1; + ctx->tiles_y = 1; + } else { + // Padded Tiling mode: multiple tiles of TILE_SIZE_X × TILE_SIZE_Y + ctx->tiles_x = (ctx->width + TAV_TILE_SIZE_X - 1) / TAV_TILE_SIZE_X; + ctx->tiles_y = (ctx->height + TAV_TILE_SIZE_Y - 1) / TAV_TILE_SIZE_Y; + if (ctx->verbose) { + printf("Padded Tiling mode: %dx%d tiles (%d total)\n", + ctx->tiles_x, ctx->tiles_y, ctx->tiles_x * ctx->tiles_y); + } + } + // Calculate decomp levels if auto (0) + // For multi-tile mode, use tile size as the basis; for monoblock, use frame size if (ctx->decomp_levels == 0) { int levels = 0; - int min_dim = (ctx->width < ctx->height) ? ctx->width : ctx->height; + int min_dim; + if (ctx->monoblock) { + min_dim = (ctx->width < ctx->height) ? ctx->width : ctx->height; + } else { + // For tiled mode, calculate based on tile size + min_dim = (TAV_TILE_SIZE_X < TAV_TILE_SIZE_Y) ? TAV_TILE_SIZE_X : TAV_TILE_SIZE_Y; + } // Keep halving until we reach minimum size while (min_dim >= 32) { min_dim /= 2; @@ -483,6 +536,9 @@ tav_encoder_context_t *tav_encoder_create(const tav_encoder_params_t *params) { printf("%s created:\n", ENCODER_VERSION); printf(" Resolution: %dx%d @ %d/%d fps\n", ctx->width, ctx->height, ctx->fps_num, ctx->fps_den); + printf(" Tiling: %s (%dx%d tiles)\n", + ctx->monoblock ? "Monoblock" : "Padded Tiling", + ctx->tiles_x, ctx->tiles_y); printf(" GOP size: %d frames\n", ctx->gop_size); printf(" Wavelet: %d (spatial), %d (temporal)\n", ctx->wavelet_type, ctx->temporal_wavelet); diff --git a/video_encoder/src/encoder_tav.c b/video_encoder/src/encoder_tav.c index e0a04eb..3fa7180 100644 --- a/video_encoder/src/encoder_tav.c +++ b/video_encoder/src/encoder_tav.c @@ -161,6 +161,10 @@ static void print_usage(const char *program) { printf(" --intra-only Disable temporal compression (I-frames only)\n"); printf(" --gop-size N GOP size 8/16/24 (default: 24)\n"); printf(" --single-pass Disable scene change detection\n"); + printf("\nTiling:\n"); + printf(" --monoblock Force single-tile mode (auto-disabled for > %dx%d)\n", + TAV_MONOBLOCK_MAX_WIDTH, TAV_MONOBLOCK_MAX_HEIGHT); + printf(" --tiled Force multi-tile mode (Padded Tiling)\n"); printf("\nCompression:\n"); printf(" --zstd-level N Zstd level 3-22 (default: 7)\n"); printf(" --no-perceptual-tuning Disable HVS perceptual quantization\n"); @@ -1212,6 +1216,8 @@ int main(int argc, char *argv[]) { {"no-audio", no_argument, 0, 1017}, {"preset-sports", no_argument, 0, 1026}, {"preset-anime", no_argument, 0, 1027}, + {"monoblock", no_argument, 0, 1028}, + {"tiled", no_argument, 0, 1029}, {"help", no_argument, 0, '?'}, {0, 0, 0, 0} }; @@ -1359,6 +1365,12 @@ int main(int argc, char *argv[]) { case 1027: // --preset-anime cli.enc_params.encoder_preset |= 0x02; break; + case 1028: // --monoblock + cli.enc_params.monoblock = 1; + break; + case 1029: // --tiled + cli.enc_params.monoblock = 0; + break; case '?': default: print_usage(argv[0]);