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

📄 matroskaparser.c

📁 大名鼎鼎的CE下播放软件,TCPPMP的源代码!!!2410下可以流畅的解QVGA的H264,MPEG4等格式.
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * Copyright (c) 2004-2005 Mike Matsnev.  All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice immediately at the beginning of the file, without modification,
 *    this list of conditions, and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Absolutely no warranty of function or purpose is made by the author
 *    Mike Matsnev.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * $Id: MatroskaParser.c,v 1.47 2005/07/06 18:44:40 mike Exp $
 * 
 */

/* modified for TCPMP by Picard 14/08/2005 */

#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
//Picard
#if !defined(__palmos__) || !defined(ARM) 
#include <setjmp.h>
#else
#ifndef EOF
#define EOF -1
#endif
typedef int jmp_buf[16];
int setjmp(jmp_buf jp);
int longjmp(jmp_buf jp, int ret);
#define alloca(size) __builtin_alloca(size)
#endif

#ifdef _WIN32
// MS names some functions differently
#define	alloca	  _alloca
#define	inline	  __inline

#include <tchar.h>
#endif

#ifndef EVCBUG
#define	EVCBUG
#endif

#include "MatroskaParser.h"

#ifdef MATROSKA_COMPRESSION_SUPPORT
#include "../../common/zlib/zlib.h" //Picard
//#include <zlib.h>
#endif

#define	EBML_VERSION	      1
#define	EBML_MAX_ID_LENGTH    4
#define	EBML_MAX_SIZE_LENGTH  8
#define	MATROSKA_VERSION      1
#define	MATROSKA_DOCTYPE      "matroska"

#define	MAX_STRING_LEN	      1023
#define	QSEGSIZE	      512
#define	MAX_TRACKS	      32
#define	MAX_READAHEAD	      (512*1024)

#define	MAXCLUSTER	      (64*1048576)
#define	MAXFRAME	      (4*1048576)

#ifdef WIN32
#define	LL(x)	x##i64
#define	ULL(x)	x##ui64
#else
#define	LL(x)	x##ll
#define	ULL(x)	x##ull
#endif

#define	MAXU64		      ULL(0xffffffffffffffff)
#define	ONE		      ULL(1)

// compatibility
static char  *mystrdup(struct InputStream *is,const char *src) {
  size_t  len;
  char	  *dst;

  if (src==NULL)
    return NULL;

  len = strlen(src);
  dst = is->memalloc(is,len+1);
  if (dst==NULL)
    return NULL;

  memcpy(dst,src,len+1);

  return dst;
}

#if defined(_WIN32) || defined(__palmos__) //Picard
static void  strlcpy(char *dst,const char *src,unsigned size) {
  unsigned  i;

  for (i=0;i+1<size && src[i];++i)
    dst[i] = src[i];
  if (i<size)
    dst[i] = 0;
}
#endif

struct Cue {
  ulonglong	Time;
  ulonglong	Position;
  ulonglong	Block;
  unsigned char	Track;
};

struct QueueEntry {
  struct QueueEntry *next;
  unsigned int	    Length;

  ulonglong	    Start;
  ulonglong	    End;
  ulonglong	    Position;
  void			*Ref; //Picard

  unsigned int	    flags;
};

struct Queue {
  struct QueueEntry *head;
  struct QueueEntry *tail;
};

#define	MPF_ERROR 0x10000
#define	IBSZ	  1024

#define	RBRESYNC  1

struct MatroskaFile {
  // parser config
  unsigned    flags;

  // input
  InputStream *cache;

  // internal buffering
  char	      inbuf[IBSZ];
  ulonglong   bufbase; // file offset of the first byte in buffer
  int	      bufpos; // current read position in buffer
  int	      buflen; // valid bytes in buffer

  // error reporting
  char	      errmsg[128];
  jmp_buf     jb;

  // pointers to key elements
  ulonglong   pSegment;
  ulonglong   pSeekHead;
  ulonglong   pSegmentInfo;
  ulonglong   pCluster;
  ulonglong   pTracks;
  ulonglong   pCues;
  ulonglong   pAttachments;
  ulonglong   pChapters;
  ulonglong   pTags;

  // flags for key elements
  struct {
    unsigned int  SegmentInfo:1;
    unsigned int  Cluster:1;
    unsigned int  Tracks:1;
    unsigned int  Cues:1;
    unsigned int  Attachments:1;
    unsigned int  Chapters:1;
    unsigned int  Tags:1;
  } seen;

  // file info
  ulonglong   firstTimecode;

  // SegmentInfo
  struct SegmentInfo  Seg;

  // Tracks
  unsigned int	    nTracks,nTracksSize;
  struct TrackInfo  **Tracks;

