1/**********
2This library is free software; you can redistribute it and/or modify it under
3the terms of the GNU Lesser General Public License as published by the
4Free Software Foundation; either version 3 of the License, or (at your
5option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
6
7This library is distributed in the hope that it will be useful, but WITHOUT
8ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
10more details.
11
12You should have received a copy of the GNU Lesser General Public License
13along with this library; if not, write to the Free Software Foundation, Inc.,
1451 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15**********/
16// "liveMedia"
17// Copyright (c) 1996-2020 Live Networks, Inc. All rights reserved.
18// Author Bernhard Feiten
19// A filter that breaks up an H.263plus video stream into frames.
20//
21
22#include "H263plusVideoStreamFramer.hh"
23#include "H263plusVideoStreamParser.hh"
24
25#include <string.h>
26#include <GroupsockHelper.hh>
27
28
29///////////////////////////////////////////////////////////////////////////////
30////////// H263plusVideoStreamFramer implementation //////////
31//public///////////////////////////////////////////////////////////////////////
32H263plusVideoStreamFramer* H263plusVideoStreamFramer::createNew(
33 UsageEnvironment& env,
34 FramedSource* inputSource)
35{
36 // Need to add source type checking here??? #####
37 H263plusVideoStreamFramer* fr;
38 fr = new H263plusVideoStreamFramer(env, inputSource);
39 return fr;
40}
41
42
43///////////////////////////////////////////////////////////////////////////////
44H263plusVideoStreamFramer::H263plusVideoStreamFramer(
45 UsageEnvironment& env,
46 FramedSource* inputSource,
47 Boolean createParser)
48 : FramedFilter(env, inputSource),
49 fFrameRate(0.0), // until we learn otherwise
50 fPictureEndMarker(False)
51{
52 // Use the current wallclock time as the base 'presentation time':
53 gettimeofday(&fPresentationTimeBase, NULL);
54 fParser = createParser ? new H263plusVideoStreamParser(this, inputSource) : NULL;
55}
56
57///////////////////////////////////////////////////////////////////////////////
58H263plusVideoStreamFramer::~H263plusVideoStreamFramer()
59{
60 delete fParser;
61}
62
63
64///////////////////////////////////////////////////////////////////////////////
65void H263plusVideoStreamFramer::doGetNextFrame()
66{
67 fParser->registerReadInterest(fTo, fMaxSize);
68 continueReadProcessing();
69}
70
71
72///////////////////////////////////////////////////////////////////////////////
73Boolean H263plusVideoStreamFramer::isH263plusVideoStreamFramer() const
74{
75 return True;
76}
77
78///////////////////////////////////////////////////////////////////////////////
79void H263plusVideoStreamFramer::continueReadProcessing(
80 void* clientData,
81 unsigned char* /*ptr*/, unsigned /*size*/,
82 struct timeval /*presentationTime*/)
83{
84 H263plusVideoStreamFramer* framer = (H263plusVideoStreamFramer*)clientData;
85 framer->continueReadProcessing();
86}
87
88///////////////////////////////////////////////////////////////////////////////
89void H263plusVideoStreamFramer::continueReadProcessing()
90{
91 unsigned acquiredFrameSize;
92
93 u_int64_t frameDuration; // in ms
94
95 acquiredFrameSize = fParser->parse(frameDuration);
96// Calculate some average bitrate information (to be adapted)
97// avgBitrate = (totalBytes * 8 * H263_TIMESCALE) / totalDuration;
98
99 if (acquiredFrameSize > 0) {
100 // We were able to acquire a frame from the input.
101 // It has already been copied to the reader's space.
102 fFrameSize = acquiredFrameSize;
103// fNumTruncatedBytes = fParser->numTruncatedBytes(); // not needed so far
104
105 fFrameRate = frameDuration == 0 ? 0.0 : 1000./(long)frameDuration;
106
107 // Compute "fPresentationTime"
108 if (acquiredFrameSize == 5) // first frame
109 fPresentationTime = fPresentationTimeBase;
110 else
111 fPresentationTime.tv_usec += (long) frameDuration*1000;
112
113 while (fPresentationTime.tv_usec >= 1000000) {
114 fPresentationTime.tv_usec -= 1000000;
115 ++fPresentationTime.tv_sec;
116 }
117
118 // Compute "fDurationInMicroseconds"
119 fDurationInMicroseconds = (unsigned int) frameDuration*1000;;
120
121 // Call our own 'after getting' function. Because we're not a 'leaf'
122 // source, we can call this directly, without risking infinite recursion.
123 afterGetting(this);
124 } else {
125 // We were unable to parse a complete frame from the input, because:
126 // - we had to read more data from the source stream, or
127 // - the source stream has ended.
128 }
129}
130