1a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Copyright 2011 Google Inc. All Rights Reserved. 27c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// 30406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Use of this source code is governed by a BSD-style license 40406ce1417f76f2034833414dcecc9f56253640cVikas Arora// that can be found in the COPYING file in the root of the source 50406ce1417f76f2034833414dcecc9f56253640cVikas Arora// tree. An additional intellectual property rights grant can be found 60406ce1417f76f2034833414dcecc9f56253640cVikas Arora// in the file PATENTS. All contributing project authors may 70406ce1417f76f2034833414dcecc9f56253640cVikas Arora// be found in the AUTHORS file in the root of the source tree. 87c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// ----------------------------------------------------------------------------- 97c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// 107c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// WebP encoder: main entry point 117c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// 127c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Author: Skal (pascal.massimino@gmail.com) 137c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 14466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#include <assert.h> 157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#include <stdlib.h> 167c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#include <string.h> 177c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#include <math.h> 187c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 19a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "./vp8enci.h" 20a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "./vp8li.h" 21a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "../utils/utils.h" 227c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 237c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// #define PRINT_MEMORY_INFO 247c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 257c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#if defined(__cplusplus) || defined(c_plusplus) 267c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroraextern "C" { 277c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#endif 287c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 297c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#ifdef PRINT_MEMORY_INFO 307c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#include <stdio.h> 317c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#endif 327c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 33a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 347c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 357c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroraint WebPGetEncoderVersion(void) { 367c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora return (ENC_MAJ_VERSION << 16) | (ENC_MIN_VERSION << 8) | ENC_REV_VERSION; 377c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 387c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 39a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 407c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// WebPPicture 41a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 427c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 437c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic int DummyWriter(const uint8_t* data, size_t data_size, 447c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const WebPPicture* const picture) { 457c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora // The following are to prevent 'unused variable' error message. 467c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora (void)data; 477c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora (void)data_size; 487c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora (void)picture; 497c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora return 1; 507c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 517c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 52a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraint WebPPictureInitInternal(WebPPicture* picture, int version) { 53a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_ENCODER_ABI_VERSION)) { 547c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora return 0; // caller/system version mismatch! 557c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 56a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (picture != NULL) { 577c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora memset(picture, 0, sizeof(*picture)); 587c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora picture->writer = DummyWriter; 59466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPEncodingSetError(picture, VP8_ENC_OK); 607c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 617c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora return 1; 627c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 637c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 64a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 657c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// VP8Encoder 66a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 677c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 687c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void ResetSegmentHeader(VP8Encoder* const enc) { 697c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8SegmentHeader* const hdr = &enc->segment_hdr_; 707c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora hdr->num_segments_ = enc->config_->segments; 717c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora hdr->update_map_ = (hdr->num_segments_ > 1); 727c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora hdr->size_ = 0; 737c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 747c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 757c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void ResetFilterHeader(VP8Encoder* const enc) { 767c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8FilterHeader* const hdr = &enc->filter_hdr_; 777c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora hdr->simple_ = 1; 787c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora hdr->level_ = 0; 797c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora hdr->sharpness_ = 0; 807c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora hdr->i4x4_lf_delta_ = 0; 817c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 827c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 837c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void ResetBoundaryPredictions(VP8Encoder* const enc) { 847c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora // init boundary values once for all 857c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora // Note: actually, initializing the preds_[] is only needed for intra4. 867c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora int i; 877c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora uint8_t* const top = enc->preds_ - enc->preds_w_; 887c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora uint8_t* const left = enc->preds_ - 1; 897c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora for (i = -1; i < 4 * enc->mb_w_; ++i) { 907c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora top[i] = B_DC_PRED; 917c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 927c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora for (i = 0; i < 4 * enc->mb_h_; ++i) { 937c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora left[i * enc->preds_w_] = B_DC_PRED; 947c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 957c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->nz_[-1] = 0; // constant 967c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 977c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 981e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// Mapping from config->method_ to coding tools used. 991e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//-------------------+---+---+---+---+---+---+---+ 1001e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// Method | 0 | 1 | 2 | 3 |(4)| 5 | 6 | 1011e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//-------------------+---+---+---+---+---+---+---+ 1021e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// fast probe | x | | | x | | | | 1031e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//-------------------+---+---+---+---+---+---+---+ 1041e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// dynamic proba | ~ | x | x | x | x | x | x | 1051e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//-------------------+---+---+---+---+---+---+---+ 1061e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// fast mode analysis| | | | | x | x | x | 1071e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//-------------------+---+---+---+---+---+---+---+ 1081e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// basic rd-opt | | | | x | x | x | x | 1091e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//-------------------+---+---+---+---+---+---+---+ 1101e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// disto-score i4/16 | | | x | | | | | 1111e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//-------------------+---+---+---+---+---+---+---+ 1121e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// rd-opt i4/16 | | | ~ | x | x | x | x | 1131e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//-------------------+---+---+---+---+---+---+---+ 1141e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// token buffer (opt)| | | | x | x | x | x | 1151e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//-------------------+---+---+---+---+---+---+---+ 1161e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// Trellis | | | | | | x |Ful| 1171e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//-------------------+---+---+---+---+---+---+---+ 1181e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// full-SNS | | | | | x | x | x | 1191e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora//-------------------+---+---+---+---+---+---+---+ 1207c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 1217c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void MapConfigToTools(VP8Encoder* const enc) { 1221e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const WebPConfig* const config = enc->config_; 1231e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const int method = config->method; 1241e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const int limit = 100 - config->partition_limit; 1257c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->method_ = method; 1261e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora enc->rd_opt_level_ = (method >= 6) ? RD_OPT_TRELLIS_ALL 1271e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora : (method >= 5) ? RD_OPT_TRELLIS 1281e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora : (method >= 3) ? RD_OPT_BASIC 1291e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora : RD_OPT_NONE; 130a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora enc->max_i4_header_bits_ = 131a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 256 * 16 * 16 * // upper bound: up to 16bit per 4x4 block 132a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora (limit * limit) / (100 * 100); // ... modulated with a quadratic curve. 1331e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1341e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora enc->thread_level_ = config->thread_level; 1351e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 1361e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora enc->do_search_ = (config->target_size > 0 || config->target_PSNR > 0); 1371e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (!config->low_memory) { 1381e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#if !defined(DISABLE_TOKEN_BUFFER) 1391e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora enc->use_tokens_ = (method >= 3) && !enc->do_search_; 1401e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#endif 1411e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (enc->use_tokens_) { 1421e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora enc->num_parts_ = 1; // doesn't work with multi-partition 1431e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 1441e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 1457c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 1467c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 1477c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Memory scaling with dimensions: 1487c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// memory (bytes) ~= 2.25 * w + 0.0625 * w * h 1497c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// 1507c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Typical memory footprint (768x510 picture) 1517c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Memory used: 1527c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// encoder: 33919 1537c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// block cache: 2880 1547c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// info: 3072 1557c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// preds: 24897 1567c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// top samples: 1623 1577c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// non-zero: 196 1587c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// lf-stats: 2048 1597c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// total: 68635 1607c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Transcient object sizes: 1617c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// VP8EncIterator: 352 1627c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// VP8ModeScore: 912 1637c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// VP8SegmentInfo: 532 1647c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// VP8Proba: 31032 1657c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// LFStats: 2048 1667c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Picture size (yuv): 589824 1677c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 168a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic VP8Encoder* InitVP8Encoder(const WebPConfig* const config, 169a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPPicture* const picture) { 1707c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const int use_filter = 1717c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora (config->filter_strength > 0) || (config->autofilter > 0); 1727c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const int mb_w = (picture->width + 15) >> 4; 1737c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const int mb_h = (picture->height + 15) >> 4; 1747c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const int preds_w = 4 * mb_w + 1; 1757c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const int preds_h = 4 * mb_h + 1; 1767c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const size_t preds_size = preds_w * preds_h * sizeof(uint8_t); 1777c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const int top_stride = mb_w * 16; 1787c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const size_t nz_size = (mb_w + 1) * sizeof(uint32_t); 1797c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const size_t cache_size = (3 * YUV_SIZE + PRED_SIZE) * sizeof(uint8_t); 1807c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const size_t info_size = mb_w * mb_h * sizeof(VP8MBInfo); 1817c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const size_t samples_size = (2 * top_stride + // top-luma/u/v 1827c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 16 + 16 + 16 + 8 + 1 + // left y/u/v 1837c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 2 * ALIGN_CST) // align all 1847c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora * sizeof(uint8_t); 185466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora const size_t lf_stats_size = 186466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora config->autofilter ? sizeof(LFStats) + ALIGN_CST : 0; 1877c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8Encoder* enc; 1887c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora uint8_t* mem; 189a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const uint64_t size = (uint64_t)sizeof(VP8Encoder) // main struct 190a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora + ALIGN_CST // cache alignment 191a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora + cache_size // working caches 192a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora + info_size // modes info 193a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora + preds_size // prediction modes 194a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora + samples_size // top/left samples 195a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora + nz_size // coeff context bits 196a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora + lf_stats_size; // autofilter stats 1977c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 1987c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#ifdef PRINT_MEMORY_INFO 1997c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora printf("===================================\n"); 2007c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora printf("Memory used:\n" 2017c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora " encoder: %ld\n" 2027c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora " block cache: %ld\n" 2037c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora " info: %ld\n" 2047c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora " preds: %ld\n" 2057c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora " top samples: %ld\n" 2067c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora " non-zero: %ld\n" 2077c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora " lf-stats: %ld\n" 2087c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora " total: %ld\n", 2097c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora sizeof(VP8Encoder) + ALIGN_CST, cache_size, info_size, 2107c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora preds_size, samples_size, nz_size, lf_stats_size, size); 2117c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora printf("Transcient object sizes:\n" 2127c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora " VP8EncIterator: %ld\n" 2137c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora " VP8ModeScore: %ld\n" 2147c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora " VP8SegmentInfo: %ld\n" 2157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora " VP8Proba: %ld\n" 2167c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora " LFStats: %ld\n", 2177c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora sizeof(VP8EncIterator), sizeof(VP8ModeScore), 2187c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora sizeof(VP8SegmentInfo), sizeof(VP8Proba), 2197c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora sizeof(LFStats)); 2207c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora printf("Picture size (yuv): %ld\n", 2217c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mb_w * mb_h * 384 * sizeof(uint8_t)); 2227c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora printf("===================================\n"); 2237c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#endif 224a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora mem = (uint8_t*)WebPSafeMalloc(size, sizeof(*mem)); 225466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (mem == NULL) { 226466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); 227466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return NULL; 228466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 2297c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc = (VP8Encoder*)mem; 2307c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mem = (uint8_t*)DO_ALIGN(mem + sizeof(*enc)); 2317c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora memset(enc, 0, sizeof(*enc)); 2327c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->num_parts_ = 1 << config->partitions; 2337c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->mb_w_ = mb_w; 2347c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->mb_h_ = mb_h; 2357c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->preds_w_ = preds_w; 2367c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->yuv_in_ = (uint8_t*)mem; 2377c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mem += YUV_SIZE; 2387c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->yuv_out_ = (uint8_t*)mem; 2397c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mem += YUV_SIZE; 2407c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->yuv_out2_ = (uint8_t*)mem; 2417c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mem += YUV_SIZE; 2427c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->yuv_p_ = (uint8_t*)mem; 2437c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mem += PRED_SIZE; 2447c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->mb_info_ = (VP8MBInfo*)mem; 2457c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mem += info_size; 2467c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->preds_ = ((uint8_t*)mem) + 1 + enc->preds_w_; 2477c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mem += preds_w * preds_h * sizeof(uint8_t); 2487c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->nz_ = 1 + (uint32_t*)mem; 2497c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mem += nz_size; 250466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora enc->lf_stats_ = lf_stats_size ? (LFStats*)DO_ALIGN(mem) : NULL; 2517c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mem += lf_stats_size; 2527c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 2537c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora // top samples (all 16-aligned) 2547c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mem = (uint8_t*)DO_ALIGN(mem); 2557c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->y_top_ = (uint8_t*)mem; 2567c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->uv_top_ = enc->y_top_ + top_stride; 2577c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mem += 2 * top_stride; 2587c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mem = (uint8_t*)DO_ALIGN(mem + 1); 2597c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->y_left_ = (uint8_t*)mem; 2607c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mem += 16 + 16; 2617c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->u_left_ = (uint8_t*)mem; 2627c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mem += 16; 2637c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->v_left_ = (uint8_t*)mem; 2647c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora mem += 8; 2657c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 2667c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->config_ = config; 2677c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->profile_ = use_filter ? ((config->filter_type == 1) ? 0 : 1) : 2; 2687c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora enc->pic_ = picture; 269a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora enc->percent_ = 0; 2707c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 2717c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora MapConfigToTools(enc); 2727c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8EncDspInit(); 2737c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora VP8DefaultProbas(enc); 2747c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora ResetSegmentHeader(enc); 2757c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora ResetFilterHeader(enc); 2767c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora ResetBoundaryPredictions(enc); 2777c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 278466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora VP8EncInitAlpha(enc); 279a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#ifdef WEBP_EXPERIMENTAL_FEATURES 280466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora VP8EncInitLayer(enc); 281466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#endif 282466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 2831e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8TBufferInit(&enc->tokens_); 2847c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora return enc; 2857c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 2867c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 2871e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic int DeleteVP8Encoder(VP8Encoder* enc) { 2881e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora int ok = 1; 289a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (enc != NULL) { 2901e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora ok = VP8EncDeleteAlpha(enc); 291a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#ifdef WEBP_EXPERIMENTAL_FEATURES 292466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora VP8EncDeleteLayer(enc); 293466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#endif 2941e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8TBufferClear(&enc->tokens_); 295466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora free(enc); 296466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora } 2971e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return ok; 2987c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 2997c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 300a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 3017c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 3027c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic double GetPSNR(uint64_t err, uint64_t size) { 3037c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora return err ? 10. * log10(255. * 255. * size / err) : 99.; 3047c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 3057c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 3067c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void FinalizePSNR(const VP8Encoder* const enc) { 3077c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora WebPAuxStats* stats = enc->pic_->stats; 3087c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const uint64_t size = enc->sse_count_; 3097c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora const uint64_t* const sse = enc->sse_; 3107c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora stats->PSNR[0] = (float)GetPSNR(sse[0], size); 3117c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora stats->PSNR[1] = (float)GetPSNR(sse[1], size / 4); 3127c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora stats->PSNR[2] = (float)GetPSNR(sse[2], size / 4); 3137c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora stats->PSNR[3] = (float)GetPSNR(sse[0] + sse[1] + sse[2], size * 3 / 2); 314a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora stats->PSNR[4] = (float)GetPSNR(sse[3], size); 3157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 3167c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 3177c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arorastatic void StoreStats(VP8Encoder* const enc) { 3187c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora WebPAuxStats* const stats = enc->pic_->stats; 319a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (stats != NULL) { 3207c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora int i, s; 3217c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora for (i = 0; i < NUM_MB_SEGMENTS; ++i) { 3227c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora stats->segment_level[i] = enc->dqm_[i].fstrength_; 3237c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora stats->segment_quant[i] = enc->dqm_[i].quant_; 3247c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora for (s = 0; s <= 2; ++s) { 3257c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora stats->residual_bytes[s][i] = enc->residual_bytes_[s][i]; 3267c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 3277c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 3287c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora FinalizePSNR(enc); 3297c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora stats->coded_size = enc->coded_size_; 3307c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora for (i = 0; i < 3; ++i) { 3317c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora stats->block_count[i] = enc->block_count_[i]; 3327c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 3337c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora } 334a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPReportProgress(enc->pic_, 100, &enc->percent_); // done! 3357c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 3367c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 337a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraint WebPEncodingSetError(const WebPPicture* const pic, 338a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPEncodingError error) { 339a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora assert((int)error < VP8_ENC_ERROR_LAST); 340466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora assert((int)error >= VP8_ENC_OK); 341a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ((WebPPicture*)pic)->error_code = error; 342466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return 0; 343466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora} 344466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 345a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraint WebPReportProgress(const WebPPicture* const pic, 346a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora int percent, int* const percent_store) { 347a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (percent_store != NULL && percent != *percent_store) { 348a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora *percent_store = percent; 349a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (pic->progress_hook && !pic->progress_hook(percent, pic)) { 350a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // user abort requested 351a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora WebPEncodingSetError(pic, VP8_ENC_ERROR_USER_ABORT); 352a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 0; 353a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 354a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 355a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return 1; // ok 356a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 357a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 3587c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 359a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraint WebPEncode(const WebPConfig* config, WebPPicture* pic) { 3601e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora int ok = 0; 3617c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 362466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (pic == NULL) 363466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return 0; 364466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora WebPEncodingSetError(pic, VP8_ENC_OK); // all ok so far 365466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora if (config == NULL) // bad params 366466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER); 3677c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora if (!WebPValidateConfig(config)) 368466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return WebPEncodingSetError(pic, VP8_ENC_ERROR_INVALID_CONFIGURATION); 3697c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora if (pic->width <= 0 || pic->height <= 0) 370466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION); 371a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (pic->width > WEBP_MAX_DIMENSION || pic->height > WEBP_MAX_DIMENSION) 372466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora return WebPEncodingSetError(pic, VP8_ENC_ERROR_BAD_DIMENSION); 3737c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 374a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (pic->stats != NULL) memset(pic->stats, 0, sizeof(*pic->stats)); 375a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 376a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!config->lossless) { 377a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8Encoder* enc = NULL; 378a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (pic->y == NULL || pic->u == NULL || pic->v == NULL) { 3790406ce1417f76f2034833414dcecc9f56253640cVikas Arora // Make sure we have YUVA samples. 3800406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (!WebPPictureARGBToYUVA(pic, WEBP_YUV420)) return 0; 381a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 382a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 383a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora enc = InitVP8Encoder(config, pic); 384a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (enc == NULL) return 0; // pic->error is already set. 385a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora // Note: each of the tasks below account for 20% in the progress report. 3861e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora ok = VP8EncAnalyze(enc); 3871e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 3881e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora // Analysis is done, proceed to actual coding. 3891e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora ok = ok && VP8EncStartAlpha(enc); // possibly done in parallel 3901e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora if (!enc->use_tokens_) { 3910406ce1417f76f2034833414dcecc9f56253640cVikas Arora ok = ok && VP8EncLoop(enc); 3921e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } else { 3930406ce1417f76f2034833414dcecc9f56253640cVikas Arora ok = ok && VP8EncTokenLoop(enc); 3941e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora } 3951e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora ok = ok && VP8EncFinishAlpha(enc); 396466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#ifdef WEBP_EXPERIMENTAL_FEATURES 3971e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora ok = ok && VP8EncFinishLayer(enc); 398466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#endif 3991e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 4001e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora ok = ok && VP8EncWrite(enc); 401a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora StoreStats(enc); 402a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora if (!ok) { 403a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora VP8EncFreeBitWriters(enc); 404a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 4051e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora ok &= DeleteVP8Encoder(enc); // must always be called, even if !ok 406a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } else { 4070406ce1417f76f2034833414dcecc9f56253640cVikas Arora // Make sure we have ARGB samples. 4080406ce1417f76f2034833414dcecc9f56253640cVikas Arora if (pic->argb == NULL && !WebPPictureYUVAToARGB(pic)) { 4090406ce1417f76f2034833414dcecc9f56253640cVikas Arora return 0; 4100406ce1417f76f2034833414dcecc9f56253640cVikas Arora } 411a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 412a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem. 413a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora } 414466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 4157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora return ok; 4167c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} 4177c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora 4187c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#if defined(__cplusplus) || defined(c_plusplus) 4197c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora} // extern "C" 4207c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#endif 421