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

📄 matroskaparser.c

📁 大名鼎鼎的CE下播放软件,TCPPMP的源代码!!!2410下可以流畅的解QVGA的H264,MPEG4等格式.
💻 C
📖 第 1 页 / 共 5 页
字号:
	errorjmp(mf,"SegmentUID size is not %d bytes",mf->Seg.UID);
      readbytes(mf,mf->Seg.UID,sizeof(mf->Seg.UID));
      break;
    case 0x7384: // SegmentFilename
      STRGETM(mf,mf->Seg.Filename,len);
      break;
    case 0x3cb923: // PrevUID
      if (len!=sizeof(mf->Seg.PrevUID))
	errorjmp(mf,"PrevUID size is not %d bytes",mf->Seg.PrevUID);
      readbytes(mf,mf->Seg.PrevUID,sizeof(mf->Seg.PrevUID));
      break;
    case 0x3c83ab: // PrevFilename
      STRGETM(mf,mf->Seg.PrevFilename,len);
      break;
    case 0x3eb923: // NextUID
      if (len!=sizeof(mf->Seg.NextUID))
	errorjmp(mf,"NextUID size is not %d bytes",mf->Seg.NextUID);
      readbytes(mf,mf->Seg.NextUID,sizeof(mf->Seg.NextUID));
      break;
    case 0x3e83bb: // NextFilename
      STRGETM(mf,mf->Seg.NextFilename,len);
      break;
    case 0x2ad7b1: // TimecodeScale
      mf->Seg.TimecodeScale = readUInt(mf,(unsigned)len);
      if (mf->Seg.TimecodeScale == 0)
	errorjmp(mf,"Segment timecode scale is zero");
      break;
    case 0x4489: // Duration
      duration = readFloat(mf,(unsigned)len);
      break;
    case 0x4461: // DateUTC
      mf->Seg.DateUTC = readUInt(mf,(unsigned)len);
      break;
    case 0x7ba9: // Title
      STRGETM(mf,mf->Seg.Title,len);
      break;
    case 0x4d80: // MuxingApp
      STRGETM(mf,mf->Seg.MuxingApp,len);
      break;
    case 0x5741: // WritingApp
      STRGETM(mf,mf->Seg.WritingApp,len);
      break;
  ENDFOR(mf);

  mf->Seg.Duration = mul3(duration,mf->Seg.TimecodeScale);
}

static void parseFirstCluster(MatroskaFile *mf,ulonglong toplen) {
  mf->seen.Cluster = 1;
  mf->firstTimecode = 0;

  FOREACH(mf,toplen)
    case 0xe7: // Timecode
      mf->firstTimecode += readUInt(mf,(unsigned)len);
      break;
    case 0xa0: // BlockGroup
      FOREACH(mf,len)
	case 0xa1: // Block
	  readVLUInt(mf); // track number
	  mf->firstTimecode += readSInt(mf,2); 

	  skipbytes(mf,start + toplen - filepos(mf));
	  return;
      ENDFOR(mf);
      break;
  ENDFOR(mf);
}

