⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 framing.c

📁 大名鼎鼎的CE下播放软件,TCPPMP的源代码!!!2410下可以流畅的解QVGA的H264,MPEG4等格式.
💻 C
📖 第 1 页 / 共 3 页
字号:
/******************************************************************** *                                                                  * * 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: decode Ogg streams back into raw packets note: The CRC code is directly derived from public domain code by Ross Williams (ross@guest.adelaide.edu.au).  See docs/framing.html for details. ********************************************************************/#include <stdlib.h>#include <string.h>#include "ogg.h"#include "misc.h"/* A complete description of Ogg framing exists in docs/framing.html *//* basic, centralized Ogg memory management based on linked lists of   references to refcounted memory buffers.  References and buffers   are both recycled.  Buffers are passed around and consumed in   reference form. */static ogg_buffer_state *ogg_buffer_create(void){  ogg_buffer_state *bs=_ogg_calloc(1,sizeof(*bs));  return bs;}/* destruction is 'lazy'; there may be memory references outstanding,   and yanking the buffer state out from underneath would be   antisocial.  Dealloc what is currently unused and have   _release_one watch for the stragglers to come in.  When they do,   finish destruction. *//* call the helper while holding lock */static void _ogg_buffer_destroy(ogg_buffer_state *bs){  ogg_buffer *bt;  ogg_reference *rt;  if(bs->shutdown){    bt=bs->unused_buffers;    rt=bs->unused_references;    while(bt){      ogg_buffer *b=bt;      bt=b->ptr.next;
	  if(b->ext)oggext_release(b->ext,b->extdata);
	  else if(b->data)_ogg_free((void*)b->data);      _ogg_free(b);    }    bs->unused_buffers=0;    while(rt){      ogg_reference *r=rt;      rt=r->next;      _ogg_free(r);    }    bs->unused_references=0;
    if(!bs->outstanding){
      _ogg_free(bs);
      return;
    }
  }}static void ogg_buffer_destroy(ogg_buffer_state *bs){  bs->shutdown=1;  _ogg_buffer_destroy(bs);}static ogg_buffer *_fetch_buffer(ogg_buffer_state *bs,long bytes){  ogg_buffer    *ob;  bs->outstanding++;  /* do we have an unused buffer sitting in the pool? */  if(bs->unused_buffers){    ob=bs->unused_buffers;    bs->unused_buffers=ob->ptr.next;    /* if the unused buffer is too small, grow it */    if(ob->size<bytes){      ob->data=_ogg_realloc((void*)ob->data,bytes);      ob->size=bytes;    }
	if (bytes<0){
      if (ob->data) _ogg_free((void*)ob->data);
      ob->data=NULL;
	  ob->size=0;
    }
  }else{    /* allocate a new buffer */    ob=_ogg_malloc(sizeof(*ob));
	ob->ext = NULL;
	ob->extdata = NULL;
	if (bytes>=0){      ob->data=_ogg_malloc(bytes<16?16:bytes);      ob->size=bytes;
    } else{ 
      ob->data=NULL;
	  ob->size=0;
	}  }  ob->refcount=1;  ob->ptr.owner=bs;  return ob;}static ogg_reference *_fetch_ref(ogg_buffer_state *bs){  ogg_reference *or;  bs->outstanding++;  /* do we have an unused reference sitting in the pool? */  if(bs->unused_references){    or=bs->unused_references;    bs->unused_references=or->next;  }else{    /* allocate a new reference */    or=_ogg_malloc(sizeof(*or));  }  or->begin=0;  or->length=0;  or->next=0;  return or;}/* fetch a reference pointing to a fresh, initially continguous buffer   of at least [bytes] length */static ogg_reference *ogg_buffer_alloc(ogg_buffer_state *bs,long bytes){  ogg_buffer    *ob=_fetch_buffer(bs,bytes);  ogg_reference *or=_fetch_ref(bs);  or->buffer=ob;  return or;}/* 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((void*)ob->data,bytes);    ob->size=bytes;  }}static void _ogg_buffer_mark_one(ogg_reference *or){  or->buffer->refcount++;}/* increase the refcount of the buffers to which the reference points */static void ogg_buffer_mark(ogg_reference *or){  while(or){    _ogg_buffer_mark_one(or);    or=or->next;  }}/* duplicate a reference (pointing to the same actual buffer memory)   and increment buffer refcount.  If the desired segment begins out   of range, NULL is returned; if the desired segment is simply zero   length, a zero length ref is returned.  Partial range overlap   returns the overlap of the ranges */static ogg_reference *ogg_buffer_sub(ogg_reference *or,long begin,long length){  ogg_reference *ret=0,*head=0;  /* walk past any preceeding fragments we don't want */  while(or && begin>=or->length){    begin-=or->length;    or=or->next;  }  /* duplicate the reference chain; increment refcounts */  while(or && length){    ogg_reference *temp=_fetch_ref(or->buffer->ptr.owner);    if(head)      head->next=temp;    else      ret=temp;    head=temp;    head->buffer=or->buffer;        head->begin=or->begin+begin;    head->length=length;    if(head->length>or->length-begin)      head->length=or->length-begin;        begin=0;    length-=head->length;    or=or->next;  }  ogg_buffer_mark(ret);  return ret;}ogg_reference *ogg_buffer_dup(ogg_reference *or){  ogg_reference *ret=0,*head=0;  /* duplicate the reference chain; increment refcounts */  while(or){    ogg_reference *temp=_fetch_ref(or->buffer->ptr.owner);    if(head)      head->next=temp;    else      ret=temp;    head=temp;    head->buffer=or->buffer;        head->begin=or->begin;    head->length=or->length;    or=or->next;  }  ogg_buffer_mark(ret);  return ret;}/* split a reference into two references; 'return' is a reference to   the buffer preceeding pos and 'head'/'tail' are the buffer past the   split.  If pos is at or past the end of the passed in segment,   'head/tail' are NULL */static ogg_reference *ogg_buffer_split(ogg_reference **tail,                                ogg_reference **head,long pos){  /* walk past any preceeding fragments to one of:     a) the exact boundary that seps two fragments     b) the fragment that needs split somewhere in the middle */  ogg_reference *ret=*tail;  ogg_reference *or=*tail;  while(or && pos>or->length){    pos-=or->length;    or=or->next;  }  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;                /* update the first piece */      or->next=0;      or->length=lengthA;          }  }  return ret;}static void ogg_buffer_release_one(ogg_reference *or){  ogg_buffer *ob=or->buffer;  ogg_buffer_state *bs=ob->ptr.owner;  ob->refcount--;  if(ob->refcount==0){
    if (ob->ext) {
      oggext_release(ob->ext,ob->extdata);
	  ob->ext = NULL;
	  ob->extdata = NULL;
	  ob->data = NULL;
	  ob->size = 0;
    }
    bs->outstanding--; /* for the returned buffer */    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;  _ogg_buffer_destroy(bs); /* lazy cleanup (if needed) */}/* release the references, decrease the refcounts of buffers to which   they point, release any buffers with a refcount that drops to zero */static void ogg_buffer_release(ogg_reference *or){  while(or){    ogg_reference *next=or->next;    ogg_buffer_release_one(or);    or=next;  }}static ogg_reference *ogg_buffer_pretruncate(ogg_reference *or,long pos){  /* release preceeding fragments we don't want */  while(or && pos>=or->length){    ogg_reference *next=or->next;    pos-=or->length;    ogg_buffer_release_one(or);    or=next;  }  if (or) {    or->begin+=pos;    or->length-=pos;  }  return or;}static ogg_reference *ogg_buffer_walk(ogg_reference *or){  if(!or)return NULL;  while(or->next){    or=or->next;  }  return(or);}/* *head is appended to the front end (head) of *tail; both continue to   be valid pointers, with *tail at the tail and *head at the head */static ogg_reference *ogg_buffer_cat(ogg_reference *tail, ogg_reference *head){  if(!tail)return head;  while(tail->next){    tail=tail->next;  }  tail->next=head;  return ogg_buffer_walk(head);}static void _positionB(oggbyte_buffer *b,int pos){  if(pos<b->pos){    /* start at beginning, scan forward */    b->ref=b->baseref;    b->pos=0;    b->end=b->pos+b->ref->length;    b->ptr=b->ref->buffer->data+b->ref->begin;  }}static void _positionF(oggbyte_buffer *b,int pos){  /* scan forward for position */  while(pos>=b->end){    /* just seek forward */    b->pos+=b->ref->length;    b->ref=b->ref->next;    b->end=b->ref->length+b->pos;    b->ptr=b->ref->buffer->data+b->ref->begin;  }}static int oggbyte_init(oggbyte_buffer *b,ogg_reference *or){  memset(b,0,sizeof(*b));  if(or){    b->ref=b->baseref=or;    b->pos=0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -