Revision b2755007 libavcodec/bitstream.h

View differences:

libavcodec/bitstream.h
39 39
#   define ALT_BITSTREAM_READER
40 40
#endif
41 41

  
42
//#define ALT_BITSTREAM_WRITER
43
//#define ALIGNED_BITSTREAM_WRITER
44 42
#if !defined(LIBMPEG2_BITSTREAM_READER) && !defined(A32_BITSTREAM_READER) && !defined(ALT_BITSTREAM_READER)
45 43
#   if ARCH_ARM
46 44
#       define A32_BITSTREAM_READER
......
74 72
#    define NEG_USR32(a,s) (((uint32_t)(a))>>(32-(s)))
75 73
#endif
76 74

  
77
/* bit output */
78

  
79
/* buf and buf_end must be present and used by every alternative writer. */
80
typedef struct PutBitContext {
81
#ifdef ALT_BITSTREAM_WRITER
82
    uint8_t *buf, *buf_end;
83
    int index;
84
#else
85
    uint32_t bit_buf;
86
    int bit_left;
87
    uint8_t *buf, *buf_ptr, *buf_end;
88
#endif
89
    int size_in_bits;
90
} PutBitContext;
91

  
92
/**
93
 * Initializes the PutBitContext \p s.
94
 *
95
 * @param buffer the buffer where to put bits
96
 * @param buffer_size the size in bytes of \p buffer
97
 */
98
static inline void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size)
99
{
100
    if(buffer_size < 0) {
101
        buffer_size = 0;
102
        buffer = NULL;
103
    }
104

  
105
    s->size_in_bits= 8*buffer_size;
106
    s->buf = buffer;
107
    s->buf_end = s->buf + buffer_size;
108
#ifdef ALT_BITSTREAM_WRITER
109
    s->index=0;
110
    ((uint32_t*)(s->buf))[0]=0;
111
//    memset(buffer, 0, buffer_size);
112
#else
113
    s->buf_ptr = s->buf;
114
    s->bit_left=32;
115
    s->bit_buf=0;
116
#endif
117
}
118

  
119
/**
120
 * Returns the total number of bits written to the bitstream.
121
 */
122
static inline int put_bits_count(PutBitContext *s)
123
{
124
#ifdef ALT_BITSTREAM_WRITER
125
    return s->index;
126
#else
127
    return (s->buf_ptr - s->buf) * 8 + 32 - s->bit_left;
128
#endif
129
}
130

  
131
/**
132
 * Pads the end of the output stream with zeros.
133
 */
134
static inline void flush_put_bits(PutBitContext *s)
135
{
136
#ifdef ALT_BITSTREAM_WRITER
137
    align_put_bits(s);
138
#else
139
#ifndef BITSTREAM_WRITER_LE
140
    s->bit_buf<<= s->bit_left;
141
#endif
142
    while (s->bit_left < 32) {
143
        /* XXX: should test end of buffer */
144
#ifdef BITSTREAM_WRITER_LE
145
        *s->buf_ptr++=s->bit_buf;
146
        s->bit_buf>>=8;
147
#else
148
        *s->buf_ptr++=s->bit_buf >> 24;
149
        s->bit_buf<<=8;
150
#endif
151
        s->bit_left+=8;
152
    }
153
    s->bit_left=32;
154
    s->bit_buf=0;
155
#endif
156
}
157

  
158
/**
159
 * Pads the bitstream with zeros up to the next byte boundary.
160
 */
161
void align_put_bits(PutBitContext *s);
162

  
163
/**
164
 * Puts the string \p s in the bitstream.
165
 *
166
 * @param terminate_string 0-terminates the written string if value is 1
167
 */
168
void ff_put_string(PutBitContext * pbc, const char *s, int terminate_string);
169

  
170
/**
171
 * Copies the content of \p src to the bitstream.
172
 *
173
 * @param length the number of bits of \p src to copy
174
 */
