📄 info.c
字号:
/******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * * * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** function: maintain the info structure, info <-> header packets ********************************************************************//* general handling of the header and the vorbis_info structure (and substructures) */#include <stdlib.h>#include <string.h>#include <ctype.h>#include "ogg.h"#include "ivorbiscodec.h"#include "codec_internal.h"#include "codebook.h"#include "registry.h"#include "window.h"#include "misc.h"#include "os.h"/* helpers */static void _v_readstring(oggpack_buffer *o, char *buf, int bytes){ while (bytes--) { *buf++ = (char)oggpack_read(o, 8); }}void vorbis_comment_init(vorbis_comment *vc){ memset(vc, 0, sizeof(*vc));}/* This is more or less the same as strncasecmp - but that doesn't exist * everywhere, and this is a fairly trivial function, so we include it */static int tagcompare(const char *s1, const char *s2, int n){ int c = 0; while (c < n) { if (toupper(s1[c]) != toupper(s2[c])) return !0; c++; } return 0;}char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count){ long i; int found = 0; int taglen = strlen(tag) + 1; /* +1 for the = we append */ char *fulltag = (char *) alloca(taglen + 1); strcpy(fulltag, tag); strcat(fulltag, "="); for (i = 0; i < vc->comments; i++) { if (!tagcompare(vc->user_comments[i], fulltag, taglen)) { if (count == found) /* We return a pointer to the data, not a copy */ return vc->user_comments[i] + taglen; else found++; } } return NULL; /* didn't find anything */}int vorbis_comment_query_count(vorbis_comment *vc, char *tag){ int i, count = 0; int taglen = strlen(tag) + 1; /* +1 for the = we append */ char *fulltag = (char *) alloca(taglen + 1); strcpy(fulltag, tag); strcat(fulltag, "="); for (i = 0; i < vc->comments; i++) { if (!tagcompare(vc->user_comments[i], fulltag, taglen)) count++; } return count;}void vorbis_comment_clear(vorbis_comment *vc){ if (vc) { long i; for (i = 0; i < vc->comments; i++) if (vc->user_comments[i]) _ogg_free(vc->user_comments[i]); if (vc->user_comments) _ogg_free(vc->user_comments); if (vc->comment_lengths) _ogg_free(vc->comment_lengths); if (vc->vendor) _ogg_free(vc->vendor); } memset(vc, 0, sizeof(*vc));}/* blocksize 0 is guaranteed to be short, 1 is guarantted to be long. They may be equal, but short will never ge greater than long */int vorbis_info_blocksize(vorbis_info *vi, int zo){ codec_setup_info *ci = (codec_setup_info *) vi->codec_setup; return ci ? ci->blocksizes[zo] : - 1;}/* used by synthesis, which has a full, alloced vi */void vorbis_info_init(vorbis_info *vi){ memset(vi, 0, sizeof(*vi)); vi->codec_setup = (codec_setup_info *) _ogg_calloc(1, sizeof(codec_setup_info));}void vorbis_info_clear(vorbis_info *vi){ codec_setup_info *ci = (codec_setup_info *) vi->codec_setup; int i; if (ci) { for (i = 0; i < ci->modes; i++) if (ci->mode_param[i]) _ogg_free(ci->mode_param[i]); for (i = 0; i < ci->maps; i++) /* unpack does the range checking */ _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]); for (i = 0; i < ci->floors; i++) /* unpack does the range checking */ _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]); for (i = 0; i < ci->residues; i++) /* unpack does the range checking */ _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]); for (i = 0; i < ci->books; i++) { if (ci->book_param[i]) { /* knows if the book was not alloced */ vorbis_staticbook_destroy(ci->book_param[i]); } if (ci->fullbooks) vorbis_book_clear(ci->fullbooks + i); } if (ci->fullbooks) _ogg_free(ci->fullbooks); _ogg_free(ci); } memset(vi, 0, sizeof(*vi));}/* Header packing/unpacking ********************************************/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); 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 int _vorbis_unpack_comment(vorbis_comment *vc, oggpack_buffer *opb){ int i; int vendorlen = oggpack_read(opb, 32); if (vendorlen < 0) goto err_out; vc->vendor = (char *) _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 = (char * *) _ogg_calloc(vc->comments + 1, sizeof(*vc->user_comments)); vc->comment_lengths = (int *) _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] = (char *) _ogg_calloc(len + 1, 1); _v_readstring(opb, vc->user_comments[i], len); } if (oggpack_read(opb, 1) != 1) goto err_out; /* EOP check */ return (0);err_out: vorbis_comment_clear(vc); return (OV_EBADHEADER);}/* 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);}/* The Vorbis header is in three packets; the initial small packet in the first page that identifies basic parameters, a second packet with bitstream comments and a third packet that holds the codebook. */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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -