示例#1
0
void CombineRanges(const MediaByteRange& pending, const MediaByteRange& preload,
				   MediaByteRange& request)
{
	OP_ASSERT(request.IsEmpty());
	// If pending and preload overlap, let request be their union,
	// clamped to pending.start.
	if (!pending.IsEmpty() && !preload.IsEmpty())
	{
		request = pending;
		request.IntersectWith(preload);
		if (!request.IsEmpty())
		{
			// non-empty intersection => overlap
			request = pending;
			request.UnionWith(preload);
			request.IntersectWith(MediaByteRange(pending.start));
			OP_ASSERT(!request.IsEmpty());
		}
	}
	// Otherwise, pick the first non-empty of pending and preload.
	if (request.IsEmpty())
	{
		if (!pending.IsEmpty())
			request = pending;
		else
			request = preload;
	}
}
示例#2
0
void IntersectWithUnavailable(MediaByteRange& range, URL& url)
{
	if (range.IsEmpty())
		return;

	// find the first unavailable range on or after range.start
	MediaByteRange unavail;
	BOOL available = FALSE;
	OpFileLength length = 0;
	url.GetPartialCoverage(range.start, available, length, TRUE);
	if (available)
	{
		OP_ASSERT(length > 0);
		unavail.start = range.start + length;
		length = 0;
		url.GetPartialCoverage(unavail.start, available, length, TRUE);
		OP_ASSERT(!available);
	}
	else
		unavail.start = range.start;

	// length is now the number of unavailable bytes, or 0 if unknown
	if (length > 0)
		unavail.SetLength(length);

	range.IntersectWith(unavail);
}
示例#3
0
void
MediaSourceImpl::CalcRequest(MediaByteRange& request)
{
	if (IsStreaming())
	{
		// When streaming we only consider the pending range (if any).
		// When there are no clients, request the entire resource.
		// To support preload together with streaming, care must be
		// taken to not restart a preload request [0,Inf] as soon as
		// data has been evicted and the cached range is e.g.
		// [500,1000499] if there is no pending request in that range.

		if (!m_clients.Empty())
		{
			MediaByteRange preload; // unused
			ReduceRanges(m_clients, request, preload);
			if (!request.IsEmpty())
			{
				request.SetLength(FILE_LENGTH_NONE);
				IntersectWithUnavailable(request, m_use_url);
				if (!request.IsEmpty())
					request.SetLength(FILE_LENGTH_NONE);
			}
		}
		else
		{
			request.start = 0;
		}
		// At this point we should have an unbounded range, but it may
		// be clamped to the resource length below.
		OP_ASSERT(!request.IsFinite());
	}
	else
	{
		// When not streaming (using multiple range disk cache), both
		// pending and preload requests are taken into account.
		//
		// Example 1: Everything should be preloaded, but since there is a
		// pending read, start buffering from that offset first. Also,
		// don't refetch the end of the resource.
		//
		// resource: <---------------------->
		// buffered: <-->               <--->
		// pending:           <---->
		// preload:  <---------------------->
		// request:           <-------->
		//
		// Example 2: The requested preload is already buffered, so the
		// request is the empty range.
		//
		// resource: <---------------------->
		// buffered: <-------->
		// pending:  empty range
		// preload:  <----->
		// request:  empty range

		MediaByteRange pending, preload;
		ReduceRanges(m_clients, pending, preload);
		CombineRanges(pending, preload, request);
		IntersectWithUnavailable(request, m_use_url);
	}

	if (!request.IsEmpty())
	{
		// Extra restrictions if resource length is known (this won't
		// be needed after CORE-30311 is fixed).
		OpFileLength resource_length = GetTotalBytes();
		if (resource_length > 0)
		{
			OP_ASSERT(request.start <= resource_length);

			MediaByteRange resource(0, resource_length - 1);

			// Clamp request to resource.
			request.IntersectWith(resource);

			// Increase size if it is unreasonably small at the end...
			if (!request.IsEmpty() &&
				request.Length() < MEDIA_SOURCE_MIN_SIZE &&
				resource.Length() >= MEDIA_SOURCE_MIN_SIZE &&
				request.end == resource.end)
			{
				// ... but only if nothing in that range is available.
				MediaByteRange cand_request(resource_length - MEDIA_SOURCE_MIN_SIZE, resource_length - 1);
				OP_ASSERT(cand_request.Length() == MEDIA_SOURCE_MIN_SIZE);
				IntersectWithUnavailable(cand_request, m_use_url);
				if (cand_request.Length() == MEDIA_SOURCE_MIN_SIZE)
					request = cand_request;
			}
		}
	}

	OP_NEW_DBG("CalcRequest", "MediaSource");
	OP_DBG(("request: ") << request);
}