Originally committed as revision 295 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.5
| @@ -80,7 +80,7 @@ static int put_pack_header(AVFormatContext *ctx, | |||
| put_bits(&pb, 1, 1); | |||
| flush_put_bits(&pb); | |||
| return pb.buf_ptr - pb.buf; | |||
| return pbBufPtr(&pb) - pb.buf; | |||
| } | |||
| static int put_system_header(AVFormatContext *ctx, UINT8 *buf) | |||
| @@ -135,7 +135,7 @@ static int put_system_header(AVFormatContext *ctx, UINT8 *buf) | |||
| } | |||
| } | |||
| flush_put_bits(&pb); | |||
| size = pb.buf_ptr - pb.buf; | |||
| size = pbBufPtr(&pb) - pb.buf; | |||
| /* patch packet size */ | |||
| buf[4] = (size - 6) >> 8; | |||
| buf[5] = (size - 6) & 0xff; | |||
| @@ -127,7 +127,7 @@ static void put_swf_rect(ByteIOContext *pb, | |||
| put_bits(&p, nbits, ymax & mask); | |||
| flush_put_bits(&p); | |||
| put_buffer(pb, buf, p.buf_ptr - p.buf); | |||
| put_buffer(pb, buf, pbBufPtr(&p) - p.buf); | |||
| } | |||
| static void put_swf_line_edge(PutBitContext *pb, int dx, int dy) | |||
| @@ -183,7 +183,7 @@ static void put_swf_matrix(ByteIOContext *pb, | |||
| put_bits(&p, 20, ty); | |||
| flush_put_bits(&p); | |||
| put_buffer(pb, buf, p.buf_ptr - p.buf); | |||
| put_buffer(pb, buf, pbBufPtr(&p) - p.buf); | |||
| } | |||
| /* XXX: handle audio only */ | |||
| @@ -271,7 +271,7 @@ static int swf_write_header(AVFormatContext *s) | |||
| put_bits(&p, 5, 0); | |||
| flush_put_bits(&p); | |||
| put_buffer(pb, buf1, p.buf_ptr - p.buf); | |||
| put_buffer(pb, buf1, pbBufPtr(&p) - p.buf); | |||
| put_swf_end_tag(s); | |||
| @@ -1227,9 +1227,9 @@ static int output_frame_end(AC3EncodeContext *s) | |||
| flush_put_bits(&s->pb); | |||
| /* add zero bytes to reach the frame size */ | |||
| frame = s->pb.buf; | |||
| n = 2 * s->frame_size - (s->pb.buf_ptr - frame) - 2; | |||
| n = 2 * s->frame_size - (pbBufPtr(&s->pb) - frame) - 2; | |||
| assert(n >= 0); | |||
| memset(s->pb.buf_ptr, 0, n); | |||
| memset(pbBufPtr(&s->pb), 0, n); | |||
| /* Now we must compute both crcs : this is not so easy for crc1 | |||
| because it is at the beginning of the data... */ | |||
| @@ -16,7 +16,7 @@ | |||
| * along with this program; if not, write to the Free Software | |||
| * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| * | |||
| * alternative bitstream reader by Michael Niedermayer <michaelni@gmx.at> | |||
| * alternative bitstream reader & writer by Michael Niedermayer <michaelni@gmx.at> | |||
| */ | |||
| #include "common.h" | |||
| #include <math.h> | |||
| @@ -27,15 +27,26 @@ void init_put_bits(PutBitContext *s, | |||
| void (*write_data)(void *, UINT8 *, int)) | |||
| { | |||
| s->buf = buffer; | |||
| s->buf_ptr = s->buf; | |||
| s->buf_end = s->buf + buffer_size; | |||
| s->bit_cnt=0; | |||
| s->bit_buf=0; | |||
| s->data_out_size = 0; | |||
| #ifdef ALT_BITSTREAM_WRITER | |||
| s->index=0; | |||
| ((uint32_t*)(s->buf))[0]=0; | |||
| // memset(buffer, 0, buffer_size); | |||
| if(write_data!=NULL) | |||
| { | |||
| fprintf(stderr, "write Data callback is not supported\n"); | |||
| } | |||
| #else | |||
| s->write_data = write_data; | |||
| s->opaque = opaque; | |||
| s->buf_ptr = s->buf; | |||
| s->bit_cnt=0; | |||
| s->bit_buf=0; | |||
| #endif | |||
| } | |||
| #ifndef ALT_BITSTREAM_WRITER | |||
| static void flush_buffer(PutBitContext *s) | |||
| { | |||
| int size; | |||
| @@ -85,21 +96,33 @@ void put_bits(PutBitContext *s, int n, unsigned int value) | |||
| s->bit_buf = bit_buf; | |||
| s->bit_cnt = bit_cnt; | |||
| } | |||
| #endif | |||
| /* return the number of bits output */ | |||
| INT64 get_bit_count(PutBitContext *s) | |||
| { | |||
| #ifdef ALT_BITSTREAM_WRITER | |||
| return s->data_out_size * 8 + s->index; | |||
| #else | |||
| return (s->buf_ptr - s->buf + s->data_out_size) * 8 + (INT64)s->bit_cnt; | |||
| #endif | |||
| } | |||
| void align_put_bits(PutBitContext *s) | |||
| { | |||
| #ifdef ALT_BITSTREAM_WRITER | |||
| put_bits(s,( - s->index) & 7,0); | |||
| #else | |||
| put_bits(s,(8 - s->bit_cnt) & 7,0); | |||
| #endif | |||
| } | |||
| /* pad the end of the output stream with zeros */ | |||
| void flush_put_bits(PutBitContext *s) | |||
| { | |||
| #ifdef ALT_BITSTREAM_WRITER | |||
| align_put_bits(s); | |||
| #else | |||
| while (s->bit_cnt > 0) { | |||
| /* XXX: should test end of buffer */ | |||
| *s->buf_ptr++=s->bit_buf >> 24; | |||
| @@ -109,8 +132,10 @@ void flush_put_bits(PutBitContext *s) | |||
| flush_buffer(s); | |||
| s->bit_cnt=0; | |||
| s->bit_buf=0; | |||
| #endif | |||
| } | |||
| #ifndef ALT_BITSTREAM_WRITER | |||
| /* for jpeg : escape 0xff with 0x00 after it */ | |||
| void jput_bits(PutBitContext *s, int n, unsigned int value) | |||
| { | |||
| @@ -152,8 +177,10 @@ void jput_bits(PutBitContext *s, int n, unsigned int value) | |||
| s->bit_buf = bit_buf; | |||
| s->bit_cnt = bit_cnt; | |||
| } | |||
| #endif | |||
| /* pad the end of the output stream with zeros */ | |||
| #ifndef ALT_BITSTREAM_WRITER | |||
| void jflush_put_bits(PutBitContext *s) | |||
| { | |||
| unsigned int b; | |||
| @@ -171,6 +198,13 @@ void jflush_put_bits(PutBitContext *s) | |||
| s->bit_cnt=0; | |||
| s->bit_buf=0; | |||
| } | |||
| #else | |||
| void jflush_put_bits(PutBitContext *s) | |||
| { | |||
| int num= ( - s->index) & 7; | |||
| jput_bits(s, num,0xFF>>(8-num)); | |||
| } | |||
| #endif | |||
| /* bit input functions */ | |||
| @@ -8,6 +8,7 @@ | |||
| #define CONFIG_WIN32 | |||
| #endif | |||
| //#define ALT_BITSTREAM_WRITER | |||
| //#define ALT_BITSTREAM_READER | |||
| //#define ALIGNED_BITSTREAM | |||
| #define FAST_GET_FIRST_VLC | |||
| @@ -161,25 +162,36 @@ struct PutBitContext; | |||
| typedef void (*WriteDataFunc)(void *, UINT8 *, int); | |||
| typedef struct PutBitContext { | |||
| #ifdef ALT_BITSTREAM_WRITER | |||
| UINT8 *buf, *buf_end; | |||
| int index; | |||
| #else | |||
| UINT32 bit_buf; | |||
| int bit_cnt; | |||
| UINT8 *buf, *buf_ptr, *buf_end; | |||
| INT64 data_out_size; /* in bytes */ | |||
| void *opaque; | |||
| WriteDataFunc write_data; | |||
| #endif | |||
| INT64 data_out_size; /* in bytes */ | |||
| } PutBitContext; | |||
| void init_put_bits(PutBitContext *s, | |||
| UINT8 *buffer, int buffer_size, | |||
| void *opaque, | |||
| void (*write_data)(void *, UINT8 *, int)); | |||
| #ifndef ALT_BITSTREAM_WRITER | |||
| void put_bits(PutBitContext *s, int n, unsigned int value); | |||
| #endif | |||
| INT64 get_bit_count(PutBitContext *s); /* XXX: change function name */ | |||
| void align_put_bits(PutBitContext *s); | |||
| void flush_put_bits(PutBitContext *s); | |||
| /* jpeg specific put_bits */ | |||
| #ifndef ALT_BITSTREAM_WRITER | |||
| void jput_bits(PutBitContext *s, int n, unsigned int value); | |||
| #endif | |||
| void jflush_put_bits(PutBitContext *s); | |||
| /* bit input */ | |||
| @@ -225,6 +237,99 @@ static inline uint32_t unaligned32(const void *v) { | |||
| #endif | |||
| #endif //!ARCH_X86 | |||
| #ifdef ALT_BITSTREAM_WRITER | |||
| static inline void put_bits(PutBitContext *s, int n, int value) | |||
| { | |||
| #ifdef ARCH_X86 | |||
| asm volatile( | |||
| "movl $7, %%ecx \n\t" | |||
| "andl %0, %%ecx \n\t" | |||
| "addl %3, %%ecx \n\t" | |||
| "negl %%ecx \n\t" | |||
| "shll %%cl, %1 \n\t" | |||
| "bswapl %1 \n\t" | |||
| "movl %0, %%ecx \n\t" | |||
| "shrl $3, %%ecx \n\t" | |||
| "orl %1, (%%ecx, %2) \n\t" | |||
| "addl %3, %0 \n\t" | |||
| "movl $0, 4(%%ecx, %2) \n\t" | |||
| : "=&r" (s->index), "=&r" (value) | |||
| : "r" (s->buf), "r" (n), "0" (s->index), "1" (value) | |||
| : "%ecx" | |||
| ); | |||
| #else | |||
| int index= s->index; | |||
| uint32_t *ptr= (uint32_t*)(((uint8_t *)s->buf)+(index>>3)); | |||
| ptr[0] |= be2me_32(value<<(32-n-(index&7) )); | |||
| ptr[1] = 0; | |||
| //if(n>24) printf("%d %d\n", n, value); | |||
| index+= n; | |||
| s->index= index; | |||
| #endif | |||
| } | |||
| #endif | |||
| #ifdef ALT_BITSTREAM_WRITER | |||
| static inline void jput_bits(PutBitContext *s, int n, int value) | |||
| { | |||
| int index= s->index; | |||
| uint32_t *ptr= (uint32_t*)(((uint8_t *)s->buf)+(index>>3)); | |||
| int v= ptr[0]; | |||
| //if(n>24) printf("%d %d\n", n, value); | |||
| v |= be2me_32(value<<(32-n-(index&7) )); | |||
| if(((v+0x01010101)^0xFFFFFFFF)&v&0x80808080) | |||
| { | |||
| /* handle idiotic (m)jpeg escapes */ | |||
| uint8_t *bPtr= (uint8_t*)ptr; | |||
| int numChecked= ((index+n)>>3) - (index>>3); | |||
| v= be2me_32(v); | |||
| *(bPtr++)= v>>24; | |||
| if((v&0xFF000000)==0xFF000000 && numChecked>0){ | |||
| *(bPtr++)= 0x00; | |||
| index+=8; | |||
| } | |||
| *(bPtr++)= (v>>16)&0xFF; | |||
| if((v&0x00FF0000)==0x00FF0000 && numChecked>1){ | |||
| *(bPtr++)= 0x00; | |||
| index+=8; | |||
| } | |||
| *(bPtr++)= (v>>8)&0xFF; | |||
| if((v&0x0000FF00)==0x0000FF00 && numChecked>2){ | |||
| *(bPtr++)= 0x00; | |||
| index+=8; | |||
| } | |||
| *(bPtr++)= v&0xFF; | |||
| if((v&0x000000FF)==0x000000FF && numChecked>3){ | |||
| *(bPtr++)= 0x00; | |||
| index+=8; | |||
| } | |||
| *((uint32_t*)bPtr)= 0; | |||
| } | |||
| else | |||
| { | |||
| ptr[0] = v; | |||
| ptr[1] = 0; | |||
| } | |||
| index+= n; | |||
| s->index= index; | |||
| } | |||
| #endif | |||
| static inline uint8_t* pbBufPtr(PutBitContext *s) | |||
| { | |||
| #ifdef ALT_BITSTREAM_WRITER | |||
| return s->buf + (s->index>>3); | |||
| #else | |||
| return s->buf_ptr; | |||
| #endif | |||
| } | |||
| void init_get_bits(GetBitContext *s, | |||
| UINT8 *buffer, int buffer_size); | |||
| @@ -64,7 +64,7 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number) | |||
| align_put_bits(&s->pb); | |||
| /* Update the pointer to last GOB */ | |||
| s->ptr_lastgob = s->pb.buf_ptr; | |||
| s->ptr_lastgob = pbBufPtr(&s->pb); | |||
| s->gob_number = 0; | |||
| put_bits(&s->pb, 22, 0x20); /* PSC */ | |||
| @@ -152,17 +152,17 @@ int h263_encode_gob_header(MpegEncContext * s, int mb_line) | |||
| /* Check to see if we need to put a new GBSC */ | |||
| /* for RTP packetization */ | |||
| if (s->rtp_mode) { | |||
| pdif = s->pb.buf_ptr - s->ptr_lastgob; | |||
| pdif = pbBufPtr(&s->pb) - s->ptr_lastgob; | |||
| if (pdif >= s->rtp_payload_size) { | |||
| /* Bad luck, packet must be cut before */ | |||
| align_put_bits(&s->pb); | |||
| flush_put_bits(&s->pb); | |||
| /* Call the RTP callback to send the last GOB */ | |||
| if (s->rtp_callback) { | |||
| pdif = s->pb.buf_ptr - s->ptr_lastgob; | |||
| pdif = pbBufPtr(&s->pb) - s->ptr_lastgob; | |||
| s->rtp_callback(s->ptr_lastgob, pdif, s->gob_number); | |||
| } | |||
| s->ptr_lastgob = s->pb.buf_ptr; | |||
| s->ptr_lastgob = pbBufPtr(&s->pb); | |||
| put_bits(&s->pb, 17, 1); /* GBSC */ | |||
| s->gob_number = mb_line / s->gob_index; | |||
| put_bits(&s->pb, 5, s->gob_number); /* GN */ | |||
| @@ -176,10 +176,10 @@ int h263_encode_gob_header(MpegEncContext * s, int mb_line) | |||
| flush_put_bits(&s->pb); | |||
| /* Call the RTP callback to send the last GOB */ | |||
| if (s->rtp_callback) { | |||
| pdif = s->pb.buf_ptr - s->ptr_lastgob; | |||
| pdif = pbBufPtr(&s->pb) - s->ptr_lastgob; | |||
| s->rtp_callback(s->ptr_lastgob, pdif, s->gob_number); | |||
| } | |||
| s->ptr_lastgob = s->pb.buf_ptr; | |||
| s->ptr_lastgob = pbBufPtr(&s->pb); | |||
| put_bits(&s->pb, 17, 1); /* GBSC */ | |||
| s->gob_number = mb_line / s->gob_index; | |||
| put_bits(&s->pb, 5, s->gob_number); /* GN */ | |||
| @@ -489,7 +489,8 @@ void mpeg4_encode_picture_header(MpegEncContext * s, int picture_number) | |||
| { | |||
| align_put_bits(&s->pb); | |||
| put_bits(&s->pb, 32, 0x1B6); /* vop header */ | |||
| put_bits(&s->pb, 16, 0); /* vop header */ | |||
| put_bits(&s->pb, 16, 0x1B6); /* vop header */ | |||
| put_bits(&s->pb, 2, s->pict_type - 1); /* pict type: I = 0 , P = 1 */ | |||
| /* XXX: time base + 1 not always correct */ | |||
| put_bits(&s->pb, 1, 1); | |||
| @@ -846,7 +847,7 @@ int h263_decode_gob_header(MpegEncContext *s) | |||
| gfid = get_bits(&s->gb, 2); /* GFID */ | |||
| s->qscale = get_bits(&s->gb, 5); /* GQUANT */ | |||
| #ifdef DEBUG | |||
| fprintf(stderr, "\nGN: %u GFID: %u Quant: %u\n", gn, gfid, s->qscale); | |||
| fprintf(stderr, "\nGN: %u GFID: %u Quant: %u\n", s->gob_number, gfid, s->qscale); | |||
| #endif | |||
| return 1; | |||
| } | |||
| @@ -243,7 +243,7 @@ static void jpeg_table_header(MpegEncContext *s) | |||
| /* huffman table */ | |||
| put_marker(p, DHT); | |||
| flush_put_bits(p); | |||
| ptr = p->buf_ptr; | |||
| ptr = pbBufPtr(p); | |||
| put_bits(p, 16, 0); /* patched later */ | |||
| size = 2; | |||
| size += put_huffman_table(s, 0, 0, bits_dc_luminance, val_dc_luminance); | |||
| @@ -763,7 +763,7 @@ int MPA_encode_frame(AVCodecContext *avctx, | |||
| encode_frame(s, bit_alloc, padding); | |||
| s->nb_samples += MPA_FRAME_SIZE; | |||
| return s->pb.buf_ptr - s->pb.buf; | |||
| return pbBufPtr(&s->pb) - s->pb.buf; | |||
| } | |||
| @@ -532,9 +532,10 @@ int MPV_encode_picture(AVCodecContext *avctx, | |||
| mjpeg_picture_trailer(s); | |||
| flush_put_bits(&s->pb); | |||
| s->total_bits += (s->pb.buf_ptr - s->pb.buf) * 8; | |||
| s->total_bits += (pbBufPtr(&s->pb) - s->pb.buf) * 8; | |||
| avctx->quality = s->qscale; | |||
| return s->pb.buf_ptr - s->pb.buf; | |||
| return pbBufPtr(&s->pb) - s->pb.buf; | |||
| } | |||
| static inline int clip(int a, int amin, int amax) | |||
| @@ -1115,13 +1116,15 @@ static void encode_picture(MpegEncContext *s, int picture_number) | |||
| MPV_decode_mb(s, s->block); | |||
| } | |||
| /* Obtain average GOB size for RTP */ | |||
| if (s->rtp_mode) { | |||
| if (!mb_y) | |||
| s->mb_line_avgsize = s->pb.buf_ptr - s->ptr_last_mb_line; | |||
| s->mb_line_avgsize = pbBufPtr(&s->pb) - s->ptr_last_mb_line; | |||
| else if (!(mb_y % s->gob_index)) { | |||
| s->mb_line_avgsize = (s->mb_line_avgsize + s->pb.buf_ptr - s->ptr_last_mb_line) >> 1; | |||
| s->ptr_last_mb_line = s->pb.buf_ptr; | |||
| s->mb_line_avgsize = (s->mb_line_avgsize + pbBufPtr(&s->pb) - s->ptr_last_mb_line) >> 1; | |||
| s->ptr_last_mb_line = pbBufPtr(&s->pb); | |||
| } | |||
| //fprintf(stderr, "\nMB line: %d\tSize: %u\tAvg. Size: %u", s->mb_y, | |||
| // (s->pb.buf_ptr - s->ptr_last_mb_line), s->mb_line_avgsize); | |||
| @@ -1138,11 +1141,11 @@ static void encode_picture(MpegEncContext *s, int picture_number) | |||
| /* Send the last GOB if RTP */ | |||
| if (s->rtp_mode) { | |||
| flush_put_bits(&s->pb); | |||
| pdif = s->pb.buf_ptr - s->ptr_lastgob; | |||
| pdif = pbBufPtr(&s->pb) - s->ptr_lastgob; | |||
| /* Call the RTP callback to send the last GOB */ | |||
| if (s->rtp_callback) | |||
| s->rtp_callback(s->ptr_lastgob, pdif, s->gob_number); | |||
| s->ptr_lastgob = s->pb.buf_ptr; | |||
| s->ptr_lastgob = pbBufPtr(&s->pb); | |||
| //fprintf(stderr,"\nGOB: %2d size: %d (last)", s->gob_number, pdif); | |||
| } | |||