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

📄 framing.c

📁 au1200 linux2.6.11 硬件解码mae驱动和maiplayer播放器源码
💻 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 <stdio.h>#include <stdlib.h>#include <string.h>#include "ogg.h"#include "misc.h"#define dprintf(stuff) /* printf stuff *//* 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));  dprintf(("ogg_buffer_create bs %p  %d bytes\n", bs, 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;    if (!bs->outstanding)    {      dprintf(("_ogg_buffer_destroy free bs %p\n", bs));      _ogg_free(bs);//      return;     // commenting this line out lets the function free the rest of the allocated memory    }    while (bt)    {      ogg_buffer      *b = bt;      bt = b->ptr.next;      if (b->data)      {        dprintf(("_ogg_buffer_destroy free b->data %p\n", b->data));        _ogg_free(b->data);      }      dprintf(("_ogg_buffer_destroy free b %p\n", b));      _ogg_free(b);    }    bs->unused_buffers = 0;    while (rt)    {      ogg_reference   *r = rt;      rt = r->next;      dprintf(("_ogg_buffer_destroy free r %p\n", r));      _ogg_free(r);    }    bs->unused_references = 0;  }}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)    {      dprintf(("_fetch_buffer AAA free ob->data %p\n", ob->data));      ob->data = _ogg_realloc(ob->data, bytes);      dprintf(("_fetch_buffer AAA ob->data %p  %d bytes\n", ob->data, bytes));      ob->size = bytes;    }  }  else   {    /* allocate a new buffer */    ob = _ogg_malloc(sizeof(*ob));    dprintf(("_fetch_buffer CCC ob %p  %d bytes\n", ob, bytes));    ob->data = _ogg_malloc(bytes < 16 ? 16 : bytes);    dprintf(("_fetch_buffer CCC ob->data %p  %d bytes\n", ob->data, bytes));    ob->size = bytes;  }  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));    dprintf(("_fetch_ref  or %p  %d bytes\n", or, 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(ob->data, bytes);    dprintf(("ogg_buffer_realloc ob->data %p  %d bytes\n", 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)  {    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;

⌨️ 快捷键说明

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