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

📄 matroskaparser.c

📁 大名鼎鼎的CE下播放软件,TCPPMP的源代码!!!2410下可以流畅的解QVGA的H264,MPEG4等格式.
💻 C
📖 第 1 页 / 共 5 页
字号:
		case 0x96: // CueRefTime
		  readUInt(mf,(unsigned)len);
		  break;
		case 0x97: // CueRefCluster
		  readUInt(mf,(unsigned)len);
		  break;
		case 0x535f: // CueRefNumber
		  readUInt(mf,(unsigned)len);
		  break;
		case 0xeb: // CueRefCodecState
		  readUInt(mf,(unsigned)len);
		  break;
	      ENDFOR(mf);
	      break;
	  ENDFOR(mf);
	  break;
      ENDFOR(mf);

      if (mf->nCues == 0 && mf->pCluster - mf->pSegment != cc.Position)
	addCue(mf,mf->pCluster - mf->pSegment,mf->firstTimecode);

      memcpy(AGET(mf,Cues),&cc,sizeof(cc));
      break;
  ENDFOR(mf);

  memcpy(&mf->jb,&jb,sizeof(jb));

  ARELEASE(mf,mf,Cues);

  // bubble sort the cues and fuck the losers that write unordered cues
  if (mf->nCues > 0)
    for (i = mf->nCues - 1, k = 1; i > 0 && k > 0; --i)
      for (j = k = 0; j < i; ++j)
	if (mf->Cues[j].Time > mf->Cues[j+1].Time) {
	  struct Cue tmp = mf->Cues[j+1];
	  mf->Cues[j+1] = mf->Cues[j];
	  mf->Cues[j] = tmp;
	  ++k;
	}

  fixupCues(mf);
}

static void parseAttachment(MatroskaFile *mf,ulonglong toplen) {
  struct Attachment a,*pa;

  memset(&a,0,sizeof(a));
  FOREACH(mf,toplen)
    case 0x467e: // Description
      STRGETA(mf,a.Description,len);
      break;
    case 0x466e: // Name
      STRGETA(mf,a.Name,len);
      break;
    case 0x4660: // MimeType
      STRGETA(mf,a.MimeType,len);
      break;
    case 0x46ae: // UID
      a.UID = readUInt(mf,(unsigned)len);
      break;
    case 0x465c: // Data
      a.Position = filepos(mf);
      a.Length = len;
      skipbytes(mf,len);
      break;
  ENDFOR(mf);

  if (!a.Position)
    return;

  pa = AGET(mf,Attachments);
  memcpy(pa,&a,sizeof(a));

  if (a.Description)
    pa->Description = mystrdup(mf->cache,a.Description);
  if (a.Name)
    pa->Name = mystrdup(mf->cache,a.Name);
  if (a.MimeType)
    pa->MimeType = mystrdup(mf->cache,a.MimeType);
}

static void parseAttachments(MatroskaFile *mf,ulonglong toplen) {
  mf->seen.Attachments = 1;

  FOREACH(mf,toplen)
    case 0x61a7: // AttachedFile
      parseAttachment(mf,len);
      break;
  ENDFOR(mf);
}

