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// RTP sink for H.263+ video (RFC 4629)
19// Implementation
20
21#include "H263plusVideoRTPSink.hh"
22
23H263plusVideoRTPSink
24::H263plusVideoRTPSink(UsageEnvironment& env, Groupsock* RTPgs,
25 unsigned char rtpPayloadFormat,
26 u_int32_t rtpTimestampFrequency)
27 : VideoRTPSink(env, RTPgs, rtpPayloadFormat, rtpTimestampFrequency, "H263-1998") {
28}
29
30H263plusVideoRTPSink::~H263plusVideoRTPSink() {
31}
32
33H263plusVideoRTPSink*
34H263plusVideoRTPSink::createNew(UsageEnvironment& env, Groupsock* RTPgs,
35 unsigned char rtpPayloadFormat,
36 u_int32_t rtpTimestampFrequency) {
37 return new H263plusVideoRTPSink(env, RTPgs, rtpPayloadFormat, rtpTimestampFrequency);
38}
39
40Boolean H263plusVideoRTPSink
41::frameCanAppearAfterPacketStart(unsigned char const* /*frameStart*/,
42 unsigned /*numBytesInFrame*/) const {
43 // A packet can contain only one frame
44 return False;
45}
46
47void H263plusVideoRTPSink
48::doSpecialFrameHandling(unsigned fragmentationOffset,
49 unsigned char* frameStart,
50 unsigned numBytesInFrame,
51 struct timeval framePresentationTime,
52 unsigned numRemainingBytes) {
53 if (fragmentationOffset == 0) {
54 // This packet contains the first (or only) fragment of the frame.
55 // Set the 'P' bit in the special header:
56 unsigned short specialHeader = 0x0400;
57
58 // Also, reuse the first two bytes of the payload for this special
59 // header. (They should both have been zero.)
60 if (numBytesInFrame < 2) {
61 envir() << "H263plusVideoRTPSink::doSpecialFrameHandling(): bad frame size "
62 << numBytesInFrame << "\n";
63 return;
64 }
65 if (frameStart[0] != 0 || frameStart[1] != 0) {
66 envir() << "H263plusVideoRTPSink::doSpecialFrameHandling(): unexpected non-zero first two bytes!\n";
67 }
68 frameStart[0] = specialHeader>>8;
69 frameStart[1] = (unsigned char)specialHeader;
70 } else {
71 unsigned short specialHeader = 0;
72 setSpecialHeaderBytes((unsigned char*)&specialHeader, 2);
73 }
74
75 if (numRemainingBytes == 0) {
76 // This packet contains the last (or only) fragment of the frame.
77 // Set the RTP 'M' ('marker') bit:
78 setMarkerBit();
79 }
80
81 // Also set the RTP timestamp:
82 setTimestamp(framePresentationTime);
83}
84
85
86unsigned H263plusVideoRTPSink::specialHeaderSize() const {
87 // There's a 2-byte special video header. However, if we're the first
88 // (or only) fragment of a frame, then we reuse the first 2 bytes of
89 // the payload instead.
90 return (curFragmentationOffset() == 0) ? 0 : 2;
91}
92