static void parseVideoInfo(MatroskaFile *mf,ulonglong toplen,struct TrackInfo *ti) {
  ulonglong v;
  char	    dW = 0, dH = 0;

  FOREACH(mf,toplen)
    case 0x9a: // FlagInterlaced
      ti->Video.Interlaced = readUInt(mf,(unsigned)len)!=0;
      break;
    case 0x53b8: // StereoMode
      v = readUInt(mf,(unsigned)len);
      if (v>3)
	errorjmp(mf,"Invalid stereo mode");
      ti->Video.StereoMode = (unsigned char)v;
      break;
    case 0xb0: // PixelWidth
      v = readUInt(mf,(unsigned)len);
      if (v>0xffffffff)
	errorjmp(mf,"PixelWidth is too large");
      ti->Video.PixelWidth = (unsigned)v;
      if (!dW)
	ti->Video.DisplayWidth = ti->Video.PixelWidth;
      break;
    case 0xba: // PixelHeight
      v = readUInt(mf,(unsigned)len);
      if (v>0xffffffff)
	errorjmp(mf,"PixelHeight is too large");
      ti->Video.PixelHeight = (unsigned)v;
      if (!dH)
	ti->Video.DisplayHeight = ti->Video.PixelHeight;
      break;
    case 0x54b0: // DisplayWidth
      v = readUInt(mf,(unsigned)len);
      if (v>0xffffffff)
	errorjmp(mf,"DisplayWidth is too large");
      ti->Video.DisplayWidth = (unsigned)v;
      dW = 1;
      break;
    case 0x54ba: // DisplayHeight
      v = readUInt(mf,(unsigned)len);
      if (v>0xffffffff)
	errorjmp(mf,"DisplayHeight is too large");
      ti->Video.DisplayHeight = (unsigned)v;
      dH = 1;
      break;
    case 0x54b2: // DisplayUnit
      v = readUInt(mf,(unsigned)len);
      if (v>2)
	errorjmp(mf,"Invalid DisplayUnit: %d",(int)v);
      ti->Video.DisplayUnit = (unsigned char)v;
      break;
    case 0x54b3: // AspectRatioType
      v = readUInt(mf,(unsigned)len);
      if (v>2)
	errorjmp(mf,"Invalid AspectRatioType: %d",(int)v);
      ti->Video.AspectRatioType = (unsigned char)v;
      break;
    case 0x54aa: // PixelCropBottom
      v = readUInt(mf,(unsigned)len);
      if (v>0xffffffff)
	errorjmp(mf,"PixelCropBottom is too large");
      ti->Video.CropB = (unsigned)v;
      break;
    case 0x54bb: // PixelCropTop
      v = readUInt(mf,(unsigned)len);
      if (v>0xffffffff)
	errorjmp(mf,"PixelCropTop is too large");
      ti->Video.CropT = (unsigned)v;
      break;
    case 0x54cc: // PixelCropLeft
      v = readUInt(mf,(unsigned)len);
      if (v>0xffffffff)
	errorjmp(mf,"PixelCropLeft is too large");
      ti->Video.CropL = (unsigned)v;
      break;
    case 0x54dd: // PixelCropRight
      v = readUInt(mf,(unsigned)len);
      if (v>0xffffffff)
	errorjmp(mf,"PixelCropRight is too large");
      ti->Video.CropR = (unsigned)v;
      break;
    case 0x2eb524: // ColourSpace
      ti->Video.ColourSpace = (unsigned)readUInt(mf,4);
      break;
    case 0x2fb523: // GammaValue
      ti->Video.GammaValue = readFloat(mf,(unsigned)len);
      break;
  ENDFOR(mf);
}

static void parseAudioInfo(MatroskaFile *mf,ulonglong toplen,struct TrackInfo *ti) {
  ulonglong   v;

  FOREACH(mf,toplen)
    case 0xb5: // SamplingFrequency
      ti->Audio.SamplingFreq = readFloat(mf,(unsigned)len);
      break;
    case 0x78b5: // OutputSamplingFrequency
      ti->Audio.OutputSamplingFreq = readFloat(mf,(unsigned)len);
      break;
    case 0x9f: // Channels
      v = readUInt(mf,(unsigned)len);
      if (v<1 || v>255)
	errorjmp(mf,"Invalid Channels value");
      ti->Audio.Channels = (unsigned char)v;
      break;
    case 0x7d7b: // ChannelPositions
      skipbytes(mf,len);
      break;
    case 0x6264: // BitDepth
      v = readUInt(mf,(unsigned)len);
#if 0
      if ((v<1 || v>255) && !IsWritingApp(mf,"AVI-Mux GUI"))
	errorjmp(mf,"Invalid BitDepth: %d",(int)v);
#endif
      ti->Audio.BitDepth = (unsigned char)v;
      break;
  ENDFOR(mf);

  if (ti->Audio.Channels == 0)
    ti->Audio.Channels = 1;
  if (mkv_TruncFloat(ti->Audio.SamplingFreq) == 0)
    ti->Audio.SamplingFreq = mkfi(8000);
  if (mkv_TruncFloat(ti->Audio.OutputSamplingFreq)==0)
    ti->Audio.OutputSamplingFreq = ti->Audio.SamplingFreq;
}

static void CopyStr(char **src,char **dst) {
  size_t l;

  if (!*src)
    return;

  l = strlen(*src)+1;
  memcpy(*dst,*src,l);
  *src = *dst;
  *dst += l;
}