static void parseChapter(MatroskaFile *mf,ulonglong toplen,struct Chapter *parent) {
  struct ChapterDisplay	*disp;
  struct ChapterProcess	*proc;
  struct ChapterCommand	*cmd;
  struct Chapter	*ch = ASGET(mf,parent,Children);

  memset(ch,0,sizeof(*ch));

  ch->Enabled = 1;

  FOREACH(mf,toplen)
    case 0x73c4: // ChapterUID
      ch->UID = readUInt(mf,(unsigned)len);
      break;
    case 0x6e67: // ChapterSegmentUID
      if (len != sizeof(ch->SegmentUID))
	skipbytes(mf, len);
      else
	readbytes(mf, ch->SegmentUID, sizeof(ch->SegmentUID));
      break;
    case 0x91: // ChapterTimeStart
      ch->Start = readUInt(mf,(unsigned)len);
      break;
    case 0x92: // ChapterTimeEnd
      ch->End = readUInt(mf,(unsigned)len);
      break;
    case 0x98: // ChapterFlagHidden
      ch->Hidden = readUInt(mf,(unsigned)len)!=0;
      break;
    case 0x4598: // ChapterFlagEnabled
      ch->Enabled = readUInt(mf,(unsigned)len)!=0;
      break;
    case 0x8f: // ChapterTrack
      FOREACH(mf,len)
	case 0x89: // ChapterTrackNumber
	  *(ulonglong*)(ASGET(mf,ch,Tracks)) = readUInt(mf,(unsigned)len);
	  break;
      ENDFOR(mf);
      break;
    case 0x80: // ChapterDisplay
      disp = NULL;

      FOREACH(mf,len)
	case 0x85: // ChapterString
	  if (disp==NULL) {
	    disp = ASGET(mf,ch,Display);
	    memset(disp, 0, sizeof(*disp));
	  }
	  if (disp->String)
	    skipbytes(mf,len); // Ignore duplicate string
	  else
	    STRGETM(mf,disp->String,len);
	  break;
	case 0x437c: // ChapterLanguage
	  if (disp==NULL) {
	    disp = ASGET(mf,ch,Display);
	    memset(disp, 0, sizeof(*disp));
	  }
	  if (disp->Language)
	    skipbytes(mf,len);
	  else
	    STRGETM(mf,disp->Language,len);
	  break;
	case 0x437e: // ChapterCountry
	  if (disp==NULL) {
	    disp = ASGET(mf,ch,Display);
	    memset(disp, 0, sizeof(*disp));
	  }
	  if (disp->Country)
	    skipbytes(mf,len);
	  else
	    STRGETM(mf,disp->Country,len);
	  break;
      ENDFOR(mf);

      if (disp && !disp->String) {
	mf->cache->memfree(mf->cache,disp->Language);
	mf->cache->memfree(mf->cache,disp->Country);
	--ch->nDisplay;
      }
      break;
    case 0x6944: // ChapProcess
      proc = NULL;

      FOREACH(mf,len)
	case 0x6955: // ChapProcessCodecID
	  if (proc == NULL) {
	    proc = ASGET(mf, ch, Process);
	    memset(proc, 0, sizeof(*proc));
	  }
	  proc->CodecID = (unsigned)readUInt(mf,(unsigned)len);
	  break;
	case 0x450d: // ChapProcessPrivate
	  if (proc == NULL) {
	    proc = ASGET(mf, ch, Process);
	    memset(proc, 0, sizeof(*proc));
	  }
	  if (proc->CodecPrivate)
	    skipbytes(mf, len);
	  else {
	    proc->CodecPrivateLength = (unsigned)len;
	    STRGETM(mf,proc->CodecPrivate,len);
	  }
	  break;
	case 0x6911: // ChapProcessCommand
	  if (proc == NULL) {
	    proc = ASGET(mf, ch, Process);
	    memset(proc, 0, sizeof(*proc));
	  }

	  cmd = NULL;

	  FOREACH(mf,len)
	    case 0x6922: // ChapterCommandTime
	      if (cmd == NULL) {
		cmd = ASGET(mf,proc,Commands);
		memset(cmd, 0, sizeof(*cmd));
	      }
	      cmd->Time = (unsigned)readUInt(mf,(unsigned)len);
	      break;
	    case 0x6933: // ChapterCommandString
	      if (cmd == NULL) {
		cmd = ASGET(mf,proc,Commands);
		memset(cmd, 0, sizeof(*cmd));
	      }
	      if (cmd->Command)
		skipbytes(mf,len);
	      else {
		cmd->CommandLength = (unsigned)len;
		STRGETM(mf,cmd->Command,len);
	      }
	      break;
	  ENDFOR(mf);

	  if (cmd && !cmd->Command)
	    --proc->nCommands;
	  break;
      ENDFOR(mf);

      if (proc && !proc->nCommands)
	--ch->nProcess;
      break;
    case 0xb6: // Nested ChapterAtom
      parseChapter(mf,len,ch);
      break;
  ENDFOR(mf);

  ARELEASE(mf,ch,Tracks);
  ARELEASE(mf,ch,Display);
  ARELEASE(mf,ch,Children);
}

static void parseChapters(MatroskaFile *mf,ulonglong toplen) {
  struct Chapter  *ch;

  mf->seen.Chapters = 1;

  FOREACH(mf,toplen)
    case 0x45b9: // EditionEntry
	ch = AGET(mf,Chapters);
	memset(ch, 0, sizeof(*ch));
 	FOREACH(mf,len)
	  case 0x45bc: // EditionUID
	    ch->UID = readUInt(mf,(unsigned)len);
	    break;
	  case 0x45bd: // EditionFlagHidden
	    ch->Hidden = readUInt(mf,(unsigned)len)!=0;
	    break;
	  case 0x45db: // EditionFlagDefault
	    ch->Default = readUInt(mf,(unsigned)len)!=0;
	    break;
	  case 0x45dd: // EditionFlagOrdered
	    ch->Ordered = readUInt(mf,(unsigned)len)!=0;
	    break;
	  case 0xb6: // ChapterAtom
	    parseChapter(mf,len,ch);
	    break;
	ENDFOR(mf);
      break;
  ENDFOR(mf);
}

