gboolean GStreamerReader::SeekData(GstAppSrc* aSrc, guint64 aOffset) { aOffset += mDataOffset; ReentrantMonitorAutoEnter mon(mGstThreadsMonitor); MediaResource* resource = mDecoder->GetResource(); int64_t resourceLength = resource->GetLength(); if (gst_app_src_get_size(mSource) == -1) { /* It's possible that we didn't know the length when we initialized mSource * but maybe we do now */ gst_app_src_set_size(mSource, GetDataLength()); } nsresult rv = NS_ERROR_FAILURE; if (aOffset < static_cast<guint64>(resourceLength)) { rv = resource->Seek(SEEK_SET, aOffset); } if (NS_FAILED(rv)) { LOG(PR_LOG_ERROR, "seek at %lu failed", aOffset); } else { MOZ_ASSERT(aOffset == static_cast<guint64>(resource->Tell())); } return NS_SUCCEEDED(rv); }
void GStreamerReader::PlayBinSourceSetup(GstAppSrc* aSource) { mSource = GST_APP_SRC(aSource); gst_app_src_set_callbacks(mSource, &mSrcCallbacks, (gpointer) this, nullptr); MediaResource* resource = mDecoder->GetResource(); /* do a short read to trigger a network request so that GetLength() below * returns something meaningful and not -1 */ char buf[512]; unsigned int size = 0; resource->Read(buf, sizeof(buf), &size); resource->Seek(SEEK_SET, 0); /* now we should have a length */ int64_t resourceLength = resource->GetLength(); gst_app_src_set_size(mSource, resourceLength); if (resource->IsDataCachedToEndOfResource(0) || (resourceLength != -1 && resourceLength <= SHORT_FILE_SIZE)) { /* let the demuxer work in pull mode for local files (or very short files) * so that we get optimal seeking accuracy/performance */ LOG(PR_LOG_DEBUG, ("configuring random access, len %lld", resourceLength)); gst_app_src_set_stream_type(mSource, GST_APP_STREAM_TYPE_RANDOM_ACCESS); } else { /* make the demuxer work in push mode so that seeking is kept to a minimum */ LOG(PR_LOG_DEBUG, ("configuring push mode, len %lld", resourceLength)); gst_app_src_set_stream_type(mSource, GST_APP_STREAM_TYPE_SEEKABLE); } }
static int webm_seek(int64_t aOffset, int aWhence, void *aUserData) { NS_ASSERTION(aUserData, "aUserData must point to a valid AbstractMediaDecoder"); AbstractMediaDecoder* decoder = reinterpret_cast<AbstractMediaDecoder*>(aUserData); MediaResource* resource = decoder->GetResource(); NS_ASSERTION(resource, "Decoder has no media resource"); nsresult rv = resource->Seek(aWhence, aOffset); return NS_SUCCEEDED(rv) ? 0 : -1; }
nsresult nsRawReader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime) { NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); MediaResource *resource = mDecoder->GetResource(); NS_ASSERTION(resource, "Decoder has no media resource"); uint32_t frame = mCurrentFrame; if (aTime >= UINT_MAX) return NS_ERROR_FAILURE; mCurrentFrame = aTime * mFrameRate / USECS_PER_S; CheckedUint32 offset = CheckedUint32(mCurrentFrame) * mFrameSize; offset += sizeof(nsRawVideoHeader); NS_ENSURE_TRUE(offset.isValid(), NS_ERROR_FAILURE); nsresult rv = resource->Seek(nsISeekableStream::NS_SEEK_SET, offset.value()); NS_ENSURE_SUCCESS(rv, rv); mVideoQueue.Erase(); while(mVideoQueue.GetSize() == 0) { bool keyframeSkip = false; if (!DecodeVideoFrame(keyframeSkip, 0)) { mCurrentFrame = frame; return NS_ERROR_FAILURE; } { mozilla::ReentrantMonitorAutoEnter autoMonitor(mDecoder->GetReentrantMonitor()); if (mDecoder->GetDecodeState() == nsBuiltinDecoderStateMachine::DECODER_STATE_SHUTDOWN) { mCurrentFrame = frame; return NS_ERROR_FAILURE; } } nsAutoPtr<VideoData> video(mVideoQueue.PeekFront()); if (video && video->mEndTime < aTime) { mVideoQueue.PopFront(); video = nullptr; } else { video.forget(); } } return NS_OK; }
static bool Read(Decoder *aDecoder, char *aBuffer, int64_t aOffset, uint32_t aCount, uint32_t* aBytes) { MediaResource *resource = GetResource(aDecoder); if (aOffset != resource->Tell()) { nsresult rv = resource->Seek(nsISeekableStream::NS_SEEK_SET, aOffset); if (NS_FAILED(rv)) { return false; } } nsresult rv = resource->Read(aBuffer, aCount, aBytes); if (NS_FAILED(rv)) { return false; } return true; }
nsresult RawReader::SeekInternal(int64_t aTime) { NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); MediaResource *resource = mDecoder->GetResource(); NS_ASSERTION(resource, "Decoder has no media resource"); uint32_t frame = mCurrentFrame; if (aTime >= UINT_MAX) return NS_ERROR_FAILURE; mCurrentFrame = aTime * mFrameRate / USECS_PER_S; CheckedUint32 offset = CheckedUint32(mCurrentFrame) * mFrameSize; offset += sizeof(RawVideoHeader); NS_ENSURE_TRUE(offset.isValid(), NS_ERROR_FAILURE); nsresult rv = resource->Seek(nsISeekableStream::NS_SEEK_SET, offset.value()); NS_ENSURE_SUCCESS(rv, rv); mVideoQueue.Reset(); while(mVideoQueue.GetSize() == 0) { bool keyframeSkip = false; if (!DecodeVideoFrame(keyframeSkip, 0)) { mCurrentFrame = frame; return NS_ERROR_FAILURE; } { ReentrantMonitorAutoEnter autoMonitor(mDecoder->GetReentrantMonitor()); if (mDecoder->IsShutdown()) { mCurrentFrame = frame; return NS_ERROR_FAILURE; } } if (mVideoQueue.PeekFront() && mVideoQueue.PeekFront()->GetEndTime() < aTime) { nsRefPtr<VideoData> releaseMe = mVideoQueue.PopFront(); } } return NS_OK; }
gboolean nsGStreamerReader::SeekData(GstAppSrc *aSrc, guint64 aOffset) { ReentrantMonitorAutoEnter mon(mGstThreadsMonitor); MediaResource* resource = mDecoder->GetResource(); if (gst_app_src_get_size(mSource) == -1) /* It's possible that we didn't know the length when we initialized mSource * but maybe we do now */ gst_app_src_set_size(mSource, resource->GetLength()); nsresult rv = NS_ERROR_FAILURE; if (aOffset < resource->GetLength()) rv = resource->Seek(SEEK_SET, aOffset); if (NS_SUCCEEDED(rv)) mByteOffset = mLastReportedByteOffset = aOffset; else LOG(PR_LOG_ERROR, ("seek at %lu failed", aOffset)); return NS_SUCCEEDED(rv); }