| 1 | /********** |
| 2 | This library is free software; you can redistribute it and/or modify it under |
| 3 | the terms of the GNU Lesser General Public License as published by the |
| 4 | Free Software Foundation; either version 3 of the License, or (at your |
| 5 | option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.) |
| 6 | |
| 7 | This library is distributed in the hope that it will be useful, but WITHOUT |
| 8 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 9 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for |
| 10 | more details. |
| 11 | |
| 12 | You should have received a copy of the GNU Lesser General Public License |
| 13 | along with this library; if not, write to the Free Software Foundation, Inc., |
| 14 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 15 | **********/ |
| 16 | // "liveMedia" |
| 17 | // Copyright (c) 1996-2020 Live Networks, Inc. All rights reserved. |
| 18 | // Framed Sources |
| 19 | // Implementation |
| 20 | |
| 21 | #include "FramedSource.hh" |
| 22 | #include <stdlib.h> |
| 23 | |
| 24 | ////////// FramedSource ////////// |
| 25 | |
| 26 | FramedSource::FramedSource(UsageEnvironment& env) |
| 27 | : MediaSource(env), |
| 28 | fAfterGettingFunc(NULL), fAfterGettingClientData(NULL), |
| 29 | fOnCloseFunc(NULL), fOnCloseClientData(NULL), |
| 30 | fIsCurrentlyAwaitingData(False) { |
| 31 | fPresentationTime.tv_sec = fPresentationTime.tv_usec = 0; // initially |
| 32 | } |
| 33 | |
| 34 | FramedSource::~FramedSource() { |
| 35 | } |
| 36 | |
| 37 | Boolean FramedSource::isFramedSource() const { |
| 38 | return True; |
| 39 | } |
| 40 | |
| 41 | Boolean FramedSource::lookupByName(UsageEnvironment& env, char const* sourceName, |
| 42 | FramedSource*& resultSource) { |
| 43 | resultSource = NULL; // unless we succeed |
| 44 | |
| 45 | MediaSource* source; |
| 46 | if (!MediaSource::lookupByName(env, sourceName, source)) return False; |
| 47 | |
| 48 | if (!source->isFramedSource()) { |
| 49 | env.setResultMsg(sourceName, " is not a framed source" ); |
| 50 | return False; |
| 51 | } |
| 52 | |
| 53 | resultSource = (FramedSource*)source; |
| 54 | return True; |
| 55 | } |
| 56 | |
| 57 | void FramedSource::getNextFrame(unsigned char* to, unsigned maxSize, |
| 58 | afterGettingFunc* afterGettingFunc, |
| 59 | void* afterGettingClientData, |
| 60 | onCloseFunc* onCloseFunc, |
| 61 | void* onCloseClientData) { |
| 62 | // Make sure we're not already being read: |
| 63 | if (fIsCurrentlyAwaitingData) { |
| 64 | envir() << "FramedSource[" << this << "]::getNextFrame(): attempting to read more than once at the same time!\n" ; |
| 65 | envir().internalError(); |
| 66 | } |
| 67 | |
| 68 | fTo = to; |
| 69 | fMaxSize = maxSize; |
| 70 | fNumTruncatedBytes = 0; // by default; could be changed by doGetNextFrame() |
| 71 | fDurationInMicroseconds = 0; // by default; could be changed by doGetNextFrame() |
| 72 | fAfterGettingFunc = afterGettingFunc; |
| 73 | fAfterGettingClientData = afterGettingClientData; |
| 74 | fOnCloseFunc = onCloseFunc; |
| 75 | fOnCloseClientData = onCloseClientData; |
| 76 | fIsCurrentlyAwaitingData = True; |
| 77 | |
| 78 | doGetNextFrame(); |
| 79 | } |
| 80 | |
| 81 | void FramedSource::afterGetting(FramedSource* source) { |
| 82 | source->nextTask() = NULL; |
| 83 | source->fIsCurrentlyAwaitingData = False; |
| 84 | // indicates that we can be read again |
| 85 | // Note that this needs to be done here, in case the "fAfterFunc" |
| 86 | // called below tries to read another frame (which it usually will) |
| 87 | |
| 88 | if (source->fAfterGettingFunc != NULL) { |
| 89 | (*(source->fAfterGettingFunc))(source->fAfterGettingClientData, |
| 90 | source->fFrameSize, source->fNumTruncatedBytes, |
| 91 | source->fPresentationTime, |
| 92 | source->fDurationInMicroseconds); |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | void FramedSource::handleClosure(void* clientData) { |
| 97 | FramedSource* source = (FramedSource*)clientData; |
| 98 | source->handleClosure(); |
| 99 | } |
| 100 | |
| 101 | void FramedSource::handleClosure() { |
| 102 | fIsCurrentlyAwaitingData = False; // because we got a close instead |
| 103 | if (fOnCloseFunc != NULL) { |
| 104 | (*fOnCloseFunc)(fOnCloseClientData); |
| 105 | } |
| 106 | } |
| 107 | |
| 108 | void FramedSource::stopGettingFrames() { |
| 109 | fIsCurrentlyAwaitingData = False; // indicates that we can be read again |
| 110 | fAfterGettingFunc = NULL; |
| 111 | fOnCloseFunc = NULL; |
| 112 | |
| 113 | // Perform any specialized action now: |
| 114 | doStopGettingFrames(); |
| 115 | } |
| 116 | |
| 117 | void FramedSource::doStopGettingFrames() { |
| 118 | // Default implementation: Do nothing except cancel any pending 'delivery' task: |
| 119 | envir().taskScheduler().unscheduleDelayedTask(nextTask()); |
| 120 | // Subclasses may wish to redefine this function. |
| 121 | } |
| 122 | |
| 123 | unsigned FramedSource::maxFrameSize() const { |
| 124 | // By default, this source has no maximum frame size. |
| 125 | return 0; |
| 126 | } |
| 127 | |