static void parseTags(MatroskaFile *mf,ulonglong toplen) {
  struct Tag  *tag;
  struct Target *target;
  struct SimpleTag *st;

  mf->seen.Tags = 1;

  FOREACH(mf,toplen)
    case 0x7373: // Tag
      tag = AGET(mf,Tags);
      memset(tag,0,sizeof(*tag));

      FOREACH(mf,len)
	case 0x63c0: // Targets
	  FOREACH(mf,len)
	    case 0x63c5: // TrackUID
	      target = ASGET(mf,tag,Targets);
	      target->UID = readUInt(mf,(unsigned)len);
	      target->Type = TARGET_TRACK;
	      break;
	    case 0x63c4: // ChapterUID
	      target = ASGET(mf,tag,Targets);
	      target->UID = readUInt(mf,(unsigned)len);
	      target->Type = TARGET_CHAPTER;
	      break;
	    case 0x63c6: // AttachmentUID
	      target = ASGET(mf,tag,Targets);
	      target->UID = readUInt(mf,(unsigned)len);
	      target->Type = TARGET_ATTACHMENT;
	      break;
	    case 0x63c9: // EditionUID
	      target = ASGET(mf,tag,Targets);
	      target->UID = readUInt(mf,(unsigned)len);
	      target->Type = TARGET_EDITION;
	      break;
	  ENDFOR(mf);
	  break;
	case 0x67c8: // SimpleTag
	  st = ASGET(mf,tag,SimpleTags);
	  memset(st,0,sizeof(*st));

	  FOREACH(mf,len)
	    case 0x45a3: // TagName
	      if (st->Name)
		skipbytes(mf,len);
	      else
		STRGETM(mf,st->Name,len);
	      break;
	    case 0x4487: // TagString
	      if (st->Value)
		skipbytes(mf,len);
	      else
		STRGETM(mf,st->Value,len);
	      break;
	    case 0x447a: // TagLanguage
	      if (st->Language)
		skipbytes(mf,len);
	      else
		STRGETM(mf,st->Language,len);
	      break;
	    case 0x4484: // TagDefault
	      st->Default = readUInt(mf,(unsigned)len)!=0;
	      break;
	  ENDFOR(mf);

	  if (!st->Name || !st->Value) {
	    mf->cache->memfree(mf->cache,st->Name);
	    mf->cache->memfree(mf->cache,st->Value);
	    mf->cache->memfree(mf->cache,st->Language); //Picard
	    --tag->nSimpleTags;
	  }
	  break;
      ENDFOR(mf);
      break;
  ENDFOR(mf);
}

static void parseContainer(MatroskaFile *mf) {
  ulonglong len;
  int	    id = readID(mf);
  if (id==EOF)
    errorjmp(mf,"Unexpected EOF in parseContainer");

  len = readSize(mf);

  switch (id) {
    case 0x1549a966: // SegmentInfo
      parseSegmentInfo(mf,len);
      break;
    case 0x1f43b675: // Cluster
      parseFirstCluster(mf,len);
      break;
    case 0x1654ae6b: // Tracks
      parseTracks(mf,len);
      break;
    case 0x1c53bb6b: // Cues
      parseCues(mf,len);
      break;
    case 0x1941a469: // Attachments
      parseAttachments(mf,len);
      break;
    case 0x1043a770: // Chapters
      parseChapters(mf,len);
      break;
    case 0x1254c367: // Tags
      parseTags(mf,len);
      break;
  }
}

static void parseContainerPos(MatroskaFile *mf,ulonglong pos) {
  seek(mf,pos);
  parseContainer(mf);
}

static void parsePointers(MatroskaFile *mf) {
  jmp_buf		jb;

  if (mf->pSegmentInfo && !mf->seen.SegmentInfo)
    parseContainerPos(mf,mf->pSegmentInfo);
  if (mf->pCluster && !mf->seen.Cluster)
    parseContainerPos(mf,mf->pCluster);
  if (mf->pTracks && !mf->seen.Tracks)
    parseContainerPos(mf,mf->pTracks);

  memcpy(&jb,&mf->jb,sizeof(jb));

  if (setjmp(mf->jb)) 
    mf->flags &= ~MPF_ERROR; // ignore errors
  else {
    if (mf->pCues && !mf->seen.Cues)
	parseContainerPos(mf,mf->pCues);
    if (mf->pAttachments && !mf->seen.Attachments)
      parseContainerPos(mf,mf->pAttachments);
    if (mf->pChapters && !mf->seen.Chapters)
      parseContainerPos(mf,mf->pChapters);
    if (mf->pTags && !mf->seen.Tags)
      parseContainerPos(mf,mf->pTags);
  }

  memcpy(&mf->jb,&jb,sizeof(jb));
}

