static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){ codec_setup_info *ci=vi->codec_setup; int j; vorbis_info_floor0 *info=_ogg_malloc(sizeof(*info)); info->order=oggpack_read(opb,8); info->rate=oggpack_read(opb,16); info->barkmap=oggpack_read(opb,16); info->ampbits=oggpack_read(opb,6); info->ampdB=oggpack_read(opb,8); info->numbooks=oggpack_read(opb,4)+1; if(info->order<1)goto err_out; if(info->rate<1)goto err_out; if(info->barkmap<1)goto err_out; if(info->numbooks<1)goto err_out; for(j=0;j<info->numbooks;j++){ info->books[j]=oggpack_read(opb,8); if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out; if(ci->book_param[info->books[j]]->maptype==0)goto err_out; if(ci->book_param[info->books[j]]->dim<1)goto err_out; } return(info); err_out: floor0_free_info(info); return(NULL); }
static PyObject * py_ogg_oggpack_read(PyObject *self, PyObject *args) { int size; long c_out; oggpack_buffer * b; int bits; PyArg_ParseTuple(args, "s#i", &b, &size, &bits); c_out = oggpack_read(b, bits); return Py_BuildValue("l", c_out); };
/* used to track pcm position without actually performing decode. Useful for sequential 'fast forward' */ int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op){ vorbis_dsp_state *vd=vb->vd; private_state *b=vd->backend_state; vorbis_info *vi=vd->vi; codec_setup_info *ci=vi->codec_setup; oggpack_buffer *opb=&vb->opb; int mode; /* first things first. Make sure decode is ready */ _vorbis_block_ripcord(vb); oggpack_readinit(opb,op->packet,op->bytes); /* Check the packet type */ if(oggpack_read(opb,1)!=0){ /* Oops. This is not an audio data packet */ return(OV_ENOTAUDIO); } /* read our mode and pre/post windowsize */ mode=oggpack_read(opb,b->modebits); if(mode==-1)return(OV_EBADPACKET); vb->mode=mode; vb->W=ci->mode_param[mode]->blockflag; if(vb->W){ vb->lW=oggpack_read(opb,1); vb->nW=oggpack_read(opb,1); if(vb->nW==-1) return(OV_EBADPACKET); }else{ vb->lW=0; vb->nW=0; } /* more setup */ vb->granulepos=op->granulepos; vb->sequence=op->packetno; vb->eofflag=op->e_o_s; /* no pcm */ vb->pcmend=0; vb->pcm=NULL; return(0); }
static vorbis_info_floor *floor1_unpack (vorbis_info *vi,oggpack_buffer *opb){ codec_setup_info *ci=vi->codec_setup; int j,k,count=0,maxclass=-1,rangebits; vorbis_info_floor1 *info=_ogg_calloc(1,sizeof(*info)); /* read partitions */ info->partitions=oggpack_read(opb,5); /* only 0 to 31 legal */ for(j=0;j<info->partitions;j++){ info->partitionclass[j]=oggpack_read(opb,4); /* only 0 to 15 legal */ if(maxclass<info->partitionclass[j])maxclass=info->partitionclass[j]; } /* read partition classes */ for(j=0;j<maxclass+1;j++){ info->class_dim[j]=oggpack_read(opb,3)+1; /* 1 to 8 */ info->class_subs[j]=oggpack_read(opb,2); /* 0,1,2,3 bits */ if(info->class_subs[j]<0) goto err_out; if(info->class_subs[j])info->class_book[j]=oggpack_read(opb,8); if(info->class_book[j]<0 || info->class_book[j]>=ci->books) goto err_out; for(k=0;k<(1<<info->class_subs[j]);k++){ info->class_subbook[j][k]=oggpack_read(opb,8)-1; if(info->class_subbook[j][k]<-1 || info->class_subbook[j][k]>=ci->books) goto err_out; } } /* read the post list */ info->mult=oggpack_read(opb,2)+1; /* only 1,2,3,4 legal now */ rangebits=oggpack_read(opb,4); for(j=0,k=0;j<info->partitions;j++){ count+=info->class_dim[info->partitionclass[j]]; for(;k<count;k++){ int t=info->postlist[k+2]=oggpack_read(opb,rangebits); if(t<0 || t>=(1<<rangebits)) goto err_out; } } info->postlist[0]=0; info->postlist[1]=1<<rangebits; return(info); err_out: floor1_free_info(info); return(NULL); }
static int _tarkin_unpack_comment (TarkinComment * vc, oggpack_buffer * opb) { int i; int vendorlen = oggpack_read (opb, 32); #ifdef DBG_OGG printf ("dbg_ogg: Decoding comment: "); #endif if (vendorlen < 0) goto err_out; vc->vendor = _ogg_calloc (vendorlen + 1, 1); _v_readstring (opb, vc->vendor, vendorlen); vc->comments = oggpack_read (opb, 32); if (vc->comments < 0) goto err_out; vc->user_comments = _ogg_calloc (vc->comments + 1, sizeof (*vc->user_comments)); vc->comment_lengths = _ogg_calloc (vc->comments + 1, sizeof (*vc->comment_lengths)); for (i = 0; i < vc->comments; i++) { int len = oggpack_read (opb, 32); if (len < 0) goto err_out; vc->comment_lengths[i] = len; vc->user_comments[i] = _ogg_calloc (len + 1, 1); _v_readstring (opb, vc->user_comments[i], len); } if (oggpack_read (opb, 1) != 1) goto err_out; /* EOP check */ #ifdef DBG_OGG printf ("Success, read %d comments\n", vc->comments); #endif return (0); err_out: #ifdef DBG_OGG printf ("Failed\n"); #endif tarkin_comment_clear (vc); return (-TARKIN_BAD_HEADER); }
int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){ oggpack_buffer opb; if(op){ oggpack_readinit(&opb,op->packet); /* Which of the three types of header is this? */ /* Also verify header-ness, vorbis */ { char buffer[6]; int packtype=oggpack_read(&opb,8); memset(buffer,0,6); _v_readstring(&opb,buffer,6); if(memcmp(buffer,"vorbis",6)){ /* not a vorbis header */ return(OV_ENOTVORBIS); } switch(packtype){ case 0x01: /* least significant *bit* is read first */ if(!op->b_o_s){ /* Not the initial packet */ return(OV_EBADHEADER); } if(vi->rate!=0){ /* previously initialized info header */ return(OV_EBADHEADER); } return(_vorbis_unpack_info(vi,&opb)); case 0x03: /* least significant *bit* is read first */ if(vi->rate==0){ /* um... we didn't get the initial header */ return(OV_EBADHEADER); } return(_vorbis_unpack_comment(vc,&opb)); case 0x05: /* least significant *bit* is read first */ if(vi->rate==0 || vc->vendor==NULL){ /* um... we didn;t get the initial header or comments yet */ return(OV_EBADHEADER); } return(_vorbis_unpack_books(vi,&opb)); default: /* Not a valid vorbis header type */ return(OV_EBADHEADER); break; } } } return(OV_EBADHEADER); }
TarkinError tarkin_synthesis_headerin(TarkinInfo *vi,TarkinComment *vc,ogg_packet *op){ oggpack_buffer opb; if(op){ oggpack_readinit(&opb,op->packet,op->bytes); /* Which of the three types of header is this? */ /* Also verify header-ness, tarkin */ { char buffer[6]; int packtype=oggpack_read(&opb,8); memset(buffer,0,6); _v_readstring(&opb,buffer,6); if(memcmp(buffer,"tarkin",6)){ /* not a tarkin header */ return(-TARKIN_NOT_TARKIN); } switch(packtype){ case 0x01: /* least significant *bit* is read first */ if(!op->b_o_s){ /* Not the initial packet */ return(-TARKIN_BAD_HEADER); } if(vi->inter.numerator!=0){ /* previously initialized info header */ return(-TARKIN_BAD_HEADER); } return(_tarkin_unpack_info(vi,&opb)); case 0x03: /* least significant *bit* is read first */ if(vi->inter.denominator==0){ /* um... we didn't get the initial header */ return(-TARKIN_BAD_HEADER); } return(_tarkin_unpack_comment(vc,&opb)); case 0x05: /* least significant *bit* is read first */ if(vi->inter.numerator == 0 || vc->vendor==NULL){ /* um... we didn;t get the initial header or comments yet */ return(-TARKIN_BAD_HEADER); } return(_tarkin_unpack_layer_desc(vi,&opb)); default: /* Not a valid tarkin header type */ return(-TARKIN_BAD_HEADER); break; } } } return(-TARKIN_BAD_HEADER); }
/* * Class: org_tritonus_lowlevel_ogg_Buffer * Method: read * Signature: (I)I */ JNIEXPORT jint JNICALL Java_org_tritonus_lowlevel_ogg_Buffer_read (JNIEnv* env, jobject obj, jint nBits) { oggpack_buffer* handle; int nReturn; if (debug_flag) { fprintf(debug_file, "Java_org_tritonus_lowlevel_ogg_Buffer_read(): begin\n"); } handle = getHandle(env, obj); nReturn = oggpack_read(handle, nBits); if (debug_flag) { fprintf(debug_file, "Java_org_tritonus_lowlevel_ogg_Buffer_read(): end\n"); } return nReturn; }
static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i) { vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; vorbis_info_floor0 *info=look->vi; int j,k; int ampraw=oggpack_read(&vb->opb,info->ampbits); if(ampraw>0) /* also handles the -1 out of data case */ { long maxval=(1<<info->ampbits)-1; float amp=(float)ampraw/maxval*info->ampdB; int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks)); if(booknum!=-1 && booknum<info->numbooks) /* be paranoid */ { codec_setup_info *ci=vb->vd->vi->codec_setup; codebook *b=ci->fullbooks+info->books[booknum]; float last=0.f; /* the additional b->dim is a guard against any possible stack smash; b->dim is provably more than we can overflow the vector */ float *lsp=_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1)); for(j=0; j<look->m; j+=b->dim) if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim)==-1)goto eop; for(j=0; j<look->m;) { for(k=0; k<b->dim; k++,j++)lsp[j]+=last; last=lsp[j-1]; } lsp[look->m]=amp; return(lsp); } } eop: return(NULL); }
long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){ codec_setup_info *ci=vi->codec_setup; oggpack_buffer opb; int mode; if(ci==NULL || ci->modes<=0){ /* codec setup not properly intialized */ return(OV_EFAULT); } oggpack_readinit(&opb,op->packet,op->bytes); /* Check the packet type */ if(oggpack_read(&opb,1)!=0){ /* Oops. This is not an audio data packet */ return(OV_ENOTAUDIO); } /* read our mode and pre/post windowsize */ mode=oggpack_read(&opb,ov_ilog(ci->modes-1)); if(mode==-1 || !ci->mode_param[mode])return(OV_EBADPACKET); return(ci->blocksizes[ci->mode_param[mode]->blockflag]); }
/* vorbis_info is for range checking */ int res_unpack(vorbis_info_residue *info, vorbis_info *vi,oggpack_buffer *opb){ int j,k; codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; memset(info,0,sizeof(*info)); info->type=oggpack_read(opb,16); if(info->type>2 || info->type<0)goto errout; info->begin=oggpack_read(opb,24); info->end=oggpack_read(opb,24); info->grouping=oggpack_read(opb,24)+1; info->partitions=oggpack_read(opb,6)+1; info->groupbook=oggpack_read(opb,8); if(info->groupbook>=ci->books)goto errout; info->stagemasks=_ogg_malloc(info->partitions*sizeof(*info->stagemasks)); info->stagebooks=_ogg_malloc(info->partitions*8*sizeof(*info->stagebooks)); for(j=0;j<info->partitions;j++){ int cascade=oggpack_read(opb,3); if(oggpack_read(opb,1)) cascade|=(oggpack_read(opb,5)<<3); info->stagemasks[j]=cascade; } for(j=0;j<info->partitions;j++){ for(k=0;k<8;k++){ if((info->stagemasks[j]>>k)&1){ unsigned char book=oggpack_read(opb,8); if(book>=ci->books)goto errout; info->stagebooks[j*8+k]=book; if(k+1>info->stages)info->stages=k+1; }else info->stagebooks[j*8+k]=0xff; } }
static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){ int vendorlen; vendorlen=oggpack_read(opb,32); if(vendorlen<0)goto err_out; if(vendorlen>opb->storage-oggpack_bytes(opb))goto err_out; vc->vendor=(char *)_ogg_calloc(vendorlen+1,1); if(vc->vendor==NULL)goto err_out; _v_readstring(opb,vc->vendor,vendorlen); vc->comments=0; /* ROCKBOX: the meat of this function was deleted as we don't need it */ return(0); err_out: vorbis_comment_clear(vc); return(OV_EBADHEADER); }
static int _tarkin_unpack_info (TarkinInfo * vi, oggpack_buffer * opb) { #ifdef DBG_OGG printf ("dbg_ogg: Decoding Info: "); #endif vi->version = oggpack_read (opb, 32); if (vi->version != 0) return (-TARKIN_VERSION); vi->n_layers = oggpack_read (opb, 8); vi->inter.numerator = oggpack_read (opb, 32); vi->inter.denominator = oggpack_read (opb, 32); vi->bitrate_upper = oggpack_read (opb, 32); vi->bitrate_nominal = oggpack_read (opb, 32); vi->bitrate_lower = oggpack_read (opb, 32); #ifdef DBG_OGG printf (" n_layers %d, interleave: %d/%d, ", vi->n_layers, vi->inter.numerator, vi->inter.denominator); #endif if (vi->inter.numerator < 1) goto err_out; if (vi->inter.denominator < 1) goto err_out; if (vi->n_layers < 1) goto err_out; if (oggpack_read (opb, 1) != 1) goto err_out; /* EOP check */ #ifdef DBG_OGG printf ("Success\n"); #endif return (0); err_out: #ifdef DBG_OGG printf ("Failed\n"); #endif tarkin_info_clear (vi); return (-TARKIN_BAD_HEADER); }
static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){ codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; if(!ci)return(OV_EFAULT); vi->version=oggpack_read(opb,32); if(vi->version!=0)return(OV_EVERSION); vi->channels=oggpack_read(opb,8); vi->rate=oggpack_read(opb,32); vi->bitrate_upper=oggpack_read(opb,32); vi->bitrate_nominal=oggpack_read(opb,32); vi->bitrate_lower=oggpack_read(opb,32); ci->blocksizes[0]=1<<oggpack_read(opb,4); ci->blocksizes[1]=1<<oggpack_read(opb,4); #ifdef LIMIT_TO_64kHz if(vi->rate>=64000 || ci->blocksizes[1]>4096)goto err_out; #else if(vi->rate<64000 && ci->blocksizes[1]>4096)goto err_out; #endif if(vi->rate<1)goto err_out; if(vi->channels<1)goto err_out; if(ci->blocksizes[0]<64)goto err_out; if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out; if(ci->blocksizes[1]>8192)goto err_out; if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ return(0); err_out: vorbis_info_clear(vi); return(OV_EBADHEADER); }
static ogg_uint32_t decpack(long entry,long used_entry,long quantvals, codebook *b,oggpack_buffer *opb,int maptype){ ogg_uint32_t ret=0; int j; switch(b->dec_type){ case 0: return (ogg_uint32_t)entry; case 1: if(maptype==1){ /* vals are already read into temporary column vector here */ for(j=0;j<b->dim;j++){ ogg_uint32_t off=entry%quantvals; entry/=quantvals; ret|=((ogg_uint16_t *)(b->q_val))[off]<<(b->q_bits*j); } }else{ for(j=0;j<b->dim;j++) ret|=oggpack_read(opb,b->q_bits)<<(b->q_bits*j); } return ret; case 2: for(j=0;j<b->dim;j++){ ogg_uint32_t off=entry%quantvals; entry/=quantvals; ret|=off<<(b->q_pack*j); } return ret; case 3: return (ogg_uint32_t)used_entry; } return 0; /* silence compiler */ }
/* Is this packet a vorbis ID header? */ int vorbis_synthesis_idheader(ogg_packet *op){ oggpack_buffer opb; char buffer[6]; if(op){ oggpack_readinit(&opb,op->packet,op->bytes); if(!op->b_o_s) return(0); /* Not the initial packet */ if(oggpack_read(&opb,8) != 1) return 0; /* not an ID header */ memset(buffer,0,6); _v_readstring(&opb,buffer,6); if(memcmp(buffer,"vorbis",6)) return 0; /* not vorbis */ return 1; } return 0; }
/* all of the real encoding details are here. The modes, books, everything */ static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){ codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; int i; if(!ci)return(OV_EFAULT); /* codebooks */ ci->books=oggpack_read(opb,8)+1; /*ci->book_param=_ogg_calloc(ci->books,sizeof(*ci->book_param));*/ for(i=0;i<ci->books;i++){ ci->book_param[i]=(static_codebook *)_ogg_calloc(1,sizeof(*ci->book_param[i])); if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out; } /* time backend settings */ ci->times=oggpack_read(opb,6)+1; /*ci->time_type=_ogg_malloc(ci->times*sizeof(*ci->time_type));*/ /*ci->time_param=_ogg_calloc(ci->times,sizeof(void *));*/ for(i=0;i<ci->times;i++){ ci->time_type[i]=oggpack_read(opb,16); if(ci->time_type[i]<0 || ci->time_type[i]>=VI_TIMEB)goto err_out; /* ci->time_param[i]=_time_P[ci->time_type[i]]->unpack(vi,opb); Vorbis I has no time backend */ /*if(!ci->time_param[i])goto err_out;*/ } /* floor backend settings */ ci->floors=oggpack_read(opb,6)+1; /*ci->floor_type=_ogg_malloc(ci->floors*sizeof(*ci->floor_type));*/ /*ci->floor_param=_ogg_calloc(ci->floors,sizeof(void *));*/ for(i=0;i<ci->floors;i++){ ci->floor_type[i]=oggpack_read(opb,16); if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out; ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb); if(!ci->floor_param[i])goto err_out; } /* residue backend settings */ ci->residues=oggpack_read(opb,6)+1; /*ci->residue_type=_ogg_malloc(ci->residues*sizeof(*ci->residue_type));*/ /*ci->residue_param=_ogg_calloc(ci->residues,sizeof(void *));*/ for(i=0;i<ci->residues;i++){ ci->residue_type[i]=oggpack_read(opb,16); if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out; ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb); if(!ci->residue_param[i])goto err_out; } /* map backend settings */ ci->maps=oggpack_read(opb,6)+1; /*ci->map_type=_ogg_malloc(ci->maps*sizeof(*ci->map_type));*/ /*ci->map_param=_ogg_calloc(ci->maps,sizeof(void *));*/ for(i=0;i<ci->maps;i++){ ci->map_type[i]=oggpack_read(opb,16); if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out; ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb); if(!ci->map_param[i])goto err_out; } /* mode settings */ ci->modes=oggpack_read(opb,6)+1; /*vi->mode_param=_ogg_calloc(vi->modes,sizeof(void *));*/ for(i=0;i<ci->modes;i++){ ci->mode_param[i]=(vorbis_info_mode *)_ogg_calloc(1,sizeof(*ci->mode_param[i])); ci->mode_param[i]->blockflag=oggpack_read(opb,1); ci->mode_param[i]->windowtype=oggpack_read(opb,16); ci->mode_param[i]->transformtype=oggpack_read(opb,16); ci->mode_param[i]->mapping=oggpack_read(opb,8); if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out; if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out; if(ci->mode_param[i]->mapping>=ci->maps)goto err_out; } if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */ return(0); err_out: vorbis_info_clear(vi); return(OV_EBADHEADER); }
static void BURGERCALL _v_readstring(oggpack_buffer *o,char *buf,int bytes) { while(bytes--){ *buf++=(char)oggpack_read(o,8); } }
status_t OggVorbisSeekable::GetStreamInfo(int64 *frameCount, bigtime_t *duration, media_format *format) { TRACE("OggVorbisSeekable::GetStreamInfo\n"); status_t result = B_OK; ogg_packet packet; // get header packet if (GetHeaderPackets().size() < 1) { result = GetPacket(&packet); if (result != B_OK) { return result; } SaveHeaderPacket(packet); } packet = GetHeaderPackets()[0]; if (!packet.b_o_s) { return B_ERROR; // first packet was not beginning of stream } // parse header packet // based on libvorbis/info.c vorbis_synthesis_headerin(...) oggpack_buffer opb; oggpack_readinit(&opb, packet.packet, packet.bytes); int packtype = oggpack_read(&opb, 8); if (packtype != 0x01) { return B_ERROR; // first packet was not an info packet } // discard vorbis string for (uint i = 0 ; i < sizeof("vorbis") - 1 ; i++) { oggpack_read(&opb, 8); } vorbis_info info; if (_vorbis_unpack_info(&info, &opb) != 0) { return B_ERROR; // couldn't unpack info } // get the format for the description media_format_description description = vorbis_description(); BMediaFormats formats; result = formats.InitCheck(); if (result == B_OK) { result = formats.GetFormatFor(description, format); } if (result != B_OK) { *format = vorbis_encoded_media_format(); // ignore error, allow user to use ReadChunk interface } // fill out format from header packet if (info.bitrate_nominal > 0) { format->u.encoded_audio.bit_rate = info.bitrate_nominal; } else if (info.bitrate_upper > 0) { format->u.encoded_audio.bit_rate = info.bitrate_upper; } else if (info.bitrate_lower > 0) { format->u.encoded_audio.bit_rate = info.bitrate_lower; } if (info.channels == 1) { format->u.encoded_audio.multi_info.channel_mask = B_CHANNEL_LEFT; } else { format->u.encoded_audio.multi_info.channel_mask = B_CHANNEL_LEFT | B_CHANNEL_RIGHT; } fFrameRate = format->u.encoded_audio.output.frame_rate = (float)info.rate; format->u.encoded_audio.output.channel_count = info.channels; format->u.encoded_audio.output.buffer_size = AudioBufferSize(&format->u.encoded_audio.output); // get comment packet if (GetHeaderPackets().size() < 2) { result = GetPacket(&packet); if (result != B_OK) { return result; } SaveHeaderPacket(packet); } // get codebook packet if (GetHeaderPackets().size() < 3) { result = GetPacket(&packet); if (result != B_OK) { return result; } SaveHeaderPacket(packet); } format->SetMetaData((void*)&GetHeaderPackets(),sizeof(GetHeaderPackets())); // TODO: count the frames in the first page.. somehow.. :-/ int64 frames = 0; ogg_page page; // read the first page result = ReadPage(&page); if (result != B_OK) { return result; } int64 fFirstGranulepos = ogg_page_granulepos(&page); TRACE("OggVorbisSeekable::GetStreamInfo: first granulepos: %lld\n", fFirstGranulepos); // read our last page off_t last = inherited::Seek(GetLastPagePosition(), SEEK_SET); if (last < 0) { return last; } result = ReadPage(&page); if (result != B_OK) { return result; } int64 last_granulepos = ogg_page_granulepos(&page); // seek back to the start int64 frame = 0; bigtime_t time = 0; result = Seek(B_MEDIA_SEEK_TO_TIME, &frame, &time); if (result != B_OK) { return result; } // compute frame count and duration from sample count frames = last_granulepos - fFirstGranulepos; *frameCount = frames; *duration = (1000000LL * frames) / (long long)fFrameRate; return B_OK; }
status_t MyVorbisExtractor::verifyHeader( MediaBuffer *buffer, uint8_t type) { const uint8_t *data = (const uint8_t *)buffer->data() + buffer->range_offset(); size_t size = buffer->range_length(); if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) { return ERROR_MALFORMED; } ogg_buffer buf; buf.data = (uint8_t *)data; buf.size = size; buf.refcount = 1; buf.ptr.owner = NULL; ogg_reference ref; ref.buffer = &buf; ref.begin = 0; ref.length = size; ref.next = NULL; oggpack_buffer bits; oggpack_readinit(&bits, &ref); CHECK_EQ(oggpack_read(&bits, 8), type); for (size_t i = 0; i < 6; ++i) { oggpack_read(&bits, 8); // skip 'vorbis' } switch (type) { case 1: { CHECK_EQ(0, _vorbis_unpack_info(&mVi, &bits)); mMeta->setData(kKeyVorbisInfo, 0, data, size); mMeta->setInt32(kKeySampleRate, mVi.rate); mMeta->setInt32(kKeyChannelCount, mVi.channels); LOGV("lower-bitrate = %ld", mVi.bitrate_lower); LOGV("upper-bitrate = %ld", mVi.bitrate_upper); LOGV("nominal-bitrate = %ld", mVi.bitrate_nominal); LOGV("window-bitrate = %ld", mVi.bitrate_window); off64_t size; if (mSource->getSize(&size) == OK) { uint64_t bps = approxBitrate(); if(0 != bps && bps < 10000000) { mMeta->setInt64(kKeyDuration, size * 8000000ll / bps); } else { uint64_t lastGranule, tDuration; lastGranule= findLastGranule(); tDuration = lastGranule*1000000/mVi.rate; mMeta->setInt64(kKeyDuration, tDuration); bps = size * 8000000ll / tDuration; mMeta->setInt64(kKeyBitRate, size * 8000000ll / tDuration); mVi.bitrate_nominal = bps; } } break; } case 3: { if (0 != _vorbis_unpack_comment(&mVc, &bits)) { return ERROR_MALFORMED; } parseFileMetaData(); break; } case 5: { if (0 != _vorbis_unpack_books(&mVi, &bits)) { return ERROR_MALFORMED; } mMeta->setData(kKeyVorbisBooks, 0, data, size); break; } } return OK; }
static inline int _vorbis_synthesis1(vorbis_block *vb,ogg_packet *op,int decodep){ vorbis_dsp_state *vd= vb ? vb->vd : 0; private_state *b= vd ? (private_state *)vd->backend_state: 0; vorbis_info *vi= vd ? vd->vi : 0; codec_setup_info *ci= vi ? (codec_setup_info *)vi->codec_setup : 0; oggpack_buffer *opb=vb ? &vb->opb : 0; int type,mode,i; if (!vd || !b || !vi || !ci || !opb) { return OV_EBADPACKET; } /* first things first. Make sure decode is ready */ _vorbis_block_ripcord(vb); oggpack_readinit(opb,op->packet,op->bytes); /* Check the packet type */ if(oggpack_read(opb,1)!=0){ /* Oops. This is not an audio data packet */ return(OV_ENOTAUDIO); } /* read our mode and pre/post windowsize */ mode=oggpack_read(opb,b->modebits); if(mode==-1)return(OV_EBADPACKET); vb->mode=mode; if(!ci->mode_param[mode]){ return(OV_EBADPACKET); } vb->W=ci->mode_param[mode]->blockflag; if(vb->W){ vb->lW=oggpack_read(opb,1); vb->nW=oggpack_read(opb,1); if(vb->nW==-1) return(OV_EBADPACKET); }else{ vb->lW=0; vb->nW=0; } /* more setup */ vb->granulepos=op->granulepos; vb->sequence=op->packetno-3; /* first block is third packet */ vb->eofflag=op->e_o_s; if(decodep && vi->channels<=CHANNELS) { vb->pcm = ipcm_vect; /* set pcm end point */ vb->pcmend=ci->blocksizes[vb->W]; /* use statically allocated buffer */ if(vd->reset_pcmb || vb->pcm[0]==NULL) { /* one-time initialisation at codec start NOT for every block synthesis start allows us to flip between buffers once initialised by simply flipping pointers */ for(i=0; i<vi->channels; i++) vb->pcm[i] = &vd->first_pcm[i*ci->blocksizes[1]]; } vd->reset_pcmb = false; /* unpack_header enforces range checking */ type=ci->map_type[ci->mode_param[mode]->mapping]; return(_mapping_P[type]->inverse(vb,b->mode[mode])); }else{ /* no pcm */ vb->pcmend=0; vb->pcm=NULL; return(0); } }
/* all of the real encoding details are here. The modes, books, everything */ static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){ codec_setup_info *ci=vi->codec_setup; int i; if(!ci)return(OV_EFAULT); /* codebooks */ ci->books=oggpack_read(opb,8)+1; if(ci->books<=0)goto err_out; for(i=0;i<ci->books;i++){ ci->book_param[i]=vorbis_staticbook_unpack(opb); if(!ci->book_param[i])goto err_out; } /* time backend settings; hooks are unused */ { int times=oggpack_read(opb,6)+1; if(times<=0)goto err_out; for(i=0;i<times;i++){ int test=oggpack_read(opb,16); if(test<0 || test>=VI_TIMEB)goto err_out; } } /* floor backend settings */ ci->floors=oggpack_read(opb,6)+1; if(ci->floors<=0)goto err_out; for(i=0;i<ci->floors;i++){ ci->floor_type[i]=oggpack_read(opb,16); if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out; ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb); if(!ci->floor_param[i])goto err_out; } /* residue backend settings */ ci->residues=oggpack_read(opb,6)+1; if(ci->residues<=0)goto err_out; for(i=0;i<ci->residues;i++){ ci->residue_type[i]=oggpack_read(opb,16); if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out; ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb); if(!ci->residue_param[i])goto err_out; } /* map backend settings */ ci->maps=oggpack_read(opb,6)+1; if(ci->maps<=0)goto err_out; for(i=0;i<ci->maps;i++){ ci->map_type[i]=oggpack_read(opb,16); if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out; ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb); if(!ci->map_param[i])goto err_out; } /* mode settings */ ci->modes=oggpack_read(opb,6)+1; if(ci->modes<=0)goto err_out; for(i=0;i<ci->modes;i++){ ci->mode_param[i]=_ogg_calloc(1,sizeof(*ci->mode_param[i])); ci->mode_param[i]->blockflag=oggpack_read(opb,1); ci->mode_param[i]->windowtype=oggpack_read(opb,16); ci->mode_param[i]->transformtype=oggpack_read(opb,16); ci->mode_param[i]->mapping=oggpack_read(opb,8); if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out; if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out; if(ci->mode_param[i]->mapping>=ci->maps)goto err_out; if(ci->mode_param[i]->mapping<0)goto err_out; } if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */ return(0); err_out: vorbis_info_clear(vi); return(OV_EBADHEADER); }
/* also responsible for range checking */ int mapping_info_unpack(vorbis_info_mapping *info,vorbis_info *vi, oggpack_buffer *opb){ int i; codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; memset(info,0,sizeof(*info)); if(oggpack_read(opb,1)) info->submaps=oggpack_read(opb,4)+1; else info->submaps=1; if(oggpack_read(opb,1)){ info->coupling_steps=oggpack_read(opb,8)+1; info->coupling= _ogg_malloc(info->coupling_steps*sizeof(*info->coupling)); for(i=0;i<info->coupling_steps;i++){ int testM=info->coupling[i].mag=oggpack_read(opb,ilog(vi->channels)); int testA=info->coupling[i].ang=oggpack_read(opb,ilog(vi->channels)); if(testM<0 || testA<0 || testM==testA || testM>=vi->channels || testA>=vi->channels) goto err_out; } } if(oggpack_read(opb,2)>0)goto err_out; /* 2,3:reserved */ if(info->submaps>1){ info->chmuxlist=_ogg_malloc(sizeof(*info->chmuxlist)*vi->channels); for(i=0;i<vi->channels;i++){ info->chmuxlist[i]=oggpack_read(opb,4); if(info->chmuxlist[i]>=info->submaps)goto err_out; } } info->submaplist=_ogg_malloc(sizeof(*info->submaplist)*info->submaps); for(i=0;i<info->submaps;i++){ int temp=oggpack_read(opb,8); info->submaplist[i].floor=oggpack_read(opb,8); if(info->submaplist[i].floor>=ci->floors)goto err_out; info->submaplist[i].residue=oggpack_read(opb,8); if(info->submaplist[i].residue>=ci->residues)goto err_out; } return 0; err_out: mapping_clear_info(info); return -1; }
/* unpacks a codebook from the packet buffer into the codebook struct, readies the codebook auxiliary structures for decode *************/ int vorbis_staticbook_unpack(oggpack_buffer *opb,static_codebook *s){ long i,j; memset(s,0,sizeof(*s)); /* make sure alignment is correct */ if(oggpack_read(opb,24)!=0x564342)goto _eofout; /* first the basic parameters */ s->dim=oggpack_read(opb,16); s->entries=oggpack_read(opb,24); if(s->entries==-1)goto _eofout; /* codeword ordering.... length ordered or unordered? */ switch((int)oggpack_read(opb,1)){ case 0: /* unordered */ s->lengthlist=(long *)_ogg_malloc(sizeof(*s->lengthlist)*s->entries); /* allocated but unused entries? */ if(oggpack_read(opb,1)){ /* yes, unused entries */ for(i=0;i<s->entries;i++){ if(oggpack_read(opb,1)){ long num=oggpack_read(opb,5); if(num==-1)goto _eofout; s->lengthlist[i]=num+1; }else s->lengthlist[i]=0; } }else{ /* all entries used; no tagging */ for(i=0;i<s->entries;i++){ long num=oggpack_read(opb,5); if(num==-1)goto _eofout; s->lengthlist[i]=num+1; } } break; case 1: /* ordered */ { long length=oggpack_read(opb,5)+1; s->lengthlist=(long *)_ogg_malloc(sizeof(*s->lengthlist)*s->entries); for(i=0;i<s->entries;){ long num=oggpack_read(opb,_ilog(s->entries-i)); if(num==-1)goto _eofout; for(j=0;j<num && i<s->entries;j++,i++) s->lengthlist[i]=length; length++; } } break; default: /* EOF */ return(-1); } /* Do we have a mapping to unpack? */ switch((s->maptype=oggpack_read(opb,4))){ case 0: /* no mapping */ break; case 1: case 2: /* implicitly populated value mapping */ /* explicitly populated value mapping */ s->q_min=oggpack_read(opb,32); s->q_delta=oggpack_read(opb,32); s->q_quant=oggpack_read(opb,4)+1; s->q_sequencep=oggpack_read(opb,1); { int quantvals=0; switch(s->maptype){ case 1: quantvals=_book_maptype1_quantvals(s); break; case 2: quantvals=s->entries*s->dim; break; } /* quantized values */ s->quantlist=(long *)_ogg_malloc(sizeof(*s->quantlist)*quantvals); for(i=0;i<quantvals;i++) s->quantlist[i]=oggpack_read(opb,s->q_quant); if(quantvals&&s->quantlist[quantvals-1]==-1)goto _eofout; } break; default: goto _errout; } /* all set */ return(0); _errout: _eofout: vorbis_staticbook_clear(s); return(-1); }
/* also responsible for range checking */ static vorbis_info_mapping *mapping0_unpack(vorbis_info *vi,oggpack_buffer *opb){ int i; vorbis_info_mapping0 *info=_ogg_calloc(1,sizeof(*info)); codec_setup_info *ci=vi->codec_setup; memset(info,0,sizeof(*info)); if(oggpack_read(opb,1)) info->submaps=oggpack_read(opb,4)+1; else info->submaps=1; if(oggpack_read(opb,1)){ info->coupling_steps=oggpack_read(opb,8)+1; for(i=0;i<info->coupling_steps;i++){ int testM=info->coupling_mag[i]=oggpack_read(opb,ilog(vi->channels)); int testA=info->coupling_ang[i]=oggpack_read(opb,ilog(vi->channels)); if(testM<0 || testA<0 || testM==testA || testM>=vi->channels || testA>=vi->channels) goto err_out; } } if(oggpack_read(opb,2)>0)goto err_out; /* 2,3:reserved */ if(info->submaps>1){ for(i=0;i<vi->channels;i++){ info->chmuxlist[i]=oggpack_read(opb,4); if(info->chmuxlist[i]>=info->submaps)goto err_out; } } for(i=0;i<info->submaps;i++){ oggpack_read(opb,8); /* time submap unused */ info->floorsubmap[i]=oggpack_read(opb,8); if(info->floorsubmap[i]>=ci->floors)goto err_out; info->residuesubmap[i]=oggpack_read(opb,8); if(info->residuesubmap[i]>=ci->residues)goto err_out; } return info; err_out: mapping0_free_info(info); return(NULL); }
static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){ vorbis_look_floor1 *look=(vorbis_look_floor1 *)in; vorbis_info_floor1 *info=look->vi; codec_setup_info *ci=(codec_setup_info *)vb->vd->vi->codec_setup; int i,j,k; codebook *books=ci->fullbooks; /* unpack wrapped/predicted values from stream */ if(oggpack_read(&vb->opb,1)==1){ int *fit_value=(int *)_vorbis_block_alloc(vb,(look->posts)*sizeof(*fit_value)); fit_value[0]=oggpack_read(&vb->opb,ilog(look->quant_q-1)); fit_value[1]=oggpack_read(&vb->opb,ilog(look->quant_q-1)); /* partition by partition */ /* partition by partition */ for(i=0,j=2;i<info->partitions;i++){ int classv=info->partitionclass[i]; int cdim=info->class_dim[classv]; int csubbits=info->class_subs[classv]; int csub=1<<csubbits; int cval=0; /* decode the partition's first stage cascade value */ if(csubbits){ cval=vorbis_book_decode(books+info->class_book[classv],&vb->opb); if(cval==-1)goto eop; } for(k=0;k<cdim;k++){ int book=info->class_subbook[classv][cval&(csub-1)]; cval>>=csubbits; if(book>=0){ if((fit_value[j+k]=vorbis_book_decode(books+book,&vb->opb))==-1) goto eop; }else{ fit_value[j+k]=0; } } j+=cdim; } /* unwrap positive values and reconsitute via linear interpolation */ for(i=2;i<look->posts;i++){ int predicted=render_point(info->postlist[look->loneighbor[i-2]], info->postlist[look->hineighbor[i-2]], fit_value[look->loneighbor[i-2]], fit_value[look->hineighbor[i-2]], info->postlist[i]); int hiroom=look->quant_q-predicted; int loroom=predicted; int room=(hiroom<loroom?hiroom:loroom)<<1; int val=fit_value[i]; if(val){ if(val>=room){ if(hiroom>loroom){ val = val-loroom; }else{ val = -1-(val-hiroom); } }else{ if(val&1){ val= -((val+1)>>1); }else{ val>>=1; } } fit_value[i]=val+predicted; fit_value[look->loneighbor[i-2]]&=0x7fff; fit_value[look->hineighbor[i-2]]&=0x7fff; }else{
int vorbis_synthesis(vorbis_block *vb,ogg_packet *op){ vorbis_dsp_state *vd= vb ? vb->vd : 0; private_state *b= vd ? vd->backend_state : 0; vorbis_info *vi= vd ? vd->vi : 0; codec_setup_info *ci= vi ? vi->codec_setup : 0; oggpack_buffer *opb=vb ? &vb->opb : 0; int type,mode,i; if (!vd || !b || !vi || !ci || !opb) { return OV_EBADPACKET; } /* first things first. Make sure decode is ready */ _vorbis_block_ripcord(vb); oggpack_readinit(opb,op->packet,op->bytes); /* Check the packet type */ if(oggpack_read(opb,1)!=0){ /* Oops. This is not an audio data packet */ return(OV_ENOTAUDIO); } /* read our mode and pre/post windowsize */ mode=oggpack_read(opb,b->modebits); if(mode==-1){ return(OV_EBADPACKET); } vb->mode=mode; if(!ci->mode_param[mode]){ return(OV_EBADPACKET); } vb->W=ci->mode_param[mode]->blockflag; if(vb->W){ /* this doesn;t get mapped through mode selection as it's used only for window selection */ vb->lW=oggpack_read(opb,1); vb->nW=oggpack_read(opb,1); if(vb->nW==-1){ return(OV_EBADPACKET); } }else{ vb->lW=0; vb->nW=0; } /* more setup */ vb->granulepos=op->granulepos; vb->sequence=op->packetno; vb->eofflag=op->e_o_s; /* alloc pcm passback storage */ vb->pcmend=ci->blocksizes[vb->W]; vb->pcm=_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels); for(i=0;i<vi->channels;i++) vb->pcm[i]=_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i])); /* unpack_header enforces range checking */ type=ci->map_type[ci->mode_param[mode]->mapping]; return(_mapping_P[type]->inverse(vb,ci->map_param[ci->mode_param[mode]-> mapping])); }
static vorbis_info_floor *floor1_unpack (vorbis_info *vi,oggpack_buffer *opb) { codec_setup_info *ci=(codec_setup_info*)vi->codec_setup; int j,k,count=0,maxclass=-1,rangebits; vorbis_info_floor1 *info=(vorbis_info_floor1*)_ogg_calloc(1,sizeof(*info)); /* read partitions */ info->partitions=oggpack_read(opb,5); /* only 0 to 31 legal */ for(j=0; j<info->partitions; j++) { info->partitionclass[j]=oggpack_read(opb,4); /* only 0 to 15 legal */ if(info->partitionclass[j]<0)goto err_out; if(maxclass<info->partitionclass[j])maxclass=info->partitionclass[j]; } /* read partition classes */ for(j=0; j<maxclass+1; j++) { info->class_dim[j]=oggpack_read(opb,3)+1; /* 1 to 8 */ info->class_subs[j]=oggpack_read(opb,2); /* 0,1,2,3 bits */ if(info->class_subs[j]<0) goto err_out; if(info->class_subs[j])info->class_book[j]=oggpack_read(opb,8); if(info->class_book[j]<0 || info->class_book[j]>=ci->books) goto err_out; for(k=0; k<(1<<info->class_subs[j]); k++) { info->class_subbook[j][k]=oggpack_read(opb,8)-1; if(info->class_subbook[j][k]<-1 || info->class_subbook[j][k]>=ci->books) goto err_out; } } /* read the post list */ info->mult=oggpack_read(opb,2)+1; /* only 1,2,3,4 legal now */ rangebits=oggpack_read(opb,4); if(rangebits<0)goto err_out; for(j=0,k=0; j<info->partitions; j++) { count+=info->class_dim[info->partitionclass[j]]; for(; k<count; k++) { int t=info->postlist[k+2]=oggpack_read(opb,rangebits); if(t<0 || t>=(1<<rangebits)) goto err_out; } } info->postlist[0]=0; info->postlist[1]=1<<rangebits; /* don't allow repeated values in post list as they'd result in zero-length segments */ { int *sortpointer[VIF_POSIT+2]; for(j=0; j<count+2; j++)sortpointer[j]=info->postlist+j; qsort(sortpointer,count+2,sizeof(*sortpointer),icomp); for(j=1; j<count+2; j++) if(*sortpointer[j-1]==*sortpointer[j])goto err_out; } return(info); err_out: floor1_free_info(info); return(NULL); }
/* helpers */ static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){ while(bytes--){ *buf++=oggpack_read(o,8); } }
/* the real encoding details are here, currently TarkinVideoLayerDesc. */ static int _tarkin_unpack_layer_desc (TarkinInfo * vi, oggpack_buffer * opb) { int i, j; vi->layer = CALLOC (vi->n_layers, (sizeof (*vi->layer))); memset (vi->layer, 0, vi->n_layers * sizeof (*vi->layer)); #ifdef DBG_OGG printf ("ogg: Decoding layers description: "); #endif for (i = 0; i < vi->n_layers; i++) { TarkinVideoLayer *layer = vi->layer + i; layer->desc.width = oggpack_read (opb, 32); layer->desc.height = oggpack_read (opb, 32); layer->desc.a_moments = oggpack_read (opb, 32); layer->desc.s_moments = oggpack_read (opb, 32); layer->desc.frames_per_buf = oggpack_read (opb, 32); layer->desc.bitstream_len = oggpack_read (opb, 32); layer->desc.format = oggpack_read (opb, 32); switch (layer->desc.format) { case TARKIN_GRAYSCALE: layer->n_comp = 1; layer->color_fwd_xform = grayscale_to_y; layer->color_inv_xform = y_to_grayscale; break; case TARKIN_RGB24: layer->n_comp = 3; layer->color_fwd_xform = rgb24_to_yuv; layer->color_inv_xform = yuv_to_rgb24; break; case TARKIN_RGB32: layer->n_comp = 3; layer->color_fwd_xform = rgb32_to_yuv; layer->color_inv_xform = yuv_to_rgb32; break; case TARKIN_RGBA: layer->n_comp = 4; layer->color_fwd_xform = rgba_to_yuv; layer->color_inv_xform = yuv_to_rgba; break; default: return -TARKIN_INVALID_COLOR_FORMAT; }; layer->waveletbuf = (Wavelet3DBuf **) CALLOC (layer->n_comp, sizeof (Wavelet3DBuf *)); layer->packet = MALLOC (layer->n_comp * sizeof (*layer->packet)); memset (layer->packet, 0, layer->n_comp * sizeof (*layer->packet)); for (j = 0; j < layer->n_comp; j++) { layer->waveletbuf[j] = wavelet_3d_buf_new (layer->desc.width, layer->desc.height, layer->desc.frames_per_buf); layer->packet[j].data = MALLOC (layer->desc.bitstream_len); layer->packet[j].storage = layer->desc.bitstream_len; } vi->max_bitstream_len += layer->desc.bitstream_len + 2 * 10 * sizeof (uint32_t) * layer->n_comp; /* truncation tables */ #ifdef DBG_OGG printf ("\n layer%d: size %dx%dx%d, format %d, a_m %d, s_m %d, %d fpb\n", i, layer->desc.width, layer->desc.height, layer->n_comp, layer->desc.format, layer->desc.a_moments, layer->desc.s_moments, layer->desc.frames_per_buf); #endif } /* for each layer */ if (oggpack_read (opb, 1) != 1) goto err_out; /* EOP check */ #ifdef DBG_OGG printf ("Success\n"); #endif return (0); err_out: #ifdef DBG_OGG printf ("Failed\n"); #endif tarkin_info_clear (vi); return (-TARKIN_BAD_HEADER); }