diff options
author | Robin Watts <robin@xiph.org> | 2010-05-30 15:27:19 +0000 |
---|---|---|
committer | Robin Watts <robin@xiph.org> | 2010-05-30 15:27:19 +0000 |
commit | d024c7dcbd50115ba7871850a18ef51caf8837f1 (patch) | |
tree | 199c0f33c9d4094d4ba43eded1f2fa7eb060d803 | |
parent | d4a99079c96f680aae57af6a49a4c0c82eea0308 (diff) | |
download | tremor-d024c7dcbd50115ba7871850a18ef51caf8837f1.tar.gz |
Add final ARM code sections for Tremolo decode.
Add missing couple of vorbis dsp entrypoints.
git-svn-id: https://svn.xiph.org/branches/lowmem-branch/Tremolo@17258 0101bb08-14d6-0310-b084-bc0e0c8e3800
-rw-r--r-- | Makefile.rjw | 4 | ||||
-rw-r--r-- | codebook.c | 14 | ||||
-rw-r--r-- | dpenARM.s | 459 | ||||
-rw-r--r-- | dsp.c | 16 | ||||
-rw-r--r-- | framing.c | 140 |
5 files changed, 575 insertions, 58 deletions
diff --git a/Makefile.rjw b/Makefile.rjw index c8acd47..63d349c 100644 --- a/Makefile.rjw +++ b/Makefile.rjw @@ -30,7 +30,7 @@ AS = arm-none-linux-gnueabi-as DEFINES := -CFLAGS := -g -mcpu=cortex-a8 -mfpu=neon -I$(srcdir) -D__ARM__ -D_ARM_ +CFLAGS := -O3 -mcpu=cortex-a8 -mfpu=neon -I$(srcdir) -D__ARM__ -D_ARM_ CXXFLAGS := $(CFLAGS) @@ -44,6 +44,7 @@ LIBOBJS := \ build/bitwise.o \ build/bitwiseARM.o \ build/codebook.o \ + build/dpenARM.o \ build/dsp.o \ build/floor0.o \ build/floor1.o \ @@ -79,6 +80,7 @@ LIBOBJS_L := \ build/bitwise.ol \ build/bitwiseARM.o \ build/codebook.ol \ + build/dpenARM.o \ build/dsp.ol \ build/floor0.ol \ build/floor1.ol \ @@ -602,6 +602,9 @@ int vorbis_book_unpack(oggpack_buffer *opb,codebook *s){ return -1; } +#ifdef _ARM_ASSEM_ +ogg_uint32_t decode_packed_entry_number(codebook *book, oggpack_buffer *b); +#else static inline ogg_uint32_t decode_packed_entry_number(codebook *book, oggpack_buffer *b){ ogg_uint32_t chase=0; @@ -695,6 +698,7 @@ static inline ogg_uint32_t decode_packed_entry_number(codebook *book, oggpack_adv(b,read+1); return(-1); } +#endif /* returns the [original, not compacted] entry number or -1 on eof *********/ long vorbis_book_decode(codebook *book, oggpack_buffer *b){ @@ -702,6 +706,9 @@ long vorbis_book_decode(codebook *book, oggpack_buffer *b){ return decode_packed_entry_number(book,b); } +#ifdef _ARM_ASSEM_ +int decode_map(codebook *s, oggpack_buffer *b, ogg_int32_t *v, int point); +#else int decode_map(codebook *s, oggpack_buffer *b, ogg_int32_t *v, int point){ ogg_uint32_t entry = decode_packed_entry_number(s,b); int i; @@ -773,6 +780,7 @@ int decode_map(codebook *s, oggpack_buffer *b, ogg_int32_t *v, int point){ return 0; } +#endif /* returns 0 on OK or -1 on eof *************************************/ long vorbis_book_decodevs_add(codebook *book,ogg_int32_t *a, @@ -832,6 +840,11 @@ long vorbis_book_decodev_set(codebook *book,ogg_int32_t *a, return 0; } +#ifdef _ARM_ASSEM_ +long vorbis_book_decodevv_add(codebook *book,ogg_int32_t **a, + long offset,int ch, + oggpack_buffer *b,int n,int point); +#else long vorbis_book_decodevv_add(codebook *book,ogg_int32_t **a, long offset,int ch, oggpack_buffer *b,int n,int point){ @@ -856,3 +869,4 @@ long vorbis_book_decodevv_add(codebook *book,ogg_int32_t **a, return 0; } +#endif diff --git a/dpenARM.s b/dpenARM.s new file mode 100644 index 0000000..8a3cbef --- /dev/null +++ b/dpenARM.s @@ -0,0 +1,459 @@ +; Tremolo library +; Copyright (C) 2009 Robin Watts for Pinknoise Productions Ltd + + AREA |.text|, CODE, READONLY + + EXPORT decode_packed_entry_number + EXPORT decode_packed_entry_number_REALSTART + EXPORT decode_map + EXPORT vorbis_book_decodevv_add + EXPORT _checksum + + IMPORT oggpack_adv + IMPORT oggpack_look + IMPORT oggpack_eop + IMPORT crc_lookup + +decode_packed_entry_number_REALSTART +dpen_nobits + MOV r0,r5 ; r0 = b + MOV r1,#1 ; r1 = 1 + BL oggpack_adv ; oggpack_adv(b,1) /* Force eop */ +duff + MVN r0,#0 ; return -1 + LDMFD r13!,{r4-r8,r10,PC} + +dpen_readfailed + SUBS r4,r4,#1 ; r4 = --read + BEQ dpen_nobits + MOV r0,r5 ; r0 = b + MOV r1,r4 ; r1 = read + ADR r14,dpen_read_return + B oggpack_look + +decode_packed_entry_number + ; r0 = codebook *book + ; r1 = oggpack_buffer *b + STMFD r13!,{r4-r8,r10,r14} + + LDMIA r0,{r4,r6,r7} ; r4 = read = book->max_length + ; r6 = book->dec_table + ; r7 = book->dec_method + MOV r5,r1 ; r5 = b + + MOV r0,r5 ; r0 = b + MOV r1,r4 ; r1 = read + BL oggpack_look +dpen_read_return + CMP r0,#0 + BLT dpen_readfailed + + ; r0 = lok + ; r4 = read + ; r5 = b + ; r6 = dec_table + ; r7 = dec_method + + CMP r7, #3 + BGT meth4 + BEQ meth3 + CMP r7, #1 + BGT meth2 + BEQ meth1 +meth0 + RSB r1, r4, #0 ; r1 = i-read = 0-read + MOV r7, #0 ; r7 = chase +m0_loop + MOVS r0, r0, LSR #1 ; r0 = lok>>1 C = bottom bit + ADC r2, r6, r7, LSL #1 ; r8 = &t[chase*2+C] + LDRB r7, [r2] + ADDS r1, r1, #1 ; r1 = i-read++ (i-read<0 => i<read) + ; stall Xscale + CMPLT r7, #0x80 + BLT m0_loop + AND r7, r7, #0x7F ; r7 = chase + CMP r1, #0 ; if (i-read >= 0) === (i >= read) + MVNGT r7, #0 ; if (i >= read) value to return = -1 + ADD r1, r1, r4 ; r1 = i-read+read+1 = i +1 + MOV r0, r5 ; r0 = b + BL oggpack_adv ; oggpack_adv(b, i+1); + MOV r0, r7 ; return chase + LDMFD r13!,{r4-r8,r10,PC} + +meth1 + ; r0 = lok + ; r4 = read + ; r5 = b + ; r6 = dec_table + RSB r1, r4, #0 ; r1 = i = -read + MOV r10,#0 ; r10= next = 0 +m1_loop + MOV r7, r10 ; r7 = chase=next + MOVS r0, r0, LSR #1 ; r0 = lok>>1 C = bottom bit + ADC r8, r6, r7 ; r8 = t+chase+bit + LDRB r10,[r8], -r6 ; r10= next=t[chase+bit] r8=chase+bit + ADDS r1, r1, #1 ; r1 = i++ + ; stall Xscale + CMPLT r10,#0x80 ; if (next & 0x80) == 0 + BLT m1_loop + + ADD r1, r1, r4 ; r1 = i+read + MOV r0, r5 ; r0 = b + BL oggpack_adv ; oggpack_adv(b, i) + + CMP r10,#0x80 + BLT duff + + CMP r8, r7 ; if bit==0 (chase+bit==chase) (sets C) + LDRNEB r14,[r6, r7] ; r14= t[chase] + MOVEQ r14,#128 + ADC r12,r8, r6 ; r12= chase+bit+1+t + LDRB r14,[r12,r14,LSR #7] ; r14= t[chase+bit+1+(!bit || t[chase]&0x80)] + BIC r10,r10,#0x80 ; r3 = next &= ~0x80 + ; stall Xscale + ORR r0, r14,r10,LSL #8 ; r7 = chase = (next<<8) | r14 + + LDMFD r13!,{r4-r8,r10,PC} + + +meth2 + RSB r1, r4, #0 ; r1 = i-read = 0-read + MOV r7, #0 ; r7 = chase + MOV r6, r6, LSR #1 +m2_loop + MOVS r0, r0, LSR #1 ; r0 = lok>>1 C = bottom bit + ADC r2, r6, r7, LSL #1 ; r8 = &t[chase*2+C] + LDRH r7, [r2, r2] + ADDS r1, r1, #1 ; r1 = i-read++ (i-read<0 => i<read) + ; stall Xscale + CMPLT r7, #0x8000 + BLT m2_loop + BIC r7, r7, #0x8000 ; r7 = chase + CMP r1, #0 ; if (i-read >= 0) === (i >= read) + MVNGT r7, #0 ; if (i >= read) value to return = -1 + ADD r1, r1, r4 ; r1 = i-read+read+1 = i +1 + MOV r0, r5 ; r0 = b + BL oggpack_adv ; oggpack_adv(b, i+1); + MOV r0, r7 ; return chase + LDMFD r13!,{r4-r8,r10,PC} + +meth3 + ; r0 = lok + ; r4 = read + ; r5 = b + ; r6 = dec_table + RSB r1, r4, #0 ; r1 = i = -read + MOV r10,#0 ; r10= next = 0 +m3_loop + MOV r7, r10 ; r7 = chase=next + MOVS r0, r0, LSR #1 ; r0 = lok>>1 C = bottom bit + ADC r8, r7, #0 ; r8 = chase+bit + MOV r8, r8, LSL #1 ; r8 = (chase+bit)<<1 + LDRH r10,[r6, r8] ; r10= next=t[chase+bit] + ADDS r1, r1, #1 ; r1 = i++ + ; stall Xscale + CMPLT r10,#0x8000 ; if (next & 0x8000) == 0 + BLT m3_loop + + ADD r1, r1, r4 ; r1 = i+read + MOV r0, r5 ; r0 = b + BL oggpack_adv ; oggpack_adv(b, i) + + CMP r10,#0x8000 + BLT duff + + MOV r7, r7, LSL #1 + CMP r8, r7 ; if bit==0 (chase+bit==chase) sets C + LDRNEH r14,[r6, r7] ; r14= t[chase] + MOVEQ r14,#0x8000 + ADC r12,r8, r14,LSR #15 ; r12= 1+((chase+bit)<<1)+(!bit || t[chase]&0x8000) + ADC r12,r12,r14,LSR #15 ; r12= t + (1+chase+bit+(!bit || t[chase]&0x8000))<<1 + LDRH r14,[r6, r12] ; r14= t[chase+bit+1 + BIC r10,r10,#0x8000 ; r3 = next &= ~0x8000 + ; stall Xscale + ORR r0, r14,r10,LSL #16 ; r7 = chase = (next<<16) | r14 + + LDMFD r13!,{r4-r8,r10,PC} + +meth4 + RSB r1, r4, #0 ; r1 = i-read = 0-read + MOV r7, #0 ; r7 = chase +m4_loop + MOVS r0, r0, LSR #1 ; r0 = lok>>1 C = bottom bit + ADC r2, r7, r7 ; r8 = chase*2+C + LDR r7, [r6, r2, LSL #2] + ADDS r1, r1, #1 ; r1 = i-read++ (i-read<0 => i<read) + ; stall Xscale + CMPLT r7, #0x80000000 + BLT m4_loop + BIC r7, r7, #0x80000000 ; r7 = chase + CMP r1, #0 ; if (i-read >= 0) === (i >= read) + MVNGT r7, #0 ; if (i >= read) value to return = -1 + ADD r1, r1, r4 ; r1 = i-read+read+1 = i +1 + MOV r0, r5 ; r0 = b + BL oggpack_adv ; oggpack_adv(b, i+1); + MOV r0, r7 ; return chase + LDMFD r13!,{r4-r8,r10,PC} + +decode_map + ; r0 = codebook *s + ; r1 = oggpack_buffer *b + ; r2 = int v + ; r3 = int point + STMFD r13!,{r4-r11,r14} + + MOV r4, r0 ; r4 = s + MOV r5, r1 ; r5 = b + MOV r6, r2 ; r6 = v + MOV r7, r3 ; r7 = point + BL decode_packed_entry_number + MOV r8, r0 + + MOV r0, r5 + BL oggpack_eop + CMP r0, #0 + BNE dm_duff + + ; r4 = s + ; r5 = b + ; r6 = v + ; r7 = point + ; r8 = entry + + LDR r1, [r4,#12] ; r1 = s->dec_type + LDR r2, [r4,#16] ; r2 = s->q_bits + LDR r3, [r4,#20] ; r3 = s->dim + LDR r5, [r4,#24] ; r5 = s->q_delp + LDR r11,[r4,#28] ; r11= s->q_minp + LDR r12,[r4,#32] ; r12= s->q_del = mul + LDR r14,[r4,#36] ; r14= s->q_min + SUBS r11,r7, r11 ; r11= add = point - s->q_minp + + MOVGT r14,r14,ASR r11 ; r14= add = s->q_min >> add (if add >0) + RSBLT r11,r11,#0 + MOVLT r14,r14,LSL r11 ; r14= add = s->q_min << -add (if add < 0) + + SUBS r5, r7, r5 ; r5 = shiftM = point - s->q_delp + LDR r7, [r4,#40] ; r7 = s->q_seq + RSBLT r5, r5, #0 ; if (shiftM<0) r5 =-shiftM + MOVLT r12,r12,LSL r5 ; r12=mul<<-shiftM + MOVLT r5, #0 ; r5 =shiftM = 0 + MOVGT r14,r14,LSL r5 ; add <<= shiftM + + CMP r7,#0 ; seqMask = (s->q_seq?-1:0) + MVNNE r7,#0 + + CMP r1, #2 + BEQ dm2 + BGT dm3 + CMP r1,#0 ; probably never happens + BLE dm_duff +dm1 + ; r1 = s->dec_type + ; r2 = s->q_bits + ; r3 = s->dim + ; r5 = shiftM + ; r6 = v + ; r7 = seqMask + ; r8 = entry + ; r12= mul + ; r14= add + MOV r0, #1 + RSB r0, r0, r0, LSL r2 ; r0 = mask = (1<<s->q_bits)-1 + MOV r11,#0 ; r11= prev = 0 +dm1_loop + AND r1, r8, r0 ; r1 = v = entry & mask + MLA r1, r12, r1, r14 ; r1 = (add + mul*v) + MOV r8, r8, LSR r2 ; r8 = entry>>s->q_bits + SUBS r3, r3, #1 + ADD r1, r11,r1, ASR r5 ; r1 = v = prev+((add+mul*v)>>shiftM) + AND r11,r1, r7 ; r11= prev = seqMask & v + STR r1, [r6], #4 ; *v++ = v + BGT dm1_loop + + MOV r0, #0 + LDMFD r13!,{r4-r11,PC} +dm2 + ; r1 = s->dec_type + ; r2 = s->q_bits + ; r3 = s->dim + ; r4 = s + ; r5 = shiftM + ; r6 = v + ; r7 = seqMask + ; r8 = entry + ; r12= mul + ; r14= add + LDR r1, [r4,#44] ; r1 = s->q_pack + LDR r4, [r4,#48] ; r4 = s->q_val + MOV r11,#0 ; r11= prev + MOV r0, #1 + RSB r0, r0, r0, LSL r1 ; r8 = mask = (1<<s->q_pack)-1 + CMP r2,#8 + BGT dm2_hword +dm2_loop + AND r2, r8, r0 ; r2 = entry & mask + LDRB r2, [r4, r2] ; r2 = v = q->val[entry & mask] + MOV r8, r8, LSR r1 ; r8 = entry>>q_pack + MLA r2, r12,r2, r14 ; r2 = (add+mul*v) + SUBS r3, r3, #1 + ADD r2, r11,r2, ASR r5 ; r2 = v = prev+(add+mul*v)>>shiftM + AND r11,r2, r7 ; r11= prev = seqMask & v + STR r2, [r6], #4 ; *v++ = v + BGT dm2_loop + MOV r0, #0 + LDMFD r13!,{r4-r11,PC} + +dm2_hword + AND r2, r8, r0 ; r2 = entry & mask + MOV r2, r2, LSL #1 ; r2 = 2*r2 + LDRH r2, [r4, r2] ; r2 = v = q->val[entry & mask] + MOV r8, r8, LSR r1 ; r8 = entry>>q_pack + MLA r2, r12,r2, r14 ; r2 = (add+mul*v) + SUBS r3, r3, #1 + ADD r2, r11,r2, ASR r5 ; r2 = v = prev+(add+mul*v)>>shiftM + AND r11,r2, r7 ; r11= prev = seqMask & v + STR r2, [r6], #4 ; *v++ = v + BGT dm2_hword + MOV r0, #0 + LDMFD r13!,{r4-r11,PC} + +dm3 + ; r1 = s->dec_type + ; r2 = s->q_bits + ; r3 = s->dim + ; r4 = s + ; r5 = shiftM + ; r6 = v + ; r7 = seqMask + ; r8 = entry + ; r12= mul + ; r14= add + LDR r1, [r4,#44] ; r1 = s->q_pack + LDR r4, [r4,#52] ; r4 = s->q_val + CMP r2,#8 + MOV r11,#0 ; r11= prev + MLA r4,r1,r8,r4 ; r4 = ptr = s->q_val+entry*s->q_pack + + BGT dm3_hword +dm3_loop + LDRB r2, [r4], #1 ; r2 = v = *ptr++ + SUBS r3, r3, #1 + MLA r2, r12,r2, r14 ; r2 = (add+mul*v) + ADD r2, r11,r2, ASR r5 ; r2 = v = prev+(add+mul*v)>>shiftM + AND r11,r2, r7 ; r11= prev = seqMask & v + STR r2, [r6], #4 ; *v++ = v + BGT dm3_loop + MOV r0, #0 + LDMFD r13!,{r4-r11,PC} + +dm3_hword + LDRH r2, [r4], #2 ; r2 = *ptr++ + SUBS r3, r3, #1 + MLA r2, r12,r2, r14 ; r2 = (add+mul*v) + ADD r2, r11,r2, ASR r5 ; r2 = v = prev+(add+mul*v)>>shiftM + AND r11,r2, r7 ; r11= prev = seqMask & v + STR r2, [r6], #4 ; *v++ = v + BGT dm3_hword + MOV r0, #0 + LDMFD r13!,{r4-r11,PC} + +dm_duff + MVN r0,#0 + LDMFD r13!,{r4-r11,PC} + +vorbis_book_decodevv_add + ; r0 = codebook *book + ; r1 = ogg_int32_t **a + ; r2 = long offset + ; r3 = int ch + ; <> = b + ; <> = n + ; <> = point + STMFD r13!,{r4-r11,R14} + LDR r7, [r0, #13*4] ; r7 = used_entries + MOV r9, r0 ; r9 = book + MOV r10,r1 ; r10= &a[chptr] chptr=0 + MOV r6, r3 ; r6 = ch + ADD r8, r10,r3, LSL #2 ; r8 = &a[ch] + MOV r11,r2 ; r11= offset + CMP r7, #0 ; if (used_entries <= 0) + BLE vbdvva_exit ; exit + LDR r5, [r13,#10*4] ; r5 = n +vbdvva_loop1 + ; r5 = n + ; r6 = ch + ; r8 = &a[ch] + ; r9 = book + ; r10= &a[chptr] + ; r11= offset + MOV r0, r9 ; r0 = book + LDR r1, [r13,# 9*4] ; r1 = b + LDR r2, [r9, #14*4] ; r2 = v = dec_buf + LDR r3, [r13,#11*4] ; r3 = point + BL decode_map + CMP r0, #0 + BNE vbdvva_fail + + LDR r0, [r9, # 5*4] ; r0 = book->dim + LDR r1, [r9, #14*4] ; r1 = v = dec_buf +vbdvva_loop2 + LDR r2, [r10],#4 ; r2 = a[chptr++] + LDR r12,[r1], #4 ; r1 = v[j++] + CMP r10,r8 ; if (chptr == ch) + SUBEQ r10,r10,r6, LSL #2 ; chptr = 0 + LDR r14,[r2, r11,LSL #2]! ; r2 = &a[chptr++][i] r14=[r12] + ADDEQ r11,r11,#1 ; i++ + SUBEQ r5, r5, #1 ; n-- + SUBS r0, r0, #1 ; r0-- + ADD r12,r12,r14 ; r12= a[chptr++][i]+ v[j] + STR r12,[r2] ; r12= a[chptr++][i]+=v[j] + BGT vbdvva_loop2 + CMP r5,#0 + BGT vbdvva_loop1 +vbdvva_exit + MOV r0, #0 ; return 0 + LDMFD r13!,{r4-r11,PC} +vbdvva_fail + MVN r0, #0 ; return -1 + LDMFD r13!,{r4-r11,PC} + +_checksum + ; r0 = ogg_reference *or + ; r1 = bytes + STMFD r13!,{r5-r6,r14} + + LDR r5,=crc_lookup + MOV r14,#0 ; r14= crc_reg = 0 + MOVS r12,r0 + BEQ _cs_end +_cs_loop1 + LDMIA r12,{r0,r2,r3,r12} ; r0 = or->buffer + ; r2 = or->begin + ; r3 = or->length + ; r12= or->next + LDR r0,[r0] ; r0 = or->buffer->data + CMP r1,r3 ; r3 = post = (bytes < or->length ? + MOVLT r3,r1 ; bytes : or->length) + MOVS r6,r3 ; r6 = j = post + BEQ _cs_no_bytes + ADD r0,r0,r2 ; r0 = or->buffer->data + or->begin +_cs_loop2 + LDRB r2, [r0],#1 ; r2 = data[j] + ; stall + ; stall Xscale + EOR r2, r2, r14,LSR #24 ; r2 = (crc_reg>>24)^data[j] + LDR r2, [r5, r2, LSL #2] ; r2 = crc_lkp[(crc_reg>>24)^data[j]] + SUBS r6, r6, #1 ; j-- + ; stall Xscale + EOR r14,r2, r14,LSL #8 ; r14= crc_reg = (crc_reg<<8)^r2 + BGT _cs_loop2 +_cs_no_bytes + SUBS r1, r1, r3 + CMPNE r12,#0 + BNE _cs_loop1 +_cs_end + MOV r0,r14 + LDMFD r13!,{r5-r6,PC} + + END @@ -43,10 +43,9 @@ int vorbis_dsp_restart(vorbis_dsp_state *v){ return 0; } -vorbis_dsp_state *vorbis_dsp_create(vorbis_info *vi){ +int vorbis_dsp_init(vorbis_dsp_state *v,vorbis_info *vi){ int i; - vorbis_dsp_state *v=_ogg_calloc(1,sizeof(*v)); codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; v->vi=vi; @@ -64,10 +63,16 @@ vorbis_dsp_state *vorbis_dsp_create(vorbis_info *vi){ v->W=0; /* current window size */ vorbis_dsp_restart(v); + return 0; +} + +vorbis_dsp_state *vorbis_dsp_create(vorbis_info *vi){ + vorbis_dsp_state *v=_ogg_calloc(1,sizeof(*v)); + vorbis_dsp_init(v,vi); return v; } -void vorbis_dsp_destroy(vorbis_dsp_state *v){ +void vorbis_dsp_clear(vorbis_dsp_state *v){ int i; if(v){ vorbis_info *vi=v->vi; @@ -87,6 +92,11 @@ void vorbis_dsp_destroy(vorbis_dsp_state *v){ } } +void vorbis_dsp_destroy(vorbis_dsp_state *v){ + vorbis_dsp_clear(v); + _ogg_free(v); +} + static LOOKUP_T *_vorbis_window(int left){ switch(left){ case 32: @@ -135,7 +135,7 @@ static ogg_reference *ogg_buffer_alloc(ogg_buffer_state *bs,long bytes){ /* enlarge the data buffer in the current link */ static void ogg_buffer_realloc(ogg_reference *or,long bytes){ ogg_buffer *ob=or->buffer; - + /* if the unused buffer is too small, grow it */ if(ob->size<bytes){ ob->data=_ogg_realloc(ob->data,bytes); @@ -160,7 +160,7 @@ static void ogg_buffer_mark(ogg_reference *or){ length, a zero length ref is returned. */ static ogg_reference *ogg_buffer_sub(ogg_reference *or,long length){ ogg_reference *ret=0,*head=0; - + /* duplicate the reference chain; increment refcounts */ while(or && length){ ogg_reference *temp=_fetch_ref(or->buffer->ptr.owner); @@ -169,12 +169,12 @@ static ogg_reference *ogg_buffer_sub(ogg_reference *or,long length){ else ret=temp; head=temp; - head->buffer=or->buffer; + head->buffer=or->buffer; head->begin=or->begin; head->length=length; if(head->length>or->length) head->length=or->length; - + length-=head->length; or=or->next; } @@ -193,7 +193,7 @@ ogg_reference *ogg_buffer_dup(ogg_reference *or){ else ret=temp; head=temp; - head->buffer=or->buffer; + head->buffer=or->buffer; head->begin=or->begin; head->length=or->length; or=or->next; @@ -224,44 +224,44 @@ static ogg_reference *ogg_buffer_split(ogg_reference **tail, if(!or || pos==0){ return 0; - + }else{ - + if(pos>=or->length){ /* exact split, or off the end? */ if(or->next){ - + /* a split */ *tail=or->next; or->next=0; - + }else{ - + /* off or at the end */ *tail=*head=0; - + } }else{ - + /* split within a fragment */ long lengthA=pos; long beginB=or->begin+pos; long lengthB=or->length-pos; - + /* make a new reference to tail the second piece */ *tail=_fetch_ref(or->buffer->ptr.owner); - + (*tail)->buffer=or->buffer; (*tail)->begin=beginB; (*tail)->length=lengthB; (*tail)->next=or->next; _ogg_buffer_mark_one(*tail); - if(head && or==*head)*head=*tail; - + if(head && or==*head)*head=*tail; + /* update the first piece */ or->next=0; or->length=lengthA; - + } } return ret; @@ -277,7 +277,7 @@ static void ogg_buffer_release_one(ogg_reference *or){ ob->ptr.next=bs->unused_buffers; bs->unused_buffers=ob; } - + bs->outstanding--; /* for the returned reference */ or->next=bs->unused_references; bs->unused_references=or; @@ -358,7 +358,7 @@ static int oggbyte_init(oggbyte_buffer *b,ogg_reference *or){ b->ref=b->baseref=or; b->pos=0; b->end=b->ref->length; - b->ptr=b->ref->buffer->data+b->ref->begin; + b->ptr=b->ref->buffer->data+b->ref->begin; return 0; }else return -1; @@ -374,7 +374,7 @@ static void oggbyte_set4(oggbyte_buffer *b,ogg_uint32_t val,int pos){ ++pos; } } - + static unsigned char oggbyte_read1(oggbyte_buffer *b,int pos){ _positionB(b,pos); _positionF(b,pos); @@ -451,7 +451,7 @@ ogg_uint32_t ogg_page_serialno(ogg_page *og){ if(oggbyte_init(&ob,og->header)) return 0xffffffffUL; return oggbyte_read4(&ob,14); } - + ogg_uint32_t ogg_page_pageno(ogg_page *og){ oggbyte_buffer ob; if(oggbyte_init(&ob,og->header))return 0xffffffffUL; @@ -465,13 +465,13 @@ ogg_uint32_t ogg_page_pageno(ogg_page *og){ /* NOTE: If a page consists of a packet begun on a previous page, and a new packet begun (but not completed) on this page, the return will be: - ogg_page_packets(page) ==1, + ogg_page_packets(page) ==1, ogg_page_continued(page) !=0 If a page happens to be a single packet that was begun on a previous page, and spans to the next page (in the case of a three or -more page packet), the return will be: - ogg_page_packets(page) ==0, +more page packet), the return will be: + ogg_page_packets(page) ==0, ogg_page_continued(page) !=0 */ @@ -491,7 +491,7 @@ int ogg_page_packets(ogg_page *og){ /* Static CRC calculation table. See older code in CVS for dead run-time initialization code. */ -static ogg_uint32_t crc_lookup[256]={ +ogg_uint32_t crc_lookup[256]={ 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9, 0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005, 0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61, @@ -557,6 +557,11 @@ static ogg_uint32_t crc_lookup[256]={ 0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668, 0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4}; +void ogg_sync_init(ogg_sync_state *oy){ + memset(oy,0,sizeof(*oy)); + oy->bufferpool=ogg_buffer_create(); +} + ogg_sync_state *ogg_sync_create(void){ ogg_sync_state *oy=_ogg_calloc(1,sizeof(*oy)); memset(oy,0,sizeof(*oy)); @@ -564,6 +569,15 @@ ogg_sync_state *ogg_sync_create(void){ return oy; } +int ogg_sync_clear(ogg_sync_state *oy){ + if(oy){ + ogg_sync_reset(oy); + ogg_buffer_destroy(oy->bufferpool); + memset(oy,0,sizeof(*oy)); + } + return OGG_SUCCESS; +} + int ogg_sync_destroy(ogg_sync_state *oy){ if(oy){ ogg_sync_reset(oy); @@ -595,7 +609,7 @@ unsigned char *ogg_sync_bufferin(ogg_sync_state *oy, long bytes){ oy->fifo_head=oy->fifo_tail=ogg_buffer_alloc(oy->bufferpool,bytes); return oy->fifo_head->buffer->data; } - + /* space left in current fragment case */ if(oy->fifo_head->buffer->size- oy->fifo_head->length- @@ -608,7 +622,7 @@ unsigned char *ogg_sync_bufferin(ogg_sync_state *oy, long bytes){ ogg_buffer_realloc(oy->fifo_head,bytes); return oy->fifo_head->buffer->data+oy->fifo_head->begin; } - + /* current fragment used/full; get new fragment */ { ogg_reference *new=ogg_buffer_alloc(oy->bufferpool,bytes); @@ -618,15 +632,18 @@ unsigned char *ogg_sync_bufferin(ogg_sync_state *oy, long bytes){ return oy->fifo_head->buffer->data; } -int ogg_sync_wrote(ogg_sync_state *oy, long bytes){ +int ogg_sync_wrote(ogg_sync_state *oy, long bytes){ if(!oy->fifo_head)return OGG_EINVAL; - if(oy->fifo_head->buffer->size-oy->fifo_head->length-oy->fifo_head->begin < + if(oy->fifo_head->buffer->size-oy->fifo_head->length-oy->fifo_head->begin < bytes)return OGG_EINVAL; oy->fifo_head->length+=bytes; oy->fifo_fill+=bytes; return OGG_SUCCESS; } +#ifdef _ARM_ASSEM_ +ogg_uint32_t _checksum(ogg_reference *or, int bytes); +#else static ogg_uint32_t _checksum(ogg_reference *or, int bytes){ ogg_uint32_t crc_reg=0; int j,post; @@ -642,7 +659,7 @@ static ogg_uint32_t _checksum(ogg_reference *or, int bytes){ return crc_reg; } - +#endif /* sync the stream. This is meant to be useful for finding page boundaries. @@ -651,7 +668,7 @@ static ogg_uint32_t _checksum(ogg_reference *or, int bytes){ -n) skipped n bytes 0) page not ready; more data (no bytes skipped) n) page synced at current location; page length n bytes - + */ long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){ @@ -665,7 +682,7 @@ long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){ if(oy->headerbytes==0){ if(bytes<27)goto sync_out; /* not enough for even a minimal header */ - + /* verify capture pattern */ if(oggbyte_read1(&page,0)!=(int)'O' || oggbyte_read1(&page,1)!=(int)'g' || @@ -682,7 +699,7 @@ long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){ for(i=0;i<oy->headerbytes-27;i++) oy->bodybytes+=oggbyte_read1(&page,27+i); } - + if(oy->bodybytes+oy->headerbytes>bytes)goto sync_out; /* we have what appears to be a complete page; last test: verify @@ -693,11 +710,11 @@ long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){ /* Compare checksums; memory continues to be common access */ if(chksum!=_checksum(oy->fifo_tail,oy->bodybytes+oy->headerbytes)){ - + /* D'oh. Mismatch! Corrupt page (or miscapture and not a page at all). replace the computed checksum with the one actually read in; remember all the memory is common access */ - + oggbyte_set4(&page,chksum,22); goto sync_fail; } @@ -717,7 +734,7 @@ long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){ ogg_buffer_pretruncate(oy->fifo_tail,oy->headerbytes+oy->bodybytes); if(!oy->fifo_tail)oy->fifo_head=0; } - + ret=oy->headerbytes+oy->bodybytes; oy->unsynced=0; oy->headerbytes=0; @@ -725,20 +742,20 @@ long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og){ oy->fifo_fill-=ret; return ret; - + sync_fail: oy->headerbytes=0; oy->bodybytes=0; oy->fifo_tail=ogg_buffer_pretruncate(oy->fifo_tail,1); ret--; - + /* search forward through fragments for possible capture */ while(oy->fifo_tail){ /* invariant: fifo_cursor points to a position in fifo_tail */ unsigned char *now=oy->fifo_tail->buffer->data+oy->fifo_tail->begin; unsigned char *next=memchr(now, 'O', oy->fifo_tail->length); - + if(next){ /* possible capture in this segment */ long bytes=next-now; @@ -786,7 +803,7 @@ int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og){ /* need more data */ return 0; } - + /* head did not start a synced page... skipped some bytes */ if(!oy->unsynced){ oy->unsynced=1; @@ -812,22 +829,37 @@ int ogg_sync_reset(ogg_sync_state *oy){ return OGG_SUCCESS; } +void ogg_stream_init(ogg_stream_state *os, int serialno){ + memset(os, 0, sizeof(*os)); + os->serialno=serialno; + os->pageno=-1; +} + ogg_stream_state *ogg_stream_create(int serialno){ ogg_stream_state *os=_ogg_calloc(1,sizeof(*os)); os->serialno=serialno; os->pageno=-1; return os; -} +} + +int ogg_stream_clear(ogg_stream_state *os){ + if(os){ + ogg_buffer_release(os->header_tail); + ogg_buffer_release(os->body_tail); + memset(os,0,sizeof(*os)); + } + return OGG_SUCCESS; +} int ogg_stream_destroy(ogg_stream_state *os){ if(os){ ogg_buffer_release(os->header_tail); ogg_buffer_release(os->body_tail); - memset(os,0,sizeof(*os)); + memset(os,0,sizeof(*os)); _ogg_free(os); } return OGG_SUCCESS; -} +} #define FINFLAG 0x80000000UL @@ -847,9 +879,9 @@ static void _next_lace(oggbyte_buffer *ob,ogg_stream_state *os){ } } -static void _span_queued_page(ogg_stream_state *os){ +static void _span_queued_page(ogg_stream_state *os){ while( !(os->body_fill&FINFLAG) ){ - + if(!os->header_tail)break; /* first flush out preceeding page header (if any). Body is @@ -866,7 +898,7 @@ static void _span_queued_page(ogg_stream_state *os){ os->header_head=0; break; }else{ - + /* process/prepare next page, if any */ long pageno; @@ -877,7 +909,7 @@ static void _span_queued_page(ogg_stream_state *os){ oggbyte_init(&ob,os->header_tail); os->lacing_fill=oggbyte_read1(&ob,26); - + /* are we in sequence? */ if(pageno!=os->pageno){ if(os->pageno==-1) /* indicates seek or reset */ @@ -891,12 +923,12 @@ static void _span_queued_page(ogg_stream_state *os){ os->body_fill=0; } - + if(ogg_page_continued(&og)){ if(os->body_fill==0){ /* continued packet, but no preceeding data to continue */ /* dump the first partial packet on the page */ - _next_lace(&ob,os); + _next_lace(&ob,os); os->body_tail= ogg_buffer_pretruncate(os->body_tail,os->body_fill_next&FINMASK); if(os->body_tail==0)os->body_head=0; @@ -928,11 +960,11 @@ static void _span_queued_page(ogg_stream_state *os){ _next_lace(&ob,os); } - + os->pageno=pageno+1; os->e_o_s=ogg_page_eos(&og); os->b_o_s=ogg_page_bos(&og); - + } } } @@ -947,11 +979,11 @@ int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og){ /* check the serial number */ if(serialno!=os->serialno){ - ogg_page_release(og); + //ogg_page_release(og); return OGG_ESERIAL; } if(version>0){ - ogg_page_release(og); + //ogg_page_release(og); return OGG_EVERSION; } @@ -1074,7 +1106,7 @@ static int _packetout(ogg_stream_state *os,ogg_packet *op,int adv){ op->bytes=os->body_fill&FINMASK; } } - + if(adv){ os->packetno++; os->b_o_s=0; |