static void parseTrackEntry(MatroskaFile *mf,ulonglong toplen) {
  struct TrackInfo  t,*tp,**tpp;
  ulonglong	    v;
  char		    *cp = NULL;
  size_t	    cplen = 0, cpadd = 0;
  unsigned	    CompScope = 1;

  if (mf->nTracks >= MAX_TRACKS)
    errorjmp(mf,"Too many tracks.");

  // clear track info
  memset(&t,0,sizeof(t));

  // fill default values
  t.Enabled = 1;
  t.Default = 1;
  t.Lacing = 1;
  t.TimecodeScale = mkfi(1);
  t.DecodeAll = 1;

  FOREACH(mf,toplen)
    case 0xd7: // TrackNumber
      v = readUInt(mf,(unsigned)len);
      if (v>255)
	errorjmp(mf,"Track number is >255 (%d)",(int)v);
      t.Number = (unsigned char)v;
      break;
    case 0x73c5: // TrackUID
      t.UID = readUInt(mf,(unsigned)len);
      break;
    case 0x83: // TrackType
      v = readUInt(mf,(unsigned)len);
      if (v<1 || v>254)
	errorjmp(mf,"Invalid track type: %d",(int)v);
      t.Type = (unsigned char)v;
      break;
    case 0xb9: // Enabled
      t.Enabled = readUInt(mf,(unsigned)len)!=0;
      break;
    case 0x88: // Default
      t.Default = readUInt(mf,(unsigned)len)!=0;
      break;
    case 0x9c: // Lacing
      t.Lacing = readUInt(mf,(unsigned)len)!=0;
      break;
    case 0x6de7: // MinCache
      v = readUInt(mf,(unsigned)len);
      if (v > 0xffffffff)
	errorjmp(mf,"MinCache is too large");
      t.MinCache = (unsigned)v;
      break;
    case 0x6df8: // MaxCache
      v = readUInt(mf,(unsigned)len);
      if (v > 0xffffffff)
	errorjmp(mf,"MaxCache is too large");
      t.MaxCache = (unsigned)v;
      break;
    case 0x23e383: // DefaultDuration
      t.DefaultDuration = readUInt(mf,(unsigned)len);
      break;
    case 0x23314f: // TrackTimecodeScale
      t.TimecodeScale = readFloat(mf,(unsigned)len);
      break;
    case 0x55ee: // MaxBlockAdditionID
      t.MaxBlockAdditionID = (unsigned)readUInt(mf,(unsigned)len);
      break;
    case 0x536e: // Name
      if (t.Name)
	errorjmp(mf,"Duplicate Track Name");
      STRGETA(mf,t.Name,len);
      break;
    case 0x22b59c: // Language
      if (t.Language)
	errorjmp(mf,"Duplicate Track Language");
      STRGETA(mf,t.Language,len);
      break;
    case 0x86: // CodecID
      if (t.CodecID)
	errorjmp(mf,"Duplicate CodecID");
      STRGETA(mf,t.CodecID,len);
      break;
    case 0x63a2: // CodecPrivate
      if (cp)
	errorjmp(mf,"Duplicate CodecPrivate");
      if (len>262144) // 256KB
	errorjmp(mf,"CodecPrivate is too large: %d",(int)len);
      cplen = (unsigned)len;
      cp = alloca(cplen);
      readbytes(mf,cp,(int)cplen);
      break;
    case 0x258688: // CodecName
      skipbytes(mf,len);
      break;
    case 0x3a9697: // CodecSettings
      skipbytes(mf,len);
      break;
    case 0x3b4040: // CodecInfoURL
      skipbytes(mf,len);
      break;
    case 0x26b240: // CodecDownloadURL
      skipbytes(mf,len);
      break;
    case 0xaa: // CodecDecodeAll
      t.DecodeAll = readUInt(mf,(unsigned)len)!=0;
      break;
    case 0x6fab: // TrackOverlay
      v = readUInt(mf,(unsigned)len);
      if (v>255)
	errorjmp(mf,"Track number in TrackOverlay is too large: %d",(int)v);
      t.TrackOverlay = (unsigned char)v;
      break;
    case 0xe0: // VideoInfo
      parseVideoInfo(mf,len,&t);
      break;
    case 0xe1: // AudioInfo
      parseAudioInfo(mf,len,&t);
      break;
    case 0x6d80: // ContentEncodings
      FOREACH(mf,len)
	case 0x6240: // ContentEncoding
	  FOREACH(mf,len)
	    case 0x5031: // ContentEncodingOrder
	      readUInt(mf,(unsigned)len);
	      break;
	    case 0x5032: // ContentEncodingScope
	      CompScope = (unsigned)readUInt(mf,(unsigned)len);
	      break;
	    case 0x5033: // ContentEncodingType
	      readUInt(mf,(unsigned)len);
	      break;
	    case 0x5034: // ContentCompression
	      // fill in defaults
	      t.CompEnabled = 1;
	      t.CompMethod = COMP_ZLIB;
	      FOREACH(mf,len)
		case 0x4254: // ContentCompAlgo
		  v = readUInt(mf,(unsigned)len);
		  if (v != 0)
		    errorjmp(mf,"Unsupported compression algorithm: %d",(int)v);
		  t.CompEnabled = 1;
		  t.CompMethod = COMP_ZLIB;
		  break;
		case 0x4255: // ContentCompSettings
		  skipbytes(mf,len);
		  break;
	      ENDFOR(mf);
	      break;
	      // TODO Implement Encryption/Signatures
	  ENDFOR(mf);
	  break;
      ENDFOR(mf);
      break;
  ENDFOR(mf);

  // validate track info
  if (!t.CodecID)
    errorjmp(mf,"Track has no Codec ID");

  if (t.UID != 0) {
    unsigned  i;
    for (i = 0; i < mf->nTracks; ++i)
      if (mf->Tracks[i]->UID == t.UID) // duplicate track entry
	return;
  }

#ifdef MATROSKA_COMPRESSION_SUPPORT
  // handle compressed CodecPrivate
  if (t.CompEnabled && (CompScope & 2) && cplen > 0) {
    z_stream  zs;
    char      tmp[64], *ncp;
    int	      code;
    uLong     ncplen;

    memset(&zs,0,sizeof(zs));
    if (inflateInit(&zs) != Z_OK)
      errorjmp(mf, "inflateInit failed");

    zs.next_in = cp;
    zs.avail_in = cplen;

    do {
      zs.next_out = tmp;
      zs.avail_out = sizeof(tmp);

      code = inflate(&zs, Z_NO_FLUSH);
    } while (code == Z_OK);

    if (code != Z_STREAM_END)
      errorjmp(mf, "invalid compressed data in CodecPrivate");

    ncplen = zs.total_out;
    ncp = alloca(ncplen);

    inflateReset(&zs);

    zs.next_in = cp;
    zs.avail_in = cplen;
    zs.next_out = ncp;
    zs.avail_out = ncplen;

    if (inflate(&zs, Z_FINISH) != Z_STREAM_END)
      errorjmp(mf, "inflate failed");

    inflateEnd(&zs);

    cp = ncp;
    cplen = ncplen;
  }
#endif

  if (!(CompScope & 1))
    t.CompEnabled = 0;

  // allocate new track
  tpp = AGET(mf,Tracks);

  // copy strings
  if (t.Name)
    cpadd += strlen(t.Name)+1;
  if (t.Language)
    cpadd += strlen(t.Language)+1;
  if (t.CodecID)
    cpadd += strlen(t.CodecID)+1;

  tp = mf->cache->memalloc(mf->cache,sizeof(*tp) + cplen + cpadd);
  if (tp == NULL)
    errorjmp(mf,"Out of memory");

  memcpy(tp,&t,sizeof(*tp));
  memcpy(tp+1,cp,cplen);
  if (cplen) {
    tp->CodecPrivate = tp+1;
    tp->CodecPrivateSize = (unsigned)cplen;
  }

  cp = (char*)(tp+1) + cplen;
  CopyStr(&tp->Name,&cp);
  CopyStr(&tp->Language,&cp);
  CopyStr(&tp->CodecID,&cp);

  // set default language
  if (!tp->Language)
    tp->Language="eng";

  *tpp = tp;
}