  // Queues
  struct QueueEntry *QFreeList;
  unsigned int	    nQBlocks,nQBlocksSize;
  struct QueueEntry **QBlocks;
  struct Queue	    *Queues;
  ulonglong	    readPosition;
  unsigned int	    trackMask;
  ulonglong	    pSegmentTop;  // offset of next byte after the segment
  ulonglong	    tcCluster;    // current cluster timecode

  // Cues
  unsigned int	    nCues,nCuesSize;
  struct Cue	    *Cues;

  // Attachments
  unsigned int	    nAttachments,nAttachmentsSize;
  struct Attachment *Attachments;

  // Chapters
  unsigned int	    nChapters,nChaptersSize;
  struct Chapter    *Chapters;

  // Tags
  unsigned int	    nTags,nTagsSize;
  struct Tag	    *Tags;
};

///////////////////////////////////////////////////////////////////////////
// error reporting
static void   myvsnprintf_string(char **pdest,char *de,const char *str) {
  char	*dest = *pdest;

  while (dest < de && *str)
    *dest++ = *str++;

  *pdest = dest;
}

static void   myvsnprintf_uint_impl(char **pdest,char *de,int width,int zero,
				    int neg,unsigned base,int letter,
				    int ms,ulonglong val)
{
  char	*dest = *pdest;
  char	tmp[21]; /* enough for 64 bit ints */
  char	*np = tmp + sizeof(tmp);
  int	rw,pad,trail;
  char	pc = zero ? '0' : ' ';

  *--np = '\0';
  while (val != 0) {
    int	  rem = (int)(val % base);
    val = val / base;

    *--np = rem < 10 ? rem + '0' : rem - 10 + letter;
  }

  rw = (int)(tmp - np + sizeof(tmp) - 1);
  if (ms)
    ++rw;

  pad = trail = 0;

  if (rw < width)
    pad = width - rw;

  if (neg)
    trail = pad, pad = 0;

  if (dest < de && ms)
    *dest++ = '-';

  while (dest < de && pad--)
    *dest++ = pc;

  while (dest < de && *np)
    *dest++ = *np++;

  while (dest < de && trail--)
    *dest++ = ' ';

  *pdest = dest;
}

static void   myvsnprintf_uint(char **pdest,char *de,int width,int zero,
			       int neg,unsigned base,int letter,
			       ulonglong val)
{
  myvsnprintf_uint_impl(pdest,de,width,zero,neg,base,letter,0,val);
}

static void   myvsnprintf_int(char **pdest,char *de,int width,int zero,
			      int neg,unsigned base,int letter,
			      longlong val)
{
  if (val < 0)
    myvsnprintf_uint_impl(pdest,de,width,zero,neg,base,letter,1,-val);
  else
    myvsnprintf_uint_impl(pdest,de,width,zero,neg,base,letter,0,val);
}

static void   myvsnprintf(char *dest,unsigned dsize,const char *fmt,va_list ap) {
  // s,d,x,u,ll
  char	    *de = dest + dsize - 1;
  int	    state = 0, width=0, zero=0, neg=0, ll=0; //Picard

  if (dsize <= 1) {
    if (dsize > 0)
      *dest = '\0';
    return;
  }

  while (*fmt && dest < de)
    switch (state) {
      case 0:
	if (*fmt == '%') {
	  ++fmt;
	  state = 1;
	  width = zero = neg = ll = 0;
	} else
	  *dest++ = *fmt++;
	break;
      case 1:
	if (*fmt == '-') {
	  neg = 1;
	  ++fmt;
	  state = 2;
	  break;
	}
	state = 2;
      case 2:
	if (*fmt >= '0' && *fmt <= '9') {
	  width = width * 10 + *fmt++ - '0';
	  break;
	}
	state = 3;
      case 3:
	if (*fmt == 'l') {
	  ++ll;
	  ++fmt;
	  break;
	}
	state = 4;
      case 4:
	switch (*fmt) {
	  case 's':
	    myvsnprintf_string(&dest,de,va_arg(ap,const char *));
	    break;
	  case 'd':
	    switch (ll) {
	      case 0:
		myvsnprintf_int(&dest,de,width,zero,neg,10,'a',va_arg(ap,int));
		break;
	      case 1:
		myvsnprintf_int(&dest,de,width,zero,neg,10,'a',va_arg(ap,long));
		break;
	      case 2:
		myvsnprintf_int(&dest,de,width,zero,neg,10,'a',va_arg(ap,longlong));
		break;
	    }
	    break;
	  case 'u':
	    switch (ll) {
	      case 0:
		myvsnprintf_uint(&dest,de,width,zero,neg,10,'a',va_arg(ap,unsigned int));
		break;
	      case 1:
		myvsnprintf_uint(&dest,de,width,zero,neg,10,'a',va_arg(ap,unsigned long));
		break;
	      case 2:
		myvsnprintf_uint(&dest,de,width,zero,neg,10,'a',va_arg(ap,ulonglong));
		break;
	    }
	    break;
	  case 'x':
	    switch (ll) {
	      case 0:
		myvsnprintf_uint(&dest,de,width,zero,neg,16,'a',va_arg(ap,unsigned int));
		break;
	      case 1:
		myvsnprintf_uint(&dest,de,width,zero,neg,16,'a',va_arg(ap,unsigned long));
		break;
	      case 2:
		myvsnprintf_uint(&dest,de,width,zero,neg,16,'a',va_arg(ap,ulonglong));
		break;
	    }
	    break;
	  case 'X':
	    switch (ll) {
	      case 0:
		myvsnprintf_uint(&dest,de,width,zero,neg,16,'A',va_arg(ap,unsigned int));
		break;
	      case 1:
		myvsnprintf_uint(&dest,de,width,zero,neg,16,'A',va_arg(ap,unsigned long));
		break;
	      case 2:
		myvsnprintf_uint(&dest,de,width,zero,neg,16,'A',va_arg(ap,ulonglong));
		break;
	    }
	    break;
	  default:
	    break;
	}
	++fmt;
	state = 0;
	break;
      default:
	state = 0;
	break;
    }
  *dest = '\0';
}

