yading@10: /* yading@10: * FFV1 codec for libavcodec yading@10: * yading@10: * Copyright (c) 2003-2012 Michael Niedermayer yading@10: * yading@10: * This file is part of FFmpeg. yading@10: * yading@10: * FFmpeg is free software; you can redistribute it and/or yading@10: * modify it under the terms of the GNU Lesser General Public yading@10: * License as published by the Free Software Foundation; either yading@10: * version 2.1 of the License, or (at your option) any later version. yading@10: * yading@10: * FFmpeg is distributed in the hope that it will be useful, yading@10: * but WITHOUT ANY WARRANTY; without even the implied warranty of yading@10: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU yading@10: * Lesser General Public License for more details. yading@10: * yading@10: * You should have received a copy of the GNU Lesser General Public yading@10: * License along with FFmpeg; if not, write to the Free Software yading@10: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA yading@10: */ yading@10: yading@10: #ifndef AVCODEC_FFV1_H yading@10: #define AVCODEC_FFV1_H yading@10: yading@10: /** yading@10: * @file yading@10: * FF Video Codec 1 (a lossless codec) yading@10: */ yading@10: yading@10: #include "libavutil/avassert.h" yading@10: #include "libavutil/crc.h" yading@10: #include "libavutil/opt.h" yading@10: #include "libavutil/imgutils.h" yading@10: #include "libavutil/pixdesc.h" yading@10: #include "libavutil/timer.h" yading@10: #include "avcodec.h" yading@10: #include "dsputil.h" yading@10: #include "get_bits.h" yading@10: #include "internal.h" yading@10: #include "mathops.h" yading@10: #include "put_bits.h" yading@10: #include "rangecoder.h" yading@10: yading@10: #ifdef __INTEL_COMPILER yading@10: #undef av_flatten yading@10: #define av_flatten yading@10: #endif yading@10: yading@10: #define MAX_PLANES 4 yading@10: #define CONTEXT_SIZE 32 yading@10: yading@10: #define MAX_QUANT_TABLES 8 yading@10: #define MAX_CONTEXT_INPUTS 5 yading@10: yading@10: extern const uint8_t ff_log2_run[41]; yading@10: yading@10: typedef struct VlcState { yading@10: int16_t drift; yading@10: uint16_t error_sum; yading@10: int8_t bias; yading@10: uint8_t count; yading@10: } VlcState; yading@10: yading@10: typedef struct PlaneContext { yading@10: int16_t quant_table[MAX_CONTEXT_INPUTS][256]; yading@10: int quant_table_index; yading@10: int context_count; yading@10: uint8_t (*state)[CONTEXT_SIZE]; yading@10: VlcState *vlc_state; yading@10: uint8_t interlace_bit_state[2]; yading@10: } PlaneContext; yading@10: yading@10: #define MAX_SLICES 256 yading@10: yading@10: typedef struct FFV1Context { yading@10: AVClass *class; yading@10: AVCodecContext *avctx; yading@10: RangeCoder c; yading@10: GetBitContext gb; yading@10: PutBitContext pb; yading@10: uint64_t rc_stat[256][2]; yading@10: uint64_t (*rc_stat2[MAX_QUANT_TABLES])[32][2]; yading@10: int version; yading@10: int minor_version; yading@10: int width, height; yading@10: int chroma_planes; yading@10: int chroma_h_shift, chroma_v_shift; yading@10: int transparency; yading@10: int flags; yading@10: int picture_number; yading@10: AVFrame picture, last_picture; yading@10: yading@10: AVFrame *cur; yading@10: int plane_count; yading@10: int ac; ///< 1=range coder <-> 0=golomb rice yading@10: int ac_byte_count; ///< number of bytes used for AC coding yading@10: PlaneContext plane[MAX_PLANES]; yading@10: int16_t quant_table[MAX_CONTEXT_INPUTS][256]; yading@10: int16_t quant_tables[MAX_QUANT_TABLES][MAX_CONTEXT_INPUTS][256]; yading@10: int context_count[MAX_QUANT_TABLES]; yading@10: uint8_t state_transition[256]; yading@10: uint8_t (*initial_states[MAX_QUANT_TABLES])[32]; yading@10: int run_index; yading@10: int colorspace; yading@10: int16_t *sample_buffer; yading@10: yading@10: int ec; yading@10: int slice_damaged; yading@10: int key_frame_ok; yading@10: yading@10: int bits_per_raw_sample; yading@10: int packed_at_lsb; yading@10: yading@10: int gob_count; yading@10: int quant_table_count; yading@10: yading@10: DSPContext dsp; yading@10: yading@10: struct FFV1Context *slice_context[MAX_SLICES]; yading@10: int slice_count; yading@10: int num_v_slices; yading@10: int num_h_slices; yading@10: int slice_width; yading@10: int slice_height; yading@10: int slice_x; yading@10: int slice_y; yading@10: } FFV1Context; yading@10: yading@10: int ffv1_common_init(AVCodecContext *avctx); yading@10: int ffv1_init_slice_state(FFV1Context *f, FFV1Context *fs); yading@10: int ffv1_init_slices_state(FFV1Context *f); yading@10: int ffv1_init_slice_contexts(FFV1Context *f); yading@10: int ffv1_allocate_initial_states(FFV1Context *f); yading@10: void ffv1_clear_slice_state(FFV1Context *f, FFV1Context *fs); yading@10: int ffv1_close(AVCodecContext *avctx); yading@10: yading@10: static av_always_inline int fold(int diff, int bits) yading@10: { yading@10: if (bits == 8) yading@10: diff = (int8_t)diff; yading@10: else { yading@10: diff += 1 << (bits - 1); yading@10: diff &= (1 << bits) - 1; yading@10: diff -= 1 << (bits - 1); yading@10: } yading@10: yading@10: return diff; yading@10: } yading@10: yading@10: static inline int predict(int16_t *src, int16_t *last) yading@10: { yading@10: const int LT = last[-1]; yading@10: const int T = last[0]; yading@10: const int L = src[-1]; yading@10: yading@10: return mid_pred(L, L + T - LT, T); yading@10: } yading@10: yading@10: static inline int get_context(PlaneContext *p, int16_t *src, yading@10: int16_t *last, int16_t *last2) yading@10: { yading@10: const int LT = last[-1]; yading@10: const int T = last[0]; yading@10: const int RT = last[1]; yading@10: const int L = src[-1]; yading@10: yading@10: if (p->quant_table[3][127]) { yading@10: const int TT = last2[0]; yading@10: const int LL = src[-2]; yading@10: return p->quant_table[0][(L - LT) & 0xFF] + yading@10: p->quant_table[1][(LT - T) & 0xFF] + yading@10: p->quant_table[2][(T - RT) & 0xFF] + yading@10: p->quant_table[3][(LL - L) & 0xFF] + yading@10: p->quant_table[4][(TT - T) & 0xFF]; yading@10: } else yading@10: return p->quant_table[0][(L - LT) & 0xFF] + yading@10: p->quant_table[1][(LT - T) & 0xFF] + yading@10: p->quant_table[2][(T - RT) & 0xFF]; yading@10: } yading@10: yading@10: static inline void update_vlc_state(VlcState *const state, const int v) yading@10: { yading@10: int drift = state->drift; yading@10: int count = state->count; yading@10: state->error_sum += FFABS(v); yading@10: drift += v; yading@10: yading@10: if (count == 128) { // FIXME: variable yading@10: count >>= 1; yading@10: drift >>= 1; yading@10: state->error_sum >>= 1; yading@10: } yading@10: count++; yading@10: yading@10: if (drift <= -count) { yading@10: if (state->bias > -128) yading@10: state->bias--; yading@10: yading@10: drift += count; yading@10: if (drift <= -count) yading@10: drift = -count + 1; yading@10: } else if (drift > 0) { yading@10: if (state->bias < 127) yading@10: state->bias++; yading@10: yading@10: drift -= count; yading@10: if (drift > 0) yading@10: drift = 0; yading@10: } yading@10: yading@10: state->drift = drift; yading@10: state->count = count; yading@10: } yading@10: yading@10: #endif /* AVCODEC_FFV1_H */