00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "H264VideoRTPSink.hh"
00022 #include "H264VideoStreamFramer.hh"
00023 #include "Base64.hh"
00024 #include "H264VideoRTPSource.hh"
00025
00027
00028 H264VideoRTPSink
00029 ::H264VideoRTPSink(UsageEnvironment& env, Groupsock* RTPgs, unsigned char rtpPayloadFormat,
00030 u_int8_t const* sps, unsigned spsSize, u_int8_t const* pps, unsigned ppsSize)
00031 : VideoRTPSink(env, RTPgs, rtpPayloadFormat, 90000, "H264"),
00032 fOurFragmenter(NULL), fFmtpSDPLine(NULL) {
00033 if (sps != NULL) {
00034 fSPSSize = spsSize;
00035 fSPS = new u_int8_t[fSPSSize];
00036 memmove(fSPS, sps, fSPSSize);
00037 } else {
00038 fSPSSize = 0;
00039 fSPS = NULL;
00040 }
00041 if (pps != NULL) {
00042 fPPSSize = ppsSize;
00043 fPPS = new u_int8_t[fPPSSize];
00044 memmove(fPPS, pps, fPPSSize);
00045 } else {
00046 fPPSSize = 0;
00047 fPPS = NULL;
00048 }
00049 }
00050
00051 H264VideoRTPSink::~H264VideoRTPSink() {
00052 fSource = fOurFragmenter;
00053 delete[] fFmtpSDPLine;
00054 delete[] fSPS; delete[] fPPS;
00055 stopPlaying();
00056
00057
00058 Medium::close(fOurFragmenter);
00059 fSource = NULL;
00060 }
00061
00062 H264VideoRTPSink*
00063 H264VideoRTPSink::createNew(UsageEnvironment& env, Groupsock* RTPgs, unsigned char rtpPayloadFormat) {
00064 return new H264VideoRTPSink(env, RTPgs, rtpPayloadFormat);
00065 }
00066
00067 H264VideoRTPSink*
00068 H264VideoRTPSink::createNew(UsageEnvironment& env, Groupsock* RTPgs, unsigned char rtpPayloadFormat,
00069 u_int8_t const* sps, unsigned spsSize, u_int8_t const* pps, unsigned ppsSize) {
00070 return new H264VideoRTPSink(env, RTPgs, rtpPayloadFormat, sps, spsSize, pps, ppsSize);
00071 }
00072
00073 H264VideoRTPSink*
00074 H264VideoRTPSink::createNew(UsageEnvironment& env, Groupsock* RTPgs, unsigned char rtpPayloadFormat,
00075 char const* sPropParameterSetsStr) {
00076 u_int8_t* sps = NULL; unsigned spsSize = 0;
00077 u_int8_t* pps = NULL; unsigned ppsSize = 0;
00078
00079 unsigned numSPropRecords;
00080 SPropRecord* sPropRecords = parseSPropParameterSets(sPropParameterSetsStr, numSPropRecords);
00081 for (unsigned i = 0; i < numSPropRecords; ++i) {
00082 if (sPropRecords[i].sPropLength == 0) continue;
00083 u_int8_t nal_unit_type = (sPropRecords[i].sPropBytes[0])&0x1F;
00084 if (nal_unit_type == 7) {
00085 sps = sPropRecords[i].sPropBytes;
00086 spsSize = sPropRecords[i].sPropLength;
00087 } else if (nal_unit_type == 8) {
00088 pps = sPropRecords[i].sPropBytes;
00089 ppsSize = sPropRecords[i].sPropLength;
00090 }
00091 }
00092
00093 H264VideoRTPSink* result = new H264VideoRTPSink(env, RTPgs, rtpPayloadFormat, sps, spsSize, pps, ppsSize);
00094 delete[] sPropRecords;
00095
00096 return result;
00097 }
00098
00099 Boolean H264VideoRTPSink::sourceIsCompatibleWithUs(MediaSource& source) {
00100
00101 return source.isH264VideoStreamFramer();
00102 }
00103
00104 Boolean H264VideoRTPSink::continuePlaying() {
00105
00106
00107 if (fOurFragmenter == NULL) {
00108 fOurFragmenter = new H264FUAFragmenter(envir(), fSource, OutPacketBuffer::maxSize,
00109 ourMaxPacketSize() - 12);
00110 } else {
00111 fOurFragmenter->reassignInputSource(fSource);
00112 }
00113 fSource = fOurFragmenter;
00114
00115
00116 return MultiFramedRTPSink::continuePlaying();
00117 }
00118
00119 void H264VideoRTPSink::doSpecialFrameHandling(unsigned ,
00120 unsigned char* ,
00121 unsigned ,
00122 struct timeval framePresentationTime,
00123 unsigned ) {
00124
00125
00126
00127 if (fOurFragmenter != NULL) {
00128 H264VideoStreamFramer* framerSource
00129 = (H264VideoStreamFramer*)(fOurFragmenter->inputSource());
00130
00131 if (fOurFragmenter->lastFragmentCompletedNALUnit()
00132 && framerSource != NULL && framerSource->pictureEndMarker()) {
00133 setMarkerBit();
00134 framerSource->pictureEndMarker() = False;
00135 }
00136 }
00137
00138 setTimestamp(framePresentationTime);
00139 }
00140
00141 Boolean H264VideoRTPSink
00142 ::frameCanAppearAfterPacketStart(unsigned char const* ,
00143 unsigned ) const {
00144 return False;
00145 }
00146
00147 char const* H264VideoRTPSink::auxSDPLine() {
00148
00149
00150
00151 u_int8_t* sps = fSPS; unsigned spsSize = fSPSSize;
00152 u_int8_t* pps = fPPS; unsigned ppsSize = fPPSSize;
00153 if (sps == NULL || pps == NULL) {
00154
00155 if (fOurFragmenter == NULL) return NULL;
00156 H264VideoStreamFramer* framerSource = (H264VideoStreamFramer*)(fOurFragmenter->inputSource());
00157 if (framerSource == NULL) return NULL;
00158
00159 framerSource->getSPSandPPS(sps, spsSize, pps, ppsSize);
00160 if (sps == NULL || pps == NULL) return NULL;
00161 }
00162
00163 u_int32_t profile_level_id;
00164 if (spsSize < 4) {
00165 profile_level_id = 0;
00166 } else {
00167 profile_level_id = (sps[1]<<16)|(sps[2]<<8)|sps[3];
00168 }
00169
00170
00171 char* sps_base64 = base64Encode((char*)sps, spsSize);
00172 char* pps_base64 = base64Encode((char*)pps, ppsSize);
00173 char const* fmtpFmt =
00174 "a=fmtp:%d packetization-mode=1"
00175 ";profile-level-id=%06X"
00176 ";sprop-parameter-sets=%s,%s\r\n";
00177 unsigned fmtpFmtSize = strlen(fmtpFmt)
00178 + 3
00179 + 6
00180 + strlen(sps_base64) + strlen(pps_base64);
00181 char* fmtp = new char[fmtpFmtSize];
00182 sprintf(fmtp, fmtpFmt,
00183 rtpPayloadType(),
00184 profile_level_id,
00185 sps_base64, pps_base64);
00186 delete[] sps_base64;
00187 delete[] pps_base64;
00188
00189 delete[] fFmtpSDPLine; fFmtpSDPLine = fmtp;
00190 return fFmtpSDPLine;
00191 }
00192
00193
00195
00196 H264FUAFragmenter::H264FUAFragmenter(UsageEnvironment& env,
00197 FramedSource* inputSource,
00198 unsigned inputBufferMax,
00199 unsigned maxOutputPacketSize)
00200 : FramedFilter(env, inputSource),
00201 fInputBufferSize(inputBufferMax+1), fMaxOutputPacketSize(maxOutputPacketSize),
00202 fNumValidDataBytes(1), fCurDataOffset(1), fSaveNumTruncatedBytes(0),
00203 fLastFragmentCompletedNALUnit(True) {
00204 fInputBuffer = new unsigned char[fInputBufferSize];
00205 }
00206
00207 H264FUAFragmenter::~H264FUAFragmenter() {
00208 delete[] fInputBuffer;
00209 detachInputSource();
00210 }
00211
00212 void H264FUAFragmenter::doGetNextFrame() {
00213 if (fNumValidDataBytes == 1) {
00214
00215 fInputSource->getNextFrame(&fInputBuffer[1], fInputBufferSize - 1,
00216 afterGettingFrame, this,
00217 FramedSource::handleClosure, this);
00218 } else {
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 if (fMaxSize < fMaxOutputPacketSize) {
00230 envir() << "H264FUAFragmenter::doGetNextFrame(): fMaxSize ("
00231 << fMaxSize << ") is smaller than expected\n";
00232 } else {
00233 fMaxSize = fMaxOutputPacketSize;
00234 }
00235
00236 fLastFragmentCompletedNALUnit = True;
00237 if (fCurDataOffset == 1) {
00238 if (fNumValidDataBytes - 1 <= fMaxSize) {
00239 memmove(fTo, &fInputBuffer[1], fNumValidDataBytes - 1);
00240 fFrameSize = fNumValidDataBytes - 1;
00241 fCurDataOffset = fNumValidDataBytes;
00242 } else {
00243
00244
00245
00246 fInputBuffer[0] = (fInputBuffer[1] & 0xE0) | 28;
00247 fInputBuffer[1] = 0x80 | (fInputBuffer[1] & 0x1F);
00248 memmove(fTo, fInputBuffer, fMaxSize);
00249 fFrameSize = fMaxSize;
00250 fCurDataOffset += fMaxSize - 1;
00251 fLastFragmentCompletedNALUnit = False;
00252 }
00253 } else {
00254
00255
00256
00257
00258
00259 fInputBuffer[fCurDataOffset-2] = fInputBuffer[0];
00260 fInputBuffer[fCurDataOffset-1] = fInputBuffer[1]&~0x80;
00261 unsigned numBytesToSend = 2 + fNumValidDataBytes - fCurDataOffset;
00262 if (numBytesToSend > fMaxSize) {
00263
00264 numBytesToSend = fMaxSize;
00265 fLastFragmentCompletedNALUnit = False;
00266 } else {
00267
00268 fInputBuffer[fCurDataOffset-1] |= 0x40;
00269 fNumTruncatedBytes = fSaveNumTruncatedBytes;
00270 }
00271 memmove(fTo, &fInputBuffer[fCurDataOffset-2], numBytesToSend);
00272 fFrameSize = numBytesToSend;
00273 fCurDataOffset += numBytesToSend - 2;
00274 }
00275
00276 if (fCurDataOffset >= fNumValidDataBytes) {
00277
00278 fNumValidDataBytes = fCurDataOffset = 1;
00279 }
00280
00281
00282 FramedSource::afterGetting(this);
00283 }
00284 }
00285
00286 void H264FUAFragmenter::afterGettingFrame(void* clientData, unsigned frameSize,
00287 unsigned numTruncatedBytes,
00288 struct timeval presentationTime,
00289 unsigned durationInMicroseconds) {
00290 H264FUAFragmenter* fragmenter = (H264FUAFragmenter*)clientData;
00291 fragmenter->afterGettingFrame1(frameSize, numTruncatedBytes, presentationTime,
00292 durationInMicroseconds);
00293 }
00294
00295 void H264FUAFragmenter::afterGettingFrame1(unsigned frameSize,
00296 unsigned numTruncatedBytes,
00297 struct timeval presentationTime,
00298 unsigned durationInMicroseconds) {
00299 fNumValidDataBytes += frameSize;
00300 fSaveNumTruncatedBytes = numTruncatedBytes;
00301 fPresentationTime = presentationTime;
00302 fDurationInMicroseconds = durationInMicroseconds;
00303
00304
00305 doGetNextFrame();
00306 }