1/* 2 * MQ-coder encoder 3 * Copyright (c) 2007 Kamil Nowosad 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/** 23 * MQ-coder encoder 24 * @file 25 * @author Kamil Nowosad 26 */ 27 28#include <string.h> 29 30#include "libavutil/avassert.h" 31#include "mqc.h" 32 33static void byteout(MqcState *mqc) 34{ 35retry: 36 if (*mqc->bp == 0xff){ 37 mqc->bp++; 38 *mqc->bp = mqc->c >> 20; 39 mqc->c &= 0xfffff; 40 mqc->ct = 7; 41 } else if ((mqc->c & 0x8000000)){ 42 (*mqc->bp)++; 43 mqc->c &= 0x7ffffff; 44 goto retry; 45 } else{ 46 mqc->bp++; 47 *mqc->bp = mqc->c >> 19; 48 mqc->c &= 0x7ffff; 49 mqc->ct = 8; 50 } 51} 52 53static void renorme(MqcState *mqc) 54{ 55 do{ 56 mqc->a += mqc->a; 57 mqc->c += mqc->c; 58 if (!--mqc->ct) 59 byteout(mqc); 60 } while (!(mqc->a & 0x8000)); 61} 62 63static void setbits(MqcState *mqc) 64{ 65 int tmp = mqc->c + mqc->a; 66 mqc->c |= 0xffff; 67 if (mqc->c >= tmp) 68 mqc->c -= 0x8000; 69} 70 71void ff_mqc_initenc(MqcState *mqc, uint8_t *bp) 72{ 73 ff_mqc_init_contexts(mqc); 74 mqc->a = 0x8000; 75 mqc->c = 0; 76 mqc->bp = bp-1; 77 mqc->bpstart = bp; 78 mqc->ct = 12 + (*mqc->bp == 0xff); 79} 80 81void ff_mqc_encode(MqcState *mqc, uint8_t *cxstate, int d) 82{ 83 int qe; 84 85 qe = ff_mqc_qe[*cxstate]; 86 mqc->a -= qe; 87 if ((*cxstate & 1) == d){ 88 if (!(mqc->a & 0x8000)){ 89 if (mqc->a < qe) 90 mqc->a = qe; 91 else 92 mqc->c += qe; 93 *cxstate = ff_mqc_nmps[*cxstate]; 94 renorme(mqc); 95 } else 96 mqc->c += qe; 97 } else{ 98 if (mqc->a < qe) 99 mqc->c += qe; 100 else 101 mqc->a = qe; 102 *cxstate = ff_mqc_nlps[*cxstate]; 103 renorme(mqc); 104 } 105} 106 107static int mqc_flush(MqcState *mqc) 108{ 109 setbits(mqc); 110 mqc->c = mqc->c << mqc->ct; 111 byteout(mqc); 112 mqc->c = mqc->c << mqc->ct; 113 byteout(mqc); 114 if (*mqc->bp != 0xff) 115 mqc->bp++; 116 return mqc->bp - mqc->bpstart; 117} 118 119int ff_mqc_flush_to(MqcState *mqc, uint8_t *dst, int *dst_len) 120{ 121 MqcState mqc2 = *mqc; 122 mqc2.bpstart= 123 mqc2.bp = dst; 124 *mqc2.bp = *mqc->bp; 125 mqc_flush(&mqc2); 126 *dst_len = mqc2.bp - dst; 127 if (mqc->bp < mqc->bpstart) { 128 av_assert1(mqc->bpstart - mqc->bp == 1); 129 av_assert1(*dst_len > 0); 130 av_assert1(mqc->bp[0] == 0 && dst[0] == 0); 131 (*dst_len) --; 132 memmove(dst, dst+1, *dst_len); 133 return mqc->bp - mqc->bpstart + 1 + *dst_len; 134 } 135 return mqc->bp - mqc->bpstart + *dst_len; 136} 137