📄 h261codec.cxx
字号:
/* * h261codec.cxx * * H.323 protocol handler * * Open H323 Library * * Copyright (c) 1998-2000 Equivalence Pty. Ltd. * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is Open H323 Library. * * The Initial Developer of the Original Code is Equivalence Pty. Ltd. * * Contributor(s): Michele Piccini (michele@piccini.com) * Derek Smithies (derek@indranet.co.nz) * * $Log: h261codec.cxx,v $ * Revision 1.20 2000/07/13 12:31:31 robertj * Fixed format name output for in band switching H.261 * * Revision 1.19 2000/07/04 13:00:36 craigs * Fixed problem with selecting large and small video sizes * * Revision 1.18 2000/06/10 09:21:36 rogerh * Make GetFormatName return H.261 QCIF or H.261 CIF * * Revision 1.17 2000/05/10 04:05:34 robertj * Changed capabilities so has a function to get name of codec, instead of relying on PrintOn. * * Revision 1.16 2000/05/02 04:32:26 robertj * Fixed copyright notice comment. * * Revision 1.15 2000/04/29 03:01:48 robertj * Fixed bug in receive of H261 capability, setting cif & qcif variables correctly. * * Revision 1.14 2000/03/24 01:23:49 robertj * Directory reorganisation. * * Revision 1.13 2000/03/21 03:06:49 robertj * Changes to make RTP TX of exact numbers of frames in some codecs. * * Revision 1.12 2000/02/10 03:08:02 craigs * Added ability to specify NTSC or PAL video format * * Revision 1.11 2000/02/04 05:11:19 craigs * Updated for new Makefiles and for new video transmission code * * Revision 1.10 2000/01/13 04:03:45 robertj * Added video transmission * * Revision 1.9 1999/12/23 23:02:35 robertj * File reorganision for separating RTP from H.323 and creation of LID for VPB support. * * Revision 1.8 1999/11/29 08:20:47 craigs * Updated for new codec interface * * Revision 1.7 1999/11/01 00:52:00 robertj * Fixed various problems in video, especially ability to pass error return value. * * Revision 1.6 1999/10/08 09:59:03 robertj * Rewrite of capability for sending multiple audio frames * * Revision 1.5 1999/10/08 04:58:38 robertj * Added capability for sending multiple audio frames in single RTP packet * * Revision 1.4 1999/09/21 14:13:53 robertj * Windows MSVC compatibility. * * Revision 1.3 1999/09/21 08:10:03 craigs * Added support for video devices and H261 codec * * Revision 1.2 1999/09/18 13:24:38 craigs * Added ability to disable jitter buffer * Added ability to access entire RTP packet in codec Write * * Revision 1.1 1999/09/08 04:05:49 robertj * Added support for video capabilities & codec, still needs the actual codec itself! * */#pragma implementation "h261codec.h"#include <ptlib.h>#include "h261codec.h"#include "videoio.h"#include "h245.h"#include "rtp.h"#include "vic/p64.h"#include "vic/p64encoder.h"#define new PNEWH323_H261Capability::H323_H261Capability(unsigned _qcifMPI, unsigned _cifMPI, BOOL _temporalSpatialTradeOffCapability, BOOL _stillImageTransmission, unsigned _maxBitRate){ qcifMPI = _qcifMPI; cifMPI = _cifMPI; temporalSpatialTradeOffCapability = _temporalSpatialTradeOffCapability; maxBitRate = _maxBitRate; stillImageTransmission = _stillImageTransmission;}PObject * H323_H261Capability::Clone() const{ return new H323_H261Capability(qcifMPI, cifMPI, temporalSpatialTradeOffCapability, stillImageTransmission, maxBitRate);}PObject::Comparison H323_H261Capability::Compare(const PObject & obj) const{ Comparison result = H323Capability::Compare(obj); if (result != EqualTo) return result; PAssert(obj.IsDescendant(H323_H261Capability::Class()), PInvalidCast); const H323_H261Capability & other = (const H323_H261Capability &)obj; if (((qcifMPI > 0) && (other.qcifMPI > 0)) || ((cifMPI > 0) && (other.cifMPI > 0))) return EqualTo; if (qcifMPI > 0) return LessThan; return GreaterThan;}PString H323_H261Capability::GetFormatName() const{ if (qcifMPI > 0 && cifMPI > 0) return "H.261-(Q)CIF"; if (qcifMPI > 0) return "H.261-QCIF"; if (cifMPI > 0) return "H.261-CIF"; return "H.261";}unsigned H323_H261Capability::GetSubType() const{ return H245_VideoCapability::e_h261VideoCapability;}BOOL H323_H261Capability::OnSendingPDU(H245_VideoCapability & cap) const{ cap.SetTag(H245_VideoCapability::e_h261VideoCapability); H245_H261VideoCapability & h261 = cap; if (qcifMPI > 0) { h261.IncludeOptionalField(H245_H261VideoCapability::e_qcifMPI); h261.m_qcifMPI = qcifMPI; } if (cifMPI > 0) { h261.IncludeOptionalField(H245_H261VideoCapability::e_cifMPI); h261.m_cifMPI = cifMPI; } h261.m_temporalSpatialTradeOffCapability = temporalSpatialTradeOffCapability; h261.m_maxBitRate = maxBitRate; h261.m_stillImageTransmission = stillImageTransmission; return TRUE;}BOOL H323_H261Capability::OnReceivedPDU(const H245_VideoCapability & cap){ if (cap.GetTag() != H245_VideoCapability::e_h261VideoCapability) return FALSE; const H245_H261VideoCapability & h261 = cap; if (h261.HasOptionalField(H245_H261VideoCapability::e_qcifMPI)) qcifMPI = h261.m_qcifMPI; else qcifMPI = 0; if (h261.HasOptionalField(H245_H261VideoCapability::e_cifMPI)) cifMPI = h261.m_cifMPI; else cifMPI = 0; temporalSpatialTradeOffCapability = h261.m_temporalSpatialTradeOffCapability; maxBitRate = h261.m_maxBitRate; stillImageTransmission = h261.m_stillImageTransmission; return TRUE;}unsigned H323_H261Capability::GetMaxFrameSize() const{ return 2000; // Need to know what correct value is for this.}H323Codec * H323_H261Capability::CreateCodec(H323Codec::Direction direction) const{ return new H323_H261Codec(direction, qcifMPI > 0);}//////////////////////////////////////////////////////////////////////////////H323_H261Codec::H323_H261Codec(Direction dir, BOOL isqCIF) : H323VideoCodec(dir){ rtpPayloadType = RTP_DataFrame::H261; //h261 = h261_create(); PTRACE(3, "Codec\tH261 " << (dir == Encoder ? "en" : "de") << "coder created"); // no video decoder until we receive a packet videoDecoder = NULL; // no video encoder until we receive a packet videoEncoder = NULL; // other stuff now = 1; rvts = NULL; nblk = ndblk = 0; // initial size of the window is CIF packetReceived = dir == Encoder; if (dir == Encoder) { width = isqCIF ? QCIF_WIDTH : CIF_WIDTH; height = isqCIF ? QCIF_HEIGHT : CIF_HEIGHT; } else { width=0; height=0; }}H323_H261Codec::~H323_H261Codec(){ delete videoDecoder; delete videoEncoder; delete rvts;}//This function grabs, displays, and compresses a video frame into//into H261 packets.//Get another frame if all packets of previous frame have been sent.//Get next packet on list and send that one.//Render the current frame if all of its packets have been sent.BOOL H323_H261Codec::Read(BYTE * buffer, unsigned & length, RTP_DataFrame & frame){ if (videoEncoder == NULL) videoEncoder = new P64Encoder(videoInput, videoIsPal); if(rawDevice){ if(!rawDevice->Width()){ PTRACE(2,"H261\t Display width is zero, so no video transmission"); length=0; return FALSE; } videoEncoder->SetSize(rawDevice->Width(),rawDevice->Height()); } if(!videoEncoder->PacketsOutStanding()) { videoEncoder->GrabOneFrame(); RenderFrame(); //use data from grab process. videoEncoder->ProcessOneFrame(); //Generate H261 packets. } videoEncoder->ReadOnePacket(buffer,length); //get next packet on list if(videoEncoder->PacketsOutStanding()) frame.SetMarker(FALSE); else frame.SetMarker(TRUE); return TRUE;}BOOL H323_H261Codec::Write(const BYTE * buffer, unsigned length, const RTP_DataFrame & frame, unsigned & written){ // always indicate we have written the entire packet written = length; // assume buffer is start of H.261 header const BYTE * header = buffer; // see if any contributing source PINDEX cnt = frame.GetContribSrcCount(); if (cnt > 0) { header += cnt * 4; length -= cnt * 4; } // rh = RTP header -> header // bp = payload // cc = payload length // determine video codec type if (videoDecoder == NULL) { if ( (*(buffer+1)) & 2) videoDecoder = new IntraP64Decoder(); else videoDecoder = new FullP64Decoder(); videoDecoder->marks(rvts); } // decode values from the RTP H261 header u_int v = ntohl(*(u_int*)header); int sbit = (v >> 29) & 0x07; int ebit = (v >> 26) & 0x07; int gob = (v >> 20) & 0xf; int mba = (v >> 15) & 0x1f; int quant = (v >> 10) & 0x1f; int mvdh = (v >> 5) & 0x1f; int mvdv = v & 0x1f; //if (gob > 12) { // h261_rtp_bug_ = 1; // mba = (v >> 19) & 0x1f; // gob = (v >> 15) & 0xf; // } if (gob > 12) { //count(STAT_BAD_HEADER); return FALSE; } // leave 4 bytes for H.261 header const BYTE * payload = header + 4; length = length - 4; videoDecoder->mark(now); (void)videoDecoder->decode(payload, length, sbit, ebit, mba, gob, quant, mvdh, mvdv); BOOL ok = TRUE; // If the stream changes format, issue a resize. if (videoDecoder->width() != width) { ok = Resize(videoDecoder->width(), videoDecoder->height()); videoDecoder->marks(rvts); } if (ok && frame.GetMarker()) { videoDecoder->sync(); ndblk = videoDecoder->ndblk(); if (!packetReceived) { packetReceived = TRUE; ok = Resize(videoDecoder->width(), videoDecoder->height()); } else ok = RenderFrame(); videoDecoder->resetndblk(); } return ok;}/**Resize is relevant to the decoder only*/BOOL H323_H261Codec::Resize(int _width, int _height){ width = _width; height = _height; nblk = (width * height) / 64; delete rvts; rvts = new BYTE[nblk]; memset(rvts, 0, nblk); // only pass on the resize if we have actually received any data if (packetReceived&&rawDevice) { rawDevice->SetSize(width, height); PTRACE(1, "Size of video frame set to " << width << "x" << height); } return Redraw();}BOOL H323_H261Codec::Redraw(){ now = 1; memset(rvts, 1, nblk);// if (rawDevice != NULL)// rawDevice->SetNow(0); return RenderFrame();}BOOL H323_H261Codec::RenderFrame(){ int wraptime = now ^ 0x80; BYTE * ts = rvts; int k; for (k = nblk; --k >= 0; ++ts) { if (*ts == wraptime) *ts = (BYTE)now; } BOOL ok = TRUE; if ((rawDevice != NULL) && packetReceived) if (direction == Encoder) ok = rawDevice->Redraw(videoEncoder->Frame()); else ok = rawDevice->Redraw(videoDecoder->Frame()); now = (now + 1) & 0xff; return ok;}unsigned H323_H261Codec::GetFrameRate() const{ return 3003; // Number of 90kHz units in a video frame at 29.97Hz}unsigned H323_H261Codec::GetBandwidth() const{ return 2400; // Number of 100 bits/sec units used by codec}/////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -