nsresult GStreamerReader::GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime) { if (!mInfo.HasValidMedia()) { return NS_OK; } #if GST_VERSION_MAJOR == 0 GstFormat format = GST_FORMAT_TIME; #endif MediaResource* resource = mDecoder->GetResource(); nsTArray<MediaByteRange> ranges; resource->GetCachedRanges(ranges); if (resource->IsDataCachedToEndOfResource(0)) { /* fast path for local or completely cached files */ gint64 duration = 0; { ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); duration = mDecoder->GetMediaDuration(); } double end = (double) duration / GST_MSECOND; LOG(PR_LOG_DEBUG, "complete range [0, %f] for [0, %li]", end, resource->GetLength()); aBuffered->Add(0, end); return NS_OK; } for(uint32_t index = 0; index < ranges.Length(); index++) { int64_t startOffset = ranges[index].mStart; int64_t endOffset = ranges[index].mEnd; gint64 startTime, endTime; #if GST_VERSION_MAJOR >= 1 if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES, startOffset, GST_FORMAT_TIME, &startTime)) continue; if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES, endOffset, GST_FORMAT_TIME, &endTime)) continue; #else if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES, startOffset, &format, &startTime) || format != GST_FORMAT_TIME) continue; if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES, endOffset, &format, &endTime) || format != GST_FORMAT_TIME) continue; #endif double start = (double) GST_TIME_AS_USECONDS (startTime) / GST_MSECOND; double end = (double) GST_TIME_AS_USECONDS (endTime) / GST_MSECOND; LOG(PR_LOG_DEBUG, "adding range [%f, %f] for [%li %li] size %li", start, end, startOffset, endOffset, resource->GetLength()); aBuffered->Add(start, end); } return NS_OK; }
nsresult GStreamerReader::GetBuffered(TimeRanges* aBuffered, int64_t aStartTime) { if (!mInfo.mHasVideo && !mInfo.mHasAudio) { return NS_OK; } GstFormat format = GST_FORMAT_TIME; MediaResource* resource = mDecoder->GetResource(); nsTArray<MediaByteRange> ranges; resource->GetCachedRanges(ranges); if (mDecoder->OnStateMachineThread()) /* Report the position from here while buffering as we can't report it from * the gstreamer threads that are actually reading from the resource */ NotifyBytesConsumed(); if (resource->IsDataCachedToEndOfResource(0)) { /* fast path for local or completely cached files */ gint64 duration = 0; duration = QueryDuration(); double end = (double) duration / GST_MSECOND; LOG(PR_LOG_DEBUG, ("complete range [0, %f] for [0, %li]", end, resource->GetLength())); aBuffered->Add(0, end); return NS_OK; } for(uint32_t index = 0; index < ranges.Length(); index++) { int64_t startOffset = ranges[index].mStart; int64_t endOffset = ranges[index].mEnd; gint64 startTime, endTime; if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES, startOffset, &format, &startTime) || format != GST_FORMAT_TIME) continue; if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES, endOffset, &format, &endTime) || format != GST_FORMAT_TIME) continue; double start = (double) GST_TIME_AS_USECONDS (startTime) / GST_MSECOND; double end = (double) GST_TIME_AS_USECONDS (endTime) / GST_MSECOND; LOG(PR_LOG_DEBUG, ("adding range [%f, %f] for [%li %li] size %li", start, end, startOffset, endOffset, resource->GetLength())); aBuffered->Add(start, end); } return NS_OK; }
media::TimeIntervals GStreamerReader::GetBuffered() { MOZ_ASSERT(OnTaskQueue()); if (!HaveStartTime()) { return media::TimeIntervals(); } media::TimeIntervals buffered; if (!mInfo.HasValidMedia()) { return buffered; } #if GST_VERSION_MAJOR == 0 GstFormat format = GST_FORMAT_TIME; #endif AutoPinned<MediaResource> resource(mDecoder->GetResource()); nsTArray<MediaByteRange> ranges; resource->GetCachedRanges(ranges); if (resource->IsDataCachedToEndOfResource(0)) { /* fast path for local or completely cached files */ gint64 duration = mDuration.ReadOnWrongThread().refOr(media::TimeUnit::FromMicroseconds(0)).ToMicroseconds(); LOG(LogLevel::Debug, "complete range [0, %f] for [0, %li]", (double) duration / GST_MSECOND, GetDataLength()); buffered += media::TimeInterval(media::TimeUnit::FromMicroseconds(0), media::TimeUnit::FromMicroseconds(duration)); return buffered; } for(uint32_t index = 0; index < ranges.Length(); index++) { int64_t startOffset = ranges[index].mStart; int64_t endOffset = ranges[index].mEnd; gint64 startTime, endTime, duration; bool haveDuration = false; #if GST_VERSION_MAJOR >= 1 if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES, startOffset, GST_FORMAT_TIME, &startTime)) continue; if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES, endOffset, GST_FORMAT_TIME, &endTime)) continue; if (gst_element_query_duration(GST_ELEMENT(mPlayBin), GST_FORMAT_TIME, &duration)) { haveDuration = true; } #else if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES, startOffset, &format, &startTime) || format != GST_FORMAT_TIME) continue; if (!gst_element_query_convert(GST_ELEMENT(mPlayBin), GST_FORMAT_BYTES, endOffset, &format, &endTime) || format != GST_FORMAT_TIME) continue; if (gst_element_query_duration(GST_ELEMENT(mPlayBin), &format, &duration) && format == GST_FORMAT_TIME) { haveDuration = true; } #endif // Check that the estimated time doesn't go beyond known duration // as this indicates a buggy gst plugin. if (haveDuration && endTime > duration) { LOG(LogLevel::Debug, "Have duration %" GST_TIME_FORMAT "contradicting endTime %" GST_TIME_FORMAT, GST_TIME_ARGS(duration), GST_TIME_ARGS(endTime)); endTime = std::min(endTime, duration); } LOG(LogLevel::Debug, "adding range [%f, %f] for [%li %li] size %li", (double) GST_TIME_AS_USECONDS (startTime) / GST_MSECOND, (double) GST_TIME_AS_USECONDS (endTime) / GST_MSECOND, startOffset, endOffset, GetDataLength()); buffered += media::TimeInterval(media::TimeUnit::FromMicroseconds(GST_TIME_AS_USECONDS(startTime)), media::TimeUnit::FromMicroseconds(GST_TIME_AS_USECONDS(endTime))); } return buffered; }