00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "AMRAudioRTPSink.hh"
00025 #include "AMRAudioSource.hh"
00026
00027 AMRAudioRTPSink*
00028 AMRAudioRTPSink::createNew(UsageEnvironment& env, Groupsock* RTPgs,
00029 unsigned char rtpPayloadFormat,
00030 Boolean sourceIsWideband,
00031 unsigned numChannelsInSource) {
00032 return new AMRAudioRTPSink(env, RTPgs, rtpPayloadFormat,
00033 sourceIsWideband, numChannelsInSource);
00034 }
00035
00036 AMRAudioRTPSink
00037 ::AMRAudioRTPSink(UsageEnvironment& env, Groupsock* RTPgs,
00038 unsigned char rtpPayloadFormat,
00039 Boolean sourceIsWideband, unsigned numChannelsInSource)
00040 : AudioRTPSink(env, RTPgs, rtpPayloadFormat,
00041 sourceIsWideband ? 16000 : 8000,
00042 sourceIsWideband ? "AMR-WB": "AMR",
00043 numChannelsInSource),
00044 fSourceIsWideband(sourceIsWideband), fAuxSDPLine(NULL) {
00045 }
00046
00047 AMRAudioRTPSink::~AMRAudioRTPSink() {
00048 delete[] fAuxSDPLine;
00049 }
00050
00051 Boolean AMRAudioRTPSink::sourceIsCompatibleWithUs(MediaSource& source) {
00052
00053 if (!source.isAMRAudioSource()) return False;
00054
00055
00056 AMRAudioSource& amrSource = (AMRAudioSource&)source;
00057 if ((amrSource.isWideband()^fSourceIsWideband) != 0) return False;
00058
00059
00060
00061
00062 if (amrSource.numChannels() != numChannels()) return False;
00063
00064
00065
00066
00067
00068 if (amrSource.numChannels() > 1) {
00069 envir() << "AMRAudioRTPSink: Warning: Input source has " << amrSource.numChannels()
00070 << " audio channels. In the current implementation, the multi-frame frame-block will be split over multiple RTP packets\n";
00071 }
00072
00073 return True;
00074 }
00075
00076 void AMRAudioRTPSink::doSpecialFrameHandling(unsigned fragmentationOffset,
00077 unsigned char* frameStart,
00078 unsigned numBytesInFrame,
00079 struct timeval frameTimestamp,
00080 unsigned numRemainingBytes) {
00081
00082
00083 if (isFirstPacket() && isFirstFrameInPacket()) {
00084 setMarkerBit();
00085 }
00086
00087
00088
00089 if (isFirstFrameInPacket()) {
00090 u_int8_t payloadHeader = 0xF0;
00091 setSpecialHeaderBytes(&payloadHeader, 1, 0);
00092 }
00093
00094
00095
00096 AMRAudioSource* amrSource = (AMRAudioSource*)fSource;
00097 if (amrSource == NULL) return;
00098
00099 u_int8_t toc = amrSource->lastFrameHeader();
00100
00101 toc &=~ 0x80;
00102 setSpecialHeaderBytes(&toc, 1, 1+numFramesUsedSoFar());
00103
00104
00105
00106 MultiFramedRTPSink::doSpecialFrameHandling(fragmentationOffset,
00107 frameStart, numBytesInFrame,
00108 frameTimestamp,
00109 numRemainingBytes);
00110 }
00111
00112 Boolean AMRAudioRTPSink
00113 ::frameCanAppearAfterPacketStart(unsigned char const* ,
00114 unsigned ) const {
00115
00116 return False;
00117 }
00118
00119 unsigned AMRAudioRTPSink::specialHeaderSize() const {
00120
00121
00122 return 2;
00123 }
00124
00125 char const* AMRAudioRTPSink::auxSDPLine() {
00126 if (fAuxSDPLine == NULL) {
00127
00128
00129 char buf[100];
00130 sprintf(buf, "a=fmtp:%d octet-align=1\r\n", rtpPayloadType());
00131 delete[] fAuxSDPLine; fAuxSDPLine = strDup(buf);
00132 }
00133 return fAuxSDPLine;
00134 }