static void parseSegment(MatroskaFile *mf,ulonglong toplen) {
  ulonglong   nextpos;
  unsigned    nSeekHeads = 0, dontstop = 0;

  // we want to read data until we find a seekhead or a trackinfo
  FOREACH(mf,toplen)
    case 0x114d9b74: // SeekHead
      if (mf->flags & MKVF_AVOID_SEEKS) {
	skipbytes(mf,len);
	break;
      }

      nextpos = filepos(mf) + len;
      do {
	mf->pSeekHead = 0;
	parseSeekHead(mf,len);
	++nSeekHeads;
	if (mf->pSeekHead) { // this is possibly a chained SeekHead
	  seek(mf,mf->pSeekHead);
	  id = readID(mf);
	  if (id==EOF) // chained SeekHead points to EOF?
	    break;
	  if (id != 0x114d9b74) // chained SeekHead doesnt point to a SeekHead?
	    break;
	  len = readSize(mf);
	} else if (mf->pSegmentInfo && mf->pTracks && mf->pCues && mf->pCluster) { // we have pointers to all key elements
	  // XXX EVIL HACK
	  // Some software doesnt index tags via SeekHead, so we continue
	  // reading the segment after the second SeekHead
	  if (mf->pTags || nSeekHeads<2 || filepos(mf)>=start+toplen) {
	    parsePointers(mf);
	    return;
	  }
	  // reset nextpos pointer to current position
	  nextpos = filepos(mf);
	  dontstop = 1;
	}
      } while (mf->pSeekHead);
      seek(mf,nextpos); // resume reading segment
      break;
    case 0x1549a966: // SegmentInfo
      mf->pSegmentInfo = cur;
      parseSegmentInfo(mf,len);
      break;
    case 0x1f43b675: // Cluster
      if (!mf->pCluster)
	mf->pCluster = cur;
      if (mf->seen.Cluster)
	skipbytes(mf,len);
      else
	parseFirstCluster(mf,len);
      break;
    case 0x1654ae6b: // Tracks
      mf->pTracks = cur;
      parseTracks(mf,len);
      break;
    case 0x1c53bb6b: // Cues
      mf->pCues = cur;
      parseCues(mf,len);
      break;
    case 0x1941a469: // Attachments
      mf->pAttachments = cur;
      parseAttachments(mf,len);
      break;
    case 0x1043a770: // Chapters
      mf->pChapters = cur;
      parseChapters(mf,len);
      break;
    case 0x1254c367: // Tags
      mf->pTags = cur;
      parseTags(mf,len);
      break;
  ENDFOR1(mf);
    // if we have pointers to all key elements
    if (!dontstop && mf->pSegmentInfo && mf->pTracks && mf->pCluster)
      break;
  ENDFOR2();
  parsePointers(mf);
}

static void parseBlockAdditions(MatroskaFile *mf, ulonglong toplen, ulonglong timecode, unsigned track) {
  ulonglong	add_id = 1, add_pos=0, add_len=0; //Picard
  unsigned char	have_add;
  void* add_ref = NULL;

  FOREACH(mf, toplen)
    case 0xa6: // BlockMore
      have_add = 0;
      FOREACH(mf, len)
	case 0xee: // BlockAddId
	  add_id = readUInt(mf, (unsigned)len);
	  break;
	case 0xa5: // BlockAddition
	  add_pos = filepos(mf);
	  add_len = len;
	  if (!have_add) add_ref = mf->cache->makeref(mf->cache,(int)len); else //Picard
	  skipbytes(mf, len);
	  ++have_add;
	  break;
      ENDFOR(mf);
      if (have_add == 1 && id > 0 && id < 255) {
	struct QueueEntry *qe = QAlloc(mf);
	qe->Start = qe->End = timecode;
	qe->Position = add_pos;
	qe->Length = (unsigned)add_len;
	qe->Ref = add_ref; //Picard
	add_ref = NULL;
	qe->flags = FRAME_UNKNOWN_START | FRAME_UNKNOWN_END |
	  (((unsigned)add_id << FRAME_STREAM_SHIFT) & FRAME_STREAM_MASK);

⌨️ 快捷键说明

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