📄 h263codec.cxx
字号:
unsigned _cif4MPI,
unsigned _cif16MPI,
unsigned _maxBitRate,
BOOL _unrestrictedVector,
BOOL _arithmeticCoding,
BOOL _advancedPrediction,
BOOL _pbFrames,
BOOL _temporalSpatialTradeOff,
unsigned _hrd_B,
unsigned _bppMaxKb,
unsigned _slowSqcifMPI,
unsigned _slowQcifMPI,
unsigned _slowCifMPI,
unsigned _slowCif4MPI,
unsigned _slowCif16MPI,
BOOL _errorCompensation)
{
sqcifMPI = (_sqcifMPI>0?_sqcifMPI:-(signed)_slowSqcifMPI);
qcifMPI = (_qcifMPI>0?_qcifMPI:-(signed)_slowQcifMPI);
cifMPI = (_cifMPI>0?_cifMPI:-(signed)_slowCifMPI);
cif4MPI = (_cif4MPI>0?_cif4MPI:-(signed)_slowCif4MPI);
cif16MPI = (_cif16MPI>0?_cif16MPI:-(signed)_slowCif16MPI);
maxBitRate = _maxBitRate;
unrestrictedVector = _unrestrictedVector;
arithmeticCoding = _arithmeticCoding;
advancedPrediction = _advancedPrediction;
pbFrames = _pbFrames;
temporalSpatialTradeOff = _temporalSpatialTradeOff;
hrd_B = _hrd_B;
bppMaxKb = _bppMaxKb;
errorCompensation = _errorCompensation;
}
PObject * H323_H263Capability::Clone() const
{
return new H323_H263Capability(*this);
}
PObject::Comparison H323_H263Capability::Compare(const PObject & obj) const
{
if (!PIsDescendant(&obj, H323_H263Capability))
return LessThan;
Comparison result = H323Capability::Compare(obj);
if (result != EqualTo)
return result;
const H323_H263Capability & other = (const H323_H263Capability &)obj;
if ((sqcifMPI && other.sqcifMPI) ||
(qcifMPI && other.qcifMPI) ||
(cifMPI && other.cifMPI) ||
(cif4MPI && other.cif4MPI) ||
(cif16MPI && other.cif16MPI))
return EqualTo;
if ((!cif16MPI && other.cif16MPI) ||
(!cif4MPI && other.cif4MPI) ||
(!cifMPI && other.cifMPI) ||
(!qcifMPI && other.qcifMPI))
return LessThan;
return GreaterThan;
}
PString H323_H263Capability::GetFormatName() const
{
PString ret = OpalH263;
if (sqcifMPI)
ret += "-SQCIF";
if (qcifMPI)
ret += "-QCIF";
if (cifMPI)
ret += "-CIF";
if (cif4MPI)
ret += "-4CIF";
if (cif16MPI)
ret += "-16CIF";
return ret;
}
unsigned H323_H263Capability::GetSubType() const
{
return H245_VideoCapability::e_h263VideoCapability;
}
BOOL H323_H263Capability::OnSendingPDU(H245_VideoCapability & cap) const
{
cap.SetTag(H245_VideoCapability::e_h263VideoCapability);
H245_H263VideoCapability & h263 = cap;
if (sqcifMPI > 0) {
h263.IncludeOptionalField(H245_H263VideoCapability::e_sqcifMPI);
h263.m_sqcifMPI = sqcifMPI;
}
if (qcifMPI > 0) {
h263.IncludeOptionalField(H245_H263VideoCapability::e_qcifMPI);
h263.m_qcifMPI = qcifMPI;
}
if (cifMPI > 0) {
h263.IncludeOptionalField(H245_H263VideoCapability::e_cifMPI);
h263.m_cifMPI = cifMPI;
}
if (cif4MPI > 0) {
h263.IncludeOptionalField(H245_H263VideoCapability::e_cif4MPI);
h263.m_cif4MPI = cif4MPI;
}
if (cif16MPI > 0) {
h263.IncludeOptionalField(H245_H263VideoCapability::e_cif16MPI);
h263.m_cif16MPI = cif16MPI;
}
h263.m_temporalSpatialTradeOffCapability = temporalSpatialTradeOff;
h263.m_maxBitRate = maxBitRate;
if (sqcifMPI < 0) {
h263.IncludeOptionalField(H245_H263VideoCapability::e_slowSqcifMPI);
h263.m_slowSqcifMPI = -sqcifMPI;
}
if (qcifMPI < 0) {
h263.IncludeOptionalField(H245_H263VideoCapability::e_slowQcifMPI);
h263.m_slowQcifMPI = -qcifMPI;
}
if (cifMPI < 0) {
h263.IncludeOptionalField(H245_H263VideoCapability::e_slowCifMPI);
h263.m_slowCifMPI = -cifMPI;
}
if (cif4MPI < 0) {
h263.IncludeOptionalField(H245_H263VideoCapability::e_slowCif4MPI);
h263.m_slowCif4MPI = -cif4MPI;
}
if (cif16MPI < 0) {
h263.IncludeOptionalField(H245_H263VideoCapability::e_slowCif16MPI);
h263.m_slowCif16MPI = -cif16MPI;
}
return TRUE;
}
BOOL H323_H263Capability::OnSendingPDU(H245_VideoMode & pdu) const
{
pdu.SetTag(H245_VideoMode::e_h263VideoMode);
H245_H263VideoMode & mode = pdu;
mode.m_resolution.SetTag(cif16MPI ? H245_H263VideoMode_resolution::e_cif16
:(cif4MPI ? H245_H263VideoMode_resolution::e_cif4
:(cifMPI ? H245_H263VideoMode_resolution::e_cif
:(qcifMPI ? H245_H263VideoMode_resolution::e_qcif
: H245_H263VideoMode_resolution::e_sqcif))));
mode.m_bitRate = maxBitRate;
mode.m_unrestrictedVector = unrestrictedVector;
mode.m_arithmeticCoding = arithmeticCoding;
mode.m_advancedPrediction = advancedPrediction;
mode.m_pbFrames = pbFrames;
mode.m_errorCompensation = errorCompensation;
return TRUE;
}
BOOL H323_H263Capability::OnReceivedPDU(const H245_VideoCapability & cap)
{
if (cap.GetTag() != H245_VideoCapability::e_h263VideoCapability)
return FALSE;
const H245_H263VideoCapability & h263 = cap;
if (h263.HasOptionalField(H245_H263VideoCapability::e_sqcifMPI))
sqcifMPI = h263.m_sqcifMPI;
else if (h263.HasOptionalField(H245_H263VideoCapability::e_slowSqcifMPI))
sqcifMPI = -(signed)h263.m_slowSqcifMPI;
else
sqcifMPI = 0;
if (h263.HasOptionalField(H245_H263VideoCapability::e_qcifMPI))
qcifMPI = h263.m_qcifMPI;
else if (h263.HasOptionalField(H245_H263VideoCapability::e_slowQcifMPI))
qcifMPI = -(signed)h263.m_slowQcifMPI;
else
qcifMPI = 0;
if (h263.HasOptionalField(H245_H263VideoCapability::e_cifMPI))
cifMPI = h263.m_cifMPI;
else if (h263.HasOptionalField(H245_H263VideoCapability::e_slowCifMPI))
cifMPI = -(signed)h263.m_slowCifMPI;
else
cifMPI = 0;
if (h263.HasOptionalField(H245_H263VideoCapability::e_cif4MPI))
cif4MPI = h263.m_cif4MPI;
else if (h263.HasOptionalField(H245_H263VideoCapability::e_slowCif4MPI))
cif4MPI = -(signed)h263.m_slowCif4MPI;
else
cif4MPI = 0;
if (h263.HasOptionalField(H245_H263VideoCapability::e_cif16MPI))
cif16MPI = h263.m_cif16MPI;
else if (h263.HasOptionalField(H245_H263VideoCapability::e_slowCif16MPI))
cif16MPI = -(signed)h263.m_slowCif16MPI;
else
cif16MPI = 0;
maxBitRate = h263.m_maxBitRate;
unrestrictedVector = h263.m_unrestrictedVector;
arithmeticCoding = h263.m_arithmeticCoding;
advancedPrediction = h263.m_advancedPrediction;
pbFrames = h263.m_pbFrames;
temporalSpatialTradeOff = h263.m_temporalSpatialTradeOffCapability;
hrd_B = h263.m_hrd_B;
bppMaxKb = h263.m_bppMaxKb;
errorCompensation = h263.m_errorCompensation;
return TRUE;
}
#endif // NO_H323
//////////////////////////////////////////////////////////////////////
void H263Packet::Store(void *_data, int _data_size, void *_hdr, int _hdr_size)
{
data = _data;
data_size = _data_size;
hdr = _hdr;
hdr_size = _hdr_size;
}
BOOL H263Packet::Read(unsigned & length, RTP_DataFrame & frame)
{
length = (unsigned) (hdr_size + data_size);
if (!frame.SetPayloadSize(length)) {
PTRACE(1, "H263Pck\tNot enough memory for packet of " << length << " bytes");
length = 0;
return FALSE;
}
memcpy(frame.GetPayloadPtr(), hdr, hdr_size);
memcpy(frame.GetPayloadPtr() + hdr_size, data, data_size);
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////
Opal_H263_YUV420P::Opal_H263_YUV420P()
: OpalVideoTranscoder(OpalH263, OpalYUV420P)
{
if (!ff.IsLoaded())
return;
if ((codec = ff.AvcodecFindDecoder(CODEC_ID_H263)) == NULL) {
PTRACE(1, "H263\tCodec not found for decoder");
return;
}
frameWidth = 352;
frameHeight = 288;
context = ff.AvcodecAllocContext();
if (context == NULL) {
PTRACE(1, "H263\tFailed to allocate context for decoder");
return;
}
picture = ff.AvcodecAllocFrame();
if (picture == NULL) {
PTRACE(1, "H263\tFailed to allocate frame for decoder");
return;
}
if (!OpenCodec()) { // decoder will re-initialise context with correct frame size
PTRACE(1, "H263\tFailed to open codec for decoder");
return;
}
frameNum = 0;
PTRACE(3, "Codec\tH263 decoder created");
}
Opal_H263_YUV420P::~Opal_H263_YUV420P()
{
if (ff.IsLoaded()) {
CloseCodec();
ff.AvcodecFree(context);
ff.AvcodecFree(picture);
}
}
BOOL Opal_H263_YUV420P::OpenCodec()
{
// avoid copying input/output
context->flags |= CODEC_FLAG_INPUT_PRESERVED; // we guarantee to preserve input for max_b_frames+1 frames
context->flags |= CODEC_FLAG_EMU_EDGE; // don't draw edges
context->width = frameWidth;
context->height = frameHeight;
context->workaround_bugs = 0; // no workaround for buggy H.263 implementations
context->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
context->error_resilience = FF_ER_CAREFULL;
if (ff.AvcodecOpen(context, codec) < 0) {
PTRACE(1, "H263\tFailed to open H.263 decoder");
return FALSE;
}
return TRUE;
}
void Opal_H263_YUV420P::CloseCodec()
{
if (context != NULL) {
if (context->codec != NULL) {
ff.AvcodecClose(context);
PTRACE(5, "H263\tClosed H.263 decoder" );
}
}
}
PINDEX Opal_H263_YUV420P::GetOptimalDataFrameSize(BOOL input) const
{
return input ? maxOutputSize : ((frameWidth * frameHeight * 12) / 8);
}
BOOL Opal_H263_YUV420P::ConvertFrames(const RTP_DataFrame & src, RTP_DataFrameList & dst)
{
if (!ff.IsLoaded())
return FALSE;
PWaitAndSignal mutex(updateMutex);
dst.RemoveAll();
int payload_size = src.GetPayloadSize();
unsigned char * payload;
// get payload and ensure correct padding
if (src.GetHeaderSize() + payload_size + FF_INPUT_BUFFER_PADDING_SIZE > src.GetSize()) {
payload = (unsigned char *) encFrameBuffer.GetPointer(payload_size + FF_INPUT_BUFFER_PADDING_SIZE);
memcpy(payload, src.GetPayloadPtr(), payload_size);
}
else
payload = (unsigned char *) src.GetPayloadPtr();
// some decoders might overread/segfault if the first 23 bits of padding are not 0
unsigned char * padding = payload + payload_size;
padding[0] = 0;
padding[1] = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -