status_t RtspMediaSource::read(MediaBuffer** out, const ReadOptions* options) { ReentrantMonitorAutoEnter mon(mMonitor); NS_ENSURE_TRUE(mIsStarted, MEDIA_ERROR_BASE); NS_ENSURE_TRUE(out, MEDIA_ERROR_BASE); *out = nullptr; // Video/audio track's initial frame size is FRAME_DEFAULT_SIZE. // We need to realloc the mBuffer if the mBuffer doesn't have enough space // for next ReadFrameFromTrack function. (actualFrameSize > mFrameMaxSize) status_t err; uint32_t readCount; uint32_t actualFrameSize; uint64_t time; nsresult rv; while (1) { err = mGroup->acquire_buffer(&mBuffer); NS_ENSURE_TRUE(err == OK, err); rv = mRtspResource->ReadFrameFromTrack((uint8_t *)mBuffer->data(), mFrameMaxSize, mTrackIdx, readCount, time, actualFrameSize); if (NS_FAILED(rv)) { // Release mGroup and mBuffer. stop(); // Since RtspMediaSource is an implementation of Android media source, // it's held by OMXCodec and isn't released yet. So we have to re-construct // mGroup and mBuffer. start(); NS_WARNING("ReadFrameFromTrack failed; releasing buffers and returning."); return ERROR_END_OF_STREAM; } if (actualFrameSize > mFrameMaxSize) { // release mGroup and mBuffer stop(); // re-construct mGroup and mBuffer mFrameMaxSize = actualFrameSize; err = start(); NS_ENSURE_TRUE(err == OK, err); } else { // ReadFrameFromTrack success, break the while loop. break; } } mBuffer->set_range(0, readCount); if (NS_SUCCEEDED(rv)) { mBuffer->meta_data()->clear(); // fill the meta data mBuffer->meta_data()->setInt64(kKeyTime, time); *out = mBuffer; mBuffer = nullptr; return OK; } return ERROR_END_OF_STREAM; }