175
void ff_copy_bits(PutBitContext *pb, const uint8_t *src, int length);
176

  
177 75
/* bit input */
178 76
/* buffer, buffer_end and size_in_bits must be present and used by every reader */
179 77
typedef struct GetBitContext {
......
207 105
    uint8_t run;
208 106
} RL_VLC_ELEM;
209 107

  
210
static inline void put_bits(PutBitContext *s, int n, unsigned int value)
211
#ifndef ALT_BITSTREAM_WRITER
212
{
213
    unsigned int bit_buf;
214
    int bit_left;
215

  
216
    //    printf("put_bits=%d %x\n", n, value);
217
    assert(n == 32 || value < (1U << n));
218

  
219
    bit_buf = s->bit_buf;
220
    bit_left = s->bit_left;
221

  
222
    //    printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf);
223
    /* XXX: optimize */
224
#ifdef BITSTREAM_WRITER_LE
225
    bit_buf |= value << (32 - bit_left);
226
    if (n >= bit_left) {
227
#if !HAVE_FAST_UNALIGNED
228
        if (3 & (intptr_t) s->buf_ptr) {
229
            AV_WL32(s->buf_ptr, bit_buf);
230
        } else
231
#endif
232
        *(uint32_t *)s->buf_ptr = le2me_32(bit_buf);
233
        s->buf_ptr+=4;
234
        bit_buf = (bit_left==32)?0:value >> bit_left;
235
        bit_left+=32;
236
    }
237
    bit_left-=n;
238
#else
239
    if (n < bit_left) {
240
        bit_buf = (bit_buf<<n) | value;
241
        bit_left-=n;
242
    } else {
243
        bit_buf<<=bit_left;
244
        bit_buf |= value >> (n - bit_left);
245
#if !HAVE_FAST_UNALIGNED
246
        if (3 & (intptr_t) s->buf_ptr) {
247
            AV_WB32(s->buf_ptr, bit_buf);
248
        } else
249
#endif
250
        *(uint32_t *)s->buf_ptr = be2me_32(bit_buf);
251
        //printf("bitbuf = %08x\n", bit_buf);
252
        s->buf_ptr+=4;
253
        bit_left+=32 - n;
254
        bit_buf = value;
255
    }
256
#endif
257

  
258
    s->bit_buf = bit_buf;
259
    s->bit_left = bit_left;
260
}
261
#else  /* ALT_BITSTREAM_WRITER defined */
262
{
263
#    ifdef ALIGNED_BITSTREAM_WRITER
264
#        if ARCH_X86
265
    __asm__ volatile(
266
        "movl %0, %%ecx                 \n\t"
267
        "xorl %%eax, %%eax              \n\t"
268
        "shrdl %%cl, %1, %%eax          \n\t"
269
        "shrl %%cl, %1                  \n\t"
270
        "movl %0, %%ecx                 \n\t"
271
        "shrl $3, %%ecx                 \n\t"
272
        "andl $0xFFFFFFFC, %%ecx        \n\t"
273
        "bswapl %1                      \n\t"
274
        "orl %1, (%2, %%ecx)            \n\t"
275
        "bswapl %%eax                   \n\t"
276
        "addl %3, %0                    \n\t"
277
        "movl %%eax, 4(%2, %%ecx)       \n\t"
278
        : "=&r" (s->index), "=&r" (value)
279
        : "r" (s->buf), "r" (n), "0" (s->index), "1" (value<<(-n))
280
        : "%eax", "%ecx"
281
    );
282
#        else
283
    int index= s->index;
284
    uint32_t *ptr= ((uint32_t *)s->buf)+(index>>5);
285

  
286
    value<<= 32-n;
287

  
288
    ptr[0] |= be2me_32(value>>(index&31));
289
    ptr[1]  = be2me_32(value<<(32-(index&31)));
290
//if(n>24) printf("%d %d\n", n, value);
291
    index+= n;
292
    s->index= index;
293
#        endif
294
#    else //ALIGNED_BITSTREAM_WRITER
295
#        if ARCH_X86
296
    __asm__ volatile(
297
        "movl $7, %%ecx                 \n\t"
298
        "andl %0, %%ecx                 \n\t"
299
        "addl %3, %%ecx                 \n\t"
300
        "negl %%ecx                     \n\t"
301
        "shll %%cl, %1                  \n\t"
302
        "bswapl %1                      \n\t"
303
        "movl %0, %%ecx                 \n\t"
304
        "shrl $3, %%ecx                 \n\t"
305
        "orl %1, (%%ecx, %2)            \n\t"
306
        "addl %3, %0                    \n\t"
307
        "movl $0, 4(%%ecx, %2)          \n\t"
308
        : "=&r" (s->index), "=&r" (value)
309
        : "r" (s->buf), "r" (n), "0" (s->index), "1" (value)
310
        : "%ecx"
311
    );
312
#        else
313
    int index= s->index;
314
    uint32_t *ptr= (uint32_t*)(((uint8_t *)s->buf)+(index>>3));
315

  
316
    ptr[0] |= be2me_32(value<<(32-n-(index&7) ));
317
    ptr[1] = 0;
318
//if(n>24) printf("%d %d\n", n, value);
319
    index+= n;
320
    s->index= index;
321
#        endif
322
#    endif //!ALIGNED_BITSTREAM_WRITER
323
}
324
#endif
325

  
326
static inline void put_sbits(PutBitContext *pb, int bits, int32_t val)
327
{
328
    assert(bits >= 0 && bits <= 31);
329

  
330
    put_bits(pb, bits, val & ((1<<bits)-1));
331
}
332

  
333

  
334
static inline uint8_t* pbBufPtr(PutBitContext *s)
335
{
336
#ifdef ALT_BITSTREAM_WRITER
337
        return s->buf + (s->index>>3);
338
#else
339
        return s->buf_ptr;
340
#endif
341
}
342

  
343
/**
344
 * Skips the given number of bytes.
345
 * PutBitContext must be flushed & aligned to a byte boundary before calling this.
346
 */
347
static inline void skip_put_bytes(PutBitContext *s, int n){
348
        assert((put_bits_count(s)&7)==0);
349
#ifdef ALT_BITSTREAM_WRITER
350
        FIXME may need some cleaning of the buffer
351
        s->index += n<<3;
352
#else
353
        assert(s->bit_left==32);
354
        s->buf_ptr += n;
355
#endif
356
}
357

  
358
/**
359
 * Skips the given number of bits.
360
 * Must only be used if the actual values in the bitstream do not matter.
361
 * If \p n is 0 the behavior is undefined.
362
 */
363
static inline void skip_put_bits(PutBitContext *s, int n){
364
#ifdef ALT_BITSTREAM_WRITER
365
    s->index += n;
366
#else
367
    s->bit_left -= n;
368
    s->buf_ptr-= s->bit_left>>5;
369
    s->bit_left &= 31;
370
#endif
371
}
372

  
373
/**
374
 * Changes the end of the buffer.
375
 *
376
 * @param size the new size in bytes of the buffer where to put bits
377
 */
378
static inline void set_put_bits_buffer_size(PutBitContext *s, int size){
379
    s->buf_end= s->buf + size;
380
}
381

  
382 108
/* Bitstream reader API docs:
383 109
name
384 110
    arbitrary name which is used as prefix for the internal variables

Also available in: Unified diff