4 * H.323 protocol handler
8 * Copyright (c) 1998-2000 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
20 * The Original Code is Open H323 Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Contributor(s): Michele Piccini (michele@piccini.com)
25 * Derek Smithies (derek@indranet.co.nz)
28 * Revision 2.19 2005/08/24 10:15:10 rjongbloed
29 * Fixed missing marker bit on codec output, get more than just the first frame!
31 * Revision 2.18 2005/08/23 12:46:27 rjongbloed
32 * Fix some decoder issues, now get inital frame displayed!
34 * Revision 2.17 2005/08/20 09:01:56 rjongbloed
35 * H.261 port to OPAL model
37 * Revision 2.16 2005/02/24 19:49:44 dsandras
38 * Applied patch from Hannes Friederich to fix quality problem in some circumstances.
40 * Revision 2.15 2005/02/21 12:19:53 rjongbloed
41 * Added new "options list" to the OpalMediaFormat class.
43 * Revision 2.14 2004/04/07 08:21:00 rjongbloed
44 * Changes for new RTTI system.
46 * Revision 2.13 2004/03/11 06:54:28 csoutheren
47 * Added ability to disable SIP or H.323 stacks
49 * Revision 2.12 2004/02/19 10:47:02 rjongbloed
50 * Merged OpenH323 version 1.13.1 changes.
52 * Revision 2.11 2004/01/18 15:35:20 rjongbloed
53 * More work on video support
55 * Revision 2.10 2003/03/17 10:26:59 robertj
56 * Added video support.
58 * Revision 2.9 2003/01/07 04:39:53 robertj
59 * Updated to OpenH323 v1.11.2
61 * Revision 2.8 2002/11/10 11:33:18 robertj
62 * Updated to OpenH323 v1.10.3
64 * Revision 2.7 2002/09/04 06:01:47 robertj
65 * Updated to OpenH323 v1.9.6
67 * Revision 2.6 2002/07/01 04:56:31 robertj
68 * Updated to OpenH323 v1.9.1
70 * Revision 2.5 2002/01/22 05:18:59 robertj
71 * Added RTP encoding name string to media format database.
72 * Changed time units to clock rate in Hz.
74 * Revision 2.4 2002/01/14 06:35:57 robertj
75 * Updated to OpenH323 v1.7.9
77 * Revision 2.3 2001/11/02 10:45:19 robertj
78 * Updated to OpenH323 v1.7.3
80 * Revision 2.2 2001/10/05 00:22:13 robertj
81 * Updated to PWLib 1.2.0 and OpenH323 1.7.0
83 * Revision 2.1 2001/08/01 05:04:28 robertj
84 * Changes to allow control of linking software transcoders, use macros
86 * Allowed codecs to be used without H.,323 being linked by using the
88 * Major changes to H.323 capabilities, uses OpalMediaFormat for base name.
90 * Revision 2.0 2001/07/27 15:48:24 robertj
91 * Conversion of OpenH323 to Open Phone Abstraction Library (OPAL)
93 * Revision 1.59 2004/01/02 00:31:42 dereksmithies
94 * Fix test on presence/absence of video.
96 * Revision 1.58 2003/12/14 10:42:29 rjongbloed
97 * Changes for compilability without video support.
99 * Revision 1.57 2003/10/02 23:37:56 dereksmithies
100 * Add fix for fast update problem in h261 codec. Thanks to Martin André for doing the initial legwork.
102 * Revision 1.56 2003/04/03 23:54:15 robertj
103 * Added fast update to H.261 codec, thanks Gustavo García Bernardo
105 * Revision 1.55 2003/03/20 23:45:46 dereks
106 * Make formatting more consistant with the openh323.org standard.
108 * Revision 1.54 2003/03/17 08:05:02 robertj
109 * Removed videoio classes in openh323 as now has versions in pwlib.
111 * Revision 1.53 2003/03/11 22:05:00 dereks
112 * Video receive will not terminate in abnormal situations
113 * Thanks to Damien Sandras.
115 * Revision 1.52 2002/12/29 22:35:34 dereks
116 * Fix so video with Windows XP works. Thanks Damien Sandras.
118 * Revision 1.51 2002/12/24 07:38:49 robertj
119 * Patches to fix divide by zero error, thanks Damien Sandras
121 * Revision 1.50 2002/12/16 09:11:19 robertj
122 * Added new video bit rate control, thanks Walter H. Whitlock
124 * Revision 1.49 2002/08/05 10:03:47 robertj
125 * Cosmetic changes to normalise the usage of pragma interface/implementation.
127 * Revision 1.48 2002/05/19 22:03:45 dereks
128 * Add fix from Sean Miceli, so correct P64Decoder is picked in calls with Netmeeting.
129 * Many thanks, good work!
131 * Revision 1.47 2002/04/26 04:58:34 dereks
132 * Add Walter Whitlock's fixes, based on Victor Ivashim's suggestions to improve
133 * the quality with Netmeeting. Thanks guys!!!
135 * Revision 1.46 2002/04/05 00:53:19 dereks
136 * Modify video frame encoding so that frame is encoded on an incremental basis.
137 * Thanks to Walter Whitlock - good work.
139 * Revision 1.45 2002/01/09 06:07:13 robertj
140 * Fixed setting of RTP timestamp values on video transmission.
142 * Revision 1.44 2002/01/09 00:21:39 robertj
143 * Changes to support outgoing H.245 RequstModeChange.
145 * Revision 1.43 2002/01/08 01:30:41 robertj
146 * Tidied up some PTRACE debug output.
148 * Revision 1.42 2002/01/03 23:05:50 dereks
149 * Add methods to count number of H261 packets waiting to be sent.
151 * Revision 1.41 2001/12/20 01:19:43 dereks
152 * modify ptrace statments.
154 * Revision 1.40 2001/12/13 03:01:23 dereks
155 * Modify trace statement.
157 * Revision 1.39 2001/12/04 05:13:12 robertj
158 * Added videa bandwidth limiting code for H.261, thanks Jose Luis Urien.
160 * Revision 1.38 2001/12/04 04:26:06 robertj
161 * Added code to allow change of video quality in H.261, thanks Damian Sandras
163 * Revision 1.37 2001/10/23 02:17:16 dereks
164 * Initial release of cu30 video codec.
166 * Revision 1.36 2001/09/26 01:59:31 robertj
167 * Fixed MSVC warning.
169 * Revision 1.35 2001/09/25 03:14:47 dereks
170 * Add constant bitrate control for the h261 video codec.
171 * Thanks Tiziano Morganti for the code to set bit rate. Good work!
173 * Revision 1.34 2001/09/21 02:51:29 robertj
174 * Added default session ID to media format description.
176 * Revision 1.33 2001/08/22 01:28:20 robertj
177 * Resolved confusion with YUV411P and YUV420P video formats, thanks Mark Cooke.
179 * Revision 1.32 2001/07/09 07:19:40 rogerh
180 * Make the encoder render a frames (for local video) only when there is a
183 * Revision 1.31 2001/06/19 02:01:42 dereks
184 * The video encoder thread ends if the renderframe fails.
186 * Revision 1.30 2001/06/13 21:46:37 dereks
187 * Add 5 msec separator between consecutive packets generated from the same
188 * frame. Prevents lost packets, and improves reliability.
190 * Revision 1.29 2001/05/25 01:10:26 dereks
191 * Remove unnecessary packet receive variable.
192 * Alter the position of the check for change in frame size.
194 * Revision 1.28 2001/02/09 05:13:55 craigs
195 * Added pragma implementation to (hopefully) reduce the executable image size
198 * Revision 1.27 2001/01/25 07:27:16 robertj
199 * Major changes to add more flexible OpalMediaFormat class to normalise
200 * all information about media types, especially codecs.
202 * Revision 1.26 2000/12/19 22:33:44 dereks
203 * Adjust so that the video channel is used for reading/writing raw video
204 * data, which better modularizes the video codec.
206 * Revision 1.25 2000/10/13 02:20:32 robertj
207 * Fixed capability clone so gets all fields including those in ancestor.
209 * Revision 1.24 2000/10/13 01:47:26 dereks
210 * Include command option for setting the number of transmitted video
211 * frames per second. use --videotxfps n
213 * Revision 1.23 2000/09/08 06:41:38 craigs
214 * Added ability to set video device
215 * Added ability to select test input frames
217 * Revision 1.22 2000/08/28 23:47:41 dereks
218 * Fix bug in resizing image of received video
220 * Revision 1.21 2000/08/21 04:45:06 dereks
221 * Fix dangling pointer that caused segfaults for windows&unix users.
222 * Improved the test image which is used when video grabber won't open.
223 * Added code to handle setting of video Tx Quality.
224 * Added code to set the number of background blocks sent with every frame.
226 * Revision 1.20 2000/07/13 12:31:31 robertj
227 * Fixed format name output for in band switching H.261
229 * Revision 1.19 2000/07/04 13:00:36 craigs
230 * Fixed problem with selecting large and small video sizes
232 * Revision 1.18 2000/06/10 09:21:36 rogerh
233 * Make GetFormatName return H.261 QCIF or H.261 CIF
235 * Revision 1.17 2000/05/10 04:05:34 robertj
236 * Changed capabilities so has a function to get name of codec, instead of relying on PrintOn.
238 * Revision 1.16 2000/05/02 04:32:26 robertj
239 * Fixed copyright notice comment.
241 * Revision 1.15 2000/04/29 03:01:48 robertj
242 * Fixed bug in receive of H261 capability, setting cif & qcif variables correctly.
244 * Revision 1.14 2000/03/24 01:23:49 robertj
245 * Directory reorganisation.
247 * Revision 1.13 2000/03/21 03:06:49 robertj
248 * Changes to make RTP TX of exact numbers of frames in some codecs.
250 * Revision 1.12 2000/02/10 03:08:02 craigs
251 * Added ability to specify NTSC or PAL video format
253 * Revision 1.11 2000/02/04 05:11:19 craigs
254 * Updated for new Makefiles and for new video transmission code
256 * Revision 1.10 2000/01/13 04:03:45 robertj
257 * Added video transmission
259 * Revision 1.9 1999/12/23 23:02:35 robertj
260 * File reorganision for separating RTP from H.323 and creation of LID for VPB support.
262 * Revision 1.8 1999/11/29 08:20:47 craigs
263 * Updated for new codec interface
265 * Revision 1.7 1999/11/01 00:52:00 robertj
266 * Fixed various problems in video, especially ability to pass error return value.
268 * Revision 1.6 1999/10/08 09:59:03 robertj
269 * Rewrite of capability for sending multiple audio frames
271 * Revision 1.5 1999/10/08 04:58:38 robertj
272 * Added capability for sending multiple audio frames in single RTP packet
274 * Revision 1.4 1999/09/21 14:13:53 robertj
275 * Windows MSVC compatibility.
277 * Revision 1.3 1999/09/21 08:10:03 craigs
278 * Added support for video devices and H261 codec
280 * Revision 1.2 1999/09/18 13:24:38 craigs
281 * Added ability to disable jitter buffer
282 * Added ability to access entire RTP packet in codec Write
284 * Revision 1.1 1999/09/08 04:05:49 robertj
285 * Added support for video capabilities & codec, still needs the actual codec itself!
292 #pragma implementation "h261codec.h"
295 #include <codec/h261codec.h>
297 #ifndef NO_OPAL_VIDEO
299 #include <asn/h245.h>
301 #include "vic/p64encoder.h"
307 const OpalVideoFormat
OpalH261_QCIF(OPAL_H261_QCIF
, RTP_DataFrame::H261
, "H261", 176, 144, 10, 128000);
308 const OpalVideoFormat
OpalH261_CIF (OPAL_H261_CIF
, RTP_DataFrame::H261
, "H261", 352, 288, 10, 128000);
311 ///////////////////////////////////////////////////////////////////////////////
315 H323_H261Capability::H323_H261Capability(unsigned _qcifMPI
,
317 BOOL _temporalSpatialTradeOffCapability
,
318 BOOL _stillImageTransmission
,
319 unsigned _maxBitRate
)
323 temporalSpatialTradeOffCapability
= _temporalSpatialTradeOffCapability
;
324 maxBitRate
= _maxBitRate
;
325 stillImageTransmission
= _stillImageTransmission
;
329 PObject
* H323_H261Capability::Clone() const
331 return new H323_H261Capability(*this);
335 PObject::Comparison
H323_H261Capability::Compare(const PObject
& obj
) const
337 Comparison result
= H323Capability::Compare(obj
);
338 if (result
!= EqualTo
)
341 PAssert(PIsDescendant(&obj
, H323_H261Capability
), PInvalidCast
);
342 const H323_H261Capability
& other
= (const H323_H261Capability
&)obj
;
344 if (((qcifMPI
> 0) && (other
.qcifMPI
> 0)) ||
345 ((cifMPI
> 0) && (other
.cifMPI
> 0)))
355 unsigned H323_H261Capability::GetSubType() const
357 return H245_VideoCapability::e_h261VideoCapability
;
361 PString
H323_H261Capability::GetFormatName() const
363 return qcifMPI
> 0 ? OpalH261_QCIF
: OpalH261_CIF
;
367 BOOL
H323_H261Capability::OnSendingPDU(H245_VideoCapability
& cap
) const
369 cap
.SetTag(H245_VideoCapability::e_h261VideoCapability
);
371 H245_H261VideoCapability
& h261
= cap
;
373 h261
.IncludeOptionalField(H245_H261VideoCapability::e_qcifMPI
);
374 h261
.m_qcifMPI
= qcifMPI
;
377 h261
.IncludeOptionalField(H245_H261VideoCapability::e_cifMPI
);
378 h261
.m_cifMPI
= cifMPI
;
380 h261
.m_temporalSpatialTradeOffCapability
= temporalSpatialTradeOffCapability
;
381 h261
.m_maxBitRate
= maxBitRate
;
382 h261
.m_stillImageTransmission
= stillImageTransmission
;
387 BOOL
H323_H261Capability::OnSendingPDU(H245_VideoMode
& pdu
) const
389 pdu
.SetTag(H245_VideoMode::e_h261VideoMode
);
390 H245_H261VideoMode
& mode
= pdu
;
391 mode
.m_resolution
.SetTag(cifMPI
> 0 ? H245_H261VideoMode_resolution::e_cif
392 : H245_H261VideoMode_resolution::e_qcif
);
393 mode
.m_bitRate
= maxBitRate
;
394 mode
.m_stillImageTransmission
= stillImageTransmission
;
399 BOOL
H323_H261Capability::OnReceivedPDU(const H245_VideoCapability
& cap
)
401 if (cap
.GetTag() != H245_VideoCapability::e_h261VideoCapability
)
404 OpalMediaFormat
& mediaFormat
= GetWritableMediaFormat();
406 const H245_H261VideoCapability
& h261
= cap
;
407 if (h261
.HasOptionalField(H245_H261VideoCapability::e_qcifMPI
)) {
408 qcifMPI
= h261
.m_qcifMPI
;
409 mediaFormat
.SetOptionInteger(OpalMediaFormat::FrameTimeOption
, OpalMediaFormat::VideoClockRate
*100*qcifMPI
/2997);
410 mediaFormat
.SetOptionInteger(OpalVideoFormat::FrameWidthOption
, 176);
411 mediaFormat
.SetOptionInteger(OpalVideoFormat::FrameHeightOption
, 144);
416 if (h261
.HasOptionalField(H245_H261VideoCapability::e_cifMPI
)) {
417 cifMPI
= h261
.m_cifMPI
;
418 mediaFormat
.SetOptionInteger(OpalMediaFormat::FrameTimeOption
, OpalMediaFormat::VideoClockRate
*100*cifMPI
/2997);
419 mediaFormat
.SetOptionInteger(OpalVideoFormat::FrameWidthOption
, 352);
420 mediaFormat
.SetOptionInteger(OpalVideoFormat::FrameHeightOption
, 288);
425 maxBitRate
= h261
.m_maxBitRate
;
426 mediaFormat
.SetOptionInteger(OpalMediaFormat::MaxBitRateOption
, maxBitRate
*100);
428 temporalSpatialTradeOffCapability
= h261
.m_temporalSpatialTradeOffCapability
;
429 stillImageTransmission
= h261
.m_stillImageTransmission
;
436 //////////////////////////////////////////////////////////////////////////////
438 Opal_H261_YUV420P::Opal_H261_YUV420P(const OpalTranscoderRegistration
& registration
)
439 : OpalVideoTranscoder(registration
)
442 expectedSequenceNumber
= 0;
446 packetReceived
= FALSE
;
448 PTRACE(3, "Codec\tH261 decoder created");
452 Opal_H261_YUV420P::~Opal_H261_YUV420P()
460 PINDEX
Opal_H261_YUV420P::GetOptimalDataFrameSize(BOOL input
) const
462 return input
? RTP_DataFrame::MaxEthernetPayloadSize
: ((frameWidth
* frameHeight
* 12) / 8);
466 BOOL
Opal_H261_YUV420P::ConvertFrames(const RTP_DataFrame
& src
, RTP_DataFrameList
& dst
)
470 if (videoDecoder
== NULL
) {
471 // Create the actual decoder
472 videoDecoder
= new FullP64Decoder();
473 videoDecoder
->marks(rvts
);
476 // Check for lost packets to help decoder
477 BOOL lostPreviousPacket
= FALSE
;
478 if (expectedSequenceNumber
!= 0 && expectedSequenceNumber
!= src
.GetSequenceNumber()) {
479 lostPreviousPacket
= TRUE
;
480 PTRACE(3,"H261\tDetected loss of one video packet. "
481 << expectedSequenceNumber
<< " != "
482 << src
.GetSequenceNumber() << " Will recover.");
484 expectedSequenceNumber
= (WORD
)(src
.GetSequenceNumber()+1);
486 videoDecoder
->mark(now
);
487 if (!videoDecoder
->decode(src
.GetPayloadPtr(), src
.GetPayloadSize(), lostPreviousPacket
)) {
488 PTRACE (3, "H261\t Could not decode frame, continuing in hope.");
492 //Check for a resize - can change at any time!
493 if (frameWidth
!= (unsigned)videoDecoder
->width() ||
494 frameHeight
!= (unsigned)videoDecoder
->height()) {
495 frameWidth
= videoDecoder
->width();
496 frameHeight
= videoDecoder
->height();
498 nblk
= (frameWidth
* frameHeight
) / 64;
500 rvts
= new BYTE
[nblk
];
501 memset(rvts
, 0, nblk
);
502 videoDecoder
->marks(rvts
);
505 if (!src
.GetMarker()) // Have not built an entire frame yet
508 videoDecoder
->sync();
509 ndblk
= videoDecoder
->ndblk();
511 int wraptime
= now
^ 0x80;
514 for (k
= nblk
; --k
>= 0; ++ts
) {
519 now
= (now
+ 1) & 0xff;
521 PINDEX frameBytes
= (frameWidth
* frameHeight
* 12) / 8;
522 RTP_DataFrame
* pkt
= new RTP_DataFrame(sizeof(FrameHeader
)+frameBytes
);
523 pkt
->SetMarker(true);
524 FrameHeader
* frameHeader
= (FrameHeader
*)pkt
->GetPayloadPtr();
525 frameHeader
->x
= frameHeader
->y
= 0;
526 frameHeader
->width
= frameWidth
;
527 frameHeader
->height
= frameHeight
;
528 memcpy(frameHeader
->data
, videoDecoder
->GetFramePtr(), frameBytes
);
532 videoDecoder
->resetndblk();
538 //////////////////////////////////////////////////////////////////////////////
540 Opal_YUV420P_H261::Opal_YUV420P_H261(const OpalTranscoderRegistration
& registration
)
541 : OpalVideoTranscoder(registration
)
544 PTRACE(3, "Codec\tH261 encoder created");
548 Opal_YUV420P_H261::~Opal_YUV420P_H261()
554 PINDEX
Opal_YUV420P_H261::GetOptimalDataFrameSize(BOOL input
) const
556 return input
? ((frameWidth
* frameHeight
* 12) / 8) : maxOutputSize
;
560 BOOL
Opal_YUV420P_H261::ConvertFrames(const RTP_DataFrame
& src
, RTP_DataFrameList
& dst
)
564 if (src
.GetPayloadSize() < sizeof(FrameHeader
)) {
565 PTRACE(1,"H261\t Video grab too small, Close down video transmission thread.");
569 FrameHeader
* header
= (FrameHeader
*)src
.GetPayloadPtr();
571 if (header
->x
!= 0 && header
->y
!= 0) {
572 PTRACE(1,"H261\tVideo grab of partial frame unsupported, Close down video transmission thread.");
576 if (videoEncoder
== NULL
)
577 videoEncoder
= new P64Encoder(videoQuality
, fillLevel
);
579 if (frameWidth
!= header
->width
|| frameHeight
!= header
->height
) {
580 frameWidth
= header
->width
;
581 frameHeight
= header
->height
;
582 videoEncoder
->SetSize(header
->width
, header
->height
);
586 memcpy(videoEncoder
->GetFramePtr(), header
->data
, frameWidth
*frameHeight
*12/8);
588 videoEncoder
->PreProcessOneFrame();
590 while (videoEncoder
->MoreToIncEncode()) {
591 RTP_DataFrame
* pkt
= new RTP_DataFrame(2048);
593 videoEncoder
->IncEncodeAndGetPacket(pkt
->GetPayloadPtr(), length
); //get next packet on list
594 pkt
->SetPayloadSize(length
);
595 pkt
->SetTimestamp(src
.GetTimestamp());
596 pkt
->SetPayloadType(RTP_DataFrame::H261
);
600 dst
[dst
.GetSize()-1].SetMarker(TRUE
);
605 #endif // NO_OPAL_VIDEO
608 /////////////////////////////////////////////////////////////////////////////