Boolean MatroskaFileParser::parse() {
  Boolean areDone = False;

  try {
    do {
      switch (fCurrentParseState) {
        case PARSING_START_OF_FILE: {
	  areDone = parseStartOfFile();
	  break;
	}
        case LOOKING_FOR_TRACKS: {
	  lookForNextTrack();
	  break;
	}
        case PARSING_TRACK: {
	  areDone = parseTrack();
	  if (areDone && fOurFile.fCuesOffset > 0) {
	    // We've finished parsing the 'Track' information.  There are also 'Cues' in the file, so parse those before finishing:
	    // Seek to the specified position in the file.  We were already told that the 'Cues' begins there:
#ifdef DEBUG
	    fprintf(stderr, "Seeking to file position %llu (the previously-reported location of 'Cues')\n", fOurFile.fCuesOffset);
#endif
	    seekToFilePosition(fOurFile.fCuesOffset);
	    fCurrentParseState = PARSING_CUES;
	    areDone = False;
	  }
	  break;
	}
        case PARSING_CUES: {
	  areDone = parseCues();
	  break;
	}
        case LOOKING_FOR_CLUSTER: {
	  if (fOurFile.fClusterOffset > 0) {
	    // Optimization: Seek to the specified position in the file.  We were already told that the 'Cluster' begins there:
#ifdef DEBUG
	    fprintf(stderr, "Optimization: Seeking to file position %llu (the previously-reported location of a 'Cluster')\n", fOurFile.fClusterOffset);
#endif
	    seekToFilePosition(fOurFile.fClusterOffset);
	  }
	  fCurrentParseState = LOOKING_FOR_BLOCK;
	  break;
	}
        case LOOKING_FOR_BLOCK: {
	  lookForNextBlock();
	  break;
	}
        case PARSING_BLOCK: {
	  parseBlock();
	  break;
	}
        case DELIVERING_FRAME_WITHIN_BLOCK: {
	  if (!deliverFrameWithinBlock()) return False;
	  break;
	}
        case DELIVERING_FRAME_BYTES: {
	  deliverFrameBytes();
	  return False; // Halt parsing for now.  A new 'read' from downstream will cause parsing to resume.
	  break;
	}
      }
    } while (!areDone);

    return True;
  } catch (int /*e*/) {
#ifdef DEBUG
    fprintf(stderr, "MatroskaFileParser::parse() EXCEPTION (This is normal behavior - *not* an error)\n");
#endif
    return False;  // the parsing got interrupted
  }
}
示例#2
0
status WAVEFile::readInit(AFfilesetup setup)
{
	Tag type, formtype;
	uint32_t size;
	uint32_t index = 0;

	bool hasFormat = false;
	bool hasData = false;
	bool hasCue = false;
	bool hasList = false;
	bool hasPlayList = false;
	bool hasFrameCount = false;
	bool hasINST = false;

	Track *track = allocateTrack();

	fh->seek(0, File::SeekFromBeginning);

	readTag(&type);
	readU32(&size);
	readTag(&formtype);

	assert(type == "RIFF");
	assert(formtype == "WAVE");

#ifdef DEBUG
	printf("size: %d\n", size);
#endif

	/* Include the offset of the form type. */
	index += 4;

	while (index < size)
	{
		Tag chunkid;
		uint32_t chunksize = 0;
		status result;

#ifdef DEBUG
		printf("index: %d\n", index);
#endif
		readTag(&chunkid);
		readU32(&chunksize);

#ifdef DEBUG
		printf("%s size: %d\n", chunkid.name().c_str(), chunksize);
#endif

		if (chunkid == "fmt ")
		{
			result = parseFormat(chunkid, chunksize);
			if (result == AF_FAIL)
				return AF_FAIL;

			hasFormat = true;
		}
		else if (chunkid == "data")
		{
			/* The format chunk must precede the data chunk. */
			if (!hasFormat)
			{
				_af_error(AF_BAD_HEADER, "missing format chunk in WAVE file");
				return AF_FAIL;
			}

			result = parseData(chunkid, chunksize);
			if (result == AF_FAIL)
				return AF_FAIL;

			hasData = true;
		}
		else if (chunkid == "inst")
		{
			result = parseInstrument(chunkid, chunksize);
			if (result == AF_FAIL)
				return AF_FAIL;
		}
		else if (chunkid == "fact")
		{
			hasFrameCount = true;
			result = parseFrameCount(chunkid, chunksize);
			if (result == AF_FAIL)
				return AF_FAIL;
		}
		else if (chunkid == "cue ")
		{
			hasCue = true;
			result = parseCues(chunkid, chunksize);
			if (result == AF_FAIL)
				return AF_FAIL;
		}
		else if (chunkid == "LIST" || chunkid == "list")
		{
			hasList = true;
			result = parseList(chunkid, chunksize);
			if (result == AF_FAIL)
				return AF_FAIL;
		}
		else if (chunkid == "INST")
		{
			hasINST = true;
			result = parseInstrument(chunkid, chunksize);
			if (result == AF_FAIL)
				return AF_FAIL;
		}
		else if (chunkid == "plst")
		{
			hasPlayList = true;
			result = parsePlayList(chunkid, chunksize);
			if (result == AF_FAIL)
				return AF_FAIL;
		}

		index += chunksize + 8;

		/* All chunks must be aligned on an even number of bytes */
		if ((index % 2) != 0)
			index++;

		fh->seek(index + 8, File::SeekFromBeginning);
	}

	/* The format chunk and the data chunk are required. */
	if (!hasFormat || !hasData)
	{
		return AF_FAIL;
	}

	/*
		At this point we know that the file has a format chunk
		and a data chunk, so we can assume that track->f and
		track->data_size have been initialized.
	*/
	if (!hasFrameCount)
	{
		track->totalfframes = track->data_size /
			(int) _af_format_frame_size(&track->f, false);
	}

	if (track->f.compressionType != AF_COMPRESSION_NONE &&
		(track->f.compressionType == AF_COMPRESSION_G711_ULAW ||
		track->f.compressionType == AF_COMPRESSION_G711_ALAW))
	{
		track->totalfframes = track->data_size / track->f.channelCount;
	}

	/*
		A return value of AF_SUCCEED indicates successful parsing.
	*/
	return AF_SUCCEED;
}