static void   errorjmp(MatroskaFile *mf,const char *fmt, ...) {
  va_list   ap;

  va_start(ap, fmt);
  myvsnprintf(mf->errmsg,sizeof(mf->errmsg),fmt,ap);
  va_end(ap);

  mf->flags |= MPF_ERROR;

  longjmp(mf->jb,1);
}

///////////////////////////////////////////////////////////////////////////
// arrays
static void *ArrayAlloc(MatroskaFile *mf,void **base,
			unsigned *cur,unsigned *max,unsigned elem_size)
{
  if (*cur>=*max) {
    void      *np;
    unsigned  newsize = *max * 2;
    if (newsize==0)
      newsize = 1;

    np = mf->cache->memrealloc(mf->cache,*base,newsize*elem_size);
    if (np==NULL)
      errorjmp(mf,"Out of memory in ArrayAlloc");

    *base = np;
    *max = newsize;
  }

  return (char*)*base + elem_size * (*cur)++;
}

static void ArrayReleaseMemory(MatroskaFile *mf,void **base,
			       unsigned cur,unsigned *max,unsigned elem_size)
{
  if (cur<*max) {
    void  *np = mf->cache->memrealloc(mf->cache,*base,cur*elem_size);
    *base = np;
    *max = cur;
  }
}


#define	ASGET(f,s,name)	  ArrayAlloc((f),(void**)&(s)->name,&(s)->n##name,&(s)->n##name##Size,sizeof(*((s)->name)))
#define	AGET(f,name)	  ArrayAlloc((f),(void**)&(f)->name,&(f)->n##name,&(f)->n##name##Size,sizeof(*((f)->name)))
#define	ARELEASE(f,s,name)  ArrayReleaseMemory((f),(void**)&(s)->name,(s)->n##name,&(s)->n##name##Size,sizeof(*((s)->name)))

///////////////////////////////////////////////////////////////////////////
// queues
static struct QueueEntry *QPut(struct Queue *q,struct QueueEntry *qe) {
  if (q->tail)
    q->tail->next = qe;
  qe->next = NULL;
  q->tail = qe;
  if (q->head==NULL)
    q->head = qe;

  return qe;
}

static struct QueueEntry  *QGet(struct Queue *q) {
  struct QueueEntry   *qe = q->head;
  if (qe == NULL)
    return NULL;
  q->head = qe->next;
  if (q->tail == qe)
    q->tail = NULL;
  return qe;
}

static struct QueueEntry  *QAlloc(MatroskaFile *mf) {
  struct QueueEntry   *qe,**qep;
  if (mf->QFreeList == NULL) {
    unsigned	      i;

    qep = AGET(mf,QBlocks);

    *qep = mf->cache->memalloc(mf->cache,QSEGSIZE * sizeof(*qe));
    if (*qep == NULL)
      errorjmp(mf,"Ouf of memory");

    qe = *qep;

    for (i=0;i<QSEGSIZE-1;++i)
      qe[i].next = qe+i+1;
    qe[QSEGSIZE-1].next = NULL;

    mf->QFreeList = qe;
  }

  qe = mf->QFreeList;
  mf->QFreeList = qe->next;

  return qe;
}

static inline void QFree(MatroskaFile *mf,struct QueueEntry *qe) {
  if (qe->Ref) mf->cache->releaseref(mf->cache,qe->Ref); //Picard
  qe->next = mf->QFreeList;
  mf->QFreeList = qe;
}

//Picard
/*
// fill the buffer at current position
static void fillbuf(MatroskaFile *mf) {
  int	    rd;

  // advance buffer pointers
  mf->bufbase += mf->buflen;

⌨️ 快捷键说明

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