/* * If we're not at end of stream, read |aNumBytes| from the media resource, * put it in |aData|, and return true. * Otherwise, put as much data as is left into |aData|, set |aNumBytes| to the * amount of data we have left, and return false. */ nsresult AppleMP3Reader::Read(uint32_t *aNumBytes, char *aData) { MediaResource *resource = mDecoder->GetResource(); // Loop until we have all the data asked for, or we've reached EOS uint32_t totalBytes = 0; uint32_t numBytes; do { uint32_t bytesWanted = *aNumBytes - totalBytes; nsresult rv = resource->Read(aData + totalBytes, bytesWanted, &numBytes); totalBytes += numBytes; if (NS_FAILED(rv)) { *aNumBytes = 0; return NS_ERROR_FAILURE; } } while(totalBytes < *aNumBytes && numBytes); *aNumBytes = totalBytes; // We will have read some data in the last iteration iff we filled the buffer. // XXX Maybe return a better value than NS_ERROR_FAILURE? return numBytes ? NS_OK : NS_ERROR_FAILURE; }
void nsGStreamerReader::ReadAndPushData(guint aLength) { MediaResource* resource = mDecoder->GetResource(); NS_ASSERTION(resource, "Decoder has no media resource"); nsresult rv = NS_OK; GstBuffer *buffer = gst_buffer_new_and_alloc(aLength); guint8 *data = GST_BUFFER_DATA(buffer); uint32_t size = 0, bytesRead = 0; while(bytesRead < aLength) { rv = resource->Read(reinterpret_cast<char*>(data + bytesRead), aLength - bytesRead, &size); if (NS_FAILED(rv) || size == 0) break; bytesRead += size; } GST_BUFFER_SIZE(buffer) = bytesRead; mByteOffset += bytesRead; GstFlowReturn ret = gst_app_src_push_buffer(mSource, gst_buffer_ref(buffer)); if (ret != GST_FLOW_OK) LOG(PR_LOG_ERROR, ("ReadAndPushData push ret %s", gst_flow_get_name(ret))); if (GST_BUFFER_SIZE (buffer) < aLength) /* If we read less than what we wanted, we reached the end */ gst_app_src_end_of_stream(mSource); gst_buffer_unref(buffer); }
// Functions for reading and seeking using MediaResource required for // nestegg_io. The 'user data' passed to these functions is the // decoder from which the media resource is obtained. static int webm_read(void *aBuffer, size_t aLength, void *aUserData) { NS_ASSERTION(aUserData, "aUserData must point to a valid nsBuiltinDecoder"); nsBuiltinDecoder* decoder = reinterpret_cast<nsBuiltinDecoder*>(aUserData); MediaResource* resource = decoder->GetResource(); NS_ASSERTION(resource, "Decoder has no media resource"); nsresult rv = NS_OK; bool eof = false; char *p = static_cast<char *>(aBuffer); while (NS_SUCCEEDED(rv) && aLength > 0) { PRUint32 bytes = 0; rv = resource->Read(p, aLength, &bytes); if (bytes == 0) { eof = true; break; } decoder->NotifyBytesConsumed(bytes); aLength -= bytes; p += bytes; } return NS_FAILED(rv) ? -1 : eof ? 0 : 1; }
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 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; }
void GStreamerReader::ReadAndPushData(guint aLength) { MediaResource* resource = mDecoder->GetResource(); NS_ASSERTION(resource, "Decoder has no media resource"); nsresult rv = NS_OK; GstBuffer* buffer = gst_buffer_new_and_alloc(aLength); #if GST_VERSION_MAJOR >= 1 GstMapInfo info; gst_buffer_map(buffer, &info, GST_MAP_WRITE); guint8 *data = info.data; #else guint8* data = GST_BUFFER_DATA(buffer); #endif uint32_t size = 0, bytesRead = 0; while(bytesRead < aLength) { rv = resource->Read(reinterpret_cast<char*>(data + bytesRead), aLength - bytesRead, &size); if (NS_FAILED(rv) || size == 0) break; bytesRead += size; } #if GST_VERSION_MAJOR >= 1 gst_buffer_unmap(buffer, &info); gst_buffer_set_size(buffer, bytesRead); #else GST_BUFFER_SIZE(buffer) = bytesRead; #endif GstFlowReturn ret = gst_app_src_push_buffer(mSource, gst_buffer_ref(buffer)); if (ret != GST_FLOW_OK) { LOG(PR_LOG_ERROR, ("ReadAndPushData push ret %s", gst_flow_get_name(ret))); } if (bytesRead < aLength) { /* If we read less than what we wanted, we reached the end */ gst_app_src_end_of_stream(mSource); } gst_buffer_unref(buffer); }
/* * If we're not at end of stream, read |aNumBytes| from the media resource, * put it in |aData|, and return true. * Otherwise, put as much data as is left into |aData|, set |aNumBytes| to the * amount of data we have left, and return false. * * This function also passes the read data on to the MP3 frame parser for * stream duration estimation. */ nsresult AppleMP3Reader::ReadAndNotify(uint32_t *aNumBytes, char *aData) { MediaResource *resource = mDecoder->GetResource(); uint64_t offset = resource->Tell(); // Loop until we have all the data asked for, or we've reached EOS uint32_t totalBytes = 0; uint32_t numBytes; do { uint32_t bytesWanted = *aNumBytes - totalBytes; nsresult rv = resource->Read(aData + totalBytes, bytesWanted, &numBytes); totalBytes += numBytes; if (NS_FAILED(rv)) { *aNumBytes = 0; return NS_ERROR_FAILURE; } } while(totalBytes < *aNumBytes && numBytes); // Pass the buffer to the MP3 frame parser to improve our duration estimate. if (mMP3FrameParser.IsMP3()) { mMP3FrameParser.Parse(aData, totalBytes, offset); uint64_t duration = mMP3FrameParser.GetDuration(); if (duration != mDuration) { LOGD("Updating media duration to %lluus\n", duration); mDuration = duration; ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); mDecoder->UpdateEstimatedMediaDuration(duration); } } *aNumBytes = totalBytes; // We will have read some data in the last iteration iff we filled the buffer. // XXX Maybe return a better value than NS_ERROR_FAILURE? return numBytes ? NS_OK : NS_ERROR_FAILURE; }
void GStreamerReader::ReadAndPushData(guint aLength) { MediaResource* resource = mDecoder->GetResource(); NS_ASSERTION(resource, "Decoder has no media resource"); int64_t offset1 = resource->Tell(); unused << offset1; nsresult rv = NS_OK; GstBuffer* buffer = gst_buffer_new_and_alloc(aLength); #if GST_VERSION_MAJOR >= 1 GstMapInfo info; gst_buffer_map(buffer, &info, GST_MAP_WRITE); guint8 *data = info.data; #else guint8* data = GST_BUFFER_DATA(buffer); #endif uint32_t size = 0, bytesRead = 0; while(bytesRead < aLength) { rv = resource->Read(reinterpret_cast<char*>(data + bytesRead), aLength - bytesRead, &size); if (NS_FAILED(rv) || size == 0) break; bytesRead += size; } int64_t offset2 = resource->Tell(); unused << offset2; #if GST_VERSION_MAJOR >= 1 gst_buffer_unmap(buffer, &info); gst_buffer_set_size(buffer, bytesRead); #else GST_BUFFER_SIZE(buffer) = bytesRead; #endif GstFlowReturn ret = gst_app_src_push_buffer(mSource, gst_buffer_ref(buffer)); if (ret != GST_FLOW_OK) { LOG(PR_LOG_ERROR, "ReadAndPushData push ret %s(%d)", gst_flow_get_name(ret), ret); } if (NS_FAILED(rv)) { /* Terminate the stream if there is an error in reading */ LOG(PR_LOG_ERROR, "ReadAndPushData read error, rv=%x", rv); gst_app_src_end_of_stream(mSource); } else if (bytesRead < aLength) { /* If we read less than what we wanted, we reached the end */ LOG(PR_LOG_WARNING, "ReadAndPushData read underflow, " "bytesRead=%u, aLength=%u, offset(%lld,%lld)", bytesRead, aLength, offset1, offset2); gst_app_src_end_of_stream(mSource); } gst_buffer_unref(buffer); /* Ensure offset change is consistent in this function. * If there are other stream operations on another thread at the same time, * it will disturb the GStreamer state machine. */ MOZ_ASSERT(offset1 + bytesRead == offset2); }