예제 #1
0
파일: audiosource.cpp 프로젝트: zzlee/ffms2
void FFMS_AudioSource::CacheBeginning() {
	// Nothing to do if the cache is already populated
	if (!Cache.empty()) return;

	// The first frame is already decoded, so add it to the cache
	CacheIterator it = Cache.end();
	CacheBlock(it);

	// The first packet after a seek is often decoded incorrectly, which
	// makes it impossible to ever correctly seek back to the beginning, so
	// store the first block now

	// In addition, anything with the same PTS as the first packet can't be
	// distinguished from the first packet and so can't be seeked to, so
	// store those as well

	// Some of LAVF's splitters don't like to seek to the beginning of the
	// file (ts and?), so cache a few blocks even if PTSes are unique
	// Packet 7 is the last packet I've had be unseekable to, so cache up to
	// 10 for a bit of an extra buffer
	CacheIterator end = Cache.end();
	while (PacketNumber < Frames.size() &&
		((Frames[0].PTS != ffms_av_nopts_value && Frames[PacketNumber].PTS == Frames[0].PTS) ||
		 Cache.size() < 10)) {

		// Vorbis in particular seems to like having 60+ packets at the start
		// of the file with a PTS of 0, so we might need to expand the search
		// range to account for that.
		// Expanding slightly before it's strictly needed to ensure there's a
		// bit of space for an actual cache
		if (Cache.size() >= MaxCacheBlocks - 5) {
			 if (MaxCacheBlocks >= EXCESSIVE_CACHE_SIZE)
				throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_ALLOCATION_FAILED,
					"Exceeded the search range for an initial valid audio PTS");
			MaxCacheBlocks *= 2;
		}

		DecodeNextBlock(&end);
	}
	// Store the iterator to the last element of the cache which is used for
	// correctness rather than speed, so that when looking for one to delete
	// we know how much to skip
	CacheNoDelete = Cache.end();
	--CacheNoDelete;
}
예제 #2
0
void FFMS_AudioSource::DecodeNextBlock(CacheIterator *pos) {
	CurrentFrame = &Frames[PacketNumber];

	AVPacket Packet;
	if (!ReadPacket(&Packet))
		throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_UNKNOWN,
			"ReadPacket unexpectedly failed to read a packet");

	// ReadPacket may have changed the packet number
	CurrentFrame = &Frames[PacketNumber];
	CurrentSample = CurrentFrame->SampleStart;

	bool GotSamples = false;
	uint8_t *Data = Packet.data;
	while (Packet.size > 0) {
		DecodeFrame.reset();
		int GotFrame = 0;
		int Ret = avcodec_decode_audio4(CodecContext, DecodeFrame, &GotFrame, &Packet);

		// Should only ever happen if the user chose to ignore decoding errors
		// during indexing, so continue to just ignore decoding errors
		if (Ret < 0) break;

		if (Ret > 0) {
			Packet.size -= Ret;
			Packet.data += Ret;
			if (GotFrame && DecodeFrame->nb_samples > 0) {
				GotSamples = true;
				if (pos)
					CacheBlock(*pos);
			}
		}
	}
	Packet.data = Data;
	FreePacket(&Packet);

	// Zero sample packets aren't included in the index
	if (GotSamples)
		++PacketNumber;
}