static void parseTracks(MatroskaFile *mf,ulonglong toplen) {
  mf->seen.Tracks = 1;
  FOREACH(mf,toplen)
    case 0xae: // TrackEntry
      parseTrackEntry(mf,len);
      break;
  ENDFOR(mf);
}

static void addCue(MatroskaFile *mf,ulonglong pos,ulonglong timecode) {
  struct Cue  *cc = AGET(mf,Cues);
  cc->Time = timecode;
  cc->Position = pos;
  cc->Track = 0;
  cc->Block = 0;
}

static void fixupCues(MatroskaFile *mf) {
  // adjust cues, shift cues if file does not start at 0
  unsigned  i;
  longlong  adjust = mf->firstTimecode * mf->Seg.TimecodeScale;

  for (i=0;i<mf->nCues;++i) {
    mf->Cues[i].Time *= mf->Seg.TimecodeScale;
    mf->Cues[i].Time -= adjust;
  }
}

static void parseCues(MatroskaFile *mf,ulonglong toplen) {
  jmp_buf     jb;
  ulonglong   v;
  struct Cue  cc;
  unsigned    i,j,k;

  mf->seen.Cues = 1;
  mf->nCues = 0;
  cc.Block = 0;

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

  if (setjmp(mf->jb)) {
    memcpy(&mf->jb,&jb,sizeof(jb));
    mf->nCues = 0;
    mf->seen.Cues = 0;
    return;
  }

  FOREACH(mf,toplen)
    case 0xbb: // CuePoint
      FOREACH(mf,len)
	case 0xb3: // CueTime
	  cc.Time = readUInt(mf,(unsigned)len);
	  break;
	case 0xb7: // CueTrackPositions
	  FOREACH(mf,len)
	    case 0xf7: // CueTrack
	      v = readUInt(mf,(unsigned)len);
	      if (v>255)
		errorjmp(mf,"CueTrack points to an invalid track: %d",(int)v);
	      cc.Track = (unsigned char)v;
	      break;
	    case 0xf1: // CueClusterPosition
	      cc.Position = readUInt(mf,(unsigned)len);
	      break;
	    case 0x5378: // CueBlockNumber
	      cc.Block = readUInt(mf,(unsigned)len);
	      break;
	    case 0xea: // CodecState
	      readUInt(mf,(unsigned)len);
	      break;
	    case 0xdb: // CueReference
	      FOREACH(mf,len)

⌨️ 快捷键说明

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