1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * SVQ1 Encoder 3cabdff1aSopenharmony_ci * Copyright (C) 2004 Mike Melanson <melanson@pcisys.net> 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci/** 23cabdff1aSopenharmony_ci * @file 24cabdff1aSopenharmony_ci * Sorenson Vector Quantizer #1 (SVQ1) video codec. 25cabdff1aSopenharmony_ci * For more information of the SVQ1 algorithm, visit: 26cabdff1aSopenharmony_ci * http://www.pcisys.net/~melanson/codecs/ 27cabdff1aSopenharmony_ci */ 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci#include "avcodec.h" 30cabdff1aSopenharmony_ci#include "codec_internal.h" 31cabdff1aSopenharmony_ci#include "encode.h" 32cabdff1aSopenharmony_ci#include "hpeldsp.h" 33cabdff1aSopenharmony_ci#include "me_cmp.h" 34cabdff1aSopenharmony_ci#include "mpegvideo.h" 35cabdff1aSopenharmony_ci#include "h263.h" 36cabdff1aSopenharmony_ci#include "h263enc.h" 37cabdff1aSopenharmony_ci#include "internal.h" 38cabdff1aSopenharmony_ci#include "mpegutils.h" 39cabdff1aSopenharmony_ci#include "packet_internal.h" 40cabdff1aSopenharmony_ci#include "svq1.h" 41cabdff1aSopenharmony_ci#include "svq1enc.h" 42cabdff1aSopenharmony_ci#include "svq1enc_cb.h" 43cabdff1aSopenharmony_ci#include "libavutil/avassert.h" 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_cistatic void svq1_write_header(SVQ1EncContext *s, int frame_type) 47cabdff1aSopenharmony_ci{ 48cabdff1aSopenharmony_ci int i; 49cabdff1aSopenharmony_ci 50cabdff1aSopenharmony_ci /* frame code */ 51cabdff1aSopenharmony_ci put_bits(&s->pb, 22, 0x20); 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_ci /* temporal reference (sure hope this is a "don't care") */ 54cabdff1aSopenharmony_ci put_bits(&s->pb, 8, 0x00); 55cabdff1aSopenharmony_ci 56cabdff1aSopenharmony_ci /* frame type */ 57cabdff1aSopenharmony_ci put_bits(&s->pb, 2, frame_type - 1); 58cabdff1aSopenharmony_ci 59cabdff1aSopenharmony_ci if (frame_type == AV_PICTURE_TYPE_I) { 60cabdff1aSopenharmony_ci /* no checksum since frame code is 0x20 */ 61cabdff1aSopenharmony_ci /* no embedded string either */ 62cabdff1aSopenharmony_ci /* output 5 unknown bits (2 + 2 + 1) */ 63cabdff1aSopenharmony_ci put_bits(&s->pb, 5, 2); /* 2 needed by quicktime decoder */ 64cabdff1aSopenharmony_ci 65cabdff1aSopenharmony_ci i = ff_match_2uint16((void*)ff_svq1_frame_size_table, 66cabdff1aSopenharmony_ci FF_ARRAY_ELEMS(ff_svq1_frame_size_table), 67cabdff1aSopenharmony_ci s->frame_width, s->frame_height); 68cabdff1aSopenharmony_ci put_bits(&s->pb, 3, i); 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_ci if (i == 7) { 71cabdff1aSopenharmony_ci put_bits(&s->pb, 12, s->frame_width); 72cabdff1aSopenharmony_ci put_bits(&s->pb, 12, s->frame_height); 73cabdff1aSopenharmony_ci } 74cabdff1aSopenharmony_ci } 75cabdff1aSopenharmony_ci 76cabdff1aSopenharmony_ci /* no checksum or extra data (next 2 bits get 0) */ 77cabdff1aSopenharmony_ci put_bits(&s->pb, 2, 0); 78cabdff1aSopenharmony_ci} 79cabdff1aSopenharmony_ci 80cabdff1aSopenharmony_ci#define QUALITY_THRESHOLD 100 81cabdff1aSopenharmony_ci#define THRESHOLD_MULTIPLIER 0.6 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_cistatic int ssd_int8_vs_int16_c(const int8_t *pix1, const int16_t *pix2, 84cabdff1aSopenharmony_ci intptr_t size) 85cabdff1aSopenharmony_ci{ 86cabdff1aSopenharmony_ci int score = 0, i; 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci for (i = 0; i < size; i++) 89cabdff1aSopenharmony_ci score += (pix1[i] - pix2[i]) * (pix1[i] - pix2[i]); 90cabdff1aSopenharmony_ci return score; 91cabdff1aSopenharmony_ci} 92cabdff1aSopenharmony_ci 93cabdff1aSopenharmony_cistatic int encode_block(SVQ1EncContext *s, uint8_t *src, uint8_t *ref, 94cabdff1aSopenharmony_ci uint8_t *decoded, int stride, int level, 95cabdff1aSopenharmony_ci int threshold, int lambda, int intra) 96cabdff1aSopenharmony_ci{ 97cabdff1aSopenharmony_ci int count, y, x, i, j, split, best_mean, best_score, best_count; 98cabdff1aSopenharmony_ci int best_vector[6]; 99cabdff1aSopenharmony_ci int block_sum[7] = { 0, 0, 0, 0, 0, 0 }; 100cabdff1aSopenharmony_ci int w = 2 << (level + 2 >> 1); 101cabdff1aSopenharmony_ci int h = 2 << (level + 1 >> 1); 102cabdff1aSopenharmony_ci int size = w * h; 103cabdff1aSopenharmony_ci int16_t (*block)[256] = s->encoded_block_levels[level]; 104cabdff1aSopenharmony_ci const int8_t *codebook_sum, *codebook; 105cabdff1aSopenharmony_ci const uint16_t(*mean_vlc)[2]; 106cabdff1aSopenharmony_ci const uint8_t(*multistage_vlc)[2]; 107cabdff1aSopenharmony_ci 108cabdff1aSopenharmony_ci best_score = 0; 109cabdff1aSopenharmony_ci // FIXME: Optimize, this does not need to be done multiple times. 110cabdff1aSopenharmony_ci if (intra) { 111cabdff1aSopenharmony_ci // level is 5 when encode_block is called from svq1_encode_plane 112cabdff1aSopenharmony_ci // and always < 4 when called recursively from this function. 113cabdff1aSopenharmony_ci codebook_sum = level < 4 ? svq1_intra_codebook_sum[level] : NULL; 114cabdff1aSopenharmony_ci codebook = ff_svq1_intra_codebooks[level]; 115cabdff1aSopenharmony_ci mean_vlc = ff_svq1_intra_mean_vlc; 116cabdff1aSopenharmony_ci multistage_vlc = ff_svq1_intra_multistage_vlc[level]; 117cabdff1aSopenharmony_ci for (y = 0; y < h; y++) { 118cabdff1aSopenharmony_ci for (x = 0; x < w; x++) { 119cabdff1aSopenharmony_ci int v = src[x + y * stride]; 120cabdff1aSopenharmony_ci block[0][x + w * y] = v; 121cabdff1aSopenharmony_ci best_score += v * v; 122cabdff1aSopenharmony_ci block_sum[0] += v; 123cabdff1aSopenharmony_ci } 124cabdff1aSopenharmony_ci } 125cabdff1aSopenharmony_ci } else { 126cabdff1aSopenharmony_ci // level is 5 or < 4, see above for details. 127cabdff1aSopenharmony_ci codebook_sum = level < 4 ? svq1_inter_codebook_sum[level] : NULL; 128cabdff1aSopenharmony_ci codebook = ff_svq1_inter_codebooks[level]; 129cabdff1aSopenharmony_ci mean_vlc = ff_svq1_inter_mean_vlc + 256; 130cabdff1aSopenharmony_ci multistage_vlc = ff_svq1_inter_multistage_vlc[level]; 131cabdff1aSopenharmony_ci for (y = 0; y < h; y++) { 132cabdff1aSopenharmony_ci for (x = 0; x < w; x++) { 133cabdff1aSopenharmony_ci int v = src[x + y * stride] - ref[x + y * stride]; 134cabdff1aSopenharmony_ci block[0][x + w * y] = v; 135cabdff1aSopenharmony_ci best_score += v * v; 136cabdff1aSopenharmony_ci block_sum[0] += v; 137cabdff1aSopenharmony_ci } 138cabdff1aSopenharmony_ci } 139cabdff1aSopenharmony_ci } 140cabdff1aSopenharmony_ci 141cabdff1aSopenharmony_ci best_count = 0; 142cabdff1aSopenharmony_ci best_score -= (int)((unsigned)block_sum[0] * block_sum[0] >> (level + 3)); 143cabdff1aSopenharmony_ci best_mean = block_sum[0] + (size >> 1) >> (level + 3); 144cabdff1aSopenharmony_ci 145cabdff1aSopenharmony_ci if (level < 4) { 146cabdff1aSopenharmony_ci for (count = 1; count < 7; count++) { 147cabdff1aSopenharmony_ci int best_vector_score = INT_MAX; 148cabdff1aSopenharmony_ci int best_vector_sum = -999, best_vector_mean = -999; 149cabdff1aSopenharmony_ci const int stage = count - 1; 150cabdff1aSopenharmony_ci const int8_t *vector; 151cabdff1aSopenharmony_ci 152cabdff1aSopenharmony_ci for (i = 0; i < 16; i++) { 153cabdff1aSopenharmony_ci int sum = codebook_sum[stage * 16 + i]; 154cabdff1aSopenharmony_ci int sqr, diff, score; 155cabdff1aSopenharmony_ci 156cabdff1aSopenharmony_ci vector = codebook + stage * size * 16 + i * size; 157cabdff1aSopenharmony_ci sqr = s->ssd_int8_vs_int16(vector, block[stage], size); 158cabdff1aSopenharmony_ci diff = block_sum[stage] - sum; 159cabdff1aSopenharmony_ci score = sqr - (diff * (int64_t)diff >> (level + 3)); // FIXME: 64 bits slooow 160cabdff1aSopenharmony_ci if (score < best_vector_score) { 161cabdff1aSopenharmony_ci int mean = diff + (size >> 1) >> (level + 3); 162cabdff1aSopenharmony_ci av_assert2(mean > -300 && mean < 300); 163cabdff1aSopenharmony_ci mean = av_clip(mean, intra ? 0 : -256, 255); 164cabdff1aSopenharmony_ci best_vector_score = score; 165cabdff1aSopenharmony_ci best_vector[stage] = i; 166cabdff1aSopenharmony_ci best_vector_sum = sum; 167cabdff1aSopenharmony_ci best_vector_mean = mean; 168cabdff1aSopenharmony_ci } 169cabdff1aSopenharmony_ci } 170cabdff1aSopenharmony_ci av_assert0(best_vector_mean != -999); 171cabdff1aSopenharmony_ci vector = codebook + stage * size * 16 + best_vector[stage] * size; 172cabdff1aSopenharmony_ci for (j = 0; j < size; j++) 173cabdff1aSopenharmony_ci block[stage + 1][j] = block[stage][j] - vector[j]; 174cabdff1aSopenharmony_ci block_sum[stage + 1] = block_sum[stage] - best_vector_sum; 175cabdff1aSopenharmony_ci best_vector_score += lambda * 176cabdff1aSopenharmony_ci (+1 + 4 * count + 177cabdff1aSopenharmony_ci multistage_vlc[1 + count][1] 178cabdff1aSopenharmony_ci + mean_vlc[best_vector_mean][1]); 179cabdff1aSopenharmony_ci 180cabdff1aSopenharmony_ci if (best_vector_score < best_score) { 181cabdff1aSopenharmony_ci best_score = best_vector_score; 182cabdff1aSopenharmony_ci best_count = count; 183cabdff1aSopenharmony_ci best_mean = best_vector_mean; 184cabdff1aSopenharmony_ci } 185cabdff1aSopenharmony_ci } 186cabdff1aSopenharmony_ci } 187cabdff1aSopenharmony_ci 188cabdff1aSopenharmony_ci split = 0; 189cabdff1aSopenharmony_ci if (best_score > threshold && level) { 190cabdff1aSopenharmony_ci int score = 0; 191cabdff1aSopenharmony_ci int offset = level & 1 ? stride * h / 2 : w / 2; 192cabdff1aSopenharmony_ci PutBitContext backup[6]; 193cabdff1aSopenharmony_ci 194cabdff1aSopenharmony_ci for (i = level - 1; i >= 0; i--) 195cabdff1aSopenharmony_ci backup[i] = s->reorder_pb[i]; 196cabdff1aSopenharmony_ci score += encode_block(s, src, ref, decoded, stride, level - 1, 197cabdff1aSopenharmony_ci threshold >> 1, lambda, intra); 198cabdff1aSopenharmony_ci score += encode_block(s, src + offset, ref + offset, decoded + offset, 199cabdff1aSopenharmony_ci stride, level - 1, threshold >> 1, lambda, intra); 200cabdff1aSopenharmony_ci score += lambda; 201cabdff1aSopenharmony_ci 202cabdff1aSopenharmony_ci if (score < best_score) { 203cabdff1aSopenharmony_ci best_score = score; 204cabdff1aSopenharmony_ci split = 1; 205cabdff1aSopenharmony_ci } else { 206cabdff1aSopenharmony_ci for (i = level - 1; i >= 0; i--) 207cabdff1aSopenharmony_ci s->reorder_pb[i] = backup[i]; 208cabdff1aSopenharmony_ci } 209cabdff1aSopenharmony_ci } 210cabdff1aSopenharmony_ci if (level > 0) 211cabdff1aSopenharmony_ci put_bits(&s->reorder_pb[level], 1, split); 212cabdff1aSopenharmony_ci 213cabdff1aSopenharmony_ci if (!split) { 214cabdff1aSopenharmony_ci av_assert1(best_mean >= 0 && best_mean < 256 || !intra); 215cabdff1aSopenharmony_ci av_assert1(best_mean >= -256 && best_mean < 256); 216cabdff1aSopenharmony_ci av_assert1(best_count >= 0 && best_count < 7); 217cabdff1aSopenharmony_ci av_assert1(level < 4 || best_count == 0); 218cabdff1aSopenharmony_ci 219cabdff1aSopenharmony_ci /* output the encoding */ 220cabdff1aSopenharmony_ci put_bits(&s->reorder_pb[level], 221cabdff1aSopenharmony_ci multistage_vlc[1 + best_count][1], 222cabdff1aSopenharmony_ci multistage_vlc[1 + best_count][0]); 223cabdff1aSopenharmony_ci put_bits(&s->reorder_pb[level], mean_vlc[best_mean][1], 224cabdff1aSopenharmony_ci mean_vlc[best_mean][0]); 225cabdff1aSopenharmony_ci 226cabdff1aSopenharmony_ci for (i = 0; i < best_count; i++) { 227cabdff1aSopenharmony_ci av_assert2(best_vector[i] >= 0 && best_vector[i] < 16); 228cabdff1aSopenharmony_ci put_bits(&s->reorder_pb[level], 4, best_vector[i]); 229cabdff1aSopenharmony_ci } 230cabdff1aSopenharmony_ci 231cabdff1aSopenharmony_ci for (y = 0; y < h; y++) 232cabdff1aSopenharmony_ci for (x = 0; x < w; x++) 233cabdff1aSopenharmony_ci decoded[x + y * stride] = src[x + y * stride] - 234cabdff1aSopenharmony_ci block[best_count][x + w * y] + 235cabdff1aSopenharmony_ci best_mean; 236cabdff1aSopenharmony_ci } 237cabdff1aSopenharmony_ci 238cabdff1aSopenharmony_ci return best_score; 239cabdff1aSopenharmony_ci} 240cabdff1aSopenharmony_ci 241cabdff1aSopenharmony_cistatic void init_block_index(MpegEncContext *s){ 242cabdff1aSopenharmony_ci s->block_index[0]= s->b8_stride*(s->mb_y*2 ) + s->mb_x*2; 243cabdff1aSopenharmony_ci s->block_index[1]= s->b8_stride*(s->mb_y*2 ) + 1 + s->mb_x*2; 244cabdff1aSopenharmony_ci s->block_index[2]= s->b8_stride*(s->mb_y*2 + 1) + s->mb_x*2; 245cabdff1aSopenharmony_ci s->block_index[3]= s->b8_stride*(s->mb_y*2 + 1) + 1 + s->mb_x*2; 246cabdff1aSopenharmony_ci s->block_index[4]= s->mb_stride*(s->mb_y + 1) + s->b8_stride*s->mb_height*2 + s->mb_x; 247cabdff1aSopenharmony_ci s->block_index[5]= s->mb_stride*(s->mb_y + s->mb_height + 2) + s->b8_stride*s->mb_height*2 + s->mb_x; 248cabdff1aSopenharmony_ci} 249cabdff1aSopenharmony_ci 250cabdff1aSopenharmony_cistatic int svq1_encode_plane(SVQ1EncContext *s, int plane, 251cabdff1aSopenharmony_ci unsigned char *src_plane, 252cabdff1aSopenharmony_ci unsigned char *ref_plane, 253cabdff1aSopenharmony_ci unsigned char *decoded_plane, 254cabdff1aSopenharmony_ci int width, int height, int src_stride, int stride) 255cabdff1aSopenharmony_ci{ 256cabdff1aSopenharmony_ci int x, y; 257cabdff1aSopenharmony_ci int i; 258cabdff1aSopenharmony_ci int block_width, block_height; 259cabdff1aSopenharmony_ci int level; 260cabdff1aSopenharmony_ci int threshold[6]; 261cabdff1aSopenharmony_ci uint8_t *src = s->scratchbuf + stride * 32; 262cabdff1aSopenharmony_ci const int lambda = (s->quality * s->quality) >> 263cabdff1aSopenharmony_ci (2 * FF_LAMBDA_SHIFT); 264cabdff1aSopenharmony_ci 265cabdff1aSopenharmony_ci /* figure out the acceptable level thresholds in advance */ 266cabdff1aSopenharmony_ci threshold[5] = QUALITY_THRESHOLD; 267cabdff1aSopenharmony_ci for (level = 4; level >= 0; level--) 268cabdff1aSopenharmony_ci threshold[level] = threshold[level + 1] * THRESHOLD_MULTIPLIER; 269cabdff1aSopenharmony_ci 270cabdff1aSopenharmony_ci block_width = (width + 15) / 16; 271cabdff1aSopenharmony_ci block_height = (height + 15) / 16; 272cabdff1aSopenharmony_ci 273cabdff1aSopenharmony_ci if (s->pict_type == AV_PICTURE_TYPE_P) { 274cabdff1aSopenharmony_ci s->m.avctx = s->avctx; 275cabdff1aSopenharmony_ci s->m.current_picture_ptr = &s->m.current_picture; 276cabdff1aSopenharmony_ci s->m.last_picture_ptr = &s->m.last_picture; 277cabdff1aSopenharmony_ci s->m.last_picture.f->data[0] = ref_plane; 278cabdff1aSopenharmony_ci s->m.linesize = 279cabdff1aSopenharmony_ci s->m.last_picture.f->linesize[0] = 280cabdff1aSopenharmony_ci s->m.new_picture->linesize[0] = 281cabdff1aSopenharmony_ci s->m.current_picture.f->linesize[0] = stride; 282cabdff1aSopenharmony_ci s->m.width = width; 283cabdff1aSopenharmony_ci s->m.height = height; 284cabdff1aSopenharmony_ci s->m.mb_width = block_width; 285cabdff1aSopenharmony_ci s->m.mb_height = block_height; 286cabdff1aSopenharmony_ci s->m.mb_stride = s->m.mb_width + 1; 287cabdff1aSopenharmony_ci s->m.b8_stride = 2 * s->m.mb_width + 1; 288cabdff1aSopenharmony_ci s->m.f_code = 1; 289cabdff1aSopenharmony_ci s->m.pict_type = s->pict_type; 290cabdff1aSopenharmony_ci s->m.motion_est = s->motion_est; 291cabdff1aSopenharmony_ci s->m.me.scene_change_score = 0; 292cabdff1aSopenharmony_ci // s->m.out_format = FMT_H263; 293cabdff1aSopenharmony_ci // s->m.unrestricted_mv = 1; 294cabdff1aSopenharmony_ci s->m.lambda = s->quality; 295cabdff1aSopenharmony_ci s->m.qscale = s->m.lambda * 139 + 296cabdff1aSopenharmony_ci FF_LAMBDA_SCALE * 64 >> 297cabdff1aSopenharmony_ci FF_LAMBDA_SHIFT + 7; 298cabdff1aSopenharmony_ci s->m.lambda2 = s->m.lambda * s->m.lambda + 299cabdff1aSopenharmony_ci FF_LAMBDA_SCALE / 2 >> 300cabdff1aSopenharmony_ci FF_LAMBDA_SHIFT; 301cabdff1aSopenharmony_ci 302cabdff1aSopenharmony_ci if (!s->motion_val8[plane]) { 303cabdff1aSopenharmony_ci s->motion_val8[plane] = av_mallocz((s->m.b8_stride * 304cabdff1aSopenharmony_ci block_height * 2 + 2) * 305cabdff1aSopenharmony_ci 2 * sizeof(int16_t)); 306cabdff1aSopenharmony_ci s->motion_val16[plane] = av_mallocz((s->m.mb_stride * 307cabdff1aSopenharmony_ci (block_height + 2) + 1) * 308cabdff1aSopenharmony_ci 2 * sizeof(int16_t)); 309cabdff1aSopenharmony_ci if (!s->motion_val8[plane] || !s->motion_val16[plane]) 310cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 311cabdff1aSopenharmony_ci } 312cabdff1aSopenharmony_ci 313cabdff1aSopenharmony_ci s->m.mb_type = s->mb_type; 314cabdff1aSopenharmony_ci 315cabdff1aSopenharmony_ci // dummies, to avoid segfaults 316cabdff1aSopenharmony_ci s->m.current_picture.mb_mean = (uint8_t *)s->dummy; 317cabdff1aSopenharmony_ci s->m.current_picture.mb_var = (uint16_t *)s->dummy; 318cabdff1aSopenharmony_ci s->m.current_picture.mc_mb_var = (uint16_t *)s->dummy; 319cabdff1aSopenharmony_ci s->m.current_picture.mb_type = s->dummy; 320cabdff1aSopenharmony_ci 321cabdff1aSopenharmony_ci s->m.current_picture.motion_val[0] = s->motion_val8[plane] + 2; 322cabdff1aSopenharmony_ci s->m.p_mv_table = s->motion_val16[plane] + 323cabdff1aSopenharmony_ci s->m.mb_stride + 1; 324cabdff1aSopenharmony_ci s->m.mecc = s->mecc; // move 325cabdff1aSopenharmony_ci ff_init_me(&s->m); 326cabdff1aSopenharmony_ci 327cabdff1aSopenharmony_ci s->m.me.dia_size = s->avctx->dia_size; 328cabdff1aSopenharmony_ci s->m.first_slice_line = 1; 329cabdff1aSopenharmony_ci for (y = 0; y < block_height; y++) { 330cabdff1aSopenharmony_ci s->m.new_picture->data[0] = src - y * 16 * stride; // ugly 331cabdff1aSopenharmony_ci s->m.mb_y = y; 332cabdff1aSopenharmony_ci 333cabdff1aSopenharmony_ci for (i = 0; i < 16 && i + 16 * y < height; i++) { 334cabdff1aSopenharmony_ci memcpy(&src[i * stride], &src_plane[(i + 16 * y) * src_stride], 335cabdff1aSopenharmony_ci width); 336cabdff1aSopenharmony_ci for (x = width; x < 16 * block_width; x++) 337cabdff1aSopenharmony_ci src[i * stride + x] = src[i * stride + x - 1]; 338cabdff1aSopenharmony_ci } 339cabdff1aSopenharmony_ci for (; i < 16 && i + 16 * y < 16 * block_height; i++) 340cabdff1aSopenharmony_ci memcpy(&src[i * stride], &src[(i - 1) * stride], 341cabdff1aSopenharmony_ci 16 * block_width); 342cabdff1aSopenharmony_ci 343cabdff1aSopenharmony_ci for (x = 0; x < block_width; x++) { 344cabdff1aSopenharmony_ci s->m.mb_x = x; 345cabdff1aSopenharmony_ci init_block_index(&s->m); 346cabdff1aSopenharmony_ci 347cabdff1aSopenharmony_ci ff_estimate_p_frame_motion(&s->m, x, y); 348cabdff1aSopenharmony_ci } 349cabdff1aSopenharmony_ci s->m.first_slice_line = 0; 350cabdff1aSopenharmony_ci } 351cabdff1aSopenharmony_ci 352cabdff1aSopenharmony_ci ff_fix_long_p_mvs(&s->m, CANDIDATE_MB_TYPE_INTRA); 353cabdff1aSopenharmony_ci ff_fix_long_mvs(&s->m, NULL, 0, s->m.p_mv_table, s->m.f_code, 354cabdff1aSopenharmony_ci CANDIDATE_MB_TYPE_INTER, 0); 355cabdff1aSopenharmony_ci } 356cabdff1aSopenharmony_ci 357cabdff1aSopenharmony_ci s->m.first_slice_line = 1; 358cabdff1aSopenharmony_ci for (y = 0; y < block_height; y++) { 359cabdff1aSopenharmony_ci for (i = 0; i < 16 && i + 16 * y < height; i++) { 360cabdff1aSopenharmony_ci memcpy(&src[i * stride], &src_plane[(i + 16 * y) * src_stride], 361cabdff1aSopenharmony_ci width); 362cabdff1aSopenharmony_ci for (x = width; x < 16 * block_width; x++) 363cabdff1aSopenharmony_ci src[i * stride + x] = src[i * stride + x - 1]; 364cabdff1aSopenharmony_ci } 365cabdff1aSopenharmony_ci for (; i < 16 && i + 16 * y < 16 * block_height; i++) 366cabdff1aSopenharmony_ci memcpy(&src[i * stride], &src[(i - 1) * stride], 16 * block_width); 367cabdff1aSopenharmony_ci 368cabdff1aSopenharmony_ci s->m.mb_y = y; 369cabdff1aSopenharmony_ci for (x = 0; x < block_width; x++) { 370cabdff1aSopenharmony_ci uint8_t reorder_buffer[2][6][7 * 32]; 371cabdff1aSopenharmony_ci int count[2][6]; 372cabdff1aSopenharmony_ci int offset = y * 16 * stride + x * 16; 373cabdff1aSopenharmony_ci uint8_t *decoded = decoded_plane + offset; 374cabdff1aSopenharmony_ci uint8_t *ref = ref_plane + offset; 375cabdff1aSopenharmony_ci int score[4] = { 0, 0, 0, 0 }, best; 376cabdff1aSopenharmony_ci uint8_t *temp = s->scratchbuf; 377cabdff1aSopenharmony_ci 378cabdff1aSopenharmony_ci if (put_bytes_left(&s->pb, 0) < 3000) { // FIXME: check size 379cabdff1aSopenharmony_ci av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); 380cabdff1aSopenharmony_ci return -1; 381cabdff1aSopenharmony_ci } 382cabdff1aSopenharmony_ci 383cabdff1aSopenharmony_ci s->m.mb_x = x; 384cabdff1aSopenharmony_ci init_block_index(&s->m); 385cabdff1aSopenharmony_ci 386cabdff1aSopenharmony_ci if (s->pict_type == AV_PICTURE_TYPE_I || 387cabdff1aSopenharmony_ci (s->m.mb_type[x + y * s->m.mb_stride] & 388cabdff1aSopenharmony_ci CANDIDATE_MB_TYPE_INTRA)) { 389cabdff1aSopenharmony_ci for (i = 0; i < 6; i++) 390cabdff1aSopenharmony_ci init_put_bits(&s->reorder_pb[i], reorder_buffer[0][i], 391cabdff1aSopenharmony_ci 7 * 32); 392cabdff1aSopenharmony_ci if (s->pict_type == AV_PICTURE_TYPE_P) { 393cabdff1aSopenharmony_ci const uint8_t *vlc = ff_svq1_block_type_vlc[SVQ1_BLOCK_INTRA]; 394cabdff1aSopenharmony_ci put_bits(&s->reorder_pb[5], vlc[1], vlc[0]); 395cabdff1aSopenharmony_ci score[0] = vlc[1] * lambda; 396cabdff1aSopenharmony_ci } 397cabdff1aSopenharmony_ci score[0] += encode_block(s, src + 16 * x, NULL, temp, stride, 398cabdff1aSopenharmony_ci 5, 64, lambda, 1); 399cabdff1aSopenharmony_ci for (i = 0; i < 6; i++) { 400cabdff1aSopenharmony_ci count[0][i] = put_bits_count(&s->reorder_pb[i]); 401cabdff1aSopenharmony_ci flush_put_bits(&s->reorder_pb[i]); 402cabdff1aSopenharmony_ci } 403cabdff1aSopenharmony_ci } else 404cabdff1aSopenharmony_ci score[0] = INT_MAX; 405cabdff1aSopenharmony_ci 406cabdff1aSopenharmony_ci best = 0; 407cabdff1aSopenharmony_ci 408cabdff1aSopenharmony_ci if (s->pict_type == AV_PICTURE_TYPE_P) { 409cabdff1aSopenharmony_ci const uint8_t *vlc = ff_svq1_block_type_vlc[SVQ1_BLOCK_INTER]; 410cabdff1aSopenharmony_ci int mx, my, pred_x, pred_y, dxy; 411cabdff1aSopenharmony_ci int16_t *motion_ptr; 412cabdff1aSopenharmony_ci 413cabdff1aSopenharmony_ci motion_ptr = ff_h263_pred_motion(&s->m, 0, 0, &pred_x, &pred_y); 414cabdff1aSopenharmony_ci if (s->m.mb_type[x + y * s->m.mb_stride] & 415cabdff1aSopenharmony_ci CANDIDATE_MB_TYPE_INTER) { 416cabdff1aSopenharmony_ci for (i = 0; i < 6; i++) 417cabdff1aSopenharmony_ci init_put_bits(&s->reorder_pb[i], reorder_buffer[1][i], 418cabdff1aSopenharmony_ci 7 * 32); 419cabdff1aSopenharmony_ci 420cabdff1aSopenharmony_ci put_bits(&s->reorder_pb[5], vlc[1], vlc[0]); 421cabdff1aSopenharmony_ci 422cabdff1aSopenharmony_ci s->m.pb = s->reorder_pb[5]; 423cabdff1aSopenharmony_ci mx = motion_ptr[0]; 424cabdff1aSopenharmony_ci my = motion_ptr[1]; 425cabdff1aSopenharmony_ci av_assert1(mx >= -32 && mx <= 31); 426cabdff1aSopenharmony_ci av_assert1(my >= -32 && my <= 31); 427cabdff1aSopenharmony_ci av_assert1(pred_x >= -32 && pred_x <= 31); 428cabdff1aSopenharmony_ci av_assert1(pred_y >= -32 && pred_y <= 31); 429cabdff1aSopenharmony_ci ff_h263_encode_motion(&s->m.pb, mx - pred_x, 1); 430cabdff1aSopenharmony_ci ff_h263_encode_motion(&s->m.pb, my - pred_y, 1); 431cabdff1aSopenharmony_ci s->reorder_pb[5] = s->m.pb; 432cabdff1aSopenharmony_ci score[1] += lambda * put_bits_count(&s->reorder_pb[5]); 433cabdff1aSopenharmony_ci 434cabdff1aSopenharmony_ci dxy = (mx & 1) + 2 * (my & 1); 435cabdff1aSopenharmony_ci 436cabdff1aSopenharmony_ci s->hdsp.put_pixels_tab[0][dxy](temp + 16*stride, 437cabdff1aSopenharmony_ci ref + (mx >> 1) + 438cabdff1aSopenharmony_ci stride * (my >> 1), 439cabdff1aSopenharmony_ci stride, 16); 440cabdff1aSopenharmony_ci 441cabdff1aSopenharmony_ci score[1] += encode_block(s, src + 16 * x, temp + 16*stride, 442cabdff1aSopenharmony_ci decoded, stride, 5, 64, lambda, 0); 443cabdff1aSopenharmony_ci best = score[1] <= score[0]; 444cabdff1aSopenharmony_ci 445cabdff1aSopenharmony_ci vlc = ff_svq1_block_type_vlc[SVQ1_BLOCK_SKIP]; 446cabdff1aSopenharmony_ci score[2] = s->mecc.sse[0](NULL, src + 16 * x, ref, 447cabdff1aSopenharmony_ci stride, 16); 448cabdff1aSopenharmony_ci score[2] += vlc[1] * lambda; 449cabdff1aSopenharmony_ci if (score[2] < score[best] && mx == 0 && my == 0) { 450cabdff1aSopenharmony_ci best = 2; 451cabdff1aSopenharmony_ci s->hdsp.put_pixels_tab[0][0](decoded, ref, stride, 16); 452cabdff1aSopenharmony_ci put_bits(&s->pb, vlc[1], vlc[0]); 453cabdff1aSopenharmony_ci } 454cabdff1aSopenharmony_ci } 455cabdff1aSopenharmony_ci 456cabdff1aSopenharmony_ci if (best == 1) { 457cabdff1aSopenharmony_ci for (i = 0; i < 6; i++) { 458cabdff1aSopenharmony_ci count[1][i] = put_bits_count(&s->reorder_pb[i]); 459cabdff1aSopenharmony_ci flush_put_bits(&s->reorder_pb[i]); 460cabdff1aSopenharmony_ci } 461cabdff1aSopenharmony_ci } else { 462cabdff1aSopenharmony_ci motion_ptr[0] = 463cabdff1aSopenharmony_ci motion_ptr[1] = 464cabdff1aSopenharmony_ci motion_ptr[2] = 465cabdff1aSopenharmony_ci motion_ptr[3] = 466cabdff1aSopenharmony_ci motion_ptr[0 + 2 * s->m.b8_stride] = 467cabdff1aSopenharmony_ci motion_ptr[1 + 2 * s->m.b8_stride] = 468cabdff1aSopenharmony_ci motion_ptr[2 + 2 * s->m.b8_stride] = 469cabdff1aSopenharmony_ci motion_ptr[3 + 2 * s->m.b8_stride] = 0; 470cabdff1aSopenharmony_ci } 471cabdff1aSopenharmony_ci } 472cabdff1aSopenharmony_ci 473cabdff1aSopenharmony_ci s->rd_total += score[best]; 474cabdff1aSopenharmony_ci 475cabdff1aSopenharmony_ci if (best != 2) 476cabdff1aSopenharmony_ci for (i = 5; i >= 0; i--) 477cabdff1aSopenharmony_ci ff_copy_bits(&s->pb, reorder_buffer[best][i], 478cabdff1aSopenharmony_ci count[best][i]); 479cabdff1aSopenharmony_ci if (best == 0) 480cabdff1aSopenharmony_ci s->hdsp.put_pixels_tab[0][0](decoded, temp, stride, 16); 481cabdff1aSopenharmony_ci } 482cabdff1aSopenharmony_ci s->m.first_slice_line = 0; 483cabdff1aSopenharmony_ci } 484cabdff1aSopenharmony_ci return 0; 485cabdff1aSopenharmony_ci} 486cabdff1aSopenharmony_ci 487cabdff1aSopenharmony_cistatic av_cold int svq1_encode_end(AVCodecContext *avctx) 488cabdff1aSopenharmony_ci{ 489cabdff1aSopenharmony_ci SVQ1EncContext *const s = avctx->priv_data; 490cabdff1aSopenharmony_ci int i; 491cabdff1aSopenharmony_ci 492cabdff1aSopenharmony_ci if (avctx->frame_number) 493cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_DEBUG, "RD: %f\n", 494cabdff1aSopenharmony_ci s->rd_total / (double)(avctx->width * avctx->height * 495cabdff1aSopenharmony_ci avctx->frame_number)); 496cabdff1aSopenharmony_ci 497cabdff1aSopenharmony_ci s->m.mb_type = NULL; 498cabdff1aSopenharmony_ci ff_mpv_common_end(&s->m); 499cabdff1aSopenharmony_ci 500cabdff1aSopenharmony_ci av_freep(&s->m.me.scratchpad); 501cabdff1aSopenharmony_ci av_freep(&s->m.me.map); 502cabdff1aSopenharmony_ci av_freep(&s->m.me.score_map); 503cabdff1aSopenharmony_ci av_freep(&s->mb_type); 504cabdff1aSopenharmony_ci av_freep(&s->dummy); 505cabdff1aSopenharmony_ci av_freep(&s->scratchbuf); 506cabdff1aSopenharmony_ci 507cabdff1aSopenharmony_ci for (i = 0; i < 3; i++) { 508cabdff1aSopenharmony_ci av_freep(&s->motion_val8[i]); 509cabdff1aSopenharmony_ci av_freep(&s->motion_val16[i]); 510cabdff1aSopenharmony_ci } 511cabdff1aSopenharmony_ci 512cabdff1aSopenharmony_ci av_frame_free(&s->current_picture); 513cabdff1aSopenharmony_ci av_frame_free(&s->last_picture); 514cabdff1aSopenharmony_ci 515cabdff1aSopenharmony_ci return 0; 516cabdff1aSopenharmony_ci} 517cabdff1aSopenharmony_ci 518cabdff1aSopenharmony_cistatic av_cold int svq1_encode_init(AVCodecContext *avctx) 519cabdff1aSopenharmony_ci{ 520cabdff1aSopenharmony_ci SVQ1EncContext *const s = avctx->priv_data; 521cabdff1aSopenharmony_ci int ret; 522cabdff1aSopenharmony_ci 523cabdff1aSopenharmony_ci if (avctx->width >= 4096 || avctx->height >= 4096) { 524cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Dimensions too large, maximum is 4095x4095\n"); 525cabdff1aSopenharmony_ci return AVERROR(EINVAL); 526cabdff1aSopenharmony_ci } 527cabdff1aSopenharmony_ci 528cabdff1aSopenharmony_ci ff_hpeldsp_init(&s->hdsp, avctx->flags); 529cabdff1aSopenharmony_ci ff_me_cmp_init(&s->mecc, avctx); 530cabdff1aSopenharmony_ci ff_mpegvideoencdsp_init(&s->m.mpvencdsp, avctx); 531cabdff1aSopenharmony_ci 532cabdff1aSopenharmony_ci s->current_picture = av_frame_alloc(); 533cabdff1aSopenharmony_ci s->last_picture = av_frame_alloc(); 534cabdff1aSopenharmony_ci if (!s->current_picture || !s->last_picture) { 535cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 536cabdff1aSopenharmony_ci } 537cabdff1aSopenharmony_ci 538cabdff1aSopenharmony_ci s->frame_width = avctx->width; 539cabdff1aSopenharmony_ci s->frame_height = avctx->height; 540cabdff1aSopenharmony_ci 541cabdff1aSopenharmony_ci s->y_block_width = (s->frame_width + 15) / 16; 542cabdff1aSopenharmony_ci s->y_block_height = (s->frame_height + 15) / 16; 543cabdff1aSopenharmony_ci 544cabdff1aSopenharmony_ci s->c_block_width = (s->frame_width / 4 + 15) / 16; 545cabdff1aSopenharmony_ci s->c_block_height = (s->frame_height / 4 + 15) / 16; 546cabdff1aSopenharmony_ci 547cabdff1aSopenharmony_ci s->avctx = avctx; 548cabdff1aSopenharmony_ci s->m.avctx = avctx; 549cabdff1aSopenharmony_ci 550cabdff1aSopenharmony_ci if ((ret = ff_mpv_common_init(&s->m)) < 0) { 551cabdff1aSopenharmony_ci return ret; 552cabdff1aSopenharmony_ci } 553cabdff1aSopenharmony_ci 554cabdff1aSopenharmony_ci s->m.picture_structure = PICT_FRAME; 555cabdff1aSopenharmony_ci s->m.me.temp = 556cabdff1aSopenharmony_ci s->m.me.scratchpad = av_mallocz((avctx->width + 64) * 557cabdff1aSopenharmony_ci 2 * 16 * 2 * sizeof(uint8_t)); 558cabdff1aSopenharmony_ci s->m.me.map = av_mallocz(ME_MAP_SIZE * sizeof(uint32_t)); 559cabdff1aSopenharmony_ci s->m.me.score_map = av_mallocz(ME_MAP_SIZE * sizeof(uint32_t)); 560cabdff1aSopenharmony_ci s->mb_type = av_mallocz((s->y_block_width + 1) * 561cabdff1aSopenharmony_ci s->y_block_height * sizeof(int16_t)); 562cabdff1aSopenharmony_ci s->dummy = av_mallocz((s->y_block_width + 1) * 563cabdff1aSopenharmony_ci s->y_block_height * sizeof(int32_t)); 564cabdff1aSopenharmony_ci s->ssd_int8_vs_int16 = ssd_int8_vs_int16_c; 565cabdff1aSopenharmony_ci 566cabdff1aSopenharmony_ci if (!s->m.me.temp || !s->m.me.scratchpad || !s->m.me.map || 567cabdff1aSopenharmony_ci !s->m.me.score_map || !s->mb_type || !s->dummy) { 568cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 569cabdff1aSopenharmony_ci } 570cabdff1aSopenharmony_ci 571cabdff1aSopenharmony_ci#if ARCH_PPC 572cabdff1aSopenharmony_ci ff_svq1enc_init_ppc(s); 573cabdff1aSopenharmony_ci#elif ARCH_X86 574cabdff1aSopenharmony_ci ff_svq1enc_init_x86(s); 575cabdff1aSopenharmony_ci#endif 576cabdff1aSopenharmony_ci 577cabdff1aSopenharmony_ci ff_h263_encode_init(&s->m); // mv_penalty 578cabdff1aSopenharmony_ci 579cabdff1aSopenharmony_ci return 0; 580cabdff1aSopenharmony_ci} 581cabdff1aSopenharmony_ci 582cabdff1aSopenharmony_cistatic int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, 583cabdff1aSopenharmony_ci const AVFrame *pict, int *got_packet) 584cabdff1aSopenharmony_ci{ 585cabdff1aSopenharmony_ci SVQ1EncContext *const s = avctx->priv_data; 586cabdff1aSopenharmony_ci int i, ret; 587cabdff1aSopenharmony_ci 588cabdff1aSopenharmony_ci ret = ff_alloc_packet(avctx, pkt, s->y_block_width * s->y_block_height * 589cabdff1aSopenharmony_ci MAX_MB_BYTES * 3 + AV_INPUT_BUFFER_MIN_SIZE); 590cabdff1aSopenharmony_ci if (ret < 0) 591cabdff1aSopenharmony_ci return ret; 592cabdff1aSopenharmony_ci 593cabdff1aSopenharmony_ci if (avctx->pix_fmt != AV_PIX_FMT_YUV410P) { 594cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n"); 595cabdff1aSopenharmony_ci return -1; 596cabdff1aSopenharmony_ci } 597cabdff1aSopenharmony_ci 598cabdff1aSopenharmony_ci if (!s->current_picture->data[0]) { 599cabdff1aSopenharmony_ci if ((ret = ff_encode_alloc_frame(avctx, s->current_picture)) < 0) { 600cabdff1aSopenharmony_ci return ret; 601cabdff1aSopenharmony_ci } 602cabdff1aSopenharmony_ci } 603cabdff1aSopenharmony_ci if (!s->last_picture->data[0]) { 604cabdff1aSopenharmony_ci ret = ff_encode_alloc_frame(avctx, s->last_picture); 605cabdff1aSopenharmony_ci if (ret < 0) 606cabdff1aSopenharmony_ci return ret; 607cabdff1aSopenharmony_ci } 608cabdff1aSopenharmony_ci if (!s->scratchbuf) { 609cabdff1aSopenharmony_ci s->scratchbuf = av_malloc_array(s->current_picture->linesize[0], 16 * 3); 610cabdff1aSopenharmony_ci if (!s->scratchbuf) 611cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 612cabdff1aSopenharmony_ci } 613cabdff1aSopenharmony_ci 614cabdff1aSopenharmony_ci FFSWAP(AVFrame*, s->current_picture, s->last_picture); 615cabdff1aSopenharmony_ci 616cabdff1aSopenharmony_ci init_put_bits(&s->pb, pkt->data, pkt->size); 617cabdff1aSopenharmony_ci 618cabdff1aSopenharmony_ci if (avctx->gop_size && (avctx->frame_number % avctx->gop_size)) 619cabdff1aSopenharmony_ci s->pict_type = AV_PICTURE_TYPE_P; 620cabdff1aSopenharmony_ci else 621cabdff1aSopenharmony_ci s->pict_type = AV_PICTURE_TYPE_I; 622cabdff1aSopenharmony_ci s->quality = pict->quality; 623cabdff1aSopenharmony_ci 624cabdff1aSopenharmony_ci ff_side_data_set_encoder_stats(pkt, pict->quality, NULL, 0, s->pict_type); 625cabdff1aSopenharmony_ci 626cabdff1aSopenharmony_ci svq1_write_header(s, s->pict_type); 627cabdff1aSopenharmony_ci for (i = 0; i < 3; i++) { 628cabdff1aSopenharmony_ci int ret = svq1_encode_plane(s, i, 629cabdff1aSopenharmony_ci pict->data[i], 630cabdff1aSopenharmony_ci s->last_picture->data[i], 631cabdff1aSopenharmony_ci s->current_picture->data[i], 632cabdff1aSopenharmony_ci s->frame_width / (i ? 4 : 1), 633cabdff1aSopenharmony_ci s->frame_height / (i ? 4 : 1), 634cabdff1aSopenharmony_ci pict->linesize[i], 635cabdff1aSopenharmony_ci s->current_picture->linesize[i]); 636cabdff1aSopenharmony_ci emms_c(); 637cabdff1aSopenharmony_ci if (ret < 0) { 638cabdff1aSopenharmony_ci int j; 639cabdff1aSopenharmony_ci for (j = 0; j < i; j++) { 640cabdff1aSopenharmony_ci av_freep(&s->motion_val8[j]); 641cabdff1aSopenharmony_ci av_freep(&s->motion_val16[j]); 642cabdff1aSopenharmony_ci } 643cabdff1aSopenharmony_ci av_freep(&s->scratchbuf); 644cabdff1aSopenharmony_ci return -1; 645cabdff1aSopenharmony_ci } 646cabdff1aSopenharmony_ci } 647cabdff1aSopenharmony_ci 648cabdff1aSopenharmony_ci // align_put_bits(&s->pb); 649cabdff1aSopenharmony_ci while (put_bits_count(&s->pb) & 31) 650cabdff1aSopenharmony_ci put_bits(&s->pb, 1, 0); 651cabdff1aSopenharmony_ci 652cabdff1aSopenharmony_ci flush_put_bits(&s->pb); 653cabdff1aSopenharmony_ci 654cabdff1aSopenharmony_ci pkt->size = put_bytes_output(&s->pb); 655cabdff1aSopenharmony_ci if (s->pict_type == AV_PICTURE_TYPE_I) 656cabdff1aSopenharmony_ci pkt->flags |= AV_PKT_FLAG_KEY; 657cabdff1aSopenharmony_ci *got_packet = 1; 658cabdff1aSopenharmony_ci 659cabdff1aSopenharmony_ci return 0; 660cabdff1aSopenharmony_ci} 661cabdff1aSopenharmony_ci 662cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(struct SVQ1EncContext, x) 663cabdff1aSopenharmony_ci#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM 664cabdff1aSopenharmony_cistatic const AVOption options[] = { 665cabdff1aSopenharmony_ci { "motion-est", "Motion estimation algorithm", OFFSET(motion_est), AV_OPT_TYPE_INT, { .i64 = FF_ME_EPZS }, FF_ME_ZERO, FF_ME_XONE, VE, "motion-est"}, 666cabdff1aSopenharmony_ci { "zero", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_ZERO }, 0, 0, FF_MPV_OPT_FLAGS, "motion-est" }, 667cabdff1aSopenharmony_ci { "epzs", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_EPZS }, 0, 0, FF_MPV_OPT_FLAGS, "motion-est" }, 668cabdff1aSopenharmony_ci { "xone", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_XONE }, 0, 0, FF_MPV_OPT_FLAGS, "motion-est" }, 669cabdff1aSopenharmony_ci 670cabdff1aSopenharmony_ci { NULL }, 671cabdff1aSopenharmony_ci}; 672cabdff1aSopenharmony_ci 673cabdff1aSopenharmony_cistatic const AVClass svq1enc_class = { 674cabdff1aSopenharmony_ci .class_name = "svq1enc", 675cabdff1aSopenharmony_ci .item_name = av_default_item_name, 676cabdff1aSopenharmony_ci .option = options, 677cabdff1aSopenharmony_ci .version = LIBAVUTIL_VERSION_INT, 678cabdff1aSopenharmony_ci}; 679cabdff1aSopenharmony_ci 680cabdff1aSopenharmony_ciconst FFCodec ff_svq1_encoder = { 681cabdff1aSopenharmony_ci .p.name = "svq1", 682cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 1 / Sorenson Video 1 / SVQ1"), 683cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 684cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_SVQ1, 685cabdff1aSopenharmony_ci .priv_data_size = sizeof(SVQ1EncContext), 686cabdff1aSopenharmony_ci .p.priv_class = &svq1enc_class, 687cabdff1aSopenharmony_ci .init = svq1_encode_init, 688cabdff1aSopenharmony_ci FF_CODEC_ENCODE_CB(svq1_encode_frame), 689cabdff1aSopenharmony_ci .close = svq1_encode_end, 690cabdff1aSopenharmony_ci .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV410P, 691cabdff1aSopenharmony_ci AV_PIX_FMT_NONE }, 692cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, 693cabdff1aSopenharmony_ci}; 694