📄 patch.cxx
字号:
const OpalMediaOption & option = sourceFormat.GetOption(i);
traceStream << " " << option.GetName() << " = " << option.AsString() << '\n';
}
traceStream << " to " << destinationFormat << '\n';
for (PINDEX j = 0; j < destinationFormat.GetOptionCount(); j++) {
const OpalMediaOption & option = destinationFormat.GetOption(j);
traceStream << " " << option.GetName() << " = " << option.AsString() << '\n';
}
traceStream << PTrace::End;
#endif
if (sourceFormat == destinationFormat && source.GetDataSize() <= stream->GetDataSize()) {
PTRACE(3, "Patch\tAdded direct media stream sink " << *stream);
return TRUE;
}
sink->primaryCodec = OpalTranscoder::Create(sourceFormat, destinationFormat);
if (sink->primaryCodec != NULL) {
sink->primaryCodec->SetRTPPayloadMap(rtpMap);
sink->primaryCodec->SetMaxOutputSize(stream->GetDataSize());
if (!stream->SetDataSize(sink->primaryCodec->GetOptimalDataFrameSize(FALSE))) {
PTRACE(2, "Patch\tSink stream " << *stream << " cannot support data size "
<< sink->primaryCodec->GetOptimalDataFrameSize(FALSE));
return FALSE;
}
PTRACE(3, "Patch\tAdded media stream sink " << *stream
<< " using transcoder " << *sink->primaryCodec);
}
else {
OpalMediaFormat intermediateFormat;
if (!OpalTranscoder::FindIntermediateFormat(sourceFormat, destinationFormat,
intermediateFormat)) {
PTRACE(2, "Patch\tCould find compatible media format for " << *stream);
return FALSE;
}
sink->primaryCodec = OpalTranscoder::Create(sourceFormat, intermediateFormat);
sink->secondaryCodec = OpalTranscoder::Create(intermediateFormat, destinationFormat);
sink->secondaryCodec->SetMaxOutputSize(sink->stream->GetDataSize());
if (!stream->SetDataSize(sink->secondaryCodec->GetOptimalDataFrameSize(FALSE))) {
PTRACE(2, "Patch\tSink stream " << *stream << " cannot support data size "
<< sink->secondaryCodec->GetOptimalDataFrameSize(FALSE));
return FALSE;
}
PTRACE(3, "Patch\tAdded media stream sink " << *stream
<< " using transcoders " << *sink->primaryCodec
<< " and " << *sink->secondaryCodec);
}
source.SetDataSize(sink->primaryCodec->GetOptimalDataFrameSize(TRUE));
return TRUE;
}
void OpalMediaPatch::RemoveSink(OpalMediaStream * stream)
{
if (PAssertNULL(stream) == NULL)
return;
PTRACE(3, "Patch\tRemoving media stream sink " << *stream);
PWaitAndSignal mutex(inUse);
for (PINDEX i = 0; i < sinks.GetSize(); i++) {
if (sinks[i].stream == stream) {
sinks.RemoveAt(i);
return;
}
}
}
OpalMediaPatch::Sink::Sink(OpalMediaPatch & p, OpalMediaStream * s)
: patch(p)
{
stream = s;
primaryCodec = NULL;
secondaryCodec = NULL;
intermediateFrames.Append(new RTP_DataFrame);
finalFrames.Append(new RTP_DataFrame);
writeSuccessful = true;
}
OpalMediaPatch::Sink::~Sink()
{
delete primaryCodec;
delete secondaryCodec;
}
void OpalMediaPatch::AddFilter(const PNotifier & filter, const OpalMediaFormat & stage)
{
inUse.Wait();
filters.Append(new Filter(filter, stage));
inUse.Signal();
}
BOOL OpalMediaPatch::RemoveFilter(const PNotifier & filter, const OpalMediaFormat & stage)
{
PWaitAndSignal mutex(inUse);
for (PINDEX i = 0; i < filters.GetSize(); i++) {
if (filters[i].notifier == filter && filters[i].stage == stage) {
filters.RemoveAt(i);
return TRUE;
}
}
return FALSE;
}
void OpalMediaPatch::FilterFrame(RTP_DataFrame & frame,
const OpalMediaFormat & mediaFormat)
{
PWaitAndSignal mutex(inUse);
for (PINDEX f = 0; f < filters.GetSize(); f++) {
Filter & filter = filters[f];
if (filter.stage.IsEmpty() || filter.stage == mediaFormat)
filter.notifier(frame, (INT)this);
}
}
BOOL OpalMediaPatch::UpdateMediaFormat(const OpalMediaFormat & mediaFormat, BOOL fromSink)
{
PWaitAndSignal mutex(inUse);
if (fromSink)
return source.UpdateMediaFormat(mediaFormat);
BOOL atLeastOne = FALSE;
for (PINDEX i = 0; i < sinks.GetSize(); i++)
atLeastOne = sinks[i].UpdateMediaFormat(mediaFormat) || atLeastOne;
return atLeastOne;
}
BOOL OpalMediaPatch::ExecuteCommand(const OpalMediaCommand & command, BOOL fromSink)
{
PWaitAndSignal mutex(inUse);
if (fromSink)
return source.ExecuteCommand(command);
BOOL atLeastOne = FALSE;
for (PINDEX i = 0; i < sinks.GetSize(); i++)
atLeastOne = sinks[i].ExecuteCommand(command) || atLeastOne;
return atLeastOne;
}
void OpalMediaPatch::SetCommandNotifier(const PNotifier & notifier, BOOL fromSink)
{
PWaitAndSignal mutex(inUse);
if (fromSink)
source.SetCommandNotifier(notifier);
else {
for (PINDEX i = 0; i < sinks.GetSize(); i++)
sinks[i].SetCommandNotifier(notifier);
}
}
bool OpalMediaPatch::Sink::UpdateMediaFormat(const OpalMediaFormat & mediaFormat)
{
if (secondaryCodec != NULL)
return secondaryCodec->UpdateOutputMediaFormat(mediaFormat);
if (primaryCodec != NULL)
return primaryCodec->UpdateOutputMediaFormat(mediaFormat);
return stream->UpdateMediaFormat(mediaFormat);
}
bool OpalMediaPatch::Sink::ExecuteCommand(const OpalMediaCommand & command)
{
BOOL atLeastOne = FALSE;
if (secondaryCodec != NULL)
atLeastOne = secondaryCodec->ExecuteCommand(command) || atLeastOne;
if (primaryCodec != NULL)
atLeastOne = primaryCodec->ExecuteCommand(command) || atLeastOne;
return atLeastOne;
}
void OpalMediaPatch::Sink::SetCommandNotifier(const PNotifier & notifier)
{
if (secondaryCodec != NULL)
secondaryCodec->SetCommandNotifier(notifier);
if (primaryCodec != NULL)
primaryCodec->SetCommandNotifier(notifier);
}
bool OpalMediaPatch::Sink::WriteFrame(RTP_DataFrame & sourceFrame)
{
if (!writeSuccessful)
return false;
if (primaryCodec == NULL)
return writeSuccessful = stream->WritePacket(sourceFrame);
if (!primaryCodec->ConvertFrames(sourceFrame, intermediateFrames)) {
PTRACE(1, "Patch\tMedia conversion (primary) failed");
return false;
}
if (sourceFrame.GetPayloadSize() == 0)
return writeSuccessful = stream->WritePacket(sourceFrame);
for (PINDEX i = 0; i < intermediateFrames.GetSize(); i++) {
RTP_DataFrame & intermediateFrame = intermediateFrames[i];
patch.FilterFrame(intermediateFrame, primaryCodec->GetOutputFormat());
if (secondaryCodec == NULL) {
if (!stream->WritePacket(intermediateFrame))
return writeSuccessful = false;
sourceFrame.SetTimestamp(intermediateFrame.GetTimestamp());
}
else {
if (!secondaryCodec->ConvertFrames(intermediateFrame, finalFrames)) {
PTRACE(1, "Patch\tMedia conversion (secondary) failed");
return false;
}
for (PINDEX f = 0; f < finalFrames.GetSize(); f++) {
RTP_DataFrame & finalFrame = finalFrames[f];
patch.FilterFrame(finalFrame, secondaryCodec->GetOutputFormat());
if (!stream->WritePacket(finalFrame))
return writeSuccessful = false;
sourceFrame.SetTimestamp(finalFrame.GetTimestamp());
}
}
}
return true;
}
/////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -