⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 svq1enc.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * SVQ1 Encoder * Copyright (C) 2004 Mike Melanson <melanson@pcisys.net> * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *//** * @file svq1enc.c * Sorenson Vector Quantizer #1 (SVQ1) video codec. * For more information of the SVQ1 algorithm, visit: *   http://www.pcisys.net/~melanson/codecs/ */#include "avcodec.h"#include "dsputil.h"#include "mpegvideo.h"#include "svq1.h"#include "svq1enc_cb.h"#undef NDEBUG#include <assert.h>typedef struct SVQ1Context {    MpegEncContext m; // needed for motion estimation, should not be used for anything else, the idea is to make the motion estimation eventually independent of MpegEncContext, so this will be removed then (FIXME/XXX)    AVCodecContext *avctx;    DSPContext dsp;    AVFrame picture;    AVFrame current_picture;    AVFrame last_picture;    PutBitContext pb;    GetBitContext gb;    PutBitContext reorder_pb[6]; //why ooh why this sick breadth first order, everything is slower and more complex    int frame_width;    int frame_height;    /* Y plane block dimensions */    int y_block_width;    int y_block_height;    /* U & V plane (C planes) block dimensions */    int c_block_width;    int c_block_height;    uint16_t *mb_type;    uint32_t *dummy;    int16_t (*motion_val8[3])[2];    int16_t (*motion_val16[3])[2];    int64_t rd_total;} SVQ1Context;static void svq1_write_header(SVQ1Context *s, int frame_type){    int i;    /* frame code */    put_bits(&s->pb, 22, 0x20);    /* temporal reference (sure hope this is a "don't care") */    put_bits(&s->pb, 8, 0x00);    /* frame type */    put_bits(&s->pb, 2, frame_type - 1);    if (frame_type == I_TYPE) {        /* no checksum since frame code is 0x20 */        /* no embedded string either */        /* output 5 unknown bits (2 + 2 + 1) */        put_bits(&s->pb, 5, 2); /* 2 needed by quicktime decoder */        for (i = 0; i < 7; i++)        {            if ((ff_svq1_frame_size_table[i].width == s->frame_width) &&                (ff_svq1_frame_size_table[i].height == s->frame_height))            {                put_bits(&s->pb, 3, i);                break;            }        }        if (i == 7)        {            put_bits(&s->pb, 3, 7);                put_bits(&s->pb, 12, s->frame_width);                put_bits(&s->pb, 12, s->frame_height);        }    }    /* no checksum or extra data (next 2 bits get 0) */    put_bits(&s->pb, 2, 0);}#define QUALITY_THRESHOLD 100#define THRESHOLD_MULTIPLIER 0.6#if defined(HAVE_ALTIVEC)#undef vector#endifstatic int encode_block(SVQ1Context *s, uint8_t *src, uint8_t *ref, uint8_t *decoded, int stride, int level, int threshold, int lambda, int intra){    int count, y, x, i, j, split, best_mean, best_score, best_count;    int best_vector[6];    int block_sum[7]= {0, 0, 0, 0, 0, 0};    int w= 2<<((level+2)>>1);    int h= 2<<((level+1)>>1);    int size=w*h;    int16_t block[7][256];    const int8_t *codebook_sum, *codebook;    const uint16_t (*mean_vlc)[2];    const uint8_t (*multistage_vlc)[2];    best_score=0;    //FIXME optimize, this doenst need to be done multiple times    if(intra){        codebook_sum= svq1_intra_codebook_sum[level];        codebook= ff_svq1_intra_codebooks[level];        mean_vlc= ff_svq1_intra_mean_vlc;        multistage_vlc= ff_svq1_intra_multistage_vlc[level];        for(y=0; y<h; y++){            for(x=0; x<w; x++){                int v= src[x + y*stride];                block[0][x + w*y]= v;                best_score += v*v;                block_sum[0] += v;            }        }    }else{        codebook_sum= svq1_inter_codebook_sum[level];        codebook= ff_svq1_inter_codebooks[level];        mean_vlc= ff_svq1_inter_mean_vlc + 256;        multistage_vlc= ff_svq1_inter_multistage_vlc[level];        for(y=0; y<h; y++){            for(x=0; x<w; x++){                int v= src[x + y*stride] - ref[x + y*stride];                block[0][x + w*y]= v;                best_score += v*v;                block_sum[0] += v;            }        }    }    best_count=0;    best_score -= ((block_sum[0]*block_sum[0])>>(level+3));    best_mean= (block_sum[0] + (size>>1)) >> (level+3);    if(level<4){        for(count=1; count<7; count++){            int best_vector_score= INT_MAX;            int best_vector_sum=-999, best_vector_mean=-999;            const int stage= count-1;            const int8_t *vector;            for(i=0; i<16; i++){                int sum= codebook_sum[stage*16 + i];                int sqr, diff, score;                vector = codebook + stage*size*16 + i*size;                sqr = s->dsp.ssd_int8_vs_int16(vector, block[stage], size);                diff= block_sum[stage] - sum;                score= sqr - ((diff*(int64_t)diff)>>(level+3)); //FIXME 64bit slooow                if(score < best_vector_score){                    int mean= (diff + (size>>1)) >> (level+3);                    assert(mean >-300 && mean<300);                    mean= av_clip(mean, intra?0:-256, 255);                    best_vector_score= score;                    best_vector[stage]= i;                    best_vector_sum= sum;                    best_vector_mean= mean;                }            }            assert(best_vector_mean != -999);            vector= codebook + stage*size*16 + best_vector[stage]*size;            for(j=0; j<size; j++){                block[stage+1][j] = block[stage][j] - vector[j];            }            block_sum[stage+1]= block_sum[stage] - best_vector_sum;            best_vector_score +=                lambda*(+ 1 + 4*count                        + multistage_vlc[1+count][1]                        + mean_vlc[best_vector_mean][1]);            if(best_vector_score < best_score){                best_score= best_vector_score;                best_count= count;                best_mean= best_vector_mean;            }        }    }    split=0;    if(best_score > threshold && level){        int score=0;        int offset= (level&1) ? stride*h/2 : w/2;        PutBitContext backup[6];        for(i=level-1; i>=0; i--){            backup[i]= s->reorder_pb[i];        }        score += encode_block(s, src         , ref         , decoded         , stride, level-1, threshold>>1, lambda, intra);        score += encode_block(s, src + offset, ref + offset, decoded + offset, stride, level-1, threshold>>1, lambda, intra);        score += lambda;        if(score < best_score){            best_score= score;            split=1;        }else{            for(i=level-1; i>=0; i--){                s->reorder_pb[i]= backup[i];            }        }    }    if (level > 0)        put_bits(&s->reorder_pb[level], 1, split);    if(!split){        assert((best_mean >= 0 && best_mean<256) || !intra);        assert(best_mean >= -256 && best_mean<256);        assert(best_count >=0 && best_count<7);        assert(level<4 || best_count==0);        /* output the encoding */        put_bits(&s->reorder_pb[level],            multistage_vlc[1 + best_count][1],            multistage_vlc[1 + best_count][0]);        put_bits(&s->reorder_pb[level], mean_vlc[best_mean][1],            mean_vlc[best_mean][0]);        for (i = 0; i < best_count; i++){            assert(best_vector[i]>=0 && best_vector[i]<16);            put_bits(&s->reorder_pb[level], 4, best_vector[i]);        }        for(y=0; y<h; y++){            for(x=0; x<w; x++){                decoded[x + y*stride]= src[x + y*stride] - block[best_count][x + w*y] + best_mean;            }        }    }    return best_score;}static int svq1_encode_plane(SVQ1Context *s, int plane, unsigned char *src_plane, unsigned char *ref_plane, unsigned char *decoded_plane,    int width, int height, int src_stride, int stride){    int x, y;    int i;    int block_width, block_height;    int level;    int threshold[6];    const int lambda= (s->picture.quality*s->picture.quality) >> (2*FF_LAMBDA_SHIFT);    /* figure out the acceptable level thresholds in advance */    threshold[5] = QUALITY_THRESHOLD;    for (level = 4; level >= 0; level--)        threshold[level] = threshold[level + 1] * THRESHOLD_MULTIPLIER;    block_width = (width + 15) / 16;    block_height = (height + 15) / 16;    if(s->picture.pict_type == P_TYPE){        s->m.avctx= s->avctx;        s->m.current_picture_ptr= &s->m.current_picture;        s->m.last_picture_ptr   = &s->m.last_picture;        s->m.last_picture.data[0]= ref_plane;        s->m.linesize=        s->m.last_picture.linesize[0]=        s->m.new_picture.linesize[0]=        s->m.current_picture.linesize[0]= stride;        s->m.width= width;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -